Skip to content

Commit 82f2d3f

Browse files
committed
fix(guides): don't evaluate positional after_scale modifiers for legends
Legend key data can only contain the matched legend aesthetics and the geom's default aesthetics. Staged positional aesthetics (e.g. x, y) never appear in it, so evaluating their after_scale expressions against the key data raised a PlotnineError, triggered a spurious "this should not happen" warning, and discarded all legitimate legend modifiers via the fallback path. Filter the modifiers to aesthetics that can be in the key data before evaluation. closes #1067
1 parent fc84802 commit 82f2d3f

2 files changed

Lines changed: 17 additions & 3 deletions

File tree

plotnine/guides/guide_legend.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,11 @@ def create_geoms(self):
184184
# Modify aesthetics
185185

186186
# When doing after_scale evaluations, we only consider those
187-
# for the aesthetics that are valid for this layer/geom.
187+
# for aesthetics that can be in the legend key data.
188+
legend_aes = l.geom.DEFAULT_AES.keys() | matched_set
188189
aes_modifiers = {
189190
ae: l.mapping._scaled[ae]
190-
for ae in l.geom.aesthetics() & l.mapping._scaled.keys()
191+
for ae in legend_aes & l.mapping._scaled.keys()
191192
}
192193

193194
try:

tests/test_guide_internals.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88
geom_bar,
99
geom_point,
1010
ggplot,
11+
stage,
1112
)
12-
from plotnine.data import mtcars
13+
from plotnine.data import mpg, mtcars
1314

1415

1516
def test_no_after_scale_warning():
@@ -20,6 +21,18 @@ def test_no_after_scale_warning():
2021
p.draw_test() # type: ignore
2122

2223

24+
def test_after_scale_positional_aesthetic_with_legend():
25+
# A staged positional aesthetic cannot appear in the legend key
26+
# data, so building the legend must not attempt to evaluate it
27+
p = ggplot(mpg, aes("drv", "displ", color="drv")) + geom_point(
28+
aes(x=stage("drv", after_scale="x"))
29+
)
30+
31+
with warnings.catch_warnings():
32+
warnings.simplefilter("error")
33+
p.draw_test() # pyright: ignore[reportAttributeAccessIssue]
34+
35+
2336
def test_guide_legend_after_scale():
2437
def alphen(series, a):
2538
ha = f"{round(a * 255):#04X}"[2:]

0 commit comments

Comments
 (0)