Refactor autoshapes to use shape.label for vline/hline/vrect/hrect
This PR is a first step toward refactoring the autoshape helpers to use the new layout.shape.label API in Plotly.js, while keeping backward-compatible annotation behavior for now.
Scope
This PR updates:
Figure.add_vlineFigure.add_hlineFigure.add_vrectFigure.add_hrect
Key changes:
-
Legacy → label shim
- Introduce
_coerce_shape_label_from_legacy_annotation_kwargs(kwargs)to translate a safe subset ofannotation_*kwargs into alabeldict:annotation_text→label.textannotation_font→label.fontannotation_textangle→label.textangle
- The shim is called from each of the four helpers and is non-destructive: it does not remove
annotation_*from kwargs. - When any
annotation_*field is used, aFutureWarningis emitted to encourage migrating tolabel={...}.
- Introduce
-
Add shape.label for autoshapes
In
_process_multiple_axis_spanning_shapes, forshape_typein:"vline""hline""vrect""hrect"
we now:
- Split kwargs into
shape_kwargsandlegacy_annviashapeannotation.split_dict_by_key_prefix(..., "annotation_"). - Build a
label_dictstarting from any explicitlabelpassed by the user and then merging in legacy fields if they are not present. - Attach
label_dictto the new shape (shape_to_add["label"] = label_dict) before callingadd_shape(...).
-
Mapping annotation_position → label.textposition
We partially map
annotation_positionintolabel.textpositionto keep intuitive placement:-
For lines:
vline:"top"→"end""bottom"→"start""middle"/"center"→"middle"
hline:"right"→"end""left"→"start""middle"/"center"→"middle"
- A helper
_normalize_legacy_line_position_to_textpositionis used to validate legacy strings and to keep behavior predictable.
-
For rectangles (
vrect,hrect):- We strip
"inside "/"outside "and map the remaining part to a valid rect textposition:"top left","top center","top right", …"middle left","middle center","middle right", …"bottom left","bottom center","bottom right", …
- Single-side positions like
"top","bottom","left","right"are mapped to sensible defaults (e.g."top"→"top center").
- We strip
-
-
Warnings for unsupported styling
annotation_bgcolor/annotation_bordercolorare not supported onshape.labeland are currently ignored with aFutureWarningsuggesting use of label font/color or a background shape instead.
-
Backward compatibility (important)
- The existing annotation path is still active:
axis_spanning_shape_annotation(...)is still called.add_annotation(...)is still called whenaugmented_annotationis notNone.
- This means that:
- existing user code that relies on
layout.annotationscontinues to work, - existing tests that assert on annotations continue to pass,
- but shapes now also carry a
label, which will allow us to stop creating separate annotations in a later step.
- existing user code that relies on
- The existing annotation path is still active:
Bug / motivation
This work is motivated by the issue where using add_vline with annotation_text on a datetime x-axis can raise a TypeError due to arithmetic on mixed types when positioning the annotation (see the discussion in #3065).
By moving toward shape.label:
- we can avoid doing arithmetic on the coordinate values just to place the label, and
- we get a more direct and robust representation of labels attached to shapes.
For now, we keep the annotation logic in place to avoid breaking existing behavior while we gather feedback.
Tests
Locally, I ran:
python -m pytest -q tests/test_optional/test_autoshapes/test_annotated_shapes.py
## Code PR
- [ x] I have read through the [contributing notes](https://github.com/plotly/plotly.py/blob/main/CONTRIBUTING.md) and understand the structure of the package. In particular, if my PR modifies code of `plotly.graph_objects`, my modifications concern the code generator and *not* the generated files.
- [ ] I have added tests or modified existing tests.
- [ ] For a new feature, I have added documentation examples (please see the doc checklist as well).
- [ ] I have added a CHANGELOG entry if changing anything substantial.
- [ ] For a new feature or a change in behavior, I have updated the relevant docstrings in the code.
Wow, fantastic PR! This is an exciting refactor and would be a great add to Plotly.py. Let us know when you need help reviewing.