24 """This module provides the FsScanner class."""
25 from __future__
import print_function
26 from builtins
import range
27 from builtins
import object
36 """Class to scan a filesystem location for paths matching a template.
38 Decomposes the resulting paths into fields and passes them to a callback
43 """Constructor. Takes the path template, which should be in the form
44 of a Python string with named format substitution specifications.
45 Such a template would be suitable for generating a path given a set of
46 fields in a dictionary. Does not handle hex (%x or %X).
49 %(field)s/%(visit)d/%(exposure)d/raw-%(visit)d-e%(exposure)03d-c%(ccd)03d-a%(amp)03d.fits
51 Note that fields may appear multiple times; the second and subsequent
52 appearances of such fields will have "_{number}" appended to them to
53 disambiguate, although it is typically assumed that they will all be
56 Trailing brackets (and their contents) can be used to indicate which HDU from a file should
57 be used. They will not be included in the filename search.
61 if pathTemplate.endswith(
']'):
62 pathTemplate = pathTemplate[0:pathTemplate.rfind(
'[')]
65 fmt = re.compile(
r'%\((\w+)\).*?([dioueEfFgGcrs])')
75 for m
in fmt.finditer(pathTemplate):
76 fieldName = m.group(1)
77 if fieldName
in self.
fields:
78 fieldName +=
"_%d" % (n,)
81 prefix = pathTemplate[last:m.start(0)]
85 if m.group(2)
in 'crs':
87 self.
reString +=
r'(?P<' + fieldName +
'>.+)'
88 elif m.group(2)
in 'eEfFgG':
90 self.
reString +=
r'(?P<' + fieldName +
'>[\d.eE+-]+)'
93 self.
reString +=
r'(?P<' + fieldName +
'>[\d+-]+)'
95 self.
fields[fieldName] = dict(pos=pos, fieldType=fieldType)
101 """Return the list of fields that will be returned from matched
104 fieldList = [
"" for i
in range(len(self.
fields))]
105 for f
in list(self.fields.keys()):
106 fieldList[self.
fields[f][
'pos']] = f
110 """Return true if the given field contains a number."""
112 return self.
fields[name][
'fieldType']
in (float, int)
115 """Return true if the given field contains an integer."""
117 return self.
fields[name][
'fieldType'] == int
120 """Return true if the given field contains an float."""
122 return self.
fields[name][
'fieldType'] == float
126 Scan a given path location. Return info about paths that conform to the path template:
128 :return: Path info: {path: {key:value ...}, ...} e.g.:
129 {'0239622/instcal0239622.fits.fz': {'visit_0': 239622, 'visit': 239622}}
135 for path
in pathList:
138 dataId = m.groupdict()
141 dataId[f] = int(dataId[f])
143 dataId[f] = float(dataId[f])
146 print(
"Warning: unmatched path: %s" % (path,), file=sys.stderr)