Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def test_namedbidict(base_type, init_items, data):
"""Test the :func:`bidict.namedbidict` factory and custom accessors."""
names = typename, keyname, valname = [data.draw(H_NAMES) for _ in range(3)]
try:
nbcls = namedbidict(typename, keyname, valname, base_type=base_type)
except ValueError:
# Either one of the names was invalid, or the keyname and valname were not distinct.
assert not all(map(NAMEDBIDICT_VALID_NAME.match, names)) or keyname == valname
return
except TypeError:
# The base type must not have been a BidirectionalMapping.
assert not issubclass(base_type, BidirectionalMapping)
return
assume(init_items)
instance = nbcls(init_items)
valfor = getattr(instance, valname + '_for')
keyfor = getattr(instance, keyname + '_for')
assert all(valfor[key] == val for (key, val) in iteritems(instance))
assert all(keyfor[val] == key for (key, val) in iteritems(instance))
# The same custom accessors should work on the inverse.
inv = instance.inv
valfor = getattr(inv, valname + '_for')
keyfor = getattr(inv, keyname + '_for')
assert all(valfor[key] == val for (key, val) in iteritems(instance))
assert all(keyfor[val] == key for (key, val) in iteritems(instance))
def test_bidi_mapping_subclasshook():
"""Ensure issubclass(foo, BidirectionalMapping) works as expected."""
assert issubclass(MyBidirectionalMapping, BidirectionalMapping)
assert not issubclass(dict, BidirectionalMapping)
# Make sure this works with old-style classes as expected.
assert not issubclass(OldStyleClass, BidirectionalMapping)
class VirtualBimapSubclass(Mapping): # pylint: disable=abstract-method
"""Dummy type that implements the BidirectionalMapping interface
without explicitly extending it, and so should still be considered a
(virtual) subclass if the BidirectionalMapping ABC is working correctly.
(See :meth:`BidirectionalMapping.__subclasshook__`.)
(Not actually a *working* BidirectionalMapping implementation,
but doesn't need to be for the purposes of this test.)
"""
inverse = NotImplemented
class AbstractBimap(BidirectionalMapping): # pylint: disable=abstract-method
"""Dummy type that explicitly extends BidirectionalMapping
but fails to provide a concrete implementation for the
:attr:`BidirectionalMapping.inverse` :func:`abc.abstractproperty`.
As a result, attempting to create an instance of this class
should result in ``TypeError: Can't instantiate abstract class
AbstractBimap with abstract methods inverse``
"""
__getitem__ = NotImplemented
__iter__ = NotImplemented
__len__ = NotImplemented
BIDICT_TYPES = (bidict, frozenbidict, FrozenOrderedBidict, OrderedBidict)
BIMAP_TYPES = BIDICT_TYPES + (VirtualBimapSubclass, AbstractBimap)
def test_issubclass_bimap(bi_cls):
"""All bidict types should subclass :class:`BidirectionalMapping`,
and any class conforming to the interface (e.g. VirtualBimapSubclass)
should be considered a (virtual) subclass too.
"""
assert issubclass(bi_cls, BidirectionalMapping)
def test_bidi_mapping_subclasshook():
"""Ensure issubclass(foo, BidirectionalMapping) works as expected."""
assert issubclass(MyBidirectionalMapping, BidirectionalMapping)
assert not issubclass(dict, BidirectionalMapping)
# Make sure this works with old-style classes as expected.
assert not issubclass(OldStyleClass, BidirectionalMapping)
To compute a frozenbidict's hash value, a temporary frozenset is
constructed out of the frozenbidict's items, and the hash of the frozenset
is returned. So be aware that computing a frozenbidict's hash is not
a constant-time or -space operation.
To mitigate this, the hash is computed lazily, only when ``__hash__`` is
first called, and is then cached so that future calls take constant time.
'''
def __hash__(self):
if self._hash is None:
self._hash = hash(frozenset(viewitems(self)))
return self._hash
class bidict(BidirectionalMapping, MutableMapping):
'''
Extends :class:`bidict.BidirectionalMapping` to implement the
``MutableMapping`` interface. The API is a superset of the ``dict`` API
minus the ``fromkeys`` method, which doesn't make sense for a bidirectional
mapping because keys *and* values must be unique.
Examples::
>>> keys = (1, 2, 3)
>>> vals = ('one', 'two', 'three')
>>> bi = bidict(zip(keys, vals))
>>> bi == bidict({1: 'one', 2: 'two', 3: 'three'})
True
>>> bidict(inverted(bi)) == bidict(zip(vals, keys))
True
iterkeys = lambda self: self._fwd.iterkeys()
viewkeys = lambda self: self._fwd.viewkeys()
iteritems = lambda self: self._fwd.iteritems()
viewitems = lambda self: self._fwd.viewitems()
itervalues = lambda self: self._bwd.iterkeys()
viewvalues = lambda self: self._bwd.viewkeys()
iterkeys.__doc__ = dict.iterkeys.__doc__
viewkeys.__doc__ = dict.viewkeys.__doc__
iteritems.__doc__ = dict.iteritems.__doc__
viewitems.__doc__ = dict.viewitems.__doc__
itervalues.__doc__ = dict.itervalues.__doc__
viewvalues.__doc__ = values.__doc__.replace('values()', 'viewvalues()')
values.__doc__ = dict.values.__doc__
class frozenbidict(BidirectionalMapping, Hashable):
'''
Extends ``BidirectionalMapping`` and ``Hashable`` to provide an immutable,
hashable bidict. It's immutable simply because it doesn't implement any
mutating methods::
>>> f = frozenbidict()
>>> f.update(H='hydrogen') # doctest: +ELLIPSIS
Traceback (most recent call last):
...
AttributeError...
>>> f['C'] = 'carbon' # doctest: +ELLIPSIS
Traceback (most recent call last):
...
TypeError...
And, unlike ``BidirectionalMapping`` and ``bidict``, it's hashable simply