diff --git a/.travis.yml b/.travis.yml index 27f0c70..471405d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,52 +1,104 @@ sudo: false language: python os: linux -python: -- &mainstream_python 2.7 -- &pypy pypy install: - &upgrade_python_toolset pip install --upgrade pip setuptools wheel -- pip install tox-travis -- pip install coveralls -script: tox +- pip install --upgrade pytest pytest-sugar +- &install_deps pip install -r CI_REQUIREMENTS.txt +- pip install --upgrade pytest-cov coveralls + +_python: +- &python27 + name: "Python 2.7" + python: 2.7 +- &pypy + name: "PyPy" + python: pypy +- &python37 + name: "Python 3.7" + python: 3.7 + dist: xenial + sudo: true + +_helpers: +- &build_package python setup.py bdist_wheel + +- &static_analysis + stage: Static analysis + <<: *python27 + after_success: skip + +- &code_style_check + stage: Code style check + <<: *python27 + 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: Static analisys - python: 3.6 - services: [] + - stage: test + <<: *python27 + - stage: test + <<: *pypy + + - <<: *static_analysis + name: "PyLint" + install: + - *upgrade_python_toolset + - *install_deps + - pip install --upgrade "pylint < 2.0" + script: + - pylint logwrap + - <<: *static_analysis + name: "Bandit" install: - *upgrade_python_toolset - - pip install tox + - pip install --upgrade bandit script: - - tox -e pylint,bandit,mypy - after_success: skip + - bandit -r logwrap + - <<: *static_analysis + <<: *python37 + name: "MyPy" + install: + - *upgrade_python_toolset + - *install_deps + - pip install --upgrade "mypy >= 0.620" + script: + - mypy --strict logwrap - - stage: Code style check - python: *mainstream_python - services: [] + - <<: *code_style_check + name: "PEP8" install: - *upgrade_python_toolset - - pip install tox + - pip install --upgrade flake8 script: - - tox -e pep8,pep257 - after_success: skip + - flake8 + - <<: *code_style_check + name: "PEP257" + install: + - *upgrade_python_toolset + - pip install --upgrade pydocstyle + script: + - pydocstyle logwrap - stage: deploy # This prevents job from appearing in test plan unless commit is tagged: if: tag IS present python: *pypy - services: - - docker + services: [] install: - *upgrade_python_toolset - script: [] - before_deploy: - - pip install -r build_requirements.txt - - python setup.py bdist_wheel + - *install_deps + script: + - *build_package + before_deploy: [] deploy: - provider: pypi # `skip_cleanup: true` is required to preserve binary wheels, built diff --git a/doc/source/PrettyFormat.rst b/doc/source/PrettyFormat.rst index 8dc7adf..5a4c769 100644 --- a/doc/source/PrettyFormat.rst +++ b/doc/source/PrettyFormat.rst @@ -11,9 +11,7 @@ API: Helpers: `pretty_repr`, `pretty_str` and base class `PrettyFormat`. Make human readable repr of object. :param src: object to process - :type src: typing.Union[ - typing.AnyStr, int, typing.Iterable, object - ] + :type src: typing.Any :param indent: start indentation, all next levels is +indent_step :type indent: int :param no_indent_start: do not indent open bracket and simple parameters @@ -35,9 +33,7 @@ API: Helpers: `pretty_repr`, `pretty_str` and base class `PrettyFormat`. .. versionadded:: 1.1.0 :param src: object to process - :type src: typing.Union[ - typing.AnyStr, int, typing.Iterable, object - ] + :type src: typing.Any :param indent: start indentation, all next levels is +indent_step :type indent: int :param no_indent_start: do not indent open bracket and simple parameters @@ -89,9 +85,7 @@ API: Helpers: `pretty_repr`, `pretty_str` and base class `PrettyFormat`. Make human readable representation of object. :param src: object to process - :type src: typing.Union[ - typing.AnyStr, int, typing.Iterable, object - ] + :type src: typing.Any :param indent: start indentation :type indent: int :param no_indent_start: @@ -105,9 +99,7 @@ API: Helpers: `pretty_repr`, `pretty_str` and base class `PrettyFormat`. Make human readable representation of object. The main entry point. :param src: object to process - :type src: typing.Union[ - typing.AnyStr, int, typing.Iterable, object - ] + :type src: typing.Any :param indent: start indentation :type indent: int :param no_indent_start: diff --git a/logwrap/_log_wrap.py b/logwrap/_log_wrap.py index 8eda4c0..fe71033 100644 --- a/logwrap/_log_wrap.py +++ b/logwrap/_log_wrap.py @@ -174,7 +174,11 @@ def bind_args_kwargs( """Bind *args and **kwargs to signature and get Bound Parameters. :param sig: source signature - :type sig: Signature + :type sig: inspect.Signature + :param args: not keyworded arguments + :type args: typing.Any + :param kwargs: keyworded arguments + :type kwargs: typing.Any :return: Iterator for bound parameters with all information about it :rtype: typing.Iterator[BoundParameter] @@ -288,7 +292,9 @@ def log_level(self): # type: () -> int def log_level(self, val): # type: (int) -> None """Log level for normal behavior. + :param val: log level to use for calls and returns :type val: int + :raises TypeError: log level is not integer """ if not isinstance(val, int): raise TypeError( @@ -311,7 +317,9 @@ def exc_level(self): # type: () -> int def exc_level(self, val): # type: (int) -> None """Log level for exceptions. + :param val: log level to use for captured exceptions :type val: int + :raises TypeError: log level is not integer """ if not isinstance(val, int): raise TypeError( @@ -334,7 +342,9 @@ def max_indent(self): # type: () -> int def max_indent(self, val): # type: (int) -> None """Maximum indentation. + :param val: Maximal indentation before use of simple repr() :type val: int + :raises TypeError: indent is not integer """ if not isinstance(val, int): raise TypeError( @@ -373,7 +383,9 @@ def log_call_args(self): # type: () -> bool def log_call_args(self, val): # type: (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( @@ -396,7 +408,9 @@ def log_call_args_on_exc(self): # type: () -> bool def log_call_args_on_exc(self, val): # type: (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( @@ -419,7 +433,9 @@ def log_result_obj(self): # type: () -> bool def log_result_obj(self, val): # type: (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( @@ -432,7 +448,7 @@ def log_result_obj(self, val): # type: (bool) -> None @property def _logger(self): # type: () -> logging.Logger - """logger instance. + """Logger instance. :rtype: logging.Logger """ @@ -513,9 +529,13 @@ def _get_func_args_repr( ): # type: (...) -> typing.Text """Internal helper for reducing complexity of decorator code. + :param sig: function signature :type sig: inspect.Signature - :type args: tuple - :type kwargs: dict + :param args: not keyworded arguments + :type args: typing.Tuple + :param kwargs: keyworded arguments + :type kwargs: typing.Dict[str, typing.Any] + :return: repr over function arguments :rtype: typing.Text .. 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 b872dfe..bb65013 100644 --- a/logwrap/_repr_utils.py +++ b/logwrap/_repr_utils.py @@ -133,7 +133,9 @@ def _prepare_repr( ): # type: (...) -> 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) @@ -209,6 +211,7 @@ def next_indent(self, indent, multiplier=1): # type: (int, int) -> int :type indent: int :param multiplier: step multiplier :type multiplier: int + :return: next indentation value :rtype: int """ return indent + multiplier * self.indent_step @@ -221,8 +224,11 @@ def _repr_callable( ): # type: (...) -> typing.Text """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: typing.Text """ raise NotImplementedError() # pragma: no cover @@ -236,9 +242,13 @@ def _repr_simple( ): # type: (...) -> typing.Text """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: typing.Text """ raise NotImplementedError() # pragma: no cover @@ -297,6 +307,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[typing.Text] """ for elem in src: @@ -452,9 +463,13 @@ def _repr_simple( ): # type: (...) -> typing.Text """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: typing.Text """ indent = 0 if no_indent_start else indent @@ -483,6 +498,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[typing.Text] """ max_len = max((len(repr(key)) for key in src)) if src else 0 @@ -506,8 +522,11 @@ def _repr_callable( ): # type: (...) -> typing.Text """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: typing.Text """ param_str = "" @@ -564,6 +583,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: typing.Text """ return ( @@ -622,9 +642,13 @@ def _repr_simple( ): # type: (...) -> typing.Text """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: typing.Text """ indent = 0 if no_indent_start else indent @@ -653,7 +677,8 @@ def _repr_dict_items( :type src: dict :param indent: start indentation :type indent: int - :rtype: typing.Generator[typing.Text] + :return: repr of key/value pair from dict + :rtype: typing.Iterator[typing.Text] """ max_len = max((len(str(key)) for key in src)) if src else 0 for key, val in src.items(): @@ -676,8 +701,11 @@ def _repr_callable( ): # type: (...) -> typing.Text """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: typing.Text """ param_str = "" @@ -734,6 +762,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: typing.Text """ 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/test/test_log_wrap.py b/test/test_log_wrap.py index 8126523..a14c084 100644 --- a/test/test_log_wrap.py +++ b/test/test_log_wrap.py @@ -40,37 +40,19 @@ def setUp(self): Due to no possibility of proper mock patch of function defaults, modify directly. """ - self.logger = mock.Mock(spec=logging.Logger) - if six.PY2: - self.logwrap_defaults = logwrap.logwrap.func_defaults - self.logwrap_cls_defaults = logwrap.LogWrap.__init__.im_func.func_defaults - logwrap.logwrap.func_defaults = logwrap.LogWrap.__init__.im_func.func_defaults = tuple(( - None, - self.logger, - logging.DEBUG, - logging.ERROR, - 20, - None, - None, - None, - True, - True, - True - )) - # raise ValueError(logwrap.logwrap.func_defaults) - else: - self.logwrap_defaults = logwrap.logwrap.__kwdefaults__['log'] - self.logwrap_cls_defaults = logwrap.LogWrap.__init__.__kwdefaults__['log'] - logwrap.logwrap.__kwdefaults__['log'] = logwrap.LogWrap.__init__.__kwdefaults__['log'] = self.logger + self.logger = logging.getLogger('logwrap') + self.logger.setLevel(logging.DEBUG) + + self.stream = six.StringIO() + + self.logger.handlers = [] + handler = logging.StreamHandler(self.stream) + handler.setFormatter(logging.Formatter(fmt='%(levelname)s>%(message)s')) + self.logger.addHandler(handler) def tearDown(self): """Revert modifications.""" - if six.PY2: - logwrap.logwrap.func_defaults = self.logwrap_defaults - logwrap.LogWrap.__init__.im_func.func_defaults = self.logwrap_cls_defaults - else: - logwrap.LogWrap.__init__.__kwdefaults__['log'] = self.logwrap_cls_defaults - logwrap.logwrap.__kwdefaults__['log'] = self.logwrap_defaults + self.logger.handlers = [] def test_001_no_args(self): @logwrap.logwrap @@ -79,19 +61,13 @@ def func(): result = func() self.assertEqual(result, 'No args') + self.assertEqual( - [ - mock.call.log( - level=logging.DEBUG, - msg="Calling: \n'func'()" - ), - mock.call.log( - level=logging.DEBUG, - msg="Done: 'func' with result:\n{}".format( - logwrap.pretty_repr(result)) - ), - ], - self.logger.mock_calls, + "DEBUG>Calling: \n" + "'func'()\n" + "DEBUG>Done: 'func' with result:\n" + "u'''No args'''\n", + self.stream.getvalue(), ) def test_002_args_simple(self): @@ -104,30 +80,14 @@ def func(tst): result = func(arg) self.assertEqual(result, arg) self.assertEqual( - [ - mock.call.log( - level=logging.DEBUG, - msg=( - "Calling: \n" - "'func'(\n" - " # POSITIONAL_OR_KEYWORD:\n" - " 'tst'={},\n" - ")".format( - logwrap.pretty_repr( - arg, - indent=8, - no_indent_start=True - ) - ) - ) - ), - mock.call.log( - level=logging.DEBUG, - msg="Done: 'func' with result:\n{}".format( - logwrap.pretty_repr(result)) - ), - ], - self.logger.mock_calls, + "DEBUG>Calling: \n" + "'func'(\n" + " # POSITIONAL_OR_KEYWORD:\n" + " 'tst'=u'''test arg''',\n" + ")\n" + "DEBUG>Done: 'func' with result:\n" + "u'''test arg'''\n", + self.stream.getvalue(), ) def test_003_args_defaults(self): @@ -141,29 +101,14 @@ def func(tst=arg): self.assertEqual(result, arg) self.assertEqual( - [ - mock.call.log( - level=logging.DEBUG, - msg=( - "Calling: \n" - "'func'(\n" - " # POSITIONAL_OR_KEYWORD:\n" - " 'tst'={},\n" - ")".format( - logwrap.pretty_repr( - arg, - indent=8, - no_indent_start=True) - ) - ) - ), - mock.call.log( - level=logging.DEBUG, - msg="Done: 'func' with result:\n{}".format( - logwrap.pretty_repr(result)) - ), - ], - self.logger.mock_calls, + "DEBUG>Calling: \n" + "'func'(\n" + " # POSITIONAL_OR_KEYWORD:\n" + " 'tst'=u'''test arg''',\n" + ")\n" + "DEBUG>Done: 'func' with result:\n" + "u'''test arg'''\n", + self.stream.getvalue(), ) def test_004_args_complex(self): @@ -178,32 +123,23 @@ def func(param_string, param_dictionary): self.assertEqual(result, (string, dictionary)) self.assertEqual( - [ - mock.call.log( - level=logging.DEBUG, - msg=( - "Calling: \n" - "'func'(\n" - " # POSITIONAL_OR_KEYWORD:\n" - " 'param_string'={string},\n" - " 'param_dictionary'={dictionary},\n" - ")".format( - string=logwrap.pretty_repr( - string, - indent=8, no_indent_start=True), - dictionary=logwrap.pretty_repr( - dictionary, - indent=8, no_indent_start=True) - ) - ) - ), - mock.call.log( - level=logging.DEBUG, - msg="Done: 'func' with result:\n{}".format( - logwrap.pretty_repr(result)) - ), - ], - self.logger.mock_calls, + "DEBUG>Calling: \n" + "'func'(\n" + " # POSITIONAL_OR_KEYWORD:\n" + " 'param_string'=u'''string''',\n" + " 'param_dictionary'=\n" + " dict({\n" + " u'key': u'''dictionary''',\n" + " }),\n" + ")\n" + "DEBUG>Done: 'func' with result:\n" + "tuple((\n" + " u'''string''',\n" + " dict({\n" + " u'key': u'''dictionary''',\n" + " }),\n" + "))\n", + self.stream.getvalue(), ) def test_005_args_kwargs(self): @@ -218,32 +154,31 @@ def func(*args, **kwargs): self.assertEqual(result, (tuple(targs), tkwargs)) self.assertEqual( - [ - mock.call.log( - level=logging.DEBUG, - msg=( - "Calling: \n" - "'func'(\n" - " # VAR_POSITIONAL:\n" - " 'args'={args},\n" - " # VAR_KEYWORD:\n" - " 'kwargs'={kwargs},\n)".format( - args=logwrap.pretty_repr( - tuple(targs), - indent=8, no_indent_start=True), - kwargs=logwrap.pretty_repr( - tkwargs, - indent=8, no_indent_start=True) - ) - ) - ), - mock.call.log( - level=logging.DEBUG, - msg="Done: 'func' with result:\n{}".format( - logwrap.pretty_repr(result)) - ), - ], - self.logger.mock_calls, + "DEBUG>Calling: \n" + "'func'(\n" + " # VAR_POSITIONAL:\n" + " 'args'=\n" + " tuple((\n" + " u'''string1''',\n" + " u'''string2''',\n" + " )),\n" + " # VAR_KEYWORD:\n" + " 'kwargs'=\n" + " dict({\n" + " u'key': u'''tkwargs''',\n" + " }),\n" + ")\n" + "DEBUG>Done: 'func' with result:\n" + "tuple((\n" + " tuple((\n" + " u'''string1''',\n" + " u'''string2''',\n" + " )),\n" + " dict({\n" + " u'key': u'''tkwargs''',\n" + " }),\n" + "))\n", + self.stream.getvalue(), ) def test_006_renamed_args_kwargs(self): @@ -259,37 +194,34 @@ def func(arg, *positional, **named): result = func(arg, *targs, **tkwargs) self.assertEqual(result, (arg, tuple(targs), tkwargs)) self.assertEqual( - [ - mock.call.log( - level=logging.DEBUG, - msg=( - "Calling: \n" - "'func'(\n" - " # POSITIONAL_OR_KEYWORD:\n" - " 'arg'={arg},\n" - " # VAR_POSITIONAL:\n" - " 'positional'={args},\n" - " # VAR_KEYWORD:\n" - " 'named'={kwargs},\n)".format( - arg=logwrap.pretty_repr( - arg, - indent=8, no_indent_start=True), - args=logwrap.pretty_repr( - tuple(targs), - indent=8, no_indent_start=True), - kwargs=logwrap.pretty_repr( - tkwargs, - indent=8, no_indent_start=True) - ) - ) - ), - mock.call.log( - level=logging.DEBUG, - msg="Done: 'func' with result:\n{}".format( - logwrap.pretty_repr(result)) - ), - ], - self.logger.mock_calls, + "DEBUG>Calling: \n" + "'func'(\n" + " # POSITIONAL_OR_KEYWORD:\n" + " 'arg'=u'''arg''',\n" + " # VAR_POSITIONAL:\n" + " 'positional'=\n" + " tuple((\n" + " u'''string1''',\n" + " u'''string2''',\n" + " )),\n" + " # VAR_KEYWORD:\n" + " 'named'=\n" + " dict({\n" + " u'key': u'''tkwargs''',\n" + " }),\n" + ")\n" + "DEBUG>Done: 'func' with result:\n" + "tuple((\n" + " u'''arg''',\n" + " tuple((\n" + " u'''string1''',\n" + " u'''string2''',\n" + " )),\n" + " dict({\n" + " u'key': u'''tkwargs''',\n" + " }),\n" + "))\n", + self.stream.getvalue(), ) def test_007_negative(self): @@ -301,18 +233,12 @@ def func(): func() self.assertEqual( - [ - mock.call.log( - level=logging.DEBUG, - msg="Calling: \n'func'()" - ), - mock.call.log( - level=logging.ERROR, - msg="Failed: \n'func'()", - exc_info=True - ), - ], - self.logger.mock_calls, + 'DEBUG>Calling: \n' + "'func'()\n" + 'ERROR>Failed: \n' + "'func'()\n" + 'Traceback (most recent call last):', + '\n'.join(self.stream.getvalue().split('\n')[:5]), ) def test_008_negative_substitutions(self): @@ -331,7 +257,6 @@ def func(): with self.assertRaises(ValueError): func() - self.assertEqual(len(self.logger.mock_calls), 0) self.assertEqual( [ mock.call( @@ -428,22 +353,14 @@ def __repr__(tst_self): result = tst.func() self.assertEqual(result, 'No args') self.assertEqual( - [ - mock.call.log( - level=logging.DEBUG, - msg="Calling: \n" - "'func'(\n" - " # POSITIONAL_OR_KEYWORD:\n" - " 'tst_self'=,\n" - ")" - ), - mock.call.log( - level=logging.DEBUG, - msg="Done: 'func' with result:\n{}".format( - logwrap.pretty_repr(result)) - ), - ], - self.logger.mock_calls, + "DEBUG>Calling: \n" + "'func'(\n" + " # POSITIONAL_OR_KEYWORD:\n" + " 'tst_self'=,\n" + ")\n" + "DEBUG>Done: 'func' with result:\n" + "u'''No args'''\n", + self.stream.getvalue(), ) def test_012_class_decorator(self): @@ -454,18 +371,11 @@ def func(): result = func() self.assertEqual(result, 'No args') self.assertEqual( - [ - mock.call.log( - level=logging.DEBUG, - msg="Calling: \n'func'()" - ), - mock.call.log( - level=logging.DEBUG, - msg="Done: 'func' with result:\n{}".format( - logwrap.pretty_repr(result)) - ), - ], - self.logger.mock_calls, + "DEBUG>Calling: \n" + "'func'()\n" + "DEBUG>Done: 'func' with result:\n" + "u'''No args'''\n", + self.stream.getvalue(), ) def test_014_wrapped(self): @@ -487,40 +397,34 @@ def func(arg, darg=1, *args, **kwargs): (0, 1, (2, ), {'arg3': 3}) ) self.assertEqual( - [ - mock.call.log( - level=10, - msg="Calling: \n" - "'func'(\n" - " # POSITIONAL_OR_KEYWORD:\n" - " 'arg'=0,\n" - " 'darg'=1,\n" - " # VAR_POSITIONAL:\n" - " 'args'=\n" - " tuple((\n" - " 2,\n" - " )),\n" - " # VAR_KEYWORD:\n" - " 'kwargs'=\n" - " dict({\n" - " 'arg3': 3,\n" - " }),\n" - ")"), - mock.call.log( - level=10, - msg="Done: 'func' with result:\n" - "tuple((\n" - " 0,\n" - " 1,\n" - " tuple((\n" - " 2,\n" - " )),\n" - " dict({\n" - " 'arg3': 3,\n" - " }),\n" - "))") - ], - self.logger.mock_calls, + "DEBUG>Calling: \n" + "'func'(\n" + " # POSITIONAL_OR_KEYWORD:\n" + " 'arg'=0,\n" + " 'darg'=1,\n" + " # VAR_POSITIONAL:\n" + " 'args'=\n" + " tuple((\n" + " 2,\n" + " )),\n" + " # VAR_KEYWORD:\n" + " 'kwargs'=\n" + " dict({\n" + " 'arg3': 3,\n" + " }),\n" + ")\n" + "DEBUG>Done: 'func' with result:\n" + "tuple((\n" + " 0,\n" + " 1,\n" + " tuple((\n" + " 2,\n" + " )),\n" + " dict({\n" + " 'arg3': 3,\n" + " }),\n" + "))\n", + self.stream.getvalue(), ) def test_015_args_blacklist(self): @@ -576,7 +480,6 @@ def func(): with self.assertRaises(TypeError): func() - self.assertEqual(len(self.logger.mock_calls), 0) self.assertEqual( [ mock.call( @@ -632,7 +535,6 @@ def func(test_arg1, test_arg2): with self.assertRaises(TypeError): func(arg1, arg2) - self.assertEqual(len(self.logger.mock_calls), 0) self.assertEqual( [ mock.call( @@ -685,7 +587,6 @@ def func(test_arg1, test_arg2): with self.assertRaises(TypeError): func(arg1, arg2) - self.assertEqual(len(self.logger.mock_calls), 0) self.assertEqual( [ mock.call( @@ -713,7 +614,6 @@ def func(): func() - self.assertEqual(len(self.logger.mock_calls), 0) self.assertEqual( [ mock.call( @@ -736,24 +636,16 @@ def func(*args, **kwargs): result = func() self.assertEqual(result, 'No args') self.assertEqual( - [ - mock.call.log( - level=logging.DEBUG, - msg="Calling: \n" - "'func'(\n" - " # VAR_POSITIONAL:\n" - " 'args'=(),\n" - " # VAR_KEYWORD:\n" - " 'kwargs'={},\n" - ")" - ), - mock.call.log( - level=logging.DEBUG, - msg="Done: 'func' with result:\n{}".format( - logwrap.pretty_repr(result)) - ), - ], - self.logger.mock_calls, + "DEBUG>Calling: \n" + "'func'(\n" + " # VAR_POSITIONAL:\n" + " 'args'=(),\n" + " # VAR_KEYWORD:\n" + " 'kwargs'={},\n" + ")\n" + "DEBUG>Done: 'func' with result:\n" + "u'''No args'''\n", + self.stream.getvalue(), ) diff --git a/tox.ini b/tox.ini index 9fcd7b9..c525afe 100644 --- a/tox.ini +++ b/tox.ini @@ -43,9 +43,9 @@ commands = flake8 [testenv:pep257] deps = - pep257 + pydocstyle usedevelop = False -commands = pep257 logwrap +commands = pydocstyle logwrap [testenv:install] deps = @@ -78,6 +78,9 @@ show-source = True count = True max-line-length = 120 +[pydocstyle] +ignore = D401, D203, D213 + [testenv:docs] usedevelop = False deps =