wrapping_function()   B
last analyzed

Complexity

Conditions 7

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 7
c 3
b 0
f 0
dl 0
loc 18
rs 7.3333
1
"""
2
The bearlib is an optional library designed to ease the task of any Bear. Just
3
as the rest of coala the bearlib is designed to be as easy to use as possible
4
while offering the best possible flexibility.
5
"""
6
7
from coalib.settings.FunctionMetadata import FunctionMetadata
8
9
10
def deprecate_settings(**depr_args):
11
    """
12
     The purpose of this decorator is to allow passing old settings names to
13
     bears due to the heavy changes in their names.
14
15
     >>> @deprecate_settings(new='old')
16
     ... def run(new):
17
     ...     print(new)
18
19
     Now we can simply call the bear with the deprecated setting, we'll get a
20
     warning - but it still works!
21
22
     >>> run(old="Hello world!")
23
     The setting `old` is deprecated. Please use `new` instead.
24
     Hello world!
25
     >>> run(new="Hello world!")
26
     Hello world!
27
28
     This example represents the case where the old setting name needs to be
29
     modified to match the new one.
30
31
     >>> @deprecate_settings(new=('old', lambda a: a + 'coala!'))
32
     ... def func(new):
33
     ...     print(new)
34
35
     >>> func(old="Welcome to ")
36
     The setting `old` is deprecated. Please use `new` instead.
37
     Welcome to coala!
38
     >>> func(new='coala!')
39
     coala!
40
41
     This example represents the case where the old and new settings are
42
     provided to the function.
43
44
     >>> @deprecate_settings(new='old')
45
     ... def run(new):
46
     ...     print(new)
47
     >>> run(old="Hello!", new='coala is always written with lowercase `c`.')
48
     The setting `old` is deprecated. Please use `new` instead.
49
     The value of `old` and `new` are conflicting. `new` will be used instead.
50
     coala is always written with lowercase `c`.
51
     >>> run(old='Hello!', new='Hello!')
52
     The setting `old` is deprecated. Please use `new` instead.
53
     Hello!
54
55
     The metadata for coala has been adjusted as well:
56
57
     >>> list(run.__metadata__.non_optional_params.keys())
58
     ['new']
59
     >>> list(run.__metadata__.optional_params.keys())
60
     ['old']
61
62
     You cannot deprecate an already deprecated setting. Don't try. It will
63
     introduce nondeterministic errors to your program.
64
65
     :param depr_args: A dictionary of settings as keys and their deprecated
66
                       names as values.
67
    """
68
    def _deprecate_decorator(func):
69
70
        def wrapping_function(*args, **kwargs):
71
            for arg, depr_arg_and_modifier in depr_args.items():
72
                deprecated_arg, _func = (
73
                    depr_arg_and_modifier
74
                    if isinstance(depr_arg_and_modifier, tuple)
75
                    else (depr_arg_and_modifier, lambda x: x))
76
                if deprecated_arg in kwargs:
77
                    print("The setting `{}` is deprecated. Please use `{}` "
78
                          "instead.".format(deprecated_arg, arg))
79
                    depr_arg_value = _func.__call__(kwargs[deprecated_arg])
80
                    if arg in kwargs and depr_arg_value != kwargs[arg]:
81
                        print('The value of `{}` and `{}` are conflicting.'
82
                              ' `{}` will be used instead.'.format(
83
                                  deprecated_arg, arg, arg))
84
                    else:
85
                        kwargs[arg] = depr_arg_value
86
                    del kwargs[deprecated_arg]
87
            return func(*args, **kwargs)
88
89
        new_metadata = FunctionMetadata.from_function(func)
90
        for arg, depr_arg_and_modifier in depr_args.items():
91
            deprecated_arg = (depr_arg_and_modifier[0]
92
                              if isinstance(depr_arg_and_modifier, tuple)
93
                              else depr_arg_and_modifier)
94
            new_metadata.add_alias(arg, deprecated_arg)
95
        wrapping_function.__metadata__ = new_metadata
96
97
        return wrapping_function
98
99
    return _deprecate_decorator
100