You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
77 lines
3.1 KiB
77 lines
3.1 KiB
# Copyright 2009-2022 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/. |
|
|
|
|
|
# * Code review nav * |
|
# (see comments in __init__.py) |
|
#============================================================================== |
|
# ← Prev: __init__.py Current: _abc.py Next: _base.py → |
|
#============================================================================== |
|
|
|
|
|
"""Provide the :class:`BidirectionalMapping` abstract base class.""" |
|
|
|
from __future__ import annotations |
|
from abc import abstractmethod |
|
import typing as t |
|
|
|
from ._typing import KT, VT |
|
|
|
|
|
class BidirectionalMapping(t.Mapping[KT, VT]): |
|
"""Abstract base class for bidirectional mapping types. |
|
|
|
Extends :class:`collections.abc.Mapping` primarily by adding the |
|
(abstract) :attr:`inverse` property, |
|
which implementors of :class:`BidirectionalMapping` |
|
should override to return a reference to the inverse |
|
:class:`BidirectionalMapping` instance. |
|
""" |
|
|
|
__slots__ = () |
|
|
|
@property |
|
@abstractmethod |
|
def inverse(self) -> BidirectionalMapping[VT, KT]: |
|
"""The inverse of this bidirectional mapping instance. |
|
|
|
*See also* :attr:`bidict.BidictBase.inverse`, :attr:`bidict.BidictBase.inv` |
|
|
|
:raises NotImplementedError: Meant to be overridden in subclasses. |
|
""" |
|
# The @abstractmethod decorator prevents BidirectionalMapping subclasses from being |
|
# instantiated unless they override ``.inverse``. So this implementation of ``.inverse`` |
|
# should never be unintentionally resolved from subclass instances. But raise here |
|
# anyway, so it's extra clear that this implementation should never be called. |
|
raise NotImplementedError |
|
|
|
def __inverted__(self) -> t.Iterator[tuple[VT, KT]]: |
|
"""Get an iterator over the items in :attr:`inverse`. |
|
|
|
This is functionally equivalent to iterating over the items in the |
|
forward mapping and inverting each one on the fly, but this provides a |
|
more efficient implementation: Assuming the already-inverted items |
|
are stored in :attr:`inverse`, just return an iterator over them directly. |
|
|
|
Providing this default implementation enables external functions, |
|
particularly :func:`~bidict.inverted`, to use this optimized |
|
implementation when available, instead of having to invert on the fly. |
|
|
|
*See also* :func:`bidict.inverted` |
|
""" |
|
return iter(self.inverse.items()) |
|
|
|
|
|
class MutableBidirectionalMapping(BidirectionalMapping[KT, VT], t.MutableMapping[KT, VT]): |
|
"""Abstract base class for mutable bidirectional mapping types.""" |
|
|
|
__slots__ = () |
|
|
|
|
|
# * Code review nav * |
|
#============================================================================== |
|
# ← Prev: __init__.py Current: _abc.py Next: _base.py → |
|
#==============================================================================
|
|
|