24 """This module provides the FsScanner class."""
33 """Class to scan a filesystem location for paths matching a template.
35 Decomposes the resulting paths into fields and passes them to a callback
40 """Constructor. Takes the path template, which should be in the form
41 of a Python string with named format substitution specifications.
42 Such a template would be suitable for generating a path given a set of
43 fields in a dictionary. Does not handle hex (%x or %X).
46 %(field)s/%(visit)d/%(exposure)d/raw-%(visit)d-e%(exposure)03d-c%(ccd)03d-a%(amp)03d.fits
48 Note that fields may appear multiple times; the second and subsequent
49 appearances of such fields will have "_{number}" appended to them to
50 disambiguate, although it is typically assumed that they will all be
53 Trailing brackets (and their contents) can be used to indicate which HDU from a file should
54 be used. They will not be included in the filename search.
58 if pathTemplate.endswith(
']'):
59 pathTemplate = pathTemplate[0:pathTemplate.rfind(
'[')]
62 fmt = re.compile(
r'%\((\w+)\).*?([dioueEfFgGcrs])')
72 for m
in fmt.finditer(pathTemplate):
73 fieldName = m.group(1)
74 if fieldName
in self.
fieldsfields:
75 fieldName +=
"_%d" % (n,)
78 prefix = pathTemplate[last:m.start(0)]
82 if m.group(2)
in 'crs':
84 self.
reStringreString +=
r'(?P<' + fieldName +
'>.+)'
85 elif m.group(2)
in 'eEfFgG':
87 self.
reStringreString +=
r'(?P<' + fieldName +
r'>[\d.eE+-]+)'
90 self.
reStringreString +=
r'(?P<' + fieldName +
r'>[\d+-]+)'
92 self.
fieldsfields[fieldName] = dict(pos=pos, fieldType=fieldType)
95 self.
reStringreString += pathTemplate[last:]
98 """Return the list of fields that will be returned from matched
101 fieldList = [
"" for i
in range(len(self.
fieldsfields))]
102 for f
in list(self.
fieldsfields.keys()):
103 fieldList[self.
fieldsfields[f][
'pos']] = f
107 """Return true if the given field contains a number."""
109 return self.
fieldsfields[name][
'fieldType']
in (float, int)
112 """Return true if the given field contains an integer."""
114 return self.
fieldsfields[name][
'fieldType'] == int
117 """Return true if the given field contains an float."""
119 return self.
fieldsfields[name][
'fieldType'] == float
123 Scan a given path location. Return info about paths that conform to the path template:
125 :return: Path info: {path: {key:value ...}, ...} e.g.:
126 {'0239622/instcal0239622.fits.fz': {'visit_0': 239622, 'visit': 239622}}
131 pathList = glob.glob(self.
globStringglobString)
132 for path
in pathList:
133 m = re.search(self.
reStringreString, path)
135 dataId = m.groupdict()
136 for f
in self.
fieldsfields:
137 if self.
isIntisInt(f):
138 dataId[f] = int(dataId[f])
140 dataId[f] = float(dataId[f])
143 print(
"Warning: unmatched path: %s" % (path,), file=sys.stderr)
def processPath(self, location)
def __init__(self, pathTemplate)
def isNumeric(self, name)