Skip to content

Refactor autoshapes to use shape.label for vline/hline/vrect/hrect#5444

Open
nochinxx wants to merge 13 commits intoplotly:mainfrom
lilyMaung:refactor/autoshapes-use-shape-label
Open

Refactor autoshapes to use shape.label for vline/hline/vrect/hrect#5444
nochinxx wants to merge 13 commits intoplotly:mainfrom
lilyMaung:refactor/autoshapes-use-shape-label

Conversation

@nochinxx
Copy link
Copy Markdown

@nochinxx nochinxx commented Dec 6, 2025

Link to issue

(#5373)

Closes #(5373)

Description of change

This PR begins migrating the autoshape helpers (add_vline, add_hline,
add_vrect, add_hrect) to use the native layout.shape.label API
introduced in Plotly.js, while keeping full backward compatibility with the
existing annotation_* kwargs.

Demo

New API — label= parameter

import plotly.graph_objects as go

Vertical line with a label at the top

fig = go.Figure(go.Scatter(x=[1, 2, 3, 4, 5], y=[2, 1, 4, 3, 5]))
fig.add_vline(x=3, label=dict(text="Target", textposition="end"), line_dash="dash")
fig.show()
demo_vline_label

Horizontal line with a label on the right

fig = go.Figure(go.Scatter(x=[1, 2, 3, 4, 5], y=[2, 1, 4, 3, 5]))
fig.add_hline(y=3, label=dict(text="Threshold", textposition="end"), line_color="red")
fig.show()
demo_hline_label

Vertical rect with a label inside

fig = go.Figure(go.Scatter(x=[1, 2, 3, 4, 5], y=[2, 1, 4, 3, 5]))
fig.add_vrect(x0=2, x1=4,
    label=dict(text="Region A", textposition="top center"),
    fillcolor="green", opacity=0.15, line_width=0)
fig.show()
demo_vrect_label

Horizontal rect with a label

fig = go.Figure(go.Scatter(x=[1, 2, 3, 4, 5], y=[2, 1, 4, 3, 5]))
fig.add_hrect(y0=2, y1=4,
    label=dict(text="Normal range", textposition="top left"),
    fillcolor="blue", opacity=0.15, line_width=0)
fig.show()
demo_hrect_label

Legacy API — annotation_text= still works (backward compat)

fig = go.Figure(go.Scatter(x=[1, 2, 3, 4, 5], y=[2, 1, 4, 3, 5]))
fig.add_vline(x=3, annotation_text="Legacy label", line_dash="dot")
fig.show()  # Works as before; also emits FutureWarning
demo_vline_legacy

Testing strategy

Ran existing autoshapes test suite to verify no regressions:

python -m pytest -q tests/test_optional/test_autoshapes/test_annotated_shapes.py

Added three new test cases:
test_legacy_annotation_text_also_sets_shape_label— verifies annotation_text= is mirrored to shape.label.text while also producing a layout.annotations entry (backward compat).
test_explicit_label_takes_precedence_over_legacy_annotation_text — verifies that an explicit label=dict(text=...) wins over annotation_text= on the shape label (annotation still gets the legacy value).
(Existing tests that assert on layout.annotations all continue to pass because the annotation path is still active.)

Additional information (optional)

What changed:

  • A new label= parameter is now respected on all four autoshape helpers,
    forwarding a shape.label dict directly to the underlying shape.
  • Legacy annotation_* kwargs are translated to shape.label fields on a
    best-effort basis (text, font, textangle) so existing code benefits without
    any changes.
  • annotation_position is mapped to label.textposition where the mapping
    is unambiguous (e.g. "top""end" for vlines, "left""start"
    for hlines, "top left""top left" for rects).
  • A FutureWarning is emitted when annotation_* kwargs are used,
    encouraging migration to label={...}.
  • The existing annotation path is preserved: layout.annotations entries
    are still created, so all current tests and user code continue to work.

Why this matters:

Using the native shape.label avoids the coordinate arithmetic that
add_vline previously did to place its annotation. That arithmetic broke on
datetime x-axes (see #3065) because it mixed datetime and float types.
The shape.label path has no such arithmetic — Plotly.js handles placement
entirely.

This is an intentionally incremental step. The existing annotation creation
is still in place; removing it (and the deprecation warning) is planned for
a follow-up PR once the shape.label path is confirmed to be sufficient.

The annotation_bgcolor / annotation_bordercolor fields are not supported
by shape.label and are explicitly ignored with a FutureWarning

Guidelines

@ndrezn
Copy link
Copy Markdown
Member

ndrezn commented Dec 10, 2025

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.

nochinxx and others added 8 commits March 23, 2026 11:26
…el_from_legacy_annotation_kwargs(kwargs) to format kwargs into shape.label
…position normalizer

-refactor(vline): emit a single labeled shape; map legacy annotation_position to label.textposition
…notation positions to the shape’s label.textposition.
Migrate add_hrect from annotation to shape/label#
@nochinxx nochinxx force-pushed the refactor/autoshapes-use-shape-label branch from c9062f1 to 1010346 Compare March 23, 2026 18:46
@nochinxx
Copy link
Copy Markdown
Author

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.

Thanks! I’ve updated the branch and this is now ready for initial review.
I also added tests covering the new shape.label behavior while preserving existing annotation functionality.
Happy to split or adjust scope if that would help.

@nochinxx nochinxx marked this pull request as ready for review March 23, 2026 20:10
@emilykl emilykl self-requested a review March 25, 2026 16:06
@emilykl
Copy link
Copy Markdown
Contributor

emilykl commented Mar 25, 2026

Thanks @nochinxx for the PR! I'll review within the next few days.

@emilykl
Copy link
Copy Markdown
Contributor

emilykl commented Mar 26, 2026

@nochinxx Thanks for your work on this.

It does seem that in order to do this "right", we'll have to change the API for shape labels, and support both APIs in parallel until the next major version, as you've done in this PR.

Before I do a more detailed review, could you update the PR description to follow the template and include a few screenshots of shape labels created using the new API?

@nochinxx
Copy link
Copy Markdown
Author

I'll work on that. Thanks

@nochinxx
Copy link
Copy Markdown
Author

@emilykl I've updated the PR description to follow the template, it now includes a link to the motivating issue, a description of the changes, demo code with screenshots of shape labels created using the new API (for all four helpers, plus a backward-compat example), and a testing strategy section.

Let me know if you'd like me to rebase onto the latest main before you dig in, or if anything else needs adjusting. Thx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants