Skip to content

Commit

Permalink
PEP 561 x 2.
Browse files Browse the repository at this point in the history
This commit by best macOS package manager ever @harens is the next in a
commit chain rendering `beartype` compliant with PEP 561 by annotating
the codebase in a manner specifically compatible with the most popular
third-party static type checker, mypy, en-route to eventually resolving
issue #25 kindly submitted also by best macOS package manager ever
@harens. Specifically, this commit further reduces the number of pending
mypy violations from 155 to 98. Thanks a meteoric load of scalding
silicates, @harens!
  • Loading branch information
harens committed Feb 17, 2021
1 parent e2144fe commit 4944835
Show file tree
Hide file tree
Showing 26 changed files with 62 additions and 37 deletions.
1 change: 1 addition & 0 deletions beartype/_cave/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@

# ....................{ IMPORTS }....................
from abc import ABCMeta, abstractmethod
from typing import Union

# See the "beartype.__init__" submodule for further commentary.
__all__ = ['STAR_IMPORTS_CONSIDERED_HARMFUL']
Expand Down
6 changes: 4 additions & 2 deletions beartype/_cave/mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
)
from beartype._util.hint.nonpep.utilhintnonpeptest import (
die_unless_hint_nonpep)
from typing import Union, Optional

# See the "beartype.__init__" submodule for further commentary.
__all__ = ['STAR_IMPORTS_CONSIDERED_HARMFUL']
Expand Down Expand Up @@ -94,7 +95,7 @@ def __setitem__(self, key: object, value: object) -> None:
'{!r} externally immutable (i.e., not settable).'.format(self))


def __missing__(self, hint: (type, tuple)) -> tuple:
def __missing__(self, hint: Union[type, str, tuple]) -> tuple:
'''
Dunder method explicitly called by the superclass
:meth:`dict.__getitem__` method implicitly called on getting the passed
Expand Down Expand Up @@ -151,12 +152,13 @@ def __missing__(self, hint: (type, tuple)) -> tuple:
)

# Tuple of types to be cached and returned by this call.
hint_or_none = None
hint_or_none: Optional[tuple] = None

# If this key is a type...
if isinstance(hint, type):
# If this type is "NoneType", reuse the existing "_NoneTypes" tuple
# containing only this type.
# I don't think mypy recognises _NoneType as None, and so gets confused
if hint is _NoneType:
hint_or_none = _NoneTypes
# Else, this type is *NOT* "NoneType". In this case, instantiate a
Expand Down
4 changes: 2 additions & 2 deletions beartype/_decor/_code/_pep/_pephint.py
Original file line number Diff line number Diff line change
Expand Up @@ -1729,7 +1729,7 @@
from beartype._util.py.utilpyversion import IS_PYTHON_AT_LEAST_3_8
from beartype._util.text.utiltextmunge import replace_str_substrs
from itertools import count
from typing import Generic, NoReturn
from typing import Set, Generic, Tuple, NoReturn, Optional

# See the "beartype.__init__" submodule for further commentary.
__all__ = ['STAR_IMPORTS_CONSIDERED_HARMFUL']
Expand Down Expand Up @@ -1862,7 +1862,7 @@
# ....................{ CODERS }....................
@callable_cached
def pep_code_check_hint(hint: object) -> (
'Tuple[str, bool, Optional[Set[str]]'):
Tuple[str, bool, Optional[Set[str]]]):
'''
Python code type-checking the previously localized parameter or return
value annotated by the passed PEP-compliant type hint against this hint of
Expand Down
4 changes: 2 additions & 2 deletions beartype/_decor/_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class BeartypeData(object):
#
# See also:
# https://docs.python.org/3/reference/datamodel.html#object.__hash__
__hash__ = None
__hash__ = None # type: ignore[assignment]

# ..................{ INITIALIZERS }..................
def __init__(self) -> None:
Expand Down Expand Up @@ -202,7 +202,7 @@ def reinit(self, func: Callable) -> None:

# Nullify all remaining attributes for safety *BEFORE* passing this
# object to any functions (e.g., resolve_hints_postponed_if_needed()).
self.func_sig = None
self.func_sig = None # type: ignore[assignment]

# Resolve all postponed annotations if any on this callable *BEFORE*
# parsing the actual annotations these postponed annotations refer to.
Expand Down
11 changes: 6 additions & 5 deletions beartype/_util/cache/pool/utilcachepool.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@

# ....................{ IMPORTS }....................
from beartype.roar import _BeartypeUtilCachedKeyPoolException
from collections import defaultdict
from collections import defaultdict, abc
from threading import Lock
from typing import Any, Hashable, Dict

# ....................{ CLASSES }....................
class KeyPool(object):
Expand Down Expand Up @@ -74,7 +75,7 @@ class KeyPool(object):
# ..................{ INITIALIZER }..................
def __init__(
self,
item_maker: 'collections.abc.Callable[(HashableType,), Any]',
item_maker: 'abc.Callable[Hashable, Any]',
) -> None:
'''
Initialize this key pool with the passed factory callable.
Expand Down Expand Up @@ -113,11 +114,11 @@ def item_maker(key: HashableType) -> object: ...
# >>> dd['ee']
# KeyError: 'ee'
self._key_to_pool = defaultdict(list)
self._pool_item_id_to_is_acquired = {}
self._pool_item_id_to_is_acquired: Dict[int, bool] = {}
self._thread_lock = Lock()

# ..................{ METHODS }..................
def acquire(self, key: 'HashableType' = None) -> object:
def acquire(self, key: 'Hashable' = None) -> object:
'''
Acquire an arbitrary object associated with the passed **arbitrary
key** (i.e., hashable object).
Expand Down Expand Up @@ -188,7 +189,7 @@ def acquire(self, key: 'HashableType' = None) -> object:
return pool_item


def release(self, item: object, key: 'HashableType' = None) -> None:
def release(self, item: object, key: 'Hashable' = None) -> None:
'''
Release the passed object acquired by a prior call to the
:meth:`acquire` method passed the same passed **arbitrary key** (i.e.,
Expand Down
10 changes: 5 additions & 5 deletions beartype/_util/cache/pool/utilcachepoollistfixed.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,29 +223,29 @@ def _die_if_slice_len_ne_value_len(self, index, value) -> None:
# Prohibit non-dunder methods modifying list length by overriding these
# methods to raise exceptions.

def append(self, obj):
def append(self, obj) -> None:
raise _BeartypeUtilCachedFixedListException(
'{} not appendable by {}.'.format(
self._label, get_object_representation(obj)))


def clear(self):
def clear(self) -> None:
raise _BeartypeUtilCachedFixedListException(
'{} not clearable.'.format(self._label))


def extend(self, obj):
def extend(self, obj) -> None:
raise _BeartypeUtilCachedFixedListException(
'{} not extendable by {}.'.format(
self._label, get_object_representation(obj)))


def pop(self, *args):
def pop(self, *args) -> None:
raise _BeartypeUtilCachedFixedListException(
'{} not poppable.'.format(self._label))


def remove(self, *args):
def remove(self, *args) -> None:
raise _BeartypeUtilCachedFixedListException(
'{} not removable.'.format(self._label))

Expand Down
3 changes: 2 additions & 1 deletion beartype/_util/cache/utilcachecall.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
from beartype._util.utilobject import SENTINEL, Iota
from functools import wraps
from inspect import Parameter
from typing import Callable, Optional
from warnings import warn

# ....................{ CONSTANTS ~ private }....................
Expand Down Expand Up @@ -69,7 +70,7 @@
'''

# ....................{ DECORATORS }....................
def callable_cached(func: 'Callable'):
def callable_cached(func: 'Callable') -> 'Callable':
'''
**Memoize** (i.e., efficiently cache and return all previously returned
values of the passed callable as well as all previously raised exceptions
Expand Down
1 change: 1 addition & 0 deletions beartype/_util/cache/utilcachelru.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
# ....................{ IMPORTS }....................
from beartype.roar import _BeartypeUtilLRUCacheException
from threading import RLock
from typing import Hashable

# ....................{ CLASSES }....................
class LRUCacheStrong(dict):
Expand Down
1 change: 1 addition & 0 deletions beartype/_util/func/utilfunccodeobj.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from beartype.roar import _BeartypeUtilCallableException
from collections.abc import Callable
from types import CodeType, FunctionType, MethodType
from typing import Optional

# ....................{ GETTERS }....................
def get_func_codeobj(
Expand Down
3 changes: 2 additions & 1 deletion beartype/_util/hint/data/pep/proposal/utilhintdatapep484.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@
# current Python version, as this superclass was thankfully publicized
# under Python >= 3.7 after its initial privatization under Python <= 3.6.
HINT_PEP484_BASE_FORWARDREF = (
typing.ForwardRef if IS_PYTHON_AT_LEAST_3_7 else typing._ForwardRef)
# mypy gets confused by _ForwardRef on python >= 3.7
typing.ForwardRef if IS_PYTHON_AT_LEAST_3_7 else typing._ForwardRef) # type: ignore [attr-defined]
'''
**Forward reference sign** (i.e., arbitrary objects uniquely identifying a
`PEP 484`_-compliant type hint unifying one or more subscripted type hint
Expand Down
3 changes: 2 additions & 1 deletion beartype/_util/hint/data/pep/proposal/utilhintdatapep544.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
# ....................{ IMPORTS }....................
from abc import abstractmethod
from beartype._util.py.utilpyversion import IS_PYTHON_AT_LEAST_3_8
from typing import Optional

# See the "beartype.__init__" submodule for further commentary.
__all__ = ['STAR_IMPORTS_CONSIDERED_HARMFUL']
Expand Down Expand Up @@ -212,7 +213,7 @@ def tell(self) -> int:
pass

@abstractmethod
def truncate(self, size: int = None) -> int:
def truncate(self, size: Optional[int] = None) -> int:
pass

@abstractmethod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

# ....................{ IMPORTS }....................
from beartype._util.py.utilpyversion import IS_PYTHON_AT_LEAST_3_9
from types import ModuleType

# See the "beartype.__init__" submodule for further commentary.
__all__ = ['STAR_IMPORTS_CONSIDERED_HARMFUL']
Expand Down
1 change: 1 addition & 0 deletions beartype/_util/hint/data/pep/utilhintdatapep.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
utilhintdatapep585,
utilhintdatapep593,
)
from types import ModuleType

# See the "beartype.__init__" submodule for further commentary.
__all__ = ['STAR_IMPORTS_CONSIDERED_HARMFUL']
Expand Down
2 changes: 1 addition & 1 deletion beartype/_util/hint/pep/proposal/utilhintpep484.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
)
from beartype._util.py.utilpyversion import IS_PYTHON_AT_LEAST_3_7
from beartype._util.utilobject import is_object_subclass
from typing import Generic, NewType
from typing import Generic, NewType, Optional, Tuple

# See the "beartype.__init__" submodule for further commentary.
__all__ = ['STAR_IMPORTS_CONSIDERED_HARMFUL']
Expand Down
5 changes: 3 additions & 2 deletions beartype/_util/hint/pep/proposal/utilhintpep544.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from beartype._util.py.utilpyversion import IS_PYTHON_AT_LEAST_3_8
from beartype._util.utilclass import is_class_builtin
from beartype._util.utilobject import is_object_subclass
from typing import Optional

# See the "beartype.__init__" submodule for further commentary.
__all__ = ['STAR_IMPORTS_CONSIDERED_HARMFUL']
Expand Down Expand Up @@ -61,7 +62,7 @@ def is_hint_pep544_io_generic(hint: object) -> bool:
return False


def is_hint_pep544_protocol(hint: object) -> None:
def is_hint_pep544_protocol(hint: object) -> bool:

# Return true only if this hint is...
return (
Expand Down Expand Up @@ -95,7 +96,7 @@ def is_hint_pep544_io_generic(hint: object) -> bool:
return False


def is_hint_pep544_protocol(hint: object) -> None:
def is_hint_pep544_protocol(hint: object) -> bool:
return False

# ....................{ TESTERS ~ doc }....................
Expand Down
5 changes: 3 additions & 2 deletions beartype/_util/hint/pep/proposal/utilhintpep585.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from beartype._util.cache.utilcachecall import callable_cached
from beartype._util.func.utilfuncget import get_func_wrappee
from beartype._util.py.utilpyversion import IS_PYTHON_AT_LEAST_3_9
from typing import Set, Tuple, TypeVar

# See the "beartype.__init__" submodule for further commentary.
__all__ = ['STAR_IMPORTS_CONSIDERED_HARMFUL']
Expand Down Expand Up @@ -254,7 +255,7 @@ def get_hint_pep585_generic_bases_unerased(hint: object) -> 'Tuple[object]':


@callable_cached
def get_hint_pep585_generic_typevars(hint: object) -> 'Tuple[TypeVar]':
def get_hint_pep585_generic_typevars(hint: object) -> 'Tuple[TypeVar, ...]':
'''
Tuple of all **unique type variables** (i.e., subscripted :class:`TypeVar`
instances of the passed `PEP 585`_-compliant generic listed by the caller
Expand Down Expand Up @@ -305,7 +306,7 @@ def get_hint_pep585_generic_typevars(hint: object) -> 'Tuple[TypeVar]':
hint_bases = get_hint_pep585_generic_bases_unerased(hint)

# Set of all type variables parametrizing these pseudo-superclasses.
hint_typevars = set()
hint_typevars: Set[TypeVar] = set()

# For each such pseudo-superclass, add all type variables parametrizing
# this pseudo-superclass to this set.
Expand Down
1 change: 1 addition & 0 deletions beartype/_util/hint/pep/proposal/utilhintpep593.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
# ....................{ IMPORTS }....................
from beartype.roar import BeartypeDecorHintPepException
from beartype._util.py.utilpyversion import IS_PYTHON_AT_LEAST_3_9
from typing import Optional

# See the "beartype.__init__" submodule for further commentary.
__all__ = ['STAR_IMPORTS_CONSIDERED_HARMFUL']
Expand Down
2 changes: 1 addition & 1 deletion beartype/_util/hint/pep/utilhintpepget.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
is_hint_pep585,
is_hint_pep585_generic,
)
from typing import Generic, NewType, TypeVar
from typing import Generic, NewType, Optional, Tuple, TypeVar

# See the "beartype.__init__" submodule for further commentary.
__all__ = ['STAR_IMPORTS_CONSIDERED_HARMFUL']
Expand Down
6 changes: 3 additions & 3 deletions beartype/_util/hint/pep/utilhintpeptest.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
from beartype._util.utilobject import get_object_class_unless_class
from beartype._util.py.utilpymodule import get_object_module_name
from beartype._util.py.utilpyversion import IS_PYTHON_AT_LEAST_3_7
from typing import TypeVar
from typing import TypeVar, Optional
from warnings import warn

# See the "beartype.__init__" submodule for further commentary.
Expand Down Expand Up @@ -333,7 +333,7 @@ def warn_if_hint_pep_sign_deprecated(

# Optional parameters.
hint_label: str = 'Annotated',
) -> bool:
) -> None:
'''
Emit a non-fatal warning only if the passed PEP-compliant sign uniquely
identifying the passed PEP-compliant type hint is **deprecated** (e.g., due
Expand Down Expand Up @@ -749,7 +749,7 @@ def is_hint_pep_supported(hint: object) -> bool:
return is_hint_pep_sign_supported(hint_pep_sign)


def is_hint_pep_sign_supported(hint) -> bool:
def is_hint_pep_sign_supported(hint: object) -> bool:
'''
``True`` only if the passed object is a **PEP-compliant supported
unsubscripted typing attribute** (i.e., public attribute of the
Expand Down
10 changes: 6 additions & 4 deletions beartype/_util/py/utilpymodule.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
# ....................{ IMPORTS }....................
import importlib
from beartype.roar import _BeartypeUtilModuleException
from types import ModuleType
from typing import Optional

# See the "beartype.__init__" submodule for further commentary.
__all__ = ['STAR_IMPORTS_CONSIDERED_HARMFUL']
Expand All @@ -24,7 +26,7 @@ def die_unless_module_attr_name(
# Optional parameters.
exception_label: 'Optional[str]' = 'Module attribute name',
exception_cls: 'Optional[type]' = _BeartypeUtilModuleException,
) -> object:
) -> None:
'''
Raise an exception unless the passed string is the fully-qualified
syntactically valid name of a **module attribute** (i.e., object declared
Expand Down Expand Up @@ -143,7 +145,7 @@ def get_object_module_name(obj: object) -> 'Optional[str]':
return module_name


def get_object_module_name_or_none(obj: object) -> 'Optional[str]':
def get_object_module_name_or_none(obj: object) -> Optional[str]:
'''
**Fully-qualified name** (i.e., ``.``-delimited name prefixed by the
declaring package) of the module declaring the passed object if this
Expand Down Expand Up @@ -309,8 +311,8 @@ def import_module_attr(
module_attr_name: str,

# Optional parameters.
exception_label: 'Optional[str]' = 'Module attribute name',
exception_cls: 'Optional[type]' = _BeartypeUtilModuleException,
exception_label: str = 'Module attribute name',
exception_cls: type = _BeartypeUtilModuleException,
) -> object:
'''
Dynamically import and return the **module attribute** (i.e., object
Expand Down
1 change: 1 addition & 0 deletions beartype/_util/text/utiltextcause.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from beartype._util.text.utiltextjoin import join_delimited_disjunction_classes
from beartype._util.text.utiltextlabel import label_class
from beartype._util.text.utiltextrepr import get_object_representation
from typing import Tuple

# See the "beartype.__init__" submodule for further commentary.
__all__ = ['STAR_IMPORTS_CONSIDERED_HARMFUL']
Expand Down
3 changes: 2 additions & 1 deletion beartype/_util/text/utiltextjoin.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ def join_delimited(
return ''
# If one string is passed, return this string as is.
elif num_strs == 1:
return strs[0]
# This is clearly a string, yet mypy thinks it's Any
return strs[0] # type: ignore[no-any-return]
# If two strings are passed, return these strings delimited appropriately.
elif num_strs == 2:
return f'{strs[0]}{delimiter_if_two}{strs[1]}'
Expand Down
2 changes: 1 addition & 1 deletion beartype/_util/utilclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
'''

# ....................{ VALIDATORS }....................
def die_unless_class(cls: type) -> bool:
def die_unless_class(cls: type) -> None:
'''
Raise an exception unless the passed object is a class.
Expand Down

0 comments on commit 4944835

Please sign in to comment.