Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7359ece

Browse files
committed
Add DecimalConverter in units.py
In axis.py, instead of first checking whether input is number like, direct handle them as a united quantity. Since Decimal is a kind of Number, so DecimalConvert doesn't need to provide extra AxisInfo or default unit.
1 parent cb82df8 commit 7359ece

2 files changed

Lines changed: 50 additions & 25 deletions

File tree

lib/matplotlib/axis.py

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
import logging
77

88
import numpy as np
9-
from numpy import ma
10-
from decimal import Decimal
119

1210
from matplotlib import rcParams
1311
import matplotlib.artist as martist
@@ -1545,27 +1543,6 @@ def have_units(self):
15451543
return self.converter is not None or self.units is not None
15461544

15471545
def convert_units(self, x):
1548-
# If x is already a number
1549-
if munits.ConversionInterface.is_numlike(x):
1550-
if np.iterable(x):
1551-
is_decimal = False
1552-
# use iterator to avoid key error
1553-
for thisx in x:
1554-
is_decimal = isinstance(thisx, Decimal)
1555-
if is_decimal:
1556-
converter = np.asarray
1557-
if isinstance(x, ma.MaskedArray):
1558-
converter = ma.asarray
1559-
return converter(x, dtype=np.float)
1560-
else:
1561-
return x
1562-
# need to convert when x is a Decimal
1563-
elif isinstance(x, Decimal):
1564-
return np.float(x)
1565-
# Otherwise, doesn't need converting
1566-
else:
1567-
return x
1568-
15691546
if self.converter is None:
15701547
self.converter = munits.registry.get_converter(x)
15711548

@@ -1574,8 +1551,16 @@ def convert_units(self, x):
15741551
try:
15751552
ret = self.converter.convert(x, self.units, self)
15761553
except Exception as e:
1577-
raise munits.ConversionError('Failed to convert value(s) to axis '
1578-
f'units: {x!r}') from e
1554+
# If x is already number like, converters other than
1555+
# DecimalConverter may raise error, so check here to walk around.
1556+
if munits.ConversionInterface.is_numlike(x):
1557+
return x
1558+
# Try convert again
1559+
try:
1560+
ret = self.converter.convert(x, self.units, self)
1561+
except Exception as e2:
1562+
raise munits.ConversionError('Failed to convert value(s) to '
1563+
f'axis units: {x!r}') from e2
15791564
return ret
15801565

15811566
def set_units(self, u):

lib/matplotlib/units.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ def default_units(x, axis):
4545
from numbers import Number
4646

4747
import numpy as np
48+
from numpy import ma
49+
from decimal import Decimal
4850

4951
from matplotlib import cbook
5052

@@ -133,6 +135,43 @@ def is_numlike(x):
133135
return isinstance(x, Number)
134136

135137

138+
class DecimalConverter(ConversionInterface):
139+
"""
140+
Converter for decimal.Decimal data to float.
141+
"""
142+
@staticmethod
143+
def convert(value, unit, axis):
144+
"""
145+
Convert Decimals to floats.
146+
147+
The *unit* and *axis* arguments are not used.
148+
149+
Parameters
150+
----------
151+
value : decimal.Decimal or iterable
152+
Decimal or list of Decimal need to be converted
153+
"""
154+
# If value is a Decimal
155+
if isinstance(value, Decimal):
156+
return np.float(value)
157+
# else x is a list of Decimal
158+
else:
159+
converter = np.asarray
160+
if isinstance(value, ma.MaskedArray):
161+
converter = ma.asarray
162+
return converter(value, dtype=np.float)
163+
164+
@staticmethod
165+
def axisinfo(unit, axis):
166+
# Since Decimal is a kind of Number, don't need specific axisinfo.
167+
return AxisInfo()
168+
169+
@staticmethod
170+
def default_units(x, axis):
171+
# Return None since Decimal is a kind of Number.
172+
return None
173+
174+
136175
class Registry(dict):
137176
"""Register types with conversion interface."""
138177

@@ -164,3 +203,4 @@ def get_converter(self, x):
164203

165204

166205
registry = Registry()
206+
registry[Decimal] = DecimalConverter()

0 commit comments

Comments
 (0)