summaryrefslogtreecommitdiffhomepage
path: root/libs/bidict/_abc.py
blob: c1bdf6e32e6939badb964a91f18bc59d3855f6d8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# 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."""

import typing as t
from abc import abstractmethod

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[t.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 →
#==============================================================================