Skip to content

Fix plot_layout.__radd__ crash with plotnine's native composition operators#24

Merged
mdmanurung merged 2 commits into
mainfrom
copilot/fix-failing-github-actions-job
Jul 13, 2026
Merged

Fix plot_layout.__radd__ crash with plotnine's native composition operators#24
mdmanurung merged 2 commits into
mainfrom
copilot/fix-failing-github-actions-job

Conversation

Copilot AI commented Jul 13, 2026

Copy link
Copy Markdown

The docs build was failing with AttributeError: 'plot_layout' object has no attribute 'setup' when the composition-and-export.ipynb notebook executed (left | right) + plot_layout(widths=[1.6, 1]).

Root cause

In plotnine 0.15.x, ggplot.__or__ creates a native plotnine.composition.Beside. The native Compose.__add__ doesn't recognise plot_layout as a composition modifier, so it delegates it to the last ggplot:

native_Beside + plot_layout(...)
  → ggplot.__iadd__(plot_layout(...))
    → plot_layout.__radd__(ggplot_obj)   # ← called with a ggplot, not a Compose
      → ggplot.layout = self             # ← overwrites plotnine's internal Layout

When ggplot._build() subsequently called layout.setup(layers, self), it found plot_layout (which has no setup) instead of plotnine's internal Layout object.

Fix

Add a type guard in plot_layout.__radd__: if cmp is a ggplot instance (i.e. we're being added via native composition plumbing rather than directly to a plotnine_extra Compose), return cmp unchanged instead of corrupting its internal layout.

def __radd__(self, cmp: Compose) -> Compose:
    from plotnine import ggplot as _ggplot
    if isinstance(cmp, _ggplot):
        # Cannot apply plot_layout to a ggplot directly; leave it unchanged
        # so native composition can still render without crashing.
        return cmp
    cmp.layout = self
    return cmp

plot_layout applied via a plotnine_extra Compose (e.g. Beside([p1, p2]) + plot_layout(...)) continues to work as before. The full custom-width/height feature is gated on plotnine ≥ 0.16.0 (which adds Compose.layout), consistent with the existing skip condition in test_plot_composition.py.

…sition

When `left | right` is evaluated, `ggplot.__or__` (from plotnine 0.15.x)
creates a native `plotnine.composition.Beside`. When `+ plot_layout(widths=[1.6, 1])`
is applied, the native Compose.__add__ doesn't recognise plot_layout as a
composition modifier and passes it to the last ggplot via ggplot.__iadd__.
This called plot_layout.__radd__(ggplot), which incorrectly set
`ggplot.layout = self` (a plot_layout instance), overwriting plotnine's
internal Layout object and causing AttributeError: 'plot_layout' object
has no attribute 'setup' in ggplot._build().

Fix: guard plot_layout.__radd__ so that when cmp is a ggplot, it returns
cmp unchanged rather than corrupting its layout attribute.
Copilot AI changed the title [WIP] Fix failing GitHub Actions job 'build' Fix plot_layout.__radd__ crash with plotnine's native composition operators Jul 13, 2026
Copilot AI requested a review from mdmanurung July 13, 2026 16:01
@mdmanurung mdmanurung marked this pull request as ready for review July 13, 2026 16:14
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@mdmanurung mdmanurung merged commit c4aa4e0 into main Jul 13, 2026
5 of 6 checks passed
@mdmanurung mdmanurung deleted the copilot/fix-failing-github-actions-job branch July 13, 2026 16:15
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.

2 participants