Skip to content

Instantly share code, notes, and snippets.

@rfezzani
Last active September 13, 2019 08:13
Show Gist options
  • Save rfezzani/002181c8667ec4c671421a4d938167eb to your computer and use it in GitHub Desktop.
Save rfezzani/002181c8667ec4c671421a4d938167eb to your computer and use it in GitHub Desktop.
Python decorator to ensure backward compatibility if function's argument name is modified
"""Decorator ensuring backward compatibility when an argument name is
modified in a function definition.
# Use case
Let's suppose that in a previous version, the function `func` was defined
with the `old_arg` argument name:
```python
def func(old_arg, arg=0):
print(old_arg, arg)
```
For any reason, if a developer decides to use more appropriate argument
name `new_name`. This may introduce backward compatibility issues if a
user has in his code `func(old_arg=1)`.
The `arg_fix` decorator takes a dictionary as argument for mapping
between old argument names and new ones, and check if the patched
function is called with an old argument name as keyword argument. In this
case, a deprecation warning is thrown and the old argument name is
replaced with the new one.
By decorating `func` with `arg_fix` like this:
```python
@arg_fix(arg_mapping={'old_arg': 'new_arg'})
def func(new_arg, arg=0):
print(new_arg, arg)
```
From now on, any code using`func` with `old_arg` explicitely (`func(old_arg=1)`)
will throw a deprecation warning.
"""
import functools
import warnings
class arg_fix:
"""Decorator ensuring backward compatibility when an argument name is
modified in a function definition.
"""
def __init__(self, arg_mapping):
"""
Args:
arg_mapping (dict): mapping between the function's old argument
names and the new ones.
"""
self.arg_mapping = arg_mapping
self.warning_msg = ("'%s' is a deprecated argument name " +
"for the function '%s', use '%s' instead.")
def __call__(self, f):
@functools.wraps(f)
def fixed_f(*args, **kwargs):
for old_arg, new_arg in self.arg_mapping.items():
if old_arg in kwargs:
# warn that the function interface has changed:
warnings.warn(self.warning_msg %
(old_arg, f.__name__, new_arg), DeprecationWarning)
# Substitute new_arg to old_arg
kwargs[new_arg] = kwargs.pop(old_arg)
# Call the function with the fixed arguments
return f(*args, **kwargs)
return fixed_f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment