File indexing completed on 2026-04-09 07:48:47
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 """
0022 datedfolder.py
0023 ================
0024
0025 Find dated folders beneath a base directory argument or beneath the current directory.
0026
0027 ::
0028
0029 [blyth@localhost issues]$ ~/opticks/ana/datedfolder.py /home/blyth/local/opticks/results/geocache-bench
0030 INFO:__main__:DatedFolder.find searching for date stamped folders beneath : /home/blyth/local/opticks/results/geocache-bench
0031 /home/blyth/local/opticks/results/geocache-bench/OFF_TITAN_RTX/20190422_175618
0032 /home/blyth/local/opticks/results/geocache-bench/ON_TITAN_RTX/20190422_175618
0033 /home/blyth/local/opticks/results/geocache-bench/OFF_TITAN_V/20190422_175618
0034 /home/blyth/local/opticks/results/geocache-bench/ON_TITAN_V/20190422_175618
0035 /home/blyth/local/opticks/results/geocache-bench/OFF_TITAN_V_AND_TITAN_RTX/20190422_175618
0036 [blyth@localhost issues]$
0037
0038 """
0039 from datetime import datetime
0040 import os, re, sys, logging
0041 log = logging.getLogger(__name__)
0042
0043 class DateParser(object):
0044 ptn = re.compile("(\d{4})(\d{2})(\d{2})_(\d{2})(\d{2})(\d{2})")
0045 def __call__(self, name):
0046 """
0047 :param name: basename of a directory
0048 :return dt: datetime if matches the date format 20160819_153245 otherwise return None
0049 """
0050 m = self.ptn.match(name)
0051 if m is None:return None
0052 if len(m.groups()) != 6:return None
0053 dt = datetime(*map(int, m.groups()))
0054 return dt
0055
0056 dateparser = DateParser()
0057
0058 def finddir(base, dirfilter=lambda _:True, relative=True):
0059 """
0060 :param base: directory to walk looking for directories to be dirfiltered
0061 :param dirfilter: function that takes directory path argument and returns true when selected
0062 :param relative: when True returns the base relative path, otherwise absolute paths are returned
0063 :return paths: all directory paths found that satisfy the filter
0064 """
0065 paths = []
0066 for root, dirs, files in os.walk(base):
0067 for name in dirs:
0068 path = os.path.join(root,name)
0069 d = dirfilter(path)
0070 if d is not None:
0071 paths.append(path[len(base)+1:] if relative else path)
0072 pass
0073 pass
0074 pass
0075 return paths
0076
0077 class DatedFolder(object):
0078 @classmethod
0079 def find(cls, base):
0080 """
0081 :param base: directory
0082 :return dirs, dfolds, dtimes:
0083
0084 Groups of executable runs are grouped together by them using
0085 the same datestamp datedfolder name.
0086 So there can be more dirs that corresponding dfolds and dtimes.
0087 """
0088 while base.endswith("/"):
0089 base = base[:-1]
0090 pass
0091
0092 df = cls()
0093 log.info("DatedFolder.find searching for date stamped folders beneath : %s " % base)
0094
0095 dirs = finddir(base, df)
0096 dfolds = list(set(map(os.path.basename, dirs)))
0097 dtimes = list(map(dateparser, dfolds ))
0098
0099 return dirs, dfolds, dtimes
0100
0101 def __call__(self, path):
0102 """
0103 :param path: directory
0104 :return datetime or None:
0105 """
0106 name = os.path.basename(path)
0107
0108 return dateparser(name)
0109
0110
0111 if __name__ == '__main__':
0112 logging.basicConfig(level=logging.INFO)
0113 base = sys.argv[1] if len(sys.argv) > 1 else "."
0114 dirs, dfolds, dtimes = DatedFolder.find(base)
0115
0116 print("\n".join(dfolds))
0117 for df in sorted(dfolds):
0118 print("\n".join(filter(lambda _:_.endswith(df),dirs)))
0119 pass
0120
0121
0122