Skip to content

Commit 81af9ee

Browse files
committed
Make FuncFormatter work with non-fixed locator
The previous fix to make FuncFormatter work, in https://github.com/mpld3/mplexporter/pull/67/files and mpld3/mpld3@e7fa282 had two issues still: 1) the mpl FuncFormatter API also takes the index as second argument, which was missing. 2) it exported `tickvalues` only in the FixedLocator case, so these were missing for non-fixed FuncFormatter and hence the FuncFormatter codepath, which also requires them to be present, was never hit with non-fixed locators. Also add a test, and let tests import `matplotlib` via the backend-setting mechanism, not only `plt`. This fixes both. Again, this was figured out and helped with gpt-codex and my careful review+cleanup. Codex even identified the two original commits I'm linking above :)
1 parent 2c2104a commit 81af9ee

3 files changed

Lines changed: 26 additions & 9 deletions

File tree

mplexporter/tests/__init__.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
import os
22

3-
MPLBE = os.environ.get('MPLBE', 'Agg')
4-
5-
if MPLBE:
6-
import matplotlib
3+
import matplotlib
4+
if MPLBE := os.environ.get('MPLBE', 'Agg'):
75
matplotlib.use(MPLBE)
8-
96
import matplotlib.pyplot as plt

mplexporter/tests/test_utils.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
from numpy.testing import assert_allclose, assert_equal
2-
from . import plt
1+
from numpy.testing import assert_, assert_allclose, assert_equal
2+
from . import plt, matplotlib
33
from .. import utils
44

55

@@ -33,3 +33,23 @@ def test_axis_w_fixed_formatter():
3333
# NOTE: Issue #471
3434
# assert_equal(props['tickformat'], labels)
3535

36+
37+
def test_funcformatter_exports_major_ticklabels():
38+
# Test both log and normal cases:
39+
for scale, x, y in [
40+
("linear", [0, 1], [0, 1]),
41+
("log", [1, 10, 100], [0, 1, 2]),
42+
]:
43+
fig, ax = plt.subplots()
44+
ax.set_xscale(scale)
45+
ax.plot([1, 10, 100], [0, 1, 2])
46+
ax.xaxis.set_major_formatter(matplotlib.ticker.FuncFormatter(lambda x, pos: f"t{pos}"))
47+
48+
props = utils.get_axis_properties(ax.xaxis)
49+
plt.close(fig)
50+
51+
assert_equal(props["scale"], scale)
52+
assert_equal(props["tickformat_formatter"], "func")
53+
assert_(props["tickvalues"] is not None)
54+
assert_equal(len(props["tickvalues"]), len(props["tickformat"]))
55+
assert_equal(props["tickformat"][:3], ["t0", "t1", "t2"])

mplexporter/utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ def _tick_format_props(formatter, tickvalues, labels):
203203
if isinstance(formatter, ticker.FixedFormatter):
204204
return list(formatter.seq), "fixed"
205205
if isinstance(formatter, ticker.FuncFormatter) and tickvalues:
206-
return [formatter(value) for value in tickvalues], "func"
206+
return [formatter(value, i) for i, value in enumerate(tickvalues)], "func"
207207
if not any(label.get_visible() for label in labels):
208208
return "", ""
209209
return None, ""
@@ -230,7 +230,7 @@ def get_axis_properties(axis):
230230
# Use tick values if appropriate
231231
locator = axis.get_major_locator()
232232
props['nticks'] = len(locator())
233-
if isinstance(locator, ticker.FixedLocator):
233+
if isinstance(locator, ticker.FixedLocator) or isinstance(axis.get_major_formatter(), ticker.FuncFormatter):
234234
props['tickvalues'] = list(locator())
235235
else:
236236
props['tickvalues'] = None

0 commit comments

Comments
 (0)