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

Skip to content

Commit 3694152

Browse files
FIX: make EngFormatter respect axes.formatter.use_locale rcParam
EngFormatter subclasses ScalarFormatter, but the inherited locale machinery is reachable only in the offset path. The normal engineering formatting path both forces the flag off at construction, by passing useLocale=False to super().__init__, and bypasses locale-aware formatting, by interpolating the mantissa directly. The rcParam therefore had no effect, and set_useLocale flipped a flag that format_data never consulted. Pass useLocale through to ScalarFormatter and add the matching keyword argument, so that the rcParam applies and an explicit value overrides it. When locale formatting is on, the mantissa goes through locale.format_string, and the separators it introduces are escaped for mathtext the same way ScalarFormatter already escapes them.
1 parent 374b2da commit 3694152

4 files changed

Lines changed: 75 additions & 4 deletions

File tree

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
``EngFormatter`` now respects ``axes.formatter.use_locale``
2+
-----------------------------------------------------------
3+
4+
`~matplotlib.ticker.EngFormatter` now formats the decimal separator according to
5+
the current locale, like `~matplotlib.ticker.ScalarFormatter` already did. This
6+
is controlled by the :rc:`axes.formatter.use_locale` rcParam, or by the new
7+
*useLocale* keyword argument:
8+
9+
.. code-block:: python
10+
11+
import locale
12+
from matplotlib.ticker import EngFormatter
13+
14+
locale.setlocale(locale.LC_ALL, "de_DE.UTF-8")
15+
16+
ax.yaxis.set_major_formatter(EngFormatter(places=2, useLocale=True))
17+
# tick labels now read "555,10 m" instead of "555.10 m"

lib/matplotlib/tests/test_ticker.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1810,6 +1810,45 @@ def test_locale_comma():
18101810
pytest.skip(skip_msg)
18111811

18121812

1813+
def _impl_engformatter_locale():
1814+
try:
1815+
locale.setlocale(locale.LC_ALL, 'de_DE.UTF-8')
1816+
except locale.Error:
1817+
print('SKIP: Locale de_DE.UTF-8 is not supported on this machine')
1818+
return
1819+
# EngFormatter is a ScalarFormatter subclass, so it must honour the
1820+
# axes.formatter.use_locale rcParam like its parent does.
1821+
with mpl.rc_context(rc={'axes.formatter.use_locale': True}):
1822+
fmt = mticker.EngFormatter(places=2)
1823+
assert fmt.get_useLocale()
1824+
assert fmt.format_data(0.5551) == '555,10 m'
1825+
# An explicit keyword argument overrides the rcParam.
1826+
fmt = mticker.EngFormatter(places=2, useLocale=False)
1827+
assert not fmt.get_useLocale()
1828+
assert fmt.format_data(1234.5) == '1.23 k'
1829+
fmt = mticker.EngFormatter(places=2, useLocale=True)
1830+
assert fmt.get_useLocale()
1831+
assert fmt.format_data(1234.5) == '1,23 k'
1832+
# The inherited setter also reaches the engineering formatting path.
1833+
fmt = mticker.EngFormatter(places=2, useLocale=False)
1834+
fmt.set_useLocale(True)
1835+
assert fmt.format_data(1234.5) == '1,23 k'
1836+
# Separators are escaped for mathtext, as ScalarFormatter does.
1837+
fmt = mticker.EngFormatter(places=2, useLocale=True, useMathText=True)
1838+
assert fmt.format_data(0.5551) == '$555{,}10$ m'
1839+
1840+
1841+
def test_engformatter_locale():
1842+
proc = mpl.testing.subprocess_run_helper(
1843+
_impl_engformatter_locale, timeout=60, extra_env={'MPLBACKEND': 'Agg'})
1844+
skip_msg = next((line[len('SKIP:'):].strip()
1845+
for line in proc.stdout.splitlines()
1846+
if line.startswith('SKIP:')),
1847+
'')
1848+
if skip_msg:
1849+
pytest.skip(skip_msg)
1850+
1851+
18131852
def test_majformatter_type():
18141853
fig, ax = plt.subplots()
18151854
with pytest.raises(TypeError):

lib/matplotlib/ticker.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1433,7 +1433,7 @@ class EngFormatter(ScalarFormatter):
14331433
}
14341434

14351435
def __init__(self, unit="", places=None, sep=" ", *, usetex=None,
1436-
useMathText=None, useOffset=False):
1436+
useMathText=None, useOffset=False, useLocale=None):
14371437
r"""
14381438
Parameters
14391439
----------
@@ -1476,14 +1476,20 @@ def __init__(self, unit="", places=None, sep=" ", *, usetex=None,
14761476
3 digits. See also `.set_useOffset`.
14771477
14781478
.. versionadded:: 3.10
1479+
1480+
useLocale : bool, default: :rc:`axes.formatter.use_locale`.
1481+
Whether to use locale settings for decimal sign and positive sign.
1482+
See `.set_useLocale`.
1483+
1484+
.. versionadded:: 3.12
14791485
"""
14801486
self.unit = unit
14811487
self.places = places
14821488
self.sep = sep
14831489
super().__init__(
14841490
useOffset=useOffset,
14851491
useMathText=useMathText,
1486-
useLocale=False,
1492+
useLocale=useLocale,
14871493
usetex=usetex,
14881494
)
14891495

@@ -1598,10 +1604,18 @@ def format_data(self, value):
15981604
suffix = f"{self.sep}{unit_prefix}{self.unit}"
15991605
else:
16001606
suffix = ""
1607+
if self._useLocale:
1608+
mant_str = locale.format_string(f"%{fmt}", (mant,), True)
1609+
if self._useMathText:
1610+
# Escape the separators introduced by locale.format_string, so
1611+
# that mathtext does not apply punctuation spacing to them.
1612+
mant_str = mant_str.replace(",", "{,}")
1613+
else:
1614+
mant_str = f"{mant:{fmt}}"
16011615
if self._usetex or self._useMathText:
1602-
return f"${mant:{fmt}}${suffix}"
1616+
return f"${mant_str}${suffix}"
16031617
else:
1604-
return f"{mant:{fmt}}{suffix}"
1618+
return f"{mant_str}{suffix}"
16051619

16061620

16071621
class PercentFormatter(Formatter):

lib/matplotlib/ticker.pyi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ class EngFormatter(ScalarFormatter):
150150
usetex: bool | None = ...,
151151
useMathText: bool | None = ...,
152152
useOffset: bool | float | None = ...,
153+
useLocale: bool | None = ...,
153154
) -> None: ...
154155
def format_eng(self, num: float) -> str: ...
155156

0 commit comments

Comments
 (0)