Merge support for lazy loading packs.
[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
19 """Misc utilities to work with python <2.6.
20
21 These utilities can all be deleted when dulwich decides it wants to stop
22 support for python <2.6.
23 """
24 try:
25     import hashlib
26 except ImportError:
27     import sha
28
29 try:
30     from urlparse import parse_qs
31 except ImportError:
32     from cgi import parse_qs
33
34 try:
35     from os import SEEK_END
36 except ImportError:
37     SEEK_END = 2
38
39 import struct
40
41
42 class defaultdict(dict):
43     """A python 2.4 equivalent of collections.defaultdict."""
44
45     def __init__(self, default_factory=None, *a, **kw):
46         if (default_factory is not None and
47             not hasattr(default_factory, '__call__')):
48             raise TypeError('first argument must be callable')
49         dict.__init__(self, *a, **kw)
50         self.default_factory = default_factory
51
52     def __getitem__(self, key):
53         try:
54             return dict.__getitem__(self, key)
55         except KeyError:
56             return self.__missing__(key)
57
58     def __missing__(self, key):
59         if self.default_factory is None:
60             raise KeyError(key)
61         self[key] = value = self.default_factory()
62         return value
63
64     def __reduce__(self):
65         if self.default_factory is None:
66             args = tuple()
67         else:
68             args = self.default_factory,
69         return type(self), args, None, None, self.items()
70
71     def copy(self):
72         return self.__copy__()
73
74     def __copy__(self):
75         return type(self)(self.default_factory, self)
76
77     def __deepcopy__(self, memo):
78         import copy
79         return type(self)(self.default_factory,
80                           copy.deepcopy(self.items()))
81     def __repr__(self):
82         return 'defaultdict(%s, %s)' % (self.default_factory,
83                                         dict.__repr__(self))
84
85
86 def make_sha(source=''):
87     """A python2.4 workaround for the sha/hashlib module fiasco."""
88     try:
89         return hashlib.sha1(source)
90     except NameError:
91         sha1 = sha.sha(source)
92         return sha1
93
94
95 def unpack_from(fmt, buf, offset=0):
96     """A python2.4 workaround for struct missing unpack_from."""
97     try:
98         return struct.unpack_from(fmt, buf, offset)
99     except AttributeError:
100         b = buf[offset:offset+struct.calcsize(fmt)]
101         return struct.unpack(fmt, b)