-
Notifications
You must be signed in to change notification settings - Fork 18
/
utils.py
141 lines (117 loc) · 4.18 KB
/
utils.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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
"""Module containing some utility methods"""
import warnings
import functools
from .ansi import ANSIMultiByteString
from .compat import to_unicode
def to_numeric(item):
"""
Helper method to convert a string to float or int if possible.
If the conversion is not possible, it simply returns the string.
"""
num_types = (int, float)
# We don't wan't to perform any conversions if item is already a number
if isinstance(item, num_types):
return item
# First try for an int conversion so that strings like "5" are converted
# to 5 instead of 5.0 . This is safe as a direct int cast for a non integer
# string raises a ValueError.
try:
num = int(to_unicode(item))
except ValueError:
try:
num = float(to_unicode(item))
except ValueError:
return item
else:
return num
except TypeError:
return item
else:
return num
def ensure_type(value, *types, varname="value"):
if not isinstance(value, types):
expected_types_str = "/".join([t.__name__ for t in types])
raise TypeError(
("Expected '{}' to be of type '{}', " "got '{}'").format(
varname, expected_types_str, type(value).__name__
)
)
return value
def pre_process(item, detect_numerics, precision, sign_value):
"""Returns the final string which should be displayed"""
if item is None:
return ""
if detect_numerics:
item = to_numeric(item)
if isinstance(item, float):
item = round(item, precision)
try:
item = "{:{sign}}".format(item, sign=sign_value)
except (ValueError, TypeError):
pass
return to_unicode(item)
def termwidth(item):
"""Returns the visible width of the string as shown on the terminal"""
obj = ANSIMultiByteString(to_unicode(item))
return obj.termwidth()
def textwrap(item, width):
obj = ANSIMultiByteString(to_unicode(item))
return obj.wrap(width)
def deprecation_message(
old_name, deprecated_in, removed_in, extra_msg
): # pragma: no cover
return (
"'{}' has been deprecated in 'v{}' and will be removed in 'v{}'. "
"{}".format(old_name, deprecated_in, removed_in, extra_msg)
)
def deprecated(
deprecated_in, removed_in, replacement=None, details=None,
): # pragma: no cover
def decorator(f):
@functools.wraps(f)
def wrapper(*args, **kwds):
nonlocal details
if not details:
if replacement:
details = replacement.__qualname__
details = details.replace(
"BTColumns", "BeautifulTable.columns",
)
details = details.replace("BTRows", "BeautifulTable.rows",)
details = details.replace(
"BTColumnHeader", "BeautifulTable.columns.header",
)
details = details.replace(
"BTRowHeader", "BeautifulTable.rows.header",
)
details = "Use '{}' instead.".format(details)
else:
details = ""
message = deprecation_message(
f.__qualname__, deprecated_in, removed_in, details,
)
if replacement:
f.__doc__ = "{}\n\n{}".format(replacement.__doc__, message)
warnings.warn(message, FutureWarning)
return f(*args, **kwds)
return wrapper
return decorator
def deprecated_param(
deprecated_in, removed_in, old_name, new_name=None, details=None,
): # pragma: no cover
def decorator(f):
@functools.wraps(f)
def wrapper(*args, **kwargs):
nonlocal details
if not details:
details = (
"Use '{}' instead.".format(new_name) if new_name else ""
)
message = deprecation_message(
old_name, deprecated_in, removed_in, details,
)
if old_name in kwargs:
warnings.warn(message, FutureWarning)
return f(*args, **kwargs)
return wrapper
return decorator