dictutils.py 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120
  1. # -*- coding: utf-8 -*-
  2. # Copyright (c) 2013, Mahmoud Hashemi
  3. #
  4. # Redistribution and use in source and binary forms, with or without
  5. # modification, are permitted provided that the following conditions are
  6. # met:
  7. #
  8. # * Redistributions of source code must retain the above copyright
  9. # notice, this list of conditions and the following disclaimer.
  10. #
  11. # * Redistributions in binary form must reproduce the above
  12. # copyright notice, this list of conditions and the following
  13. # disclaimer in the documentation and/or other materials provided
  14. # with the distribution.
  15. #
  16. # * The names of the contributors may not be used to endorse or
  17. # promote products derived from this software without specific
  18. # prior written permission.
  19. #
  20. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. """Python has a very powerful mapping type at its core: the :class:`dict`
  32. type. While versatile and featureful, the :class:`dict` prioritizes
  33. simplicity and performance. As a result, it does not retain the order
  34. of item insertion [1]_, nor does it store multiple values per key. It
  35. is a fast, unordered 1:1 mapping.
  36. The :class:`OrderedMultiDict` contrasts to the built-in :class:`dict`,
  37. as a relatively maximalist, ordered 1:n subtype of
  38. :class:`dict`. Virtually every feature of :class:`dict` has been
  39. retooled to be intuitive in the face of this added
  40. complexity. Additional methods have been added, such as
  41. :class:`collections.Counter`-like functionality.
  42. A prime advantage of the :class:`OrderedMultiDict` (OMD) is its
  43. non-destructive nature. Data can be added to an :class:`OMD` without being
  44. rearranged or overwritten. The property can allow the developer to
  45. work more freely with the data, as well as make more assumptions about
  46. where input data will end up in the output, all without any extra
  47. work.
  48. One great example of this is the :meth:`OMD.inverted()` method, which
  49. returns a new OMD with the values as keys and the keys as values. All
  50. the data and the respective order is still represented in the inverted
  51. form, all from an operation which would be outright wrong and reckless
  52. with a built-in :class:`dict` or :class:`collections.OrderedDict`.
  53. The OMD has been performance tuned to be suitable for a wide range of
  54. usages, including as a basic unordered MultiDict. Special
  55. thanks to `Mark Williams`_ for all his help.
  56. .. [1] As of 2015, `basic dicts on PyPy are ordered
  57. <http://morepypy.blogspot.com/2015/01/faster-more-memory-efficient-and-more.html>`_,
  58. and as of December 2017, `basic dicts in CPython 3 are now ordered
  59. <https://mail.python.org/pipermail/python-dev/2017-December/151283.html>`_, as
  60. well.
  61. .. _Mark Williams: https://github.com/markrwilliams
  62. """
  63. try:
  64. from collections.abc import KeysView, ValuesView, ItemsView
  65. except ImportError:
  66. from collections import KeysView, ValuesView, ItemsView
  67. import itertools
  68. try:
  69. from itertools import izip_longest
  70. except ImportError:
  71. from itertools import zip_longest as izip_longest
  72. try:
  73. from .typeutils import make_sentinel
  74. _MISSING = make_sentinel(var_name='_MISSING')
  75. except ImportError:
  76. _MISSING = object()
  77. PREV, NEXT, KEY, VALUE, SPREV, SNEXT = range(6)
  78. __all__ = ['MultiDict', 'OMD', 'OrderedMultiDict', 'OneToOne', 'ManyToMany', 'subdict', 'FrozenDict']
  79. try:
  80. profile
  81. except NameError:
  82. profile = lambda x: x
  83. class OrderedMultiDict(dict):
  84. """A MultiDict is a dictionary that can have multiple values per key
  85. and the OrderedMultiDict (OMD) is a MultiDict that retains
  86. original insertion order. Common use cases include:
  87. * handling query strings parsed from URLs
  88. * inverting a dictionary to create a reverse index (values to keys)
  89. * stacking data from multiple dictionaries in a non-destructive way
  90. The OrderedMultiDict constructor is identical to the built-in
  91. :class:`dict`, and overall the API constitutes an intuitive
  92. superset of the built-in type:
  93. >>> omd = OrderedMultiDict()
  94. >>> omd['a'] = 1
  95. >>> omd['b'] = 2
  96. >>> omd.add('a', 3)
  97. >>> omd.get('a')
  98. 3
  99. >>> omd.getlist('a')
  100. [1, 3]
  101. Some non-:class:`dict`-like behaviors also make an appearance,
  102. such as support for :func:`reversed`:
  103. >>> list(reversed(omd))
  104. ['b', 'a']
  105. Note that unlike some other MultiDicts, this OMD gives precedence
  106. to the most recent value added. ``omd['a']`` refers to ``3``, not
  107. ``1``.
  108. >>> omd
  109. OrderedMultiDict([('a', 1), ('b', 2), ('a', 3)])
  110. >>> omd.poplast('a')
  111. 3
  112. >>> omd
  113. OrderedMultiDict([('a', 1), ('b', 2)])
  114. >>> omd.pop('a')
  115. 1
  116. >>> omd
  117. OrderedMultiDict([('b', 2)])
  118. If you want a safe-to-modify or flat dictionary, use
  119. :meth:`OrderedMultiDict.todict()`.
  120. >>> from pprint import pprint as pp # preserve printed ordering
  121. >>> omd = OrderedMultiDict([('a', 1), ('b', 2), ('a', 3)])
  122. >>> pp(omd.todict())
  123. {'a': 3, 'b': 2}
  124. >>> pp(omd.todict(multi=True))
  125. {'a': [1, 3], 'b': [2]}
  126. With ``multi=False``, items appear with the keys in to original
  127. insertion order, alongside the most-recently inserted value for
  128. that key.
  129. >>> OrderedMultiDict([('a', 1), ('b', 2), ('a', 3)]).items(multi=False)
  130. [('a', 3), ('b', 2)]
  131. .. warning::
  132. ``dict(omd)`` changed behavior `in Python 3.7
  133. <https://bugs.python.org/issue34320>`_ due to changes made to
  134. support the transition from :class:`collections.OrderedDict` to
  135. the built-in dictionary being ordered. Before 3.7, the result
  136. would be a new dictionary, with values that were lists, similar
  137. to ``omd.todict(multi=True)`` (but only shallow-copy; the lists
  138. were direct references to OMD internal structures). From 3.7
  139. onward, the values became singular, like
  140. ``omd.todict(multi=False)``. For reliable cross-version
  141. behavior, just use :meth:`~OrderedMultiDict.todict()`.
  142. """
  143. def __init__(self, *args, **kwargs):
  144. if len(args) > 1:
  145. raise TypeError('%s expected at most 1 argument, got %s'
  146. % (self.__class__.__name__, len(args)))
  147. super(OrderedMultiDict, self).__init__()
  148. self._clear_ll()
  149. if args:
  150. self.update_extend(args[0])
  151. if kwargs:
  152. self.update(kwargs)
  153. def _clear_ll(self):
  154. try:
  155. _map = self._map
  156. except AttributeError:
  157. _map = self._map = {}
  158. self.root = []
  159. _map.clear()
  160. self.root[:] = [self.root, self.root, None]
  161. def _insert(self, k, v):
  162. root = self.root
  163. cells = self._map.setdefault(k, [])
  164. last = root[PREV]
  165. cell = [last, root, k, v]
  166. last[NEXT] = root[PREV] = cell
  167. cells.append(cell)
  168. def add(self, k, v):
  169. """Add a single value *v* under a key *k*. Existing values under *k*
  170. are preserved.
  171. """
  172. values = super(OrderedMultiDict, self).setdefault(k, [])
  173. self._insert(k, v)
  174. values.append(v)
  175. def addlist(self, k, v):
  176. """Add an iterable of values underneath a specific key, preserving
  177. any values already under that key.
  178. >>> omd = OrderedMultiDict([('a', -1)])
  179. >>> omd.addlist('a', range(3))
  180. >>> omd
  181. OrderedMultiDict([('a', -1), ('a', 0), ('a', 1), ('a', 2)])
  182. Called ``addlist`` for consistency with :meth:`getlist`, but
  183. tuples and other sequences and iterables work.
  184. """
  185. if not v:
  186. return
  187. self_insert = self._insert
  188. values = super(OrderedMultiDict, self).setdefault(k, [])
  189. for subv in v:
  190. self_insert(k, subv)
  191. values.extend(v)
  192. def get(self, k, default=None):
  193. """Return the value for key *k* if present in the dictionary, else
  194. *default*. If *default* is not given, ``None`` is returned.
  195. This method never raises a :exc:`KeyError`.
  196. To get all values under a key, use :meth:`OrderedMultiDict.getlist`.
  197. """
  198. return super(OrderedMultiDict, self).get(k, [default])[-1]
  199. def getlist(self, k, default=_MISSING):
  200. """Get all values for key *k* as a list, if *k* is in the
  201. dictionary, else *default*. The list returned is a copy and
  202. can be safely mutated. If *default* is not given, an empty
  203. :class:`list` is returned.
  204. """
  205. try:
  206. return super(OrderedMultiDict, self).__getitem__(k)[:]
  207. except KeyError:
  208. if default is _MISSING:
  209. return []
  210. return default
  211. def clear(self):
  212. "Empty the dictionary."
  213. super(OrderedMultiDict, self).clear()
  214. self._clear_ll()
  215. def setdefault(self, k, default=_MISSING):
  216. """If key *k* is in the dictionary, return its value. If not, insert
  217. *k* with a value of *default* and return *default*. *default*
  218. defaults to ``None``. See :meth:`dict.setdefault` for more
  219. information.
  220. """
  221. if not super(OrderedMultiDict, self).__contains__(k):
  222. self[k] = None if default is _MISSING else default
  223. return self[k]
  224. def copy(self):
  225. "Return a shallow copy of the dictionary."
  226. return self.__class__(self.iteritems(multi=True))
  227. @classmethod
  228. def fromkeys(cls, keys, default=None):
  229. """Create a dictionary from a list of keys, with all the values
  230. set to *default*, or ``None`` if *default* is not set.
  231. """
  232. return cls([(k, default) for k in keys])
  233. def update(self, E, **F):
  234. """Add items from a dictionary or iterable (and/or keyword arguments),
  235. overwriting values under an existing key. See
  236. :meth:`dict.update` for more details.
  237. """
  238. # E and F are throwback names to the dict() __doc__
  239. if E is self:
  240. return
  241. self_add = self.add
  242. if isinstance(E, OrderedMultiDict):
  243. for k in E:
  244. if k in self:
  245. del self[k]
  246. for k, v in E.iteritems(multi=True):
  247. self_add(k, v)
  248. elif callable(getattr(E, 'keys', None)):
  249. for k in E.keys():
  250. self[k] = E[k]
  251. else:
  252. seen = set()
  253. seen_add = seen.add
  254. for k, v in E:
  255. if k not in seen and k in self:
  256. del self[k]
  257. seen_add(k)
  258. self_add(k, v)
  259. for k in F:
  260. self[k] = F[k]
  261. return
  262. def update_extend(self, E, **F):
  263. """Add items from a dictionary, iterable, and/or keyword
  264. arguments without overwriting existing items present in the
  265. dictionary. Like :meth:`update`, but adds to existing keys
  266. instead of overwriting them.
  267. """
  268. if E is self:
  269. iterator = iter(E.items())
  270. elif isinstance(E, OrderedMultiDict):
  271. iterator = E.iteritems(multi=True)
  272. elif hasattr(E, 'keys'):
  273. iterator = ((k, E[k]) for k in E.keys())
  274. else:
  275. iterator = E
  276. self_add = self.add
  277. for k, v in iterator:
  278. self_add(k, v)
  279. def __setitem__(self, k, v):
  280. if super(OrderedMultiDict, self).__contains__(k):
  281. self._remove_all(k)
  282. self._insert(k, v)
  283. super(OrderedMultiDict, self).__setitem__(k, [v])
  284. def __getitem__(self, k):
  285. return super(OrderedMultiDict, self).__getitem__(k)[-1]
  286. def __delitem__(self, k):
  287. super(OrderedMultiDict, self).__delitem__(k)
  288. self._remove_all(k)
  289. def __eq__(self, other):
  290. if self is other:
  291. return True
  292. try:
  293. if len(other) != len(self):
  294. return False
  295. except TypeError:
  296. return False
  297. if isinstance(other, OrderedMultiDict):
  298. selfi = self.iteritems(multi=True)
  299. otheri = other.iteritems(multi=True)
  300. zipped_items = izip_longest(selfi, otheri, fillvalue=(None, None))
  301. for (selfk, selfv), (otherk, otherv) in zipped_items:
  302. if selfk != otherk or selfv != otherv:
  303. return False
  304. if not(next(selfi, _MISSING) is _MISSING
  305. and next(otheri, _MISSING) is _MISSING):
  306. # leftovers (TODO: watch for StopIteration?)
  307. return False
  308. return True
  309. elif hasattr(other, 'keys'):
  310. for selfk in self:
  311. try:
  312. other[selfk] == self[selfk]
  313. except KeyError:
  314. return False
  315. return True
  316. return False
  317. def __ne__(self, other):
  318. return not (self == other)
  319. def pop(self, k, default=_MISSING):
  320. """Remove all values under key *k*, returning the most-recently
  321. inserted value. Raises :exc:`KeyError` if the key is not
  322. present and no *default* is provided.
  323. """
  324. try:
  325. return self.popall(k)[-1]
  326. except KeyError:
  327. if default is _MISSING:
  328. raise KeyError(k)
  329. return default
  330. def popall(self, k, default=_MISSING):
  331. """Remove all values under key *k*, returning them in the form of
  332. a list. Raises :exc:`KeyError` if the key is not present and no
  333. *default* is provided.
  334. """
  335. super_self = super(OrderedMultiDict, self)
  336. if super_self.__contains__(k):
  337. self._remove_all(k)
  338. if default is _MISSING:
  339. return super_self.pop(k)
  340. return super_self.pop(k, default)
  341. def poplast(self, k=_MISSING, default=_MISSING):
  342. """Remove and return the most-recently inserted value under the key
  343. *k*, or the most-recently inserted key if *k* is not
  344. provided. If no values remain under *k*, it will be removed
  345. from the OMD. Raises :exc:`KeyError` if *k* is not present in
  346. the dictionary, or the dictionary is empty.
  347. """
  348. if k is _MISSING:
  349. if self:
  350. k = self.root[PREV][KEY]
  351. else:
  352. if default is _MISSING:
  353. raise KeyError('empty %r' % type(self))
  354. return default
  355. try:
  356. self._remove(k)
  357. except KeyError:
  358. if default is _MISSING:
  359. raise KeyError(k)
  360. return default
  361. values = super(OrderedMultiDict, self).__getitem__(k)
  362. v = values.pop()
  363. if not values:
  364. super(OrderedMultiDict, self).__delitem__(k)
  365. return v
  366. def _remove(self, k):
  367. values = self._map[k]
  368. cell = values.pop()
  369. cell[PREV][NEXT], cell[NEXT][PREV] = cell[NEXT], cell[PREV]
  370. if not values:
  371. del self._map[k]
  372. def _remove_all(self, k):
  373. values = self._map[k]
  374. while values:
  375. cell = values.pop()
  376. cell[PREV][NEXT], cell[NEXT][PREV] = cell[NEXT], cell[PREV]
  377. del self._map[k]
  378. def iteritems(self, multi=False):
  379. """Iterate over the OMD's items in insertion order. By default,
  380. yields only the most-recently inserted value for each key. Set
  381. *multi* to ``True`` to get all inserted items.
  382. """
  383. root = self.root
  384. curr = root[NEXT]
  385. if multi:
  386. while curr is not root:
  387. yield curr[KEY], curr[VALUE]
  388. curr = curr[NEXT]
  389. else:
  390. for key in self.iterkeys():
  391. yield key, self[key]
  392. def iterkeys(self, multi=False):
  393. """Iterate over the OMD's keys in insertion order. By default, yields
  394. each key once, according to the most recent insertion. Set
  395. *multi* to ``True`` to get all keys, including duplicates, in
  396. insertion order.
  397. """
  398. root = self.root
  399. curr = root[NEXT]
  400. if multi:
  401. while curr is not root:
  402. yield curr[KEY]
  403. curr = curr[NEXT]
  404. else:
  405. yielded = set()
  406. yielded_add = yielded.add
  407. while curr is not root:
  408. k = curr[KEY]
  409. if k not in yielded:
  410. yielded_add(k)
  411. yield k
  412. curr = curr[NEXT]
  413. def itervalues(self, multi=False):
  414. """Iterate over the OMD's values in insertion order. By default,
  415. yields the most-recently inserted value per unique key. Set
  416. *multi* to ``True`` to get all values according to insertion
  417. order.
  418. """
  419. for k, v in self.iteritems(multi=multi):
  420. yield v
  421. def todict(self, multi=False):
  422. """Gets a basic :class:`dict` of the items in this dictionary. Keys
  423. are the same as the OMD, values are the most recently inserted
  424. values for each key.
  425. Setting the *multi* arg to ``True`` is yields the same
  426. result as calling :class:`dict` on the OMD, except that all the
  427. value lists are copies that can be safely mutated.
  428. """
  429. if multi:
  430. return dict([(k, self.getlist(k)) for k in self])
  431. return dict([(k, self[k]) for k in self])
  432. def sorted(self, key=None, reverse=False):
  433. """Similar to the built-in :func:`sorted`, except this method returns
  434. a new :class:`OrderedMultiDict` sorted by the provided key
  435. function, optionally reversed.
  436. Args:
  437. key (callable): A callable to determine the sort key of
  438. each element. The callable should expect an **item**
  439. (key-value pair tuple).
  440. reverse (bool): Set to ``True`` to reverse the ordering.
  441. >>> omd = OrderedMultiDict(zip(range(3), range(3)))
  442. >>> omd.sorted(reverse=True)
  443. OrderedMultiDict([(2, 2), (1, 1), (0, 0)])
  444. Note that the key function receives an **item** (key-value
  445. tuple), so the recommended signature looks like:
  446. >>> omd = OrderedMultiDict(zip('hello', 'world'))
  447. >>> omd.sorted(key=lambda i: i[1]) # i[0] is the key, i[1] is the val
  448. OrderedMultiDict([('o', 'd'), ('l', 'l'), ('e', 'o'), ('l', 'r'), ('h', 'w')])
  449. """
  450. cls = self.__class__
  451. return cls(sorted(self.iteritems(multi=True), key=key, reverse=reverse))
  452. def sortedvalues(self, key=None, reverse=False):
  453. """Returns a copy of the :class:`OrderedMultiDict` with the same keys
  454. in the same order as the original OMD, but the values within
  455. each keyspace have been sorted according to *key* and
  456. *reverse*.
  457. Args:
  458. key (callable): A single-argument callable to determine
  459. the sort key of each element. The callable should expect
  460. an **item** (key-value pair tuple).
  461. reverse (bool): Set to ``True`` to reverse the ordering.
  462. >>> omd = OrderedMultiDict()
  463. >>> omd.addlist('even', [6, 2])
  464. >>> omd.addlist('odd', [1, 5])
  465. >>> omd.add('even', 4)
  466. >>> omd.add('odd', 3)
  467. >>> somd = omd.sortedvalues()
  468. >>> somd.getlist('even')
  469. [2, 4, 6]
  470. >>> somd.keys(multi=True) == omd.keys(multi=True)
  471. True
  472. >>> omd == somd
  473. False
  474. >>> somd
  475. OrderedMultiDict([('even', 2), ('even', 4), ('odd', 1), ('odd', 3), ('even', 6), ('odd', 5)])
  476. As demonstrated above, contents and key order are
  477. retained. Only value order changes.
  478. """
  479. try:
  480. superself_iteritems = super(OrderedMultiDict, self).iteritems()
  481. except AttributeError:
  482. superself_iteritems = super(OrderedMultiDict, self).items()
  483. # (not reverse) because they pop off in reverse order for reinsertion
  484. sorted_val_map = dict([(k, sorted(v, key=key, reverse=(not reverse)))
  485. for k, v in superself_iteritems])
  486. ret = self.__class__()
  487. for k in self.iterkeys(multi=True):
  488. ret.add(k, sorted_val_map[k].pop())
  489. return ret
  490. def inverted(self):
  491. """Returns a new :class:`OrderedMultiDict` with values and keys
  492. swapped, like creating dictionary transposition or reverse
  493. index. Insertion order is retained and all keys and values
  494. are represented in the output.
  495. >>> omd = OMD([(0, 2), (1, 2)])
  496. >>> omd.inverted().getlist(2)
  497. [0, 1]
  498. Inverting twice yields a copy of the original:
  499. >>> omd.inverted().inverted()
  500. OrderedMultiDict([(0, 2), (1, 2)])
  501. """
  502. return self.__class__((v, k) for k, v in self.iteritems(multi=True))
  503. def counts(self):
  504. """Returns a mapping from key to number of values inserted under that
  505. key. Like :py:class:`collections.Counter`, but returns a new
  506. :class:`OrderedMultiDict`.
  507. """
  508. # Returns an OMD because Counter/OrderedDict may not be
  509. # available, and neither Counter nor dict maintain order.
  510. super_getitem = super(OrderedMultiDict, self).__getitem__
  511. return self.__class__((k, len(super_getitem(k))) for k in self)
  512. def keys(self, multi=False):
  513. """Returns a list containing the output of :meth:`iterkeys`. See
  514. that method's docs for more details.
  515. """
  516. return list(self.iterkeys(multi=multi))
  517. def values(self, multi=False):
  518. """Returns a list containing the output of :meth:`itervalues`. See
  519. that method's docs for more details.
  520. """
  521. return list(self.itervalues(multi=multi))
  522. def items(self, multi=False):
  523. """Returns a list containing the output of :meth:`iteritems`. See
  524. that method's docs for more details.
  525. """
  526. return list(self.iteritems(multi=multi))
  527. def __iter__(self):
  528. return self.iterkeys()
  529. def __reversed__(self):
  530. root = self.root
  531. curr = root[PREV]
  532. lengths = {}
  533. lengths_sd = lengths.setdefault
  534. get_values = super(OrderedMultiDict, self).__getitem__
  535. while curr is not root:
  536. k = curr[KEY]
  537. vals = get_values(k)
  538. if lengths_sd(k, 1) == len(vals):
  539. yield k
  540. lengths[k] += 1
  541. curr = curr[PREV]
  542. def __repr__(self):
  543. cn = self.__class__.__name__
  544. kvs = ', '.join([repr((k, v)) for k, v in self.iteritems(multi=True)])
  545. return '%s([%s])' % (cn, kvs)
  546. def viewkeys(self):
  547. "OMD.viewkeys() -> a set-like object providing a view on OMD's keys"
  548. return KeysView(self)
  549. def viewvalues(self):
  550. "OMD.viewvalues() -> an object providing a view on OMD's values"
  551. return ValuesView(self)
  552. def viewitems(self):
  553. "OMD.viewitems() -> a set-like object providing a view on OMD's items"
  554. return ItemsView(self)
  555. # A couple of convenient aliases
  556. OMD = OrderedMultiDict
  557. MultiDict = OrderedMultiDict
  558. class FastIterOrderedMultiDict(OrderedMultiDict):
  559. """An OrderedMultiDict backed by a skip list. Iteration over keys
  560. is faster and uses constant memory but adding duplicate key-value
  561. pairs is slower. Brainchild of Mark Williams.
  562. """
  563. def _clear_ll(self):
  564. # TODO: always reset objects? (i.e., no else block below)
  565. try:
  566. _map = self._map
  567. except AttributeError:
  568. _map = self._map = {}
  569. self.root = []
  570. _map.clear()
  571. self.root[:] = [self.root, self.root,
  572. None, None,
  573. self.root, self.root]
  574. def _insert(self, k, v):
  575. root = self.root
  576. empty = []
  577. cells = self._map.setdefault(k, empty)
  578. last = root[PREV]
  579. if cells is empty:
  580. cell = [last, root,
  581. k, v,
  582. last, root]
  583. # was the last one skipped?
  584. if last[SPREV][SNEXT] is root:
  585. last[SPREV][SNEXT] = cell
  586. last[NEXT] = last[SNEXT] = root[PREV] = root[SPREV] = cell
  587. cells.append(cell)
  588. else:
  589. # if the previous was skipped, go back to the cell that
  590. # skipped it
  591. sprev = last[SPREV] if (last[SPREV][SNEXT] is not last) else last
  592. cell = [last, root,
  593. k, v,
  594. sprev, root]
  595. # skip me
  596. last[SNEXT] = root
  597. last[NEXT] = root[PREV] = root[SPREV] = cell
  598. cells.append(cell)
  599. def _remove(self, k):
  600. cells = self._map[k]
  601. cell = cells.pop()
  602. if not cells:
  603. del self._map[k]
  604. cell[PREV][SNEXT] = cell[SNEXT]
  605. if cell[PREV][SPREV][SNEXT] is cell:
  606. cell[PREV][SPREV][SNEXT] = cell[NEXT]
  607. elif cell[SNEXT] is cell[NEXT]:
  608. cell[SPREV][SNEXT], cell[SNEXT][SPREV] = cell[SNEXT], cell[SPREV]
  609. cell[PREV][NEXT], cell[NEXT][PREV] = cell[NEXT], cell[PREV]
  610. def _remove_all(self, k):
  611. cells = self._map.pop(k)
  612. while cells:
  613. cell = cells.pop()
  614. if cell[PREV][SPREV][SNEXT] is cell:
  615. cell[PREV][SPREV][SNEXT] = cell[NEXT]
  616. elif cell[SNEXT] is cell[NEXT]:
  617. cell[SPREV][SNEXT], cell[SNEXT][SPREV] = cell[SNEXT], cell[SPREV]
  618. cell[PREV][NEXT], cell[NEXT][PREV] = cell[NEXT], cell[PREV]
  619. cell[PREV][SNEXT] = cell[SNEXT]
  620. def iteritems(self, multi=False):
  621. next_link = NEXT if multi else SNEXT
  622. root = self.root
  623. curr = root[next_link]
  624. while curr is not root:
  625. yield curr[KEY], curr[VALUE]
  626. curr = curr[next_link]
  627. def iterkeys(self, multi=False):
  628. next_link = NEXT if multi else SNEXT
  629. root = self.root
  630. curr = root[next_link]
  631. while curr is not root:
  632. yield curr[KEY]
  633. curr = curr[next_link]
  634. def __reversed__(self):
  635. root = self.root
  636. curr = root[PREV]
  637. while curr is not root:
  638. if curr[SPREV][SNEXT] is not curr:
  639. curr = curr[SPREV]
  640. if curr is root:
  641. break
  642. yield curr[KEY]
  643. curr = curr[PREV]
  644. _OTO_INV_MARKER = object()
  645. _OTO_UNIQUE_MARKER = object()
  646. class OneToOne(dict):
  647. """Implements a one-to-one mapping dictionary. In addition to
  648. inheriting from and behaving exactly like the builtin
  649. :class:`dict`, all values are automatically added as keys on a
  650. reverse mapping, available as the `inv` attribute. This
  651. arrangement keeps key and value namespaces distinct.
  652. Basic operations are intuitive:
  653. >>> oto = OneToOne({'a': 1, 'b': 2})
  654. >>> print(oto['a'])
  655. 1
  656. >>> print(oto.inv[1])
  657. a
  658. >>> len(oto)
  659. 2
  660. Overwrites happens in both directions:
  661. >>> oto.inv[1] = 'c'
  662. >>> print(oto.get('a'))
  663. None
  664. >>> len(oto)
  665. 2
  666. For a very similar project, with even more one-to-one
  667. functionality, check out `bidict <https://github.com/jab/bidict>`_.
  668. """
  669. __slots__ = ('inv',)
  670. def __init__(self, *a, **kw):
  671. raise_on_dupe = False
  672. if a:
  673. if a[0] is _OTO_INV_MARKER:
  674. self.inv = a[1]
  675. dict.__init__(self, [(v, k) for k, v in self.inv.items()])
  676. return
  677. elif a[0] is _OTO_UNIQUE_MARKER:
  678. a, raise_on_dupe = a[1:], True
  679. dict.__init__(self, *a, **kw)
  680. self.inv = self.__class__(_OTO_INV_MARKER, self)
  681. if len(self) == len(self.inv):
  682. # if lengths match, that means everything's unique
  683. return
  684. if not raise_on_dupe:
  685. dict.clear(self)
  686. dict.update(self, [(v, k) for k, v in self.inv.items()])
  687. return
  688. # generate an error message if the values aren't 1:1
  689. val_multidict = {}
  690. for k, v in self.items():
  691. val_multidict.setdefault(v, []).append(k)
  692. dupes = dict([(v, k_list) for v, k_list in
  693. val_multidict.items() if len(k_list) > 1])
  694. raise ValueError('expected unique values, got multiple keys for'
  695. ' the following values: %r' % dupes)
  696. @classmethod
  697. def unique(cls, *a, **kw):
  698. """This alternate constructor for OneToOne will raise an exception
  699. when input values overlap. For instance:
  700. >>> OneToOne.unique({'a': 1, 'b': 1})
  701. Traceback (most recent call last):
  702. ...
  703. ValueError: expected unique values, got multiple keys for the following values: ...
  704. This even works across inputs:
  705. >>> a_dict = {'a': 2}
  706. >>> OneToOne.unique(a_dict, b=2)
  707. Traceback (most recent call last):
  708. ...
  709. ValueError: expected unique values, got multiple keys for the following values: ...
  710. """
  711. return cls(_OTO_UNIQUE_MARKER, *a, **kw)
  712. def __setitem__(self, key, val):
  713. hash(val) # ensure val is a valid key
  714. if key in self:
  715. dict.__delitem__(self.inv, self[key])
  716. if val in self.inv:
  717. del self.inv[val]
  718. dict.__setitem__(self, key, val)
  719. dict.__setitem__(self.inv, val, key)
  720. def __delitem__(self, key):
  721. dict.__delitem__(self.inv, self[key])
  722. dict.__delitem__(self, key)
  723. def clear(self):
  724. dict.clear(self)
  725. dict.clear(self.inv)
  726. def copy(self):
  727. return self.__class__(self)
  728. def pop(self, key, default=_MISSING):
  729. if key in self:
  730. dict.__delitem__(self.inv, self[key])
  731. return dict.pop(self, key)
  732. if default is not _MISSING:
  733. return default
  734. raise KeyError()
  735. def popitem(self):
  736. key, val = dict.popitem(self)
  737. dict.__delitem__(self.inv, val)
  738. return key, val
  739. def setdefault(self, key, default=None):
  740. if key not in self:
  741. self[key] = default
  742. return self[key]
  743. def update(self, dict_or_iterable, **kw):
  744. if isinstance(dict_or_iterable, dict):
  745. for val in dict_or_iterable.values():
  746. hash(val)
  747. keys_vals = list(dict_or_iterable.items())
  748. else:
  749. for key, val in dict_or_iterable:
  750. hash(key)
  751. hash(val)
  752. keys_vals = list(dict_or_iterable)
  753. for val in kw.values():
  754. hash(val)
  755. keys_vals.extend(kw.items())
  756. for key, val in keys_vals:
  757. self[key] = val
  758. def __repr__(self):
  759. cn = self.__class__.__name__
  760. dict_repr = dict.__repr__(self)
  761. return "%s(%s)" % (cn, dict_repr)
  762. # marker for the secret handshake used internally to set up the invert ManyToMany
  763. _PAIRING = object()
  764. class ManyToMany(object):
  765. """
  766. a dict-like entity that represents a many-to-many relationship
  767. between two groups of objects
  768. behaves like a dict-of-tuples; also has .inv which is kept
  769. up to date which is a dict-of-tuples in the other direction
  770. also, can be used as a directed graph among hashable python objects
  771. """
  772. def __init__(self, items=None):
  773. self.data = {}
  774. if type(items) is tuple and items and items[0] is _PAIRING:
  775. self.inv = items[1]
  776. else:
  777. self.inv = self.__class__((_PAIRING, self))
  778. if items:
  779. self.update(items)
  780. return
  781. def get(self, key, default=frozenset()):
  782. try:
  783. return self[key]
  784. except KeyError:
  785. return default
  786. def __getitem__(self, key):
  787. return frozenset(self.data[key])
  788. def __setitem__(self, key, vals):
  789. vals = set(vals)
  790. if key in self:
  791. to_remove = self.data[key] - vals
  792. vals -= self.data[key]
  793. for val in to_remove:
  794. self.remove(key, val)
  795. for val in vals:
  796. self.add(key, val)
  797. def __delitem__(self, key):
  798. for val in self.data.pop(key):
  799. self.inv.data[val].remove(key)
  800. if not self.inv.data[val]:
  801. del self.inv.data[val]
  802. def update(self, iterable):
  803. """given an iterable of (key, val), add them all"""
  804. if type(iterable) is type(self):
  805. other = iterable
  806. for k in other.data:
  807. if k not in self.data:
  808. self.data[k] = other.data[k]
  809. else:
  810. self.data[k].update(other.data[k])
  811. for k in other.inv.data:
  812. if k not in self.inv.data:
  813. self.inv.data[k] = other.inv.data[k]
  814. else:
  815. self.inv.data[k].update(other.inv.data[k])
  816. elif callable(getattr(iterable, 'keys', None)):
  817. for k in iterable.keys():
  818. self.add(k, iterable[k])
  819. else:
  820. for key, val in iterable:
  821. self.add(key, val)
  822. return
  823. def add(self, key, val):
  824. if key not in self.data:
  825. self.data[key] = set()
  826. self.data[key].add(val)
  827. if val not in self.inv.data:
  828. self.inv.data[val] = set()
  829. self.inv.data[val].add(key)
  830. def remove(self, key, val):
  831. self.data[key].remove(val)
  832. if not self.data[key]:
  833. del self.data[key]
  834. self.inv.data[val].remove(key)
  835. if not self.inv.data[val]:
  836. del self.inv.data[val]
  837. def replace(self, key, newkey):
  838. """
  839. replace instances of key by newkey
  840. """
  841. if key not in self.data:
  842. return
  843. self.data[newkey] = fwdset = self.data.pop(key)
  844. for val in fwdset:
  845. revset = self.inv.data[val]
  846. revset.remove(key)
  847. revset.add(newkey)
  848. def iteritems(self):
  849. for key in self.data:
  850. for val in self.data[key]:
  851. yield key, val
  852. def keys(self):
  853. return self.data.keys()
  854. def __contains__(self, key):
  855. return key in self.data
  856. def __iter__(self):
  857. return self.data.__iter__()
  858. def __len__(self):
  859. return self.data.__len__()
  860. def __eq__(self, other):
  861. return type(self) == type(other) and self.data == other.data
  862. def __repr__(self):
  863. cn = self.__class__.__name__
  864. return '%s(%r)' % (cn, list(self.iteritems()))
  865. def subdict(d, keep=None, drop=None):
  866. """Compute the "subdictionary" of a dict, *d*.
  867. A subdict is to a dict what a subset is a to set. If *A* is a
  868. subdict of *B*, that means that all keys of *A* are present in
  869. *B*.
  870. Returns a new dict with any keys in *drop* removed, and any keys
  871. in *keep* still present, provided they were in the original
  872. dict. *keep* defaults to all keys, *drop* defaults to empty, so
  873. without one of these arguments, calling this function is
  874. equivalent to calling ``dict()``.
  875. >>> from pprint import pprint as pp
  876. >>> pp(subdict({'a': 1, 'b': 2}))
  877. {'a': 1, 'b': 2}
  878. >>> subdict({'a': 1, 'b': 2, 'c': 3}, drop=['b', 'c'])
  879. {'a': 1}
  880. >>> pp(subdict({'a': 1, 'b': 2, 'c': 3}, keep=['a', 'c']))
  881. {'a': 1, 'c': 3}
  882. """
  883. if keep is None:
  884. keep = d.keys()
  885. if drop is None:
  886. drop = []
  887. keys = set(keep) - set(drop)
  888. return type(d)([(k, v) for k, v in d.items() if k in keys])
  889. class FrozenHashError(TypeError):
  890. pass
  891. class FrozenDict(dict):
  892. """An immutable dict subtype that is hashable and can itself be used
  893. as a :class:`dict` key or :class:`set` entry. What
  894. :class:`frozenset` is to :class:`set`, FrozenDict is to
  895. :class:`dict`.
  896. There was once an attempt to introduce such a type to the standard
  897. library, but it was rejected: `PEP 416 <https://www.python.org/dev/peps/pep-0416/>`_.
  898. Because FrozenDict is a :class:`dict` subtype, it automatically
  899. works everywhere a dict would, including JSON serialization.
  900. """
  901. __slots__ = ('_hash',)
  902. def updated(self, *a, **kw):
  903. """Make a copy and add items from a dictionary or iterable (and/or
  904. keyword arguments), overwriting values under an existing
  905. key. See :meth:`dict.update` for more details.
  906. """
  907. data = dict(self)
  908. data.update(*a, **kw)
  909. return type(self)(data)
  910. @classmethod
  911. def fromkeys(cls, keys, value=None):
  912. # one of the lesser known and used/useful dict methods
  913. return cls(dict.fromkeys(keys, value))
  914. def __repr__(self):
  915. cn = self.__class__.__name__
  916. return '%s(%s)' % (cn, dict.__repr__(self))
  917. def __reduce_ex__(self, protocol):
  918. return type(self), (dict(self),)
  919. def __hash__(self):
  920. try:
  921. ret = self._hash
  922. except AttributeError:
  923. try:
  924. ret = self._hash = hash(frozenset(self.items()))
  925. except Exception as e:
  926. ret = self._hash = FrozenHashError(e)
  927. if ret.__class__ is FrozenHashError:
  928. raise ret
  929. return ret
  930. def __copy__(self):
  931. return self # immutable types don't copy, see tuple's behavior
  932. # block everything else
  933. def _raise_frozen_typeerror(self, *a, **kw):
  934. "raises a TypeError, because FrozenDicts are immutable"
  935. raise TypeError('%s object is immutable' % self.__class__.__name__)
  936. __ior__ = __setitem__ = __delitem__ = update = _raise_frozen_typeerror
  937. setdefault = pop = popitem = clear = _raise_frozen_typeerror
  938. del _raise_frozen_typeerror
  939. # end dictutils.py