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
__init__.py
(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 runkey 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 runmybidict == 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 :class:
~collections.abc.MappingView
objects returned by :meth:bidict.OrderedBidict.keys
, :meth:bidict.OrderedBidict.values
, and :meth:bidict.OrderedBidict.items
to delegate to backingdict_keys
anddict_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 :class:~collections.abc.Mapping
, 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 :class:~collections.abc.Reversible
. Previously, a__reversed__
implementation was only added to :class:~bidict.BidictBase
whenBidictBase._fwdm_cls
was :class:~collections.abc.Reversible
. 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 :class:
~collections.abc.MappingView
objects returned by :meth:bidict.OrderedBidict.keys
, :meth:bidict.OrderedBidict.values
, and :meth:bidict.OrderedBidict.items
are now :class:~collections.abc.Reversible
. (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 <https://www.python.org/dev/peps/pep-0584/>
__).
See
the tests <https://github.com/jab/bidict/blob/main/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 <collections.abc.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 <https://github.com/pypa/setuptools_scm>
__ as asetup_requires
dependency.🔖 Remove the
bidict.__version_info__
attribute.
- All bidicts now provide the :meth:
-
v0.21.2 Changes
September 07, 2020🚀 Please see https://bidict.readthedocs.io/en/v0.21.2/changelog.html 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 providestype hints <https://www.python.org/dev/peps/pep-0484/>
__! ⌨️ ✅
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 <https://github.com/python/typing/issues/548#issuecomment-621195693>
), too-narrow type hints for :class:collections.abc.Mapping
(python/typeshed#4435 <https://github.com/python/typeshed/issues/4435>
), a :class:typing.Generic
bug in Python 3.6 (BPO-41451 <https://bugs.python.org/issue41451>
__), 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 <https://pypistats.org/packages/bidict>
, and lacks support forvariable type hint syntax <https://www.python.org/dev/peps/pep-0526/>
,ordered dicts <https://stackoverflow.com/a/39980744>
, 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 areverse
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 providedbase_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.
- :mod:
-
v0.20.0 Changes
July 23, 2020The following breaking changes are expected to affect few if any users.
✂ Remove APIs deprecated in the previous release:
bidict.OVERWRITE
andbidict.IGNORE
.The
on_dup_key
,on_dup_val
, andon_dup_kv
arguments of :meth:~bidict.bidict.put
and :meth:~bidict.bidict.putall
.The
on_dup_key
,on_dup_val
, andon_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 :class:collections.abc.Mapping
.#111 <https://github.com/jab/bidict/issues/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
andbidict.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
, andon_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
, andon_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__init__.py
.
- ⬇️ Drop support for Python 2
:ref:
-
v0.18.4 Changes
November 03, 2020🚀 Please see https://bidict.readthedocs.io/en/v0.18.4/changelog.html#id1 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 providedtypename
argument.