Skip to content

ENG-9587: pyOr is not defined#6560

Merged
masenf merged 3 commits into
mainfrom
khaleel/eng-9587-pyor-is-not-defined
May 22, 2026
Merged

ENG-9587: pyOr is not defined#6560
masenf merged 3 commits into
mainfrom
khaleel/eng-9587-pyor-is-not-defined

Conversation

@adhami3310
Copy link
Copy Markdown
Member

@adhami3310 adhami3310 commented May 22, 2026

import reflex as rx

import reflex_components_internal as ui


def match_thing():
    return rx.match(
        "Foo",
        ("foo", rx.text("foo is foo!")),
        ("bar", rx.text("foo is bar!")),
        rx.text("foo is something else!"),
    )


def index() -> rx.Component:
    return rx.vstack(
        ui.dialog.trigger(
            render_=match_thing(),
        ),
        match_thing(),
    )


app = rx.App()
app.add_page(index)

previously:

import {
  Flex as RadixThemesFlex,
  Text as RadixThemesText,
} from "@radix-ui/themes";
import { Fragment, useEffect } from "react";
import { Dialog } from "@base-ui/react/dialog";
import { jsx } from "@emotion/react";

export default function Component() {
  return jsx(
    Fragment,
    {},
    jsx(
      RadixThemesFlex,
      { align: "start", className: "rx-Stack", direction: "column", gap: "3" },
      jsx(Dialog.Trigger, {
        "data-slot": "dialog-trigger",
        render: jsx(
          Fragment,
          {},
          pyOr(
            false,
            () =>
              JSON.stringify("foo")?.valueOf?.() ===
              JSON.stringify("Foo")?.valueOf?.(),
          )
            ? jsx(RadixThemesText, { as: "p" }, "foo is foo!")
            : pyOr(
                  false,
                  () =>
                    JSON.stringify("bar")?.valueOf?.() ===
                    JSON.stringify("Foo")?.valueOf?.(),
                )
              ? jsx(RadixThemesText, { as: "p" }, "foo is bar!")
              : jsx(RadixThemesText, { as: "p" }, "foo is something else!"),
        ),
      }),
      jsx(
        Fragment,
        {},
        (() => {
          switch (JSON.stringify("Foo")) {
            case JSON.stringify("foo"):
              return jsx(RadixThemesText, { as: "p" }, "foo is foo!");
              break;
            case JSON.stringify("bar"):
              return jsx(RadixThemesText, { as: "p" }, "foo is bar!");
              break;
            default:
              return jsx(
                RadixThemesText,
                { as: "p" },
                "foo is something else!",
              );
              break;
          }
        })(),
      ),
    ),
    jsx("title", {}, "ReproPyorImport | Index"),
    jsx("meta", { content: "favicon.ico", property: "og:image" }),
  );
}

now:

import {
  Flex as RadixThemesFlex,
  Text as RadixThemesText,
} from "@radix-ui/themes";
import { Fragment, useEffect } from "react";
import { Dialog } from "@base-ui/react/dialog";
import { jsx } from "@emotion/react";
import { pyOr } from "$/utils/state";

export default function Component() {
  return jsx(
    Fragment,
    {},
    jsx(
      RadixThemesFlex,
      { align: "start", className: "rx-Stack", direction: "column", gap: "3" },
      jsx(Dialog.Trigger, {
        "data-slot": "dialog-trigger",
        render: jsx(
          Fragment,
          {},
          JSON.stringify("foo")?.valueOf?.() ===
            JSON.stringify("Foo")?.valueOf?.()
            ? jsx(RadixThemesText, { as: "p" }, "foo is foo!")
            : JSON.stringify("bar")?.valueOf?.() ===
                JSON.stringify("Foo")?.valueOf?.()
              ? jsx(RadixThemesText, { as: "p" }, "foo is bar!")
              : jsx(RadixThemesText, { as: "p" }, "foo is something else!"),
        ),
      }),
      jsx(
        Fragment,
        {},
        (() => {
          switch (JSON.stringify("Foo")) {
            case JSON.stringify("foo"):
              return jsx(RadixThemesText, { as: "p" }, "foo is foo!");
              break;
            case JSON.stringify("bar"):
              return jsx(RadixThemesText, { as: "p" }, "foo is bar!");
              break;
            default:
              return jsx(
                RadixThemesText,
                { as: "p" },
                "foo is something else!",
              );
              break;
          }
        })(),
      ),
    ),
    jsx("title", {}, "MatchTest | Index"),
    jsx("meta", { content: "favicon.ico", property: "og:image" }),
  );
}

@adhami3310 adhami3310 requested a review from a team as a code owner May 22, 2026 22:16
@linear-code
Copy link
Copy Markdown

linear-code Bot commented May 22, 2026

ENG-9587

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 22, 2026

Greptile Summary

This PR fixes a ReferenceError: pyOr is not defined that occurred when rx.match was used with multiple patterns per case. The root cause was that _cached_var_name in LiteralComponentVar calls str() on the result of render_dict_to_var, discarding any VarData (including import requirements) accumulated during expression construction.

  • Bug fix: _PY_OR_IMPORT is now unconditionally added to the merged VarData of every LiteralComponentVar to guarantee pyOr is always available in the compiled output. The developer explicitly notes a cleaner long-term alternative (propagating VarData out of render_dict_to_var) as a follow-up.
  • Refactor: The per-case OR-chaining logic is extracted into _format_patterns_into_condition, which also eliminates the previous Var.create(False) seed that caused an unnecessary pyOr(False, () => (...)) wrapper for single-pattern cases.

Confidence Score: 4/5

The fix is correct and resolves the reported runtime error; the only trade-off is a blanket pyOr import added to every component, which is safe but worth revisiting as a follow-up.

The core bug (missing pyOr import with multi-pattern rx.match) is correctly fixed and well-explained. The workaround unconditionally injects the import for all components — the developer documents this and proposes a cleaner alternative — but the approach introduces a permanent, minor unnecessary import in cases that don't use multi-pattern matching. No data loss or incorrect behavior introduced.

packages/reflex-base/src/reflex_base/components/component.py — specifically the _cached_get_all_var_data workaround and the undocumented _format_patterns_into_condition helper.

Important Files Changed

Filename Overview
packages/reflex-base/src/reflex_base/components/component.py Fixes missing pyOr import when rx.match generates OR conditions; extracts pattern-matching logic into a helper function and unconditionally injects the import into all LiteralComponentVar instances as a documented workaround.

Reviews (1): Last reviewed commit: "ENG-9587: pyOr is not defined" | Re-trigger Greptile

Comment thread packages/reflex-base/src/reflex_base/components/component.py
Comment thread packages/reflex-base/src/reflex_base/components/component.py
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented May 22, 2026

Merging this PR will not alter performance

✅ 24 untouched benchmarks


Comparing khaleel/eng-9587-pyor-is-not-defined (a578756) with main (d611a5d)

Open in CodSpeed

@masenf masenf merged commit bfb4c26 into main May 22, 2026
70 checks passed
@masenf masenf deleted the khaleel/eng-9587-pyor-is-not-defined branch May 22, 2026 23:39
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