diff --git a/logwrap/_class_decorator.py b/logwrap/_class_decorator.py index 6dadbe8..ac18778 100644 --- a/logwrap/_class_decorator.py +++ b/logwrap/_class_decorator.py @@ -21,13 +21,12 @@ import abc import functools -import sys import typing # noqa # pylint: disable=unused-import -PY3 = sys.version_info[:2] > (3, 0) # type: bool +import six -class BaseDecorator(object): +class BaseDecorator(six.with_metaclass(abc.ABCMeta, object)): """Base class for decorators. Implements wrapping and __call__, wrapper getter is abstract. @@ -81,7 +80,7 @@ def __init__( self.__func = func # type: typing.Optional[typing.Callable] if self.__func is not None: functools.update_wrapper(self, self.__func) - if not PY3: # pragma: no cover + if not six.PY3: # pragma: no cover self.__wrapped__ = self.__func # type: typing.Callable # pylint: enable=assigning-non-slot # noinspection PyArgumentList diff --git a/logwrap/_class_decorator.pyi b/logwrap/_class_decorator.pyi index 789857d..25f29bf 100644 --- a/logwrap/_class_decorator.pyi +++ b/logwrap/_class_decorator.pyi @@ -3,7 +3,7 @@ import typing PY3: bool -class BaseDecorator: +class BaseDecorator(object, metaclass=abc.ABCMeta): def __init__(self, func: typing.Optional[typing.Callable]=...) -> None: ... @property diff --git a/logwrap/_log_wrap2.pyi b/logwrap/_log_wrap2.pyi index 4f4dbfd..066fe14 100644 --- a/logwrap/_log_wrap2.pyi +++ b/logwrap/_log_wrap2.pyi @@ -23,8 +23,26 @@ class LogWrap(_log_wrap_shared.BaseLogWrap): def _get_function_wrapper(self, func: typing.Callable) -> typing.Callable: ... + +@typing.overload +def logwrap( + func: None=..., + log: logging.Logger=..., + log_level: int=..., + exc_level: int=..., + max_indent: int=..., + spec: typing.Optional[typing.Callable]=..., + blacklisted_names: typing.Optional[typing.List[str]]=..., + blacklisted_exceptions: typing.Optional[typing.List[typing.Type[Exception]]]=..., + log_call_args: bool=..., + log_call_args_on_exc: bool=..., + log_result_obj: bool=... +) -> LogWrap: ... + + +@typing.overload def logwrap( - func: typing.Optional[typing.Callable]=None, + func: typing.Callable=..., log: logging.Logger=..., log_level: int=..., exc_level: int=..., @@ -35,4 +53,4 @@ def logwrap( log_call_args: bool=..., log_call_args_on_exc: bool=..., log_result_obj: bool=... -) -> typing.Union[LogWrap, typing.Callable]: ... +) -> typing.Callable: ... diff --git a/logwrap/_log_wrap3.pyi b/logwrap/_log_wrap3.pyi index a28ada5..9c894c9 100644 --- a/logwrap/_log_wrap3.pyi +++ b/logwrap/_log_wrap3.pyi @@ -8,7 +8,7 @@ class LogWrap(_log_wrap_shared.BaseLogWrap): def __init__( self, - func: typing.Optional[typing.Callable]=None, + func: typing.Optional[typing.Callable]=..., *, log: logging.Logger=..., log_level: int=..., @@ -24,8 +24,27 @@ class LogWrap(_log_wrap_shared.BaseLogWrap): def _get_function_wrapper(self, func: typing.Callable) -> typing.Callable: ... + +@typing.overload +def logwrap( + func: None=..., + *, + log: logging.Logger=..., + log_level: int=..., + exc_level: int=..., + max_indent: int=..., + spec: typing.Optional[typing.Callable]=..., + blacklisted_names: typing.Optional[typing.List[str]]=..., + blacklisted_exceptions: typing.Optional[typing.List[typing.Type[Exception]]]=..., + log_call_args: bool=..., + log_call_args_on_exc: bool=..., + log_result_obj: bool=... +) -> LogWrap: ... + + +@typing.overload def logwrap( - func: typing.Optional[typing.Callable]=None, + func: typing.Callable=..., *, log: logging.Logger=..., log_level: int=..., @@ -37,4 +56,4 @@ def logwrap( log_call_args: bool=..., log_call_args_on_exc: bool=..., log_result_obj: bool=... -) -> typing.Union[LogWrap, typing.Callable]: ... +) -> typing.Callable: ... diff --git a/logwrap/_log_wrap_shared.pyi b/logwrap/_log_wrap_shared.pyi index 5473d5c..6be59b1 100644 --- a/logwrap/_log_wrap_shared.pyi +++ b/logwrap/_log_wrap_shared.pyi @@ -1,3 +1,4 @@ +import abc import enum import inspect import logging @@ -33,7 +34,7 @@ class BoundParameter(object): KEYWORD_ONLY = Parameter.KEYWORD_ONLY VAR_KEYWORD = Parameter.VAR_KEYWORD - empty = Parameter.empty # type: typing.Type + empty: typing.Type = Parameter.empty def __init__( self, @@ -62,12 +63,12 @@ class BoundParameter(object): def bind_args_kwargs( sig: Signature, - *args, - **kwargs + *args: typing.Tuple, + **kwargs: typing.Dict ) -> typing.Iterator[BoundParameter]: ... -class BaseLogWrap(_class_decorator.BaseDecorator): +class BaseLogWrap(_class_decorator.BaseDecorator, metaclass=abc.ABCMeta): def __init__( self, func: typing.Optional[typing.Callable]=None, @@ -134,8 +135,8 @@ class BaseLogWrap(_class_decorator.BaseDecorator): @staticmethod def _bind_args_kwargs( sig: Signature, - *args, - **kwargs + *args: typing.Tuple, + **kwargs: typing.Dict ) -> typing.Iterator[BoundParameter]: ... def pre_process_param( diff --git a/setup.cfg b/setup.cfg index 32d107e..039d434 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,15 +1,14 @@ [metadata] name = logwrap +project_urls = + Bug Tracker = https://github.com/python-useful-helpers/logwrap/issues + Documentation = https://logwrap.readthedocs.io/ long_description = file: README.rst [options] zip_safe = False packages = find: -setup_requires = - setuptools > 20.2 - -python_requires = >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.* [bdist_wheel] # This flag says that the code is written to work on both Python 2 and Python diff --git a/setup.py b/setup.py index 25ed0e7..e4db1de 100644 --- a/setup.py +++ b/setup.py @@ -256,6 +256,16 @@ def get_simple_vars_from_src(src): long_description=long_description, classifiers=classifiers, keywords=keywords, + python_requires='>=2.7.5,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*', + # While setuptools cannot deal with pre-installed incompatible versions, + # setting a lower bound is not harmful - it makes error messages cleaner. DO + # NOT set an upper bound on setuptools, as that will lead to uninstallable + # situations as progressive releases of projects are done. + # Blacklist setuptools 34.0.0-34.3.2 due to https://github.com/pypa/setuptools/issues/951 + # Blacklist setuptools 36.2.0 due to https://github.com/pypa/setuptools/issues/1086 + setup_requires="setuptools >= 21.0.0,!=24.0.0," + "!=34.0.0,!=34.0.1,!=34.0.2,!=34.0.3,!=34.1.0,!=34.1.1,!=34.2.0,!=34.3.0,!=34.3.1,!=34.3.2," + "!=36.2.0", extras_require={ ':python_version == "2.7"': [ 'funcsigs>=1.0', diff --git a/tox.ini b/tox.ini index 615f767..ebce8ff 100644 --- a/tox.ini +++ b/tox.ini @@ -80,7 +80,7 @@ commands = pip install ./ -vvv -U [testenv:pylint] deps = - pylint + pylint<2 -r{toxinidir}/CI_REQUIREMENTS.txt commands = pylint logwrap @@ -118,3 +118,9 @@ deps = commands = pipenv install -r {toxinidir}/build_requirements.txt --skip-lock pipenv graph + +[testenv:mypy] +deps = + mypy>=0.620 + -r{toxinidir}/CI_REQUIREMENTS.txt +commands = mypy --strict logwrap