|
1 | | -import os |
2 | | -import wrapt |
3 | | -import inspect |
4 | | - |
5 | | - |
6 | | -def deep_getattr(obj, attr_string, default=None): |
7 | | - """ |
8 | | - Returns the attribute of `obj` at the dotted path given by `attr_string` |
9 | | - If no such attribute is reachable, returns `default` |
10 | | -
|
11 | | - >>> deep_getattr(cass, "cluster") |
12 | | - <cassandra.cluster.Cluster object at 0xa20c350 |
13 | | -
|
14 | | - >>> deep_getattr(cass, "cluster.metadata.partitioner") |
15 | | - u'org.apache.cassandra.dht.Murmur3Partitioner' |
16 | | -
|
17 | | - >>> deep_getattr(cass, "i.dont.exist", default="default") |
18 | | - 'default' |
19 | | - """ |
20 | | - attrs = attr_string.split('.') |
21 | | - for attr in attrs: |
22 | | - try: |
23 | | - obj = getattr(obj, attr) |
24 | | - except AttributeError: |
25 | | - return default |
26 | | - |
27 | | - return obj |
28 | | - |
29 | | - |
30 | | -def safe_patch(patchable, key, patch_func, service, meta, tracer): |
31 | | - """ takes patch_func (signature: takes the orig_method that is |
32 | | - wrapped in the monkey patch == UNBOUND + service and meta) and |
33 | | - attach the patched result to patchable at patchable.key |
34 | | -
|
35 | | -
|
36 | | - - if this is the module/class we can rely on methods being unbound, and just have to |
37 | | - update the __dict__ |
38 | | -
|
39 | | - - if this is an instance, we have to unbind the current and rebind our |
40 | | - patched method |
41 | | -
|
42 | | - - If patchable is an instance and if we've already patched at the module/class level |
43 | | - then patchable[key] contains an already patched command! |
44 | | - To workaround this, check if patchable or patchable.__class__ are _dogtraced |
45 | | - If is isn't, nothing to worry about, patch the key as usual |
46 | | - But if it is, search for a "__dd_orig_{key}" method on the class, which is |
47 | | - the original unpatched method we wish to trace. |
48 | | -
|
49 | | - """ |
50 | | - def _get_original_method(thing, key): |
51 | | - orig = None |
52 | | - if hasattr(thing, '_dogtraced'): |
53 | | - # Search for original method |
54 | | - orig = getattr(thing, "__dd_orig_{}".format(key), None) |
55 | | - else: |
56 | | - orig = getattr(thing, key) |
57 | | - # Set it for the next time we attempt to patch `thing` |
58 | | - setattr(thing, "__dd_orig_{}".format(key), orig) |
59 | | - |
60 | | - return orig |
61 | | - |
62 | | - if inspect.isclass(patchable) or inspect.ismodule(patchable): |
63 | | - orig = _get_original_method(patchable, key) |
64 | | - if not orig: |
65 | | - # Should never happen |
66 | | - return |
67 | | - elif hasattr(patchable, '__class__'): |
68 | | - orig = _get_original_method(patchable.__class__, key) |
69 | | - if not orig: |
70 | | - # Should never happen |
71 | | - return |
72 | | - else: |
73 | | - return |
74 | | - |
75 | | - dest = patch_func(orig, service, meta, tracer) |
76 | | - |
77 | | - if inspect.isclass(patchable) or inspect.ismodule(patchable): |
78 | | - setattr(patchable, key, dest) |
79 | | - elif hasattr(patchable, '__class__'): |
80 | | - setattr(patchable, key, dest.__get__(patchable, patchable.__class__)) |
81 | | - |
82 | | - |
83 | | -def asbool(value): |
84 | | - """Convert the given String to a boolean object. Accepted |
85 | | - values are `True` and `1`.""" |
86 | | - if value is None: |
87 | | - return False |
88 | | - |
89 | | - if isinstance(value, bool): |
90 | | - return value |
91 | | - |
92 | | - return value.lower() in ("true", "1") |
93 | | - |
94 | | - |
95 | | -def get_env(integration, variable, default=None): |
96 | | - """Retrieves environment variables value for the given integration. It must be used |
97 | | - for consistency between integrations. The implementation is backward compatible |
98 | | - with legacy nomenclature: |
99 | | - * `DATADOG_` is a legacy prefix with lower priority |
100 | | - * `DD_` environment variables have the highest priority |
101 | | - * the environment variable is built concatenating `integration` and `variable` |
102 | | - arguments |
103 | | - * return `default` otherwise |
104 | | - """ |
105 | | - key = '{}_{}'.format(integration, variable).upper() |
106 | | - legacy_env = 'DATADOG_{}'.format(key) |
107 | | - env = 'DD_{}'.format(key) |
108 | | - |
109 | | - # [Backward compatibility]: `DATADOG_` variables should be supported; |
110 | | - # add a deprecation warning later if it's used, so that we can drop the key |
111 | | - # in newer releases. |
112 | | - value = os.getenv(env) or os.getenv(legacy_env) |
113 | | - return value if value else default |
114 | | - |
115 | | - |
116 | | -def unwrap(obj, attr): |
117 | | - f = getattr(obj, attr, None) |
118 | | - if f and isinstance(f, wrapt.ObjectProxy) and hasattr(f, '__wrapped__'): |
119 | | - setattr(obj, attr, f.__wrapped__) |
| 1 | +# [Backward compatibility]: keep importing modules functions |
| 2 | +from .utils.deprecation import deprecated |
| 3 | +from .utils.formats import asbool, deep_getattr, get_env |
| 4 | +from .utils.wrappers import safe_patch, unwrap |
| 5 | + |
| 6 | + |
| 7 | +__all__ = [ |
| 8 | + 'deprecated', |
| 9 | + 'asbool', |
| 10 | + 'deep_getattr', |
| 11 | + 'get_env', |
| 12 | + 'safe_patch', |
| 13 | + 'unwrap', |
| 14 | +] |
0 commit comments