142
# Implementation of permutations from Python 2.6 documentation:
143
# http://docs.python.org/2.6/library/functions.html#all
144
# Copyright (c) 2001-2010 Python Software Foundation; All Rights Reserved
145
# Licensed under the Python Software Foundation License.
147
for element in iterable:
139
154
from collections import namedtuple
141
TreeEntryTuple = namedtuple('TreeEntryTuple', ['path', 'mode', 'sha'])
142
TreeChangeTuple = namedtuple('TreeChangeTuple', ['type', 'old', 'new'])
143
155
except ImportError:
144
# Provide manual implementations of namedtuples for Python <2.5.
145
# If the class definitions change, be sure to keep these in sync by running
146
# namedtuple(..., verbose=True) in a recent Python and pasting the output.
148
# Necessary globals go here.
156
# Recipe for namedtuple from http://code.activestate.com/recipes/500261/
157
# Copyright (c) 2007 Python Software Foundation; All Rights Reserved
158
# Licensed under the Python Software Foundation License.
151
159
from operator import itemgetter as _itemgetter
153
class TreeEntryTuple(tuple):
154
'TreeEntryTuple(path, mode, sha)'
158
_fields = ('path', 'mode', 'sha')
160
def __new__(_cls, path, mode, sha):
161
return _tuple.__new__(_cls, (path, mode, sha))
164
def _make(cls, iterable, new=tuple.__new__, len=len):
165
'Make a new TreeEntryTuple object from a sequence or iterable'
166
result = new(cls, iterable)
168
raise TypeError('Expected 3 arguments, got %d' % len(result))
172
return 'TreeEntryTuple(path=%r, mode=%r, sha=%r)' % self
175
'Return a new dict which maps field names to their values'
176
return {'path': t[0], 'mode': t[1], 'sha': t[2]}
178
def _replace(_self, **kwds):
179
'Return a new TreeEntryTuple object replacing specified fields with new values'
180
result = _self._make(map(kwds.pop, ('path', 'mode', 'sha'), _self))
182
raise ValueError('Got unexpected field names: %r' % kwds.keys())
185
def __getnewargs__(self):
188
path = _property(_itemgetter(0))
189
mode = _property(_itemgetter(1))
190
sha = _property(_itemgetter(2))
193
class TreeChangeTuple(tuple):
194
'TreeChangeTuple(type, old, new)'
198
_fields = ('type', 'old', 'new')
200
def __new__(_cls, type, old, new):
201
return _tuple.__new__(_cls, (type, old, new))
204
def _make(cls, iterable, new=tuple.__new__, len=len):
205
'Make a new TreeChangeTuple object from a sequence or iterable'
206
result = new(cls, iterable)
208
raise TypeError('Expected 3 arguments, got %d' % len(result))
212
return 'TreeChangeTuple(type=%r, old=%r, new=%r)' % self
215
'Return a new dict which maps field names to their values'
216
return {'type': t[0], 'old': t[1], 'new': t[2]}
218
def _replace(_self, **kwds):
219
'Return a new TreeChangeTuple object replacing specified fields with new values'
220
result = _self._make(map(kwds.pop, ('type', 'old', 'new'), _self))
222
raise ValueError('Got unexpected field names: %r' % kwds.keys())
225
def __getnewargs__(self):
228
type = _property(_itemgetter(0))
229
old = _property(_itemgetter(1))
230
new = _property(_itemgetter(2))
160
from keyword import iskeyword as _iskeyword
163
def namedtuple(typename, field_names, verbose=False, rename=False):
164
"""Returns a new subclass of tuple with named fields.
166
>>> Point = namedtuple('Point', 'x y')
167
>>> Point.__doc__ # docstring for the new class
169
>>> p = Point(11, y=22) # instantiate with positional args or keywords
170
>>> p[0] + p[1] # indexable like a plain tuple
172
>>> x, y = p # unpack like a regular tuple
175
>>> p.x + p.y # fields also accessable by name
177
>>> d = p._asdict() # convert to a dictionary
180
>>> Point(**d) # convert from a dictionary
182
>>> p._replace(x=100) # _replace() is like str.replace() but targets named fields
187
# Parse and validate the field names. Validation serves two purposes,
188
# generating informative error messages and preventing template injection attacks.
189
if isinstance(field_names, basestring):
190
field_names = field_names.replace(',', ' ').split() # names separated by whitespace and/or commas
191
field_names = tuple(map(str, field_names))
193
names = list(field_names)
195
for i, name in enumerate(names):
196
if (not min(c.isalnum() or c=='_' for c in name) or _iskeyword(name)
197
or not name or name[0].isdigit() or name.startswith('_')
201
field_names = tuple(names)
202
for name in (typename,) + field_names:
203
if not min(c.isalnum() or c=='_' for c in name):
204
raise ValueError('Type names and field names can only contain alphanumeric characters and underscores: %r' % name)
206
raise ValueError('Type names and field names cannot be a keyword: %r' % name)
207
if name[0].isdigit():
208
raise ValueError('Type names and field names cannot start with a number: %r' % name)
210
for name in field_names:
211
if name.startswith('_') and not rename:
212
raise ValueError('Field names cannot start with an underscore: %r' % name)
213
if name in seen_names:
214
raise ValueError('Encountered duplicate field name: %r' % name)
217
# Create and fill-in the class template
218
numfields = len(field_names)
219
argtxt = repr(field_names).replace("'", "")[1:-1] # tuple repr without parens or quotes
220
reprtxt = ', '.join('%s=%%r' % name for name in field_names)
221
template = '''class %(typename)s(tuple):
222
'%(typename)s(%(argtxt)s)' \n
224
_fields = %(field_names)r \n
225
def __new__(_cls, %(argtxt)s):
226
return _tuple.__new__(_cls, (%(argtxt)s)) \n
228
def _make(cls, iterable, new=tuple.__new__, len=len):
229
'Make a new %(typename)s object from a sequence or iterable'
230
result = new(cls, iterable)
231
if len(result) != %(numfields)d:
232
raise TypeError('Expected %(numfields)d arguments, got %%d' %% len(result))
235
return '%(typename)s(%(reprtxt)s)' %% self \n
237
'Return a new dict which maps field names to their values'
238
return dict(zip(self._fields, self)) \n
239
def _replace(_self, **kwds):
240
'Return a new %(typename)s object replacing specified fields with new values'
241
result = _self._make(map(kwds.pop, %(field_names)r, _self))
243
raise ValueError('Got unexpected field names: %%r' %% kwds.keys())
245
def __getnewargs__(self):
246
return tuple(self) \n\n''' % locals()
247
for i, name in enumerate(field_names):
248
template += ' %s = _property(_itemgetter(%d))\n' % (name, i)
252
# Execute the template string in a temporary namespace
253
namespace = dict(_itemgetter=_itemgetter, __name__='namedtuple_%s' % typename,
254
_property=property, _tuple=tuple)
256
exec template in namespace
257
except SyntaxError, e:
258
raise SyntaxError(e.message + ':\n' + template)
259
result = namespace[typename]
261
# For pickling to work, the __module__ variable needs to be set to the frame
262
# where the named tuple is created. Bypass this step in enviroments where
263
# sys._getframe is not defined (Jython for example) or sys._getframe is not
264
# defined for arguments greater than 0 (IronPython).
266
result.__module__ = _sys._getframe(1).f_globals.get('__name__', '__main__')
267
except (AttributeError, ValueError):