Modified get_mod_info to raise an exception when it is passed a directory.
[translate_toolkit.git] / misc / dictutils.py
blob61b074b78e6d0ad377b776326ab3ddf52f27785a
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
4 """Implements a case-insensitive (on keys) dictionary and order-sensitive dictionary"""
6 # Copyright 2002, 2003 St James Software
7 #
8 # This file is part of translate.
10 # translate is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 2 of the License, or
13 # (at your option) any later version.
15 # translate is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
20 # You should have received a copy of the GNU General Public License
21 # along with translate; if not, write to the Free Software
22 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 def generalupper(str):
25 """this uses the object's upper method - works with string and unicode"""
26 if str is None: return str
27 return str.upper()
29 class cidict(dict):
30 def __init__(self, fromdict = None):
31 """constructs the cidict, optionally using another dict to do so"""
32 if fromdict is not None:
33 self.update(fromdict)
35 def __getitem__(self, key):
36 if type(key) != str and type(key) != unicode:
37 raise TypeError, "cidict can only have str or unicode as key (got %r)" % type(key)
38 for akey in self.iterkeys():
39 if akey.lower() == key.lower():
40 return dict.__getitem__(self, akey)
41 raise IndexError
43 def __setitem__(self, key, value):
44 if type(key) != str and type(key) != unicode:
45 raise TypeError, "cidict can only have str or unicode as key (got %r)" % type(key)
46 for akey in self.iterkeys():
47 if akey.lower() == key.lower():
48 return dict.__setitem__(self, akey, value)
49 return dict.__setitem__(self, key, value)
51 def update(self, updatedict):
52 """D.update(E) -> None. Update D from E: for k in E.keys(): D[k] = E[k]"""
53 for key, value in updatedict.iteritems():
54 self[key] = value
56 def __delitem__(self, key):
57 if type(key) != str and type(key) != unicode:
58 raise TypeError, "cidict can only have str or unicode as key (got %r)" % type(key)
59 for akey in self.iterkeys():
60 if akey.lower() == key.lower():
61 return dict.__delitem__(self, akey)
62 raise IndexError
64 def __contains__(self, key):
65 if type(key) != str and type(key) != unicode:
66 raise TypeError, "cidict can only have str or unicode as key (got %r)" % type(key)
67 for akey in self.iterkeys():
68 if akey.lower() == key.lower():
69 return 1
70 return 0
72 def has_key(self, key):
73 return self.__contains__(key)
75 def get(self, key, default=None):
76 if self.has_key(key):
77 return self[key]
78 else:
79 return default
81 class ordereddict(dict):
82 """a dictionary which remembers its keys in the order in which they were given"""
83 def __init__(self, *args):
84 if len(args) == 0:
85 super(ordereddict, self).__init__()
86 self.order = []
87 elif len(args) > 1:
88 raise TypeError("ordereddict() takes at most 1 argument (%d given)" % len(args))
89 else:
90 initarg = args[0]
91 apply(super(ordereddict, self).__init__, args)
92 if hasattr(initarg, "keys"):
93 self.order = initarg.keys()
94 else:
95 # danger: could have duplicate keys...
96 self.order = []
97 checkduplicates = {}
98 for key, value in initarg:
99 if not key in checkduplicates:
100 self.order.append(key)
101 checkduplicates[key] = None
103 def __setitem__(self, key, value):
104 alreadypresent = key in self
105 result = dict.__setitem__(self, key, value)
106 if not alreadypresent: self.order.append(key)
107 return result
109 def update(self, updatedict):
110 """D.update(E) -> None. Update D from E: for k in E.keys(): D[k] = E[k]"""
111 for key, value in updatedict.iteritems():
112 self[key] = value
114 def __delitem__(self, key):
115 alreadypresent = key in self
116 result = dict.__delitem__(self, key)
117 if alreadypresent: del self.order[self.order.index(key)]
118 return result
120 def copy(self):
121 """D.copy() -> a shallow copy of D"""
122 thecopy = ordereddict(super(ordereddict, self).copy())
123 thecopy.order = self.order[:]
124 return thecopy
126 def items(self):
127 """D.items() -> list of D's (key, value) pairs, as 2-tuples"""
128 return [(key, self[key]) for key in self.order]
130 def iteritems(self):
131 """D.iteritems() -> an iterator over the (key, value) items of D"""
132 for key in self.order:
133 yield (key, self[key])
135 def iterkeys(self):
136 """D.iterkeys() -> an iterator over the keys of D"""
137 for key in self.order:
138 yield key
140 __iter__ = iterkeys
142 def itervalues(self):
143 """D.itervalues() -> an iterator over the values of D"""
144 for key in self.order:
145 yield self[key]
147 def keys(self):
148 """D.keys() -> list of D's keys"""
149 return self.order[:]
151 def popitem(self):
152 """D.popitem() -> (k, v), remove and return some (key, value) pair as a 2-tuple; but raise KeyError if D is empty"""
153 if len(self.order) == 0:
154 raise KeyError("popitem(): ordered dictionary is empty")
155 k = self.order.pop()
156 v = self[k]
157 del self[k]
158 return (k,v)
160 def pop(self, key):
161 """remove entry from dict and internal list"""
162 value = super(ordereddict, self).pop(key)
163 del self.order[self.order.index(key)]
164 return value