FIX: make EngFormatter respect axes.formatter.use_locale rcParam by christianaurichzm · Pull Request #32281 · matplotlib/matplotlib · GitHub
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions doc/release/next_whats_new/engformatter_locale.rst
39 changes: 39 additions & 0 deletions lib/matplotlib/tests/test_ticker.py
Original file line number Diff line number Diff line change
Expand Up @@ -1810,6 +1810,45 @@ def test_locale_comma():
pytest.skip(skip_msg)


def _impl_engformatter_locale():
try:
locale.setlocale(locale.LC_ALL, 'de_DE.UTF-8')
except locale.Error:
print('SKIP: Locale de_DE.UTF-8 is not supported on this machine')
return
# EngFormatter is a ScalarFormatter subclass, so it must honour the
# axes.formatter.use_locale rcParam like its parent does.
with mpl.rc_context(rc={'axes.formatter.use_locale': True}):
fmt = mticker.EngFormatter(places=2)
assert fmt.get_useLocale()
assert fmt.format_data(0.5551) == '555,10 m'
# An explicit keyword argument overrides the rcParam.
fmt = mticker.EngFormatter(places=2, useLocale=False)
assert not fmt.get_useLocale()
assert fmt.format_data(1234.5) == '1.23 k'
fmt = mticker.EngFormatter(places=2, useLocale=True)
assert fmt.get_useLocale()
assert fmt.format_data(1234.5) == '1,23 k'
# The inherited setter also reaches the engineering formatting path.
fmt = mticker.EngFormatter(places=2, useLocale=False)
fmt.set_useLocale(True)
assert fmt.format_data(1234.5) == '1,23 k'
# Separators are escaped for mathtext, as ScalarFormatter does.
fmt = mticker.EngFormatter(places=2, useLocale=True, useMathText=True)
assert fmt.format_data(0.5551) == '$555{,}10$ m'


def test_engformatter_locale():
proc = mpl.testing.subprocess_run_helper(
_impl_engformatter_locale, timeout=60, extra_env={'MPLBACKEND': 'Agg'})
skip_msg = next((line[len('SKIP:'):].strip()
for line in proc.stdout.splitlines()
if line.startswith('SKIP:')),
'')
if skip_msg:
pytest.skip(skip_msg)


def test_majformatter_type():
fig, ax = plt.subplots()
with pytest.raises(TypeError):
Expand Down
22 changes: 18 additions & 4 deletions lib/matplotlib/ticker.py
Original file line number Diff line number Diff line change
Expand Up @@ -1433,7 +1433,7 @@ class EngFormatter(ScalarFormatter):
}

def __init__(self, unit="", places=None, sep=" ", *, usetex=None,
useMathText=None, useOffset=False):
useMathText=None, useOffset=False, useLocale=None):
r"""
Parameters
----------
Expand Down Expand Up @@ -1476,14 +1476,20 @@ def __init__(self, unit="", places=None, sep=" ", *, usetex=None,
3 digits. See also `.set_useOffset`.

.. versionadded:: 3.10

useLocale : bool, default: :rc:`axes.formatter.use_locale`.
Whether to use locale settings for decimal sign and positive sign.
See `.set_useLocale`.

.. versionadded:: 3.12
"""
self.unit = unit
self.places = places
self.sep = sep
super().__init__(
useOffset=useOffset,
useMathText=useMathText,
useLocale=False,
useLocale=useLocale,
usetex=usetex,
)

Expand Down Expand Up @@ -1598,10 +1604,18 @@ def format_data(self, value):
suffix = f"{self.sep}{unit_prefix}{self.unit}"
else:
suffix = ""
if self._useLocale:
mant_str = locale.format_string(f"%{fmt}", (mant,), True)
if self._useMathText:
# Escape the separators introduced by locale.format_string, so
# that mathtext does not apply punctuation spacing to them.
mant_str = mant_str.replace(",", "{,}")
else:
mant_str = f"{mant:{fmt}}"
if self._usetex or self._useMathText:
return f"${mant:{fmt}}${suffix}"
return f"${mant_str}${suffix}"
else:
return f"{mant:{fmt}}{suffix}"
return f"{mant_str}{suffix}"


class PercentFormatter(Formatter):
Expand Down
1 change: 1 addition & 0 deletions lib/matplotlib/ticker.pyi
Loading