##// END OF EJS Templates
Fixes for python2.5 compatibility.
Fernando Perez -
Show More
@@ -0,0 +1,110 b''
1 """Code taken from the Python2.6 standard library for backwards compatibility.
2
3 This is just so we can use 2.6 features when running in 2.5, the code below is
4 copied verbatim from the stdlib's collections and doctest modules.
5 """
6
7 from keyword import iskeyword as _iskeyword
8 from operator import itemgetter as _itemgetter
9 import sys as _sys
10
11 def namedtuple(typename, field_names, verbose=False):
12 """Returns a new subclass of tuple with named fields.
13
14 >>> Point = namedtuple('Point', 'x y')
15 >>> Point.__doc__ # docstring for the new class
16 'Point(x, y)'
17 >>> p = Point(11, y=22) # instantiate with positional args or keywords
18 >>> p[0] + p[1] # indexable like a plain tuple
19 33
20 >>> x, y = p # unpack like a regular tuple
21 >>> x, y
22 (11, 22)
23 >>> p.x + p.y # fields also accessable by name
24 33
25 >>> d = p._asdict() # convert to a dictionary
26 >>> d['x']
27 11
28 >>> Point(**d) # convert from a dictionary
29 Point(x=11, y=22)
30 >>> p._replace(x=100) # _replace() is like str.replace() but targets named fields
31 Point(x=100, y=22)
32
33 """
34
35 # Parse and validate the field names. Validation serves two purposes,
36 # generating informative error messages and preventing template injection attacks.
37 if isinstance(field_names, basestring):
38 field_names = field_names.replace(',', ' ').split() # names separated by whitespace and/or commas
39 field_names = tuple(map(str, field_names))
40 for name in (typename,) + field_names:
41 if not all(c.isalnum() or c=='_' for c in name):
42 raise ValueError('Type names and field names can only contain alphanumeric characters and underscores: %r' % name)
43 if _iskeyword(name):
44 raise ValueError('Type names and field names cannot be a keyword: %r' % name)
45 if name[0].isdigit():
46 raise ValueError('Type names and field names cannot start with a number: %r' % name)
47 seen_names = set()
48 for name in field_names:
49 if name.startswith('_'):
50 raise ValueError('Field names cannot start with an underscore: %r' % name)
51 if name in seen_names:
52 raise ValueError('Encountered duplicate field name: %r' % name)
53 seen_names.add(name)
54
55 # Create and fill-in the class template
56 numfields = len(field_names)
57 argtxt = repr(field_names).replace("'", "")[1:-1] # tuple repr without parens or quotes
58 reprtxt = ', '.join('%s=%%r' % name for name in field_names)
59 dicttxt = ', '.join('%r: t[%d]' % (name, pos) for pos, name in enumerate(field_names))
60 template = '''class %(typename)s(tuple):
61 '%(typename)s(%(argtxt)s)' \n
62 __slots__ = () \n
63 _fields = %(field_names)r \n
64 def __new__(_cls, %(argtxt)s):
65 return _tuple.__new__(_cls, (%(argtxt)s)) \n
66 @classmethod
67 def _make(cls, iterable, new=tuple.__new__, len=len):
68 'Make a new %(typename)s object from a sequence or iterable'
69 result = new(cls, iterable)
70 if len(result) != %(numfields)d:
71 raise TypeError('Expected %(numfields)d arguments, got %%d' %% len(result))
72 return result \n
73 def __repr__(self):
74 return '%(typename)s(%(reprtxt)s)' %% self \n
75 def _asdict(t):
76 'Return a new dict which maps field names to their values'
77 return {%(dicttxt)s} \n
78 def _replace(_self, **kwds):
79 'Return a new %(typename)s object replacing specified fields with new values'
80 result = _self._make(map(kwds.pop, %(field_names)r, _self))
81 if kwds:
82 raise ValueError('Got unexpected field names: %%r' %% kwds.keys())
83 return result \n
84 def __getnewargs__(self):
85 return tuple(self) \n\n''' % locals()
86 for i, name in enumerate(field_names):
87 template += ' %s = _property(_itemgetter(%d))\n' % (name, i)
88 if verbose:
89 print template
90
91 # Execute the template string in a temporary namespace and
92 # support tracing utilities by setting a value for frame.f_globals['__name__']
93 namespace = dict(_itemgetter=_itemgetter, __name__='namedtuple_%s' % typename,
94 _property=property, _tuple=tuple)
95 try:
96 exec template in namespace
97 except SyntaxError, e:
98 raise SyntaxError(e.message + ':\n' + template)
99 result = namespace[typename]
100
101 # For pickling to work, the __module__ variable needs to be set to the frame
102 # where the named tuple is created. Bypass this step in enviroments where
103 # sys._getframe is not defined (Jython for example).
104 if hasattr(_sys, '_getframe'):
105 result.__module__ = _sys._getframe(1).f_globals.get('__name__', '__main__')
106
107 return result
108
109
110 TestResults = namedtuple('TestResults', 'failed attempted')
@@ -40,7 +40,11 b' from __future__ import absolute_import'
40 import re
40 import re
41 import sys
41 import sys
42 import unittest
42 import unittest
43 from doctest import DocTestFinder, DocTestRunner, TestResults
43 from doctest import DocTestFinder, DocTestRunner
44 try:
45 from doctest import TestResults
46 except:
47 from ._doctest26 import TestResults
44
48
45 # Our own, a nose monkeypatch
49 # Our own, a nose monkeypatch
46 from . import nosepatch
50 from . import nosepatch
General Comments 0
You need to be logged in to leave comments. Login now