Skip to content

Commit

Permalink
Initial stab at typing, made it through _abc and _base
Browse files Browse the repository at this point in the history
  • Loading branch information
cjgibson committed Nov 4, 2019
1 parent cd73edd commit f40b1b6
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 65 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ matrix:
allow_failures:
- env: 'TASK=docs-linkcheck INSTALL_EXTRAS=docs'
- env: 'TASK=deploy-if-tag'
## fast_finish causes Travis to sned a useless daily "build pending" email; not worth the noise.
## fast_finish causes Travis to send a useless daily "build pending" email; not worth the noise.

This comment has been minimized.

Copy link
@jab

jab Nov 6, 2019

Owner

(Thanks for the typo fix! :)

# fast_finish: true
include:
# Each job below performs a single task. Setting a per-job "TASK" env var
Expand Down
19 changes: 10 additions & 9 deletions bidict/_abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,13 @@

from abc import abstractmethod
from collections.abc import Mapping
from typing import Any, Type, Mapping as MappingType, Iterator, TypeVar, Tuple, Union

KT = TypeVar('KT')
VT = TypeVar('VT')

class BidirectionalMapping(Mapping): # pylint: disable=abstract-method,no-init

class BidirectionalMapping(MappingType[KT, VT]): # pylint: disable=abstract-method,no-init
"""Abstract base class (ABC) for bidirectional mapping types.
Extends :class:`collections.abc.Mapping` primarily by adding the
Expand All @@ -51,7 +55,7 @@ class BidirectionalMapping(Mapping): # pylint: disable=abstract-method,no-init

@property
@abstractmethod
def inverse(self):
def inverse(self) -> MappingType[VT, KT]:
"""The inverse of this bidirectional mapping instance.
*See also* :attr:`bidict.BidictBase.inverse`, :attr:`bidict.BidictBase.inv`
Expand All @@ -65,7 +69,7 @@ def inverse(self):
# clear there's no reason to call this implementation (e.g. via super() after overriding).
raise NotImplementedError

def __inverted__(self):
def __inverted__(self) -> Iterator[Tuple[VT, KT]]:
"""Get an iterator over the items in :attr:`inverse`.
This is functionally equivalent to iterating over the items in the
Expand All @@ -82,7 +86,7 @@ def __inverted__(self):
return iter(self.inverse.items())

@classmethod
def __subclasshook__(cls, C): # noqa: N803 (argument name should be lowercase)
def __subclasshook__(cls, C: 'Type[BidirectionalMapping[Any, Any]]') -> Union[bool, 'NotImplemented']: # noqa: N803 (argument name should be lowercase)

This comment has been minimized.

Copy link
@jab

jab Nov 6, 2019

Owner

Shouldn't C's type be type here, since any type can get passed into __subclasshook__? For example, issubclass(int, BidirectionalMapping) results in int getting passed in as the value of C.

This comment has been minimized.

Copy link
@cjgibson

cjgibson Nov 7, 2019

Author

Yep - good catch!

"""Check if *C* is a :class:`~collections.abc.Mapping`
that also provides an ``inverse`` attribute,
thus conforming to the :class:`BidirectionalMapping` interface,
Expand All @@ -91,12 +95,9 @@ def __subclasshook__(cls, C): # noqa: N803 (argument name should be lowercase)
"""
if cls is not BidirectionalMapping: # lgtm [py/comparison-using-is]
return NotImplemented
if not Mapping.__subclasshook__(C):
return NotImplemented
mro = getattr(C, '__mro__', None)
if mro is None: # Python 2 old-style class

This comment has been minimized.

Copy link
@jab

jab Nov 8, 2019

Owner

Another Python 2 vestige I missed in #99, thanks for catching! Will fix on master separately. Thanks for putting up with rebasing 😊

if not Mapping.__subclasshook__(C): # type: ignore
return NotImplemented
if not any(B.__dict__.get('inverse') for B in mro):
if not any(B.__dict__.get('inverse') for B in C.__mro__):
return NotImplemented
return True

Expand Down
Loading

0 comments on commit f40b1b6

Please sign in to comment.