From da67ff862002d5a4f19e89cedcf6ce4701bb49dd Mon Sep 17 00:00:00 2001
From: Joseph Weston <joseph@weston.cloud>
Date: Thu, 14 Feb 2019 16:04:25 +0100
Subject: [PATCH] implement decorator for deprecating function parameters

Also implement a specialization of this decorator for the 'args'
parameter, so as to avoid boilerplate (i.e. redefining the help
string everywhere the decorator is used).

The deprecation decorator can also be called directly with no
parameters to raise the warning. This is necessary because
methods of Cython cdef classes do not seem to play well with
this decorator (even after applying @cython.bind(True)), so
we need to call it directly from the body of the method.
---
 kwant/_common.py | 41 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/kwant/_common.py b/kwant/_common.py
index 71b4f782..e4623b8d 100644
--- a/kwant/_common.py
+++ b/kwant/_common.py
@@ -12,6 +12,7 @@ import numbers
 import inspect
 import warnings
 import importlib
+import functools
 from contextlib import contextmanager
 
 __all__ = ['KwantDeprecationWarning', 'UserCodeError']
@@ -41,6 +42,46 @@ class UserCodeError(Exception):
     pass
 
 
+def deprecate_parameter(parameter_name, version=None, help=None,
+                        stacklevel=3):
+    """Trigger a deprecation warning if the wrapped function is called
+       with the provided parameter."""
+
+    message = ("The '{}' parameter has been deprecated since version {} -- {}"
+               .format(parameter_name, version, help))
+
+    def warn():
+        warnings.warn(message, KwantDeprecationWarning,
+                      stacklevel=stacklevel)
+
+    def wrapper(f=None):
+
+        # Instead of being used as a decorator, can be called with
+        # no arguments to just raise the warning.
+        if f is None:
+            warn()
+            return
+
+        sig = inspect.signature(f)
+
+        @functools.wraps(f)
+        def inner(*args, **kwargs):
+            # If the named argument is truthy
+            if sig.bind(*args, **kwargs).arguments.get(parameter_name):
+                warn()
+            return f(*args, **kwargs)
+
+        return inner
+
+    return wrapper
+
+
+# Deprecation for 'args' parameter; defined once to minimize boilerplate,
+# as this parameter is present all over Kwant.
+deprecate_args = deprecate_parameter('args', version=1.4, help=
+    "Instead, provide named parameters as a dictionary via 'params'.")
+
+
 def interleave(seq):
     """Return an iterator that yields pairs of elements from a sequence.
 
-- 
GitLab