symbian-qemu-0.9.1-12/python-win32-2.6.1/lib/collections.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 __all__ = ['deque', 'defaultdict', 'namedtuple']
       
     2 # For bootstrapping reasons, the collection ABCs are defined in _abcoll.py.
       
     3 # They should however be considered an integral part of collections.py.
       
     4 from _abcoll import *
       
     5 import _abcoll
       
     6 __all__ += _abcoll.__all__
       
     7 
       
     8 from _collections import deque, defaultdict
       
     9 from operator import itemgetter as _itemgetter
       
    10 from keyword import iskeyword as _iskeyword
       
    11 import sys as _sys
       
    12 
       
    13 def namedtuple(typename, field_names, verbose=False):
       
    14     """Returns a new subclass of tuple with named fields.
       
    15 
       
    16     >>> Point = namedtuple('Point', 'x y')
       
    17     >>> Point.__doc__                   # docstring for the new class
       
    18     'Point(x, y)'
       
    19     >>> p = Point(11, y=22)             # instantiate with positional args or keywords
       
    20     >>> p[0] + p[1]                     # indexable like a plain tuple
       
    21     33
       
    22     >>> x, y = p                        # unpack like a regular tuple
       
    23     >>> x, y
       
    24     (11, 22)
       
    25     >>> p.x + p.y                       # fields also accessable by name
       
    26     33
       
    27     >>> d = p._asdict()                 # convert to a dictionary
       
    28     >>> d['x']
       
    29     11
       
    30     >>> Point(**d)                      # convert from a dictionary
       
    31     Point(x=11, y=22)
       
    32     >>> p._replace(x=100)               # _replace() is like str.replace() but targets named fields
       
    33     Point(x=100, y=22)
       
    34 
       
    35     """
       
    36 
       
    37     # Parse and validate the field names.  Validation serves two purposes,
       
    38     # generating informative error messages and preventing template injection attacks.
       
    39     if isinstance(field_names, basestring):
       
    40         field_names = field_names.replace(',', ' ').split() # names separated by whitespace and/or commas
       
    41     field_names = tuple(map(str, field_names))
       
    42     for name in (typename,) + field_names:
       
    43         if not all(c.isalnum() or c=='_' for c in name):
       
    44             raise ValueError('Type names and field names can only contain alphanumeric characters and underscores: %r' % name)
       
    45         if _iskeyword(name):
       
    46             raise ValueError('Type names and field names cannot be a keyword: %r' % name)
       
    47         if name[0].isdigit():
       
    48             raise ValueError('Type names and field names cannot start with a number: %r' % name)
       
    49     seen_names = set()
       
    50     for name in field_names:
       
    51         if name.startswith('_'):
       
    52             raise ValueError('Field names cannot start with an underscore: %r' % name)
       
    53         if name in seen_names:
       
    54             raise ValueError('Encountered duplicate field name: %r' % name)
       
    55         seen_names.add(name)
       
    56 
       
    57     # Create and fill-in the class template
       
    58     numfields = len(field_names)
       
    59     argtxt = repr(field_names).replace("'", "")[1:-1]   # tuple repr without parens or quotes
       
    60     reprtxt = ', '.join('%s=%%r' % name for name in field_names)
       
    61     dicttxt = ', '.join('%r: t[%d]' % (name, pos) for pos, name in enumerate(field_names))
       
    62     template = '''class %(typename)s(tuple):
       
    63         '%(typename)s(%(argtxt)s)' \n
       
    64         __slots__ = () \n
       
    65         _fields = %(field_names)r \n
       
    66         def __new__(cls, %(argtxt)s):
       
    67             return tuple.__new__(cls, (%(argtxt)s)) \n
       
    68         @classmethod
       
    69         def _make(cls, iterable, new=tuple.__new__, len=len):
       
    70             'Make a new %(typename)s object from a sequence or iterable'
       
    71             result = new(cls, iterable)
       
    72             if len(result) != %(numfields)d:
       
    73                 raise TypeError('Expected %(numfields)d arguments, got %%d' %% len(result))
       
    74             return result \n
       
    75         def __repr__(self):
       
    76             return '%(typename)s(%(reprtxt)s)' %% self \n
       
    77         def _asdict(t):
       
    78             'Return a new dict which maps field names to their values'
       
    79             return {%(dicttxt)s} \n
       
    80         def _replace(self, **kwds):
       
    81             'Return a new %(typename)s object replacing specified fields with new values'
       
    82             result = self._make(map(kwds.pop, %(field_names)r, self))
       
    83             if kwds:
       
    84                 raise ValueError('Got unexpected field names: %%r' %% kwds.keys())
       
    85             return result \n
       
    86         def __getnewargs__(self):
       
    87             return tuple(self) \n\n''' % locals()
       
    88     for i, name in enumerate(field_names):
       
    89         template += '        %s = property(itemgetter(%d))\n' % (name, i)
       
    90     if verbose:
       
    91         print template
       
    92 
       
    93     # Execute the template string in a temporary namespace and
       
    94     # support tracing utilities by setting a value for frame.f_globals['__name__']
       
    95     namespace = dict(itemgetter=_itemgetter, __name__='namedtuple_%s' % typename)
       
    96     try:
       
    97         exec template in namespace
       
    98     except SyntaxError, e:
       
    99         raise SyntaxError(e.message + ':\n' + template)
       
   100     result = namespace[typename]
       
   101 
       
   102     # For pickling to work, the __module__ variable needs to be set to the frame
       
   103     # where the named tuple is created.  Bypass this step in enviroments where
       
   104     # sys._getframe is not defined (Jython for example).
       
   105     if hasattr(_sys, '_getframe'):
       
   106         result.__module__ = _sys._getframe(1).f_globals['__name__']
       
   107 
       
   108     return result
       
   109 
       
   110 
       
   111 
       
   112 
       
   113 
       
   114 
       
   115 if __name__ == '__main__':
       
   116     # verify that instances can be pickled
       
   117     from cPickle import loads, dumps
       
   118     Point = namedtuple('Point', 'x, y', True)
       
   119     p = Point(x=10, y=20)
       
   120     assert p == loads(dumps(p))
       
   121 
       
   122     # test and demonstrate ability to override methods
       
   123     class Point(namedtuple('Point', 'x y')):
       
   124         __slots__ = ()
       
   125         @property
       
   126         def hypot(self):
       
   127             return (self.x ** 2 + self.y ** 2) ** 0.5
       
   128         def __str__(self):
       
   129             return 'Point: x=%6.3f  y=%6.3f  hypot=%6.3f' % (self.x, self.y, self.hypot)
       
   130 
       
   131     for p in Point(3, 4), Point(14, 5/7.):
       
   132         print p
       
   133 
       
   134     class Point(namedtuple('Point', 'x y')):
       
   135         'Point class with optimized _make() and _replace() without error-checking'
       
   136         __slots__ = ()
       
   137         _make = classmethod(tuple.__new__)
       
   138         def _replace(self, _map=map, **kwds):
       
   139             return self._make(_map(kwds.get, ('x', 'y'), self))
       
   140 
       
   141     print Point(11, 22)._replace(x=100)
       
   142 
       
   143     Point3D = namedtuple('Point3D', Point._fields + ('z',))
       
   144     print Point3D.__doc__
       
   145 
       
   146     import doctest
       
   147     TestResults = namedtuple('TestResults', 'failed attempted')
       
   148     print TestResults(*doctest.testmod())