Initial work on a fastexport module.
[jelmer/dulwich-libgit2.git] / dulwich / misc.py
1 # misc.py -- For dealing with python2.4 oddness
2 # Copyright (C) 2008 Canonical Ltd.
3
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; version 2
7 # of the License or (at your option) a later version.
8
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 # MA  02110-1301, USA.
18 """Misc utilities to work with python <2.6.
19
20 These utilities can all be deleted when dulwich decides it wants to stop
21 support for python <2.6.
22 """
23 try:
24     import hashlib
25 except ImportError:
26     import sha
27
28 try:
29     from urlparse import parse_qs
30 except ImportError:
31     from cgi import parse_qs
32
33 import struct
34
35
36 class defaultdict(dict):
37     """A python 2.4 equivalent of collections.defaultdict."""
38
39     def __init__(self, default_factory=None, *a, **kw):
40         if (default_factory is not None and
41             not hasattr(default_factory, '__call__')):
42             raise TypeError('first argument must be callable')
43         dict.__init__(self, *a, **kw)
44         self.default_factory = default_factory
45
46     def __getitem__(self, key):
47         try:
48             return dict.__getitem__(self, key)
49         except KeyError:
50             return self.__missing__(key)
51
52     def __missing__(self, key):
53         if self.default_factory is None:
54             raise KeyError(key)
55         self[key] = value = self.default_factory()
56         return value
57
58     def __reduce__(self):
59         if self.default_factory is None:
60             args = tuple()
61         else:
62             args = self.default_factory,
63         return type(self), args, None, None, self.items()
64
65     def copy(self):
66         return self.__copy__()
67
68     def __copy__(self):
69         return type(self)(self.default_factory, self)
70
71     def __deepcopy__(self, memo):
72         import copy
73         return type(self)(self.default_factory,
74                           copy.deepcopy(self.items()))
75     def __repr__(self):
76         return 'defaultdict(%s, %s)' % (self.default_factory,
77                                         dict.__repr__(self))
78
79
80 def make_sha(source=''):
81     """A python2.4 workaround for the sha/hashlib module fiasco."""
82     try:
83         return hashlib.sha1(source)
84     except NameError:
85         sha1 = sha.sha(source)
86         return sha1
87
88
89 def unpack_from(fmt, buf, offset=0):
90     """A python2.4 workaround for struct missing unpack_from."""
91     try:
92         return struct.unpack_from(fmt, buf, offset)
93     except AttributeError:
94         b = buf[offset:offset+struct.calcsize(fmt)]
95         return struct.unpack(fmt, b)