diff options
Diffstat (limited to 'git')
-rw-r--r-- | git/cmd.py | 11 | ||||
-rw-r--r-- | git/config.py | 8 | ||||
-rw-r--r-- | git/objects/commit.py | 14 | ||||
-rw-r--r-- | git/objects/submodule/base.py | 12 | ||||
-rw-r--r-- | git/objects/submodule/root.py | 8 | ||||
-rw-r--r-- | git/odict.py | 1545 | ||||
-rw-r--r-- | git/refs/tag.py | 4 | ||||
-rw-r--r-- | git/test/lib/asserts.py | 1 | ||||
-rw-r--r-- | git/test/lib/helper.py | 4 | ||||
-rw-r--r-- | git/test/performance/test_commit.py | 16 | ||||
-rw-r--r-- | git/test/performance/test_odb.py | 14 | ||||
-rw-r--r-- | git/test/performance/test_streams.py | 35 | ||||
-rw-r--r-- | git/test/performance/test_utils.py | 44 | ||||
-rw-r--r-- | git/test/test_actor.py | 1 | ||||
-rw-r--r-- | git/test/test_commit.py | 5 | ||||
-rw-r--r-- | git/test/test_config.py | 1 | ||||
-rw-r--r-- | git/test/test_diff.py | 1 | ||||
-rw-r--r-- | git/test/test_git.py | 4 | ||||
-rw-r--r-- | git/test/test_index.py | 1 |
19 files changed, 116 insertions, 1613 deletions
@@ -6,6 +6,7 @@ import os import sys +import logging from util import ( LazyMixin, stream_copy @@ -22,6 +23,8 @@ execute_kwargs = ('istream', 'with_keep_cwd', 'with_extended_output', 'with_exceptions', 'as_process', 'output_stream') +log = logging.getLogger('git.cmd') + __all__ = ('Git', ) @@ -334,7 +337,7 @@ class Git(LazyMixin): If you add additional keyword arguments to the signature of this method, you must update the execute_kwargs tuple housed in this module.""" if self.GIT_PYTHON_TRACE and (self.GIT_PYTHON_TRACE != 'full' or as_process): - print(' '.join(command)) + log.info(' '.join(command)) # Allow the user to have the command executed in their working dir. if with_keep_cwd or self._working_dir is None: @@ -389,11 +392,11 @@ class Git(LazyMixin): if self.GIT_PYTHON_TRACE == 'full': cmdstr = " ".join(command) if stderr_value: - print("%s -> %d; stdout: '%s'; stderr: '%s'" % (cmdstr, status, stdout_value, stderr_value)) + log.info("%s -> %d; stdout: '%s'; stderr: '%s'", cmdstr, status, stdout_value, stderr_value) elif stdout_value: - print("%s -> %d; stdout: '%s'" % (cmdstr, status, stdout_value)) + log.info("%s -> %d; stdout: '%s'", cmdstr, status, stdout_value) else: - print("%s -> %d" % (cmdstr, status)) + log.info("%s -> %d", cmdstr, status) # END handle debug printing if with_exceptions and status != 0: diff --git a/git/config.py b/git/config.py index 51337db4..6a85760c 100644 --- a/git/config.py +++ b/git/config.py @@ -9,6 +9,7 @@ configuration files""" import re import ConfigParser as cp import inspect +import logging from git.odict import OrderedDict from git.util import LockFile @@ -16,6 +17,9 @@ from git.util import LockFile __all__ = ('GitConfigParser', 'SectionConstraint') +log = logging.getLogger('git.config') + + class MetaParserBuilder(type): """Utlity class wrapping base-class methods into decorators that assure read-only properties""" @@ -186,8 +190,8 @@ class GitConfigParser(cp.RawConfigParser, object): try: try: self.write() - except IOError as e: - print("Exception during destruction of GitConfigParser: %s" % str(e)) + except IOError: + log.error("Exception during destruction of GitConfigParser", exc_info=True) finally: self._lock._release_lock() diff --git a/git/objects/commit.py b/git/objects/commit.py index 4a4a314c..9c733695 100644 --- a/git/objects/commit.py +++ b/git/objects/commit.py @@ -31,7 +31,9 @@ from time import ( altzone ) import os -import sys +import logging + +log = logging.getLogger('git.objects.commit') __all__ = ('Commit', ) @@ -473,16 +475,16 @@ class Commit(base.Object, Iterable, Diffable, Traversable, Serializable): try: self.author.name = self.author.name.decode(self.encoding) except UnicodeDecodeError: - print >> sys.stderr, "Failed to decode author name '%s' using encoding %s" % ( - self.author.name, self.encoding) + log.error("Failed to decode author name '%s' using encoding %s", self.author.name, self.encoding, + exc_info=True) # END handle author's encoding # decode committer name try: self.committer.name = self.committer.name.decode(self.encoding) except UnicodeDecodeError: - print >> sys.stderr, "Failed to decode committer name '%s' using encoding %s" % ( - self.committer.name, self.encoding) + log.error("Failed to decode committer name '%s' using encoding %s", self.committer.name, self.encoding, + exc_info=True) # END handle author's encoding # a stream from our data simply gives us the plain message @@ -491,7 +493,7 @@ class Commit(base.Object, Iterable, Diffable, Traversable, Serializable): try: self.message = self.message.decode(self.encoding) except UnicodeDecodeError: - print >> sys.stderr, "Failed to decode message '%s' using encoding %s" % (self.message, self.encoding) + log.error("Failed to decode message '%s' using encoding %s", self.message, self.encoding, exc_info=True) # END exception handling return self diff --git a/git/objects/submodule/base.py b/git/objects/submodule/base.py index 6951fd63..d6f8982b 100644 --- a/git/objects/submodule/base.py +++ b/git/objects/submodule/base.py @@ -27,11 +27,14 @@ import stat import git import os -import sys +import logging __all__ = ["Submodule", "UpdateProgress"] +log = logging.getLogger('git.objects.submodule.base') + + class UpdateProgress(RemoteProgress): """Class providing detailed progress information to the caller who should @@ -408,7 +411,7 @@ class Submodule(util.IndexObject, Iterable, Traversable): mrepo.head.set_reference(local_branch, logmsg="submodule: attaching head to %s" % local_branch) mrepo.head.ref.set_tracking_branch(remote_branch) except IndexError: - print >> sys.stderr, "Warning: Failed to checkout tracking branch %s" % self.branch_path + log.warn("Failed to checkout tracking branch %s", self.branch_path) # END handle tracking branch # NOTE: Have to write the repo config file as well, otherwise @@ -437,11 +440,10 @@ class Submodule(util.IndexObject, Iterable, Traversable): binsha = rcommit.binsha hexsha = rcommit.hexsha else: - print >> sys.stderr, "%s a tracking branch was not set for local branch '%s'" % ( - msg_base, mrepo.head.ref) + log.error("%s a tracking branch was not set for local branch '%s'", msg_base, mrepo.head.ref) # END handle remote ref else: - print >> sys.stderr, "%s there was no local tracking branch" % msg_base + log.error("%s there was no local tracking branch", msg_base) # END handle detached head # END handle to_latest_revision option diff --git a/git/objects/submodule/root.py b/git/objects/submodule/root.py index 871cc21c..708749c7 100644 --- a/git/objects/submodule/root.py +++ b/git/objects/submodule/root.py @@ -5,10 +5,12 @@ from util import ( from git.exc import InvalidGitRepositoryError import git -import sys +import logging __all__ = ["RootModule", "RootUpdateProgress"] +log = logging.getLogger('git.objects.submodule.root') + class RootUpdateProgress(UpdateProgress): @@ -247,8 +249,8 @@ class RootModule(Submodule): # this way, it will be checked out in the next step # This will change the submodule relative to us, so # the user will be able to commit the change easily - print >> sys.stderr, "WARNING: Current sha %s was not contained in the tracking\ - branch at the new remote, setting it the the remote's tracking branch" % sm.hexsha + log.warn("Current sha %s was not contained in the tracking\ + branch at the new remote, setting it the the remote's tracking branch", sm.hexsha) sm.binsha = rref.commit.binsha # END reset binsha diff --git a/git/odict.py b/git/odict.py index c505b7fd..f003d14e 100644 --- a/git/odict.py +++ b/git/odict.py @@ -1,1535 +1,10 @@ -# odict.py -# An Ordered Dictionary object -# Copyright (C) 2005 Nicola Larosa, Michael Foord -# E-mail: nico AT tekNico DOT net, fuzzyman AT voidspace DOT org DOT uk - -# This software is licensed under the terms of the BSD license. -# http://www.voidspace.org.uk/python/license.shtml -# Basically you're free to copy, modify, distribute and relicense it, -# So long as you keep a copy of the license with it. - -# Documentation at http://www.voidspace.org.uk/python/odict.html -# For information about bugfixes, updates and support, please join the -# Pythonutils mailing list: -# http://groups.google.com/group/pythonutils/ -# Comments, suggestions and bug reports welcome. - -"""A dict that keeps keys in insertion order""" -from __future__ import generators - -__author__ = ('Nicola Larosa <nico-NoSp@m-tekNico.net>,' - 'Michael Foord <fuzzyman AT voidspace DOT org DOT uk>') - -__docformat__ = "restructuredtext en" - -__revision__ = '$Id: odict.py 129 2005-09-12 18:15:28Z teknico $' - -__version__ = '0.2.2' - -__all__ = ['OrderedDict', 'SequenceOrderedDict'] - -import sys -INTP_VER = sys.version_info[:2] -if INTP_VER < (2, 2): - raise RuntimeError("Python v.2.2 or later required") - -import types -import warnings - - -class OrderedDict(dict): - - """ - A class of dictionary that keeps the insertion order of keys. - - All appropriate methods return keys, items, or values in an ordered way. - - All normal dictionary methods are available. Update and comparison is - restricted to other OrderedDict objects. - - Various sequence methods are available, including the ability to explicitly - mutate the key ordering. - - __contains__ tests: - - >>> d = OrderedDict(((1, 3),)) - >>> 1 in d - 1 - >>> 4 in d - 0 - - __getitem__ tests: - - >>> OrderedDict(((1, 3), (3, 2), (2, 1)))[2] - 1 - >>> OrderedDict(((1, 3), (3, 2), (2, 1)))[4] - Traceback (most recent call last): - KeyError: 4 - - __len__ tests: - - >>> len(OrderedDict()) - 0 - >>> len(OrderedDict(((1, 3), (3, 2), (2, 1)))) - 3 - - get tests: - - >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) - >>> d.get(1) - 3 - >>> d.get(4) is None - 1 - >>> d.get(4, 5) - 5 - >>> d - OrderedDict([(1, 3), (3, 2), (2, 1)]) - - has_key tests: - - >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) - >>> d.has_key(1) - 1 - >>> d.has_key(4) - 0 - """ - - def __init__(self, init_val=(), strict=False): - """ - Create a new ordered dictionary. Cannot init from a normal dict, - nor from kwargs, since items order is undefined in those cases. - - If the ``strict`` keyword argument is ``True`` (``False`` is the - default) then when doing slice assignment - the ``OrderedDict`` you are - assigning from *must not* contain any keys in the remaining dict. - - >>> OrderedDict() - OrderedDict([]) - >>> OrderedDict({1: 1}) - Traceback (most recent call last): - TypeError: undefined order, cannot get items from dict - >>> OrderedDict({1: 1}.items()) - OrderedDict([(1, 1)]) - >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) - >>> d - OrderedDict([(1, 3), (3, 2), (2, 1)]) - >>> OrderedDict(d) - OrderedDict([(1, 3), (3, 2), (2, 1)]) - """ - self.strict = strict - dict.__init__(self) - if isinstance(init_val, OrderedDict): - self._sequence = init_val.keys() - dict.update(self, init_val) - elif isinstance(init_val, dict): - # we lose compatibility with other ordered dict types this way - raise TypeError('undefined order, cannot get items from dict') - else: - self._sequence = [] - self.update(init_val) - -### Special methods ### - - def __delitem__(self, key): - """ - >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) - >>> del d[3] - >>> d - OrderedDict([(1, 3), (2, 1)]) - >>> del d[3] - Traceback (most recent call last): - KeyError: 3 - >>> d[3] = 2 - >>> d - OrderedDict([(1, 3), (2, 1), (3, 2)]) - >>> del d[0:1] - >>> d - OrderedDict([(2, 1), (3, 2)]) - """ - if isinstance(key, types.SliceType): - # FIXME: efficiency? - keys = self._sequence[key] - for entry in keys: - dict.__delitem__(self, entry) - del self._sequence[key] - else: - # do the dict.__delitem__ *first* as it raises - # the more appropriate error - dict.__delitem__(self, key) - self._sequence.remove(key) - - def __eq__(self, other): - """ - >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) - >>> d == OrderedDict(d) - True - >>> d == OrderedDict(((1, 3), (2, 1), (3, 2))) - False - >>> d == OrderedDict(((1, 0), (3, 2), (2, 1))) - False - >>> d == OrderedDict(((0, 3), (3, 2), (2, 1))) - False - >>> d == dict(d) - False - >>> d == False - False - """ - if isinstance(other, OrderedDict): - # FIXME: efficiency? - # Generate both item lists for each compare - return (self.items() == other.items()) - else: - return False - - def __lt__(self, other): - """ - >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) - >>> c = OrderedDict(((0, 3), (3, 2), (2, 1))) - >>> c < d - True - >>> d < c - False - >>> d < dict(c) - Traceback (most recent call last): - TypeError: Can only compare with other OrderedDicts - """ - if not isinstance(other, OrderedDict): - raise TypeError('Can only compare with other OrderedDicts') - # FIXME: efficiency? - # Generate both item lists for each compare - return (self.items() < other.items()) - - def __le__(self, other): - """ - >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) - >>> c = OrderedDict(((0, 3), (3, 2), (2, 1))) - >>> e = OrderedDict(d) - >>> c <= d - True - >>> d <= c - False - >>> d <= dict(c) - Traceback (most recent call last): - TypeError: Can only compare with other OrderedDicts - >>> d <= e - True - """ - if not isinstance(other, OrderedDict): - raise TypeError('Can only compare with other OrderedDicts') - # FIXME: efficiency? - # Generate both item lists for each compare - return (self.items() <= other.items()) - - def __ne__(self, other): - """ - >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) - >>> d != OrderedDict(d) - False - >>> d != OrderedDict(((1, 3), (2, 1), (3, 2))) - True - >>> d != OrderedDict(((1, 0), (3, 2), (2, 1))) - True - >>> d == OrderedDict(((0, 3), (3, 2), (2, 1))) - False - >>> d != dict(d) - True - >>> d != False - True - """ - if isinstance(other, OrderedDict): - # FIXME: efficiency? - # Generate both item lists for each compare - return not (self.items() == other.items()) - else: - return True - - def __gt__(self, other): - """ - >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) - >>> c = OrderedDict(((0, 3), (3, 2), (2, 1))) - >>> d > c - True - >>> c > d - False - >>> d > dict(c) - Traceback (most recent call last): - TypeError: Can only compare with other OrderedDicts - """ - if not isinstance(other, OrderedDict): - raise TypeError('Can only compare with other OrderedDicts') - # FIXME: efficiency? - # Generate both item lists for each compare - return (self.items() > other.items()) - - def __ge__(self, other): - """ - >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) - >>> c = OrderedDict(((0, 3), (3, 2), (2, 1))) - >>> e = OrderedDict(d) - >>> c >= d - False - >>> d >= c - True - >>> d >= dict(c) - Traceback (most recent call last): - TypeError: Can only compare with other OrderedDicts - >>> e >= d - True - """ - if not isinstance(other, OrderedDict): - raise TypeError('Can only compare with other OrderedDicts') - # FIXME: efficiency? - # Generate both item lists for each compare - return (self.items() >= other.items()) - - def __repr__(self): - """ - Used for __repr__ and __str__ - - >>> r1 = repr(OrderedDict((('a', 'b'), ('c', 'd'), ('e', 'f')))) - >>> r1 - "OrderedDict([('a', 'b'), ('c', 'd'), ('e', 'f')])" - >>> r2 = repr(OrderedDict((('a', 'b'), ('e', 'f'), ('c', 'd')))) - >>> r2 - "OrderedDict([('a', 'b'), ('e', 'f'), ('c', 'd')])" - >>> r1 == str(OrderedDict((('a', 'b'), ('c', 'd'), ('e', 'f')))) - True - >>> r2 == str(OrderedDict((('a', 'b'), ('e', 'f'), ('c', 'd')))) - True - """ - return '%s([%s])' % (self.__class__.__name__, ', '.join( - ['(%r, %r)' % (key, self[key]) for key in self._sequence])) - - def __setitem__(self, key, val): - """ - Allows slice assignment, so long as the slice is an OrderedDict - >>> d = OrderedDict() - >>> d['a'] = 'b' - >>> d['b'] = 'a' - >>> d[3] = 12 - >>> d - OrderedDict([('a', 'b'), ('b', 'a'), (3, 12)]) - >>> d[:] = OrderedDict(((1, 2), (2, 3), (3, 4))) - >>> d - OrderedDict([(1, 2), (2, 3), (3, 4)]) - >>> d[::2] = OrderedDict(((7, 8), (9, 10))) - >>> d - OrderedDict([(7, 8), (2, 3), (9, 10)]) - >>> d = OrderedDict(((0, 1), (1, 2), (2, 3), (3, 4))) - >>> d[1:3] = OrderedDict(((1, 2), (5, 6), (7, 8))) - >>> d - OrderedDict([(0, 1), (1, 2), (5, 6), (7, 8), (3, 4)]) - >>> d = OrderedDict(((0, 1), (1, 2), (2, 3), (3, 4)), strict=True) - >>> d[1:3] = OrderedDict(((1, 2), (5, 6), (7, 8))) - >>> d - OrderedDict([(0, 1), (1, 2), (5, 6), (7, 8), (3, 4)]) - - >>> a = OrderedDict(((0, 1), (1, 2), (2, 3)), strict=True) - >>> a[3] = 4 - >>> a - OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)]) - >>> a[::1] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)]) - >>> a - OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)]) - >>> a[:2] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)]) - Traceback (most recent call last): - ValueError: slice assignment must be from unique keys - >>> a = OrderedDict(((0, 1), (1, 2), (2, 3))) - >>> a[3] = 4 - >>> a - OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)]) - >>> a[::1] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)]) - >>> a - OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)]) - >>> a[:2] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)]) - >>> a - OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)]) - >>> a[::-1] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)]) - >>> a - OrderedDict([(3, 4), (2, 3), (1, 2), (0, 1)]) - - >>> d = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)]) - >>> d[:1] = 3 - Traceback (most recent call last): - TypeError: slice assignment requires an OrderedDict - - >>> d = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)]) - >>> d[:1] = OrderedDict([(9, 8)]) - >>> d - OrderedDict([(9, 8), (1, 2), (2, 3), (3, 4)]) - """ - if isinstance(key, types.SliceType): - if not isinstance(val, OrderedDict): - # FIXME: allow a list of tuples? - raise TypeError('slice assignment requires an OrderedDict') - keys = self._sequence[key] - # NOTE: Could use ``range(*key.indices(len(self._sequence)))`` - indexes = range(len(self._sequence))[key] - if key.step is None: - # NOTE: new slice may not be the same size as the one being - # overwritten ! - # NOTE: What is the algorithm for an impossible slice? - # e.g. d[5:3] - pos = key.start or 0 - del self[key] - newkeys = val.keys() - for k in newkeys: - if k in self: - if self.strict: - raise ValueError('slice assignment must be from ' - 'unique keys') - else: - # NOTE: This removes duplicate keys *first* - # so start position might have changed? - del self[k] - self._sequence = (self._sequence[:pos] + newkeys + - self._sequence[pos:]) - dict.update(self, val) - else: - # extended slice - length of new slice must be the same - # as the one being replaced - if len(keys) != len(val): - raise ValueError('attempt to assign sequence of size %s ' - 'to extended slice of size %s' % (len(val), len(keys))) - # FIXME: efficiency? - del self[key] - item_list = zip(indexes, val.items()) - # smallest indexes first - higher indexes not guaranteed to - # exist - item_list.sort() - for pos, (newkey, newval) in item_list: - if self.strict and newkey in self: - raise ValueError('slice assignment must be from unique' - ' keys') - self.insert(pos, newkey, newval) - else: - if key not in self: - self._sequence.append(key) - dict.__setitem__(self, key, val) - - def __getitem__(self, key): - """ - Allows slicing. Returns an OrderedDict if you slice. - >>> b = OrderedDict([(7, 0), (6, 1), (5, 2), (4, 3), (3, 4), (2, 5), (1, 6)]) - >>> b[::-1] - OrderedDict([(1, 6), (2, 5), (3, 4), (4, 3), (5, 2), (6, 1), (7, 0)]) - >>> b[2:5] - OrderedDict([(5, 2), (4, 3), (3, 4)]) - >>> type(b[2:4]) - <class '__main__.OrderedDict'> - """ - if isinstance(key, types.SliceType): - # FIXME: does this raise the error we want? - keys = self._sequence[key] - # FIXME: efficiency? - return OrderedDict([(entry, self[entry]) for entry in keys]) - else: - return dict.__getitem__(self, key) - - __str__ = __repr__ - - def __setattr__(self, name, value): - """ - Implemented so that accesses to ``sequence`` raise a warning and are - diverted to the new ``setkeys`` method. - """ - if name == 'sequence': - warnings.warn('Use of the sequence attribute is deprecated.' - ' Use the keys method instead.', DeprecationWarning) - # NOTE: doesn't return anything - self.setkeys(value) - else: - # FIXME: do we want to allow arbitrary setting of attributes? - # Or do we want to manage it? - object.__setattr__(self, name, value) - - def __getattr__(self, name): - """ - Implemented so that access to ``sequence`` raises a warning. - - >>> d = OrderedDict() - >>> d.sequence - [] - """ - if name == 'sequence': - warnings.warn('Use of the sequence attribute is deprecated.' - ' Use the keys method instead.', DeprecationWarning) - # NOTE: Still (currently) returns a direct reference. Need to - # because code that uses sequence will expect to be able to - # mutate it in place. - return self._sequence - else: - # raise the appropriate error - raise AttributeError("OrderedDict has no '%s' attribute" % name) - - def __deepcopy__(self, memo): - """ - To allow deepcopy to work with OrderedDict. - - >>> from copy import deepcopy - >>> a = OrderedDict([(1, 1), (2, 2), (3, 3)]) - >>> a['test'] = {} - >>> b = deepcopy(a) - >>> b == a - True - >>> b is a - False - >>> a['test'] is b['test'] - False - """ - from copy import deepcopy - return self.__class__(deepcopy(self.items(), memo), self.strict) - - -### Read-only methods ### - - def copy(self): - """ - >>> OrderedDict(((1, 3), (3, 2), (2, 1))).copy() - OrderedDict([(1, 3), (3, 2), (2, 1)]) - """ - return OrderedDict(self) - - def items(self): - """ - ``items`` returns a list of tuples representing all the - ``(key, value)`` pairs in the dictionary. - - >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) - >>> d.items() - [(1, 3), (3, 2), (2, 1)] - >>> d.clear() - >>> d.items() - [] - """ - return zip(self._sequence, self.values()) - - def keys(self): - """ - Return a list of keys in the ``OrderedDict``. - - >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) - >>> d.keys() - [1, 3, 2] - """ - return self._sequence[:] - - def values(self, values=None): - """ - Return a list of all the values in the OrderedDict. - - Optionally you can pass in a list of values, which will replace the - current list. The value list must be the same len as the OrderedDict. - - >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) - >>> d.values() - [3, 2, 1] - """ - return [self[key] for key in self._sequence] - - def iteritems(self): - """ - >>> ii = OrderedDict(((1, 3), (3, 2), (2, 1))).iteritems() - >>> ii.next() - (1, 3) - >>> ii.next() - (3, 2) - >>> ii.next() - (2, 1) - >>> ii.next() - Traceback (most recent call last): - StopIteration - """ - - def make_iter(self=self): - keys = self.iterkeys() - while True: - key = keys.next() - yield (key, self[key]) - return make_iter() - - def iterkeys(self): - """ - >>> ii = OrderedDict(((1, 3), (3, 2), (2, 1))).iterkeys() - >>> ii.next() - 1 - >>> ii.next() - 3 - >>> ii.next() - 2 - >>> ii.next() - Traceback (most recent call last): - StopIteration - """ - return iter(self._sequence) - - __iter__ = iterkeys - - def itervalues(self): - """ - >>> iv = OrderedDict(((1, 3), (3, 2), (2, 1))).itervalues() - >>> iv.next() - 3 - >>> iv.next() - 2 - >>> iv.next() - 1 - >>> iv.next() - Traceback (most recent call last): - StopIteration - """ - - def make_iter(self=self): - keys = self.iterkeys() - while True: - yield self[keys.next()] - return make_iter() - -### Read-write methods ### - - def clear(self): - """ - >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) - >>> d.clear() - >>> d - OrderedDict([]) - """ - dict.clear(self) - self._sequence = [] - - def pop(self, key, *args): - """ - No dict.pop in Python 2.2, gotta reimplement it - - >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) - >>> d.pop(3) - 2 - >>> d - OrderedDict([(1, 3), (2, 1)]) - >>> d.pop(4) - Traceback (most recent call last): - KeyError: 4 - >>> d.pop(4, 0) - 0 - >>> d.pop(4, 0, 1) - Traceback (most recent call last): - TypeError: pop expected at most 2 arguments, got 3 - """ - if len(args) > 1: - raise TypeError('pop expected at most 2 arguments, got %s' % (len(args) + 1)) - if key in self: - val = self[key] - del self[key] - else: - try: - val = args[0] - except IndexError: - raise KeyError(key) - return val - - def popitem(self, i=-1): - """ - Delete and return an item specified by index, not a random one as in - dict. The index is -1 by default (the last item). - - >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) - >>> d.popitem() - (2, 1) - >>> d - OrderedDict([(1, 3), (3, 2)]) - >>> d.popitem(0) - (1, 3) - >>> OrderedDict().popitem() - Traceback (most recent call last): - KeyError: 'popitem(): dictionary is empty' - >>> d.popitem(2) - Traceback (most recent call last): - IndexError: popitem(): index 2 not valid - """ - if not self._sequence: - raise KeyError('popitem(): dictionary is empty') - try: - key = self._sequence[i] - except IndexError: - raise IndexError('popitem(): index %s not valid' % i) - return (key, self.pop(key)) - - def setdefault(self, key, defval=None): - """ - >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) - >>> d.setdefault(1) - 3 - >>> d.setdefault(4) is None - True - >>> d - OrderedDict([(1, 3), (3, 2), (2, 1), (4, None)]) - >>> d.setdefault(5, 0) - 0 - >>> d - OrderedDict([(1, 3), (3, 2), (2, 1), (4, None), (5, 0)]) - """ - if key in self: - return self[key] - else: - self[key] = defval - return defval - - def update(self, from_od): - """ - Update from another OrderedDict or sequence of (key, value) pairs - - >>> d = OrderedDict(((1, 0), (0, 1))) - >>> d.update(OrderedDict(((1, 3), (3, 2), (2, 1)))) - >>> d - OrderedDict([(1, 3), (0, 1), (3, 2), (2, 1)]) - >>> d.update({4: 4}) - Traceback (most recent call last): - TypeError: undefined order, cannot get items from dict - >>> d.update((4, 4)) - Traceback (most recent call last): - TypeError: cannot convert dictionary update sequence element "4" to a 2-item sequence - """ - if isinstance(from_od, OrderedDict): - for key, val in from_od.items(): - self[key] = val - elif isinstance(from_od, dict): - # we lose compatibility with other ordered dict types this way - raise TypeError('undefined order, cannot get items from dict') - else: - # FIXME: efficiency? - # sequence of 2-item sequences, or error - for item in from_od: - try: - key, val = item - except TypeError: - raise TypeError('cannot convert dictionary update' - ' sequence element "%s" to a 2-item sequence' % item) - self[key] = val - - def rename(self, old_key, new_key): - """ - Rename the key for a given value, without modifying sequence order. - - For the case where new_key already exists this raise an exception, - since if new_key exists, it is ambiguous as to what happens to the - associated values, and the position of new_key in the sequence. - - >>> od = OrderedDict() - >>> od['a'] = 1 - >>> od['b'] = 2 - >>> od.items() - [('a', 1), ('b', 2)] - >>> od.rename('b', 'c') - >>> od.items() - [('a', 1), ('c', 2)] - >>> od.rename('c', 'a') - Traceback (most recent call last): - ValueError: New key already exists: 'a' - >>> od.rename('d', 'b') - Traceback (most recent call last): - KeyError: 'd' - """ - if new_key == old_key: - # no-op - return - if new_key in self: - raise ValueError("New key already exists: %r" % new_key) - # rename sequence entry - value = self[old_key] - old_idx = self._sequence.index(old_key) - self._sequence[old_idx] = new_key - # rename internal dict entry - dict.__delitem__(self, old_key) - dict.__setitem__(self, new_key, value) - - def setitems(self, items): - """ - This method allows you to set the items in the dict. - - It takes a list of tuples - of the same sort returned by the ``items`` - method. - - >>> d = OrderedDict() - >>> d.setitems(((3, 1), (2, 3), (1, 2))) - >>> d - OrderedDict([(3, 1), (2, 3), (1, 2)]) - """ - self.clear() - # FIXME: this allows you to pass in an OrderedDict as well :-) - self.update(items) - - def setkeys(self, keys): - """ - ``setkeys`` all ows you to pass in a new list of keys which will - replace the current set. This must contain the same set of keys, but - need not be in the same order. - - If you pass in new keys that don't match, a ``KeyError`` will be - raised. - - >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) - >>> d.keys() - [1, 3, 2] - >>> d.setkeys((1, 2, 3)) - >>> d - OrderedDict([(1, 3), (2, 1), (3, 2)]) - >>> d.setkeys(['a', 'b', 'c']) - Traceback (most recent call last): - KeyError: 'Keylist is not the same as current keylist.' - """ - # FIXME: Efficiency? (use set for Python 2.4 :-) - # NOTE: list(keys) rather than keys[:] because keys[:] returns - # a tuple, if keys is a tuple. - kcopy = list(keys) - kcopy.sort() - self._sequence.sort() - if kcopy != self._sequence: - raise KeyError('Keylist is not the same as current keylist.') - # NOTE: This makes the _sequence attribute a new object, instead - # of changing it in place. - # FIXME: efficiency? - self._sequence = list(keys) - - def setvalues(self, values): - """ - You can pass in a list of values, which will replace the - current list. The value list must be the same len as the OrderedDict. - - (Or a ``ValueError`` is raised.) - - >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) - >>> d.setvalues((1, 2, 3)) - >>> d - OrderedDict([(1, 1), (3, 2), (2, 3)]) - >>> d.setvalues([6]) - Traceback (most recent call last): - ValueError: Value list is not the same length as the OrderedDict. - """ - if len(values) != len(self): - # FIXME: correct error to raise? - raise ValueError('Value list is not the same length as the ' - 'OrderedDict.') - self.update(zip(self, values)) - -### Sequence Methods ### - - def index(self, key): - """ - Return the position of the specified key in the OrderedDict. - - >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) - >>> d.index(3) - 1 - >>> d.index(4) - Traceback (most recent call last): - ValueError: list.index(x): x not in list - """ - return self._sequence.index(key) - - def insert(self, index, key, value): - """ - Takes ``index``, ``key``, and ``value`` as arguments. - - Sets ``key`` to ``value``, so that ``key`` is at position ``index`` in - the OrderedDict. - - >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) - >>> d.insert(0, 4, 0) - >>> d - OrderedDict([(4, 0), (1, 3), (3, 2), (2, 1)]) - >>> d.insert(0, 2, 1) - >>> d - OrderedDict([(2, 1), (4, 0), (1, 3), (3, 2)]) - >>> d.insert(8, 8, 1) - >>> d - OrderedDict([(2, 1), (4, 0), (1, 3), (3, 2), (8, 1)]) - """ - if key in self: - # FIXME: efficiency? - del self[key] - self._sequence.insert(index, key) - dict.__setitem__(self, key, value) - - def reverse(self): - """ - Reverse the order of the OrderedDict. - - >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) - >>> d.reverse() - >>> d - OrderedDict([(2, 1), (3, 2), (1, 3)]) - """ - self._sequence.reverse() - - def sort(self, *args, **kwargs): - """ - Sort the key order in the OrderedDict. - - This method takes the same arguments as the ``list.sort`` method on - your version of Python. - - >>> d = OrderedDict(((4, 1), (2, 2), (3, 3), (1, 4))) - >>> d.sort() - >>> d - OrderedDict([(1, 4), (2, 2), (3, 3), (4, 1)]) - """ - self._sequence.sort(*args, **kwargs) - - -class Keys(object): - # FIXME: should this object be a subclass of list? - - """ - Custom object for accessing the keys of an OrderedDict. - - Can be called like the normal ``OrderedDict.keys`` method, but also - supports indexing and sequence methods. - """ - - def __init__(self, main): - self._main = main - - def __call__(self): - """Pretend to be the keys method.""" - return self._main._keys() - - def __getitem__(self, index): - """Fetch the key at position i.""" - # NOTE: this automatically supports slicing :-) - return self._main._sequence[index] - - def __setitem__(self, index, name): - """ - You cannot assign to keys, but you can do slice assignment to re-order - them. - - You can only do slice assignment if the new set of keys is a reordering - of the original set. - """ - if isinstance(index, types.SliceType): - # FIXME: efficiency? - # check length is the same - indexes = range(len(self._main._sequence))[index] - if len(indexes) != len(name): - raise ValueError('attempt to assign sequence of size %s ' - 'to slice of size %s' % (len(name), len(indexes))) - # check they are the same keys - # FIXME: Use set - old_keys = self._main._sequence[index] - new_keys = list(name) - old_keys.sort() - new_keys.sort() - if old_keys != new_keys: - raise KeyError('Keylist is not the same as current keylist.') - orig_vals = [self._main[k] for k in name] - del self._main[index] - vals = zip(indexes, name, orig_vals) - vals.sort() - for i, k, v in vals: - if self._main.strict and k in self._main: - raise ValueError('slice assignment must be from ' - 'unique keys') - self._main.insert(i, k, v) - else: - raise ValueError('Cannot assign to keys') - - ### following methods pinched from UserList and adapted ### - def __repr__(self): - return repr(self._main._sequence) - - # FIXME: do we need to check if we are comparing with another ``Keys`` - # object? (like the __cast method of UserList) - def __lt__(self, other): - return self._main._sequence < other - - def __le__(self, other): - return self._main._sequence <= other - - def __eq__(self, other): - return self._main._sequence == other - - def __ne__(self, other): - return self._main._sequence != other - - def __gt__(self, other): - return self._main._sequence > other - - def __ge__(self, other): - return self._main._sequence >= other - # FIXME: do we need __cmp__ as well as rich comparisons? - - def __cmp__(self, other): - return cmp(self._main._sequence, other) - - def __contains__(self, item): - return item in self._main._sequence - - def __len__(self): - return len(self._main._sequence) - - def __iter__(self): - return self._main.iterkeys() - - def count(self, item): - return self._main._sequence.count(item) - - def index(self, item, *args): - return self._main._sequence.index(item, *args) - - def reverse(self): - self._main._sequence.reverse() - - def sort(self, *args, **kwds): - self._main._sequence.sort(*args, **kwds) - - def __mul__(self, n): - return self._main._sequence * n - __rmul__ = __mul__ - - def __add__(self, other): - return self._main._sequence + other - - def __radd__(self, other): - return other + self._main._sequence - - ## following methods not implemented for keys ## - def __delitem__(self, i): - raise TypeError('Can\'t delete items from keys') - - def __iadd__(self, other): - raise TypeError('Can\'t add in place to keys') - - def __imul__(self, n): - raise TypeError('Can\'t multiply keys in place') - - def append(self, item): - raise TypeError('Can\'t append items to keys') - - def insert(self, i, item): - raise TypeError('Can\'t insert items into keys') - - def pop(self, i=-1): - raise TypeError('Can\'t pop items from keys') - - def remove(self, item): - raise TypeError('Can\'t remove items from keys') - - def extend(self, other): - raise TypeError('Can\'t extend keys') - - -class Items(object): - - """ - Custom object for accessing the items of an OrderedDict. - - Can be called like the normal ``OrderedDict.items`` method, but also - supports indexing and sequence methods. - """ - - def __init__(self, main): - self._main = main - - def __call__(self): - """Pretend to be the items method.""" - return self._main._items() - - def __getitem__(self, index): - """Fetch the item at position i.""" - if isinstance(index, types.SliceType): - # fetching a slice returns an OrderedDict - return self._main[index].items() - key = self._main._sequence[index] - return (key, self._main[key]) - - def __setitem__(self, index, item): - """Set item at position i to item.""" - if isinstance(index, types.SliceType): - # NOTE: item must be an iterable (list of tuples) - self._main[index] = OrderedDict(item) - else: - # FIXME: Does this raise a sensible error? - orig = self._main.keys[index] - key, value = item - if self._main.strict and key in self and (key != orig): - raise ValueError('slice assignment must be from ' - 'unique keys') - # delete the current one - del self._main[self._main._sequence[index]] - self._main.insert(index, key, value) - - def __delitem__(self, i): - """Delete the item at position i.""" - key = self._main._sequence[i] - if isinstance(i, types.SliceType): - for k in key: - # FIXME: efficiency? - del self._main[k] - else: - del self._main[key] - - ### following methods pinched from UserList and adapted ### - def __repr__(self): - return repr(self._main.items()) - - # FIXME: do we need to check if we are comparing with another ``Items`` - # object? (like the __cast method of UserList) - def __lt__(self, other): - return self._main.items() < other - - def __le__(self, other): - return self._main.items() <= other - - def __eq__(self, other): - return self._main.items() == other - - def __ne__(self, other): - return self._main.items() != other - - def __gt__(self, other): - return self._main.items() > other - - def __ge__(self, other): - return self._main.items() >= other - - def __cmp__(self, other): - return cmp(self._main.items(), other) - - def __contains__(self, item): - return item in self._main.items() - - def __len__(self): - return len(self._main._sequence) # easier :-) - - def __iter__(self): - return self._main.iteritems() - - def count(self, item): - return self._main.items().count(item) - - def index(self, item, *args): - return self._main.items().index(item, *args) - - def reverse(self): - self._main.reverse() - - def sort(self, *args, **kwds): - self._main.sort(*args, **kwds) - - def __mul__(self, n): - return self._main.items() * n - __rmul__ = __mul__ - - def __add__(self, other): - return self._main.items() + other - - def __radd__(self, other): - return other + self._main.items() - - def append(self, item): - """Add an item to the end.""" - # FIXME: this is only append if the key isn't already present - key, value = item - self._main[key] = value - - def insert(self, i, item): - key, value = item - self._main.insert(i, key, value) - - def pop(self, i=-1): - key = self._main._sequence[i] - return (key, self._main.pop(key)) - - def remove(self, item): - key, value = item - try: - assert value == self._main[key] - except (KeyError, AssertionError): - raise ValueError('ValueError: list.remove(x): x not in list') - else: - del self._main[key] - - def extend(self, other): - # FIXME: is only a true extend if none of the keys already present - for item in other: - key, value = item - self._main[key] = value - - def __iadd__(self, other): - self.extend(other) - - ## following methods not implemented for items ## - - def __imul__(self, n): - raise TypeError('Can\'t multiply items in place') - - -class Values(object): - - """ - Custom object for accessing the values of an OrderedDict. - - Can be called like the normal ``OrderedDict.values`` method, but also - supports indexing and sequence methods. - """ - - def __init__(self, main): - self._main = main - - def __call__(self): - """Pretend to be the values method.""" - return self._main._values() - - def __getitem__(self, index): - """Fetch the value at position i.""" - if isinstance(index, types.SliceType): - return [self._main[key] for key in self._main._sequence[index]] - else: - return self._main[self._main._sequence[index]] - - def __setitem__(self, index, value): - """ - Set the value at position i to value. - - You can only do slice assignment to values if you supply a sequence of - equal length to the slice you are replacing. - """ - if isinstance(index, types.SliceType): - keys = self._main._sequence[index] - if len(keys) != len(value): - raise ValueError('attempt to assign sequence of size %s ' - 'to slice of size %s' % (len(value), len(keys))) - # FIXME: efficiency? Would be better to calculate the indexes - # directly from the slice object - # NOTE: the new keys can collide with existing keys (or even - # contain duplicates) - these will overwrite - for key, val in zip(keys, value): - self._main[key] = val - else: - self._main[self._main._sequence[index]] = value - - ### following methods pinched from UserList and adapted ### - def __repr__(self): - return repr(self._main.values()) - - # FIXME: do we need to check if we are comparing with another ``Values`` - # object? (like the __cast method of UserList) - def __lt__(self, other): - return self._main.values() < other - - def __le__(self, other): - return self._main.values() <= other - - def __eq__(self, other): - return self._main.values() == other - - def __ne__(self, other): - return self._main.values() != other - - def __gt__(self, other): - return self._main.values() > other - - def __ge__(self, other): - return self._main.values() >= other - - def __cmp__(self, other): - return cmp(self._main.values(), other) - - def __contains__(self, item): - return item in self._main.values() - - def __len__(self): - return len(self._main._sequence) # easier :-) - - def __iter__(self): - return self._main.itervalues() - - def count(self, item): - return self._main.values().count(item) - - def index(self, item, *args): - return self._main.values().index(item, *args) - - def reverse(self): - """Reverse the values""" - vals = self._main.values() - vals.reverse() - # FIXME: efficiency - self[:] = vals - - def sort(self, *args, **kwds): - """Sort the values.""" - vals = self._main.values() - vals.sort(*args, **kwds) - self[:] = vals - - def __mul__(self, n): - return self._main.values() * n - __rmul__ = __mul__ - - def __add__(self, other): - return self._main.values() + other - - def __radd__(self, other): - return other + self._main.values() - - ## following methods not implemented for values ## - def __delitem__(self, i): - raise TypeError('Can\'t delete items from values') - - def __iadd__(self, other): - raise TypeError('Can\'t add in place to values') - - def __imul__(self, n): - raise TypeError('Can\'t multiply values in place') - - def append(self, item): - raise TypeError('Can\'t append items to values') - - def insert(self, i, item): - raise TypeError('Can\'t insert items into values') - - def pop(self, i=-1): - raise TypeError('Can\'t pop items from values') - - def remove(self, item): - raise TypeError('Can\'t remove items from values') - - def extend(self, other): - raise TypeError('Can\'t extend values') - - -class SequenceOrderedDict(OrderedDict): - - """ - Experimental version of OrderedDict that has a custom object for ``keys``, - ``values``, and ``items``. - - These are callable sequence objects that work as methods, or can be - manipulated directly as sequences. - - Test for ``keys``, ``items`` and ``values``. - - >>> d = SequenceOrderedDict(((1, 2), (2, 3), (3, 4))) - >>> d - SequenceOrderedDict([(1, 2), (2, 3), (3, 4)]) - >>> d.keys - [1, 2, 3] - >>> d.keys() - [1, 2, 3] - >>> d.setkeys((3, 2, 1)) - >>> d - SequenceOrderedDict([(3, 4), (2, 3), (1, 2)]) - >>> d.setkeys((1, 2, 3)) - >>> d.keys[0] - 1 - >>> d.keys[:] - [1, 2, 3] - >>> d.keys[-1] - 3 - >>> d.keys[-2] - 2 - >>> d.keys[0:2] = [2, 1] - >>> d - SequenceOrderedDict([(2, 3), (1, 2), (3, 4)]) - >>> d.keys.reverse() - >>> d.keys - [3, 1, 2] - >>> d.keys = [1, 2, 3] - >>> d - SequenceOrderedDict([(1, 2), (2, 3), (3, 4)]) - >>> d.keys = [3, 1, 2] - >>> d - SequenceOrderedDict([(3, 4), (1, 2), (2, 3)]) - >>> a = SequenceOrderedDict() - >>> b = SequenceOrderedDict() - >>> a.keys == b.keys - 1 - >>> a['a'] = 3 - >>> a.keys == b.keys - 0 - >>> b['a'] = 3 - >>> a.keys == b.keys - 1 - >>> b['b'] = 3 - >>> a.keys == b.keys - 0 - >>> a.keys > b.keys - 0 - >>> a.keys < b.keys - 1 - >>> 'a' in a.keys - 1 - >>> len(b.keys) - 2 - >>> 'c' in d.keys - 0 - >>> 1 in d.keys - 1 - >>> [v for v in d.keys] - [3, 1, 2] - >>> d.keys.sort() - >>> d.keys - [1, 2, 3] - >>> d = SequenceOrderedDict(((1, 2), (2, 3), (3, 4)), strict=True) - >>> d.keys[::-1] = [1, 2, 3] - >>> d - SequenceOrderedDict([(3, 4), (2, 3), (1, 2)]) - >>> d.keys[:2] - [3, 2] - >>> d.keys[:2] = [1, 3] - Traceback (most recent call last): - KeyError: 'Keylist is not the same as current keylist.' - - >>> d = SequenceOrderedDict(((1, 2), (2, 3), (3, 4))) - >>> d - SequenceOrderedDict([(1, 2), (2, 3), (3, 4)]) - >>> d.values - [2, 3, 4] - >>> d.values() - [2, 3, 4] - >>> d.setvalues((4, 3, 2)) - >>> d - SequenceOrderedDict([(1, 4), (2, 3), (3, 2)]) - >>> d.values[::-1] - [2, 3, 4] - >>> d.values[0] - 4 - >>> d.values[-2] - 3 - >>> del d.values[0] - Traceback (most recent call last): - TypeError: Can't delete items from values - >>> d.values[::2] = [2, 4] - >>> d - SequenceOrderedDict([(1, 2), (2, 3), (3, 4)]) - >>> 7 in d.values - 0 - >>> len(d.values) - 3 - >>> [val for val in d.values] - [2, 3, 4] - >>> d.values[-1] = 2 - >>> d.values.count(2) - 2 - >>> d.values.index(2) - 0 - >>> d.values[-1] = 7 - >>> d.values - [2, 3, 7] - >>> d.values.reverse() - >>> d.values - [7, 3, 2] - >>> d.values.sort() - >>> d.values - [2, 3, 7] - >>> d.values.append('anything') - Traceback (most recent call last): - TypeError: Can't append items to values - >>> d.values = (1, 2, 3) - >>> d - SequenceOrderedDict([(1, 1), (2, 2), (3, 3)]) - - >>> d = SequenceOrderedDict(((1, 2), (2, 3), (3, 4))) - >>> d - SequenceOrderedDict([(1, 2), (2, 3), (3, 4)]) - >>> d.items() - [(1, 2), (2, 3), (3, 4)] - >>> d.setitems([(3, 4), (2 ,3), (1, 2)]) - >>> d - SequenceOrderedDict([(3, 4), (2, 3), (1, 2)]) - >>> d.items[0] - (3, 4) - >>> d.items[:-1] - [(3, 4), (2, 3)] - >>> d.items[1] = (6, 3) - >>> d.items - [(3, 4), (6, 3), (1, 2)] - >>> d.items[1:2] = [(9, 9)] - >>> d - SequenceOrderedDict([(3, 4), (9, 9), (1, 2)]) - >>> del d.items[1:2] - >>> d - SequenceOrderedDict([(3, 4), (1, 2)]) - >>> (3, 4) in d.items - 1 - >>> (4, 3) in d.items - 0 - >>> len(d.items) - 2 - >>> [v for v in d.items] - [(3, 4), (1, 2)] - >>> d.items.count((3, 4)) - 1 - >>> d.items.index((1, 2)) - 1 - >>> d.items.index((2, 1)) - Traceback (most recent call last): - ValueError: list.index(x): x not in list - >>> d.items.reverse() - >>> d.items - [(1, 2), (3, 4)] - >>> d.items.reverse() - >>> d.items.sort() - >>> d.items - [(1, 2), (3, 4)] - >>> d.items.append((5, 6)) - >>> d.items - [(1, 2), (3, 4), (5, 6)] - >>> d.items.insert(0, (0, 0)) - >>> d.items - [(0, 0), (1, 2), (3, 4), (5, 6)] - >>> d.items.insert(-1, (7, 8)) - >>> d.items - [(0, 0), (1, 2), (3, 4), (7, 8), (5, 6)] - >>> d.items.pop() - (5, 6) - >>> d.items - [(0, 0), (1, 2), (3, 4), (7, 8)] - >>> d.items.remove((1, 2)) - >>> d.items - [(0, 0), (3, 4), (7, 8)] - >>> d.items.extend([(1, 2), (5, 6)]) - >>> d.items - [(0, 0), (3, 4), (7, 8), (1, 2), (5, 6)] - """ - - def __init__(self, init_val=(), strict=True): - OrderedDict.__init__(self, init_val, strict=strict) - self._keys = self.keys - self._values = self.values - self._items = self.items - self.keys = Keys(self) - self.values = Values(self) - self.items = Items(self) - self._att_dict = { - 'keys': self.setkeys, - 'items': self.setitems, - 'values': self.setvalues, - } - - def __setattr__(self, name, value): - """Protect keys, items, and values.""" - if '_att_dict' not in self.__dict__: - object.__setattr__(self, name, value) - else: - try: - fun = self._att_dict[name] - except KeyError: - OrderedDict.__setattr__(self, name, value) - else: - fun(value) - -if __name__ == '__main__': - if INTP_VER < (2, 3): - raise RuntimeError("Tests require Python v.2.3 or later") - # turn off warnings for tests - warnings.filterwarnings('ignore') - # run the code tests in doctest format - import doctest - m = sys.modules.get('__main__') - globs = m.__dict__.copy() - globs.update({ - 'INTP_VER': INTP_VER, - }) - doctest.testmod(m, globs=globs) +try: + from collections import OrderedDict +except ImportError: + try: + from ordereddict import OrderedDict + except ImportError: + import warnings + warnings.warn("git-python needs the ordereddict module installed in python below 2.6 and below.") + warnings.warn("Using standard dictionary as substitute, and cause reordering when writing git config") + OrderedDict = dict diff --git a/git/refs/tag.py b/git/refs/tag.py index 50d2b2af..6509c891 100644 --- a/git/refs/tag.py +++ b/git/refs/tag.py @@ -13,9 +13,9 @@ class TagReference(Reference): information in a tag object:: tagref = TagReference.list_items(repo)[0] - print tagref.commit.message + print(tagref.commit.message) if tagref.tag is not None: - print tagref.tag.message""" + print(tagref.tag.message)""" __slots__ = tuple() _common_path_default = "refs/tags" diff --git a/git/test/lib/asserts.py b/git/test/lib/asserts.py index 98751d4d..0f2fd99a 100644 --- a/git/test/lib/asserts.py +++ b/git/test/lib/asserts.py @@ -27,6 +27,7 @@ from mock import ( patch ) + def assert_instance_of(expected, actual, msg=None): """Verify that object is an instance of expected """ assert isinstance(actual, expected), msg diff --git a/git/test/lib/helper.py b/git/test/lib/helper.py index a18f22ef..9c935ce0 100644 --- a/git/test/lib/helper.py +++ b/git/test/lib/helper.py @@ -3,7 +3,7 @@ # # This module is part of GitPython and is released under # the BSD License: http://www.opensource.org/licenses/bsd-license.php - +from __future__ import print_function import os import sys from git import Repo, Remote, GitCommandError, Git @@ -111,7 +111,7 @@ def with_rw_repo(working_tree_ref, bare=False): try: return func(self, rw_repo) except: - print >> sys.stderr, "Keeping repo after failure: %s" % repo_dir + print("Keeping repo after failure: %s" % repo_dir, file=sys.stderr) repo_dir = None raise finally: diff --git a/git/test/performance/test_commit.py b/git/test/performance/test_commit.py index 257442ea..a890c833 100644 --- a/git/test/performance/test_commit.py +++ b/git/test/performance/test_commit.py @@ -3,7 +3,7 @@ # # This module is part of GitPython and is released under # the BSD License: http://www.opensource.org/licenses/bsd-license.php - +from __future__ import print_function from .lib import TestBigRepoRW from git import Commit from gitdb import IStream @@ -46,8 +46,8 @@ class TestPerformance(TestBigRepoRW): # END for each object # END for each commit elapsed_time = time() - st - print >> sys.stderr, "Traversed %i Trees and a total of %i unchached objects in %s [s] ( %f objs/s )" % ( - nc, no, elapsed_time, no / elapsed_time) + print("Traversed %i Trees and a total of %i unchached objects in %s [s] ( %f objs/s )" + % (nc, no, elapsed_time, no / elapsed_time), file=sys.stderr) def test_commit_traversal(self): # bound to cat-file parsing performance @@ -58,7 +58,8 @@ class TestPerformance(TestBigRepoRW): self._query_commit_info(c) # END for each traversed commit elapsed_time = time() - st - print >> sys.stderr, "Traversed %i Commits in %s [s] ( %f commits/s )" % (nc, elapsed_time, nc / elapsed_time) + print("Traversed %i Commits in %s [s] ( %f commits/s )" + % (nc, elapsed_time, nc / elapsed_time), file=sys.stderr) def test_commit_iteration(self): # bound to stream parsing performance @@ -69,7 +70,8 @@ class TestPerformance(TestBigRepoRW): self._query_commit_info(c) # END for each traversed commit elapsed_time = time() - st - print >> sys.stderr, "Iterated %i Commits in %s [s] ( %f commits/s )" % (nc, elapsed_time, nc / elapsed_time) + print("Iterated %i Commits in %s [s] ( %f commits/s )" + % (nc, elapsed_time, nc / elapsed_time), file=sys.stderr) def test_commit_serialization(self): assert_commit_serialization(self.gitrwrepo, self.gitrwrepo.head, True) @@ -97,5 +99,5 @@ class TestPerformance(TestBigRepoRW): # END commit creation elapsed = time() - st - print >> sys.stderr, "Serialized %i commits to loose objects in %f s ( %f commits / s )" % ( - nc, elapsed, nc / elapsed) + print("Serialized %i commits to loose objects in %f s ( %f commits / s )" + % (nc, elapsed, nc / elapsed), file=sys.stderr) diff --git a/git/test/performance/test_odb.py b/git/test/performance/test_odb.py index 779adb00..b14e6db0 100644 --- a/git/test/performance/test_odb.py +++ b/git/test/performance/test_odb.py @@ -1,5 +1,5 @@ """Performance tests for object store""" - +from __future__ import print_function from time import time import sys @@ -20,8 +20,8 @@ class TestObjDBPerformance(TestBigRepoR): nc = len(commits) elapsed = time() - st - print >> sys.stderr, "%s: Retrieved %i commits from ObjectStore in %g s ( %f commits / s )" % ( - type(repo.odb), nc, elapsed, nc / elapsed) + print("%s: Retrieved %i commits from ObjectStore in %g s ( %f commits / s )" + % (type(repo.odb), nc, elapsed, nc / elapsed), file=sys.stderr) results[0].append(elapsed) # GET TREES @@ -42,8 +42,8 @@ class TestObjDBPerformance(TestBigRepoR): # END for each commit elapsed = time() - st - print >> sys.stderr, "%s: Retrieved %i objects from %i commits in %g s ( %f objects / s )" % ( - type(repo.odb), nt, len(commits), elapsed, nt / elapsed) + print("%s: Retrieved %i objects from %i commits in %g s ( %f objects / s )" + % (type(repo.odb), nt, len(commits), elapsed, nt / elapsed), file=sys.stderr) results[1].append(elapsed) # GET BLOBS @@ -63,11 +63,11 @@ class TestObjDBPerformance(TestBigRepoR): msg = "%s: Retrieved %i blob (%i KiB) and their data in %g s ( %f blobs / s, %f KiB / s )"\ % (type(repo.odb), nb, data_bytes / 1000, elapsed, nb / elapsed, (data_bytes / 1000) / elapsed) + print(msg, file=sys.stderr) results[2].append(elapsed) - print >> sys.stderr, msg # END for each repo type # final results for test_name, a, b in results: - print >> sys.stderr, "%s: %f s vs %f s, pure is %f times slower" % (test_name, a, b, b / a) + print("%s: %f s vs %f s, pure is %f times slower" % (test_name, a, b, b / a), file=sys.stderr) # END for each result diff --git a/git/test/performance/test_streams.py b/git/test/performance/test_streams.py index 48527f0e..ff664c10 100644 --- a/git/test/performance/test_streams.py +++ b/git/test/performance/test_streams.py @@ -1,4 +1,6 @@ """Performance data streaming performance""" +from __future__ import print_function + from time import time import os import sys @@ -19,6 +21,7 @@ from gitdb import ( IStream ) + class TestObjDBPerformance(TestBigRepoR): large_data_size_bytes = 1000 * 1000 * 10 # some MiB should do it @@ -32,11 +35,11 @@ class TestObjDBPerformance(TestBigRepoR): for randomize in range(2): desc = (randomize and 'random ') or '' - print >> sys.stderr, "Creating %s data ..." % desc + print("Creating %s data ..." % desc, file=sys.stderr) st = time() size, stream = make_memory_file(self.large_data_size_bytes, randomize) elapsed = time() - st - print >> sys.stderr, "Done (in %f s)" % elapsed + print("Done (in %f s)" % elapsed, file=sys.stderr) # writing - due to the compression it will seem faster than it is st = time() @@ -49,7 +52,7 @@ class TestObjDBPerformance(TestBigRepoR): size_kib = size / 1000 msg = "Added %i KiB (filesize = %i KiB) of %s data to loose odb in %f s ( %f Write KiB / s)" msg %= (size_kib, fsize_kib, desc, elapsed_add, size_kib / elapsed_add) - print >> sys.stderr, msg + print(msg, file=sys.stderr) # reading all at once st = time() @@ -61,7 +64,7 @@ class TestObjDBPerformance(TestBigRepoR): assert shadata == stream.getvalue() msg = "Read %i KiB of %s data at once from loose odb in %f s ( %f Read KiB / s)" msg %= (size_kib, desc, elapsed_readall, size_kib / elapsed_readall) - print >> sys.stderr, msg + print(msg, file=sys.stderr) # reading in chunks of 1 MiB cs = 512 * 1000 @@ -80,8 +83,8 @@ class TestObjDBPerformance(TestBigRepoR): assert ''.join(chunks) == stream.getvalue() cs_kib = cs / 1000 - print >> sys.stderr, "Read %i KiB of %s data in %i KiB chunks from loose odb in %f s ( %f Read KiB / s)" % ( - size_kib, desc, cs_kib, elapsed_readchunks, size_kib / elapsed_readchunks) + print("Read %i KiB of %s data in %i KiB chunks from loose odb in %f s ( %f Read KiB / s)" + % (size_kib, desc, cs_kib, elapsed_readchunks, size_kib / elapsed_readchunks), file=sys.stderr) # del db file so git has something to do os.remove(db_file) @@ -106,22 +109,22 @@ class TestObjDBPerformance(TestBigRepoR): fsize_kib = os.path.getsize(db_file) / 1000 msg = "Added %i KiB (filesize = %i KiB) of %s data to using git-hash-object in %f s ( %f Write KiB / s)" msg %= (size_kib, fsize_kib, desc, gelapsed_add, size_kib / gelapsed_add) - print >> sys.stderr, msg + print(msg, file=sys.stderr) # compare ... - print >> sys.stderr, "Git-Python is %f %% faster than git when adding big %s files" % ( - 100.0 - (elapsed_add / gelapsed_add) * 100, desc) + print("Git-Python is %f %% faster than git when adding big %s files" + % (100.0 - (elapsed_add / gelapsed_add) * 100, desc), file=sys.stderr) # read all st = time() s, t, size, data = rwrepo.git.get_object_data(gitsha) gelapsed_readall = time() - st - print >> sys.stderr, "Read %i KiB of %s data at once using git-cat-file in %f s ( %f Read KiB / s)" % ( - size_kib, desc, gelapsed_readall, size_kib / gelapsed_readall) + print("Read %i KiB of %s data at once using git-cat-file in %f s ( %f Read KiB / s)" + % (size_kib, desc, gelapsed_readall, size_kib / gelapsed_readall), file=sys.stderr) # compare - print >> sys.stderr, "Git-Python is %f %% faster than git when reading big %sfiles" % ( - 100.0 - (elapsed_readall / gelapsed_readall) * 100, desc) + print("Git-Python is %f %% faster than git when reading big %sfiles" + % (100.0 - (elapsed_readall / gelapsed_readall) * 100, desc), file=sys.stderr) # read chunks st = time() @@ -134,9 +137,9 @@ class TestObjDBPerformance(TestBigRepoR): gelapsed_readchunks = time() - st msg = "Read %i KiB of %s data in %i KiB chunks from git-cat-file in %f s ( %f Read KiB / s)" msg %= (size_kib, desc, cs_kib, gelapsed_readchunks, size_kib / gelapsed_readchunks) - print >> sys.stderr, msg + print(msg, file=sys.stderr) # compare - print >> sys.stderr, "Git-Python is %f %% faster than git when reading big %s files in chunks" % ( - 100.0 - (elapsed_readchunks / gelapsed_readchunks) * 100, desc) + print ("Git-Python is %f %% faster than git when reading big %s files in chunks" + % (100.0 - (elapsed_readchunks / gelapsed_readchunks) * 100, desc), file=sys.stderr) # END for each randomization factor diff --git a/git/test/performance/test_utils.py b/git/test/performance/test_utils.py index 0bd47098..af8e8047 100644 --- a/git/test/performance/test_utils.py +++ b/git/test/performance/test_utils.py @@ -1,4 +1,5 @@ """Performance of utilities""" +from __future__ import print_function from time import time import sys @@ -43,8 +44,8 @@ class TestUtilPerformance(TestBigRepoR): cli.attr # END for each access elapsed = time() - st - print >> sys.stderr, "Accessed %s.attr %i times in %s s ( %f acc / s)" % ( - cls.__name__, ni, elapsed, ni / elapsed) + print("Accessed %s.attr %i times in %s s ( %f acc / s)" + % (cls.__name__, ni, elapsed, ni / elapsed), file=sys.stderr) # END for each class type # check num of sequence-acceses @@ -59,8 +60,8 @@ class TestUtilPerformance(TestBigRepoR): # END for elapsed = time() - st na = ni * 3 - print >> sys.stderr, "Accessed %s[x] %i times in %s s ( %f acc / s)" % ( - cls.__name__, na, elapsed, na / elapsed) + print("Accessed %s[x] %i times in %s s ( %f acc / s)" + % (cls.__name__, na, elapsed, na / elapsed), file=sys.stderr) # END for each sequence def test_instantiation(self): @@ -85,8 +86,8 @@ class TestUtilPerformance(TestBigRepoR): # END handle empty cls # END for each item elapsed = time() - st - print >> sys.stderr, "Created %i %ss of size %i in %f s ( %f inst / s)" % ( - ni, cls.__name__, mni, elapsed, ni / elapsed) + print("Created %i %ss of size %i in %f s ( %f inst / s)" + % (ni, cls.__name__, mni, elapsed, ni / elapsed), file=sys.stderr) # END for each type # END for each item count @@ -96,14 +97,16 @@ class TestUtilPerformance(TestBigRepoR): (1, 2, 3, 4) # END for each item elapsed = time() - st - print >> sys.stderr, "Created %i tuples (1,2,3,4) in %f s ( %f tuples / s)" % (ni, elapsed, ni / elapsed) + print("Created %i tuples (1,2,3,4) in %f s ( %f tuples / s)" + % (ni, elapsed, ni / elapsed), file=sys.stderr) st = time() for i in xrange(ni): tuple((1, 2, 3, 4)) # END for each item elapsed = time() - st - print >> sys.stderr, "Created %i tuples tuple((1,2,3,4)) in %f s ( %f tuples / s)" % (ni, elapsed, ni / elapsed) + print("Created %i tuples tuple((1,2,3,4)) in %f s ( %f tuples / s)" + % (ni, elapsed, ni / elapsed), file=sys.stderr) def test_unpacking_vs_indexing(self): ni = 1000000 @@ -116,24 +119,24 @@ class TestUtilPerformance(TestBigRepoR): one, two, three, four = sequence # END for eac iteration elapsed = time() - st - print >> sys.stderr, "Unpacked %i %ss of size %i in %f s ( %f acc / s)" % ( - ni, type(sequence).__name__, len(sequence), elapsed, ni / elapsed) + print("Unpacked %i %ss of size %i in %f s ( %f acc / s)" + % (ni, type(sequence).__name__, len(sequence), elapsed, ni / elapsed), file=sys.stderr) st = time() for i in xrange(ni): one, two, three, four = sequence[0], sequence[1], sequence[2], sequence[3] # END for eac iteration elapsed = time() - st - print >> sys.stderr, "Unpacked %i %ss of size %i individually in %f s ( %f acc / s)" % ( - ni, type(sequence).__name__, len(sequence), elapsed, ni / elapsed) + print("Unpacked %i %ss of size %i individually in %f s ( %f acc / s)" + % (ni, type(sequence).__name__, len(sequence), elapsed, ni / elapsed), file=sys.stderr) st = time() for i in xrange(ni): one, two = sequence[0], sequence[1] # END for eac iteration elapsed = time() - st - print >> sys.stderr, "Unpacked %i %ss of size %i individually (2 of 4) in %f s ( %f acc / s)" % ( - ni, type(sequence).__name__, len(sequence), elapsed, ni / elapsed) + print("Unpacked %i %ss of size %i individually (2 of 4) in %f s ( %f acc / s)" + % (ni, type(sequence).__name__, len(sequence), elapsed, ni / elapsed), file=sys.stderr) # END for each sequence def test_large_list_vs_iteration(self): @@ -150,14 +153,16 @@ class TestUtilPerformance(TestBigRepoR): i # END for each item elapsed = time() - st - print >> sys.stderr, "Iterated %i items from list in %f s ( %f acc / s)" % (ni, elapsed, ni / elapsed) + print("Iterated %i items from list in %f s ( %f acc / s)" + % (ni, elapsed, ni / elapsed), file=sys.stderr) st = time() for i in slow_iter(ni): i # END for each item elapsed = time() - st - print >> sys.stderr, "Iterated %i items from iterator in %f s ( %f acc / s)" % (ni, elapsed, ni / elapsed) + print("Iterated %i items from iterator in %f s ( %f acc / s)" + % (ni, elapsed, ni / elapsed), file=sys.stderr) # END for each number of iterations def test_type_vs_inst_class(self): @@ -173,12 +178,13 @@ class TestUtilPerformance(TestBigRepoR): inst.__class__() # END for each item elapsed = time() - st - print >> sys.stderr, "Created %i items using inst.__class__ in %f s ( %f items / s)" % ( - ni, elapsed, ni / elapsed) + print("Created %i items using inst.__class__ in %f s ( %f items / s)" + % (ni, elapsed, ni / elapsed), file=sys.stderr) st = time() for i in xrange(ni): type(inst)() # END for each item elapsed = time() - st - print >> sys.stderr, "Created %i items using type(inst)() in %f s ( %f items / s)" % (ni, elapsed, ni / elapsed) + print("Created %i items using type(inst)() in %f s ( %f items / s)" + % (ni, elapsed, ni / elapsed), file=sys.stderr) diff --git a/git/test/test_actor.py b/git/test/test_actor.py index d79673f8..9ba0aeba 100644 --- a/git/test/test_actor.py +++ b/git/test/test_actor.py @@ -7,6 +7,7 @@ from git.test.lib import assert_equal from git import Actor + class TestActor(object): def test_from_string_should_separate_name_and_email(self): diff --git a/git/test/test_commit.py b/git/test/test_commit.py index 961ae44f..bfad6fd6 100644 --- a/git/test/test_commit.py +++ b/git/test/test_commit.py @@ -4,6 +4,7 @@ # # This module is part of GitPython and is released under # the BSD License: http://www.opensource.org/licenses/bsd-license.php +from __future__ import print_function from git.test.lib import ( TestBase, @@ -72,8 +73,8 @@ def assert_commit_serialization(rwrepo, commit_id, print_performance_info=False) elapsed = time.time() - st if print_performance_info: - print >> sys.stderr, "Serialized %i and deserialized %i commits in %f s ( (%f, %f) commits / s" % ( - ns, nds, elapsed, ns / elapsed, nds / elapsed) + print("Serialized %i and deserialized %i commits in %f s ( (%f, %f) commits / s" + % (ns, nds, elapsed, ns / elapsed, nds / elapsed), file=sys.stderr) # END handle performance info diff --git a/git/test/test_config.py b/git/test/test_config.py index f470b143..d1c8e72f 100644 --- a/git/test/test_config.py +++ b/git/test/test_config.py @@ -64,7 +64,6 @@ class TestBase(TestCase): file_obj.seek(0) r_config = GitConfigParser(file_obj, read_only=True) - # print file_obj.getvalue() assert r_config.has_section(sname) assert r_config.has_option(sname, oname) assert r_config.get(sname, oname) == val diff --git a/git/test/test_diff.py b/git/test/test_diff.py index adac5ed4..3453f6a8 100644 --- a/git/test/test_diff.py +++ b/git/test/test_diff.py @@ -18,6 +18,7 @@ from git import ( DiffIndex ) + class TestDiff(TestBase): def _assert_diff_format(self, diffs): diff --git a/git/test/test_git.py b/git/test/test_git.py index 9c8bb490..553f8d1b 100644 --- a/git/test/test_git.py +++ b/git/test/test_git.py @@ -50,7 +50,9 @@ class TestGit(TestBase): assert_equal(["--max-count"], self.git.transform_kwargs(**{'max_count': True})) assert_equal(["--max-count=5"], self.git.transform_kwargs(**{'max_count': 5})) - assert_equal(["-s", "-t"], self.git.transform_kwargs(**{'s': True, 't': True})) + # order is undefined + res = self.git.transform_kwargs(**{'s': True, 't': True}) + assert ['-s', '-t'] == res or ['-t', '-s'] == res def test_it_executes_git_to_shell_and_returns_result(self): assert_match('^git version [\d\.]{2}.*$', self.git.execute(["git", "version"])) diff --git a/git/test/test_index.py b/git/test/test_index.py index 2eef4b5d..15fff8d4 100644 --- a/git/test/test_index.py +++ b/git/test/test_index.py @@ -19,7 +19,6 @@ from git import ( Diff, GitCommandError, CheckoutError, - ) from gitdb.util import hex_to_bin import os |