Changeset 1483

Show
Ignore:
Timestamp:
10/26/05 15:30:08 (3 years ago)
Author:
paul
Message:

Converted a couple whole files from space indentation to tab indentation,
and made the tool executable.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/dabo/ui/uiwx/masked/format.py

    r1029 r1483  
    66_xchars =  string.letters+string.punctuation+string.digits 
    77_abrmonths = [datetime.date(2000, m, 01).strftime("%b") for m in 
    8               [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]] 
     8       [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]] 
    99 
    1010def _isX(c): c in _xchars 
     
    1313 
    1414class _TokMatch(object): 
    15     __tests = { 
    16         '#': str.isdigit, 
    17         'N': str.isalnum, 
    18         'A': str.isupper, 
    19         'a': str.islower, 
    20         'C': str.isalpha, 
    21         'X': _isX, 
    22         '&': _isPunctuation, 
    23         '*': _isAnsi, 
    24        
    25  
    26     def __init__(self, v): 
    27         self.__test = _TokMatch.__tests[v] 
    28     def __call__(self, i, o): 
    29         return self.__test(i[0]) and (i[1:], o+i[0]) 
     15   __tests = { 
     16           '#': str.isdigit, 
     17           'N': str.isalnum, 
     18           'A': str.isupper, 
     19           'a': str.islower, 
     20           'C': str.isalpha, 
     21           'X': _isX, 
     22           '&': _isPunctuation, 
     23           '*': _isAnsi, 
     24           
     25 
     26   def __init__(self, v): 
     27       self.__test = _TokMatch.__tests[v] 
     28   def __call__(self, i, o): 
     29       return self.__test(i[0]) and (i[1:], o+i[0]) 
    3030 
    3131class _TokQmatch(object): 
    32     def __init__(self, v): 
    33         self.__qval = v 
    34     def __call__(self, i, o): 
    35         return i[0] == self.__qval and (i[1:], o+i[0]) or (i, o+self.__qval) 
     32   def __init__(self, v): 
     33       self.__qval = v 
     34   def __call__(self, i, o): 
     35       return i[0] == self.__qval and (i[1:], o+i[0]) or (i, o+self.__qval) 
    3636 
    3737def _tok_repeat(subnode, strCnt): 
    38     cnt = int(strCnt) 
    39     return subnode*cnt 
     38   cnt = int(strCnt) 
     39   return subnode*cnt 
    4040 
    4141_grammar_ = map(lambda e: (re.compile(e[0]), e[1]), 
    42                 [('#', _TokMatch), 
    43                  ('N', _TokMatch), 
    44                  ('A', _TokMatch), 
    45                  ('a', _TokMatch), 
    46                  ('C', _TokMatch), 
    47                  ('X', _TokMatch), 
    48                  ('&', _TokMatch), 
    49                  (r'\*'       , _TokMatch ), 
    50                  (r'\\(.)'    , _TokQmatch), 
    51                  (r'\{(\d+)\}', _tok_repeat), 
    52                  (r'([^#NAaCX&*{}])', _TokQmatch), 
    53                  ]) 
     42       [('#', _TokMatch), 
     43       ('N', _TokMatch), 
     44       ('A', _TokMatch), 
     45       ('a', _TokMatch), 
     46       ('C', _TokMatch), 
     47       ('X', _TokMatch), 
     48       ('&', _TokMatch), 
     49       (r'\*'       , _TokMatch ), 
     50       (r'\\(.)'    , _TokQmatch), 
     51       (r'\{(\d+)\}', _tok_repeat), 
     52       (r'([^#NAaCX&*{}])', _TokQmatch), 
     53       ]) 
    5454 
    5555_time_mask_ = r'(##):(##)(:(##))?( (AM|PM))?' 
    5656_date_masks_ = tuple(reduce(lambda l1, l2: l1 + l2, 
    57                             [[re.escape(delim).join(parts) for delim in '-/.'] 
    58                              for parts in (('(##)','(##)', '(####)'), 
    59                                            ('(####)', '(##)','(##)'), 
    60                                            ('(##)','(##)', '(####)'), 
    61                                            ('(CCC)','(##)', '(####)'), 
    62                                            ('(####)', '(CCC)','(##)'), 
    63                                            ('(##)','(##)', '(##)'), 
    64                                            )] 
    65                             )) 
     57       [[re.escape(delim).join(parts) for delim in '-/.'] 
     58               for parts in (('(##)','(##)', '(####)'), 
     59                       ('(####)', '(##)','(##)'), 
     60                       ('(##)','(##)', '(####)'), 
     61                       ('(CCC)','(##)', '(####)'), 
     62                       ('(####)', '(CCC)','(##)'), 
     63                       ('(##)','(##)', '(##)'), 
     64                       )] 
     65               )) 
    6666_datetime_masks_ = map(lambda e: e + " " + _time_mask_, _date_masks_) 
    6767 
    6868_datetime_parts_ = { 
    69     ('Y', '##'):   '%y', 
    70     ('Y', '####'): '%Y', 
    71     ('M', '##'):   '%m', 
    72     ('M', 'CCC'):  '%b', 
    73     ('D', '##'):   '%d', 
    74    
     69       ('Y', '##'):   '%y', 
     70       ('Y', '####'): '%Y', 
     71       ('M', '##'):   '%m', 
     72       ('M', 'CCC'):  '%b', 
     73       ('D', '##'):   '%d', 
     74       
    7575 
    7676_datetime_format_regexps_ = \ 
    77                           [('%y', r'(?P<year>\d{2})'), 
    78                            ('%Y', r'(?P<year>\d{4})'), 
    79                            ('%m', r'(?P<month>\d{2})'), 
    80                            ('%b', r'(?P<month>[\wA-Za-z]{3})'), 
    81                            ('%d', r'(?P<day>\d{2})'), 
    82                            ('%I', r'(?P<hour>\d{2})'), 
    83                            ('%H', r'(?P<hour>\d{2})'), 
    84                            ('%M', r'(?P<minute>\d{2})'), 
    85                            ('%S', r'(?P<second>\d{2})'), 
    86                            ('%p', r'(?P<p>AM|PM)') 
    87                            
    88   
     77       [('%y', r'(?P<year>\d{2})'), 
     78       ('%Y', r'(?P<year>\d{4})'), 
     79       ('%m', r'(?P<month>\d{2})'), 
     80       ('%b', r'(?P<month>[\wA-Za-z]{3})'), 
     81       ('%d', r'(?P<day>\d{2})'), 
     82       ('%I', r'(?P<hour>\d{2})'), 
     83       ('%H', r'(?P<hour>\d{2})'), 
     84       ('%M', r'(?P<minute>\d{2})'), 
     85       ('%S', r'(?P<second>\d{2})'), 
     86       ('%p', r'(?P<p>AM|PM)') 
     87       
     88 
    8989def _num_mask_parse(val): 
    90     if isinstance(val,  str): 
    91         intp, fractp = val, "" 
    92     else: 
    93         intp, fractp = val 
    94     return (len(intp), len(fractp)) 
     90   if isinstance(val,  str): 
     91       intp, fractp = val, "" 
     92   else: 
     93       intp, fractp = val 
     94   return (len(intp), len(fractp)) 
    9595 
    9696def _time_mask_parse(val): 
    97     # ('##', '##', _, '##', _, CC) 
    98     h, m, s, p = val[0], val[1], val[3], val[5] 
    99     hFmt = p and '%I' or '%H' 
    100      
    101     outFmt = hFmt + ':%M' 
    102     outFmt += s and ':%S' or '' 
    103     outFmt += p and ' %p' or '' 
    104     return outFmt 
     97   # ('##', '##', _, '##', _, CC) 
     98   h, m, s, p = val[0], val[1], val[3], val[5] 
     99   hFmt = p and '%I' or '%H' 
     100 
     101   outFmt = hFmt + ':%M' 
     102   outFmt += s and ':%S' or '' 
     103   outFmt += p and ' %p' or '' 
     104   return outFmt 
    105105 
    106106def _date_mask_parse(val, mask, dateStyle): 
    107     sep = (('/' in mask) * '/') + (('-' in mask) * '-') + (('.' in mask) * '.') 
    108     outFmt = sep.join([_datetime_parts_[(v, val[dateStyle.index(v)])] for v in dateStyle]) 
    109     return outFmt 
     107   sep = (('/' in mask) * '/') + (('-' in mask) * '-') + (('.' in mask) * '.') 
     108   outFmt = sep.join([_datetime_parts_[(v, val[dateStyle.index(v)])] for v in dateStyle]) 
     109   return outFmt 
    110110 
    111111def _datetime_mask_parse(val, mask, dateStyle): 
    112     dateFmt = _date_mask_parse(val[:3], mask, dateStyle) 
    113     timeFmt = _time_mask_parse(val[3:]) 
    114     return dateFmt + " " + timeFmt 
     112   dateFmt = _date_mask_parse(val[:3], mask, dateStyle) 
     113   timeFmt = _time_mask_parse(val[3:]) 
     114   return dateFmt + " " + timeFmt 
    115115 
    116116_datetime_rules_ = \ 
    117                  map(lambda e: (re.compile(e[0]), e[1]), 
    118                      map(lambda e: (e, _datetime_mask_parse), 
    119                          _datetime_masks_) + \ 
    120                      map(lambda e: (e, _date_mask_parse), 
    121                          _date_masks_) + \ 
    122                      [(_time_mask_, _time_mask_parse)]) 
     117       map(lambda e: (re.compile(e[0]), e[1]), 
     118       map(lambda e: (e, _datetime_mask_parse), 
     119               _datetime_masks_) + \ 
     120       map(lambda e: (e, _date_mask_parse), 
     121               _date_masks_) + \ 
     122               [(_time_mask_, _time_mask_parse)]) 
    123123_num_rules = \ 
    124       map(lambda e: (re.compile(e[0]), e[1]),      
    125           [(r'([#]+)\.([#]+)', _num_mask_parse), 
    126            (r'[#]+', _num_mask_parse),]) 
     124       map(lambda e: (re.compile(e[0]), e[1]),      
     125               [(r'([#]+)\.([#]+)', _num_mask_parse), 
     126               (r'[#]+', _num_mask_parse),]) 
    127127 
    128128def _match_rule(rule, text): 
    129     regexp, tag = rule 
    130     res = regexp.match(text) 
    131     if res: 
    132         groups = res.groups() 
    133         if not groups: 
    134             val = res.group(0) 
    135         elif len(groups) == 1: 
    136             val, = groups 
    137         else: 
    138             val = groups 
    139         rest_text = text[res.end():] 
    140         return (tag, val), rest_text 
    141     else: 
    142         return False 
     129   regexp, tag = rule 
     130   res = regexp.match(text) 
     131   if res: 
     132       groups = res.groups() 
     133       if not groups: 
     134           val = res.group(0) 
     135       elif len(groups) == 1: 
     136           val, = groups 
     137       else: 
     138           val = groups 
     139       rest_text = text[res.end():] 
     140       return (tag, val), rest_text 
     141   else: 
     142       return False 
    143143 
    144144def _map_rules(rules, text): 
    145     for rule in rules: 
    146         res = _match_rule(rule, text) 
    147         if res: return res 
    148     return False 
     145   for rule in rules: 
     146       res = _match_rule(rule, text) 
     147       if res: return res 
     148   return False 
    149149 
    150150def _tokenizer(rules, text): 
    151     rest_text = text 
    152     while rest_text: 
    153         res = _map_rules(rules, rest_text) 
    154         if res: 
    155             val, rest_text = res 
    156             yield val 
    157         else: raise ValueError, 'Invalid mask format' 
    158     return 
     151   rest_text = text 
     152   while rest_text: 
     153       res = _map_rules(rules, rest_text) 
     154       if res: 
     155           val, rest_text = res 
     156           yield val 
     157       else: raise ValueError, 'Invalid mask format' 
     158   return 
    159159 
    160160def kwval(key, kwargs): 
    161     return kwargs.has_key(key) and kwargs[key] 
     161   return kwargs.has_key(key) and kwargs[key] 
    162162 
    163163def Ctrl(controlType=controlTypes.TEXT, **kwargs): 
    164     return { 
    165         controlTypes.NUMBER: NumFormat, 
    166         controlTypes.TEXT: TextFormat, 
    167         controlTypes.TIME: TimeFormat, 
    168         controlTypes.COMBO: TextFormat, 
    169         }[controlType](**kwargs) 
     164   return { 
     165       controlTypes.NUMBER: NumFormat, 
     166       controlTypes.TEXT: TextFormat, 
     167       controlTypes.TIME: TimeFormat, 
     168       controlTypes.COMBO: TextFormat, 
     169       }[controlType](**kwargs) 
    170170 
    171171def _add_properties(param_names): 
    172     ret = [] 
    173     for param in param_names: 
    174         propname = param[0].upper() + param[1:] 
    175         getter_name = '_get%s' % propname 
    176         setter_name = '_set%s' % propname 
    177         getter = 'def %s(self): return self._%s' % (getter_name, param) 
    178         setter = 'def %s(self, val): self.SetParameters(%s=val)' % (setter_name, param) 
    179         prop = '%s = property(%s, %s, None,"Generated.")' % (propname, getter_name, setter_name) 
    180         ret.extend([getter, setter, prop]) 
    181     return tuple(ret) 
     172   ret = [] 
     173   for param in param_names: 
     174       propname = param[0].upper() + param[1:] 
     175       getter_name = '_get%s' % propname 
     176       setter_name = '_set%s' % propname 
     177       getter = 'def %s(self): return self._%s' % (getter_name, param) 
     178       setter = 'def %s(self, val): self.SetParameters(%s=val)' % (setter_name, param) 
     179       prop = '%s = property(%s, %s, None,"Generated.")' % (propname, getter_name, setter_name) 
     180       ret.extend([getter, setter, prop]) 
     181   return tuple(ret) 
    182182 
    183183 
    184184class TextFormat(object): 
    185     valid_params = { 
    186         'name':         "text", 
    187         'formatcodes':  "", 
    188         'groupChar':    ',', 
    189         'decimalChar':  '.', 
    190         'autoformat':   "", 
    191         'mask':         'XXXXXXXXXXXXX', 
    192         'datestyle':    'MDY', 
    193         'useParensForNegatives': False 
    194        
    195  
    196     for d in  _add_properties(valid_params): exec(d) 
    197      
    198     def __init__(self, **kwargs): 
    199         self._mytype = None 
    200         self._format = None 
    201         self._scaner = None 
    202         for key, value in TextFormat.valid_params.items(): 
    203            setattr(self, '_' + key, copy.copy(value)) 
    204         self.SetParameters(**kwargs) 
    205  
    206     def format(self, val): 
    207         fmt = { 
    208             'string': self._mask_format, 
    209             'date':   self._time_format, 
    210             'time':   self._time_format, 
    211             'int':    self._num_format, 
    212             'float':  self._num_format, 
    213             }[self._mytype] 
    214         return fmt(val) 
    215  
    216     def fromstr(self, strv, dataType=str): 
    217         try: 
    218             if dataType == str or dataType == unicode: return strv 
    219          
    220             v =  self._scaner(self, strv) 
    221             if v is None: return v 
    222  
    223             if self._mytype in ('date', 'time'): 
    224                 if dataType == datetime.datetime: 
    225                     return datetime.datetime(*v) 
    226                 elif dataType == datetime.date: 
    227                     return datetime.date(*v[0:3]) 
    228                 elif str(dataType) == "<type 'DateTime'>": 
    229                     try: 
    230                         import mx.DateTime 
    231                         return mx.DateTime.DateTime(*v) 
    232                     except ImportError: 
    233                         return None 
    234             elif dataType == bool: 
    235                 return v == 'True' or False 
    236             else: 
    237                 return dataType(strv) 
    238         except (ValueError, TypeError): 
    239             return None 
    240              
    241     def SetParameters(self, **kwargs): 
    242         if kwargs.has_key('autoformat'): 
    243             autoformat = kwargs['autoformat'] 
    244             try: 
    245                 kws = masked.maskededit.masktags[autoformat] 
    246                 for key, value in kws.items(): 
    247                     kwargs[key] = value 
    248             except KeyError: 
    249                 raise(AttributeError, 
    250                       'invalid autoformat value %s' % repr(autoformat)) 
    251  
    252         for key in TextFormat.valid_params.keys(): 
    253             if kwargs.has_key(key): 
    254                 setattr(self, '_' + key, kwargs[key]) 
    255  
    256         self._groupdigits = ',' in self._formatcodes 
    257         self._padZero = '0' in self._formatcodes 
    258         self._guess_type() 
    259         self._choose_scanner() 
    260         if self._mytype in ('date', 'time'): 
    261              # autoformat masks could get 'AM' at the end 
    262              self._mask = self._mask.replace('AM', 'CC') 
    263         self._cmask = self._parse(self._mask) 
    264  
    265         return 
    266  
    267     def _guess_type(self): 
    268         self._format = None 
    269         self._mytype = 'string' 
    270         # try date/time 
    271         is_date = 'D' in self._formatcodes and 'date' 
    272         is_time = 'T' in self._formatcodes and 'time' 
    273         if is_date or is_time: 
    274             self._mytype =  is_date or is_time 
    275             for kv in (('MDDY', 'MDY'), ('YMMD', 'YMD'), ('YMMMD', 'YMD'), 
    276                        ('DMMY', 'DMY'), ('DMMMY', 'DMY'),): 
    277                 pat, style = kv 
    278                 if self._autoformat.find(pat) != -1: 
    279                     self._datestyle = style 
    280                     break 
    281  
    282         type_rules = (is_date or is_time) and _datetime_rules_ \ 
    283                      or _num_rules 
    284         res = _map_rules(type_rules, self._mask.strip()) 
    285  
    286         if not res: self._mytype = 'string'; return 
    287         rule_res, rest_text = res 
    288         if rest_text: self._mytype = 'string'; return 
    289         tag, tag_val = rule_res 
    290  
    291         if tag == _num_mask_parse: 
    292             self._integerWidth, self._fractionWidth = tag(tag_val) 
    293             self._mytype = self._fractionWidth and 'float' or 'int' 
    294             fmtInt = self._padZero and '%%0%dd' % self._integerWidth or '%d' 
    295             fmtFrac = self._fractionWidth and self._decimalChar + '%d' or None 
    296             self._format = (fmtInt, fmtFrac)  
    297         elif tag in (_date_mask_parse, _datetime_mask_parse): 
    298             self._format = tag(tag_val, self._mask, self._datestyle) 
    299             self._mytype = 'date' 
    300         elif tag == _time_mask_parse: 
    301             self._format = tag(tag_val) 
    302             self._mytype = 'time' 
    303         else: 
    304             self._format = None 
    305             self._mytype = 'string' 
    306  
    307         return 
    308  
    309     def _choose_scanner(self): 
    310         if self._mytype in ('date', 'time'): 
    311             format = self._format 
    312             for pat, reg in _datetime_format_regexps_: 
    313                 format = format.replace(pat, reg) 
    314             def scan(self, v): 
    315                 m = re.match(format, v) 
    316                 if m is None: 
    317                     return None 
    318                 else: 
    319                     gd = m.groupdict() 
    320                     year, day, hour, minute, second = \ 
    321                           [int(gd.get(k, v)) for (k, v) in 
    322                            [('year', '1970'), ('day', '1'), 
    323                             ('hour', '0'), ('minute', '0'), ('second', '0')]] 
    324                     [sp, smonth] = [gd.get(k, v) for (k,v) in 
    325                                     [('p',''), ('month', '1')]] 
    326                     p = sp == 'PM' and 12 or 0 
    327                     month = len(smonth) == 3 and _abrmonths.index(smonth)+1 \ 
    328                             or int(smonth) 
    329                 return (year, month, day, hour, minute, second) 
    330         elif self._mytype in ('int', 'float'): 
    331             def scan(self, v): 
    332                 sign = v[0] == '(' and -1 or 1 
    333                 v = v.replace('(', '').replace(')', '').replace(',', '') 
    334                 ret = (self._mytype == 'int' and int(v) or float(v))*sign 
    335                 return ret 
    336         else: 
    337             scan = lambda self, v: v 
    338  
    339         self._scaner = scan 
    340                      
    341     def _mask_format(self, text): 
    342         if not isinstance(text, basestring): 
    343             text = text is None and "" or str(text) 
    344         out = "" 
    345         for f in self._cmask: 
    346             if not text: return out 
    347             res = f(text, out) 
    348             if not res: return out+text 
    349             text, out = res 
    350         return out+text 
    351  
    352     def _num_format(self, val): 
    353         try: 
    354             if self._mytype == 'int': v = int(val) 
    355             else: v = float(val) 
    356         except: 
    357             try: v = float(val) 
    358             except: 
    359                 return self._mask_format(val) 
    360         is_neg = v < 0 
    361         v = abs(v) 
    362         vi, vf = divmod(v, 1) 
    363         vf *= 10**self._fractionWidth 
    364         vf = round(vf, 0) 
    365         fmtInt, fmtFrac = self._format 
    366         intStr = fmtInt % vi 
    367         if fmtFrac: 
    368             fracStr = self._decimalChar + \ 
    369                       (vf and '%d' % vf or '0'*self._fractionWidth) 
    370         else: 
    371             fracStr = '' 
    372         if self._groupdigits: 
    373             groups = []; rest = intStr 
    374             while rest: 
    375                 groups.append(rest[-3:]) 
    376                 rest = rest[0:-3] 
    377             groups.reverse() 
    378             intStr = self._groupChar.join(groups) 
    379         retStr = intStr + fracStr 
    380         if is_neg: 
    381             if self._useParensForNegatives: 
    382                 retStr = '(' + retStr + ')' 
    383             else: 
    384                 retStr = '-'+retStr 
    385         return retStr 
    386  
    387     def _time_format(self, val): 
    388         dataType = type(val) 
    389         if dataType == wx.DateTime: 
    390             val.Format(self._format) 
    391         try: 
    392             return val.strftime(self._format) 
    393         except: 
    394             return self._mask_format(val) 
    395      
    396     def _parse(self, mask): 
    397         # we use one token for look ahead, so add [None] to the end 
    398         tokens = itertools.chain(_tokenizer(_grammar_, mask), [None]) 
    399         nodes = [] 
    400         def parse_next(cur, next): 
    401             if not cur: return None 
    402              
    403             cur_type, cur_val = cur 
    404             next_type, next_val = next or (None, None) 
    405             if cur_type == _tok_repeat: 
    406                 raise ValueError, 'Invalid mask format'   
    407             if next_type == _tok_repeat: 
    408                 add_nodes = next_type(cur_type(cur_val), next_val) 
    409                 next = tokens.next() 
    410             else: 
    411                 add_nodes = [cur_type(cur_val)] 
    412             nodes.extend(add_nodes) 
    413             return next 
    414         reduce(parse_next, tokens) 
    415         return nodes 
    416  
    417     def _getFormatType(self): 
    418         return self._mytype 
    419  
    420     FormatType = property(_getFormatType, None, None,"FormatType.") 
    421      
     185   valid_params = { 
     186           'name':         "text", 
     187           'formatcodes':  "", 
     188           'groupChar':    ',', 
     189           'decimalChar':  '.', 
     190           'autoformat':   "", 
     191           'mask':         'XXXXXXXXXXXXX', 
     192           'datestyle':    'MDY', 
     193           'useParensForNegatives': False 
     194   
     195 
     196   for d in  _add_properties(valid_params): exec(d) 
     197     
     198   def __init__(self, **kwargs): 
     199       self._mytype = None 
     200       self._format = None 
     201       self._scaner = None 
     202       for key, value in TextFormat.valid_params.items(): 
     203           setattr(self, '_' + key, copy.copy(value)) 
     204       self.SetParameters(**kwargs) 
     205 
     206   def format(self, val): 
     207       fmt = { 
     208               'string': self._mask_format, 
     209               'date':   self._time_format, 
     210               'time':   self._time_format, 
     211               'int':    self._num_format, 
     212               'float':  self._num_format, 
     213       }[self._mytype] 
     214       return fmt(val) 
     215 
     216   def fromstr(self, strv, dataType=str): 
     217       try: 
     218           if dataType == str or dataType == unicode: return strv 
     219 
     220           v =  self._scaner(self, strv) 
     221           if v is None: return v 
     222 
     223           if self._mytype in ('date', 'time'): 
     224               if dataType == datetime.datetime: 
     225                   return datetime.datetime(*v) 
     226               elif dataType == datetime.date: 
     227                   return datetime.date(*v[0:3]) 
     228               elif str(dataType) == "<type 'DateTime'>": 
     229                   try: 
     230                       import mx.DateTime 
     231                       return mx.DateTime.DateTime(*v) 
     232                   except ImportError: 
     233                       return None 
     234           elif dataType == bool: 
     235               return v == 'True' or False 
     236           else: 
     237               return dataType(strv) 
     238       except (ValueError, TypeError): 
     239           return None 
     240 
     241   def SetParameters(self, **kwargs): 
     242       if kwargs.has_key('autoformat'): 
     243           autoformat = kwargs['autoformat'] 
     244           try: 
     245               kws = masked.maskededit.masktags[autoformat] 
     246               for key, value in kws.items(): 
     247                   kwargs[key] = value 
     248           except KeyError: 
     249               raise(AttributeError, 
     250                       'invalid autoformat value %s' % repr(autoformat)) 
     251 
     252       for key in TextFormat.valid_params.keys(): 
     253           if kwargs.has_key(key): 
     254               setattr(self, '_' + key, kwargs[key]) 
     255 
     256       self._groupdigits = ',' in self._formatcodes 
     257       self._padZero = '0' in self._formatcodes 
     258       self._guess_type() 
     259       self._choose_scanner() 
     260       if self._mytype in ('date', 'time'): 
     261           # autoformat masks could get 'AM' at the end 
     262           self._mask = self._mask.replace('AM', 'CC') 
     263       self._cmask = self._parse(self._mask) 
     264 
     265       return 
     266 
     267   def _guess_type(self): 
     268       self._format = None 
     269       self._mytype = 'string' 
     270       # try date/time 
     271       is_date = 'D' in self._formatcodes and 'date' 
     272       is_time = 'T' in self._formatcodes and 'time' 
     273       if is_date or is_time: 
     274           self._mytype =  is_date or is_time 
     275           for kv in (('MDDY', 'MDY'), ('YMMD', 'YMD'), ('YMMMD', 'YMD'), 
     276                   ('DMMY', 'DMY'), ('DMMMY', 'DMY'),): 
     277               pat, style = kv 
     278               if self._autoformat.find(pat) != -1: 
     279                   self._datestyle = style 
     280                   break 
     281 
     282       type_rules = (is_date or is_time) and _datetime_rules_ \ 
     283               or _num_rules 
     284       res = _map_rules(type_rules, self._mask.strip()) 
     285 
     286       if not res: self._mytype = 'string'; return 
     287       rule_res, rest_text = res 
     288       if rest_text: self._mytype = 'string'; return 
     289       tag, tag_val = rule_res 
     290 
     291       if tag == _num_mask_parse: 
     292           self._integerWidth, self._fractionWidth = tag(tag_val) 
     293           self._mytype = self._fractionWidth and 'float' or 'int' 
     294           fmtInt = self._padZero and '%%0%dd' % self._integerWidth or '%d' 
     295           fmtFrac = self._fractionWidth and self._decimalChar + '%d' or None 
     296           self._format = (fmtInt, fmtFrac)  
     297       elif tag in (_date_mask_parse, _datetime_mask_parse): 
     298           self._format = tag(tag_val, self._mask, self._datestyle) 
     299           self._mytype = 'date' 
     300       elif tag == _time_mask_parse: 
     301           self._format = tag(tag_val) 
     302           self._mytype = 'time' 
     303       else: 
     304           self._format = None 
     305           self._mytype = 'string' 
     306 
     307       return 
     308 
     309   def _choose_scanner(self): 
     310       if self._mytype in ('date', 'time'): 
     311           format = self._format 
     312           for pat, reg in _datetime_format_regexps_: 
     313               format = format.replace(pat, reg) 
     314           def scan(self, v): 
     315               m = re.match(format, v) 
     316               if m is None: 
     317                   return None 
     318               else: 
     319                   gd = m.groupdict() 
     320                   year, day, hour, minute, second = \ 
     321                           [int(gd.get(k, v)) for (k, v) in 
     322                                   [('year', '1970'), ('day', '1'), 
     323                                   ('hour', '0'), ('minute', '0'), ('second', '0')]] 
     324                   [sp, smonth] = [gd.get(k, v) for (k,v) in 
     325                           [('p',''), ('month', '1')]] 
     326                   p = sp == 'PM' and 12 or 0 
     327                   month = len(smonth) == 3 and _abrmonths.index(smonth)+1 \ 
     328                           or int(smonth) 
     329               return (year, month, day, hour, minute, second) 
     330       elif self._mytype in ('int', 'float'): 
     331           def scan(self, v): 
     332               sign = v[0] == '(' and -1 or 1 
     333               v = v.replace('(', '').replace(')', '').replace(',', '') 
     334               ret = (self._mytype == 'int' and int(v) or float(v))*sign 
     335               return ret 
     336       else: 
     337           scan = lambda self, v: v 
     338 
     339       self._scaner = scan 
     340 
     341   def _mask_format(self, text): 
     342       if not isinstance(text, basestring): 
     343           text = text is None and "" or str(text) 
     344       out = "" 
     345       for f in self._cmask: 
     346           if not text: return out 
     347           res = f(text, out) 
     348           if not res: return out+text 
     349           text, out = res 
     350       return out+text 
     351 
     352   def _num_format(self, val): 
     353       try: 
     354           if self._mytype == 'int': v = int(val) 
     355           else: v = float(val) 
     356       except: 
     357           try: v = float(val) 
     358           except: 
     359               return self._mask_format(val) 
     360       is_neg = v < 0 
     361       v = abs(v) 
     362       vi, vf = divmod(v, 1) 
     363       vf *= 10**self._fractionWidth 
     364       vf = round(vf, 0) 
     365       fmtInt, fmtFrac = self._format 
     366       intStr = fmtInt % vi 
     367       if fmtFrac: 
     368           fracStr = self._decimalChar + \ 
     369                   (vf and '%d' % vf or '0'*self._fractionWidth) 
     370       else: 
     371           fracStr = '' 
     372       if self._groupdigits: 
     373           groups = []; rest = intStr 
     374           while rest: 
     375               groups.append(rest[-3:]) 
     376               rest = rest[0:-3] 
     377           groups.reverse() 
     378           intStr = self._groupChar.join(groups) 
     379       retStr = intStr + fracStr 
     380       if is_neg: 
     381           if self._useParensForNegatives: 
     382               retStr = '(' + retStr + ')' 
     383           else: 
     384               retStr = '-'+retStr 
     385       return retStr 
     386 
     387   def _time_format(self, val): 
     388       dataType = type(val) 
     389       if dataType == wx.DateTime: 
     390           val.Format(self._format) 
     391       try: 
     392           return val.strftime(self._format) 
     393       except: 
     394           return self._mask_format(val) 
     395 
     396   def _parse(self, mask): 
     397       # we use one token for look ahead, so add [None] to the end 
     398       tokens = itertools.chain(_tokenizer(_grammar_, mask), [None]) 
     399       nodes = [] 
     400       def parse_next(cur, next): 
     401           if not cur: return None 
     402 
     403           cur_type, cur_val = cur 
     404           next_type, next_val = next or (None, None) 
     405           if cur_type == _tok_repeat: 
     406               raise ValueError, 'Invalid mask format'   
     407           if next_type == _tok_repeat: 
     408               add_nodes = next_type(cur_type(cur_val), next_val) 
     409               next = tokens.next() 
     410           else: 
     411               add_nodes = [cur_type(cur_val)] 
     412           nodes.extend(add_nodes) 
     413           return next 
     414       reduce(parse_next, tokens) 
     415       return nodes 
     416 
     417   def _getFormatType(self): 
     418       return self._mytype 
     419 
     420   FormatType = property(_getFormatType, None, None,"FormatType.") 
     421 
    422422class TimeFormat(TextFormat): 
    423     valid_params = { 
    424         'format' : 'HHMMSS', 
    425         'displaySeconds' : True, 
    426        
    427     valid_time_formats = ( 
    428         'HHMMSS', 'TIMEHHMMSS', 'HHMM', 'TIMEHHMM', 
    429         '24HHMMSS', '24HRTIMEHHMMSS', '24HHMM', '24HRTIMEHHMM', 
    430        
    431      
    432     __need24hr = False 
    433  
    434     for d in  _add_properties(valid_params): exec(d) 
    435  
    436     def __init__(self, name='time', **kwargs): 
    437  
    438         if not TimeFormat.__need24hr: 
    439             wxdt = wx.DateTimeFromDMY(1, 0, 1970) 
    440             if wxdt.Format('%p') not in  ('AM', 'PM'): 
    441                 TimeFormat.valid_params['format'] = '24HHMMSS' 
    442                 TimeFormat.__need24hr = True 
    443             else: 
    444                 TimeFormat.__need24hr = False 
    445         for key, value in TimeFormat.valid_params.items(): 
    446             setattr(self, "_TimeFormat__" + key, value) 
    447         TextFormat.__init__(self,  name = name, **kwargs) 
    448  
    449     def SetParameters(self, **kwargs): 
    450         TextFormat.SetParameters(self, **self._SetParameters(**kwargs)) 
    451          
    452     def _SetParameters(self, format=None, fmt24hr=False, displaySeconds=True, 
    453                        **kwargs): 
    454         if format and format not in valid_time_formats: 
    455             raise AttributeError, 'invalid format %s' % format 
    456  
    457         if TimeFormat.__need24hr: 
    458             self.__fmt24hr = TimeFormat.__need24hr 
    459         elif format: 
    460             self.__fmt24hr = format.startswith('24')  
    461         else: 
    462             self.__fmt24hr = fmt24hr 
    463  
    464         if format: 
    465             self.__displaySeconds = format.endswith('SS') 
    466         else: 
    467             self.__displaySeconds = displaySeconds 
    468              
    469         self.__format = (self.__fmt24hr and '24HR' or '') + \ 
    470                         'TIME' + \ 
    471                         (self.__displaySeconds and 'HHMMSS' or 'HHMM') 
    472  
    473         retargs = {} 
    474         retargs['autoformat'] = self.__format 
    475         retargs['formatcodes'] = 'T' 
    476         return retargs 
    477      
     423   valid_params = { 
     424           'format' : 'HHMMSS', 
     425           'displaySeconds' : True, 
     426   
     427   valid_time_formats = ( 
     428           'HHMMSS', 'TIMEHHMMSS', 'HHMM', 'TIMEHHMM', 
     429           '24HHMMSS', '24HRTIMEHHMMSS', '24HHMM', '24HRTIMEHHMM', 
     430   
     431 
     432   __need24hr = False 
     433 
     434   for d in  _add_properties(valid_params): exec(d) 
     435 
     436   def __init__(self, name='time', **kwargs): 
     437 
     438       if not TimeFormat.__need24hr: 
     439           wxdt = wx.DateTimeFromDMY(1, 0, 1970) 
     440           if wxdt.Format('%p') not in  ('AM', 'PM'): 
     441               TimeFormat.valid_params['format'] = '24HHMMSS' 
     442               TimeFormat.__need24hr = True 
     443           else: 
     444               TimeFormat.__need24hr = False 
     445       for key, value in TimeFormat.valid_params.items(): 
     446           setattr(self, "_TimeFormat__" + key, value) 
     447       TextFormat.__init__(self,  name = name, **kwargs) 
     448 
     449   def SetParameters(self, **kwargs): 
     450       TextFormat.SetParameters(self, **self._SetParameters(**kwargs)) 
     451 
     452   def _SetParameters(self, format=None, fmt24hr=False, displaySeconds=True, 
     453           **kwargs): 
     454       if format and format not in valid_time_formats: 
     455           raise AttributeError, 'invalid format %s' % format 
     456 
     457       if TimeFormat.__need24hr: 
     458           self.__fmt24hr = TimeFormat.__need24hr 
     459       elif format: 
     460           self.__fmt24hr = format.startswith('24')  
     461       else: 
     462           self.__fmt24hr = fmt24hr 
     463 
     464       if format: 
     465           self.__displaySeconds = format.endswith('SS') 
     466       else: 
     467           self.__displaySeconds = displaySeconds 
     468 
     469       self.__format = (self.__fmt24hr and '24HR' or '') + \ 
     470               'TIME' + \ 
     471               (self.__displaySeconds and 'HHMMSS' or 'HHMM') 
     472 
     473       retargs = {} 
     474       retargs['autoformat'] = self.__format 
     475       retargs['formatcodes'] = 'T' 
     476       return retargs 
     477 
    478478class NumFormat(TextFormat): 
    479     valid_params = { 
    480         'integerWidth': 10, 
    481         'fractionWidth': 0, 
    482         'decimalChar': '.', 
    483         'useParensForNegatives': False, 
    484         'groupDigits': True, 
    485         'groupChar': ',', 
    486        
    487  
    488     for d in  _add_properties(valid_params): exec(d) 
    489  
    490     def __init__(self, name='num', **kwargs): 
    491         for key, value in NumFormat.valid_params.items(): 
    492            setattr(self, '_' + key, copy.copy(value)) 
    493         TextFormat.__init__(self,  name=name, **kwargs) 
    494  
    495     def SetParameters(self, **kwargs): 
    496         TextFormat.SetParameters(self, **self._SetParameters(**kwargs)) 
    497  
    498     def _SetParameters(self, **kwargs): 
    499         for key in NumFormat.valid_params.keys(): 
    500             if kwargs.has_key(key): 
    501                 setattr(self, '_' + key, kwargs[key]) 
    502                  
    503         mask = '#'*self._integerWidth 
    504         if self._fractionWidth: 
    505             mask += '.'+ '#'*self._fractionWidth 
    506  
    507         formatcodes = kwval('formatcodes', kwargs) or "" 
    508         if self._groupDigits: formatcodes += ',' 
    509              
    510         retargs = { 
    511             'mask': mask, 
    512             'formatcodes': formatcodes, 
    513            
    514          
    515         for key in  ('decimalChar',  'groupChar', 'useParensForNegatives',): 
    516             if kwargs.has_key(key): 
    517                 retargs[key] = kwargs[key] 
    518         return retargs 
     479   valid_params = { 
     480           'integerWidth': 10, 
     481           'fractionWidth': 0, 
     482           'decimalChar': '.', 
     483           'useParensForNegatives': False, 
     484           'groupDigits': True, 
     485           'groupChar': ',', 
     486   
     487 
     488   for d in  _a