Plotly.py is an open-source Python library for creating interactive browser-based visualizations. Because it wraps Plotly.js, users can build high-quality charts in Python without needing to touch JavaScript directly.

My contribution focused on a bug and refactor path around labeled autoshapes, especially add_vline() on datetime axes.

The Issue

Historically, Plotly.py created two separate objects whenever a user added a labeled line or rectangle:

  1. a shape
  2. an annotation

That worked until users plotted datetime data and called add_vline(x="2020-09-24", annotation_text="Test"). The old code tried to compute the mean of x-coordinates to decide where to place the annotation, but dates cannot be averaged with integers, which caused a hard crash.

The real issue was architectural. Plotly.py was duplicating annotation behavior that Plotly.js already supports natively through shape.label.

Why I Started With add_vline()

I intentionally started with add_vline() because the datetime-axis crash was easiest to reproduce there. That made it the best entry point for validating whether the move to shape.label actually fixed the real user-facing failure mode.

What I Learned from Debugging

The old approach:

By shifting toward shape.label, that fragile arithmetic disappears. The label becomes part of the shape, and Plotly.js handles placement more consistently across axis types.

Progress

Why it mattered

This contribution helped me understand how architectural decisions inside large libraries can create subtle but real failures for users. It also reinforced the importance of aligning abstractions across language boundaries when working on wrapper libraries like Plotly.py.

Related project · Plotly.py repository · Original LinkedIn article