coveralls: ## Pull Request Test Coverage Report for [Build 371](https://coveralls.io/builds/17841933)

* **8** of **8**   **(100.0%)**  changed or added relevant lines in **3** files are covered.
* **3** unchanged lines in **2** files lost coverage.
* Overall coverage remained the same at **100.0%**

---


|  Files with Coverage Reduction | New Missed Lines | % |
| :-----|--------------|--: |
| [logwrap/_log_wrap_shared.py](https://coveralls.io/builds/17841933/source?filename=logwrap%2F_log_wrap_shared.py#L576) | 1 | 100.0% |
| [logwrap/_repr_utils.py](https://coveralls.io/builds/17841933/source?filename=logwrap%2F_repr_utils.py#L536) | 2 | 100.0% |
<!-- | **Total:** | **3** |  | -->

|  Totals | [![Coverage Status](https://coveralls.io/builds/17841933/badge)](https://coveralls.io/builds/17841933) |
| :-- | --: |
| Change from base [Build 369](https://coveralls.io/builds/17810316): |  0.0% |
| Covered Lines: | 457 |
| Relevant Lines: | 457 |

---
##### 💛  - [Coveralls](https://coveralls.io)

diff --git a/MANIFEST.in b/MANIFEST.in
index bce7ee3..69fb558 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -3,7 +3,7 @@ global-exclude *.c
 exclude Makefile
 prune tools
 exclude .travis.yml appveyor.yml
-exclude tox.ini
+exclude tox.ini pytest.ini .coveragerc
 prune test
 prune .github
 prune docs
diff --git a/doc/source/logwrap.rst b/doc/source/logwrap.rst
index 329d480..bd7970a 100644
--- a/doc/source/logwrap.rst
+++ b/doc/source/logwrap.rst
@@ -38,7 +38,7 @@ API: Decorators: `LogWrap` class and `logwrap` function.
         :param blacklisted_exceptions: list of exception,
                                        which should be re-raised without
                                        producing log record.
-        :type blacklisted_exceptions: typing.Optional[typing.Iterable[Exception]]
+        :type blacklisted_exceptions: typing.Optional[typing.Iterable[typing.Type[Exception]]]
         :param log_call_args: log call arguments before executing wrapped function.
         :type log_call_args: bool
         :param log_call_args_on_exc: log call arguments if exception raised.
@@ -48,6 +48,7 @@ API: Decorators: `LogWrap` class and `logwrap` function.
 
         .. versionchanged:: 3.3.0 Extract func from log and do not use Union.
         .. versionchanged:: 3.3.0 Deprecation of `*args`
+        .. versionchanged:: 4.0.0 Drop of *args
 
     .. py:method:: pre_process_param(self, arg)
 
@@ -88,7 +89,7 @@ API: Decorators: `LogWrap` class and `logwrap` function.
         ``typing.List[str]``, modified via mutability
     .. py:attribute:: blacklisted_exceptions
 
-        ``typing.List[Exception]``, modified via mutability
+        ``typing.List[typing.Type[Exception]]``, modified via mutability
     .. py:attribute:: log_call_args
     .. py:attribute:: log_call_args_on_exc
     .. py:attribute:: log_result_obj
diff --git a/logwrap/__init__.py b/logwrap/__init__.py
index 0e0a9b0..ccb47b1 100644
--- a/logwrap/__init__.py
+++ b/logwrap/__init__.py
@@ -56,7 +56,7 @@ __all__ = (
     'bind_args_kwargs'
 )
 
-__version__ = '3.3.1'
+__version__ = '4.0.0'
 __author__ = "Alexey Stepanov"
 __author_email__ = 'penguinolog@gmail.com'
 __maintainers__ = {
diff --git a/logwrap/_log_wrap2.py b/logwrap/_log_wrap2.py
index bb12316..7017ddc 100644
--- a/logwrap/_log_wrap2.py
+++ b/logwrap/_log_wrap2.py
@@ -25,7 +25,6 @@ from __future__ import unicode_literals
 
 import logging
 import typing  # noqa # pylint: disable=unused-import
-import warnings
 
 import six
 # noinspection PyUnresolvedReferences
@@ -36,45 +35,24 @@ from . import _log_wrap_shared
 __all__ = ('logwrap', 'LogWrap')
 
 
-def _apply_old_spec(*args, **kwargs):  # type: (...) -> typing.Dict[str, typing.Any]
-    # pylint: disable=unused-argument
-    def old_spec(
-        log=_log_wrap_shared.logger,  # type: typing.Union[logging.Logger, typing.Callable]
+class LogWrap(_log_wrap_shared.BaseLogWrap):
+    """LogWrap."""
+
+    __slots__ = ()
+
+    def __init__(
+        self,
+        func=None,  # type: typing.Optional[typing.Callable]
+        log=_log_wrap_shared.logger,  # type: logging.Logger
         log_level=logging.DEBUG,  # type: int
         exc_level=logging.ERROR,  # type: int
         max_indent=20,  # type: int
         spec=None,  # type: typing.Optional[typing.Callable]
         blacklisted_names=None,  # type: typing.Optional[typing.List[str]]
-        blacklisted_exceptions=None,  # type: typing.Optional[typing.List[Exception]]
+        blacklisted_exceptions=None,  # type: typing.Optional[typing.List[typing.Type[Exception]]]
         log_call_args=True,  # type: bool
         log_call_args_on_exc=True,  # type: bool
         log_result_obj=True,  # type: bool
-    ):  # type: (...) -> None
-        """Old spec."""
-        pass  # pragma: no cover
-
-    # pylint: enable=unused-argument
-
-    sig = funcsigs.signature(old_spec)  # type: funcsigs.Signature
-
-    final_kwargs = {
-        parameter.name: parameter.value
-        for parameter in _log_wrap_shared.bind_args_kwargs(sig, *args, **kwargs)
-    }  # type: typing.Dict[str, typing.Any]
-
-    return final_kwargs
-
-
-class LogWrap(_log_wrap_shared.BaseLogWrap):
-    """LogWrap."""
-
-    __slots__ = ()
-
-    def __init__(  # pylint: disable=keyword-arg-before-vararg
-        self,
-        func=None,  # type: typing.Optional[typing.Callable]
-        *args,
-        **kwargs
     ):  # type: (...) -> None
         """Log function calls and return values.
 
@@ -99,7 +77,7 @@ class LogWrap(_log_wrap_shared.BaseLogWrap):
         :param blacklisted_names: Blacklisted argument names. Arguments with this names will be skipped in log.
         :type blacklisted_names: typing.Optional[typing.Iterable[str]]
         :param blacklisted_exceptions: list of exception, which should be re-raised without producing log record.
-        :type blacklisted_exceptions: typing.Optional[typing.Iterable[Exception]]
+        :type blacklisted_exceptions: typing.Optional[typing.Iterable[typing.Type[Exception]]]
         :param log_call_args: log call arguments before executing wrapped function.
         :type log_call_args: bool
         :param log_call_args_on_exc: log call arguments if exception raised.
@@ -109,18 +87,19 @@ class LogWrap(_log_wrap_shared.BaseLogWrap):
 
         .. versionchanged:: 3.3.0 Extract func from log and do not use Union.
         """
-        if isinstance(func, logging.Logger):
-            args = (func,) + args
-            func = None
-
-        if args:
-            warnings.warn(
-                'Logwrap should use keyword-only parameters starting from version 3.4.0\n'
-                'After version 3.4.0 arguments list and order may be changed.',
-                DeprecationWarning
-            )
-
-        super(LogWrap, self).__init__(func=func, **_apply_old_spec(*args, **kwargs))
+        super(LogWrap, self).__init__(
+            func=func,
+            log=log,
+            log_level=log_level,
+            exc_level=exc_level,
+            max_indent=max_indent,
+            spec=spec,
+            blacklisted_names=blacklisted_names,
+            blacklisted_exceptions=blacklisted_exceptions,
+            log_call_args=log_call_args,
+            log_call_args_on_exc=log_call_args_on_exc,
+            log_result_obj=log_result_obj
+        )
 
     def _get_function_wrapper(
         self,
@@ -161,10 +140,18 @@ class LogWrap(_log_wrap_shared.BaseLogWrap):
 
 
 # pylint: disable=unexpected-keyword-arg, no-value-for-parameter
-def logwrap(  # pylint: disable=keyword-arg-before-vararg
+def logwrap(
     func=None,  # type: typing.Optional[typing.Callable]
-    *args,
-    **kwargs
+    log=_log_wrap_shared.logger,  # type: logging.Logger
+    log_level=logging.DEBUG,  # type: int
+    exc_level=logging.ERROR,  # type: int
+    max_indent=20,  # type: int
+    spec=None,  # type: typing.Optional[typing.Callable]
+    blacklisted_names=None,  # type: typing.Optional[typing.List[str]]
+    blacklisted_exceptions=None,  # type: typing.Optional[typing.List[typing.Type[Exception]]]
+    log_call_args=True,  # type: bool
+    log_call_args_on_exc=True,  # type: bool
+    log_result_obj=True,  # type: bool
 ):  # type: (...) -> typing.Union[LogWrap, typing.Callable]
     """Log function calls and return values.
 
@@ -188,7 +175,7 @@ def logwrap(  # pylint: disable=keyword-arg-before-vararg
     :param blacklisted_names: Blacklisted argument names. Arguments with this names will be skipped in log.
     :type blacklisted_names: typing.Optional[typing.List[str]]
     :param blacklisted_exceptions: list of exception, which should be re-raised without producing log record.
-    :type blacklisted_exceptions: typing.Optional[typing.List[Exception]]
+    :type blacklisted_exceptions: typing.Optional[typing.List[typing.Type[Exception]]]
     :param log_call_args: log call arguments before executing wrapped function.
     :type log_call_args: bool
     :param log_call_args_on_exc: log call arguments if exception raised.
@@ -200,19 +187,17 @@ def logwrap(  # pylint: disable=keyword-arg-before-vararg
 
     .. versionchanged:: 3.3.0 Extract func from log and do not use Union.
     """
-    if isinstance(func, logging.Logger):
-        args = (func, ) + args
-        func = None
-
-    if args:
-        warnings.warn(
-            'Logwrap should use keyword-only parameters starting from version 3.4.0\n'
-            'After version 3.4.0 arguments list and order may be changed.',
-            DeprecationWarning
-        )
-
     wrapper = LogWrap(
-        **_apply_old_spec(*args, **kwargs)
+        log=log,
+        log_level=log_level,
+        exc_level=exc_level,
+        max_indent=max_indent,
+        spec=spec,
+        blacklisted_names=blacklisted_names,
+        blacklisted_exceptions=blacklisted_exceptions,
+        log_call_args=log_call_args,
+        log_call_args_on_exc=log_call_args_on_exc,
+        log_result_obj=log_result_obj
     )
     if func is not None:
         return wrapper(func)
diff --git a/logwrap/_log_wrap2.pyi b/logwrap/_log_wrap2.pyi
index 027e34a..4f4dbfd 100644
--- a/logwrap/_log_wrap2.pyi
+++ b/logwrap/_log_wrap2.pyi
@@ -15,7 +15,7 @@ class LogWrap(_log_wrap_shared.BaseLogWrap):
         max_indent: int=...,
         spec: typing.Optional[typing.Callable]=...,
         blacklisted_names: typing.Optional[typing.List[str]]=...,
-        blacklisted_exceptions: typing.Optional[typing.List[Exception]]=...,
+        blacklisted_exceptions: typing.Optional[typing.List[typing.Type[Exception]]]=...,
         log_call_args: bool=...,
         log_call_args_on_exc: bool=...,
         log_result_obj: bool=...
@@ -31,7 +31,7 @@ def logwrap(
     max_indent: int=...,
     spec: typing.Optional[typing.Callable]=...,
     blacklisted_names: typing.Optional[typing.List[str]]=...,
-    blacklisted_exceptions: typing.Optional[typing.List[Exception]]=...,
+    blacklisted_exceptions: typing.Optional[typing.List[typing.Type[Exception]]]=...,
     log_call_args: bool=...,
     log_call_args_on_exc: bool=...,
     log_result_obj: bool=...
diff --git a/logwrap/_log_wrap3.py b/logwrap/_log_wrap3.py
index c808c5f..967c6b1 100644
--- a/logwrap/_log_wrap3.py
+++ b/logwrap/_log_wrap3.py
@@ -29,53 +29,31 @@ import functools
 import inspect
 import logging
 import typing
-import warnings
-
 
 from . import _log_wrap_shared
 
 __all__ = ('logwrap', 'LogWrap')
 
 
-def _apply_old_spec(*args, **kwargs) -> typing.Dict[str, typing.Any]:
-    # pylint: disable=unused-argument
-    def old_spec(
-        log: typing.Union[logging.Logger, typing.Callable] = _log_wrap_shared.logger,
-        log_level: int = logging.DEBUG,
-        exc_level: int = logging.ERROR,
-        max_indent: int = 20,
-        spec: typing.Optional[typing.Callable] = None,
-        blacklisted_names: typing.Optional[typing.List[str]] = None,
-        blacklisted_exceptions: typing.Optional[typing.List[Exception]] = None,
-        log_call_args: bool = True,
-        log_call_args_on_exc: bool = True,
-        log_result_obj: bool = True,
-    ) -> None:
-        """Old spec."""
-        pass  # pragma: no cover
-
-    # pylint: enable=unused-argument
-
-    sig = inspect.signature(old_spec)  # type: inspect.Signature
-
-    final_kwargs = {
-        parameter.name: parameter.value
-        for parameter in _log_wrap_shared.bind_args_kwargs(sig, *args, **kwargs)
-    }  # type: typing.Dict[str, typing.Any]
-
-    return final_kwargs
-
-
 class LogWrap(_log_wrap_shared.BaseLogWrap):
     """Python 3.4+ version of LogWrap."""
 
     __slots__ = ()
 
-    def __init__(  # pylint: disable=keyword-arg-before-vararg
+    def __init__(
         self,
         func: typing.Optional[typing.Callable] = None,
-        *args,
-        **kwargs
+        *,
+        log: logging.Logger = _log_wrap_shared.logger,
+        log_level: int = logging.DEBUG,
+        exc_level: int = logging.ERROR,
+        max_indent: int = 20,
+        spec: typing.Optional[typing.Callable] = None,
+        blacklisted_names: typing.Optional[typing.List[str]] = None,
+        blacklisted_exceptions: typing.Optional[typing.List[typing.Type[Exception]]] = None,
+        log_call_args: bool = True,
+        log_call_args_on_exc: bool = True,
+        log_result_obj: bool = True
     ) -> None:
         """Log function calls and return values.
 
@@ -98,15 +76,10 @@ class LogWrap(_log_wrap_shared.BaseLogWrap):
                      will be failed!
         :type spec: typing.Optional[typing.Callable]
         :param blacklisted_names: Blacklisted argument names.
-                                  Arguments with this names will be skipped
-                                  in log.
+                                  Arguments with this names will be skipped in log.
         :type blacklisted_names: typing.Optional[typing.Iterable[str]]
-        :param blacklisted_exceptions: list of exception,
-                                       which should be re-raised without
-                                       producing log record.
-        :type blacklisted_exceptions: typing.Optional[
-                                          typing.Iterable[Exception]
-                                      ]
+        :param blacklisted_exceptions: list of exception, which should be re-raised without producing log record.
+        :type blacklisted_exceptions: typing.Optional[typing.Iterable[typing.Type[Exception]]]
         :param log_call_args: log call arguments before executing
                               wrapped function.
         :type log_call_args: bool
@@ -117,18 +90,21 @@ class LogWrap(_log_wrap_shared.BaseLogWrap):
 
         .. versionchanged:: 3.3.0 Extract func from log and do not use Union.
         .. versionchanged:: 3.3.0 Deprecation of *args
+        .. versionchanged:: 4.0.0 Drop of *args
         """
-        if isinstance(func, logging.Logger):
-            args = (func,) + args
-            func = None
-
-        if args:
-            warnings.warn(
-                'Logwrap will accept keyword-only parameters starting from version 3.4.0',
-                DeprecationWarning
-            )
-
-        super(LogWrap, self).__init__(func=func, **_apply_old_spec(*args, **kwargs))
+        super(LogWrap, self).__init__(
+            func=func,
+            log=log,
+            log_level=log_level,
+            exc_level=exc_level,
+            max_indent=max_indent,
+            spec=spec,
+            blacklisted_names=blacklisted_names,
+            blacklisted_exceptions=blacklisted_exceptions,
+            log_call_args=log_call_args,
+            log_call_args_on_exc=log_call_args_on_exc,
+            log_result_obj=log_result_obj
+        )
 
     def _get_function_wrapper(
         self,
@@ -197,10 +173,19 @@ class LogWrap(_log_wrap_shared.BaseLogWrap):
 
 
 # pylint: disable=unexpected-keyword-arg, no-value-for-parameter
-def logwrap(  # pylint: disable=keyword-arg-before-vararg
+def logwrap(
     func: typing.Optional[typing.Callable] = None,
-    *args,
-    **kwargs
+    *,
+    log: logging.Logger = _log_wrap_shared.logger,
+    log_level: int = logging.DEBUG,
+    exc_level: int = logging.ERROR,
+    max_indent: int = 20,
+    spec: typing.Optional[typing.Callable] = None,
+    blacklisted_names: typing.Optional[typing.List[str]] = None,
+    blacklisted_exceptions: typing.Optional[typing.List[typing.Type[Exception]]] = None,
+    log_call_args: bool = True,
+    log_call_args_on_exc: bool = True,
+    log_result_obj: bool = True
 ) -> typing.Union[LogWrap, typing.Callable]:
     """Log function calls and return values. Python 3.4+ version.
 
@@ -224,7 +209,7 @@ def logwrap(  # pylint: disable=keyword-arg-before-vararg
     :param blacklisted_names: Blacklisted argument names. Arguments with this names will be skipped in log.
     :type blacklisted_names: typing.Optional[typing.Iterable[str]]
     :param blacklisted_exceptions: list of exceptions, which should be re-raised without producing log record.
-    :type blacklisted_exceptions: typing.Optional[typing.Iterable[Exception]]
+    :type blacklisted_exceptions: typing.Optional[typing.Iterable[typing.Type[Exception]]]
     :param log_call_args: log call arguments before executing wrapped function.
     :type log_call_args: bool
     :param log_call_args_on_exc: log call arguments if exception raised.
@@ -236,19 +221,19 @@ def logwrap(  # pylint: disable=keyword-arg-before-vararg
 
     .. versionchanged:: 3.3.0 Extract func from log and do not use Union.
     .. versionchanged:: 3.3.0 Deprecation of *args
+    .. versionchanged:: 4.0.0 Drop of *args
     """
-    if isinstance(func, logging.Logger):
-        args = (func, ) + args
-        func = None
-
-    if args:
-        warnings.warn(
-            'Logwrap will accept keyword-only parameters starting from version 3.4.0',
-            DeprecationWarning
-        )
-
     wrapper = LogWrap(
-        **_apply_old_spec(*args, **kwargs)
+        log=log,
+        log_level=log_level,
+        exc_level=exc_level,
+        max_indent=max_indent,
+        spec=spec,
+        blacklisted_names=blacklisted_names,
+        blacklisted_exceptions=blacklisted_exceptions,
+        log_call_args=log_call_args,
+        log_call_args_on_exc=log_call_args_on_exc,
+        log_result_obj=log_result_obj
     )
     if func is not None:
         return wrapper(func)
diff --git a/logwrap/_log_wrap3.pyi b/logwrap/_log_wrap3.pyi
index 7ea74fe..a28ada5 100644
--- a/logwrap/_log_wrap3.pyi
+++ b/logwrap/_log_wrap3.pyi
@@ -16,7 +16,7 @@ class LogWrap(_log_wrap_shared.BaseLogWrap):
         max_indent: int=...,
         spec: typing.Optional[typing.Callable]=...,
         blacklisted_names: typing.Optional[typing.List[str]]=...,
-        blacklisted_exceptions: typing.Optional[typing.List[Exception]]=...,
+        blacklisted_exceptions: typing.Optional[typing.List[typing.Type[Exception]]]=...,
         log_call_args: bool=...,
         log_call_args_on_exc: bool=...,
         log_result_obj: bool=...
@@ -33,7 +33,7 @@ def logwrap(
     max_indent: int=...,
     spec: typing.Optional[typing.Callable]=...,
     blacklisted_names: typing.Optional[typing.List[str]]=...,
-    blacklisted_exceptions: typing.Optional[typing.List[Exception]]=...,
+    blacklisted_exceptions: typing.Optional[typing.List[typing.Type[Exception]]]=...,
     log_call_args: bool=...,
     log_call_args_on_exc: bool=...,
     log_result_obj: bool=...
diff --git a/logwrap/_log_wrap_shared.py b/logwrap/_log_wrap_shared.py
index 0c95d9f..8bbc42a 100644
--- a/logwrap/_log_wrap_shared.py
+++ b/logwrap/_log_wrap_shared.py
@@ -45,14 +45,11 @@ else:  # pragma: no cover
 
 __all__ = ('BaseLogWrap', 'BoundParameter', 'bind_args_kwargs')
 
-logger = logging.getLogger(__name__)  # type: logging.Logger
+logger = logging.getLogger('logwrap')  # type: logging.Logger
 
 
 indent = 4
-fmt = "\n{spc:<{indent}}{{key!r}}={{val}},{{annotation}}".format(
-    spc='',
-    indent=indent,
-).format
+fmt = "\n{spc:<{indent}}{{key!r}}={{val}},{{annotation}}".format(spc='', indent=indent, ).format
 comment = "\n{spc:<{indent}}# {{kind!s}}:".format(spc='', indent=indent).format
 
 
@@ -246,7 +243,7 @@ class BaseLogWrap(_class_decorator.BaseDecorator):
         max_indent=20,  # type: int
         spec=None,  # type: typing.Optional[typing.Callable]
         blacklisted_names=None,  # type: typing.Optional[typing.Iterable[str]]
-        blacklisted_exceptions=None,  # type: typing.Optional[typing.Iterable[Exception]]
+        blacklisted_exceptions=None,  # type: typing.Optional[typing.Iterable[typing.Type[Exception]]]
         log_call_args=True,  # type: bool
         log_call_args_on_exc=True,  # type: bool
         log_result_obj=True,  # type: bool
@@ -271,18 +268,11 @@ class BaseLogWrap(_class_decorator.BaseDecorator):
                      signature with decorated function, or arguments bind
                      will be failed!
         :type spec: typing.Optional[typing.Callable]
-        :param blacklisted_names: Blacklisted argument names.
-                                  Arguments with this names will be skipped
-                                  in log.
+        :param blacklisted_names: Blacklisted argument names. Arguments with this names will be skipped in log.
         :type blacklisted_names: typing.Optional[typing.Iterable[str]]
-        :param blacklisted_exceptions: list of exception,
-                                       which should be re-raised without
-                                       producing log record.
-        :type blacklisted_exceptions: typing.Optional[
-                                          typing.Iterable[Exception]
-                                      ]
-        :param log_call_args: log call arguments before executing
-                              wrapped function.
+        :param blacklisted_exceptions: list of exception, which should be re-raised without producing log record.
+        :type blacklisted_exceptions: typing.Optional[typing.Iterable[typing.Type[Exception]]]
+        :param log_call_args: log call arguments before executing wrapped function.
         :type log_call_args: bool
         :param log_call_args_on_exc: log call arguments if exception raised.
         :type log_call_args_on_exc: bool
@@ -377,10 +367,10 @@ class BaseLogWrap(_class_decorator.BaseDecorator):
     @property
     def blacklisted_exceptions(
         self
-    ):  # type: () -> typing.List[Exception]
+    ):  # type: () -> typing.List[typing.Type[Exception]]
         """List of exceptions to re-raise without log.
 
-        :rtype: typing.List[Exception]
+        :rtype: typing.List[typing.Type[Exception]]
         """
         return self.__blacklisted_exceptions
 
diff --git a/logwrap/_log_wrap_shared.pyi b/logwrap/_log_wrap_shared.pyi
index 630f33e..5473d5c 100644
--- a/logwrap/_log_wrap_shared.pyi
+++ b/logwrap/_log_wrap_shared.pyi
@@ -105,7 +105,7 @@ class BaseLogWrap(_class_decorator.BaseDecorator):
     def blacklisted_names(self) -> typing.List[str]: ...
 
     @property
-    def blacklisted_exceptions(self) -> typing.List[Exception]: ...
+    def blacklisted_exceptions(self) -> typing.List[typing.Type[Exception]]: ...
 
     @property
     def log_call_args(self) -> bool: ...

Return normal signature from `*args` and `**kwargs` in logwrap.
**API breaking**.
diff --git a/test/test_log_wrap.py b/test/test_log_wrap.py
index 835eb6f..b6ec27e 100644
--- a/test/test_log_wrap.py
+++ b/test/test_log_wrap.py
@@ -37,9 +37,45 @@ else:
 
 
 # noinspection PyUnusedLocal,PyMissingOrEmptyDocstring
-@mock.patch('logwrap._log_wrap_shared.logger', autospec=True)
 class TestLogWrap(unittest.TestCase):
-    def test_001_no_args(self, logger):
+    def setUp(self):
+        """Preparation for tests.
+
+        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
+
+    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
+
+    def test_001_no_args(self):
         @logwrap.logwrap
         def func():
             return 'No args'
@@ -47,7 +83,6 @@ class TestLogWrap(unittest.TestCase):
         result = func()
         self.assertEqual(result, 'No args')
         self.assertEqual(
-            logger.mock_calls,
             [
                 mock.call.log(
                     level=logging.DEBUG,
@@ -58,10 +93,11 @@ class TestLogWrap(unittest.TestCase):
                     msg="Done: 'func' with result:\n{}".format(
                         logwrap.pretty_repr(result))
                 ),
-            ]
+            ],
+            self.logger.mock_calls,
         )
 
-    def test_002_args_simple(self, logger):
+    def test_002_args_simple(self):
         arg = 'test arg'
 
         @logwrap.logwrap
@@ -71,7 +107,6 @@ class TestLogWrap(unittest.TestCase):
         result = func(arg)
         self.assertEqual(result, arg)
         self.assertEqual(
-            logger.mock_calls,
             [
                 mock.call.log(
                     level=logging.DEBUG,
@@ -94,10 +129,11 @@ class TestLogWrap(unittest.TestCase):
                     msg="Done: 'func' with result:\n{}".format(
                         logwrap.pretty_repr(result))
                 ),
-            ]
+            ],
+            self.logger.mock_calls,
         )
 
-    def test_003_args_defaults(self, logger):
+    def test_003_args_defaults(self):
         arg = 'test arg'
 
         @logwrap.logwrap
@@ -108,7 +144,6 @@ class TestLogWrap(unittest.TestCase):
         self.assertEqual(result, arg)
 
         self.assertEqual(
-            logger.mock_calls,
             [
                 mock.call.log(
                     level=logging.DEBUG,
@@ -130,10 +165,11 @@ class TestLogWrap(unittest.TestCase):
                     msg="Done: 'func' with result:\n{}".format(
                         logwrap.pretty_repr(result))
                 ),
-            ]
+            ],
+            self.logger.mock_calls,
         )
 
-    def test_004_args_complex(self, logger):
+    def test_004_args_complex(self):
         string = 'string'
         dictionary = {'key': 'dictionary'}
 
@@ -145,7 +181,6 @@ class TestLogWrap(unittest.TestCase):
         self.assertEqual(result, (string, dictionary))
 
         self.assertEqual(
-            logger.mock_calls,
             [
                 mock.call.log(
                     level=logging.DEBUG,
@@ -170,10 +205,11 @@ class TestLogWrap(unittest.TestCase):
                     msg="Done: 'func' with result:\n{}".format(
                         logwrap.pretty_repr(result))
                 ),
-            ]
+            ],
+            self.logger.mock_calls,
         )
 
-    def test_005_args_kwargs(self, logger):
+    def test_005_args_kwargs(self):
         targs = ['string1', 'string2']
         tkwargs = {'key': 'tkwargs'}
 
@@ -185,7 +221,6 @@ class TestLogWrap(unittest.TestCase):
         self.assertEqual(result, (tuple(targs), tkwargs))
 
         self.assertEqual(
-            logger.mock_calls,
             [
                 mock.call.log(
                     level=logging.DEBUG,
@@ -210,10 +245,11 @@ class TestLogWrap(unittest.TestCase):
                     msg="Done: 'func' with result:\n{}".format(
                         logwrap.pretty_repr(result))
                 ),
-            ]
+            ],
+            self.logger.mock_calls,
         )
 
-    def test_006_renamed_args_kwargs(self, logger):
+    def test_006_renamed_args_kwargs(self):
         arg = 'arg'
         targs = ['string1', 'string2']
         tkwargs = {'key': 'tkwargs'}
@@ -226,7 +262,6 @@ class TestLogWrap(unittest.TestCase):
         result = func(arg, *targs, **tkwargs)
         self.assertEqual(result, (arg, tuple(targs), tkwargs))
         self.assertEqual(
-            logger.mock_calls,
             [
                 mock.call.log(
                     level=logging.DEBUG,
@@ -256,10 +291,11 @@ class TestLogWrap(unittest.TestCase):
                     msg="Done: 'func' with result:\n{}".format(
                         logwrap.pretty_repr(result))
                 ),
-            ]
+            ],
+            self.logger.mock_calls,
         )
 
-    def test_007_negative(self, logger):
+    def test_007_negative(self):
         @logwrap.logwrap
         def func():
             raise ValueError('as expected')
@@ -268,7 +304,6 @@ class TestLogWrap(unittest.TestCase):
             func()
 
         self.assertEqual(
-            logger.mock_calls,
             [
                 mock.call.log(
                     level=logging.DEBUG,
@@ -279,10 +314,11 @@ class TestLogWrap(unittest.TestCase):
                     msg="Failed: \n'func'()",
                     exc_info=True
                 ),
-            ]
+            ],
+            self.logger.mock_calls,
         )
 
-    def test_008_negative_substitutions(self, logger):
+    def test_008_negative_substitutions(self):
         new_logger = mock.Mock(spec=logging.Logger, name='logger')
         log = mock.Mock(name='log')
         new_logger.attach_mock(log, 'log')
@@ -298,9 +334,8 @@ class TestLogWrap(unittest.TestCase):
         with self.assertRaises(ValueError):
             func()
 
-        self.assertEqual(len(logger.mock_calls), 0)
+        self.assertEqual(len(self.logger.mock_calls), 0)
         self.assertEqual(
-            log.mock_calls,
             [
                 mock.call(
                     level=logging.INFO,
@@ -311,10 +346,11 @@ class TestLogWrap(unittest.TestCase):
                     msg="Failed: \n'func'()",
                     exc_info=True
                 ),
-            ]
+            ],
+            log.mock_calls,
         )
 
-    def test_009_spec(self, logger):
+    def test_009_spec(self):
         new_logger = mock.Mock(spec=logging.Logger, name='logger')
         log = mock.Mock(name='log')
         new_logger.attach_mock(log, 'log')
@@ -335,7 +371,6 @@ class TestLogWrap(unittest.TestCase):
         result = func()
         self.assertEqual(result, arg)
         self.assertEqual(
-            log.mock_calls,
             [
                 mock.call(
                     level=logging.DEBUG,
@@ -348,10 +383,11 @@ class TestLogWrap(unittest.TestCase):
                     level=logging.DEBUG,
                     msg="Done: 'func' with result:\n"
                         "u'''test arg'''"),
-            ]
+            ],
+            log.mock_calls,
         )
 
-    def test_010_indent(self, logger):
+    def test_010_indent(self):
         new_logger = mock.Mock(spec=logging.Logger, name='logger')
         log = mock.Mock(name='log')
         new_logger.attach_mock(log, 'log')
@@ -363,7 +399,6 @@ class TestLogWrap(unittest.TestCase):
         func()
 
         self.assertEqual(
-            log.mock_calls,
             [
                 mock.call(
                     level=logging.DEBUG,
@@ -379,10 +414,11 @@ class TestLogWrap(unittest.TestCase):
                         "        ]),\n"
                         "    ]),\n"
                         "])"),
-            ]
+            ],
+            log.mock_calls,
         )
 
-    def test_011_method(self, logger):
+    def test_011_method(self):
         class Tst(object):
             @logwrap.logwrap
             def func(tst_self):
@@ -395,7 +431,6 @@ class TestLogWrap(unittest.TestCase):
         result = tst.func()
         self.assertEqual(result, 'No args')
         self.assertEqual(
-            logger.mock_calls,
             [
                 mock.call.log(
                     level=logging.DEBUG,
@@ -410,10 +445,11 @@ class TestLogWrap(unittest.TestCase):
                     msg="Done: 'func' with result:\n{}".format(
                         logwrap.pretty_repr(result))
                 ),
-            ]
+            ],
+            self.logger.mock_calls,
         )
 
-    def test_012_class_decorator(self, logger):
+    def test_012_class_decorator(self):
         @logwrap.LogWrap
         def func():
             return 'No args'
@@ -421,7 +457,6 @@ class TestLogWrap(unittest.TestCase):
         result = func()
         self.assertEqual(result, 'No args')
         self.assertEqual(
-            logger.mock_calls,
             [
                 mock.call.log(
                     level=logging.DEBUG,
@@ -432,14 +467,15 @@ class TestLogWrap(unittest.TestCase):
                     msg="Done: 'func' with result:\n{}".format(
                         logwrap.pretty_repr(result))
                 ),
-            ]
+            ],
+            self.logger.mock_calls,
         )
 
     @unittest.skipUnless(
         six.PY3,
         'Strict python 3 syntax'
     )
-    def test_013_py3_args(self, logger):
+    def test_013_py3_args(self):
         new_logger = mock.Mock(spec=logging.Logger, name='logger')
         log = mock.Mock(name='log')
         new_logger.attach_mock(log, 'log')
@@ -488,7 +524,7 @@ def tst(arg, darg=1, *args, kwarg, dkwarg=4, **kwargs):
             ]
         )
 
-    def test_014_wrapped(self, logger):
+    def test_014_wrapped(self):
         # noinspection PyShadowingNames
         def simpledeco(func):
             @six.wraps(func)
@@ -507,7 +543,6 @@ def tst(arg, darg=1, *args, kwarg, dkwarg=4, **kwargs):
             (0, 1, (2, ), {'arg3': 3})
         )
         self.assertEqual(
-            logger.mock_calls,
             [
                 mock.call.log(
                     level=10,
@@ -540,10 +575,11 @@ def tst(arg, darg=1, *args, kwarg, dkwarg=4, **kwargs):
                         "        'arg3': 3,\n"
                         "    }),\n"
                         "))")
-            ]
+            ],
+            self.logger.mock_calls,
         )
 
-    def test_015_args_blacklist(self, logger):
+    def test_015_args_blacklist(self):
         new_logger = mock.Mock(spec=logging.Logger, name='logger')
         log = mock.Mock(name='log')
         new_logger.attach_mock(log, 'log')
@@ -584,7 +620,7 @@ def tst(arg, darg=1, *args, kwarg, dkwarg=4, **kwargs):
             ]
         )
 
-    def test_016_exceptions_blacklist(self, logger):
+    def test_016_exceptions_blacklist(self):
         new_logger = mock.Mock(spec=logging.Logger, name='logger')
         log = mock.Mock(name='log')
         new_logger.attach_mock(log, 'log')
@@ -596,18 +632,18 @@ def tst(arg, darg=1, *args, kwarg, dkwarg=4, **kwargs):
         with self.assertRaises(TypeError):
             func()
 
-        self.assertEqual(len(logger.mock_calls), 0)
+        self.assertEqual(len(self.logger.mock_calls), 0)
         self.assertEqual(
-            log.mock_calls,
             [
                 mock.call(
                     level=logging.DEBUG,
                     msg="Calling: \n'func'()"
                 ),
-            ]
+            ],
+            log.mock_calls,
         )
 
-    def test_017_disable_args(self, logger):
+    def test_017_disable_args(self):
         new_logger = mock.Mock(spec=logging.Logger, name='logger')
         log = mock.Mock(name='log')
         new_logger.attach_mock(log, 'log')
@@ -622,7 +658,6 @@ def tst(arg, darg=1, *args, kwarg, dkwarg=4, **kwargs):
         result = func(arg1, arg2)
         self.assertEqual(result, (arg1, arg2))
         self.assertEqual(
-            log.mock_calls,
             [
                 mock.call(
                     level=logging.DEBUG,
@@ -634,10 +669,11 @@ def tst(arg, darg=1, *args, kwarg, dkwarg=4, **kwargs):
                     msg="Done: 'func' with result:\n{}".format(
                         logwrap.pretty_repr(result))
                 ),
-            ]
+            ],
+            log.mock_calls,
         )
 
-    def test_018_disable_args_exc(self, logger):
+    def test_018_disable_args_exc(self):
         new_logger = mock.Mock(spec=logging.Logger, name='logger')
         log = mock.Mock(name='log')
         new_logger.attach_mock(log, 'log')
@@ -652,9 +688,8 @@ def tst(arg, darg=1, *args, kwarg, dkwarg=4, **kwargs):
         with self.assertRaises(TypeError):
             func(arg1, arg2)
 
-        self.assertEqual(len(logger.mock_calls), 0)
+        self.assertEqual(len(self.logger.mock_calls), 0)
         self.assertEqual(
-            log.mock_calls,
             [
                 mock.call(
                     level=logging.DEBUG,
@@ -683,10 +718,11 @@ def tst(arg, darg=1, *args, kwarg, dkwarg=4, **kwargs):
                     msg="Failed: \n'func'()",
                     exc_info=True
                 ),
-            ]
+            ],
+            log.mock_calls,
         )
 
-    def test_019_disable_all_args(self, logger):
+    def test_019_disable_all_args(self):
         new_logger = mock.Mock(spec=logging.Logger, name='logger')
         log = mock.Mock(name='log')
         new_logger.attach_mock(log, 'log')
@@ -705,9 +741,8 @@ def tst(arg, darg=1, *args, kwarg, dkwarg=4, **kwargs):
         with self.assertRaises(TypeError):
             func(arg1, arg2)
 
-        self.assertEqual(len(logger.mock_calls), 0)
+        self.assertEqual(len(self.logger.mock_calls), 0)
         self.assertEqual(
-            log.mock_calls,
             [
                 mock.call(
                     level=logging.DEBUG,
@@ -719,10 +754,11 @@ def tst(arg, darg=1, *args, kwarg, dkwarg=4, **kwargs):
                     msg="Failed: \n'func'()",
                     exc_info=True
                 ),
-            ]
+            ],
+            log.mock_calls,
         )
 
-    def test_020_disable_result(self, logger):
+    def test_020_disable_result(self):
         new_logger = mock.Mock(spec=logging.Logger, name='logger')
         log = mock.Mock(name='log')
         new_logger.attach_mock(log, 'log')
@@ -733,9 +769,8 @@ def tst(arg, darg=1, *args, kwarg, dkwarg=4, **kwargs):
 
         func()
 
-        self.assertEqual(len(logger.mock_calls), 0)
+        self.assertEqual(len(self.logger.mock_calls), 0)
         self.assertEqual(
-            log.mock_calls,
             [
                 mock.call(
                     level=logging.DEBUG,
@@ -745,7 +780,36 @@ def tst(arg, darg=1, *args, kwarg, dkwarg=4, **kwargs):
                     level=logging.DEBUG,
                     msg="Done: 'func'"
                 ),
-            ]
+            ],
+            log.mock_calls,
+        )
+
+    def test_empty_args_kwargs(self):
+        @logwrap.logwrap
+        def func(*args, **kwargs):
+            return 'No args'
+
+        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,
         )
 
 
@@ -908,81 +972,3 @@ class TestObject(unittest.TestCase):
                 mock.call.log(level=logging.DEBUG, msg="Done: 'func'")
             ]
         )
-
-
-# noinspection PyUnusedLocal,PyMissingOrEmptyDocstring
-@mock.patch('logwrap._log_wrap_shared.logger', autospec=True)
-class TestDeprecation(unittest.TestCase):
-    def test_001_args_func(self, logger):
-        new_logger = mock.Mock(spec=logging.Logger, name='logger')
-        log = mock.Mock(name='log')
-        new_logger.attach_mock(log, 'log')
-
-        arg = 'test arg'
-
-        with mock.patch('warnings.warn') as warn:
-            @logwrap.logwrap(
-                new_logger,
-            )
-            def func(*args, **kwargs):
-                return args[0] if args else kwargs.get('arg', arg)
-
-            self.assertTrue(bool(warn.mock_calls))
-
-        result = func()
-        self.assertEqual(result, arg)
-        self.assertEqual(
-            log.mock_calls,
-            [
-                mock.call(
-                    level=logging.DEBUG,
-                    msg="Calling: \n"
-                        "'func'(\n"
-                        "    # VAR_POSITIONAL:\n"
-                        "    'args'=(),\n"
-                        "    # VAR_KEYWORD:\n"
-                        "    'kwargs'={},\n"
-                        ")"),
-                mock.call(
-                    level=logging.DEBUG,
-                    msg="Done: 'func' with result:\n"
-                        "u'''test arg'''"),
-            ]
-        )
-
-    def test_002_args_cls(self, logger):
-        new_logger = mock.Mock(spec=logging.Logger, name='logger')
-        log = mock.Mock(name='log')
-        new_logger.attach_mock(log, 'log')
-
-        arg = 'test arg'
-
-        with mock.patch('warnings.warn') as warn:
-            @logwrap.LogWrap(
-                new_logger,
-            )
-            def func(*args, **kwargs):
-                return args[0] if args else kwargs.get('arg', arg)
-
-            self.assertTrue(bool(warn.mock_calls))
-
-        result = func()
-        self.assertEqual(result, arg)
-        self.assertEqual(
-            log.mock_calls,
-            [
-                mock.call(
-                    level=logging.DEBUG,
-                    msg="Calling: \n"
-                        "'func'(\n"
-                        "    # VAR_POSITIONAL:\n"
-                        "    'args'=(),\n"
-                        "    # VAR_KEYWORD:\n"
-                        "    'kwargs'={},\n"
-                        ")"),
-                mock.call(
-                    level=logging.DEBUG,
-                    msg="Done: 'func' with result:\n"
-                        "u'''test arg'''"),
-            ]
-        )
diff --git a/test/test_log_wrap_py3.py b/test/test_log_wrap_py3.py
index bd97db9..e7c6728 100644
--- a/test/test_log_wrap_py3.py
+++ b/test/test_log_wrap_py3.py
@@ -34,7 +34,6 @@ import logwrap
 
 
 # noinspection PyUnusedLocal,PyMissingOrEmptyDocstring
-@mock.patch('logwrap._log_wrap_shared.logger', autospec=True)
 @unittest.skipIf(
     asyncio is None,
     'Strict python 3.3+ API'
@@ -44,7 +43,22 @@ class TestLogWrapAsync(unittest.TestCase):
     def setUpClass(cls):
         cls.loop = asyncio.get_event_loop()
 
-    def test_coroutine_async(self, logger):
+    def setUp(self):
+        """Preparation for tests.
+
+        Due to no possibility of proper mock patch of function defaults, modify directly.
+        """
+        self.logger = mock.Mock(spec=logging.Logger)
+        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
+
+    def tearDown(self):
+        """Revert modifications."""
+        logwrap.LogWrap.__init__.__kwdefaults__['log'] = self.logwrap_cls_defaults
+        logwrap.logwrap.__kwdefaults__['log'] = self.logwrap_defaults
+
+    def test_coroutine_async(self):
         @logwrap.logwrap
         @asyncio.coroutine
         def func():
@@ -52,7 +66,6 @@ class TestLogWrapAsync(unittest.TestCase):
 
         self.loop.run_until_complete(func())
         self.assertEqual(
-            logger.mock_calls,
             [
                 mock.call.log(
                     level=logging.DEBUG,
@@ -62,10 +75,11 @@ class TestLogWrapAsync(unittest.TestCase):
                     level=logging.DEBUG,
                     msg="Done: 'func' with result:\nNone"
                 )
-            ]
+            ],
+            self.logger.mock_calls,
         )
 
-    def test_coroutine_async_as_argumented(self, logger):
+    def test_coroutine_async_as_argumented(self):
         new_logger = mock.Mock(spec=logging.Logger, name='logger')
         log = mock.Mock(name='log')
         new_logger.attach_mock(log, 'log')
@@ -78,7 +92,6 @@ class TestLogWrapAsync(unittest.TestCase):
         self.loop.run_until_complete(func())
 
         self.assertEqual(
-            log.mock_calls,
             [
                 mock.call.log(
                     level=logging.DEBUG,
@@ -88,10 +101,11 @@ class TestLogWrapAsync(unittest.TestCase):
                     level=logging.DEBUG,
                     msg="Done: 'func' with result:\nNone"
                 )
-            ]
+            ],
+            log.mock_calls,
         )
 
-    def test_coroutine_fail(self, logger):
+    def test_coroutine_fail(self):
         @logwrap.logwrap
         @asyncio.coroutine
         def func():
@@ -101,7 +115,6 @@ class TestLogWrapAsync(unittest.TestCase):
             self.loop.run_until_complete(func())
 
         self.assertEqual(
-            logger.mock_calls,
             [
                 mock.call.log(
                     level=logging.DEBUG,
@@ -112,10 +125,11 @@ class TestLogWrapAsync(unittest.TestCase):
                     msg="Failed: \n'func'()",
                     exc_info=True
                 )
-            ]
+            ],
+            self.logger.mock_calls,
         )
 
-    def test_exceptions_blacklist(self, logger):
+    def test_exceptions_blacklist(self):
         new_logger = mock.Mock(spec=logging.Logger, name='logger')
         log = mock.Mock(name='log')
         new_logger.attach_mock(log, 'log')
@@ -131,26 +145,40 @@ class TestLogWrapAsync(unittest.TestCase):
         # While we're not expanding result coroutine object from namespace,
         # do not check execution result
 
-        self.assertEqual(len(logger.mock_calls), 0)
+        self.assertEqual(len(self.logger.mock_calls), 0)
         self.assertEqual(
-            log.mock_calls,
             [
                 mock.call(
                     level=logging.DEBUG,
                     msg="Awaiting: \n'func'()"
                 ),
-            ]
+            ],
+            log.mock_calls,
         )
 
 
 # noinspection PyUnusedLocal,PyMissingOrEmptyDocstring
-@mock.patch('logwrap._log_wrap_shared.logger', autospec=True)
 @unittest.skipIf(
     sys.version_info[:2] < (3, 4),
     'Strict python 3.3+ API'
 )
 class TestAnnotated(unittest.TestCase):
-    def test_annotation_args(self, logger):
+    def setUp(self):
+        """Preparation for tests.
+
+        Due to no possibility of proper mock patch of function defaults, modify directly.
+        """
+        self.logger = mock.Mock(spec=logging.Logger)
+        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
+
+    def tearDown(self):
+        """Revert modifications."""
+        logwrap.LogWrap.__init__.__kwdefaults__['log'] = self.logwrap_cls_defaults
+        logwrap.logwrap.__kwdefaults__['log'] = self.logwrap_defaults
+
+    def test_annotation_args(self):
         namespace = {'logwrap': logwrap}
 
         exec("""
@@ -164,7 +192,6 @@ def func(a: typing.Optional[int]=None):
         func = namespace['func']  # type: typing.Callable[..., None]
         func()
         self.assertEqual(
-            logger.mock_calls,
             [
                 mock.call.log(
                     level=logging.DEBUG,
@@ -178,5 +205,6 @@ def func(a: typing.Optional[int]=None):
                     level=logging.DEBUG,
                     msg="Done: 'func' with result:\nNone"
                 )
-            ]
+            ],
+            self.logger.mock_calls,
         )
diff --git a/test/test_log_wrap_py35.py b/test/test_log_wrap_py35.py
index 2f0c00f..7498e8b 100644
--- a/test/test_log_wrap_py35.py
+++ b/test/test_log_wrap_py35.py
@@ -33,7 +33,6 @@ import logwrap
 
 
 # noinspection PyUnusedLocal,PyMissingOrEmptyDocstring
-@mock.patch('logwrap._log_wrap_shared.logger', autospec=True)
 @unittest.skipIf(
     asyncio is None or sys.version_info[:2] < (3, 5),
     'Strict python 3.5+ API'
@@ -44,7 +43,22 @@ class TestLogWrapAsync(unittest.TestCase):
     def setUpClass(cls):
         cls.loop = asyncio.get_event_loop()
 
-    def test_coroutine_async(self, logger):
+    def setUp(self):
+        """Preparation for tests.
+
+        Due to no possibility of proper mock patch of function defaults, modify directly.
+        """
+        self.logger = mock.Mock(spec=logging.Logger)
+        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
+
+    def tearDown(self):
+        """Revert modifications."""
+        logwrap.LogWrap.__init__.__kwdefaults__['log'] = self.logwrap_cls_defaults
+        logwrap.logwrap.__kwdefaults__['log'] = self.logwrap_defaults
+
+    def test_coroutine_async(self):
         namespace = {'logwrap': logwrap}
 
         exec("""
@@ -58,7 +72,6 @@ async def func():
 
         self.loop.run_until_complete(func())
         self.assertEqual(
-            logger.mock_calls,
             [
                 mock.call.log(
                     level=logging.DEBUG,
@@ -68,10 +81,11 @@ async def func():
                     level=logging.DEBUG,
                     msg="Done: 'func' with result:\nNone"
                 )
-            ]
+            ],
+            self.logger.mock_calls,
         )
 
-    def test_coroutine_async_as_argumented(self, logger):
+    def test_coroutine_async_as_argumented(self):
         new_logger = mock.Mock(spec=logging.Logger, name='logger')
         log = mock.Mock(name='log')
         new_logger.attach_mock(log, 'log')
@@ -90,7 +104,6 @@ async def func():
         self.loop.run_until_complete(func())
 
         self.assertEqual(
-            log.mock_calls,
             [
                 mock.call.log(
                     level=logging.DEBUG,
@@ -100,10 +113,11 @@ async def func():
                     level=logging.DEBUG,
                     msg="Done: 'func' with result:\nNone"
                 )
-            ]
+            ],
+            log.mock_calls,
         )
 
-    def test_coroutine_fail(self, logger):
+    def test_coroutine_fail(self):
         namespace = {'logwrap': logwrap}
 
         exec("""
@@ -119,7 +133,6 @@ async def func():
             self.loop.run_until_complete(func())
 
         self.assertEqual(
-            logger.mock_calls,
             [
                 mock.call.log(
                     level=logging.DEBUG,
@@ -130,10 +143,11 @@ async def func():
                     msg="Failed: \n'func'()",
                     exc_info=True
                 )
-            ]
+            ],
+            self.logger.mock_calls,
         )
 
-    def test_exceptions_blacklist(self, logger):
+    def test_exceptions_blacklist(self):
         new_logger = mock.Mock(spec=logging.Logger, name='logger')
         log = mock.Mock(name='log')
         new_logger.attach_mock(log, 'log')
@@ -155,13 +169,13 @@ async def func():
         # While we're not expanding result coroutine object from namespace,
         # do not check execution result
 
-        self.assertEqual(len(logger.mock_calls), 0)
+        self.assertEqual(len(self.logger.mock_calls), 0)
         self.assertEqual(
-            log.mock_calls,
             [
                 mock.call(
                     level=logging.DEBUG,
                     msg="Awaiting: \n'func'()"
                 ),
-            ]
+            ],
+            log.mock_calls,
         )

pip install -e .[dev]
parse_log_pytest_v2
requirements.txt
pytest pytest-cov pytest-html pytest-sugar
apt-get update apt-get install -y gcc
3.7
requirements.txt
pytest -vv
certifi @ file:///croot/certifi_1671487769961/work/certifi
coverage==7.2.7
exceptiongroup==1.2.2
importlib-metadata==6.7.0
iniconfig==2.0.0
-e git+https://github.com/python-useful-helpers/logwrap.git@f31146e46482f95dcf003432b96844edd4d3ceb7#egg=logwrap
packaging==24.0
pluggy==1.2.0
py==1.11.0
pytest==7.4.4
pytest-cov==4.1.0
pytest-html==3.2.0
pytest-metadata==3.0.0
pytest-sugar==1.0.0
six==1.17.0
termcolor==2.3.0
tomli==2.0.1
typing==3.7.4.3
typing_extensions==4.7.1
zipp==3.15.0

name: logwrap
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=22.3.1=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - coverage==7.2.7
      - exceptiongroup==1.2.2
      - importlib-metadata==6.7.0
      - iniconfig==2.0.0
      - logwrap==3.3.1
      - packaging==24.0
      - pluggy==1.2.0
      - py==1.11.0
      - pytest==7.4.4
      - pytest-cov==4.1.0
      - pytest-html==3.2.0
      - pytest-metadata==3.0.0
      - pytest-sugar==1.0.0
      - six==1.17.0
      - termcolor==2.3.0
      - tomli==2.0.1
      - typing==3.7.4.3
      - typing-extensions==4.7.1
      - zipp==3.15.0
prefix: /opt/conda/envs/logwrap

test/test_log_wrap.py::TestLogWrap::test_001_no_args test/test_log_wrap.py::TestLogWrap::test_002_args_simple test/test_log_wrap.py::TestLogWrap::test_003_args_defaults test/test_log_wrap.py::TestLogWrap::test_004_args_complex test/test_log_wrap.py::TestLogWrap::test_005_args_kwargs test/test_log_wrap.py::TestLogWrap::test_006_renamed_args_kwargs test/test_log_wrap.py::TestLogWrap::test_007_negative test/test_log_wrap.py::TestLogWrap::test_008_negative_substitutions test/test_log_wrap.py::TestLogWrap::test_009_spec test/test_log_wrap.py::TestLogWrap::test_010_indent test/test_log_wrap.py::TestLogWrap::test_011_method test/test_log_wrap.py::TestLogWrap::test_012_class_decorator test/test_log_wrap.py::TestLogWrap::test_013_py3_args test/test_log_wrap.py::TestLogWrap::test_014_wrapped test/test_log_wrap.py::TestLogWrap::test_015_args_blacklist test/test_log_wrap.py::TestLogWrap::test_016_exceptions_blacklist test/test_log_wrap.py::TestLogWrap::test_017_disable_args test/test_log_wrap.py::TestLogWrap::test_018_disable_args_exc test/test_log_wrap.py::TestLogWrap::test_019_disable_all_args test/test_log_wrap.py::TestLogWrap::test_020_disable_result test/test_log_wrap.py::TestLogWrap::test_empty_args_kwargs test/test_log_wrap_py3.py::TestLogWrapAsync::test_coroutine_async test/test_log_wrap_py3.py::TestLogWrapAsync::test_coroutine_async_as_argumented test/test_log_wrap_py3.py::TestLogWrapAsync::test_coroutine_fail test/test_log_wrap_py3.py::TestLogWrapAsync::test_exceptions_blacklist test/test_log_wrap_py3.py::TestAnnotated::test_annotation_args test/test_log_wrap_py35.py::TestLogWrapAsync::test_coroutine_async test/test_log_wrap_py35.py::TestLogWrapAsync::test_coroutine_async_as_argumented test/test_log_wrap_py35.py::TestLogWrapAsync::test_coroutine_fail test/test_log_wrap_py35.py::TestLogWrapAsync::test_exceptions_blacklist
test/test_log_wrap.py::TestObject::test_001_basic test/test_log_wrap.py::TestObject::test_002_override_skip_arg test/test_log_wrap.py::TestObject::test_003_override_change_arg test/test_log_wrap.py::TestObject::test_003_override_change_repr
logwrap/_log_wrap3.py logwrap/_log_wrap_shared.pyi logwrap/_log_wrap2.py logwrap/_log_wrap3.pyi doc/source/logwrap.rst MANIFEST.in logwrap/__init__.py logwrap/_log_wrap_shared.py logwrap/_log_wrap2.pyi
logwrap/_log_wrap3.py logwrap/_log_wrap_shared.pyi logwrap/_log_wrap2.py logwrap/_log_wrap3.pyi doc/source/logwrap.rst MANIFEST.in logwrap/__init__.py logwrap/_log_wrap_shared.py logwrap/_log_wrap2.pyi