diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 3a45a8d..ea8395a 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -3,6 +3,7 @@ name: pre-commit push: branches: - main + - dev pull_request: branches: - main diff --git a/.pylintrc b/.pylintrc index c750be3..eeb1929 100644 --- a/.pylintrc +++ b/.pylintrc @@ -16,8 +16,8 @@ max-args = 6 disable = abstract-method, arguments-differ, + assigning-non-slot, # pylint does not understand descriptors like WeakAttr in _orderedbase.py attribute-defined-outside-init, - class-variable-slots-conflict, # pylint does not understand descriptors like WeakAttr in _orderedbase.py invalid-name, line-too-long, missing-function-docstring, # flags @typing.overload's diff --git a/bidict/_base.py b/bidict/_base.py index 7458a6e..9c24111 100644 --- a/bidict/_base.py +++ b/bidict/_base.py @@ -47,12 +47,6 @@ dict_keys: t.Type[t.KeysView[t.Any]] = type({}.keys()) BidictKeysView.register(dict_keys) -# See _set_reversed() below. -def _fwdm_reversed(self: t.Any) -> t.Iterator[KT]: - """Iterator over the contained keys in reverse order.""" - return reversed(self._fwdm) - - def get_arg(*args: MapOrIterItems[KT, VT]) -> MapOrIterItems[KT, VT]: """Ensure there's only a single arg in *args*, then return it.""" if len(args) > 1: @@ -127,17 +121,17 @@ class BidictBase(BidirectionalMapping[KT, VT]): cls._inv_cls = cls._make_inv_cls() @classmethod - def _make_inv_cls(cls, _miss: t.Any = object()) -> 't.Type[BidictBase[VT, KT]]': + def _make_inv_cls(cls: t.Type[BT], _miss: t.Any = object()) -> 't.Type[BT]': diff = cls._inv_cls_dict_diff() cls_is_own_inv = all(getattr(cls, k, _miss) == v for (k, v) in diff.items()) if cls_is_own_inv: - return t.cast(t.Type[BidictBase[VT, KT]], cls) + return cls # Suppress auto-calculation of _inv_cls's _inv_cls since we know it already. # Works with the guard in BidictBase._ensure_inv_cls() to prevent infinite recursion. diff['_inv_cls'] = cls inv_cls = type(f'{cls.__name__}Inv', (cls, GeneratedBidictInverse), diff) inv_cls.__module__ = cls.__module__ - return inv_cls + return t.cast(t.Type[BT], inv_cls) @classmethod def _inv_cls_dict_diff(cls) -> t.Dict[str, t.Any]: @@ -537,6 +531,13 @@ class BidictBase(BidirectionalMapping[KT, VT]): return self._from_other, (cls, dict(init_from), should_invert) # type: ignore [call-overload] # https://github.com/python/mypy/issues/4975 +# See BidictBase._set_reversed() above. +def _fwdm_reversed(self: BidictBase[KT, t.Any]) -> t.Iterator[KT]: + """Iterator over the contained keys in reverse order.""" + assert isinstance(self._fwdm, t.Reversible) + return reversed(self._fwdm) + + BidictBase._init_class() diff --git a/bidict/_dup.py b/bidict/_dup.py index 51a7803..2ce937a 100644 --- a/bidict/_dup.py +++ b/bidict/_dup.py @@ -8,8 +8,8 @@ """Provide :class:`OnDup` and related functionality.""" -from collections import namedtuple from enum import Enum +import typing as t class OD(Enum): @@ -31,7 +31,7 @@ DROP_OLD = OD.DROP_OLD DROP_NEW = OD.DROP_NEW -class OnDup(namedtuple('_OnDup', 'key val kv')): +class OnDup(t.NamedTuple('_OnDup', [('key', OD), ('val', OD), ('kv', OD)])): r"""A 3-tuple of :class:`OD`\s specifying how to handle the 3 kinds of duplication. *See also* :ref:`basic-usage:Values Must Be Unique` @@ -42,7 +42,7 @@ class OnDup(namedtuple('_OnDup', 'key val kv')): __slots__ = () - def __new__(cls, key: OD = DROP_OLD, val: OD = RAISE, kv: OD = RAISE) -> 'OnDup': + def __new__(cls, key: OD = DROP_OLD, val: OD = RAISE, kv: t.Optional[OD] = None) -> 'OnDup': """Override to provide user-friendly default values.""" return super().__new__(cls, key, val, kv or val) diff --git a/bidict/_orderedbase.py b/bidict/_orderedbase.py index e33adca..1c273a5 100644 --- a/bidict/_orderedbase.py +++ b/bidict/_orderedbase.py @@ -56,8 +56,6 @@ class Node: prv: 'WeakAttr[Node, Node]' = WeakAttr(slot='_prv_weak') __slots__ = ('_prv_weak', 'nxt', '__weakref__') - if t.TYPE_CHECKING: # no 'prv' in __slots__ makes mypy think we don't have a 'prv' attr, so trick it: - __slots__ = ('prv', 'nxt', '__weakref__') def __init__(self, prv: 'Node', nxt: 'Node') -> None: self.prv = prv