Changelog History
Page 3
-
v0.15.0 Changes
March 29, 2018Speedups and memory usage improvements ++++++++++++++++++++++++++++++++++++++
๐ Use :ref:
slots
to speed up bidict attribute access and reduce memory usage. On Python 3, instantiating a large number of bidicts now uses ~57% the amount of memory that it used before, and on Python 2 only ~33% the amount of memory that it used before, in a simple but representativebenchmark <https://github.com/jab/bidict/pull/56#issuecomment-368203591>
__.๐ Use weakrefs to refer to a bidict's inverse internally, no longer creating a strong reference cycle. Memory for a bidict that you create can now be reclaimed in CPython as soon as you no longer hold any references to it, rather than having to wait for the next garbage collection. See the new :ref:
addendum:Bidict Avoids Reference Cycles
documentation.#24 <https://github.com/jab/bidict/issues/20>
__Make :func:
bidict.BidictBase.__eq__
significantly more speed- and memory-efficient when comparing to a non-:class:dict
:class:~collections.abc.Mapping
. (Mapping.__eq__()
\'s inefficient implementation will now never be used.) The implementation is now more reusable as well.Make :func:
bidict.OrderedBidictBase.__iter__
as well as equality comparison slightly faster for ordered bidicts.
๐ Minor Bugfixes ++++++++++++++
:func:
~bidict.namedbidict
now verifies that the providedkeyname
andvalname
are distinct, raising :class:ValueError
if they are equal.:func:
~bidict.namedbidict
now raises :class:TypeError
if the providedbase_type
is not a :class:~bidict.BidirectionalMapping
.If you create a custom bidict subclass whose
_fwdm_cls
differs from its_invm_cls
(as in theFwdKeySortedBidict
example from the :ref:extending:Sorted Bidict Recipes
), the inverse bidirectional mapping type (with_fwdm_cls
and_invm_cls
swapped) is now correctly computed and used automatically for your custom bidict's :attr:~bidict.BidictBase.inverse
bidict.
Miscellaneous +++++++++++++
Classes no longer have to provide an
__inverted__
attribute to be considered virtual subclasses of :class:~bidict.BidirectionalMapping
.If :func:
bidict.inverted
is passed an object with an__inverted__
attribute, it now ensures it is :func:callable
before returning the result of calling it.:func:
~bidict.BidictBase.__repr__
no longer checks for a__reversed__
method to determine whether to use an ordered or unordered-style repr. It now calls the new__repr_delegate__
instead (which may be overridden if needed), for better composability.
Minor Breaking API Changes ++++++++++++++++++++++++++
The following breaking changes are expected to affect few if any users.
- Split back out the :class:
~bidict.BidictBase
class from :class:~bidict.frozenbidict
and :class:~bidict.OrderedBidictBase
from :class:~bidict.FrozenOrderedBidict
, reverting the merging of these in 0.14.0. Having e.g.issubclass(bidict, frozenbidict) == True
was confusing, so this change restoresissubclass(bidict, frozenbidict) == False
.
See the updated :ref:
other-bidict-types:Bidict Types Diagram
and :ref:other-bidict-types:Polymorphism
documentation.๐ Rename:
bidict.BidictBase.fwdm
โ._fwdm
bidict.BidictBase.invm
โ._invm
bidict.BidictBase.fwd_cls
โ._fwdm_cls
bidict.BidictBase.inv_cls
โ._invm_cls
bidict.BidictBase.isinv
โ._isinv
Though overriding
_fwdm_cls
and_invm_cls
remains supported (see :doc:extending
), this is not a common enough use case to warrant public names. Most users do not need to know or care about any of these.The :attr:
~bidict.RAISE
, :attr:~bidict.OVERWRITE
, and :attr:~bidict.IGNORE
duplication policies are no longer available as attributes of :class:bidict.DuplicationPolicy
, and can now only be accessed as attributes of the :mod:bidict
module namespace, which was the canonical way to refer to them anyway. It is now no longer possible to create an infinite chain likeDuplicationPolicy.RAISE.RAISE.RAISE...
๐ Make
bidict.pairs()
and :func:bidict.inverted
no longer importable frombidict.util
, and now only importable from the top-level :mod:bidict
module. (bidict.util
was renamedbidict._util
.)Pickling ordered bidicts now requires at least version 2 of the pickle protocol. If you are using Python 3, :attr:
pickle.DEFAULT_PROTOCOL
is 3 anyway, so this will not affect you. However if you are using in Python 2, :attr:~pickle.DEFAULT_PROTOCOL
is 0, so you must now explicitly specify the version in your :func:pickle.dumps
calls, e.g.pickle.dumps(ob, 2)
.
-
v0.14.2 Changes
December 06, 2017โก๏ธ Make initializing (or updating an empty bidict) from only another :class:
~bidict.BidirectionalMapping
more efficient by skipping unnecessary duplication checking.๐ Fix accidental ignoring of specified
base_type
argument when (un)pickling a :func:~bidict.namedbidict
.๐ Fix incorrect inversion of
some_named_bidict.inv.<fwdname>_for
andsome_named_bidict.inv.<invname>_for
.๐ Only warn when an unsupported Python version is detected (e.g. Python < 2.7) rather than raising :class:
AssertionError
.
-
v0.14.1 Changes
November 28, 2017๐ Fix a bug introduced in 0.14.0 where hashing a :class:
~bidict.frozenbidict
\โs inverse (e.g.f = frozenbidict(); {f.inv: '...'}
) would cause anAttributeError
.๐ Fix a bug introduced in 0.14.0 for Python 2 users where attempting to call
viewitems()
would cause aTypeError
.#48 <https://github.com/jab/bidict/issues/48>
__
-
v0.14.0 Changes
November 20, 2017๐ Fix a bug where :class:
~bidict.bidict
\โs default on_dup_kv policy was set to :attr:~bidict.RAISE
, rather than matching whatever on_dup_val policy was in effect as was :ref:documented <basic-usage:Key and Value Duplication>
.๐ Fix a bug that could happen when using Python's optimization (
-O
) flag that could leave an ordered bidict in an inconsistent state when dealing with duplicated, overwritten keys or values. If you do not use optimizations (specifically, skippingassert
statements), this would not have affected you.๐ Fix a bug introduced by the optimizations in 0.13.0 that could cause a frozen bidict that compared equal to another mapping to have a different hash value from the other mapping, violating Python's object model. This would only have affected you if you were inserting a frozen bidict and some other immutable mapping that it compared equal to into the same set or mapping.
Add :meth:
~bidict.OrderedBidictBase.equals_order_sensitive
.โฌ๏ธ Reduce the memory usage of ordered bidicts.
๐ Make copying of ordered bidicts faster.
๐ Improvements to tests and CI, including:
- Test on Windows
- Test with PyPy3
- Test with CPython 3.7-dev
- Test with optimization flags
- Require pylint to pass
๐ฅ Breaking API Changes ++++++++++++++++++++
๐ This release includes multiple API simplifications and improvements.
๐ Rename:
orderedbidict
โ :class:~bidict.OrderedBidict
frozenorderedbidict
โ :class:~bidict.FrozenOrderedBidict
so that these now match the case of :class:
collections.OrderedDict
.The names of the :class:
~bidict.bidict
, :func:~bidict.namedbidict
, and :class:~bidict.frozenbidict
classes have been retained as all-lowercase so that they continue to match the case of :class:dict
, :func:~collections.namedtuple
, and :class:frozenset
, respectively.The
ON_DUP_VAL
duplication policy value for on_dup_kv has been removed. UseNone
instead.๐ Merge :class:
~bidict.frozenbidict
andBidictBase
together and removeBidictBase
. :class:~bidict.frozenbidict
is now the concrete base class that all other bidict types derive from. See the updated :ref:other-bidict-types:Bidict Types Diagram
.๐ Merge :class:
~bidict.frozenbidict
andFrozenBidictBase
together and removeFrozenBidictBase
. See the updated :ref:other-bidict-types:Bidict Types Diagram
.๐ Merge
frozenorderedbidict
andOrderedBidictBase
together into a single :class:~bidict.FrozenOrderedBidict
class and removeOrderedBidictBase
. :class:~bidict.OrderedBidict
now extends :class:~bidict.FrozenOrderedBidict
to add mutable behavior. See the updated :ref:other-bidict-types:Bidict Types Diagram
.Make :meth:
~bidict.OrderedBidictBase.__eq__
always perform an order-insensitive equality test, even if the other mapping is ordered.
Previously, :meth:
~bidict.OrderedBidictBase.__eq__
was only order-sensitive for otherOrderedBidictBase
subclasses, and order-insensitive otherwise.Use the new :meth:
~bidict.OrderedBidictBase.equals_order_sensitive
method for order-sensitive equality comparison.orderedbidict._should_compare_order_sensitive()
has been removed.frozenorderedbidict._HASH_NITEMS_MAX
has been removed. Since its hash value must be computed from all contained items (so that hash results are consistent with equality comparisons against unordered mappings), the number of items that influence the hash value should not be limitable.๐
frozenbidict._USE_ITEMSVIEW_HASH
has been removed, andfrozenbidict.compute_hash()
now usescollections.ItemsView._hash()
to compute the hash always, not just when running on PyPy.
Override
frozenbidict.compute_hash()
to returnhash(frozenset(iteritems(self)))
if you prefer the old default behavior on CPython, which takes linear rather than constant space, but which uses thefrozenset_hash
routine (implemented insetobject.c
) rather than the pure PythonItemsView._hash()
routine.๐
loosebidict
andlooseorderedbidict
have been removed. A simple recipe to implement equivalents yourself is now given in :ref:extending:OverwritingBidict Recipe
.Rename
FrozenBidictBase._compute_hash()
โfrozenbidict.compute_hash()
.๐ Rename
DuplicationBehavior
โ :class:~bidict.DuplicationPolicy
.๐ Rename:
bidict.BidictBase._fwd_class
โ.fwd_cls
bidict.BidictBase._inv_class
โ.inv_cls
bidict.BidictBase._on_dup_key
โ :attr:~bidict.BidictBase.on_dup_key
bidict.BidictBase._on_dup_val
โ :attr:~bidict.BidictBase.on_dup_val
bidict.BidictBase._on_dup_kv
โ :attr:~bidict.BidictBase.on_dup_kv
-
v0.13.1 Changes
March 15, 2017- ๐ Fix regression introduced by the new
:meth:
~bidict.BidirectionalMapping.__subclasshook__
functionality in 0.13.0 so thatissubclass(OldStyleClass, BidirectionalMapping)
once again works with old-style classes, returningFalse
rather than raising :class:AttributeError
#41 <https://github.com/jab/bidict/pull/41>
__
- ๐ Fix regression introduced by the new
:meth:
-
v0.13.0 Changes
January 19, 2017- ๐ Support Python 3.6.
(Earlier versions of bidict should work fine on 3.6, but it is officially supported starting in this version.)
- :class:
~bidict.BidirectionalMapping
has been refactored into an abstract base class, following the way :class:collections.abc.Mapping
works. The concrete method implementations it used to provide have been moved into a newBidictBase
subclass.
:class:
~bidict.BidirectionalMapping
now also implements :meth:~bidict.BidirectionalMapping.__subclasshook__
, so any class that provides a conforming set of attributes (enumerated in :attr:~bidict.BidirectionalMapping._subclsattrs
) will be considered a :class:~bidict.BidirectionalMapping
subclass automatically.OrderedBidirectionalMapping
has been renamed toOrderedBidictBase
, to better reflect its function. (It is not an ABC.)A new
FrozenBidictBase
class has been factored out of :class:~bidict.frozenbidict
and :class:frozenorderedbidict <bidict.FrozenOrderedBidict>
. This implements common behavior such as caching the result of__hash__
after the first call.The hash implementations of :class:
~bidict.frozenbidict
and :class:frozenorderedbidict <bidict.FrozenOrderedBidict>
. have been reworked to improve performance and flexibility. :class:frozenorderedbidict <bidict.FrozenOrderedBidict>
\โs hash implementation is now order-sensitive.
See
frozenbidict._compute_hash()
andfrozenorderedbidict._compute_hash
for more documentation of the changes, including the newfrozenbidict._USE_ITEMSVIEW_HASH
andfrozenorderedbidict._HASH_NITEMS_MAX
attributes. If you have an interesting use case that requires overriding these, or suggestions for an alternative implementation, pleaseshare your feedback <https://gitter.im/jab/bidict>
__.- Add
_fwd_class
and_inv_class
attributes representing the backing :class:~collections.abc.Mapping
types used internally to store the forward and inverse dictionaries, respectively.
This allows creating custom bidict types with extended functionality simply by overriding these attributes in a subclass.
See the new :doc:
extending
documentation for examples.Pass any parameters passed to :meth:
~bidict.bidict.popitem
through to_fwd.popitem
for greater extensibility.More concise repr strings for empty bidicts.
e.g.
bidict()
rather thanbidict({})
andorderedbidict()
rather thanorderedbidict([])
.- โ Add :attr:
bidict.compat.PYPY
and remove unusedbidict.compat.izip_longest
.
-
v0.12.0 Changes
July 03, 2016๐ New/renamed exceptions:
- :class:
~bidict.KeyDuplicationError
- :class:
~bidict.ValueDuplicationError
- :class:
~bidict.KeyAndValueDuplicationError
- :class:
~bidict.DuplicationError
(base class for the above)
- :class:
:func:
~bidict.bidict.put
now acceptson_dup_key
,on_dup_val
, andon_dup_kv
keyword args which allow you to override the default policy when the key or value of a given item duplicates any existing item's. These can take the following values:- :attr:
~bidict.RAISE
- :attr:
~bidict.OVERWRITE
- :attr:
~bidict.IGNORE
- :attr:
on_dup_kv
can also takeON_DUP_VAL
.If not provided, :func:
~bidict.bidict.put
uses the :attr:~bidict.RAISE
policy by default.๐ New :func:
~bidict.bidict.putall
method provides a bulk :func:~bidict.bidict.put
API, allowing you to override the default duplication handling policy that :func:~bidict.bidict.update
uses.โก๏ธ :func:
~bidict.bidict.update
now fails clean, so if an :func:~bidict.bidict.update
call raises a :class:~bidict.DuplicationError
, you can now be sure that none of the given items was inserted.
Previously, all of the given items that were processed before the one causing the failure would have been inserted, and no facility was provided to recover which items were inserted and which weren't, nor to revert any changes made by the failed :func:
~bidict.bidict.update
call. The new behavior makes it easier to reason about and control the effects of failed :func:~bidict.bidict.update
calls.The new :func:
~bidict.bidict.putall
method also fails clean.Internally, this is implemented by storing a log of changes made while an update is being processed, and rolling back the changes when one of them is found to cause an error. This required reimplementing :class:
orderedbidict <bidict.OrderedBidict>
on top of two dicts and a linked list, rather than two OrderedDicts, since :class:~collections.OrderedDict
does not expose its backing linked list.:func:
orderedbidict.move_to_end() <bidict.OrderedBidict.move_to_end>
now works on Python < 3.2 as a result of the new :class:orderedbidict <bidict.OrderedBidict>
implementation.โ Add
- :func:
bidict.compat.viewkeys
- :func:
bidict.compat.viewvalues
- :func:
bidict.compat.iterkeys
- :func:
bidict.compat.itervalues
bidict.compat.izip
bidict.compat.izip_longest
- :func:
to complement the existing :func:
~bidict.compat.iteritems
and :func:~bidict.compat.viewitems
compatibility helpers.More efficient implementations of
bidict.pairs()
, :func:~bidict.inverted
, and :func:~bidict.BidictBase.copy
.Implement :func:
~bidict.BidictBase.__copy__
for use with the :mod:copy
module.๐ Fix issue preventing a client class from inheriting from
loosebidict
.#34 <https://github.com/jab/bidict/issues/34>
__โ Add benchmarking to tests.
โฌ๏ธ Drop official support for CPython 3.3. (It may continue to work, but is no longer being tested.)
๐ฅ Breaking API Changes ++++++++++++++++++++
๐ Rename
KeyExistsException
โ :class:~bidict.KeyDuplicationError
andValueExistsException
โ :class:~bidict.ValueDuplicationError
.When overwriting the key of an existing value in an :class:
orderedbidict <bidict.OrderedBidict>
, the position of the existing item is now preserved, overwriting the key of the existing item in place, rather than moving the item to the end. This now matches the behavior of overwriting the value of an existing key, which has always preserved the position of the existing item. (If inserting an item whose key duplicates that of one existing item and whose value duplicates that of another, the existing item whose value is duplicated is still dropped, and the existing item whose key is duplicated still gets its value overwritten in place, as before.)
For example:
.. code:: python
>>> from bidict import orderedbidict # doctest: +SKIP >>> o = orderedbidict([(0, 1), (2, 3)]) # doctest: +SKIP >>> o.forceput(4, 1) # doctest: +SKIP
previously would have resulted in:
.. code:: python
>>> o # doctest: +SKIP orderedbidict([(2, 3), (4, 1)])
but now results in:
.. code:: python
>>> o # doctest: +SKIP orderedbidict([(4, 1), (2, 3)])
-
v0.11.0 Changes
February 05, 2016โ Add :class:
orderedbidict <bidict.OrderedBidict>
,looseorderedbidict
, and :class:frozenorderedbidict <bidict.FrozenOrderedBidict>
.โ Add :doc:
code-of-conduct
.โฌ๏ธ Drop official support for pypy3. (It still may work but is no longer being tested. Support may be added back once pypy3 has made more progress.)
-
v0.10.0 Changes
December 23, 2015โ Remove several features in favor of keeping the API simpler and the code more maintainable.
0๏ธโฃ In the interest of protecting data safety more proactively, by default bidict now raises an error on attempting to insert a non-unique value, rather than allowing its associated key to be silently overwritten. See discussion in
#21 <https://github.com/jab/bidict/issues/21>
__.๐ New :meth:
~bidict.bidict.forceupdate
method provides a bulk :meth:~bidict.bidict.forceput
operation.๐ Fix bugs in :attr:
~bidict.bidict.pop
and :attr:~bidict.bidict.setdefault
which could leave a bidict in an inconsistent state.
๐ฅ Breaking API Changes ++++++++++++++++++++
Remove
bidict.__invert__
, and with it, support for the~b
syntax. Use :attr:~bidict.BidictBase.inv
instead.#19 <https://github.com/jab/bidict/issues/19>
__โ Remove support for the slice syntax. Use
b.inv[val]
rather thanb[:val]
.#19 <https://github.com/jab/bidict/issues/19>
__โ Remove
bidict.invert
. Use :attr:~bidict.BidictBase.inv
rather than inverting a bidict in place.#20 <https://github.com/jab/bidict/issues/20>
__Raise
ValueExistsException
when attempting to insert a mapping with a non-unique key.#21 <https://github.com/jab/bidict/issues/21>
__๐ Rename
collapsingbidict
โloosebidict
now that it suppressesValueExistsException
rather than the less generalCollapseException
.#21 <https://github.com/jab/bidict/issues/21>
__๐
CollapseException
has been subsumed byValueExistsException
.#21 <https://github.com/jab/bidict/issues/21>
__:meth:
~bidict.bidict.put
now raisesKeyExistsException
when attempting to insert an already-existing key, andValueExistsException
when attempting to insert an already-existing value.
-
v0.10.0.post1 Changes
December 23, 2015- ๐ Minor documentation fixes and improvements.