diff --git a/.pylintrc b/.pylintrc index 9e6d02f..15373de 100644 --- a/.pylintrc +++ b/.pylintrc @@ -16,7 +16,7 @@ persistent=yes # List of plugins (as comma separated values of python modules names) to load, # usually to register additional checkers. -load-plugins= +load-plugins=pylint.extensions.docparams # Use multiple processes to speed up Pylint. jobs=1 diff --git a/.travis.yml b/.travis.yml index 94638e2..3112564 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,46 +1,128 @@ sudo: false language: python os: linux -python: -- 3.5 -- 3.6 -- &mainstream_python 3.7-dev -- &pypy pypy3.5 install: - &upgrade_python_toolset pip install --upgrade pip setuptools wheel -- pip install tox-travis -- pip install coveralls -script: tox +- &install_test_deps pip install --upgrade pytest pytest-sugar +- &install_deps pip install -r CI_REQUIREMENTS.txt +- pip install --upgrade pytest-cov coveralls + +_helpers: +- &install_cython pip install --upgrade Cython +- &build_package python setup.py bdist_wheel +- &install_built pip install logwrap --no-index -f dist +- &test_no_cov py.test -vv test +- &test_cythonized + install: + - *upgrade_python_toolset + - *install_test_deps + - *install_deps + - *install_cython + script: + - *build_package + - *install_built + - *test_no_cov + after_success: skip + +script: +- pip install -e . +- py.test -vv --cov-config .coveragerc --cov-report= --cov=logwrap test +- coverage report -m --fail-under 87 after_success: - coveralls jobs: fast_finish: true include: + - stage: test + name: "Python 3.5" + python: 3.5 + - stage: test + name: "Python 3.6" + python: 3.6 + - stage: test + name: "Python 3.7" + python: 3.7 + dist: xenial + sudo: true + - stage: test + name: "PyPy3" + python: pypy3.5 + + - stage: Static analisys + name: "PyLint" + python: 3.6 + services: [] + install: + - *upgrade_python_toolset + - *install_deps + - pip install --upgrade "pylint >= 2.0" + script: + - pylint logwrap + after_success: skip - stage: Static analisys + name: "Bandit" python: 3.6 services: [] install: - *upgrade_python_toolset - - pip install tox + - pip install --upgrade bandit script: - - tox -e pylint,bandit,mypy + - bandit -r logwrap + after_success: skip + - stage: Static analisys + name: "MyPy" + python: 3.7 + dist: xenial + sudo: true + services: [] + install: + - *upgrade_python_toolset + - *install_deps + - pip install --upgrade "mypy >= 0.620" + script: + - mypy --strict logwrap after_success: skip + - stage: Test cythonized + name: "Python 3.5" + python: 3.5 + <<: *test_cythonized + - stage: Test cythonized + name: "Python 3.6" + python: 3.6 + <<: *test_cythonized + - stage: Test cythonized + name: "Python 3.7" + python: 3.7 + dist: xenial + sudo: true + <<: *test_cythonized + - stage: Code style check - python: *mainstream_python - services: [] + name: "PEP8" + python: 3.6 + install: + - *upgrade_python_toolset + - pip install --upgrade flake8 + script: + - flake8 + after_success: skip + - stage: Code style check + name: "PEP257" + python: 3.6 install: - *upgrade_python_toolset - - pip install tox + - pip install --upgrade pydocstyle script: - - tox -e pep8,pep257 + - pydocstyle logwrap after_success: skip - stage: deploy # This prevents job from appearing in test plan unless commit is tagged: if: tag IS present - python: *pypy + # Run on pypy to build not cythonized wheel + python: pypy3.5 services: - docker install: @@ -49,7 +131,7 @@ jobs: - ./tools/run_docker.sh "logwrap" before_deploy: - pip install -r build_requirements.txt - - python setup.py bdist_wheel + - *build_package deploy: - provider: pypi # `skip_cleanup: true` is required to preserve binary wheels, built diff --git a/logwrap/_log_wrap.py b/logwrap/_log_wrap.py index 9c13337..2a151a4 100644 --- a/logwrap/_log_wrap.py +++ b/logwrap/_log_wrap.py @@ -165,6 +165,10 @@ def bind_args_kwargs( :param sig: source signature :type sig: inspect.Signature + :param args: not keyworded arguments + :type args: tuple + :param kwargs: keyworded arguments + :type kwargs: dict :return: Iterator for bound parameters with all information about it :rtype: typing.Iterator[BoundParameter] @@ -366,7 +370,9 @@ def log_call_args(self) -> bool: def log_call_args(self, val: bool) -> None: """Flag: log call arguments before call. + :param val: Enable flag :type val: bool + :raises TypeError: Value is not bool """ if not isinstance(val, bool): raise TypeError( @@ -389,7 +395,9 @@ def log_call_args_on_exc(self) -> bool: def log_call_args_on_exc(self, val: bool) -> None: """Flag: log call arguments on exception. + :param val: Enable flag :type val: bool + :raises TypeError: Value is not bool """ if not isinstance(val, bool): raise TypeError( @@ -412,7 +420,9 @@ def log_result_obj(self) -> bool: def log_result_obj(self, val: bool) -> None: """Flag: log result object. + :param val: Enable flag :type val: bool + :raises TypeError: Value is not bool """ if not isinstance(val, bool): raise TypeError( @@ -425,7 +435,7 @@ def log_result_obj(self, val: bool) -> None: @property def _logger(self) -> logging.Logger: - """logger instance. + """Logger instance. :rtype: logging.Logger """ @@ -506,9 +516,13 @@ def _get_func_args_repr( ) -> str: """Internal helper for reducing complexity of decorator code. + :param sig: function signature :type sig: inspect.Signature + :param args: not keyworded arguments :type args: tuple + :param kwargs: keyworded arguments :type kwargs: dict + :return: repr over function arguments :rtype: str .. versionchanged:: 3.3.0 Use pre- and post- processing of params during execution diff --git a/logwrap/_repr_utils.py b/logwrap/_repr_utils.py index ca66a3d..828f6cf 100644 --- a/logwrap/_repr_utils.py +++ b/logwrap/_repr_utils.py @@ -121,7 +121,9 @@ def _prepare_repr( ) -> typing.Iterator[ReprParameter]: """Get arguments lists with defaults. + :param func: Callable object to process :type func: typing.Union[types.FunctionType, types.MethodType] + :return: repr of callable parameter from signature :rtype: typing.Iterator[ReprParameter] """ isfunction = isinstance(func, types.FunctionType) @@ -192,6 +194,7 @@ def next_indent(self, indent: int, multiplier: int = 1) -> int: :type indent: int :param multiplier: step multiplier :type multiplier: int + :return: next indentation value :rtype: int """ return indent + multiplier * self.indent_step @@ -204,8 +207,11 @@ def _repr_callable( ) -> str: """Repr callable object (function or method). + :param src: Callable to process :type src: typing.Union[types.FunctionType, types.MethodType] + :param indent: start indentation :type indent: int + :return: Repr of function or method with signature. :rtype: str """ raise NotImplementedError() # pragma: no cover @@ -219,9 +225,13 @@ def _repr_simple( ) -> str: """Repr object without iteration. + :param src: Source object :type src: typing.Any + :param indent: start indentation :type indent: int + :param no_indent_start: ignore indent :type no_indent_start: bool + :return: simple repr() over object :rtype: str """ raise NotImplementedError() # pragma: no cover @@ -280,6 +290,7 @@ def _repr_iterable_items( :type src: typing.Iterable :param indent: start indentation :type indent: int + :return: repr of element in iterable item :rtype: typing.Iterator[str] """ for elem in src: @@ -427,9 +438,13 @@ def _repr_simple( ) -> str: """Repr object without iteration. + :param src: Source object :type src: typing.Any + :param indent: start indentation :type indent: int + :param no_indent_start: ignore indent :type no_indent_start: bool + :return: simple repr() over object, except strings (add prefix) and set (uniform py2/py3) :rtype: str """ indent = 0 if no_indent_start else indent @@ -458,6 +473,7 @@ def _repr_dict_items( :type src: dict :param indent: start indentation :type indent: int + :return: repr of key/value pair from dict :rtype: typing.Iterator[str] """ max_len = max((len(repr(key)) for key in src)) if src else 0 @@ -481,8 +497,11 @@ def _repr_callable( ) -> str: """Repr callable object (function or method). + :param src: Callable to process :type src: typing.Union[types.FunctionType, types.MethodType] + :param indent: start indentation :type indent: int + :return: Repr of function or method with signature. :rtype: str """ param_str = "" @@ -545,6 +564,7 @@ def _repr_iterable_item( :type result: str :param suffix: suffix :type suffix: str + :return: formatted repr of "result" with prefix and suffix to explain type. :rtype: str """ return ( @@ -600,9 +620,13 @@ def _repr_simple( ) -> str: """Repr object without iteration. + :param src: Source object :type src: typing.Any + :param indent: start indentation :type indent: int + :param no_indent_start: ignore indent :type no_indent_start: bool + :return: simple repr() over object, except strings (decode) and set (uniform py2/py3) :rtype: str """ indent = 0 if no_indent_start else indent @@ -631,7 +655,8 @@ def _repr_dict_items( :type src: dict :param indent: start indentation :type indent: int - :rtype: typing.Generator[str] + :return: repr of key/value pair from dict + :rtype: typing.Iterator[str] """ max_len = max((len(str(key)) for key in src)) if src else 0 for key, val in src.items(): @@ -654,8 +679,11 @@ def _repr_callable( ) -> str: """Repr callable object (function or method). + :param src: Callable to process :type src: typing.Union[types.FunctionType, types.MethodType] + :param indent: start indentation :type indent: int + :return: Repr of function or method with signature. :rtype: str """ param_str = "" @@ -718,6 +746,7 @@ def _repr_iterable_item( :type result: str :param suffix: suffix :type suffix: str + :return: formatted repr of "result" with prefix and suffix to explain type. :rtype: str """ return ( diff --git a/setup.cfg b/setup.cfg index 039d434..fb16d2d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -40,8 +40,13 @@ exclude = __init__.py, docs ignore = +show-pep8 = True show-source = True count = True +max-line-length = 120 + +[pydocstyle] +ignore = D401, D203, D213 [aliases] test=pytest diff --git a/tox.ini b/tox.ini index 0260c42..fbf59a1 100644 --- a/tox.ini +++ b/tox.ini @@ -65,9 +65,9 @@ commands = flake8 [testenv:pep257] deps = - pep257 + pydocstyle usedevelop = False -commands = pep257 logwrap +commands = pydocstyle logwrap [testenv:install] deps = @@ -98,6 +98,9 @@ show-source = True count = True max-line-length = 120 +[pydocstyle] +ignore = D401, D203, D213 + [testenv:docs] deps = sphinx