Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/python/selector.py

    r2881 r2340  
    11import re
    2 import math
    3 import string
    42from asap._asap import selector as _selector, srctype
    53from asap.utils import unique, _to_list
     
    202200            raise TypeError('Unknown row number type. Use lists of integers.')
    203201
    204     def set_msselection_field(self, selection):
    205         """
    206         Set a field selection in msselection syntax. The msselection
    207         suppports the following syntax:
    208 
    209         pattern match:
    210             - UNIX style pattern match for source name using '*'
    211               (compatible with set_name)
    212 
    213         field id selection:
    214             - simple number in string ('0', '1', etc.)
    215             - range specification using '~' ('0~1', etc.)
    216             - range specification using '>' or '<' in combination
    217               with '=' ('>=1', '<3', etc.)
    218 
    219         comma separated multiple selection:
    220             - selections can be combined by using ',' ('0,>1',
    221               'mysource*,2~4', etc.)
    222         """
    223         selection_list =  map(string.strip, selection.split(','))
    224         query_list = list(self.generate_query(selection_list))
    225         if len(query_list) > 0:
    226             original_query = self.get_query()
    227             if len(original_query) == 0 or re.match('.*(SRC|FIELD)NAME.*',original_query):
    228                 query = 'SELECT FROM $1 WHERE ' + ' || '.join(query_list)
    229             else:
    230                 query = 'SELECT FROM $1 WHERE (' + original_query + ') && (' + ' || '.join(query_list) + ')'
    231             self._settaql(query)
    232 
    233     def generate_query(self, selection_list):
    234         for s in selection_list:
    235             if s.isdigit() or re.match('^[<>]=?[0-9]*$', s) or \
    236                     re.match('^[0-9]+~[0-9]+$', s):
    237                 #print '"%s" is ID selection using < or <='%(s)
    238                 a = FieldIdRegexGenerator(s)
    239                 yield '(%s)'%(a.get_regex())
    240             elif len(s) > 0:
    241                 #print '"%s" is UNIX style pattern match'%(s)
    242                 yield '(SRCNAME == pattern(\'%s\'))'%(s)
    243        
    244202    def get_scans(self):
    245203        return list(self._getscans())
     
    317275                union.set_query(qs)
    318276        return union
    319 
    320 class FieldIdRegexGenerator(object):
    321     def __init__(self, pattern):
    322         if pattern.isdigit():
    323             self.regex = 'FIELDNAME == regex(\'.+__%s$\')'%(pattern)
    324         else:
    325             self.regex = None
    326             ineq = None
    327             if pattern.find('<') >= 0:
    328                 ineq = '<'
    329                 s = pattern.strip().lstrip(ineq).lstrip('=')
    330                 if not s.isdigit():
    331                     raise RuntimeError('Invalid syntax: %s'%(pattern))
    332                 self.id = int(s) + (-1 if pattern.find('=') < 0 else 0)
    333                 self.template = string.Template('FIELDNAME == regex(\'.+__${reg}$\')')
    334             elif pattern.find('>') >= 0:
    335                 ineq = '>'
    336                 s = pattern.strip().lstrip(ineq).lstrip('=')
    337                 if not s.isdigit():
    338                     raise RuntimeError('Invalid syntax: %s'%(pattern))
    339                 self.id = int(s) + (-1 if pattern.find('=') >= 0 else 0)
    340                 self.template = string.Template('FIELDNAME == regex(\'.+__[0-9]+$\') && FIELDNAME != regex(\'.+__${reg}$\')')
    341             elif pattern.find('~') >= 0:
    342                 s = map(string.strip, pattern.split('~'))
    343                 if len(s) == 2 and s[0].isdigit() and s[1].isdigit():
    344                     id0 = int(s[0])
    345                     id1 = int(s[1])
    346                     if id0 == 0:
    347                         self.id = id1
    348                         self.template = string.Template('FIELDNAME == regex(\'.+__${reg}$\')')
    349                     else:
    350                         self.id = [id0-1,id1]
    351                         self.template = string.Template('FIELDNAME == regex(\'.+__${reg}$\') && FIELDNAME != regex(\'.+__${optreg}$\')')
    352                 else:
    353                     raise RuntimeError('Invalid syntax: %s'%(pattern))
    354             else:
    355                 raise RuntimeError('Invalid syntax: %s'%(pattern))
    356             #print 'self.id=',self.id
    357 
    358     def get_regex(self):
    359         if self.regex is not None:
    360             # 'X'
    361             return self.regex
    362         elif isinstance(self.id, list):
    363             # 'X~Y'
    364             return self.template.safe_substitute(reg=self.__compile(self.id[1]),
    365                                                  optreg=self.__compile(self.id[0]))
    366         else:
    367             # '<(=)X' or '>(=)X'
    368             return self.template.safe_substitute(reg=self.__compile(self.id))
    369 
    370     def __compile(self, idx):
    371         pattern = ''
    372         if idx >= 0:
    373             numerics = map(int,list(str(idx)))
    374             #numerics.reverse()
    375             num_digits = len(numerics)
    376             #print 'numerics=',numerics
    377             if num_digits == 1:
    378                 if numerics[0] == 0:
    379                     pattern = '0'
    380                 else:
    381                     pattern = '[0-%s]'%(numerics[0])
    382             elif num_digits == 2:
    383                 pattern = '(%s)'%('|'.join(
    384                         list(self.__gen_two_digit_pattern(numerics))))
    385             elif num_digits == 3:
    386                 pattern = '(%s)'%('|'.join(
    387                         list(self.__gen_three_digit_pattern(numerics))))
    388             else:
    389                 raise RuntimeError('ID > 999 is not supported')
    390         else:
    391             raise RuntimeError('ID must be >= 0')
    392         return pattern
    393 
    394     def __gen_two_digit_pattern(self, numerics):
    395         assert len(numerics) == 2
    396         yield '[0-9]'
    397         if numerics[0] == 2:
    398             yield '1[0-9]'
    399         elif numerics[0] > 2:
    400             yield '[1-%s][0-9]'%(numerics[0]-1)
    401         if numerics[1] == 0:
    402             yield '%s%s'%(numerics[0],numerics[1])
    403         else:
    404             yield '%s[0-%s]'%(numerics[0],numerics[1])
    405 
    406     def __gen_three_digit_pattern(self, numerics):
    407         assert len(numerics) == 3
    408         yield '[0-9]'
    409         yield '[1-9][0-9]'
    410         if numerics[0] == 2:
    411             yield '1[0-9][0-9]'
    412         elif numerics[0] > 2:
    413             yield '[1-%s][0-9][0-9]'%(numerics[0]-1)
    414         if numerics[1] == 0:
    415             if numerics[2] == 0:
    416                 yield '%s00'%(numerics[0])
    417             else:
    418                 yield '%s0[0-%s]'%(numerics[0],numerics[2])
    419         else:
    420             if numerics[1] > 1:
    421                 yield '%s[0-%s][0-9]'%(numerics[0],numerics[1]-1)
    422             elif numerics[1] == 1:
    423                 yield '%s0[0-9]'%(numerics[0])
    424             if numerics[0] == 0:
    425                 yield '%s%s%s'%(numerics[0],numerics[1],numerics[2])
    426             else:
    427                 yield '%s%s[0-%s]'%(numerics[0],numerics[1],numerics[2])
Note: See TracChangeset for help on using the changeset viewer.