All Versions
Latest Version
Avg Release Cycle
80 days
Latest Release
65 days ago

Changelog History
Page 1

  • v0.22.0 Changes

    March 23, 2022
    • ⬇️ Drop support for Python 3.6, which reached end of life on 2021-12-23 and is no longer supported by pip as of pip version 22. Take advantage of this to reduce bidict's maintenance costs.

    • Use mypy-appeasing explicit re-exports in (e.g. import x as x) so that mypy no longer gives you an implicit re-export error if you run it with --no-implicit-reexport (or --strict) against code that imports from :mod:bidict.

    • ⚡️ Update the implementations and type annotations of :meth:bidict.BidictBase.keys and :meth:bidict.BidictBase.values to make use of the new :class:~bidict.BidictKeysView type, which works a bit better with type checkers.

    • Inverse bidict instances are now computed lazily the first time the :attr:~bidict.BidictBase.inverse attribute is accessed rather than being computed eagerly during initialization. (A bidict's backing, inverse, one-way mapping is still kept in sync eagerly as any mutations are made, to preserve key- and value-uniqueness.)

    • ⚡️ Optimize initializing a bidict with another bidict. In a microbenchmark on Python 3.10, this now performs over 2x faster.

    • ⚡️ Optimize updating an empty bidict with another bidict. In a microbenchmark on Python 3.10, this now performs 60-75% faster.

    • ⚡️ Optimize :meth:~bidict.BidictBase.copy. In a microbenchmark on Python 3.10, this now performs 10-20x faster.

    • ⚡️ Optimize rolling back :ref:failed updates to a bidict <basic-usage:Updates Fail Clean> in the case that the number of items passed to the update call can be determined to be larger than the bidict being updated. Previously this rollback was O(n) in the number of items passed. Now it is O(1), i.e. unboundedly faster.

    • Optimize :meth:bidict.BidictBase.__contains__ (the method called when you run key in mybidict). In a microbenchmark on Python 3.10, this now performs over 3-10x faster in the False case, and at least 50% faster in the True case.

    • Optimize :meth:bidict.BidictBase.__eq__ (the method called when you run mybidict == other). In a microbenchmark on Python 3.10, this now performs 15-25x faster for ordered bidicts, and 7-12x faster for unordered bidicts.

    • Optimize :meth:~bidict.BidictBase.equals_order_sensitive. In a microbenchmark on Python 3.10, this now performs 2x faster for ordered bidicts and 60-90% faster for unordered bidicts.

    • ⚡️ Optimize the objects returned by :meth:bidict.OrderedBidict.keys, :meth:bidict.OrderedBidict.values, and :meth:bidict.OrderedBidict.items to delegate to backing dict_keys and dict_items objects if available, which are much faster in CPython. For example, in a microbenchmark on Python 3.10, orderedbi.items() == d.items() now performs 30-50x faster.

    • 🛠 Fix a bug where :meth:bidict.BidictBase.__eq__ was always returning False rather than :obj:NotImplemented in the case that the argument was not a, defeating the argument's own __eq__() if implemented. As a notable example, bidicts now correctly compare equal to :obj:unittest.mock.ANY.

    • :class:bidict.BidictBase now adds a __reversed__ implementation to subclasses that don't have an overridden implementation depending on whether both their backing mappings are Previously, a __reversed__ implementation was only added to :class:~bidict.BidictBase when BidictBase._fwdm_cls was So if a :class:~bidict.BidictBase subclass set its _fwdm_cls to a non-reversible mutable mapping, it would also have to manually set its __reversed__ attribute to None to override the implementation inherited from :class:~bidict.BidictBase. This is no longer necessary thanks to bidict's new :meth:object.__init_subclass__ logic.

    • The objects returned by :meth:bidict.OrderedBidict.keys, :meth:bidict.OrderedBidict.values, and :meth:bidict.OrderedBidict.items are now (This was already the case for unordered bidicts when running on Python 3.8+.)

    • ➕ Add support for Python 3.9-style dict merge operators (PEP 584 <>__).

    See the tests <>__ for examples.

    • ⚡️ Update docstrings for :meth:bidict.BidictBase.keys, :meth:bidict.BidictBase.values, and :meth:bidict.BidictBase.items to include more details.

    • :func:~bidict.namedbidict now exposes the passed-in keyname and valname in the corresponding properties on the generated class.

    • :func:~bidict.namedbidict now requires base_type to be a subclass of :class:~bidict.BidictBase, but no longer requires base_type to provide an _isinv attribute, which :class:~bidict.BidictBase subclasses no longer provide.

    • When attempting to pickle a bidict's inverse whose class was :ref:dynamically generated <extending:Dynamic Inverse Class Generation>, and no reference to the dynamically-generated class has been stored anywhere in :data:sys.modules where :mod:pickle can find it, the pickle call is now more likely to succeed rather than failing with a :class:~pickle.PicklingError.

    • ✂ Remove the use of slots from (non-ABC) bidict types.

    This better matches the mapping implementations in Python's standard library, and significantly reduces code complexity and maintenance burden. The memory savings conferred by using slots are not noticeable unless you're creating millions of bidict instances anyway, which is an extremely unusual usage pattern.

    Of course, bidicts can still contain millions (or more) items (which is not an unusual usage pattern) without using any more memory than before these changes. Notably, slots are still used in the internal linked list nodes of ordered bidicts to save memory, since as many node instances are created as there are items inserted.

  • v0.21.4 Changes

    October 23, 2021

    👍 Explicitly declare support for Python 3.10 as well as some minor internal improvements.

  • v0.21.3 Changes

    September 05, 2021
    • All bidicts now provide the :meth:~bidict.BidictBase.equals_order_sensitive method, not just :class:~bidict.OrderedBidict\s.

    Since support for Python < 3.6 was dropped in v0.21.0, :class:dict\s provide a deterministic ordering on all supported Python versions, and as a result, all bidicts do too. So now even non-:class:Ordered <bidict.OrderedBidict> bidicts might as well provide :meth:~bidict.BidictBase.equals_order_sensitive.

    See the updated :ref:other-bidict-types:What about order-preserving dicts? docs for more info.

    • 👍 Take better advantage of the fact that dicts became :class:reversible <> in Python 3.8.

    Specifically, now even non-:class:Ordered <bidict.OrderedBidict> bidicts provide a :meth:~bidict.BidictBase.__reversed__ implementation on Python 3.8+ that calls :func:reversed on the backing _fwdm mapping.

    As a result, if you are using Python 3.8+, :class:~bidict.frozenbidict now gives you everything that :class:~bidict.FrozenOrderedBidict gives you, but with less space overhead.

    • Drop setuptools_scm <>__ as a setup_requires dependency.

    • 🔖 Remove the bidict.__version_info__ attribute.

  • v0.21.2 Changes

    September 07, 2020

    🚀 Please see for the changes in this release.

  • v0.21.1 Changes

    September 07, 2020

    🚀 This release was yanked and replaced with the 0.21.2 release, which actually provides the intended changes.

  • v0.21.0 Changes

    August 22, 2020
    • :mod:bidict now provides type hints <>__! ⌨️ ✅

    Adding type hints to :mod:bidict poses particularly interesting challenges due to the combination of generic types, dynamically-generated types (such as :ref:inverse bidict classes <extending:Dynamic Inverse Class Generation> and :func:namedbidicts <bidict.namedbidict>), and complicating optimizations such as the use of slots and weakrefs.

    It didn't take long to hit bugs and missing features in the state of the art for type hinting in Python today, e.g. missing higher-kinded types support (python/typing#548 <>), too-narrow type hints for (python/typeshed#4435 <>), a :class:typing.Generic bug in Python 3.6 (BPO-41451 <>__), etc.

    That said, this release should provide a solid foundation for code using :mod:bidict that enables static type checking.

    As always, if you spot any opportunities to improve :mod:bidict (including its new type hints), please don't hesitate to submit a PR!

    • ➕ Add :class:bidict.MutableBidirectionalMapping ABC.

    The :ref:other-bidict-types:Bidict Types Diagram has been updated accordingly.

    • ⬇️ Drop support for Python 3.5, which reaches end of life on 2020-09-13, represents a tiny percentage of bidict downloads on PyPI Stats <>, and lacks support for variable type hint syntax <>, ordered dicts <>, and :attr:`object.init_subclass__`.

    • ✂ Remove the no-longer-needed bidict.compat module.

    • 🚚 Move :ref:inverse bidict class access <extending:Dynamic Inverse Class Generation> from a property to an attribute set in :attr:~bidict.BidictBase.__init_subclass__, to save function call overhead on repeated access.

    • :meth:bidict.OrderedBidictBase.__iter__ no longer accepts a reverse keyword argument so that it matches the signature of :meth:container.__iter__.

    • Set the __module__ attribute of various :mod:bidict types (using :func:sys._getframe when necessary) so that private, internal modules are not exposed e.g. in classes' repr strings.

    • :func:~bidict.namedbidict now immediately raises :class:TypeError if the provided base_type does not provide _isinv or :meth:~object.__getstate__, rather than succeeding with a class whose instances may raise :class:AttributeError when these attributes are accessed.

  • v0.20.0 Changes

    July 23, 2020

    The following breaking changes are expected to affect few if any users.

    ✂ Remove APIs deprecated in the previous release:

    • bidict.OVERWRITE and bidict.IGNORE.

    • The on_dup_key, on_dup_val, and on_dup_kv arguments of :meth:~bidict.bidict.put and :meth:~bidict.bidict.putall.

    • The on_dup_key, on_dup_val, and on_dup_kv :class:~bidict.bidict class attributes.

    • Remove :meth:bidict.BidirectionalMapping.__subclasshook__ due to lack of use and maintenance cost.

    Fixes a bug introduced in 0.15.0 that caused any class with an inverse attribute to be incorrectly considered a subclass of #111 <>__

  • v0.19.0 Changes

    January 09, 2020
    • ⬇️ Drop support for Python 2 :ref:as promised in v0.18.2 <changelog:0.18.2 (2019-09-08)>.

    The :mod:bidict.compat module has been pruned accordingly.

    This makes bidict more efficient on Python 3 and enables further improvement to bidict in the future.

    • 🗄 Deprecate bidict.OVERWRITE and bidict.IGNORE. A :class:UserWarning will now be emitted if these are used.

    :attr:bidict.DROP_OLD and :attr:bidict.DROP_NEW should be used instead.

    • 📇 Rename DuplicationPolicy to :class:~bidict.OnDupAction (and implement it via an :class:~enum.Enum).

    An :class:~bidict.OnDupAction may be one of :attr:~bidict.RAISE, :attr:~bidict.DROP_OLD, or :attr:~bidict.DROP_NEW.

    • 🔦 Expose the new :class:~bidict.OnDup class to contain the three :class:~bidict.OnDupAction\s that should be taken upon encountering the three kinds of duplication that can occur (key, val, kv).

    • Provide the :attr:~bidict.ON_DUP_DEFAULT, :attr:~bidict.ON_DUP_RAISE, and :attr:~bidict.ON_DUP_DROP_OLD :class:~bidict.OnDup convenience instances.

    • 🗄 Deprecate the on_dup_key, on_dup_val, and on_dup_kv arguments of :meth:~bidict.bidict.put and :meth:~bidict.bidict.putall. A :class:UserWarning will now be emitted if these are used.

    These have been subsumed by the new on_dup argument, which takes an :class:~bidict.OnDup instance.

    Use it like this: bi.put(1, 2, OnDup(key=RAISE, val=...)). Or pass one of the instances already provided, such as :attr:~bidict.ON_DUP_DROP_OLD. Or just don't pass an on_dup argument to use the default value of :attr:~bidict.ON_DUP_RAISE.

    The :ref:basic-usage:Values Must Be Unique docs have been updated accordingly.

    • 🗄 Deprecate the on_dup_key, on_dup_val, and on_dup_kv :class:~bidict.bidict class attributes. A :class:UserWarning will now be emitted if these are used.

    These have been subsumed by the new :attr:~bidict.bidict.on_dup class attribute, which takes an :class:~bidict.OnDup instance.

    See the updated :doc:extending docs for example usage.

    • 👌 Improve the more efficient implementations of :meth:~bidict.BidirectionalMapping.keys, :meth:~bidict.BidirectionalMapping.values, and :meth:~bidict.BidirectionalMapping.items, and now also provide a more efficient implementation of :meth:~bidict.BidirectionalMapping.__iter__ by delegating to backing :class:dict\s in the bidict types for which this is possible.

    • 🚚 Move :meth:bidict.BidictBase.values to :meth:bidict.BidirectionalMapping.values, since the implementation is generic.

    • No longer use __all__ in :mod:bidict's

  • v0.18.4 Changes

    November 03, 2020

    🚀 Please see for the changes in this release.

  • v0.18.3 Changes

    September 22, 2019
    • 👌 Improve validation of names passed to :func:~bidict.namedbidict: Use :meth:str.isidentifier on Python 3, and a better regex on Python 2.

    • On Python 3, set :attr:~definition.__qualname__ on :func:~bidict.namedbidict classes based on the provided typename argument.