bidict/tests/test_bidict.txt

241 lines
5.5 KiB
Plaintext
Raw Normal View History

2021-01-01 17:14:24 +00:00
# Copyright 2009-2021 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 http://mozilla.org/MPL/2.0/.
Test script for bidict.bidict::
>>> from bidict import bidict
>>> keys = (1, 2, 3)
>>> vals = ('one', 'two', 'three')
>>> bi = bidict(zip(keys, vals))
>>> bi == bidict({1: 'one', 2: 'two', 3: 'three'})
True
Works like dict for getting and changing forward mappings::
>>> bi[2]
'two'
>>> bi[2] = 'twain'
>>> bi[2]
'twain'
>>> bi[4]
Traceback (most recent call last):
...
KeyError: 4
>>> del bi[2]
>>> bi.pop(3)
'three'
>>> bi
bidict({1: 'one'})
``put`` can also be used to insert a mapping as long as its key and value
don't already exist::
>>> bi.put(0, 'zero')
>>> bi[0]
'zero'
>>> bi.put(1, 'aught')
Traceback (most recent call last):
...
2016-06-28 04:05:22 +00:00
KeyDuplicationError: 1
>>> del bi[1]
>>> bi.put(1, 'aught')
>>> bi[1]
'aught'
>>> del bi[0]
>>> bi
bidict({1: 'aught'})
bidicts maintain references to their inverses via the ``inv`` property,
which can also be used to access or modify them::
>>> bi.inv
bidict({'aught': 1})
>>> bi.inv['aught']
1
>>> bi.inv['aught'] = 'one'
>>> bi
bidict({'one': 'aught'})
>>> bi.inv.pop('aught')
'one'
2016-06-28 04:05:22 +00:00
>>> bi == bi.inv == bidict()
True
>>> bi.inv.update(one=1)
>>> bi
bidict({1: 'one'})
>>> bi is bi.inv.inv
True
>>> bi.inv is bi.inv.inv.inv
True
bidicts work with ``inverted`` as expected::
>>> from bidict import inverted
>>> biinv = bidict(inverted(bi))
>>> biinv
bidict({'one': 1})
This created a new object (equivalent but not identical)::
>>> biinv == bi.inv
True
>>> biinv is bi.inv
False
Inverting the inverse should round-trip::
>>> bi == bidict(inverted(inverted(bi)))
True
>>> bi = bi.inv
>>> bi == bidict(inverted(inverted(bi)))
True
The rest of the ``MutableMapping`` interface is supported::
>>> bi.get('one')
1
>>> bi.get('zero')
>>> bi.get('zero', 'default')
'default'
>>> list(bi.keys())
['one']
>>> list(bi.values())
[1]
>>> list(bi.items())
[('one', 1)]
>>> bi.setdefault('one', 2)
1
>>> bi.setdefault('two', 2)
2
>>> bi.pop('one')
1
>>> bi
bidict({'two': 2})
>>> bi.inv
bidict({2: 'two'})
>>> bi.pop('wrong', 'number', 'of', 'args')
Traceback (most recent call last):
...
TypeError: pop expected at most 2 arguments (got 4)
>>> bi.popitem()
('two', 2)
>>> bi.popitem()
Traceback (most recent call last):
...
KeyError: 'popitem(): bidict is empty'
>>> bi.inv.setdefault(3, 'three')
'three'
>>> bi
bidict({'three': 3})
>>> len(bi) # calls __len__
1
>>> [key for key in bi] # calls __iter__, returns keys like dict
['three']
>>> 'three' in bi # calls __contains__
True
>>> list(bi.keys())
['three']
>>> list(bi.values())
[3]
>>> bi.update([('four', 4)])
>>> bi.update({'five': 5}, six=6, seven=7)
>>> sorted(bi.items(), key=lambda x: x[1])
[('three', 3), ('four', 4), ('five', 5), ('six', 6), ('seven', 7)]
>>> bi.clear()
>>> bi
bidict()
Empty update is a no-op::
>>> bi.update()
>>> bi
bidict()
2018-02-19 07:53:03 +00:00
Not part of the public API, but test this anyway for the coverage::
>>> bi._update(False, None)
2018-02-19 07:53:03 +00:00
>>> bi
bidict()
Initializing with different keys mapping to the same value fails::
2015-11-25 06:36:41 +00:00
>>> bidict([(1, 1), (2, 1)])
2015-11-25 06:36:41 +00:00
Traceback (most recent call last):
...
2016-06-28 04:05:22 +00:00
ValueDuplicationError: 1
2015-11-25 06:36:41 +00:00
Adding a new key associated with an existing value fails::
>>> b = bidict({1: 1})
>>> b[2] = 1
2015-11-25 06:36:41 +00:00
Traceback (most recent call last):
...
2016-06-28 04:05:22 +00:00
ValueDuplicationError: 1
>>> b.update({2: 1})
Traceback (most recent call last):
...
2016-06-28 04:05:22 +00:00
ValueDuplicationError: 1
``forceput`` and ``forceupdate`` can be used instead::
>>> b.forceput(2, 1)
>>> b
bidict({2: 1})
>>> b.forceupdate({1: 1})
>>> b
bidict({1: 1})
2015-11-25 06:36:41 +00:00
Trying to insert an existing mapping does not raise, and is a no-op::
>>> b = bidict({1: 'one'})
>>> b[1] = 'one'
>>> b[1]
'one'
>>> b.inv['one'] = 1
>>> b.inv['one']
1
The following case does not half-succeed,
i.e. the bidict is not in an inconsistent state after::
>>> b = bidict(one=1, two=2)
>>> b['one'] = 2
Traceback (most recent call last):
...
2016-06-28 04:05:22 +00:00
KeyAndValueDuplicationError: ('one', 2)
>>> len(b) == len(b.inv)
True
2016-06-28 04:05:22 +00:00
``put`` and ``putall`` allow you to have
per-call control over duplication behavior
2016-06-28 04:05:22 +00:00
(see doctests in ``../docs/unique-values.rst.inc``).
Even with RAISE duplication behavior,
2016-06-28 04:05:22 +00:00
inserting existing items is a no-op (i.e. it doesn't raise)::
Various API changes and other improvements. * 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`). A :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, a named (*key*, *val*, *kv*) tuple of :class:`~bidict.OnDupAction`\s that should be taken upon encountering the 3 kinds of duplication that can occur. * 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. They 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=DROP_NEW))``. Or better yet, pass one of the ``ON_DUP_*`` convenience instances instead if possible. See the updated :ref:`basic-usage:Values Must Be Unique` docs for more info. * Deprecate the ``on_dup_key``, ``on_dup_val``, and ``on_dup_kv`` bidict class attributes. A :class:`UserWarning` will now be emitted if these are used. They 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. * Move :meth:`bidict.BidictBase.values` to :meth:`bidict.BidirectionalMapping.values`, since the implementation is generic. * No longer use ``__all__`` in ``bidict/__init__.py``. * Cap max_size rather than disabling health checks and deadline as a less heavyhanded way to improve hypothesis test reliability on Travis.
2020-01-07 22:20:20 +00:00
>>> from bidict import RAISE, OnDup
>>> b.putall(
... [('three', 3), ('one', 1)],
... OnDup(key=RAISE, val=RAISE)
2020-07-26 17:21:27 +00:00
... ) # does not raise an error because these items were already contained
>>> b0 = b.copy()
>>> b.putall([]) # no-op
>>> b == b0
True
2017-11-29 01:56:50 +00:00
2019-09-03 14:26:35 +00:00
Make sure copy.copy and copy.deepcopy create shallow and deep copies, respectively::
>>> from copy import copy, deepcopy
>>> from bidict import frozenbidict
>>> b = frozenbidict({1: frozenbidict()})
>>> c = copy(b)
>>> d = deepcopy(b)
>>> b == c == d
True
>>> b[1] is c[1]
True
>>> b[1] is d[1]
False