/
util.py
81 lines (66 loc) · 2.34 KB
/
util.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
"""Various utility functions to support physt implementation.
These functions are mostly general Python functions, not specific
for numerical computing, histogramming, etc.
"""
import warnings
from functools import wraps
from typing import Any, Dict, Tuple
def all_subclasses(cls: type) -> Tuple[type, ...]:
"""All subclasses of a class.
From: http://stackoverflow.com/a/17246726/2692780
"""
subclasses = []
for subclass in cls.__subclasses__():
subclasses.append(subclass)
subclasses.extend(all_subclasses(subclass))
return tuple(subclasses)
def find_subclass(base: type, name: str) -> type:
"""Find a named subclass of a base class.
Uses only the class name without namespace.
"""
class_candidates = [klass
for klass in all_subclasses(base)
if klass.__name__ == name
]
if len(class_candidates) == 0:
raise RuntimeError("No \"{0}\" subclass of \"{1}\".".format(base.__name__, name))
elif len(class_candidates) > 1:
raise RuntimeError("Multiple \"{0}\" subclasses of \"{1}\".".format(base.__name__, name))
return class_candidates[0]
def pop_many(a_dict: Dict[str, Any], *args: str, **kwargs) -> Dict[str, Any]:
"""Pop multiple items from a dictionary.
Parameters
----------
a_dict : Dictionary from which the items will popped
args: Keys which will be popped (and not included if not present)
kwargs: Keys + default value pairs (if key not found, this default is included)
Returns
-------
A dictionary of collected items.
"""
result = {}
for arg in args:
if arg in a_dict:
result[arg] = a_dict.pop(arg)
for key, value in kwargs.items():
result[key] = a_dict.pop(key, value)
return result
def deprecation_alias(f, deprecated_name: str):
"""Provide a deprecated copy of a function.
Parameters
----------
f : The correct function
deprecated_name : The name the function will be given
Examples
--------
>>> def new(x): return 1
>>> old = deprecated_name(new, "old")
"""
@wraps(f)
def inner(*args, **kwargs):
warnings.warn(
f"{deprecated_name} is deprecated, use {f.__name__} instead",
DeprecationWarning
)
return f(*args, **kwargs)
return inner