From 05ab861ceb27a5ad98d2db28fba4f0511ff6b260 Mon Sep 17 00:00:00 2001 From: Bas van Beek <43369155+BvB93@users.noreply.github.com> Date: Sun, 10 May 2020 00:18:54 +0200 Subject: [PATCH] AssertionLib 2.3.0 (#19) AssertionLib 2.3.0 ------------------ * Added the ``AssertionManager.xor()``, ``AssertionManager.isdisjoint()`` and ``AssertionManager.length_hint()`` methods. * Annotate most ``AssertionManager`` methods using Protocols. * Moved Protocols to their own separate stub module. * Cleaned up the ``_MetaAM`` metaclass. * Reworked some of the internals of ``AssertionManager``. * Added tests using [pydocstyle ](https://github.com/henry0312/pytest-pydocstyle). --- .github/workflows/pythonpackage.yml | 4 +- .travis.yml | 3 +- CHANGELOG.rst | 10 + README.rst | 2 +- assertionlib/README.rst | 6 - assertionlib/__init__.py | 2 + assertionlib/__version__.py | 4 +- assertionlib/assertion_functions.py | 185 +++++++++ assertionlib/dataclass.py | 53 ++- assertionlib/functions.py | 490 ++++++++++++------------ assertionlib/manager.py | 337 ++++++++-------- assertionlib/manager.pyi | 575 ++++++++++++++++++---------- assertionlib/ndrepr.py | 31 +- assertionlib/protocol.pyi | 159 ++++++++ assertionlib/signature_utils.py | 254 ------------ docs/0_documentation.rst | 2 +- docs/3_assertionmanager.rst | 3 + docs/4_ndrepr.rst | 3 + docs/5_dataclass.rst | 3 + docs/6_functions.rst | 3 + docs/7_assertion_functions.rst | 5 + docs/7_signature_utils.rst | 2 - docs/conf.py | 2 +- setup.cfg | 7 +- setup.py | 20 +- tests/test_manager.py | 17 +- tests/test_manager_misc.py | 93 ++++- tests/test_ndrepr.py | 6 +- tests/test_signature_utils.py | 54 --- 29 files changed, 1349 insertions(+), 986 deletions(-) create mode 100644 assertionlib/assertion_functions.py create mode 100644 assertionlib/protocol.pyi delete mode 100644 assertionlib/signature_utils.py create mode 100755 docs/7_assertion_functions.rst delete mode 100644 docs/7_signature_utils.rst delete mode 100644 tests/test_signature_utils.py diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index b692c9d..b32368f 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -29,7 +29,7 @@ jobs: python-version: ${{ matrix.python-version }} - name: Install dependencies - run: pip install -e .[test] + run: pip install -e .[test]; pip install git+https://github.com/numpy/numpy-stubs@master - name: Test with pytest - run: pytest assertionlib tests docs + run: pytest assertionlib tests diff --git a/.travis.yml b/.travis.yml index ad31f7d..4b74fc3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,10 +38,11 @@ install: # Install the tests - pip install .[test] --upgrade + - pip install git+https://github.com/numpy/numpy-stubs@master script: # Run the unitary tests excluding the expensive computations - - pytest assertionlib tests docs + - pytest assertionlib tests - coverage xml && coverage report -m branches: diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 9f50419..8b65dae 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,6 +6,16 @@ All notable changes to this project will be documented in this file. This project adheres to `Semantic Versioning `_. +2.3.0 +***** +* Added the ``AssertionManager.xor()``, ``AssertionManager.isdisjoint()`` and ``AssertionManager.length_hint()`` methods. +* Annotate most ``AssertionManager`` methods using Protocols. +* Moved Protocols to their own separate stub module. +* Cleaned up the ``_MetaAM`` metaclass. +* Reworked some of the internals of ``AssertionManager``. +* Added tests using `pydocstyle `_. + + 2.2.3 ***** * Windows bug fix: Check for the presence of the ``AssertionManager._isdir()`` diff --git a/README.rst b/README.rst index 4ac8015..4acd941 100644 --- a/README.rst +++ b/README.rst @@ -18,7 +18,7 @@ ################## -AssertionLib 2.2.3 +AssertionLib 2.3.0 ################## A package for performing assertions and providing informative exception messages. diff --git a/assertionlib/README.rst b/assertionlib/README.rst index 5a65f12..24d04c2 100644 --- a/assertionlib/README.rst +++ b/assertionlib/README.rst @@ -25,11 +25,6 @@ A module for holding the ``assertionlib.NDRepr()`` class, a subclass of the builtin ``reprlib.Repr()`` class. -``assertionlib.signature_utils`` --------------------------------- -Various functions for manipulating the signatures of callables. - - .. _`Python 3.7`: https://www.python.org/dev/peps/pep-0557/ .. |dataclasses| replace:: :mod:`dataclasses` @@ -38,7 +33,6 @@ Various functions for manipulating the signatures of callables. .. |assertionlib.functions| replace:: :mod:`assertionlib.functions` .. |assertionlib.manager| replace:: :mod:`assertionlib.manager` .. |assertionlib.ndrepr| replace:: :mod:`assertionlib.ndrepr` -.. |assertionlib.signature| replace:: :mod:`assertionlib.signature` .. |assertionlib.AssertionManager| replace:: :class:`assertionlib.AssertionManager` .. |assertionlib.NDRepr| replace:: :class:`assertionlib.NDRepr` diff --git a/assertionlib/__init__.py b/assertionlib/__init__.py index 570b875..356d98c 100644 --- a/assertionlib/__init__.py +++ b/assertionlib/__init__.py @@ -1,3 +1,5 @@ +"""AssertionLib.""" + from .__version__ import __version__ from .ndrepr import NDRepr, aNDRepr diff --git a/assertionlib/__version__.py b/assertionlib/__version__.py index 05633ca..fcafd15 100644 --- a/assertionlib/__version__.py +++ b/assertionlib/__version__.py @@ -1 +1,3 @@ -__version__ = '2.2.3' +"""The AssertionLib version.""" + +__version__ = '2.3.0' diff --git a/assertionlib/assertion_functions.py b/assertionlib/assertion_functions.py new file mode 100644 index 0000000..e444bcb --- /dev/null +++ b/assertionlib/assertion_functions.py @@ -0,0 +1,185 @@ +"""A module with various new assertion functions. + +Index +----- +.. currentmodule:: assertionlib.assertion_functions +.. autosummary:: + len_eq + str_eq + shape_eq + isdisjoint + function_eq + +API +--- +.. autofunction:: len_eq +.. autofunction:: str_eq +.. autofunction:: shape_eq +.. autofunction:: isdisjoint +.. autofunction:: function_eq + +""" + +import dis +from types import FunctionType +from itertools import zip_longest +from typing import ( + Sized, + Callable, + TypeVar, + Iterable, + Union, + Tuple, + Hashable, + TYPE_CHECKING +) + +from .functions import to_positional + +if TYPE_CHECKING: + from numpy import ndarray # type: ignore +else: + ndarray = 'numpy.ndarray' + +__all__ = ['len_eq', 'str_eq', 'shape_eq', 'isdisjoint', 'function_eq'] + +T = TypeVar('T') +IT = TypeVar('IT', bound=Union[None, dis.Instruction]) + + +@to_positional +def len_eq(a: Sized, b: int) -> bool: + """Check if the length of **a** is equivalent to **b**: :code:`len(a) == b`. + + Parameters + ---------- + a : :class:`~collections.abc.Sized` + The object whose size will be evaluated. + + b : :class:`int` + The integer that will be matched against the size of **a**. + + """ + return len(a) == b + + +@to_positional +def str_eq(a: T, b: str, *, str_converter: Callable[[T], str] = repr) -> bool: + """Check if the string-representation of **a** is equivalent to **b**: :code:`repr(a) == b`. + + Parameters + ---------- + a : :class:`T` + An object whose string represention will be evaluated. + + b : :class:`str` + The string that will be matched against the string-output of **a**. + + Keyword Arguments + ----------------- + str_converter : :data:`Callable[[T], str]` + The callable for constructing **a**'s string representation. + Uses :func:`repr` by default. + + """ + return str_converter(a) == b + + +@to_positional +def shape_eq(a: ndarray, b: Union[ndarray, Tuple[int, ...]]) -> bool: + """Check if the shapes of **a** and **b** are equivalent: :code:`a.shape == getattr(b, 'shape', b)`. + + **b** should be either an object with the ``shape`` attribute (*e.g.* a NumPy array) + or a :class:`tuple` representing a valid array shape. + + Parameters + ---------- + a : :class:`numpy.ndarray` + A NumPy array. + + b : :class:`numpy.ndarray` or :class:`tuple` [:class:`int`, ...] + A NumPy array or a tuple of integers representing the shape of **a**. + + """ # noqa + return a.shape == getattr(b, 'shape', b) + + +@to_positional +def isdisjoint(a: Iterable[Hashable], b: Iterable[Hashable]) -> bool: + """Check if **a** has no elements in **b**. + + Parameters + ---------- + a/b : :class:`~collections.abc.Iterable` [:class:`~collections.abc.Hashable`] + Two to-be compared iterables. + Note that both iterables must consist of hashable objects. + + See Also + -------- + :meth:`set.isdisjoint()` + Return ``True`` if two sets have a null intersection. + + """ + try: + return a.isdisjoint(b) # type: ignore + + # **a** does not have the isdisjoint method + except AttributeError: + return set(a).isdisjoint(b) + + # **a.isdisjoint** is not a callable or + # **a** and/or **b** do not consist of hashable elements + except TypeError as ex: + if callable(a.isdisjoint): # type: ignore + raise ex + return set(a).isdisjoint(b) + + +@to_positional +def function_eq(func1: FunctionType, func2: FunctionType) -> bool: + """Check if two functions are equivalent by checking if their :attr:`__code__` is identical. + + **func1** and **func2** should be instances of :data:`~types.FunctionType` + or any other object with access to the :attr:`__code__` attribute. + + Parameters + ---------- + func1/func2 : :data:`~types.FunctionType` + Two functions. + + Examples + -------- + .. code:: python + + >>> from assertionlib.assertion_functions import function_eq + + >>> func1 = lambda x: x + 5 + >>> func2 = lambda x: x + 5 + >>> func3 = lambda x: 5 + x + + >>> print(function_eq(func1, func2)) + True + + >>> print(function_eq(func1, func3)) + False + + """ + code1 = None + try: + code1 = func1.__code__ + code2 = func2.__code__ + except AttributeError as ex: + name, obj = ('func1', func1) if code1 is None else ('func2', func2) + raise TypeError(f"{name!r} expected a function or object with the '__code__' attribute; " + f"observed type: {obj.__class__.__name__!r}") from ex + + iterator = zip_longest(dis.get_instructions(code1), dis.get_instructions(code2)) + tup_iter = ((_sanitize_instruction(i), _sanitize_instruction(j)) for i, j in iterator) + return all([i == j for i, j in tup_iter]) + + +def _sanitize_instruction(instruction: IT) -> IT: + """Sanitize the supplied instruction by setting :attr:`~dis.Instruction.starts_line` to :data:`None`.""" # noqa + if instruction is None: + return None + return instruction._replace(starts_line=None) # type: ignore diff --git a/assertionlib/dataclass.py b/assertionlib/dataclass.py index 309355f..ffcad75 100644 --- a/assertionlib/dataclass.py +++ b/assertionlib/dataclass.py @@ -1,8 +1,4 @@ -""" -assertionlib.dataclass -====================== - -A class with a number of generic pre-defined (magic) methods inspired by dataclass of Python 3.7. +"""A class with a number of generic pre-defined (magic) methods inspired by dataclass of Python 3.7. Index ----- @@ -32,7 +28,7 @@ .. automethod:: AbstractDataClass.from_dict .. automethod:: AbstractDataClass.inherit_annotations -""" +""" # noqa: E501 import textwrap import copy @@ -41,26 +37,27 @@ from threading import get_ident from typing import ( Any, Dict, Set, Iterable, Tuple, ClassVar, NoReturn, cast, Iterator, Union, - Callable, Optional, Mapping, TypeVar + Callable, Optional, Mapping, TypeVar, Type ) __all__ = ['AbstractDataClass'] T = TypeVar('T') -UserFunc = Callable[..., T] +AT = TypeVar('AT', bound='AbstractDataClass') +FT = TypeVar('FT', bound=Callable[..., Any]) -def recursion_safeguard(fallback: UserFunc) -> Callable[[UserFunc], UserFunc]: +def recursion_safeguard(fallback: FT) -> Callable[[FT], FT]: """Decorate a function such that it calls **fallback** in case of recursive calls. Implementation based on :func:`reprlib.recursive_repr`. """ - def decorating_function(user_function: UserFunc) -> UserFunc: + def decorating_function(user_function: FT) -> FT: running: Set[Tuple[int, int]] = set() @wraps(user_function) - def wrapper(self: Any, *args: Any, **kwargs: Any) -> T: + def wrapper(self, *args: Any, **kwargs: Any) -> Any: key = id(self), get_ident() if key in running: return fallback(self, *args, **kwargs) @@ -71,7 +68,7 @@ def wrapper(self: Any, *args: Any, **kwargs: Any) -> T: finally: running.discard(key) return result - return wrapper + return cast(FT, wrapper) return decorating_function @@ -86,12 +83,12 @@ def __new__(mcls, name, bases, namespace) -> '_MetaADC': # noqa: N804 return cls @staticmethod - def _hash_template1(self: Any) -> NoReturn: + def _hash_template1(self) -> NoReturn: """Unhashable type; raise a :exc:`TypeError`.""" raise TypeError(f"Unhashable type: {self.__class__.__name__!r}") @staticmethod - def _hash_template2(self: Any) -> int: + def _hash_template2(self) -> int: """Return the hash of this instance. The returned hash is constructed from two components: @@ -102,7 +99,7 @@ def _hash_template2(self: Any) -> int: then its :func:`id` is used for hashing. This method will raise a :exc:`TypeError` if the class attribute - :attr:`AbstractDataClass._HASHABLE` is ``False``. + :attr:`AbstractDataClass._HASHABLE` is :data:`False`. See Also -------- @@ -162,11 +159,11 @@ class AbstractDataClass(metaclass=_MetaADC): _HASHABLE : :class:`bool` A class variable denoting whether or not class instances are hashable. - The :attr:`AbstractDataClass.__hash__` method will be unavailable if ``False``. + The :attr:`AbstractDataClass.__hash__` method will be unavailable if :data:`False`. _hash : :class:`int` An attribute for caching the :func:`hash` of this instance. - Only available if :attr:`AbstractDataClass._HASHABLE` is ``True``. + Only available if :attr:`AbstractDataClass._HASHABLE` is :data:`True`. """ @@ -176,7 +173,7 @@ class AbstractDataClass(metaclass=_MetaADC): _PRIVATE_ATTR: Set[str] = frozenset() # type: ignore #: Whether or not this class is hashable. - #: If ``False``, raise a :exc:`TypeError` when calling :meth:`AbstractDataClass.__hash__`. + #: If :data:`False`, raise a :exc:`TypeError` when calling :meth:`AbstractDataClass.__hash__`. _HASHABLE: ClassVar[bool] = True #: Empty slots which can be filled by subclasses. @@ -222,7 +219,7 @@ def _repr_fallback(self) -> str: """Fallback function for :meth:`AbstractDataClass.__repr__` incase of recursive calls.""" return object.__repr__(self).rstrip('>').rsplit(maxsplit=1)[1] - @recursion_safeguard(fallback=_repr_fallback) + @recursion_safeguard(fallback=_repr_fallback) # type: ignore def __repr__(self) -> str: """Return a (machine readable) string representation of this instance. @@ -279,7 +276,7 @@ def _eq_fallback(self, value: Any) -> bool: """Fallback function for :meth:`AbstractDataClass.__eq__` incase of recursive calls.""" return self is value - @recursion_safeguard(fallback=_eq_fallback) + @recursion_safeguard(fallback=_eq_fallback) # type: ignore def __eq__(self, value: Any) -> bool: """Check if this instance is equivalent to **value**. @@ -324,7 +321,7 @@ def _eq(v1: Any, v2: Any) -> bool: """Return if **v1** and **v2** are equivalent.""" return v1 == v2 - def copy(self, deep: bool = False) -> 'AbstractDataClass': + def copy(self: AT, deep: bool = False) -> AT: """Return a shallow or deep copy of this instance. Parameters @@ -349,11 +346,11 @@ def return_arg(arg: T) -> T: setattr(ret, k, copy_func(v)) return ret - def __copy__(self) -> 'AbstractDataClass': + def __copy__(self: AT) -> AT: """Return a shallow copy of this instance; see :meth:`AbstractDataClass.copy`.""" return self.copy(deep=False) - def __deepcopy__(self, memo: Optional[Dict[int, Any]] = None) -> 'AbstractDataClass': + def __deepcopy__(self: AT, memo: Optional[Dict[int, Any]] = None) -> AT: """Return a deep copy of this instance; see :meth:`AbstractDataClass.copy`.".""" return self.copy(deep=True) @@ -365,7 +362,7 @@ def as_dict(self, return_private: bool = False) -> Dict[str, Any]: Parameters ---------- return_private : :class:`bool` - If ``True``, return both public and private instance variables. + If :data:`True`, return both public and private instance variables. Private instance variables are defined in :data:`AbstractDataClass._PRIVATE_ATTR`. Returns @@ -389,7 +386,7 @@ def as_dict(self, return_private: bool = False) -> Dict[str, Any]: return {k: copy.copy(v) for k, v in self._iter_attrs() if k not in self._PRIVATE_ATTR} @classmethod - def from_dict(cls, dct: Mapping[str, Any]) -> 'AbstractDataClass': + def from_dict(cls: Type[AT], dct: Mapping[str, Any]) -> AT: """Construct a instance of this objects' class from a dictionary with keyword arguments. Parameters @@ -412,7 +409,7 @@ def from_dict(cls, dct: Mapping[str, Any]) -> 'AbstractDataClass': return cls(**dct) # type: ignore @classmethod - def inherit_annotations(cls) -> Callable[[UserFunc], UserFunc]: + def inherit_annotations(cls) -> Callable[[FT], FT]: """A decorator for inheriting annotations and docstrings. Can be applied to methods of :class:`AbstractDataClass` subclasses to automatically @@ -439,10 +436,10 @@ def inherit_annotations(cls) -> Callable[[UserFunc], UserFunc]: Return a shallow copy of this instance; see :meth:`SubClass.copy`. >>> print(SubClass.__copy__.__annotations__) - {'return': 'SubClass'} + {'self': ~AT, 'return': ~AT} """ - def decorator(func: UserFunc) -> UserFunc: + def decorator(func: FT) -> FT: cls_func: str = getattr(cls, func.__name__) sub_cls_name: str = func.__qualname__.split('.')[0] diff --git a/assertionlib/functions.py b/assertionlib/functions.py index 69ee005..96d113c 100644 --- a/assertionlib/functions.py +++ b/assertionlib/functions.py @@ -1,8 +1,4 @@ -""" -assertionlib.functions -====================== - -Various functions related to the :class:`.AssertionManager` class. +"""Various functions related to the :class:`.AssertionManager` class. Index ----- @@ -12,9 +8,7 @@ create_assertion_doc bind_callable skip_if - len_eq - str_eq - function_eq + to_positional API --- @@ -22,42 +16,132 @@ .. autofunction:: create_assertion_doc .. autofunction:: bind_callable .. autofunction:: skip_if -.. autofunction:: len_eq -.. autofunction:: str_eq -.. autofunction:: function_eq +.. autofunction:: to_positional """ import os -import dis import sys -import inspect import textwrap import warnings import functools -import contextlib -from types import MappingProxyType, FunctionType, MethodType, CodeType -from itertools import zip_longest +from types import MappingProxyType, MethodType from typing import ( - Callable, Any, Optional, Union, Sized, Mapping, Tuple, Type, TypeVar, cast, TYPE_CHECKING + Callable, + Any, + Optional, + Union, + Mapping, + Type, + TypeVar, + Iterable, + List, + Tuple, + cast, + TYPE_CHECKING +) +from inspect import ( + signature, + Parameter, + Signature, + isbuiltin, + isfunction, + ismethod, + ismethoddescriptor, + isclass ) -from .signature_utils import generate_signature, _signature_to_str, _get_cls_annotation - -if TYPE_CHECKING: - from numpy import ndarray -else: - ndarray = 'numpy.ndarray' - -if sys.version_info <= (3, 6): +if sys.version_info < (3, 7): COMMA = ',' + SPACE = '' else: COMMA = '' + SPACE = ' ' + +if TYPE_CHECKING: + from enum import IntEnum +else: + IntEnum = 'enum.IntEnum' -__all__ = ['get_sphinx_domain', 'create_assertion_doc', 'bind_callable', 'skip_if', - 'len_eq', 'str_eq', 'function_eq'] +__all__ = [ + 'set_docstring', 'get_sphinx_domain', 'create_assertion_doc', 'bind_callable', 'skip_if' +] T = TypeVar('T') +FT = TypeVar('FT', bound=Callable[..., Any]) + +PO = Parameter.POSITIONAL_ONLY +POK = Parameter.POSITIONAL_OR_KEYWORD +VP = Parameter.VAR_POSITIONAL +KO = Parameter.KEYWORD_ONLY +VK = Parameter.VAR_KEYWORD +_empty = Parameter.empty + +PARAM_NAME_MAPPING: Mapping[IntEnum, str] = MappingProxyType({ + PO: 'positional-only', + POK: 'positional or keyword', + VP: 'variadic positional', + KO: 'keyword-only', + VK: 'variadic keyword' +}) + +DEFAULT_PRM: Tuple[Parameter, Parameter] = ( + Parameter('args', Parameter.VAR_POSITIONAL, annotation=Any), + Parameter('kwargs', Parameter.VAR_KEYWORD, annotation=Any) +) + + +def set_docstring(docstring: Optional[str]) -> Callable[[FT], FT]: + """A decorator for assigning docstrings.""" + def wrapper(func: FT) -> FT: + func.__doc__ = docstring + return func + return wrapper + + +def _to_positional(iterable: Iterable[Parameter]) -> List[Parameter]: + """Helper function for :func:`to_positional`; used in creating the new :class:`~inspect.Parameter` list.""" # noqa: E501 + ret = [] + for prm in iterable: + if prm.kind is not POK: + ret.append(prm) + elif prm.default is _empty: + ret.append(prm.replace(kind=PO)) + else: + ret.append(prm.replace(kind=KO)) + return ret + + +@set_docstring(f"""Decorate a function's :attr:`__signature__` such that all positional-or-keyword arguments are changed to either positional- or keyword-only. + +Example +------- +.. code:: python + + >>> from inspect import signature + >>> from assertionlib.functions import to_positional + + >>> def func1(a: int, b: int = 0) -> int: + ... pass + + >>> @to_positional + ... def func2(a: int, b: int = 0) -> int: + ... pass + + >>> print(signature(func1), signature(func2), sep='\\n') + (a:{SPACE}int, b:{SPACE}int{SPACE}={SPACE}0) -> int + (a:{SPACE}int, /, *, b:{SPACE}int{SPACE}={SPACE}0) -> int + +""") # noqa: E501 +def to_positional(func: FT) -> FT: + sgn = signature(func) + prm_dict = sgn.parameters + + prm_list = _to_positional(prm_dict.values()) + func.__signature__ = Signature( # type: ignore + parameters=prm_list, return_annotation=sgn.return_annotation + ) + return func def bind_callable(class_type: Union[type, Any], func: Callable, @@ -65,8 +149,8 @@ def bind_callable(class_type: Union[type, Any], func: Callable, """Take a callable and use it to create a new assertion method for **class_type**. The created callable will have the same signature as **func** except for one additional - keyword argument by the name of ``func`` (default value: ``False``). - Setting this keyword argument to ``True`` will invert the output of the assertion, + keyword argument by the name of ``func`` (default value: :data:`False`). + Setting this keyword argument to :data:`True` will invert the output of the assertion, *i.e.* it changes ``assert func(...)`` into ``assert not func(...)``. Examples @@ -90,93 +174,60 @@ def bind_callable(class_type: Union[type, Any], func: Callable, :rtype: :data:`None` """ - name_: str = name if name is not None else func.__name__ - # Create the new function - function, signature_str = _create_assertion_func(func) - - # Update the docstring and sanitize the signature - signature_str = signature_str.replace('(func, ', '(') - signature_str = signature_str.replace(', *args', '').replace(', **kwargs', '') - signature_str = signature_str.replace(', invert=invert, exception=exception, post_process=post_process, message=message', '') # noqa - function.__doc__ = create_assertion_doc(func, signature_str) - - # Update annotations - _set_annotations(function, func) + function = create_assertion_func(func) + if name is not None: + function.__name__ = name # Set the new method if isinstance(class_type, type): # A class - setattr(class_type, name_, function) + function.__qualname__ = f'{class_type.__name__}.{function.__name__}' + function.__module__ = class_type.__module__ + setattr(class_type, function.__name__, function) + else: # A class instance + function.__qualname__ = f'{class_type.__class__.__name__}.{function.__name__}' + function.__module__ = class_type.__class__.__module__ method = MethodType(function, class_type) # Create a bound method - setattr(class_type, name_, method) - - -def _set_annotations(func_new: Callable, func_old: Callable) -> None: - """Assign Annotations to the assertion function in :func:`bind_callable`.""" - func_new.__annotations__ = annotations = getattr(func_old, '__annotations__', {}).copy() - annotations['return'] = None - annotations['invert'] = bool - annotations['exception'] = Optional[Type[Exception]] - annotations['post_process'] = Optional[Callable[[Any], Any]] - annotations['message'] = Optional[str] + setattr(class_type, function.__name__, method) - # Create an additional annotation in case **func_old** is an instance-method - with contextlib.suppress(ValueError): # Raised if **func_old** has no readable signature - prm = inspect.signature(func_old).parameters - if 'self' in prm: - key, value = _get_cls_annotation(func_old) - annotations[key] = value +def create_assertion_func(func: Callable[..., Any]) -> Callable[..., None]: + """Construct an assertion function from **func**.""" -def _create_assertion_func(func: Callable) -> Tuple[FunctionType, str]: - """Generate the assertion function for :func:`bind_callable`. + def wrapper(self, *args: Any, + invert: bool = False, + exception: Optional[Type[Exception]] = None, + post_process: Optional[Callable[[Any], Any]] = None, + message: Optional[str] = None, + **kwargs: Any) -> None: + __tracebackhide__ = True - Parameters - ---------- - func : :class:`~collections.abc.Callable` - A callable object forming the basis of the to-be created assertion function. + self.assert_( + func, *args, + exception=exception, invert=invert, post_process=post_process, message=message, + **kwargs + ) - """ - _empty = inspect._empty # type: ignore - - def _to_str(prm: inspect.Parameter) -> str: - """Create a string from **prm**; ensure that callables are represented by their __name__.""" - ret = str(prm) - default = prm.default - if default is not _empty: - ret = ret.replace(str(default), 'obj') - return ret - - sgn: inspect.Signature = generate_signature(func) - sgn_str1: str = '(' + ', '.join(_to_str(v) for v in sgn.parameters.values()) + ')' - sgn_str2: str = _signature_to_str(sgn, 'func') - - # Create the code object for the to-be returned function - code_compile: CodeType = compile( - f'def {func.__name__}{sgn_str1}: __tracebackhide__ = True; self.assert_{sgn_str2}', - "", "exec" - ) - for code in code_compile.co_consts: # Type: CodeType - if isinstance(code, CodeType): - break + # Create a new list of Parameter instances + # All keyword-or-positional parameters are converted into positional- or keyword-only + try: + _prm_values = signature(func).parameters.values() + prm_list = _to_positional(_prm_values) + except ValueError: + prm_list = list(DEFAULT_PRM) else: - raise TypeError(f"Failed to identify a {CodeType.__name__!r} instance " - "in the compiled code") - - # Extract the default arguments for positional or keyword parameters - defaults: Optional[Tuple[object, ...]] = code_compile.co_consts[-1] - if isinstance(defaults, str): # no default arguments - defaults = None - func_new = FunctionType(code, {'func': func}, func.__name__, defaults) - - # Set default values for keyword-only parameters - ko = inspect.Parameter.KEYWORD_ONLY - kwdefault = {k: v.default for k, v in sgn.parameters.items() if v.kind is ko} - if kwdefault: - func_new.__kwdefaults__ = kwdefault + if not prm_list or prm_list[-1].kind is not VK: + prm_list.append(Parameter('kwargs', kind=VK, annotation=Any)) + finally: + if prm_list and prm_list[0].name == 'self': + prm_list[0] = Parameter('obj', kind=PO, annotation=prm_list[0].annotation) + prm_list.insert(0, Parameter('self', kind=PO)) - return func_new, sgn_str2 + wrapper.__name__ = wrapper.__qualname__ = func.__name__ + wrapper.__doc__ = create_assertion_doc(func) + wrapper.__signature__ = Signature(parameters=prm_list, return_annotation=None) # type: ignore + return wrapper #: A string with the (to-be formatted) docstring returned by :func:`wrap_docstring` @@ -184,24 +235,23 @@ def _to_str(prm: inspect.Parameter) -> str: Parameters ---------- +{parameters} +Keyword Arguments +----------------- invert : :class:`bool` - Invert the output of the assertion: :code:`assert not {name}{signature}`. - This value should only be supplied as keyword argument. + If :data:`True`, invert the output of the assertion: + :code:`assert not {name}{signature}`. exception : :class:`type` [:exc:`Exception`], optional Assert that **exception** is raised during/before the assertion operation. - This value should only be supplied as keyword argument. -post_process : :class:`~collections.abc.Callable`, optional +post_process : :data:`Callable[[Any], bool]`, optional Apply post-processing to the to-be asserted data before asserting aforementioned data. - Example functions would be the likes of :func:`~builtins.any` and :func:`~builtins.all`. + Example values would be the likes of :func:`any()` and :func:`all()`. -message : :data:`~typing.Any`, optional +message : :class:`str`, optional A custom error message to-be passed to the ``assert`` statement. -\*args/\**kwargs : :data:`~typing.Any` - Parameters for catching excess variable positional and keyword arguments. - :rtype: :data:`None` @@ -212,7 +262,7 @@ def _to_str(prm: inspect.Parameter) -> str: """ -def create_assertion_doc(func: Callable, signature: Optional[str] = None) -> str: +def create_assertion_doc(func: Callable) -> str: r"""Create a new NumPy style assertion docstring from the docstring of **func**. The summary of **funcs'** docstring, if available, is added to the ``"See also"`` section, @@ -226,34 +276,39 @@ def create_assertion_doc(func: Callable, signature: Optional[str] = None) -> str >>> docstring: str = create_assertion_doc(isinstance) >>> print(docstring) - Perform the following assertion: :code:`assert isinstance(*args, **kwargs)`. + Perform the following assertion: :code:`assert isinstance(obj, class_or_tuple)`. Parameters ---------- + obj + The positional-only argument ``obj`` of :func:`isinstance()`. + + class_or_tuple + The positional-only argument ``class_or_tuple`` of :func:`isinstance()`. + + + Keyword Arguments + ----------------- invert : :class:`bool` - Invert the output of the assertion: :code:`assert not isinstance(*args, **kwargs)`. - This value should only be supplied as keyword argument. + If :data:`True`, invert the output of the assertion: + :code:`assert not isinstance(obj, class_or_tuple)`. exception : :class:`type` [:exc:`Exception`], optional Assert that **exception** is raised during/before the assertion operation. - This value should only be supplied as keyword argument. - post_process : :class:`~collections.abc.Callable`, optional + post_process : :data:`Callable[[Any], bool]`, optional Apply post-processing to the to-be asserted data before asserting aforementioned data. - Example functions would be the likes of :func:`~builtins.any` and :func:`~builtins.all`. + Example values would be the likes of :func:`any()` and :func:`all()`. - message : :data:`~typing.Any`, optional + message : :class:`str`, optional A custom error message to-be passed to the ``assert`` statement. - \*args/\**kwargs : :data:`~typing.Any` - Parameters for catching excess variable positional and keyword arguments. - :rtype: :data:`None` See also -------- - :func:`~builtins.isinstance`: + :func:`isinstance()`: Return whether an object is an instance of a class or of a subclass thereof. A tuple, as in ``isinstance(x, (A, B, ...))``, may be given as the target to @@ -261,33 +316,40 @@ def create_assertion_doc(func: Callable, signature: Optional[str] = None) -> str or ...`` etc. + Parameters ---------- func : :class:`~collections.abc.Callable` A callable whose output is to-be asserted. - signature : :class:`str`, optional - Provide a custom signature for **func**. - If ``None``, default to ``(*args, **kwargs)``. - Returns ------- :class:`str` A new docstring constructed from **funcs'** docstring. - """ - # domain is :class:`...`, :func:`...` or :meth:`...` + """ # noqa: E501 + try: + __sgn = signature(func) + sgn = Signature(_to_positional(__sgn.parameters.values()), return_annotation=None) + except ValueError: + sgn = Signature(parameters=DEFAULT_PRM, return_annotation=None) + sgn_str = '(*args, **kwargs)' + else: + kv = sgn.parameters.items() + sgn_str = '(' + ', '.join((k if v.default is _empty else f'{k}={k}') for k, v in kv) + ')' + + name = getattr(func, '__qualname__', func.__name__) domain = get_sphinx_domain(func) - sgn: str = signature if signature is not None else '(*args, **kwargs)' + summary = textwrap.indent(func.__doc__ or 'No description.', 4 * ' ') - # Create a summary for a single `See Also` section using the docstring of **func** - indent = 4 * ' ' - func_doc: str = func.__doc__ or 'No description.' - func_summary = textwrap.indent(func_doc, indent) + parameters = '' + for k, v in sgn.parameters.items(): + prm_type = PARAM_NAME_MAPPING[v.kind] + parameters += f'{k}\n The {prm_type} argument ``{k}`` of {domain}.\n\n' - # Return a new docstring - name: str = getattr(func, '__qualname__', func.__name__) - return BASE_DOCSTRING.format(name=name, signature=sgn, domain=domain, summary=func_summary) + return BASE_DOCSTRING.format( + parameters=parameters, name=name, signature=sgn_str, domain=domain, summary=summary + ) #: A dictionary which translates certain __module__ values to an actual valid modules @@ -300,10 +362,7 @@ def create_assertion_doc(func: Callable, signature: Optional[str] = None) -> str def _is_builtin_func(func: Callable) -> bool: """Check if **func** is a builtin function.""" - try: - return inspect.isbuiltin(func) and '.' not in getattr(func, '__qualname__', '') - except AttributeError: - return False + return isbuiltin(func) and '.' not in getattr(func, '__qualname__', '') def get_sphinx_domain(func: Callable, module_mapping: Mapping[str, str] = MODULE_DICT) -> str: @@ -318,11 +377,11 @@ def get_sphinx_domain(func: Callable, module_mapping: Mapping[str, str] = MODULE >>> value1: str = get_sphinx_domain(int) >>> print(value1) - :class:`~builtins.int` + :class:`int` >>> value2: str = get_sphinx_domain(list.count) >>> print(value2) - :meth:`~builtins.list.count` + :meth:`list.count()` >>> value3: str = get_sphinx_domain(OrderedDict) >>> print(value3) @@ -364,18 +423,30 @@ def get_sphinx_domain(func: Callable, module_mapping: Mapping[str, str] = MODULE # Convert the extracted __module__ into an actual valid module module = MODULE_DICT.get(_module, _module) + # Identify the sphinx domain + if isfunction(func) or _is_builtin_func(func): + directive = 'func' + elif ismethod(func) or ismethoddescriptor(func) or isbuiltin(func): + directive = 'meth' + elif isclass(func): + directive = 'class' + # Return the domain as either :func:`...`, :meth:`...` or :class:`...` - if inspect.isfunction(func) or _is_builtin_func(func): - return f':func:`~{module}.{name}`' - elif inspect.ismethod(func) or inspect.ismethoddescriptor(func) or inspect.isbuiltin(func): - return f':meth:`~{module}.{name}`' - elif inspect.isclass(func): - return f':class:`~{module}.{name}`' - raise TypeError(f"{name!r} is neither a (builtin) function, method nor class") + try: + if module != 'builtins': + return f':{directive}:`~{module}.{name}`' + else: + parenthesis = '()' if directive in {'func', 'meth'} else '' + return f':{directive}:`{name}{parenthesis}`' + except UnboundLocalError as ex: + raise TypeError(f"{name!r} is neither a (builtin) function, method nor class") from ex #: An immutable mapping of to-be replaced substrings and their replacements. -README_MAPPING: Mapping[str, str] = MappingProxyType({'``': '|', '()': ''}) +README_MAPPING: Mapping[str, str] = MappingProxyType({ + '``': '|', + '()': '' +}) def load_readme(readme: Union[str, os.PathLike] = 'README.rst', @@ -410,47 +481,46 @@ def load_readme(readme: Union[str, os.PathLike] = 'README.rst', return ret -UserFunc = Callable[..., T] NoneFunc = Callable[..., None] -def skip_if(condition: Any) -> Callable[[UserFunc], Union[UserFunc, NoneFunc]]: - f"""A decorator which causes function calls to be ignored if :code:`bool(condition) is True`. +@set_docstring(f"""A decorator which causes function calls to be ignored if :code:`bool(condition) is True`. - A :exc:`UserWarning` is issued if **condition** evaluates to ``True``. +A :exc:`UserWarning` is issued if **condition** evaluates to :data:`True`. - Examples - -------- - .. code:: python +Examples +-------- +.. code:: python - >>> import warnings - >>> from assertionlib.functions import skip_if + >>> import warnings + >>> from assertionlib.functions import skip_if - >>> condition = Exception("Error") + >>> condition = Exception("Error") - >>> def func1() -> None: - ... print(True) + >>> def func1() -> None: + ... print(True) - >>> @skip_if(condition) - ... def func2() -> None: - ... print(True) + >>> @skip_if(condition) + ... def func2() -> None: + ... print(True) - >>> func1() - True + >>> func1() + True - >>> with warnings.catch_warnings(): # Convert the warning into a raised exception - ... warnings.simplefilter("error", UserWarning) - ... func2() - Traceback (most recent call last): - ... - UserWarning: Exception('Error'{COMMA}) evaluated to True; skipping call to func2(...) - - """ + >>> with warnings.catch_warnings(): # Convert the warning into a raised exception + ... warnings.simplefilter("error", UserWarning) + ... func2() + Traceback (most recent call last): + ... + UserWarning: Exception('Error'{COMMA}) evaluated to True; skipping call to func2(...) +""") # noqa: E501 +def skip_if(condition: Any) -> Callable[[FT], Union[FT, NoneFunc]]: + """Placeholder.""" def skip() -> None: return None - def decorator(func: UserFunc) -> Union[UserFunc, NoneFunc]: + def decorator(func: FT) -> Union[FT, NoneFunc]: @functools.wraps(func) def wrapper(*args: Any, **kwargs: Any) -> Optional[T]: if not condition: @@ -464,67 +534,3 @@ def wrapper(*args: Any, **kwargs: Any) -> Optional[T]: return cast(None, skip()) return wrapper return decorator - - -def len_eq(a: Sized, b: int) -> bool: - """Check if the length of **a** is equivalent to **b**: :code:`len(a) == b`.""" - return len(a) == b - - -def str_eq(a: T, b: str, str_converter: Callable[[T], str] = repr) -> bool: - """Check if the string-representation of **a** is equivalent to **b**: :code:`repr(a) == b`.""" - return str_converter(a) == b - - -def shape_eq(a: ndarray, b: Union[ndarray, Tuple[int, ...]]) -> bool: - """Check if the shapes of **a** and **b** are equivalent: :code:`a.shape == getattr(b, 'shape', b)`. - - **b** should be either an object with the ``shape`` attribute (*e.g.* a NumPy array) - or a :class:`tuple` representing a valid array shape. - - """ # noqa - return a.shape == getattr(b, 'shape', b) - - -def function_eq(func1: FunctionType, func2: FunctionType) -> bool: - """Check if two functions are equivalent by checking if their :attr:`__code__` is identical. - - **func1** and **func2** should be instances of :class:`~types.FunctionType` - or any other object with access to the :attr:`__code__` attribute. - - Examples - -------- - .. code:: python - - >>> from assertionlib.functions import function_eq - - >>> func1 = lambda x: x + 5 - >>> func2 = lambda x: x + 5 - >>> func3 = lambda x: 5 + x - - >>> print(function_eq(func1, func2)) - True - - >>> print(function_eq(func1, func3)) - False - - """ - code1 = None - try: - code1 = func1.__code__ - code2 = func2.__code__ - except AttributeError as ex: - name, obj = ('func1', func1) if code1 is None else ('func2', func2) - raise TypeError(f"{name!r} expected a function or object with the '__code__' attribute; " - f"observed type: {obj.__class__.__name__!r}") from ex - - iterator = zip_longest(dis.get_instructions(code1), dis.get_instructions(code2)) - tup_list = [(_sanitize_instruction(i), _sanitize_instruction(j)) for i, j in iterator] - return all([i == j for i, j in tup_list]) - - -def _sanitize_instruction(instruction: Optional[dis.Instruction]) -> Optional[dis.Instruction]: - """Sanitize the supplied instruction by setting :attr:`Instruction.starts_line` to ``None``.""" # noqa - if instruction is None: - return None - return instruction._replace(starts_line=None) diff --git a/assertionlib/manager.py b/assertionlib/manager.py index ab39e4f..f079019 100644 --- a/assertionlib/manager.py +++ b/assertionlib/manager.py @@ -1,8 +1,4 @@ -""" -assertionlib.manager -==================== - -A module containing the actual :class:`AssertionManager` class. +"""A module containing the actual :class:`AssertionManager` class. Index ----- @@ -52,6 +48,7 @@ AssertionManager.sub AssertionManager.truediv AssertionManager.truth + AssertionManager.length_hint Assertions based on the builtin :mod:`os.path` module. @@ -75,7 +72,7 @@ AssertionManager.isinf AssertionManager.isnan -Assertions based on :mod:`builtin` functions. +Assertions based on the builtin :mod:`builtins` module. .. autosummary:: :nosignatures: @@ -87,14 +84,14 @@ AssertionManager.len AssertionManager.any AssertionManager.all - + AssertionManager.isdisjoint + AssertionManager.round Miscellaneous assertions. .. autosummary:: :nosignatures: - AssertionManager.allclose AssertionManager.len_eq AssertionManager.str_eq AssertionManager.shape_eq @@ -145,6 +142,7 @@ .. automethod:: AssertionManager.sub .. automethod:: AssertionManager.truediv .. automethod:: AssertionManager.truth +.. automethod:: AssertionManager.length_hint Assertions based on the builtin :mod:`os.path` module ----------------------------------------------------- @@ -162,8 +160,8 @@ .. automethod:: AssertionManager.isinf .. automethod:: AssertionManager.isnan -Assertions based on :class:`builtin` functions --------------------------------------------------------- +Assertions based on the builtin :mod:`builtins` module +------------------------------------------------------ .. automethod:: AssertionManager.callable .. automethod:: AssertionManager.hasattr .. automethod:: AssertionManager.isinstance @@ -171,10 +169,11 @@ .. automethod:: AssertionManager.len .. automethod:: AssertionManager.any .. automethod:: AssertionManager.all +.. automethod:: AssertionManager.isdisjoint +.. automethod:: AssertionManager.round Miscellaneous assertions ------------------------ -.. automethod:: AssertionManager.allclose .. automethod:: AssertionManager.len_eq .. automethod:: AssertionManager.str_eq .. automethod:: AssertionManager.shape_eq @@ -190,17 +189,21 @@ import builtins import textwrap import operator +import functools from types import MappingProxyType -from inspect import Parameter from string import ascii_lowercase -from typing import (Callable, Any, Type, Set, Optional, Mapping, Sequence, cast, Iterable, - FrozenSet, TypeVar) +from inspect import Parameter +from typing import ( + Callable, Any, Type, Set, Optional, Mapping, Sequence, cast, Iterable, + FrozenSet, TypeVar, NoReturn, Union +) from .ndrepr import aNDRepr -from .functions import bind_callable, len_eq, str_eq, shape_eq, function_eq +from .functions import bind_callable, set_docstring +from .assertion_functions import len_eq, str_eq, shape_eq, function_eq, isdisjoint from .dataclass import AbstractDataClass, _MetaADC -if sys.version_info <= (3, 6): +if sys.version_info < (3, 7): COMMA = ',' else: COMMA = '' @@ -210,11 +213,14 @@ T = TypeVar('T') -def return_value(value: T) -> T: +def _return_value(value: T) -> T: """Return the supplied **value** in unaltered form.""" return value +_return_value.__name__ = _return_value.__qualname__ = '' + + class _MetaAM(_MetaADC): """The meta-class of :class:`AssertionManager`. @@ -225,45 +231,39 @@ class _MetaAM(_MetaADC): #: A :class:`frozenset` of to-be ignored functions in :mod:`operator`. EXCLUDE: FrozenSet[str] = frozenset({ - 'setitem', 'delitem', 'attrgetter', 'methodcaller', 'itemgetter', 'length_hint' + 'setitem', 'delitem', 'attrgetter', 'methodcaller', 'itemgetter' }) #: A :class:`frozenset` of callables which need an assertion function. INCLUDE: FrozenSet[Callable] = frozenset({ os.path.isfile, os.path.isdir, os.path.isabs, os.path.islink, os.path.ismount, math.isclose, math.isfinite, math.isinf, math.isnan, - isinstance, issubclass, callable, hasattr, len, bool, any, all, - len_eq, str_eq, shape_eq, function_eq + isinstance, issubclass, callable, hasattr, len, any, all, round, + len_eq, str_eq, shape_eq, function_eq, isdisjoint }) def __new__(mcls, name, bases, namespace) -> '_MetaAM': # noqa: N804 cls = cast('_MetaAM', super().__new__(mcls, name, bases, namespace)) - exclude = mcls.EXCLUDE - include = mcls.INCLUDE - operator_set = set(operator.__all__) # type: ignore + operator_set: Set[str] = set(operator.__all__) - mcls.EXCLUDE # type: ignore # Iterature over the __all__ attribute of the operator builtin module for name in operator_set: - if name[1:] in operator_set or name[1:] + '_' in operator_set or name in exclude: - continue # Exclude inplace operations - - func = getattr(operator, name) + func: Callable = getattr(operator, name) bind_callable(cls, func, name) # Iterate over all remaining callables - for func in include: - name = func.__name__ - bind_callable(cls, func, name) + for func in mcls.INCLUDE: + bind_callable(cls, func) cls.allclose = cls.isclose # type: ignore # On windows os.path.isdir is an alias for the ._isdir function if hasattr(cls, '_isdir'): - cls.isdir = cls._isdir # type: ignore - cls.isdir.__name__ = 'isdir' # type: ignore - cls.isdir.__qualname__ = 'isdir' # type: ignore - cls.isdir.__doc__ = cls.isdir.__doc__.replace('_isdir', 'isdir') # type: ignore + cls.isdir = isdir = cls._isdir # type: ignore + isdir.__name__ = 'isdir' + isdir.__qualname__ = f'{cls.__name__}.isdir' + isdir.__doc__ = isdir.__doc__.replace('_isdir', 'isdir') del cls._isdir # type: ignore return cls @@ -276,9 +276,15 @@ def __repr__(self) -> str: return str(self.value) -class _NoneException(Exception): +class _NoneException(BaseException): """An empty exception used by :meth:`AssertionManager.assert_` incase the **exception** parameter is ``None``.""" # noqa + def __init__(self, *args: Any) -> NoReturn: # type: ignore + raise TypeError(f"{self.__class__.__name__!r} cannot not be initiated") + + +ExcType = Union[Type[_NoneException], Type[Exception]] + class AssertionManager(AbstractDataClass, metaclass=_MetaAM): """A class for performing assertions and providing informative exception messages. @@ -304,7 +310,7 @@ class AssertionManager(AbstractDataClass, metaclass=_MetaAM): which in turn should produce a string representation of passed objects. If ``None``, default the builtin :func:`repr` function. - _repr_fallback : :class:`~collections.abc.Callable` [[:data:`~typing.Any`], :class:`str`] + _repr_fallback : :class:`Callable[[Any], str]` A fallback value in case :attr:`AssertionManager.repr_instance` is ``None``. _maxstring_fallback : :class:`int` @@ -312,17 +318,17 @@ class AssertionManager(AbstractDataClass, metaclass=_MetaAM): """ - _PRIVATE_ATTR: Set[str] = frozenset({'_repr_fallback', '_maxstring_fallback'}) # type: ignore + _PRIVATE_ATTR: Set[str] = frozenset({'repr_fallback', 'maxstring_fallback'}) # type: ignore def __init__(self, repr_instance: Optional[reprlib.Repr] = aNDRepr) -> None: """Initialize an :class:`AssertionManager` instance.""" super().__init__() self.repr_instance = repr_instance - # Back values for AssertionManager.repr and AssertionManager.maxstring + # Backup values for AssertionManager.repr and AssertionManager.maxstring # Used when repr_instance is None - self._repr_fallback: Callable[[Any], str] = builtins.repr - self._maxstring_fallback = 80 + self.repr_fallback: Callable[[Any], str] = builtins.repr + self.maxstring_fallback = 80 @property def repr(self) -> Callable[[Any], str]: @@ -330,7 +336,7 @@ def repr(self) -> Callable[[Any], str]: try: return self.repr_instance.repr # type: ignore except AttributeError: # If self.repr_instance is None - return self._repr_fallback + return self.repr_fallback @property def maxstring(self) -> int: @@ -338,7 +344,7 @@ def maxstring(self) -> int: try: return self.repr_instance.maxstring # type: ignore except AttributeError: # If self.repr_instance is None - return self._maxstring_fallback + return self.maxstring_fallback # Public methods @@ -356,28 +362,31 @@ def assert_(self, func: Callable[..., T], *args: Any, invert: bool = False, Parameters ---------- - func : :class:`~collections.abc.Callable` + func : :class:`Callable[..., T]` The callable whose output will be evaluated. \*args : :data:`~typing.Any` Positional arguments for **func**. - invert : :class:`bool` - If ``True``, invert the output of the assertion: + Keyword Arguments + ----------------- + invert : :class:`bool`, optional + If :data:`True`, invert the output of the assertion: :code:`assert not func(*args, **kwargs)`. exception : :class:`type` [:exc:`Exception`], optional Assert that **exception** is raised during/before the assertion operation. The only dissalowed value is :exc:`AssertionError`. - post_process : :class:`~collections.abc.Callable`, optional + post_process : :data:`Callable[[T], bool]`, optional Apply post-processing to the to-be asserted data before asserting aforementioned data. - Example functions would be the likes of :func:`~builtins.any` and :func:`~builtins.all`. + Example functions would be the likes of :func:`any()` and + :func:`all()`. - message : :data:`~typing.Any`, optional + message : :class:`str`, optional A custom error message to-be passed to the ``assert`` statement. - \**kwargs : :class:`str`, optional + \**kwargs : :data:`~typing.Any`, optional Keyword arguments for **func**. @@ -392,15 +401,17 @@ def assert_(self, func: Callable[..., T], *args: Any, invert: bool = False, __tracebackhide__ = True # Set exception to _NoneException - exception_ = cast(Type[Exception], _NoneException if exception is None else exception) - - if not (isinstance(exception_, type) and issubclass(exception_, Exception)): - raise TypeError("'exception' expected 'None' or an Exception type; " - f"observed {self.repr(exception)} " - f"of type {exception.__class__.__name__!r}") - elif exception_ is AssertionError: - raise ValueError("'AssertionError' is not allowed as value " - "for the 'exception' parameter") + if exception is None: + exc_type: ExcType = _NoneException + else: + if not (isinstance(exception, type) and issubclass(exception, Exception)): + raise TypeError(f"{'exception'!r} expected {None!r} or an Exception type; " + f"observed {self.repr(exception)} " + f"of type {exception.__class__.__name__!r}") + elif exception is AssertionError: + raise ValueError(f"{exception.__name__!r} is not allowed as value " + f"for the {'exception'!r} parameter") + exc_type = exception output: Any = None try: @@ -414,13 +425,13 @@ def assert_(self, func: Callable[..., T], *args: Any, invert: bool = False, else: assert post_process(output), message - if exception_ is not _NoneException: # i.e. the exception parameter is not None - message_ = f"Failed to raise {exception_.__name__!r}" + if exc_type is not _NoneException: # i.e. the exception parameter is not None + exc_msg = f"Failed to raise {exc_type.__name__!r}" if message is not None: - message_ += f'; {message}' - raise AssertionError(message_) + exc_msg += f'; {message}' + raise AssertionError(exc_msg) - except exception_: # This is the expected exception + except exc_type: # This is the expected exception pass # Not relevant if the exception parameter is None except Exception as ex: # This is an unexpected exception @@ -435,52 +446,53 @@ def assert_(self, func: Callable[..., T], *args: Any, invert: bool = False, else: raise exc from ex - def __call__(self, value: T, invert: bool = False, - post_process: Optional[Callable[[T], Any]] = None, - message: Optional[str] = None) -> None: - f"""Equivalent to :code:`assert value`. + @set_docstring(f"""Equivalent to :code:`assert value`. - Examples - -------- - .. code:: python + Examples + -------- + .. code:: python - >>> from assertionlib import assertion + >>> from assertionlib import assertion - >>> assertion(5 == 5) - >>> assertion(5 == 6) - Traceback (most recent call last): - ... - AssertionError: output = return_value(value); assert output - - exception: AssertionError = AssertionError(None{COMMA}) - - output: bool = False - value: bool = False + >>> assertion(5 == 5) + >>> assertion(5 == 6) + Traceback (most recent call last): + ... + AssertionError: output = (value); assert output + + exception: AssertionError = AssertionError(None{COMMA}) + + output: bool = False + value: bool = False - Note: :func:`return_value` is a function which, as the name implies, - returns the passed value in unaltered form. - Parameters - ---------- - value : :data:`~typing.Any` - The to-be asserted value. + Parameters + ---------- + value : :class:`T` + The to-be asserted value. - invert : :class:`bool` - If ``True``, invert the output of the assertion: - :code:`assert not value`. + Keyword Arguments + ----------------- + invert : :class:`bool` + If :data:`True`, invert the output of the assertion: + :code:`assert not value`. - post_process : :class:`~collections.abc.Callable`, optional - Apply post-processing to the to-be asserted data before asserting aforementioned data. - Example functions would be the likes of :func:`~builtins.any` and :func:`~builtins.all`. + post_process : :data:`Callable[[T], bool]`, optional + Apply post-processing to the to-be asserted data before asserting aforementioned data. + Example functions would be the likes of :func:`any()` and + :func:`all()`. - message : :data:`~typing.Any`, optional - A custom error message to-be passed to the ``assert`` statement. + message : :class:`str`, optional + A custom error message to-be passed to the ``assert`` statement. - :rtype: :data:`None` + :rtype: :data:`None` - """ - return self.assert_(return_value, value, invert=invert, + """) + def __call__(self, value: T, *, invert: bool = False, + post_process: Optional[Callable[[T], Any]] = None, + message: Optional[str] = None) -> None: + return self.assert_(_return_value, value, invert=invert, post_process=post_process, message=message) def add_to_instance(self, func: Callable, name: Optional[str] = None, @@ -494,12 +506,14 @@ def add_to_instance(self, func: Callable, name: Optional[str] = None, func : :class:`~collections.abc.Callable` The callable whose output will be asserted in the to-be created method. + Keyword Arguments + ----------------- name : :class:`str`, optional The name of the new method. If ``None``, use the name of **func**. override_attr : :class:`bool` - If ``False``, raise an :exc:`AttributeError` if a method with the same name already + If :data:`False`, raise an :exc:`AttributeError` if a method with the same name already exists in this instance. @@ -514,8 +528,8 @@ def add_to_instance(self, func: Callable, name: Optional[str] = None, """ name = name if name is not None else func.__name__ if not override_attr and hasattr(self, name): - raise AttributeError(f"{self.__class__.__name__!r} instance already has an attribute " - f"by the name of {name!r}") + raise AttributeError(f"The {self.__class__.__name__!r} instance has a pre-existing " + f"attribute by the name of {name!r}") bind_callable(self, func, name) # Add the name as private attribute @@ -523,69 +537,82 @@ def add_to_instance(self, func: Callable, name: Optional[str] = None, # Private methods - def _get_exc_message(self, ex: Exception, func: Callable[..., T], *args: Any, - invert: bool = False, output: Any = None, - post_process: Optional[Callable[[T], Any]] = None, - **kwargs: Any) -> str: - f"""Return a formatted exception message for failed assertions. + @set_docstring(f"""Return a formatted exception message for failed assertions. - Examples - -------- - .. code:: python - - >>> import operator - - >>> ex = TypeError('Fancy custom exception') - >>> func = operator.contains - >>> a = [1, 2, 3, 4] - >>> b = 5 - - >>> msg = assertion._get_exc_message(ex, func, a, b) - >>> raise AssertionError(msg) - Traceback (most recent call last): - ... - AssertionError: output = contains(a, b); assert output - - exception: TypeError = TypeError('Fancy custom exception'{COMMA}) - - output: NoneType = None - a: list = [1, 2, 3, 4] - b: int = 5 + Examples + -------- + .. code:: python - Parameters - ---------- - ex : :class:`Exception` - The exception raised by :meth:`AssertionManager.assert_`. + >>> def contains(a, b): + ... return b in a - func : :class:`~collections.abc.Callable` - The callable whose output has been evaluated. + >>> ex = TypeError('Fancy custom exception') + >>> a = [1, 2, 3, 4] + >>> b = 5 + + >>> msg = assertion._get_exc_message(ex, contains, a, b) + >>> raise AssertionError(msg) + Traceback (most recent call last): + ... + AssertionError: output = contains(a, b); assert output + + exception: TypeError = TypeError('Fancy custom exception'{COMMA}) + + output: NoneType = None + a: list = [1, 2, 3, 4] + b: int = 5 + + Parameters + ---------- + ex : :class:`Exception` + The exception raised by :meth:`AssertionManager.assert_`. - \\*args : :data:`~typing.Any` - Positional arguments supplied to **func**. + func : :class:`~collections.abc.Callable` + The callable whose output has been evaluated. - invert : :class:`bool` - If ``True``, invert the output of the assertion: :code:`not func(a, b, **kwargs)`. + \\*args : :data:`~typing.Any` + Positional arguments supplied to **func**. - output : :data:`~typing.Any`, optional - The output value of :code:`func(*args, **kwargs)` or :code:`not func(*args, **kwargs)`. + Keyword Arguments + ----------------- + invert : :class:`bool` + If :data:`True`, invert the output of the assertion: :code:`not func(a, b, **kwargs)`. - post_process : :class:`~collections.abc.Callable`, optional - Apply post-processing to the to-be asserted data before asserting aforementioned data. - Example functions would be the likes of :func:`~builtins.any` and :func:`~builtins.all`. + output : :data:`~typing.Any`, optional + The output value of :code:`func(*args, **kwargs)` or :code:`not func(*args, **kwargs)`. - \\**kwargs : :data:`~typing.Any`, optional - Further optional keyword arguments supplied to **func**. + post_process : :class:`~collections.abc.Callable`, optional + Apply post-processing to the to-be asserted data before asserting aforementioned data. + Example functions would be the likes of :func:`~builtins.any` and :func:`~builtins.all`. - Returns - ------- - :class:`str` - A newly-formatted exception message to-be raised by :meth:`AssertionManager.assert_`. + \\**kwargs : :data:`~typing.Any`, optional + Further optional keyword arguments supplied to **func**. - """ # noqa + Returns + ------- + :class:`str` + A newly-formatted exception message to-be raised by :meth:`AssertionManager.assert_`. + + """) + def _get_exc_message(self, ex: Exception, func: Callable[..., T], *args: Any, + invert: bool = False, output: Any = None, + post_process: Optional[Callable[[T], Any]] = None, + **kwargs: Any) -> str: __tracebackhide__ = True # Construct a string-reprensentation of the to-be assert function - name: str = getattr(func, '__qualname__', func.__name__) + try: + name: str = getattr(func, '__qualname__', func.__name__) + except AttributeError: + if not callable(func): + raise TypeError(f"{'func'!r} expected a callable object; observed type: " + f"{func.__class__.__name__!r}") + + # func could potentially be a functools.partial object + if isinstance(func, functools.partial): + name = repr(func) + else: + name = func.__class__.__name__.lower() # Construct a signature of the to-be asserted function try: @@ -605,8 +632,6 @@ def _get_exc_message(self, ex: Exception, func: Callable[..., T], *args: Any, # Create a description of the to-be returned value ret += '\n\n' + self._get_prm_description('output', output) - if post_process is not None: - ret += '\n' + self._get_prm_description('post_process', post_process) # Create a description of positional arguments for key, value in zip(parameters, args): @@ -616,6 +641,8 @@ def _get_exc_message(self, ex: Exception, func: Callable[..., T], *args: Any, for key, value in kwargs.items(): ret += '\n' + self._get_prm_description(key, value) + if post_process is not None: + ret += '\n' + self._get_prm_description('post_process', post_process) return ret @staticmethod @@ -629,6 +656,8 @@ def _get_exc_signature(signature: inspect.Signature, args: Sequence[str], * Extra positional/keyword arguments supplied to the callable. """ # noqa + __tracebackhide__ = True + # Unpack parameters empty = inspect._empty # type: ignore parameters = signature.parameters @@ -656,6 +685,8 @@ def _get_prm_description(self, key: str, value: Any) -> str: newline character or is longer than :attr:`AssertionManager.maxstring`. """ # noqa + __tracebackhide__ = True + _value_str = f'{self.repr(value)}' if not isinstance(value, Exception) else repr(value) key_str = f'{key}: {value.__class__.__name__} =' diff --git a/assertionlib/manager.pyi b/assertionlib/manager.pyi index bec1e65..3b8a817 100644 --- a/assertionlib/manager.pyi +++ b/assertionlib/manager.pyi @@ -1,478 +1,649 @@ +"""Stub files for :mode:`assertionlib.manager`.""" + import os import sys import types import reprlib import inspect -import builtins from typing import ( Any, + Hashable, + AbstractSet, Callable, FrozenSet, Optional, Type, TypeVar, Tuple, - Dict, Union, Sized, SupportsFloat, + SupportsInt, SupportsAbs, + SupportsRound, Sequence, Mapping, Container, - ClassVar, Iterable, + NoReturn, + type_check_only, overload ) -import numpy as np +import numpy as np # type: ignore from .dataclass import AbstractDataClass, _MetaADC +from .protocol import ( + _SupportsIndex, + _SupportsShape, + _SupportsCode, + _SupportsAdd, + _SupportsSub, + _SupportsMul, + _SupportsFloordiv, + _SupportsTruediv, + _SupportsPow, + _SupportsMatmul, + _SupportsMod, + _SupportsGt, + _SupportsLt, + _SupportsGe, + _SupportsLe, + _SupportsNeg, + _SupportsInvert, + _SupportsRshift, + _SupportsLshift, + _SupportsPos, + _SupportsXor, + _SupportsOr, + _SupportsGetitem, + _SupportsEq, + _SupportsNe, + _SupportsBool as __SupportsBool, + _SupportsAnd, + _SupportsLengthHint +) if sys.version_info >= (3, 8): - from typing import Final, Protocol, SupportsIndex as _SupportsIndex + from typing import Final else: - from typing_extensions import Final, Protocol - - class _SupportsIndex(Protocol): - def __index__(self) -> int: - pass - -class _SupportsShape(Protocol): - shape: Tuple[int, ...] - -class _SupportsCode(Protocol): - __code__: types.CodeType + from typing_extensions import Final T = TypeVar('T') -KT = TypeVar('KT') -VT = TypeVar('VT') +T1 = TypeVar('T1') +T2 = TypeVar('T2') +RT = TypeVar('RT') + +_SupportsBool = Optional[__SupportsBool] +PostProcessAny = Optional[Callable[[Any], Any]] +PostProcessInt = Optional[Callable[[int], _SupportsBool]] +PostProcessBool = Optional[Callable[[bool], _SupportsBool]] +@type_check_only class _MetaAM(_MetaADC): EXCLUDE: FrozenSet[str] = ... INCLUDE: FrozenSet[Callable] = ... -class _Str: - value: Any = ... - def __init__(self, value: str) -> None: ... - -class _NoneException(Exception): ... - class AssertionManager(AbstractDataClass, metaclass=_MetaAM): repr_instance: Optional[reprlib.Repr] - _repr_fallback: Callable[[Any], str] - _maxstring_fallback: int + repr_fallback: Callable[[object], str] + maxstring_fallback: int def __init__(self, repr_instance: Optional[reprlib.Repr] = ...) -> None: ... @property - def repr(self) -> Callable[[Any], str]: ... + def repr(self) -> Callable[[object], str]: ... @property def maxstring(self) -> int: ... - def assert_(self, __func: Callable[..., T], *args: Any, invert: builtins.bool = ..., exception: Optional[Type[Exception]] = ..., post_process: Optional[Callable[[T], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... - def __call__(self, value: T, invert: builtins.bool = ..., post_process: Optional[Callable[[T], Any]] = ..., message: Optional[str] = ...) -> None: ... - def add_to_instance(self, func: Callable[..., Any], name: Optional[str] = ..., override_attr: builtins.bool = ...) -> None: ... - def _get_exc_message(self, __ex: Exception, __func: Callable, *args: Any, invert: bool = ..., output: Any = ..., post_process: Optional[Callable[[Any], Any]] = ..., **kwargs: Any) -> str: ... - @staticmethod - def _get_exc_signature(signature: inspect.Signature, args: Sequence[str], kwargs: Mapping[str, Any] = ...) -> inspect.Signature: ... - def _get_prm_description(self, key: str, value: Any) -> str: ... + + @overload + def assert_(self, __func: Callable[..., RT], *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... + @overload + def assert_(self, __func: Callable[..., RT], *args: Any, exception: Optional[Type[Exception]] = ..., invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def __call__(self, __value: RT, *, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... + def add_to_instance(self, func: Callable[..., Any], name: Optional[str] = ..., override_attr: bool = ...) -> None: ... # operators @overload - def abs(self, __a: SupportsAbs[T], *, invert: builtins.bool = ..., post_process: Optional[Callable[[T], Any]] = ..., message: Optional[str] = ...) -> None: ... + def abs(self, __a: SupportsAbs[RT], *, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def abs(self, __a: SupportsAbs[T], *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[T], Any]] = ..., message: Optional[str] = ...) -> None: ... + def abs(self, __a: SupportsAbs[RT], *, exception: None, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def abs(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def abs(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... + @overload + def abs(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def add(self, __a: Any, __b: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def add(self, __a: _SupportsAdd[T, RT], __b: T, *, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... + @overload + def add(self, __a: _SupportsAdd[T, RT], __b: T, *, exception: None, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def add(self, __a: Any, __b: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def add(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def add(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def add(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def and_(self, __a: Any, __b: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def and_(self, __a: _SupportsAnd[T, RT], __b: T, *, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... + @overload + def and_(self, __a: _SupportsAnd[T, RT], __b: T, *, exception: None, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def and_(self, __a: Any, __b: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def and_(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def and_(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def and_(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def concat(self, __a: Sequence[T], __b: Sequence[T], *, invert: builtins.bool = ..., post_process: Optional[Callable[[Sequence[T]], Any]] = ..., message: Optional[str] = ...) -> None: ... + def concat(self, __a: Sequence[T1], __b: Sequence[T2], *, invert: bool = ..., post_process: Optional[Callable[[Sequence[Union[T1, T2]]], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def concat(self, __a: Sequence[T], __b: Sequence[T], *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[Sequence[T]], Any]] = ..., message: Optional[str] = ...) -> None: ... + def concat(self, __a: Sequence[T1], __b: Sequence[T2], *, exception: None, invert: bool = ..., post_process: Optional[Callable[[Sequence[Union[T1, T2]]], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def concat(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def concat(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... + @overload + def concat(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def contains(self, __a: Container[Any], __b: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def contains(self, __a: Container[Any], __b: Any, *, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... + @overload + def contains(self, __a: Container[Any], __b: Any, *, exception: None, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def contains(self, __a: Container[Any], __b: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def contains(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def contains(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def contains(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def countOf(self, __a: Container[Any], __b: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[int], Any]] = ..., message: Optional[str] = ...) -> None: ... + def countOf(self, __a: Iterable[Any], __b: Any, *, invert: bool = ..., post_process: PostProcessInt = ..., message: Optional[str] = ...) -> None: ... + @overload + def countOf(self, __a: Iterable[Any], __b: Any, *, exception: None, invert: bool = ..., post_process: PostProcessInt = ..., message: Optional[str] = ...) -> None: ... @overload - def countOf(self, __a: Container[Any], __b: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[int], Any]] = ..., message: Optional[str] = ...) -> None: ... + def countOf(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def countOf(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def countOf(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + # .ne() and .eq() need an extra overload for __a = None as NoneType.__eq__() is not annotated + + @overload + def eq(self, __a: _SupportsEq[T, RT], __b: T, *, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... + @overload + def eq(self, __a: None, __b: Any, *, invert: bool = ..., post_process: Optional[Callable[[bool], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def eq(self, __a: Any, __b: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def eq(self, __a: _SupportsEq[T, RT], __b: T, *, exception: None, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def eq(self, __a: Any, __b: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def eq(self, __a: None, __b: Any, *, exception: None, invert: bool = ..., post_process: Optional[Callable[[bool], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def eq(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def eq(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... + @overload + def eq(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def floordiv(self, __a: Any, __b: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def floordiv(self, __a: _SupportsFloordiv[T, RT], __b: T, *, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... + @overload + def floordiv(self, __a: _SupportsFloordiv[T, RT], __b: T, *, exception: None, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def floordiv(self, __a: Any, __b: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def floordiv(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def floordiv(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def floordiv(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def ge(self, __a: Any, __b: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def ge(self, __a: _SupportsGe[T, RT], __b: T, *, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def ge(self, __a: Any, __b: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def ge(self, __a: _SupportsGe[T, RT], __b: T, *, exception: None, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def ge(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def ge(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... + @overload + def ge(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def getitem(self, __a: Sequence[T], __b: _SupportsIndex, *, invert: builtins.bool = ..., post_process: Optional[Callable[[T], Any]] = ..., message: Optional[str] = ...) -> None: ... + def getitem(self, __a: _SupportsGetitem[T, RT], __b: T, *, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... + @overload + def getitem(self, __a: _SupportsGetitem[T, RT], __b: T, *, exception: None, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... + @overload + def getitem(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def getitem(self, __a: Mapping[KT, VT], __b: KT, *, invert: builtins.bool = ..., post_process: Optional[Callable[[VT], Any]] = ..., message: Optional[str] = ...) -> None: ... + def getitem(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + + @overload + def gt(self, __a: _SupportsGt[T, RT], __b: T, *, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def getitem(self, __a: Sequence[T], __b: _SupportsIndex, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[T], Any]] = ..., message: Optional[str] = ...) -> None: ... + def gt(self, __a: _SupportsGt[T, RT], __b: T, *, exception: None, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def getitem(self, __a: Mapping[KT, VT], __b: KT, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[VT], Any]] = ..., message: Optional[str] = ...) -> None: ... + def gt(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def getitem(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def gt(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def gt(self, __a: Any, __b: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def index(self, __a: _SupportsIndex, *, invert: bool = ..., post_process: PostProcessInt = ..., message: Optional[str] = ...) -> None: ... + @overload + def index(self, __a: _SupportsIndex, *, exception: None, invert: bool = ..., post_process: PostProcessInt = ..., message: Optional[str] = ...) -> None: ... @overload - def gt(self, __a: Any, __b: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def index(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def gt(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def index(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def index(self, __a: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[int], Any]] = ..., message: Optional[str] = ...) -> None: ... + def indexOf(self, __a: Iterable[Any], __b: Any, *, invert: bool = ..., post_process: PostProcessInt = ..., message: Optional[str] = ...) -> None: ... @overload - def index(self, __a: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[int], Any]] = ..., message: Optional[str] = ...) -> None: ... + def indexOf(self, __a: Iterable[Any], __b: Any, *, exception: None = ..., invert: bool = ..., post_process: PostProcessInt = ..., message: Optional[str] = ...) -> None: ... @overload - def index(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def indexOf(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... + @overload + def indexOf(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def indexOf(self, __a: Sequence[T], __b: T, *, invert: builtins.bool = ..., post_process: Optional[Callable[[int], Any]] = ..., message: Optional[str] = ...) -> None: ... + def inv(self, __a: _SupportsInvert[RT], *, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... + @overload + def inv(self, __a: _SupportsInvert[RT], *, exception: None, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def indexOf(self, __a: Sequence[T], __b: T, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[int], Any]] = ..., message: Optional[str] = ...) -> None: ... + def inv(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def indexOf(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def inv(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def inv(self, __a: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def invert(self, __a: _SupportsInvert[RT], *, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... + @overload + def invert(self, __a: _SupportsInvert[RT], *, exception: None, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def inv(self, __a: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def invert(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def inv(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def invert(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def invert(self, __a: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def is_(self, __a: object, __b: object, *, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def invert(self, __a: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def is_(self, __a: object, __b: object, *, exception: None, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def invert(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def is_(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... + @overload + def is_(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def is_(self, __a: Any, __b: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def is_not(self, __a: object, __b: object, *, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... + @overload + def is_not(self, __a: object, __b: object, *, exception: None, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def is_(self, __a: Any, __b: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def is_not(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def is_(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def is_not(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def is_not(self, __a: Any, __b: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def le(self, __a: _SupportsLe[T, RT], __b: T, *, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def is_not(self, __a: Any, __b: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def le(self, __a: _SupportsLe[T, RT], __b: T, *, exception: None, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def is_not(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def le(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... + @overload + def le(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def le(self, __a: Any, __b: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def lshift(self, __a: _SupportsLshift[T, RT], __b: T, *, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... + @overload + def lshift(self, __a: _SupportsLshift[T, RT], __b: T, *, exception: None, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def le(self, __a: Any, __b: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def lshift(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def le(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def lshift(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def lshift(self, __a: Any, __b: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def lt(self, __a: _SupportsLt[T, RT], __b: T, *, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... + @overload + def lt(self, __a: _SupportsLt[T, RT], __b: T, *, exception: None, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def lshift(self, __a: Any, __b: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def lt(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def lshift(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def lt(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def lt(self, __a: Any, __b: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def matmul(self, __a: _SupportsMatmul[T, RT], __b: T, *, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def lt(self, __a: Any, __b: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def matmul(self, __a: _SupportsMatmul[T, RT], __b: T, *, exception: None, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def lt(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def matmul(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... + @overload + def matmul(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def matmul(self, __a: Any, __b: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def mod(self, __a: _SupportsMod[T, RT], __b: T, *, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... + @overload + def mod(self, __a: _SupportsMod[T, RT], __b: T, *, exception: None, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def matmul(self, __a: Any, __b: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def mod(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def matmul(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def mod(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def mod(self, __a: Any, __b: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def mul(self, __a: _SupportsMul[T, RT], __b: T, *, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def mod(self, __a: Any, __b: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def mul(self, __a: _SupportsMul[T, RT], __b: T, *, exception: None, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def mod(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def mul(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... + @overload + def mul(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + + # .ne() and .eq() need an extra overload for __a = None as NoneType.__eq__() is not annotated @overload - def mul(self, __a: Any, __b: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def ne(self, __a: _SupportsNe[T, RT], __b: T, *, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... + @overload + def ne(self, __a: None, __b: Any, *, invert: bool = ..., post_process: Optional[Callable[[bool], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... + @overload + def ne(self, __a: _SupportsNe[T, RT], __b: T, *, exception: None, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... + @overload + def ne(self, __a: None, __b: Any, *, exception: None, invert: bool = ..., post_process: Optional[Callable[[bool], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def mul(self, __a: Any, __b: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def ne(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def mul(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def ne(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def ne(self, __a: Any, __b: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def neg(self, __a: _SupportsNeg[RT], *, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def ne(self, __a: Any, __b: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def neg(self, __a: _SupportsNeg[RT], *, exception: None, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def ne(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def neg(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... + @overload + def neg(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def neg(self, __a: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def not_(self, __a: _SupportsBool, *, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... + @overload + def not_(self, __a: _SupportsBool, *, exception: None, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def neg(self, __a: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def not_(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def neg(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def not_(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def not_(self, __a: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def or_(self, __a: _SupportsOr[T, RT], __b: T, *, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... + @overload + def or_(self, __a: _SupportsOr[T, RT], __b: T, *, exception: None, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def not_(self, __a: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def or_(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def not_(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def or_(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def or_(self, __a: Any, __b: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def pos(self, __a: _SupportsPos[RT], *, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def or_(self, __a: Any, __b: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def pos(self, __a: _SupportsPos[RT], *, exception: None, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def or_(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def pos(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... + @overload + def pos(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def pos(self, __a: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def pow(self, __a: _SupportsPow[T, RT], __b: T, *, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... + @overload + def pow(self, __a: _SupportsPow[T, RT], __b: T, *, exception: None, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def pos(self, __a: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def pow(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def pos(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def pow(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def pow(self, __a: Any, __b: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def rshift(self, __a: _SupportsRshift[T, RT], __b: T, *, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... + @overload + def rshift(self, __a: _SupportsRshift[T, RT], __b: T, *, exception: None, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def pow(self, __a: Any, __b: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def rshift(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def pow(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def rshift(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def rshift(self, __a: Any, __b: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def sub(self, __a: _SupportsSub[T, RT], __b: T, *, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def rshift(self, __a: Any, __b: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def sub(self, __a: _SupportsSub[T, RT], __b: T, *, exception: None, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def rshift(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def sub(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... + @overload + def sub(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def sub(self, __a: Any, __b: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def truediv(self, __a: _SupportsTruediv[T, RT], __b: T, *, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... + @overload + def truediv(self, __a: _SupportsTruediv[T, RT], __b: T, *, exception: None, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def sub(self, __a: Any, __b: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def truediv(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def sub(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def truediv(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def truediv(self, __a: Any, __b: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def truth(self, __a: _SupportsBool, *, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... + @overload + def truth(self, __a: _SupportsBool, *, exception: None, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def truediv(self, __a: Any, __b: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ...) -> None: ... + def truth(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def truediv(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def truth(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def truth(self, __a: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def xor(self, __a: _SupportsXor[T, RT], __b: T, *, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def truth(self, __a: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def xor(self, __a: _SupportsXor[T, RT], __b: T, *, exception: None, invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def truth(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def xor(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... + @overload + def xor(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + + @overload + def length_hint(self, __obj: Union[Sized, _SupportsLengthHint], *, default: int = ..., invert: bool = ..., post_process: PostProcessInt = ..., message: Optional[str] = ...) -> None: ... + @overload + def length_hint(self, __obj: Union[Sized, _SupportsLengthHint], *, exception: None, default: int = ..., invert: bool = ..., post_process: PostProcessInt = ..., message: Optional[str] = ...) -> None: ... + @overload + def length_hint(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... + @overload + def length_hint(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... # builtins @overload - def callable(self, __obj: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def callable(self, __obj: Any, *, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... + @overload + def callable(self, __obj: Any, *, exception: None, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... + @overload + def callable(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... + @overload + def callable(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + + @overload + def isinstance(self, __obj: Any, __class_or_tuple: Union[type, Tuple[type, ...]], *, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... + @overload + def isinstance(self, __obj: Any, __class_or_tuple: Union[type, Tuple[type, ...]], *, exception: None, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def callable(self, __obj: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def isinstance(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def callable(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def isinstance(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def isinstance(self, __obj: Any, __class_or_tuple: Union[type, Tuple[type, ...]], *, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def issubclass(self, __cls: type, __class_or_tuple: Union[type, Tuple[type, ...]], *, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def isinstance(self, __obj: Any, __class_or_tuple: Union[type, Tuple[type, ...]], *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def issubclass(self, __cls: type, __class_or_tuple: Union[type, Tuple[type, ...]], *, exception: None, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def isinstance(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def issubclass(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... + @overload + def issubclass(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def issubclass(self, __cls: type, __class_or_tuple: Union[type, Tuple[type, ...]], *, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def hasattr(self, __obj: Any, __name: str, *, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... + @overload + def hasattr(self, __obj: Any, __name: str, *, exception: None, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def issubclass(self, __cls: type, __class_or_tuple: Union[type, Tuple[type, ...]], *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def hasattr(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def issubclass(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def hasattr(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def bool(self, __o: Any, *, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def len(self, __obj: Sized, *, invert: bool = ..., post_process: PostProcessInt = ..., message: Optional[str] = ...) -> None: ... + @overload + def len(self, __obj: Sized, *, exception: None, invert: bool = ..., post_process: PostProcessInt = ..., message: Optional[str] = ...) -> None: ... @overload - def bool(self, __o: Any, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def len(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def bool(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def len(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def hasattr(self, __obj: Any, name: str, *, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def any(self, __obj: Iterable[Optional[_SupportsBool]], *, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def hasattr(self, __obj: Any, name: str, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def any(self, __obj: Iterable[Optional[_SupportsBool]], *, exception: None, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def hasattr(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def any(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... + @overload + def any(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def len(self, __obj: Sized, *, invert: builtins.bool = ..., post_process: Optional[Callable[[int], Any]] = ..., message: Optional[str] = ...) -> None: ... + def all(self, __obj: Iterable[Optional[_SupportsBool]], *, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... + @overload + def all(self, __obj: Iterable[Optional[_SupportsBool]], *, exception: None, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def len(self, __obj: Sized, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[int], Any]] = ..., message: Optional[str] = ...) -> None: ... + def all(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def len(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def all(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def any(self, __obj: Iterable[Any], *, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def isdisjoint(self, __a: Iterable[Hashable], __b: Iterable[Hashable], *, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... + @overload + def isdisjoint(self, __a: Iterable[Hashable], __b: Iterable[Hashable], *, exception: None, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def any(self, __obj: Iterable[Any], *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def isdisjoint(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def any(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def isdisjoint(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def all(self, __obj: Iterable[Any], *, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def round(self, __number: SupportsRound[RT], *, ndigits: int = ..., invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def all(self, __obj: Iterable[Any], *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def round(self, __number: SupportsRound[RT], *, exception: None, ndigits: int = ..., invert: bool = ..., post_process: Optional[Callable[[RT], _SupportsBool]] = ..., message: Optional[str] = ...) -> None: ... @overload - def all(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def round(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... + @overload + def round(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... # os @overload - def isabs(self, __s: Union[str, bytes, os.PathLike], *, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def isabs(self, __s: Union[str, bytes, os.PathLike], *, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... + @overload + def isabs(self, __s: Union[str, bytes, os.PathLike], *, exception: None, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def isabs(self, __s: Union[str, bytes, os.PathLike], *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def isabs(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def isabs(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def isabs(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def islink(self, __path: Union[str, bytes, os.PathLike], *, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def islink(self, __path: Union[str, bytes, os.PathLike], *, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... + @overload + def islink(self, __path: Union[str, bytes, os.PathLike], *, exception: None, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def islink(self, __path: Union[str, bytes, os.PathLike], *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def islink(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def islink(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def islink(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def ismount(self, __path: Union[str, bytes, os.PathLike], *, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def ismount(self, __path: Union[str, bytes, os.PathLike], *, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def ismount(self, __path: Union[str, bytes, os.PathLike], *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def ismount(self, __path: Union[str, bytes, os.PathLike], *, exception: None, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def ismount(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def ismount(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... + @overload + def ismount(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def isdir(self, __s: Union[str, bytes, os.PathLike], *, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def isdir(self, __s: Union[str, bytes, os.PathLike], *, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... + @overload + def isdir(self, __s: Union[str, bytes, os.PathLike], *, exception: None, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def isdir(self, __s: Union[str, bytes, os.PathLike], *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def isdir(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def isdir(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def isdir(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def isfile(self, __path: Union[str, bytes, os.PathLike], *, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def isfile(self, __path: Union[str, bytes, os.PathLike], *, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def isfile(self, __path: Union[str, bytes, os.PathLike], *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def isfile(self, __path: Union[str, bytes, os.PathLike], *, exception: None, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def isfile(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def isfile(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... + @overload + def isfile(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... # math @overload - def isinf(self, __x: SupportsFloat, *, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def isinf(self, __x: SupportsFloat, *, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... + @overload + def isinf(self, __x: SupportsFloat, *, exception: None, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def isinf(self, __x: SupportsFloat, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def isinf(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def isinf(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def isinf(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def isnan(self, __x: SupportsFloat, *, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def isnan(self, __x: SupportsFloat, *, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... + @overload + def isnan(self, __x: SupportsFloat, *, exception: None, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def isnan(self, __x: SupportsFloat, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def isnan(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def isnan(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def isnan(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def isfinite(self, __x: SupportsFloat, *, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def isfinite(self, __x: SupportsFloat, *, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def isfinite(self, __x: SupportsFloat, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def isfinite(self, __x: SupportsFloat, *, exception: None, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def isfinite(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def isfinite(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... + @overload + def isfinite(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def isclose(self, __a: SupportsFloat, __b: SupportsFloat, *, rel_tol: SupportsFloat = ..., abs_tol: SupportsFloat = ..., invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def isclose(self, __a: SupportsFloat, __b: SupportsFloat, *, rel_tol: SupportsFloat = ..., abs_tol: SupportsFloat = ..., invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... + @overload + def isclose(self, __a: SupportsFloat, __b: SupportsFloat, *, exception: None, rel_tol: SupportsFloat = ..., abs_tol: SupportsFloat = ..., invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def isclose(self, __a: SupportsFloat, __b: SupportsFloat, *, exception: None, rel_tol: SupportsFloat = ..., abs_tol: SupportsFloat = ..., invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def isclose(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def isclose(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def isclose(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def allclose(self, __a: SupportsFloat, __b: SupportsFloat, *, rel_tol: SupportsFloat = ..., abs_tol: SupportsFloat = ..., invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def allclose(self, __a: SupportsFloat, __b: SupportsFloat, *, rel_tol: SupportsFloat = ..., abs_tol: SupportsFloat = ..., invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def allclose(self, __a: SupportsFloat, __b: SupportsFloat, *, exception: None, rel_tol: SupportsFloat = ..., abs_tol: SupportsFloat = ..., invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def allclose(self, __a: SupportsFloat, __b: SupportsFloat, *, exception: None, rel_tol: SupportsFloat = ..., abs_tol: SupportsFloat = ..., invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def allclose(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def allclose(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... + @overload + def allclose(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... # misc @overload - def shape_eq(self, __a: _SupportsShape, __b: Union[_SupportsShape, Tuple[int, ...]], *, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def shape_eq(self, __a: _SupportsShape, __b: Union[_SupportsShape, Tuple[SupportsInt, ...]], *, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... + @overload + def shape_eq(self, __a: _SupportsShape, __b: Union[_SupportsShape, Tuple[SupportsInt, ...]], *, exception: None, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def shape_eq(self, __a: _SupportsShape, __b: Union[_SupportsShape, Tuple[int, ...]], *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def shape_eq(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def shape_eq(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def shape_eq(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def len_eq(self, __a: Sized, __b: int, *, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def len_eq(self, __a: Sized, __b: SupportsInt, *, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... + @overload + def len_eq(self, __a: Sized, __b: SupportsInt, *, exception: None, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def len_eq(self, __a: Sized, __b: int, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def len_eq(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def len_eq(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def len_eq(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def str_eq(self, __a: T, __b: str, *, str_converter: Callable[[T], str] = ..., invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def str_eq(self, __a: T, __b: str, *, str_converter: Callable[[T, RT], str] = ..., invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def str_eq(self, __a: T, __b: str, *, str_converter: Callable[[T], str] = ..., exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def str_eq(self, __a: T, __b: str, *, exception: None, str_converter: Callable[[T, RT], str] = ..., invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def str_eq(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def str_eq(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... + @overload + def str_eq(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... @overload - def function_eq(self, __func1: _SupportsCode, __func2: _SupportsCode, *, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def function_eq(self, __func1: _SupportsCode, __func2: _SupportsCode, *, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... + @overload + def function_eq(self, __func1: _SupportsCode, __func2: _SupportsCode, *, exception: None, invert: bool = ..., post_process: PostProcessBool = ..., message: Optional[str] = ...) -> None: ... @overload - def function_eq(self, __func1: _SupportsCode, __func2: _SupportsCode, *, exception: None, invert: builtins.bool = ..., post_process: Optional[Callable[[builtins.bool], Any]] = ..., message: Optional[str] = ...) -> None: ... + def function_eq(self, *args: Any, exception: Type[AssertionError], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> NoReturn: ... @overload - def function_eq(self, *args: Any, exception: Type[Exception], invert: builtins.bool = ..., post_process: Optional[Callable[[Any], Any]] = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... + def function_eq(self, *args: Any, exception: Type[Exception], invert: bool = ..., post_process: PostProcessAny = ..., message: Optional[str] = ..., **kwargs: Any) -> None: ... -assertion: Final[AssertionManager] +assertion: Final[AssertionManager] = ... diff --git a/assertionlib/ndrepr.py b/assertionlib/ndrepr.py index d2bc5ba..57310c5 100644 --- a/assertionlib/ndrepr.py +++ b/assertionlib/ndrepr.py @@ -1,8 +1,4 @@ -""" -assertionlib.ndrepr -==================== - -A module for holding the :class:`NDRepr` class, a subclass of the builtin :class:`reprlib.Repr` class. +"""A module for holding the :class:`NDRepr` class, a subclass of the builtin :class:`reprlib.Repr` class. Index ----- @@ -31,6 +27,7 @@ NDRepr.repr_ndarray NDRepr.repr_DataFrame NDRepr.repr_Series + NDRepr.repr_Dataset API --- @@ -51,8 +48,9 @@ .. automethod:: NDRepr.repr_ndarray .. automethod:: NDRepr.repr_DataFrame .. automethod:: NDRepr.repr_Series +.. automethod:: NDRepr.repr_Dataset -""" # noqa +""" # noqa: E501 import sys import inspect @@ -62,10 +60,13 @@ from typing import Any, Dict, Callable, Union, Tuple, Optional, Mapping, List, TYPE_CHECKING from itertools import chain, islice +from .functions import set_docstring + if TYPE_CHECKING: from scm.plams import Molecule, Atom, Bond, Settings # type: ignore - from numpy import ndarray + from numpy import ndarray # type: ignore from pandas import DataFrame, Series # type: ignore + from h5py import Dataset # type: ignore from types import (BuiltinFunctionType, BuiltinMethodType, ModuleType, FunctionType, MethodType) if sys.version_info >= (3, 7): @@ -76,6 +77,7 @@ class MethodDescriptorType(Protocol): """See https://github.com/python/typeshed/blob/master/stdlib/3/types.pyi .""" + __name__: str __qualname__: str __objclass__: type @@ -89,9 +91,9 @@ def __get__(self, obj: Any, type: type = ...) -> Any: ... # noqa: E302 ndarray = 'numpy.ndarray' Series = 'pandas.core.series.Series' DataFrame = 'pandas.core.frame.DataFrame' + Dataset = 'h5py._h1.dataset.Dataset' - BuiltinFunctionType = "builtins.builtin_function_or_method" - BuiltinMethodType = "builtins.builtin_function_or_method" + BuiltinFunctionType = BuiltinMethodType = "builtins.builtin_function_or_method" ModuleType = "builtins.module" FunctionType = "builtins.function" MethodType = "builtins.method" @@ -206,7 +208,7 @@ class NDRepr(reprlib.Repr): """ def __init__(self, **kwargs: Union[int, Mapping[str, Any]]) -> None: - """Initialize a :class:`NDRepr` instance.""" + """Initialize an :class:`NDRepr` instance.""" super().__init__() self.maxstring: int = 80 @@ -229,13 +231,12 @@ def __init__(self, **kwargs: Union[int, Mapping[str, Any]]) -> None: f'has no attribute {self.repr(k)}') setattr(self, k, v) + @set_docstring(reprlib.Repr.repr1.__doc__) def repr1(self, obj: Any, level: int) -> str: if isinstance(obj, Exception): # Refer all exceptions NDRepr.repr_Exception() return self.repr_Exception(obj, level) return super().repr1(obj, level) - repr1.__doc__ = reprlib.Repr.repr1.__doc__ - def repr_float(self, obj: float, level: int) -> str: """Create a :class:`str` representation of a :class:`float` instance.""" # noqa i = self.maxfloat @@ -261,7 +262,7 @@ def repr_method(self, obj: MethodType, level: int) -> str: def repr_method_descriptor(self, obj: MethodDescriptorType, level: int) -> str: """Create a :class:`str` representation of an unbound method.""" name, signature = self._parse_callable(obj, level) - return f"" + return f"" def repr_function(self, obj: FunctionType, level: int) -> str: """Create a :class:`str` representation of a function.""" @@ -451,6 +452,10 @@ def repr_Series(self, obj: Series, level: int) -> str: # noqa: N802 with pd.option_context(*args): return builtins.repr(obj) + def repr_Dataset(self, obj: Dataset, level: int) -> str: # noqa: N802 + """Create a :class:`str` representation of a :class:`h5py.Dataset` instance.""" + return repr(obj) + def _get_ndformatter(self, obj: ndarray) -> Dict[str, Callable[[Union[int, float]], str]]: """Return a value for the **formatter** argument in :func:`numpy.printoptions`.""" if obj.dtype != float and obj.dtype != int: diff --git a/assertionlib/protocol.pyi b/assertionlib/protocol.pyi new file mode 100644 index 0000000..27bc61b --- /dev/null +++ b/assertionlib/protocol.pyi @@ -0,0 +1,159 @@ +"""A stub-only module containing a number of :class:`~typing.Protocol` subclasses.""" + +import sys +import types +from abc import abstractmethod +from typing import ( + Tuple, + TypeVar, + Any, + Optional, + type_check_only +) + +if sys.version_info >= (3, 8): + from typing import Protocol, SupportsIndex as _SupportsIndex +else: + from typing_extensions import Protocol + + @type_check_only + class _SupportsIndex(Protocol): + @abstractmethod + def __index__(self) -> int: + pass + +T_contra = TypeVar('T_contra', contravariant=True) +RT_co = TypeVar('RT_co', covariant=True) + +@type_check_only +class _SupportsShape(Protocol): + shape: Tuple[int, ...] + +@type_check_only +class _SupportsCode(Protocol): + __code__: types.CodeType + +@type_check_only +class _SupportsLengthHint(Protocol): + @abstractmethod + def __length_hint__(self) -> int: ... + +@type_check_only +class _SupportsNeg(Protocol[RT_co]): + @abstractmethod + def __neg__(self) -> RT_co: ... + +@type_check_only +class _SupportsPos(Protocol[RT_co]): + @abstractmethod + def __pos__(self) -> RT_co: ... + +@type_check_only +class _SupportsInvert(Protocol[RT_co]): + @abstractmethod + def __invert__(self) -> RT_co: ... + +@type_check_only +class _SupportsGetitem(Protocol[T_contra, RT_co]): + @abstractmethod + def __getitem__(self, x: T_contra) -> RT_co: ... + +@type_check_only +class _SupportsAdd(Protocol[T_contra, RT_co]): + @abstractmethod + def __add__(self, x: T_contra) -> RT_co: ... + +@type_check_only +class _SupportsSub(Protocol[T_contra, RT_co]): + @abstractmethod + def __sub__(self, x: T_contra) -> RT_co: ... + +@type_check_only +class _SupportsMul(Protocol[T_contra, RT_co]): + @abstractmethod + def __mul__(self, x: T_contra) -> RT_co: ... + +@type_check_only +class _SupportsFloordiv(Protocol[T_contra, RT_co]): + @abstractmethod + def __floordiv__(self, x: T_contra) -> RT_co: ... + +@type_check_only +class _SupportsTruediv(Protocol[T_contra, RT_co]): + @abstractmethod + def __truediv__(self, x: T_contra) -> RT_co: ... + +@type_check_only +class _SupportsPow(Protocol[T_contra, RT_co]): + @abstractmethod + def __pow__(self, x: T_contra) -> RT_co: ... + +@type_check_only +class _SupportsMatmul(Protocol[T_contra, RT_co]): + @abstractmethod + def __matmul__(self, x: T_contra) -> RT_co: ... + +@type_check_only +class _SupportsMod(Protocol[T_contra, RT_co]): + @abstractmethod + def __mod__(self, x: T_contra) -> RT_co: ... + +@type_check_only +class _SupportsGt(Protocol[T_contra, RT_co]): + @abstractmethod + def __gt__(self, x: T_contra) -> RT_co: ... + +@type_check_only +class _SupportsLt(Protocol[T_contra, RT_co]): + @abstractmethod + def __lt__(self, x: T_contra) -> RT_co: ... + +@type_check_only +class _SupportsGe(Protocol[T_contra, RT_co]): + @abstractmethod + def __ge__(self, x: T_contra) -> RT_co: ... + +@type_check_only +class _SupportsLe(Protocol[T_contra, RT_co]): + @abstractmethod + def __le__(self, x: T_contra) -> RT_co: ... + +@type_check_only +class _SupportsLshift(Protocol[T_contra, RT_co]): + @abstractmethod + def __lshift__(self, x: T_contra) -> RT_co: ... + +@type_check_only +class _SupportsRshift(Protocol[T_contra, RT_co]): + @abstractmethod + def __rshift__(self, x: T_contra) -> RT_co: ... + +@type_check_only +class _SupportsXor(Protocol[T_contra, RT_co]): + @abstractmethod + def __xor__(self, x: T_contra) -> RT_co: ... + +@type_check_only +class _SupportsOr(Protocol[T_contra, RT_co]): + @abstractmethod + def __or__(self, x: T_contra) -> RT_co: ... + +@type_check_only +class _SupportsAnd(Protocol[T_contra, RT_co]): + @abstractmethod + def __and__(self, x: T_contra) -> RT_co: ... + +@type_check_only +class _SupportsEq(Protocol[T_contra, RT_co]): + @abstractmethod + def __eq__(self, x: T_contra) -> RT_co: ... # type: ignore + +@type_check_only +class _SupportsNe(Protocol[T_contra, RT_co]): + @abstractmethod + def __ne__(self, x: T_contra) -> RT_co: ... # type: ignore + +@type_check_only +class _SupportsBool(Protocol): + @abstractmethod + def __bool__(self) -> bool: ... diff --git a/assertionlib/signature_utils.py b/assertionlib/signature_utils.py deleted file mode 100644 index 8c6883f..0000000 --- a/assertionlib/signature_utils.py +++ /dev/null @@ -1,254 +0,0 @@ -""" -assertionlib.signature_utils -============================ - -Various functions for manipulating function signatures. - -Index ------ -.. currentmodule:: assertionlib.signature_utils -.. autosummary:: - generate_signature - BACK_SIGNATURE - _get_backup_signature - _signature_to_str - -API ---- -.. autofunction:: generate_signature -.. autodata:: BACK_SIGNATURE -.. autofunction:: _get_backup_signature -.. autofunction:: _signature_to_str - -""" - -import sys -from typing import Callable, Optional, Type, Dict, Collection, Tuple, Any, List, Union -from inspect import Parameter, Signature, signature, _ParameterKind -from inspect import _empty # type: ignore -from itertools import chain -import warnings - -from .ndrepr import aNDRepr - -if sys.version_info < (3, 7): - SPACE = '' - from collections import OrderedDict -else: # Dictionaries are ordered starting from python 3.7 - SPACE = ' ' - from builtins import dict as OrderedDict # type: ignore # noqa - -PO: _ParameterKind = Parameter.POSITIONAL_ONLY -POK: _ParameterKind = Parameter.POSITIONAL_OR_KEYWORD -VP: _ParameterKind = Parameter.VAR_POSITIONAL -KO: _ParameterKind = Parameter.KEYWORD_ONLY -VK: _ParameterKind = Parameter.VAR_KEYWORD - -#: Annotation for (optional) exception types -ExType = Optional[Type[Exception]] - - -def _get_backup_signature() -> Signature: - """Create a generic backup :class:`~inspect.Signature` instance. - - Used in :func:`generate_signature` incase a callables' signature cannot be read. - - Returns - ------- - :class:`~inspect.Signature` - `` None>`` - - See Also - -------- - :attr:`Parameter.kind` - Describes how argument values are bound to the parameter. - - :data:`.BACK_SIGNATURE` - A generic backup signature generated by this function. - - """ # noqa - parameters = [ - Parameter(name='self', kind=POK), # Avoid using positional-only - Parameter(name='args', kind=VP), - Parameter(name='invert', kind=KO, default=False, annotation=bool), - Parameter(name='exception', kind=KO, default=None, annotation=ExType), # type: ignore - Parameter(name='post_process', kind=KO, default=None, annotation=Optional[Callable[[Any], Any]]), # noqa: E105, E501 - Parameter(name='message', kind=KO, default=None, annotation=Optional[str]), - Parameter(name='kwargs', kind=VK) - ] - return Signature(parameters=parameters, return_annotation=None) - - -#: A generic backup :class:`~inspect.Signature` generated -#: by :func:`._get_backup_signature`. -BACK_SIGNATURE: Signature = _get_backup_signature() - - -def generate_signature(func: Callable) -> Signature: - f"""Generate a new function signatures with the ``self``, ``invert`` and ``exception`` parameters. - - Default to :data:`BACK_SIGNATURE` if a functions' signature cannot be read. - - Examples - -------- - .. code:: python - - >>> from inspect import signature, Signature - >>> from assertionlib.signature_utils import generate_signature - - >>> def func(iterable, start=0): - ... pass - - # Print the signature of enumerate - >>> sgn1: Signature = signature(func) - >>> print(sgn1) - (iterable, start=0) - - # Print the newly create signature - >>> sgn2: Signature = generate_signature(func) - >>> print(sgn2) - (self, iterable, *args, start=0, invert:{SPACE}bool{SPACE}={SPACE}False, exception:{SPACE}Union[Type[Exception], NoneType]{SPACE}={SPACE}None, post_process:{SPACE}Union[Callable[[Any], Any], NoneType]{SPACE}={SPACE}None, message: Union[str, NoneType]{SPACE}={SPACE}None, **kwargs) -> None - - Parameters - ---------- - func : :class:`~collections.abc.Callable` - A callable object. - - Returns - ------- - :class:`~inspect.Signature` - The signature of **func** with the ``self`` and ``invert`` parameters. - Return :data:`BACK_SIGNATURE` if funcs' signature cannot be read. - - """ # noqa: E501 - try: - sgn = signature(func) - except ValueError: # Not all callables have a signature which can be read. - return BACK_SIGNATURE - - prm_dict: Dict[_ParameterKind, List[Parameter]] = OrderedDict({ - POK: [Parameter(name='self', kind=POK)], VP: [], KO: [], VK: [] - }) - - # Fill the parameter dict - for prm in sgn.parameters.values(): - if prm.name == 'self': - name, _ = _get_cls_annotation(func) - prm = Parameter(name=name, kind=POK) - elif prm.kind is PO: # Positional-only to positional or keyword - prm = prm.replace(kind=POK) - elif prm.kind is POK and prm.default is not _empty: # keyword or positional to keyword only - prm = prm.replace(kind=KO) - prm_dict[prm.kind].append(prm) - - # Double check if the invert and exception parameters are already defined by **func** - invert_name = _sanitize_name('invert', func, prm_dict[KO]) - exception_name = _sanitize_name('exception', func, prm_dict[KO]) - post_process_name = _sanitize_name('post_process', func, prm_dict[KO]) - message = _sanitize_name('message', func, prm_dict[KO]) - - # Ensure the parameter dict contains the following 4 parameters - prm_dict[KO].append(Parameter(name=invert_name, kind=KO, default=False, annotation=bool)) - prm_dict[KO].append(Parameter(name=exception_name, kind=KO, default=None, annotation=ExType)) # type: ignore # noqa - prm_dict[KO].append(Parameter(name=post_process_name, kind=KO, - default=None, annotation=Optional[Callable[[Any], Any]])) - prm_dict[KO].append(Parameter(name=message, kind=KO, default=None, annotation=Optional[str])) - - if not prm_dict[VP]: - prm_dict[VP].append(Parameter(name='args', kind=VP)) - if not prm_dict[VK]: - prm_dict[VK].append(Parameter(name='kwargs', kind=VK)) - - # Construct and return a new signature - parameters = list(chain.from_iterable(prm_dict.values())) - return Signature(parameters=parameters, return_annotation=None) - - -def _get_cls_annotation(func: Callable) -> Tuple[str, Union[str, type]]: - """Return an annotation for ``self`` or ``cls``.""" - if hasattr(func, '__self__'): - cls: Union[str, type] = func.__self__.__class__ # type: ignore - elif hasattr(func, '__objclass__'): - cls = func.__objclass__ # type: ignore - elif hasattr(func, '__qualname__') and '.' in func.__qualname__: - cls_name: str = func.__qualname__.split('.')[0] - cls = cls_name - else: - cls = func.__class__ - - if not isinstance(cls, str): - cls_name = cls.__name__ - return cls_name.lower(), cls - - -def _sanitize_name(name: str, func: Callable, prm_list: Collection[Parameter]) -> str: - """Return **name** if it is not present in **container**, otherwise append it with ``'_'`` and try again.""" # noqa - if name in {prm.name for prm in prm_list}: - warnings.warn(f"The '{name}' parameter is already defined in {aNDRepr.repr(func)}; " - f"renaming new parameter to '{name}_'", RuntimeWarning, stacklevel=2) - return _sanitize_name(name + '_', func, prm_list) - else: - return name - - -#: A dictionary for creating format string for specific parameter kinds. -#: Used by :func:`_signature_to_str`. -_KIND_TO_STR: Dict[_ParameterKind, str] = { - PO: '{}', - POK: '{}', - VP: '*{}', - VK: '**{}', -} - - -def _signature_to_str(sgn: Signature, func_name: Optional[str] = None) -> str: - f"""Create a string from a signature. - - * The ``self`` parameter will be substituted for **func_name**, - *i.e.* the name of the to-be asserted function. - * Annotations will be removed - * keyword arguments will have their default values replaced with their respective keys. - - Examples - -------- - .. code:: python - - >>> from inspect import signature, Signature - - >>> def func(self, a: int, b: float, *args, c=1, d=2, **kwargs) -> None: - ... pass - - >>> sgn: Signature = signature(func) - >>> print(sgn) - (self, a:{SPACE}int, b:{SPACE}float, *args, c=1, d=2, **kwargs) -> None - - >>> sgn_str: str = _signature_to_str(sgn, func_name='fancy_func_name') - >>> print(sgn_str) - (fancy_func_name, a, b, *args, c=c, d=d, **kwargs) - - Parameters - ---------- - sgn : :class:`~inspect.Signature` - A Signature object. - - func_name : :class:`str`, optional - If not ``None``, replace all references to ``self`` with **func_name**. - - Returns - ------- - :class:`str` - A stringified version of **sgn**. - - """ - func_name = 'self' if func_name is None else func_name - parameters = [] - for name, prm in sgn.parameters.items(): - if name == 'self': - value = func_name - elif prm.default is not _empty: - value = f'{name}={name}' - else: - value = _KIND_TO_STR[prm.kind].format(name) - parameters.append(value) - - return '(' + ', '.join(i for i in parameters) + ')' diff --git a/docs/0_documentation.rst b/docs/0_documentation.rst index 3acb48a..8c49f28 100755 --- a/docs/0_documentation.rst +++ b/docs/0_documentation.rst @@ -11,4 +11,4 @@ Index 4_ndrepr 5_dataclass 6_functions - 7_signature_utils + 7_assertion_functions diff --git a/docs/3_assertionmanager.rst b/docs/3_assertionmanager.rst index cf1173c..f8ed76f 100755 --- a/docs/3_assertionmanager.rst +++ b/docs/3_assertionmanager.rst @@ -1,2 +1,5 @@ +assertionlib.manager +==================== + .. automodule:: assertionlib.manager diff --git a/docs/4_ndrepr.rst b/docs/4_ndrepr.rst index a106d39..f9bfa5e 100755 --- a/docs/4_ndrepr.rst +++ b/docs/4_ndrepr.rst @@ -1,2 +1,5 @@ +assertionlib.ndrepr +=================== + .. automodule:: assertionlib.ndrepr diff --git a/docs/5_dataclass.rst b/docs/5_dataclass.rst index 2b9f3a0..76e83b7 100755 --- a/docs/5_dataclass.rst +++ b/docs/5_dataclass.rst @@ -1,2 +1,5 @@ +assertionlib.dataclass +====================== + .. automodule:: assertionlib.dataclass diff --git a/docs/6_functions.rst b/docs/6_functions.rst index 879f933..9253d1b 100755 --- a/docs/6_functions.rst +++ b/docs/6_functions.rst @@ -1,2 +1,5 @@ +assertionlib.functions +====================== + .. automodule:: assertionlib.functions diff --git a/docs/7_assertion_functions.rst b/docs/7_assertion_functions.rst new file mode 100755 index 0000000..3d32f3b --- /dev/null +++ b/docs/7_assertion_functions.rst @@ -0,0 +1,5 @@ +assertionlib.assertion_functions +================================ + +.. automodule:: + assertionlib.assertion_functions diff --git a/docs/7_signature_utils.rst b/docs/7_signature_utils.rst deleted file mode 100644 index ae17465..0000000 --- a/docs/7_signature_utils.rst +++ /dev/null @@ -1,2 +0,0 @@ -.. automodule:: - assertionlib.signature_utils diff --git a/docs/conf.py b/docs/conf.py index 6c6e341..5ad4be2 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -35,7 +35,7 @@ # 'signature' – Show typehints as its signature (default) # 'none' – Do not show typehints # New in version 2.1. -autodoc_typehints = 'none' +autodoc_typehints = 'signature' # Output is processed with HTML4 writer. diff --git a/setup.cfg b/setup.cfg index 37a0389..a0665ba 100644 --- a/setup.cfg +++ b/setup.cfg @@ -12,7 +12,7 @@ source = assertionlib [tool:pytest] flake8-max-line-length = 100 testpaths = tests -addopts = --tb=short --doctest-glob='*.py' --doctest-glob='*.rst' --doctest-modules --cache-clear --flake8 --cov --cov-report xml --cov-report term --cov-report html --mypy +addopts = --tb=short --doctest-glob='*.py' --doctest-glob='*.rst' --doctest-modules --cache-clear --flake8 --cov --cov-report xml --cov-report term --cov-report html --pydocstyle --mypy # Define `python setup.py build_sphinx` [build_sphinx] @@ -20,3 +20,8 @@ source-dir = docs build-dir = docs/_build all_files = 1 builder = html + +[pydocstyle] +convention = numpy +add-ignore = D401 +ignore-decorators = set_docstring diff --git a/setup.py b/setup.py index a38e4d3..cd3249b 100644 --- a/setup.py +++ b/setup.py @@ -52,24 +52,24 @@ python_requires='>=3.6', test_suite='tests', tests_require=[ - 'pytest', + 'pytest>=4.1.0', 'pytest-cov', - 'pytest-flake8', + 'pytest-flake8>=1.0.4', + 'pytest-pydocstyle>=2.1', 'numpy', - 'typing-extensions>=3.6.4', - 'numpy-stubs@git+https://github.com/numpy/numpy-stubs@master', - 'pytest-mypy@git+https://github.com/nlesc-nano/pytest-mypy@master' + 'typing-extensions>=3.7.4; python_version<"3.8"', + 'pytest-mypy>=0.6.2' ], extras_require={ 'doc': ['sphinx>=2.1', 'sphinx_rtd_theme'], 'test': [ - 'pytest', + 'pytest>=4.1.0', 'pytest-cov', - 'pytest-flake8', + 'pytest-flake8>=1.0.5', + 'pytest-pydocstyle>=2.1', 'numpy', - 'typing-extensions>=3.6.4', - 'numpy-stubs@git+https://github.com/numpy/numpy-stubs@master', - 'pytest-mypy@git+https://github.com/nlesc-nano/pytest-mypy@master' + 'typing-extensions>=3.7.4; python_version<"3.8"', + 'pytest-mypy>=0.6.2' ], } ) diff --git a/tests/test_manager.py b/tests/test_manager.py index c38f734..12cbc8c 100644 --- a/tests/test_manager.py +++ b/tests/test_manager.py @@ -3,7 +3,7 @@ from typing import Optional try: - import numpy as np + import numpy as np # type: ignore NUMPY_EX: Optional[ImportError] = None except ImportError as ex: NUMPY_EX = ex @@ -250,10 +250,20 @@ def test_or() -> None: assertion.or_(5, 6, 7, 8, exception=TypeError) +def test_xor() -> None: + """Test :meth:`AssertionManager.xor`.""" + assertion.xor(5, 6) + assertion.xor(0, 6) + assertion.xor(5, 0) + assertion.xor(0, 0, invert=True) + assertion.xor(5, 6, 7, 8, exception=TypeError) + + @skip_if(NUMPY_EX) def test_or_np() -> None: """Test :meth:`AssertionManager.not_` with a NumPy array.""" - assertion.or_(np.random.rand(10), 6, exception=TypeError) + array: np.ndarray = np.random.rand(10) + assertion.or_(array, 6, exception=TypeError) def test_pos() -> None: @@ -317,4 +327,5 @@ def test_truth() -> None: @skip_if(NUMPY_EX) def test_truth_np() -> None: """Test :meth:`AssertionManager.truth` with a NumPy array.""" - assertion.truth(np.random.rand(10), exception=ValueError) + array: np.ndarray = np.random.rand(10) + assertion.truth(array, exception=ValueError) diff --git a/tests/test_manager_misc.py b/tests/test_manager_misc.py index 7c86950..f8e4709 100644 --- a/tests/test_manager_misc.py +++ b/tests/test_manager_misc.py @@ -2,13 +2,15 @@ import operator from sys import version_info -from typing import Optional, cast +from typing import Optional, cast, Callable +from functools import partial from assertionlib import assertion, AssertionManager +from assertionlib.manager import _Str, _NoneException # type: ignore from assertionlib.functions import skip_if try: - import numpy as np + import numpy as np # type: ignore NUMPY_EX: Optional[ImportError] = None except ImportError as ex: NUMPY_EX = ex @@ -88,13 +90,13 @@ def test_as_dict() -> None: class _TestClass: - def instance_meth(self): return True + def instance_meth(self) -> bool: return True @classmethod - def class_meth(cls): return True + def class_meth(cls) -> bool: return True @staticmethod - def static_meth(): return True + def static_meth() -> bool: return True def test_add_to_instance() -> None: @@ -154,6 +156,20 @@ def test_assert_() -> None: else: raise AssertionError('Failed to raise a ValueError') + try: + assertion.eq(1, 1, exception=TypeError, message='') + except AssertionError as ex: + assertion.contains(str(ex), '') + else: + raise AssertionError('Failed to raise an AssertionError') + + try: + assertion.contains(1, 1, exception=ValueError) + except AssertionError as ex: + assertion.isinstance(ex.__cause__, TypeError) + else: + raise AssertionError('Failed to raise an AssertionError') + func = operator.__invert__ assertion(False, post_process=func) assertion(True, invert=True, post_process=func) @@ -238,14 +254,42 @@ def test_all() -> None: assertion.all(5, exception=TypeError) +def test_isdisjoint() -> None: + """Test :meth:`AssertionManager.isdisjoint`.""" + class _Test1(): + isdisjoint = False + + class _Test2(): + def isdisjoint(self): return False + + assertion.isdisjoint([1], [2]) + assertion.isdisjoint({1}, [2]) + assertion.isdisjoint({1}, {2}) + assertion.isdisjoint([1], [1], invert=True) + assertion.isdisjoint(5, 6, 7, 8, exception=TypeError) + assertion.isdisjoint([[1]], [2], exception=TypeError) + assertion.isdisjoint(_Test1(), [2], exception=TypeError) + assertion.isdisjoint(_Test2(), [2], exception=TypeError) + + +def test_round() -> None: + """Test :meth:`AssertionManager.round`.""" + assertion.round(0.6) + assertion.round(60, ndigits=-2) + assertion.round(0.4, invert=True) + assertion.round(40, ndigits=-2, invert=True) + assertion.round(40, 1, 1, exception=TypeError) + assertion.round('bob', exception=TypeError) + + def test_get_exc_message() -> None: """Test :meth:`AssertionManager._get_exc_message`.""" ex = TypeError("object of type 'int' has no len()") - func = len + func1 = len args = (1,) - str1 = assertion._get_exc_message(ex, func, *args, invert=False, output=None) - str2 = assertion._get_exc_message(ex, func, *args, invert=True, output=None) + str1 = assertion._get_exc_message(ex, func1, *args, invert=False, output=None) # type: ignore + str2 = assertion._get_exc_message(ex, func1, *args, invert=True, output=None) # type: ignore comma = ',' if version_info.minor < 7 else '' # For Python 3.6 and later ref1 = f"""output = len(obj); assert output @@ -262,3 +306,36 @@ def test_get_exc_message() -> None: assertion.eq(str1, ref1) assertion.eq(str2, ref2) + + func2: Callable = assertion._get_exc_message # type: ignore + assertion.assert_(func2, ex, 1, exception=TypeError) + + func3 = partial(len) + str3 = assertion._get_exc_message(ex, func3) # type: ignore + assertion.contains(str3, 'functools.partial()') + + class Func(): + def __call__(self): pass + + str4 = assertion._get_exc_message(ex, Func()) # type: ignore + assertion.contains(str4, 'output = func(); assert output') + + +def test_str() -> None: + """Test :class:`_Str`.""" + a = _Str('bob') + assertion.eq(repr(a), str('bob')) + assertion.eq(str(a), str('bob')) + + +def test_none_exception() -> None: + """Test :class:`_NoneException`.""" + assertion.assert_(_NoneException, exception=TypeError) + assertion.issubclass(_NoneException, Exception, invert=True) + + +def test_property() -> None: + """Test :attr:`AssertionManager.repr` and :attr:`AssertionManager.maxstring`.""" + manager_ = AssertionManager(None) + assertion.is_(manager_.repr, repr) + assertion.eq(manager_.maxstring, 80) diff --git a/tests/test_ndrepr.py b/tests/test_ndrepr.py index 9f7a711..047b9af 100644 --- a/tests/test_ndrepr.py +++ b/tests/test_ndrepr.py @@ -5,7 +5,7 @@ from typing import Optional try: - import numpy as np + import numpy as np # type: ignore NUMPY_EX: Optional[ImportError] = None except ImportError as ex: NUMPY_EX = ex @@ -51,8 +51,8 @@ def test_callables() -> None: ref1 = "" ref1_backup = "" - ref2 = "" - ref2_backup = "" + ref2 = "" + ref2_backup = "" ref3 = "" ref4 = "" ref4_backup = "" diff --git a/tests/test_signature_utils.py b/tests/test_signature_utils.py deleted file mode 100644 index 1a4511e..0000000 --- a/tests/test_signature_utils.py +++ /dev/null @@ -1,54 +0,0 @@ -"""Tests for :mod:`assertionlib.signature`.""" - -from sys import version_info - -from assertionlib import assertion -from assertionlib.signature_utils import ( - _get_backup_signature, BACK_SIGNATURE, generate_signature, _signature_to_str -) - - -def test_get_backup_signature() -> None: - """Test :func:`assertionlib.signature_utils._get_backup_signature`.""" - if version_info >= (3, 7): # Python >= 3.7 - sgn_str = ' None>' # noqa: E501 - else: # Python < 3.7 - sgn_str = ' None>' # noqa: E501 - - assertion.str_eq(BACK_SIGNATURE, sgn_str) - assertion.str_eq(_get_backup_signature(), sgn_str) - - -def _test_func(a, *args, b=1, **kwargs): pass - - -def test_generate_signature() -> None: - """Test :func:`assertionlib.signature_utils.generate_signature`.""" - if version_info.minor >= 7: # Python >= 3.7 - ref1 = ' None>' # noqa: E501 - ref2 = ' None>' # noqa: E501 - else: # Python < 3.6 - ref1 = ' None>' # noqa: E501 - ref2 = ' None>' # noqa: E501 - - sgn1 = generate_signature(_test_func) - sgn2 = generate_signature(bool) - assertion.str_eq(sgn1, ref1) - assertion.str_eq(sgn2, ref2) - - -def test_signature_to_str() -> None: - """Test :func:`assertionlib.signature_utils._signature_to_str`.""" - def test(a, *args, b=1, **kwargs): - pass - - ref1 = '(self, a, *args, b=b, invert=invert, exception=exception, post_process=post_process, message=message, **kwargs)' # noqa: E501 - ref2 = '(self, *args, invert=invert, exception=exception, post_process=post_process, message=message, **kwargs)' # noqa: E501 - - sgn1 = generate_signature(test) - sgn2 = generate_signature(bool) - sgn1_str = _signature_to_str(sgn1) - sgn2_str = _signature_to_str(sgn2) - - assertion.eq(sgn1_str, ref1) - assertion.eq(sgn2_str, ref2)