Source code for bidict._frozenordered

# -*- coding: utf-8 -*-
# Copyright 2018 Joshua Bronson. All Rights Reserved.
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at

#                    * Welcome to the bidict source code *

# Doing a code review? You'll find a "Code review nav" comment like the one
# below at the top and bottom of the most important source files. This provides
# a suggested initial path through the source when reviewing.
# Note: If you aren't reading this on, you may be
# viewing an outdated version of the code. Please head to GitHub to review the
# latest version, which contains important improvements over older versions.
# Thank you for reading and for any feedback you provide.

#                             * Code review nav *
#  ← Prev:  Current:    Next: →

"""Provides :class:`FrozenOrderedBidict`, an immutable, hashable, ordered bidict."""

from ._frozen import frozenbidict
from ._orderedbase import OrderedBidictBase
from ._proxied import _ProxiedKeysVals
from .compat import DICTS_ORDERED, PY2, izip

# FrozenOrderedBidict intentionally does not subclass frozenbidict because it only complicates the
# inheritance hierarchy without providing any actual code reuse: The only thing from frozenbidict
# that FrozenOrderedBidict uses is frozenbidict.__hash__(), but Python specifically prevents
# __hash__ from being inherited; it must instead always be defined explicitly as below. Users who
# need an `is_frozenbidict(..)` test that succeeds for both frozenbidicts and FrozenOrderedBidicts
# should therefore not use isinstance(foo, frozenbidict), but should instead use the appropriate
# ABCs, e.g. `isinstance(foo, BidirectionalMapping) and not isinstance(foo, MutableMapping)`.
[docs]class FrozenOrderedBidict(OrderedBidictBase): """Hashable, immutable, ordered bidict type.""" __slots__ = () # frozenbidict.__hash__ can be resued for FrozenOrderedBidict: # FrozenOrderedBidict inherits BidictBase.__eq__ which is order-insensitive, # and frozenbidict.__hash__ is consistent with BidictBase.__eq__. __hash__ = frozenbidict.__hash__ # Must define __hash__ explicitly, Python prevents inheriting if PY2: # Must grab the __func__ attribute off the method in Python 2, or else get "TypeError: # unbound method __hash__() must be called with frozenbidict instance as first argument" __hash__ = __hash__.__func__
if DICTS_ORDERED: # If the Python implementation's dict type is ordered (e.g. PyPy or CPython >= 3.6), then # `FrozenOrderedBidict` can use the `_ProxiedKeysVals` mixin's more efficient implementations # of `keys` and `values`, rather than the less efficient implementations inherited from # `Mapping.keys` and `OrderedBidictBase.values`. # Both the `_fwdm` and `_invm` backing dicts will always be initialized with the provided # items in the correct order, and since `FrozenOrderedBidict` is immutable, their respective # orders can't get out of sync after a mutation, like they can with a mutable `OrderedBidict`. # (`FrozenOrderedBidict` can't use the more efficient `_ProxiedKeysValsItems.items` # implementation because the values in `_fwdm.items()` are nodes, so inheriting the # implementation from `Mapping.items` is the best we can do.) FrozenOrderedBidict.__bases__ = (_ProxiedKeysVals,) + FrozenOrderedBidict.__bases__ if PY2: # We can do better than the `iteritems` implementation inherited from `Mapping`; # zipping together the keys from `_fwdm` and `_invm` runs faster (e.g. C speed on CPython). def iteritems(self): """An iterator over the contained items.""" return izip(self._fwdm, self._invm) # pylint: disable=protected-access FrozenOrderedBidict.iteritems = iteritems # * Code review nav * #============================================================================== # ← Prev: Current: Next: → #==============================================================================