_ModuleProxy()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
c 1
b 0
f 1
dl 0
loc 15
rs 9.4285
1
# -*- coding: utf-8 -*-
2
from __future__ import absolute_import, division, print_function
3
4
from inspect import isbuiltin
5
from logging import getLogger
6
import sys
7
import warnings
8
9
log = getLogger(__name__)
10
11
12
def deprecated(func):
13
    """This is a decorator which can be used to mark functions
14
    as deprecated. It will result in a warning being emmitted
15
    when the function is used."""
16
    if callable(func):
17
        def new_func(*args, **kwargs):
18
            warnings.simplefilter('always', DeprecationWarning)  # turn off filter
19
            warnings.warn("Call to deprecated {0}.".format(func.__name__),
20
                          category=DeprecationWarning,
21
                          stacklevel=2)
22
            warnings.simplefilter('default', DeprecationWarning)  # reset filter
23
            return func(*args, **kwargs)
24
        new_func.__name__ = func.__name__
25
        new_func.__doc__ = func.__doc__
26
        new_func.__dict__.update(func.__dict__)
27
    else:
28
        raise NotImplementedError()
29
    return new_func
30
31
32
def deprecated_import(module_name):
33
    warnings.simplefilter('always', ImportWarning)  # turn off filter
34
    warnings.warn("Import of deprecated module {0}.".format(module_name),
35
                  category=ImportWarning)
36
    warnings.simplefilter('default', ImportWarning)  # reset filter
37
38
39
def import_and_wrap_deprecated(module_name, module_dict, warn_import=True):
40
    """
41
    Usage:
42
        import_and_wrap_deprecated('conda.common.connection', locals())
43
        # looks for conda.common.connection.__all__
44
    """
45
    if warn_import:
46
        deprecated_import(module_name)
47
48
    from importlib import import_module
49
    module = import_module(module_name)
50
    for attr in module.__all__:
51
        module_dict[attr] = deprecated(getattr(module, attr))
52
53
54
def deprecate_module_with_proxy(module_name, module_dict, deprecated_attributes=None):
55
    """
56
    Usage:
57
        deprecate_module_with_proxy(__name__, locals())  # at bottom of module
58
    """
59
    def _ModuleProxy(module, depr):
60
        """Return a wrapped object that warns about deprecated accesses"""
61
        # http://stackoverflow.com/a/922693/2127762
62
        class Wrapper(object):
63
            def __getattr__(self, attr):
64
                if depr is None or attr in depr:
65
                    warnings.warn("Property %s is deprecated" % attr)
66
67
                return getattr(module, attr)
68
69
            def __setattr__(self, attr, value):
70
                if depr is None or attr in depr:
71
                    warnings.warn("Property %s is deprecated" % attr)
72
                return setattr(module, attr, value)
73
        return Wrapper()
74
75
    deprecated_import(module_name)
76
77
    deprs = set()
78
    for key in deprecated_attributes or module_dict:
79
        if key.startswith('_'):
80
            continue
81
        if callable(module_dict[key]) and not isbuiltin(module_dict[key]):
82
            module_dict[key] = deprecated(module_dict[key])
83
        else:
84
            deprs.add(key)
85
    sys.modules[module_name] = _ModuleProxy(sys.modules[module_name], deprs or None)
86