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.
fields:
 
   75                 fieldName += 
"_%d" % (n,)
 
   78             prefix = pathTemplate[last:m.start(0)]
 
   82             if m.group(2) 
in 'crs':
 
   84                 self.
reString += 
r'(?P<' + fieldName + 
'>.+)' 
   85             elif m.group(2) 
in 'eEfFgG':
 
   87                 self.
reString += 
r'(?P<' + fieldName + 
r'>[\d.eE+-]+)' 
   90                 self.
reString += 
r'(?P<' + fieldName + 
r'>[\d+-]+)' 
   92             self.
fields[fieldName] = dict(pos=pos, fieldType=fieldType)
 
   98         """Return the list of fields that will be returned from matched 
  101         fieldList = [
"" for i 
in range(len(self.
fields))]
 
  103             fieldList[self.
fields[f][
'pos']] = f
 
  107         """Return true if the given field contains a number.""" 
  109         return self.
fields[name][
'fieldType'] 
in (float, int)
 
  112         """Return true if the given field contains an integer.""" 
  114         return self.
fields[name][
'fieldType'] == int
 
  117         """Return true if the given field contains an float.""" 
  119         return self.
fields[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}} 
  132         for path 
in pathList:
 
  135                 dataId = m.groupdict()
 
  138                         dataId[f] = int(dataId[f])
 
  140                         dataId[f] = float(dataId[f])
 
  143                 print(
"Warning: unmatched path: %s" % (path,), file=sys.stderr)