odict.py 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897
  1. """odict.py: An Ordered Dictionary object"""
  2. # Copyright (C) 2005 Nicola Larosa, Michael Foord
  3. # E-mail: nico AT tekNico DOT net, fuzzyman AT voidspace DOT org DOT uk
  4. # Copyright (c) 2003-2010, Michael Foord
  5. # E-mail : fuzzyman AT voidspace DOT org DOT uk
  6. #
  7. # Redistribution and use in source and binary forms, with or without
  8. # modification, are permitted provided that the following conditions are
  9. # met:
  10. #
  11. #
  12. # * Redistributions of source code must retain the above copyright
  13. # notice, this list of conditions and the following disclaimer.
  14. #
  15. # * Redistributions in binary form must reproduce the above
  16. # copyright notice, this list of conditions and the following
  17. # disclaimer in the documentation and/or other materials provided
  18. # with the distribution.
  19. #
  20. # * Neither the name of Michael Foord nor the name of Voidspace
  21. # may be used to endorse or promote products derived from this
  22. # software without specific prior written permission.
  23. #
  24. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  25. # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  26. # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  27. # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  28. # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  29. # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  30. # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  31. # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  32. # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  33. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  34. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  35. from __future__ import generators
  36. import sys
  37. import warnings
  38. __docformat__ = "restructuredtext en"
  39. __all__ = ['OrderedDict']
  40. INTP_VER = sys.version_info[:2]
  41. if INTP_VER < (2, 2):
  42. raise RuntimeError("Python v.2.2 or later required")
  43. class OrderedDict(dict):
  44. """
  45. A class of dictionary that keeps the insertion order of keys.
  46. All appropriate methods return keys, items, or values in an ordered way.
  47. All normal dictionary methods are available. Update and comparison is
  48. restricted to other OrderedDict objects.
  49. Various sequence methods are available, including the ability to explicitly
  50. mutate the key ordering.
  51. __contains__ tests:
  52. >>> d = OrderedDict(((1, 3),))
  53. >>> 1 in d
  54. 1
  55. >>> 4 in d
  56. 0
  57. __getitem__ tests:
  58. >>> OrderedDict(((1, 3), (3, 2), (2, 1)))[2]
  59. 1
  60. >>> OrderedDict(((1, 3), (3, 2), (2, 1)))[4]
  61. Traceback (most recent call last):
  62. KeyError: 4
  63. __len__ tests:
  64. >>> len(OrderedDict())
  65. 0
  66. >>> len(OrderedDict(((1, 3), (3, 2), (2, 1))))
  67. 3
  68. get tests:
  69. >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
  70. >>> d.get(1)
  71. 3
  72. >>> d.get(4) is None
  73. 1
  74. >>> d.get(4, 5)
  75. 5
  76. >>> d
  77. OrderedDict([(1, 3), (3, 2), (2, 1)])
  78. has_key tests:
  79. >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
  80. >>> d.has_key(1)
  81. 1
  82. >>> d.has_key(4)
  83. 0
  84. """
  85. def __init__(self, init_val=(), strict=False):
  86. """
  87. Create a new ordered dictionary. Cannot init from a normal dict,
  88. nor from kwargs, since items order is undefined in those cases.
  89. If the ``strict`` keyword argument is ``True`` (``False`` is the
  90. default) then when doing slice assignment - the ``OrderedDict`` you are
  91. assigning from *must not* contain any keys in the remaining dict.
  92. >>> OrderedDict()
  93. OrderedDict([])
  94. >>> OrderedDict({1: 1})
  95. Traceback (most recent call last):
  96. TypeError: undefined order, cannot get items from dict
  97. >>> OrderedDict({1: 1}.items())
  98. OrderedDict([(1, 1)])
  99. >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
  100. >>> d
  101. OrderedDict([(1, 3), (3, 2), (2, 1)])
  102. >>> OrderedDict(d)
  103. OrderedDict([(1, 3), (3, 2), (2, 1)])
  104. """
  105. self.strict = strict
  106. dict.__init__(self)
  107. if isinstance(init_val, OrderedDict):
  108. self._sequence = init_val.keys()
  109. dict.update(self, init_val)
  110. elif isinstance(init_val, dict):
  111. # we lose compatibility with other ordered dict types this way
  112. raise TypeError('undefined order, cannot get items from dict')
  113. else:
  114. self._sequence = []
  115. self.update(init_val)
  116. ### Special methods ###
  117. def __delitem__(self, key):
  118. """
  119. >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
  120. >>> del d[3]
  121. >>> d
  122. OrderedDict([(1, 3), (2, 1)])
  123. >>> del d[3]
  124. Traceback (most recent call last):
  125. KeyError: 3
  126. >>> d[3] = 2
  127. >>> d
  128. OrderedDict([(1, 3), (2, 1), (3, 2)])
  129. >>> del d[0:1]
  130. >>> d
  131. OrderedDict([(2, 1), (3, 2)])
  132. """
  133. if isinstance(key, slice):
  134. # FIXME: efficiency?
  135. keys = self._sequence[key]
  136. for entry in keys:
  137. dict.__delitem__(self, entry)
  138. del self._sequence[key]
  139. else:
  140. # do the dict.__delitem__ *first* as it raises
  141. # the more appropriate error
  142. dict.__delitem__(self, key)
  143. self._sequence.remove(key)
  144. def __eq__(self, other):
  145. """
  146. >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
  147. >>> d == OrderedDict(d)
  148. True
  149. >>> d == OrderedDict(((1, 3), (2, 1), (3, 2)))
  150. False
  151. >>> d == OrderedDict(((1, 0), (3, 2), (2, 1)))
  152. False
  153. >>> d == OrderedDict(((0, 3), (3, 2), (2, 1)))
  154. False
  155. >>> d == dict(d)
  156. False
  157. >>> d == False
  158. False
  159. """
  160. if isinstance(other, OrderedDict):
  161. # FIXME: efficiency?
  162. # Generate both item lists for each compare
  163. return (self.items() == other.items())
  164. else:
  165. return False
  166. def __lt__(self, other):
  167. """
  168. >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
  169. >>> c = OrderedDict(((0, 3), (3, 2), (2, 1)))
  170. >>> c < d
  171. True
  172. >>> d < c
  173. False
  174. >>> d < dict(c)
  175. Traceback (most recent call last):
  176. TypeError: Can only compare with other OrderedDicts
  177. """
  178. if not isinstance(other, OrderedDict):
  179. raise TypeError('Can only compare with other OrderedDicts')
  180. # FIXME: efficiency?
  181. # Generate both item lists for each compare
  182. return (self.items() < other.items())
  183. def __le__(self, other):
  184. """
  185. >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
  186. >>> c = OrderedDict(((0, 3), (3, 2), (2, 1)))
  187. >>> e = OrderedDict(d)
  188. >>> c <= d
  189. True
  190. >>> d <= c
  191. False
  192. >>> d <= dict(c)
  193. Traceback (most recent call last):
  194. TypeError: Can only compare with other OrderedDicts
  195. >>> d <= e
  196. True
  197. """
  198. if not isinstance(other, OrderedDict):
  199. raise TypeError('Can only compare with other OrderedDicts')
  200. # FIXME: efficiency?
  201. # Generate both item lists for each compare
  202. return (self.items() <= other.items())
  203. def __ne__(self, other):
  204. """
  205. >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
  206. >>> d != OrderedDict(d)
  207. False
  208. >>> d != OrderedDict(((1, 3), (2, 1), (3, 2)))
  209. True
  210. >>> d != OrderedDict(((1, 0), (3, 2), (2, 1)))
  211. True
  212. >>> d == OrderedDict(((0, 3), (3, 2), (2, 1)))
  213. False
  214. >>> d != dict(d)
  215. True
  216. >>> d != False
  217. True
  218. """
  219. if isinstance(other, OrderedDict):
  220. # FIXME: efficiency?
  221. # Generate both item lists for each compare
  222. return not (self.items() == other.items())
  223. else:
  224. return True
  225. def __gt__(self, other):
  226. """
  227. >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
  228. >>> c = OrderedDict(((0, 3), (3, 2), (2, 1)))
  229. >>> d > c
  230. True
  231. >>> c > d
  232. False
  233. >>> d > dict(c)
  234. Traceback (most recent call last):
  235. TypeError: Can only compare with other OrderedDicts
  236. """
  237. if not isinstance(other, OrderedDict):
  238. raise TypeError('Can only compare with other OrderedDicts')
  239. # FIXME: efficiency?
  240. # Generate both item lists for each compare
  241. return (self.items() > other.items())
  242. def __ge__(self, other):
  243. """
  244. >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
  245. >>> c = OrderedDict(((0, 3), (3, 2), (2, 1)))
  246. >>> e = OrderedDict(d)
  247. >>> c >= d
  248. False
  249. >>> d >= c
  250. True
  251. >>> d >= dict(c)
  252. Traceback (most recent call last):
  253. TypeError: Can only compare with other OrderedDicts
  254. >>> e >= d
  255. True
  256. """
  257. if not isinstance(other, OrderedDict):
  258. raise TypeError('Can only compare with other OrderedDicts')
  259. # FIXME: efficiency?
  260. # Generate both item lists for each compare
  261. return (self.items() >= other.items())
  262. def __repr__(self):
  263. """
  264. Used for __repr__ and __str__
  265. >>> r1 = repr(OrderedDict((('a', 'b'), ('c', 'd'), ('e', 'f'))))
  266. >>> r1
  267. "OrderedDict([('a', 'b'), ('c', 'd'), ('e', 'f')])"
  268. >>> r2 = repr(OrderedDict((('a', 'b'), ('e', 'f'), ('c', 'd'))))
  269. >>> r2
  270. "OrderedDict([('a', 'b'), ('e', 'f'), ('c', 'd')])"
  271. >>> r1 == str(OrderedDict((('a', 'b'), ('c', 'd'), ('e', 'f'))))
  272. True
  273. >>> r2 == str(OrderedDict((('a', 'b'), ('e', 'f'), ('c', 'd'))))
  274. True
  275. """
  276. return '%s([%s])' % (self.__class__.__name__, ', '.join(
  277. ['(%r, %r)' % (key, self[key]) for key in self._sequence]))
  278. def __setitem__(self, key, val):
  279. """
  280. Allows slice assignment, so long as the slice is an OrderedDict
  281. >>> d = OrderedDict()
  282. >>> d['a'] = 'b'
  283. >>> d['b'] = 'a'
  284. >>> d[3] = 12
  285. >>> d
  286. OrderedDict([('a', 'b'), ('b', 'a'), (3, 12)])
  287. >>> d[:] = OrderedDict(((1, 2), (2, 3), (3, 4)))
  288. >>> d
  289. OrderedDict([(1, 2), (2, 3), (3, 4)])
  290. >>> d[::2] = OrderedDict(((7, 8), (9, 10)))
  291. >>> d
  292. OrderedDict([(7, 8), (2, 3), (9, 10)])
  293. >>> d = OrderedDict(((0, 1), (1, 2), (2, 3), (3, 4)))
  294. >>> d[1:3] = OrderedDict(((1, 2), (5, 6), (7, 8)))
  295. >>> d
  296. OrderedDict([(0, 1), (1, 2), (5, 6), (7, 8), (3, 4)])
  297. >>> d = OrderedDict(((0, 1), (1, 2), (2, 3), (3, 4)), strict=True)
  298. >>> d[1:3] = OrderedDict(((1, 2), (5, 6), (7, 8)))
  299. >>> d
  300. OrderedDict([(0, 1), (1, 2), (5, 6), (7, 8), (3, 4)])
  301. >>> a = OrderedDict(((0, 1), (1, 2), (2, 3)), strict=True)
  302. >>> a[3] = 4
  303. >>> a
  304. OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
  305. >>> a[::1] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
  306. >>> a
  307. OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
  308. >>> a[:2] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)])
  309. Traceback (most recent call last):
  310. ValueError: slice assignment must be from unique keys
  311. >>> a = OrderedDict(((0, 1), (1, 2), (2, 3)))
  312. >>> a[3] = 4
  313. >>> a
  314. OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
  315. >>> a[::1] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
  316. >>> a
  317. OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
  318. >>> a[:2] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
  319. >>> a
  320. OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
  321. >>> a[::-1] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
  322. >>> a
  323. OrderedDict([(3, 4), (2, 3), (1, 2), (0, 1)])
  324. >>> d = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
  325. >>> d[:1] = 3
  326. Traceback (most recent call last):
  327. TypeError: slice assignment requires an OrderedDict
  328. >>> d = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
  329. >>> d[:1] = OrderedDict([(9, 8)])
  330. >>> d
  331. OrderedDict([(9, 8), (1, 2), (2, 3), (3, 4)])
  332. """
  333. if isinstance(key, slice):
  334. if not isinstance(val, OrderedDict):
  335. # FIXME: allow a list of tuples?
  336. raise TypeError('slice assignment requires an OrderedDict')
  337. keys = self._sequence[key]
  338. # NOTE: Could use ``range(*key.indices(len(self._sequence)))``
  339. indexes = range(len(self._sequence))[key]
  340. if key.step is None:
  341. # NOTE: new slice may not be the same size as the one being
  342. # overwritten !
  343. # NOTE: What is the algorithm for an impossible slice?
  344. # e.g. d[5:3]
  345. pos = key.start or 0
  346. del self[key]
  347. newkeys = val.keys()
  348. for k in newkeys:
  349. if k in self:
  350. if self.strict:
  351. raise ValueError('slice assignment must be from '
  352. 'unique keys')
  353. else:
  354. # NOTE: This removes duplicate keys *first*
  355. # so start position might have changed?
  356. del self[k]
  357. self._sequence = (self._sequence[:pos] + newkeys +
  358. self._sequence[pos:])
  359. dict.update(self, val)
  360. else:
  361. # extended slice - length of new slice must be the same
  362. # as the one being replaced
  363. if len(keys) != len(val):
  364. raise ValueError('attempt to assign sequence of size %s '
  365. 'to extended slice of size %s' % (len(val), len(keys)))
  366. # FIXME: efficiency?
  367. del self[key]
  368. item_list = zip(indexes, val.items())
  369. # smallest indexes first - higher indexes not guaranteed to
  370. # exist
  371. item_list.sort()
  372. for pos, (newkey, newval) in item_list:
  373. if self.strict and newkey in self:
  374. raise ValueError('slice assignment must be from unique'
  375. ' keys')
  376. self.insert(pos, newkey, newval)
  377. else:
  378. if key not in self:
  379. self._sequence.append(key)
  380. dict.__setitem__(self, key, val)
  381. def __getitem__(self, key):
  382. """
  383. Allows slicing. Returns an OrderedDict if you slice.
  384. >>> b = OrderedDict([(7, 0), (6, 1), (5, 2), (4, 3), (3, 4), (2, 5), (1, 6)])
  385. >>> b[::-1]
  386. OrderedDict([(1, 6), (2, 5), (3, 4), (4, 3), (5, 2), (6, 1), (7, 0)])
  387. >>> b[2:5]
  388. OrderedDict([(5, 2), (4, 3), (3, 4)])
  389. >>> type(b[2:4])
  390. <class '__main__.OrderedDict'>
  391. """
  392. if isinstance(key, slice):
  393. # FIXME: does this raise the error we want?
  394. keys = self._sequence[key]
  395. # FIXME: efficiency?
  396. return OrderedDict([(entry, self[entry]) for entry in keys])
  397. else:
  398. return dict.__getitem__(self, key)
  399. __str__ = __repr__
  400. def __setattr__(self, name, value):
  401. """
  402. Implemented so that accesses to ``sequence`` raise a warning and are
  403. diverted to the new ``setkeys`` method.
  404. """
  405. if name == 'sequence':
  406. warnings.warn('Use of the sequence attribute is deprecated.'
  407. ' Use the keys method instead.', DeprecationWarning)
  408. # NOTE: doesn't return anything
  409. self.setkeys(value)
  410. else:
  411. # FIXME: do we want to allow arbitrary setting of attributes?
  412. # Or do we want to manage it?
  413. object.__setattr__(self, name, value)
  414. def __getattr__(self, name):
  415. """
  416. Implemented so that access to ``sequence`` raises a warning.
  417. >>> d = OrderedDict()
  418. >>> d.sequence
  419. []
  420. """
  421. if name == 'sequence':
  422. warnings.warn('Use of the sequence attribute is deprecated.'
  423. ' Use the keys method instead.', DeprecationWarning)
  424. # NOTE: Still (currently) returns a direct reference. Need to
  425. # because code that uses sequence will expect to be able to
  426. # mutate it in place.
  427. return self._sequence
  428. else:
  429. # raise the appropriate error
  430. raise AttributeError("OrderedDict has no '%s' attribute" % name)
  431. def __deepcopy__(self, memo):
  432. """
  433. To allow deepcopy to work with OrderedDict.
  434. >>> from copy import deepcopy
  435. >>> a = OrderedDict([(1, 1), (2, 2), (3, 3)])
  436. >>> a['test'] = {}
  437. >>> b = deepcopy(a)
  438. >>> b == a
  439. True
  440. >>> b is a
  441. False
  442. >>> a['test'] is b['test']
  443. False
  444. """
  445. from copy import deepcopy
  446. return self.__class__(deepcopy(self.items(), memo), self.strict)
  447. ### Read-only methods ###
  448. def copy(self):
  449. """
  450. >>> OrderedDict(((1, 3), (3, 2), (2, 1))).copy()
  451. OrderedDict([(1, 3), (3, 2), (2, 1)])
  452. """
  453. return OrderedDict(self)
  454. def items(self):
  455. """
  456. ``items`` returns a list of tuples representing all the
  457. ``(key, value)`` pairs in the dictionary.
  458. >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
  459. >>> d.items()
  460. [(1, 3), (3, 2), (2, 1)]
  461. >>> d.clear()
  462. >>> d.items()
  463. []
  464. """
  465. return zip(self._sequence, self.values())
  466. def keys(self):
  467. """
  468. Return a list of keys in the ``OrderedDict``.
  469. >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
  470. >>> d.keys()
  471. [1, 3, 2]
  472. """
  473. return self._sequence[:]
  474. def values(self, values=None):
  475. """
  476. Return a list of all the values in the OrderedDict.
  477. Optionally you can pass in a list of values, which will replace the
  478. current list. The value list must be the same len as the OrderedDict.
  479. >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
  480. >>> d.values()
  481. [3, 2, 1]
  482. """
  483. return [self[key] for key in self._sequence]
  484. def iteritems(self):
  485. """
  486. >>> ii = OrderedDict(((1, 3), (3, 2), (2, 1))).iteritems()
  487. >>> ii.next()
  488. (1, 3)
  489. >>> ii.next()
  490. (3, 2)
  491. >>> ii.next()
  492. (2, 1)
  493. >>> ii.next()
  494. Traceback (most recent call last):
  495. StopIteration
  496. """
  497. def make_iter(self=self):
  498. keys = self.iterkeys()
  499. while True:
  500. key = keys.next()
  501. yield (key, self[key])
  502. return make_iter()
  503. def iterkeys(self):
  504. """
  505. >>> ii = OrderedDict(((1, 3), (3, 2), (2, 1))).iterkeys()
  506. >>> ii.next()
  507. 1
  508. >>> ii.next()
  509. 3
  510. >>> ii.next()
  511. 2
  512. >>> ii.next()
  513. Traceback (most recent call last):
  514. StopIteration
  515. """
  516. return iter(self._sequence)
  517. __iter__ = iterkeys
  518. def itervalues(self):
  519. """
  520. >>> iv = OrderedDict(((1, 3), (3, 2), (2, 1))).itervalues()
  521. >>> iv.next()
  522. 3
  523. >>> iv.next()
  524. 2
  525. >>> iv.next()
  526. 1
  527. >>> iv.next()
  528. Traceback (most recent call last):
  529. StopIteration
  530. """
  531. def make_iter(self=self):
  532. keys = self.iterkeys()
  533. while True:
  534. yield self[keys.next()]
  535. return make_iter()
  536. ### Read-write methods ###
  537. def clear(self):
  538. """
  539. >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
  540. >>> d.clear()
  541. >>> d
  542. OrderedDict([])
  543. """
  544. dict.clear(self)
  545. self._sequence = []
  546. def pop(self, key, *args):
  547. """
  548. No dict.pop in Python 2.2, gotta reimplement it
  549. >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
  550. >>> d.pop(3)
  551. 2
  552. >>> d
  553. OrderedDict([(1, 3), (2, 1)])
  554. >>> d.pop(4)
  555. Traceback (most recent call last):
  556. KeyError: 4
  557. >>> d.pop(4, 0)
  558. 0
  559. >>> d.pop(4, 0, 1)
  560. Traceback (most recent call last):
  561. TypeError: pop expected at most 2 arguments, got 3
  562. """
  563. if len(args) > 1:
  564. raise TypeError('pop expected at most 2 arguments, got %s' %
  565. (len(args) + 1))
  566. if key in self:
  567. val = self[key]
  568. del self[key]
  569. else:
  570. try:
  571. val = args[0]
  572. except IndexError:
  573. raise KeyError(key)
  574. return val
  575. def popitem(self, i=-1):
  576. """
  577. Delete and return an item specified by index, not a random one as in
  578. dict. The index is -1 by default (the last item).
  579. >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
  580. >>> d.popitem()
  581. (2, 1)
  582. >>> d
  583. OrderedDict([(1, 3), (3, 2)])
  584. >>> d.popitem(0)
  585. (1, 3)
  586. >>> OrderedDict().popitem()
  587. Traceback (most recent call last):
  588. KeyError: 'popitem(): dictionary is empty'
  589. >>> d.popitem(2)
  590. Traceback (most recent call last):
  591. IndexError: popitem(): index 2 not valid
  592. """
  593. if not self._sequence:
  594. raise KeyError('popitem(): dictionary is empty')
  595. try:
  596. key = self._sequence[i]
  597. except IndexError:
  598. raise IndexError('popitem(): index %s not valid' % i)
  599. return (key, self.pop(key))
  600. def setdefault(self, key, defval=None):
  601. """
  602. >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
  603. >>> d.setdefault(1)
  604. 3
  605. >>> d.setdefault(4) is None
  606. True
  607. >>> d
  608. OrderedDict([(1, 3), (3, 2), (2, 1), (4, None)])
  609. >>> d.setdefault(5, 0)
  610. 0
  611. >>> d
  612. OrderedDict([(1, 3), (3, 2), (2, 1), (4, None), (5, 0)])
  613. """
  614. if key in self:
  615. return self[key]
  616. else:
  617. self[key] = defval
  618. return defval
  619. def update(self, from_od):
  620. """
  621. Update from another OrderedDict or sequence of (key, value) pairs
  622. >>> d = OrderedDict(((1, 0), (0, 1)))
  623. >>> d.update(OrderedDict(((1, 3), (3, 2), (2, 1))))
  624. >>> d
  625. OrderedDict([(1, 3), (0, 1), (3, 2), (2, 1)])
  626. >>> d.update({4: 4})
  627. Traceback (most recent call last):
  628. TypeError: undefined order, cannot get items from dict
  629. >>> d.update((4, 4))
  630. Traceback (most recent call last):
  631. TypeError: cannot convert dictionary update sequence element "4" to a 2-item sequence
  632. """
  633. if isinstance(from_od, OrderedDict):
  634. for key, val in from_od.items():
  635. self[key] = val
  636. elif isinstance(from_od, dict):
  637. # we lose compatibility with other ordered dict types this way
  638. raise TypeError('undefined order, cannot get items from dict')
  639. else:
  640. # FIXME: efficiency?
  641. # sequence of 2-item sequences, or error
  642. for item in from_od:
  643. try:
  644. key, val = item
  645. except TypeError:
  646. raise TypeError('cannot convert dictionary update'
  647. ' sequence element "%s" to a 2-item sequence' % item)
  648. self[key] = val
  649. def rename(self, old_key, new_key):
  650. """
  651. Rename the key for a given value, without modifying sequence order.
  652. For the case where new_key already exists this raise an exception,
  653. since if new_key exists, it is ambiguous as to what happens to the
  654. associated values, and the position of new_key in the sequence.
  655. >>> od = OrderedDict()
  656. >>> od['a'] = 1
  657. >>> od['b'] = 2
  658. >>> od.items()
  659. [('a', 1), ('b', 2)]
  660. >>> od.rename('b', 'c')
  661. >>> od.items()
  662. [('a', 1), ('c', 2)]
  663. >>> od.rename('c', 'a')
  664. Traceback (most recent call last):
  665. ValueError: New key already exists: 'a'
  666. >>> od.rename('d', 'b')
  667. Traceback (most recent call last):
  668. KeyError: 'd'
  669. """
  670. if new_key == old_key:
  671. # no-op
  672. return
  673. if new_key in self:
  674. raise ValueError("New key already exists: %r" % new_key)
  675. # rename sequence entry
  676. value = self[old_key]
  677. old_idx = self._sequence.index(old_key)
  678. self._sequence[old_idx] = new_key
  679. # rename internal dict entry
  680. dict.__delitem__(self, old_key)
  681. dict.__setitem__(self, new_key, value)
  682. def setitems(self, items):
  683. """
  684. This method allows you to set the items in the dict.
  685. It takes a list of tuples - of the same sort returned by the ``items``
  686. method.
  687. >>> d = OrderedDict()
  688. >>> d.setitems(((3, 1), (2, 3), (1, 2)))
  689. >>> d
  690. OrderedDict([(3, 1), (2, 3), (1, 2)])
  691. """
  692. self.clear()
  693. # FIXME: this allows you to pass in an OrderedDict as well :-)
  694. self.update(items)
  695. def setkeys(self, keys):
  696. """
  697. ``setkeys`` all ows you to pass in a new list of keys which will
  698. replace the current set. This must contain the same set of keys, but
  699. need not be in the same order.
  700. If you pass in new keys that don't match, a ``KeyError`` will be
  701. raised.
  702. >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
  703. >>> d.keys()
  704. [1, 3, 2]
  705. >>> d.setkeys((1, 2, 3))
  706. >>> d
  707. OrderedDict([(1, 3), (2, 1), (3, 2)])
  708. >>> d.setkeys(['a', 'b', 'c'])
  709. Traceback (most recent call last):
  710. KeyError: 'Keylist is not the same as current keylist.'
  711. """
  712. # FIXME: Efficiency? (use set for Python 2.4 :-)
  713. # NOTE: list(keys) rather than keys[:] because keys[:] returns
  714. # a tuple, if keys is a tuple.
  715. kcopy = list(keys)
  716. kcopy.sort()
  717. self._sequence.sort()
  718. if kcopy != self._sequence:
  719. raise KeyError('Keylist is not the same as current keylist.')
  720. # NOTE: This makes the _sequence attribute a new object, instead
  721. # of changing it in place.
  722. # FIXME: efficiency?
  723. self._sequence = list(keys)
  724. def setvalues(self, values):
  725. """
  726. You can pass in a list of values, which will replace the
  727. current list. The value list must be the same len as the OrderedDict.
  728. (Or a ``ValueError`` is raised.)
  729. >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
  730. >>> d.setvalues((1, 2, 3))
  731. >>> d
  732. OrderedDict([(1, 1), (3, 2), (2, 3)])
  733. >>> d.setvalues([6])
  734. Traceback (most recent call last):
  735. ValueError: Value list is not the same length as the OrderedDict.
  736. """
  737. if len(values) != len(self):
  738. # FIXME: correct error to raise?
  739. raise ValueError('Value list is not the same length as the '
  740. 'OrderedDict.')
  741. self.update(zip(self, values))
  742. ### Sequence Methods ###
  743. def index(self, key):
  744. """
  745. Return the position of the specified key in the OrderedDict.
  746. >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
  747. >>> d.index(3)
  748. 1
  749. >>> d.index(4)
  750. Traceback (most recent call last):
  751. ValueError: 4 is not in list
  752. """
  753. return self._sequence.index(key)
  754. def insert(self, index, key, value):
  755. """
  756. Takes ``index``, ``key``, and ``value`` as arguments.
  757. Sets ``key`` to ``value``, so that ``key`` is at position ``index`` in
  758. the OrderedDict.
  759. >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
  760. >>> d.insert(0, 4, 0)
  761. >>> d
  762. OrderedDict([(4, 0), (1, 3), (3, 2), (2, 1)])
  763. >>> d.insert(0, 2, 1)
  764. >>> d
  765. OrderedDict([(2, 1), (4, 0), (1, 3), (3, 2)])
  766. >>> d.insert(8, 8, 1)
  767. >>> d
  768. OrderedDict([(2, 1), (4, 0), (1, 3), (3, 2), (8, 1)])
  769. """
  770. if key in self:
  771. # FIXME: efficiency?
  772. del self[key]
  773. self._sequence.insert(index, key)
  774. dict.__setitem__(self, key, value)
  775. def reverse(self):
  776. """
  777. Reverse the order of the OrderedDict.
  778. >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
  779. >>> d.reverse()
  780. >>> d
  781. OrderedDict([(2, 1), (3, 2), (1, 3)])
  782. """
  783. self._sequence.reverse()
  784. def sort(self, *args, **kwargs):
  785. """
  786. Sort the key order in the OrderedDict.
  787. This method takes the same arguments as the ``list.sort`` method on
  788. your version of Python.
  789. >>> d = OrderedDict(((4, 1), (2, 2), (3, 3), (1, 4)))
  790. >>> d.sort()
  791. >>> d
  792. OrderedDict([(1, 4), (2, 2), (3, 3), (4, 1)])
  793. """
  794. self._sequence.sort(*args, **kwargs)
  795. if __name__ == '__main__':
  796. # turn off warnings for tests
  797. warnings.filterwarnings('ignore')
  798. # run the code tests in doctest format
  799. import doctest
  800. m = sys.modules.get('__main__')
  801. globs = m.__dict__.copy()
  802. globs.update({
  803. 'INTP_VER': INTP_VER,
  804. })
  805. doctest.testmod(m, globs=globs)