diff --git a/pyproject.toml b/pyproject.toml
index 8c7b1c84c23..7ab5355c99b 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -164,6 +164,7 @@ reportIncompatibleMethodOverride = false
[tool.ruff]
target-version = "py310"
output-format = "concise"
+extend-exclude = ["tests/units/reflex_base/utils/pyi_generator/golden"]
lint.isort.split-on-trailing-comma = false
preview = true
lint.select = ["ALL"]
diff --git a/tests/units/reflex_base/utils/__init__.py b/tests/units/reflex_base/utils/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tests/units/reflex_base/utils/pyi_generator/__init__.py b/tests/units/reflex_base/utils/pyi_generator/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tests/units/reflex_base/utils/pyi_generator/__main__.py b/tests/units/reflex_base/utils/pyi_generator/__main__.py
new file mode 100644
index 00000000000..3f0828cefda
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/__main__.py
@@ -0,0 +1,10 @@
+"""CLI entry point for pyi_generator regression tests.
+
+Usage:
+ python -m tests.units.reflex_base.utils.pyi_generator --update
+ python -m tests.units.reflex_base.utils.pyi_generator --check
+"""
+
+from tests.units.reflex_base.utils.pyi_generator.test_regression import main
+
+main()
diff --git a/tests/units/reflex_base/utils/pyi_generator/dataset/__init__.py b/tests/units/reflex_base/utils/pyi_generator/dataset/__init__.py
new file mode 100644
index 00000000000..9ba86475d37
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/dataset/__init__.py
@@ -0,0 +1,6 @@
+"""Test dataset for pyi_generator regression tests.
+
+This package contains Python modules designed to exercise all translation
+features of the pyi_generator. Each module targets specific code paths
+in the generator.
+"""
diff --git a/tests/units/reflex_base/utils/pyi_generator/dataset/classvar_and_private.py b/tests/units/reflex_base/utils/pyi_generator/dataset/classvar_and_private.py
new file mode 100644
index 00000000000..e9aa27b9243
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/dataset/classvar_and_private.py
@@ -0,0 +1,52 @@
+"""Component with ClassVar, private attrs, and excluded props.
+
+This module tests:
+- ClassVar annotations are preserved (not turned into create() kwargs)
+- Private annotated attributes (_foo) are removed from stubs
+- EXCLUDED_PROPS (like tag, library, etc.) are not in create()
+- Private methods are removed
+- Non-annotated assignments inside Component classes are removed
+- AnnAssign with value is blanked (value set to None)
+"""
+
+from typing import Any, ClassVar
+
+from reflex_base.components.component import Component, field
+from reflex_base.vars.base import Var
+
+
+class StrictComponent(Component):
+ """A component with ClassVar, private, and excluded props."""
+
+ _internal_counter: int = 0
+
+ _hidden_state: ClassVar[dict[str, Any]] = {}
+
+ tag: str | None = "div"
+
+ library: str | None = "some-lib"
+
+ # The valid children for this component.
+ _valid_children: ClassVar[list[str]] = ["ChildA", "ChildB"]
+
+ # The memoization mode.
+ _memoization_mode: ClassVar[Any] = None
+
+ # A public prop that should appear in create().
+ visible_prop: Var[str] = field(doc="A prop visible in the stub.")
+
+ # Another public prop.
+ size: Var[int] = field(doc="The size of the component.")
+
+ some_constant = "not_a_prop"
+
+ def _internal_helper(self) -> None:
+ """Private method, should be removed."""
+
+ def render_item(self) -> str:
+ """Public method, body should be blanked.
+
+ Returns:
+ The rendered item.
+ """
+ return f"
{self.visible_prop}
"
diff --git a/tests/units/reflex_base/utils/pyi_generator/dataset/custom_create.py b/tests/units/reflex_base/utils/pyi_generator/dataset/custom_create.py
new file mode 100644
index 00000000000..65b1472c03b
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/dataset/custom_create.py
@@ -0,0 +1,38 @@
+"""Component with an explicitly defined create() method.
+
+This module tests:
+- Existing create() is regenerated (replaced with generated version)
+- Decorator list from original create() is preserved
+- Custom kwargs on create() are included
+"""
+
+from typing import Any
+
+from reflex_base.components.component import Component, field
+from reflex_base.vars.base import Var
+
+
+class CustomCreateComponent(Component):
+ """A component that defines its own create method."""
+
+ # A label prop.
+ label: Var[str] = field(doc="Display label.")
+
+ # A numeric value.
+ amount: Var[int] = field(doc="The amount.")
+
+ @classmethod
+ def create(
+ cls, *children: Any, custom_kwarg: str = "default", **props: Any
+ ) -> "CustomCreateComponent":
+ """Create a custom component with extra kwargs.
+
+ Args:
+ *children: The child components.
+ custom_kwarg: A custom keyword argument.
+ **props: Additional properties.
+
+ Returns:
+ The component instance.
+ """
+ return super().create(*children, **props)
diff --git a/tests/units/reflex_base/utils/pyi_generator/dataset/inheritance.py b/tests/units/reflex_base/utils/pyi_generator/dataset/inheritance.py
new file mode 100644
index 00000000000..da31cde1ade
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/dataset/inheritance.py
@@ -0,0 +1,39 @@
+"""Components with inheritance hierarchy.
+
+This module tests:
+- Props from parent classes appear in create() via MRO traversal
+- Overridden props are not duplicated
+- Multiple levels of inheritance
+"""
+
+from reflex_base.components.component import Component, field
+from reflex_base.event import EventHandler, passthrough_event_spec
+from reflex_base.vars.base import Var
+
+
+class BaseWidget(Component):
+ """A base widget with common props."""
+
+ # Widget color.
+ color: Var[str] = field(doc="The widget color.")
+
+ # Whether the widget is disabled.
+ disabled: Var[bool] = field(doc="Whether the widget is disabled.")
+
+
+class InteractiveWidget(BaseWidget):
+ """An interactive widget extending BaseWidget."""
+
+ # The placeholder text.
+ placeholder: Var[str] = field(doc="Placeholder text.")
+
+ on_value_change: EventHandler[passthrough_event_spec(str)] = field(
+ doc="Fired when value changes.",
+ )
+
+
+class FancyWidget(InteractiveWidget):
+ """A fancy widget with extra styling, three levels deep."""
+
+ # Border radius.
+ border_radius: Var[str] = field(doc="The border radius.")
diff --git a/tests/units/reflex_base/utils/pyi_generator/dataset/literal_types.py b/tests/units/reflex_base/utils/pyi_generator/dataset/literal_types.py
new file mode 100644
index 00000000000..7ff76d70669
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/dataset/literal_types.py
@@ -0,0 +1,31 @@
+"""Component with Literal type props.
+
+This module tests:
+- Literal type annotations on props
+- Module-level Literal type aliases
+- Var[Literal[...]] expansion (Var union with inner literal)
+"""
+
+from typing import Literal
+
+from reflex_base.components.component import Component, field
+from reflex_base.vars.base import Var
+
+LiteralSize = Literal["sm", "md", "lg", "xl"]
+LiteralVariant = Literal["solid", "outline", "ghost"]
+LiteralOrientation = Literal["horizontal", "vertical"]
+
+
+class ThemedComponent(Component):
+ """A component with literal-typed props."""
+
+ # The size of the component.
+ size: Var[LiteralSize] = field(doc="Component size.")
+
+ # The variant style.
+ variant: Var[LiteralVariant] = field(doc="Visual variant.")
+
+ orientation: Var[LiteralOrientation]
+
+ # A direct Literal annotation without alias.
+ color_scheme: Var[Literal["red", "green", "blue"]]
diff --git a/tests/units/reflex_base/utils/pyi_generator/dataset/module_level.py b/tests/units/reflex_base/utils/pyi_generator/dataset/module_level.py
new file mode 100644
index 00000000000..376fd167dd6
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/dataset/module_level.py
@@ -0,0 +1,48 @@
+"""Module with module-level functions, constants, and type aliases.
+
+This module tests:
+- Module-level function body blanking
+- Module-level annotated assignments (value blanked)
+- Module-level non-annotated assignments (removed)
+- Type alias preservation
+- Combined: component + module-level items
+"""
+
+from typing import Literal
+
+from reflex_base.components.component import Component, field
+from reflex_base.vars.base import Var
+
+LiteralMode = Literal["light", "dark", "system"]
+
+# A module-level constant (non-annotated, should be removed).
+DEFAULT_TIMEOUT = 30
+
+# Annotated module-level var (value should be blanked).
+current_mode: LiteralMode = "system"
+
+
+def helper_function(x: int, y: int) -> int:
+ """Add two numbers.
+
+ Args:
+ x: First number.
+ y: Second number.
+
+ Returns:
+ The sum.
+ """
+ return x + y
+
+
+def another_helper() -> None:
+ """Do nothing important."""
+ print("side effect")
+
+
+class ModuleComponent(Component):
+ """A component defined alongside module-level items."""
+
+ mode: Var[LiteralMode] = field(doc="The display mode.")
+
+ timeout: Var[int] = field(doc="Timeout in seconds.")
diff --git a/tests/units/reflex_base/utils/pyi_generator/dataset/namespace_component.py b/tests/units/reflex_base/utils/pyi_generator/dataset/namespace_component.py
new file mode 100644
index 00000000000..f7ce43da7ed
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/dataset/namespace_component.py
@@ -0,0 +1,43 @@
+"""Components using ComponentNamespace pattern.
+
+This module tests:
+- ComponentNamespace with __call__ = staticmethod(SomeComponent.create)
+- Multiple components in the same module
+- Namespace with staticmethod assignments
+- Module-level namespace instance assignment
+"""
+
+from reflex_base.components.component import Component, ComponentNamespace, field
+from reflex_base.vars.base import Var
+
+
+class DialogRoot(Component):
+ """The root dialog component."""
+
+ # Whether the dialog is open.
+ is_open: Var[bool] = field(doc="Whether the dialog is open.")
+
+
+class DialogContent(Component):
+ """The dialog content component."""
+
+ # Whether to force mount the content.
+ force_mount: Var[bool] = field(doc="Whether to force mount.")
+
+
+class DialogTitle(Component):
+ """The dialog title component."""
+
+ # The title text.
+ title_text: Var[str]
+
+
+class Dialog(ComponentNamespace):
+ """Dialog components namespace."""
+
+ root = __call__ = staticmethod(DialogRoot.create)
+ content = staticmethod(DialogContent.create)
+ title = staticmethod(DialogTitle.create)
+
+
+dialog = Dialog()
diff --git a/tests/units/reflex_base/utils/pyi_generator/dataset/simple_component.py b/tests/units/reflex_base/utils/pyi_generator/dataset/simple_component.py
new file mode 100644
index 00000000000..7687d780a07
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/dataset/simple_component.py
@@ -0,0 +1,58 @@
+"""A simple component with basic props.
+
+This module tests:
+- Basic component stub generation
+- Props with various simple types (str, int, bool, float)
+- Default event handlers inherited from Component
+- Props with doc strings (via field(doc=...))
+- Props with comment-based docs (# comment above prop)
+- Module docstring removal in stubs
+- visit_Assign: assignment to `Any` is preserved
+- visit_Assign: non-annotated assignments are removed
+"""
+
+from typing import Any
+
+from reflex_base.components.component import Component, field
+from reflex_base.vars.base import Var
+
+# Assignment to Any should be preserved in the stub.
+SomeType = Any
+
+# A regular non-annotated assignment should be removed.
+SOME_CONSTANT = 42
+
+
+class SimpleComponent(Component):
+ """A simple test component with basic prop types."""
+
+ # The title displayed on the component.
+ title: Var[str]
+
+ # The count to display.
+ count: Var[int]
+
+ is_active: Var[bool] = field(doc="Whether the component is active.")
+
+ opacity: Var[float] = field(doc="The opacity of the component.")
+
+ label: Var[str] = field(
+ default=Var.create("default"),
+ doc="An optional label with a default value.",
+ )
+
+ def _private_method(self):
+ """This should not appear in the stub.
+
+ Returns:
+ A string indicating this is a private method.
+ """
+ return "private"
+
+ def public_helper(self) -> str:
+ """A public method that should have its body blanked out.
+
+ Returns:
+ A string indicating this is a public helper method.
+ """
+ return "hello"
diff --git a/tests/units/reflex_base/utils/pyi_generator/dataset/staticmethod_namespace.py b/tests/units/reflex_base/utils/pyi_generator/dataset/staticmethod_namespace.py
new file mode 100644
index 00000000000..3f5fc00f725
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/dataset/staticmethod_namespace.py
@@ -0,0 +1,42 @@
+"""Namespace with staticmethod __call__ that is not Component.create.
+
+This module tests:
+- _generate_staticmethod_call_functiondef path
+- Namespace __call__ with custom function (not wrapping .create)
+- The fallback where __call__.__func__.__name__ != "create"
+"""
+
+from reflex_base.components.component import Component, ComponentNamespace, field
+from reflex_base.event import EventSpec
+from reflex_base.vars.base import Var
+
+
+class NotifyComponent(Component):
+ """A notification component."""
+
+ message: Var[str] = field(doc="The notification message.")
+
+ level: Var[str] = field(doc="The notification level.")
+
+
+def send_notification(message: str, level: str = "info") -> EventSpec:
+ """Send a notification event.
+
+ Args:
+ message: The message to send.
+ level: The notification level.
+
+ Returns:
+ The event spec.
+ """
+ return EventSpec() # type: ignore[call-arg]
+
+
+class Notify(ComponentNamespace):
+ """Notification namespace."""
+
+ component = staticmethod(NotifyComponent.create)
+ __call__ = staticmethod(send_notification)
+
+
+notify = Notify()
diff --git a/tests/units/reflex_base/utils/pyi_generator/dataset/string_event_annotations.py b/tests/units/reflex_base/utils/pyi_generator/dataset/string_event_annotations.py
new file mode 100644
index 00000000000..f1e3bd61189
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/dataset/string_event_annotations.py
@@ -0,0 +1,63 @@
+"""Component with string-based tuple return annotations on event handlers.
+
+This module tests:
+- figure_out_return_type with string-based "tuple[...]" annotation
+- The string parsing path for event handler signatures
+- Empty tuple[()], single arg tuple[str], multi-arg tuple[str, int]
+"""
+
+from reflex_base.components.component import Component, field
+from reflex_base.event import EventHandler
+from reflex_base.vars.base import Var
+
+
+def on_empty_handler() -> "tuple[()]":
+ """Handler returning empty tuple.
+
+ Returns:
+ An empty tuple.
+ """
+ return ()
+
+
+def on_string_handler(value: Var[str]) -> "tuple[Var[str]]":
+ """Handler returning a single string arg.
+
+ Args:
+ value: The string value from the event.
+
+ Returns:
+ A tuple containing the string value.
+ """
+ return (value,)
+
+
+def on_multi_handler(name: Var[str], age: Var[int]) -> "tuple[Var[str], Var[int]]":
+ """Handler returning multiple args.
+
+ Args:
+ name: The name from the event.
+ age: The age from the event.
+
+ Returns:
+ A tuple containing the name and age.
+ """
+ return (name, age)
+
+
+class StringAnnotationComponent(Component):
+ """A component with string-annotated event handlers."""
+
+ value: Var[str]
+
+ on_empty: EventHandler[on_empty_handler] = field(
+ doc="Fires with no args.",
+ )
+
+ on_string: EventHandler[on_string_handler] = field(
+ doc="Fires with a string.",
+ )
+
+ on_multi: EventHandler[on_multi_handler] = field(
+ doc="Fires with name and age.",
+ )
diff --git a/tests/units/reflex_base/utils/pyi_generator/dataset/sub_package/__init__.py b/tests/units/reflex_base/utils/pyi_generator/dataset/sub_package/__init__.py
new file mode 100644
index 00000000000..a3f4ee8e02b
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/dataset/sub_package/__init__.py
@@ -0,0 +1,15 @@
+"""A sub-package with lazy loading.
+
+This tests __init__.py stub generation with _SUBMOD_ATTRS.
+"""
+
+from reflex_base.utils import lazy_loader
+
+_SUBMOD_ATTRS: dict[str, list[str]] = {
+ "widget": ["SubWidget"],
+}
+
+__getattr__, __dir__, __all__ = lazy_loader.attach(
+ __name__,
+ submod_attrs=_SUBMOD_ATTRS,
+)
diff --git a/tests/units/reflex_base/utils/pyi_generator/dataset/sub_package/widget.py b/tests/units/reflex_base/utils/pyi_generator/dataset/sub_package/widget.py
new file mode 100644
index 00000000000..d5147be5034
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/dataset/sub_package/widget.py
@@ -0,0 +1,13 @@
+"""A widget component for the sub_package.
+
+This is a simple module providing a component for the __init__.py lazy loader test.
+"""
+
+from reflex_base.components.component import Component, field
+from reflex_base.vars.base import Var
+
+
+class SubWidget(Component):
+ """A widget in the sub package."""
+
+ name: Var[str] = field(doc="Widget name.")
diff --git a/tests/units/reflex_base/utils/pyi_generator/dataset/typed_event_handlers.py b/tests/units/reflex_base/utils/pyi_generator/dataset/typed_event_handlers.py
new file mode 100644
index 00000000000..ed436acbc73
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/dataset/typed_event_handlers.py
@@ -0,0 +1,77 @@
+"""Components with various event handler signatures.
+
+This module tests:
+- Custom event handlers with typed tuple returns
+- passthrough_event_spec usage
+- Multiple event specs (Sequence of specs)
+- Event handlers with no args (no_args_event_spec)
+- Event handler with multi-arg tuples
+- String-based tuple return annotations
+"""
+
+from reflex_base.components.component import Component, field
+from reflex_base.event import EventHandler, passthrough_event_spec
+from reflex_base.vars.base import Var
+
+
+def on_value_change_handler(value: Var[str]) -> tuple[Var[str]]:
+ """Event spec for a string value change.
+
+ Args:
+ value: The new value.
+
+ Returns:
+ The value tuple.
+ """
+ return (value,)
+
+
+def on_pair_change_handler(key: Var[str], value: Var[int]) -> tuple[Var[str], Var[int]]:
+ """Event spec for a key-value pair change.
+
+ Args:
+ key: The key.
+ value: The value.
+
+ Returns:
+ The key-value tuple.
+ """
+ return (key, value)
+
+
+class EventComponent(Component):
+ """A component with various event handler types."""
+
+ # A simple string value prop.
+ value: Var[str]
+
+ # Custom event handler with typed return.
+ on_value_change: EventHandler[on_value_change_handler] = field(
+ doc="Fired when the value changes.",
+ )
+
+ # Event handler with multiple return args.
+ on_pair_change: EventHandler[on_pair_change_handler] = field(
+ doc="Fired when a key-value pair changes.",
+ )
+
+ # Passthrough event spec with single type.
+ on_item_select: EventHandler[passthrough_event_spec(str)] = field(
+ doc="Fired when an item is selected.",
+ )
+
+ # Passthrough event spec with multiple types.
+ on_range_change: EventHandler[passthrough_event_spec(int, int)] = field(
+ doc="Fired when the range changes.",
+ )
+
+
+class MultiSpecComponent(Component):
+ """A component where event triggers have multiple possible specs."""
+
+ value: Var[str]
+
+ # Multiple event specs: can fire with no args or with a string value.
+ on_open_change: EventHandler[passthrough_event_spec(bool)] = field(
+ doc="Fired when the open state changes.",
+ )
diff --git a/tests/units/reflex_base/utils/pyi_generator/dataset/var_types.py b/tests/units/reflex_base/utils/pyi_generator/dataset/var_types.py
new file mode 100644
index 00000000000..dc858c690d1
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/dataset/var_types.py
@@ -0,0 +1,45 @@
+"""Component with various Var[T] prop types and edge cases.
+
+This module tests:
+- Var[T] expansion: Var[str] -> Var[str] | str
+- Var with Union args: Var[str | int] -> Var[str | int] | str | int
+- Complex nested types: Var[list[str]], Var[dict[str, Any]], Var[list[dict[str, Any]]]
+- Component with no custom props (just inherited defaults)
+- Component with only event handlers (no data props)
+"""
+
+from typing import Any
+
+from reflex_base.components.component import Component, field
+from reflex_base.event import EventHandler, passthrough_event_spec
+from reflex_base.vars.base import Var
+
+
+class EmptyComponent(Component):
+ """A component with no custom props at all."""
+
+
+class EventOnlyComponent(Component):
+ """A component with only custom event handlers, no data props."""
+
+ on_toggle: EventHandler[passthrough_event_spec(bool)] = field(
+ doc="Fired when toggled.",
+ )
+
+
+class VarTypesComponent(Component):
+ """A component exercising various Var type expansions."""
+
+ # Basic Var types.
+ name: Var[str]
+ count: Var[int]
+ ratio: Var[float]
+ flag: Var[bool]
+
+ # Union inside Var.
+ value: Var[str | int] = field(doc="A string or int value.")
+
+ # Nested generic Var types.
+ items: Var[list[str]] = field(doc="A list of string items.")
+ metadata: Var[dict[str, Any]] = field(doc="Metadata dictionary.")
+ nested: Var[list[dict[str, Any]]] = field(doc="Nested structures.")
diff --git a/tests/units/reflex_base/utils/pyi_generator/golden/.gitignore b/tests/units/reflex_base/utils/pyi_generator/golden/.gitignore
new file mode 100644
index 00000000000..c9c1cd6e861
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/golden/.gitignore
@@ -0,0 +1 @@
+!*.pyi
\ No newline at end of file
diff --git a/tests/units/reflex_base/utils/pyi_generator/golden/classvar_and_private.pyi b/tests/units/reflex_base/utils/pyi_generator/golden/classvar_and_private.pyi
new file mode 100644
index 00000000000..d459b1b82bf
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/golden/classvar_and_private.pyi
@@ -0,0 +1,84 @@
+"""Stub file for """
+
+# ------------------- DO NOT EDIT ----------------------
+# This file was generated by `reflex/utils/pyi_generator.py`!
+# ------------------------------------------------------
+from collections.abc import Mapping, Sequence
+from typing import Any
+
+from reflex_base.components.component import Component
+from reflex_base.event import EventType, PointerEventInfo
+from reflex_base.vars.base import Var
+from reflex_components_core.core.breakpoints import Breakpoints
+
+class StrictComponent(Component):
+ def render_item(self) -> str: ...
+ @classmethod
+ def create(
+ cls,
+ *children,
+ _internal_counter: int | None = None,
+ visible_prop: Var[str] | str | None = None,
+ size: Var[int] | int | None = None,
+ style: Sequence[Mapping[str, Any]]
+ | Mapping[str, Any]
+ | Var[Mapping[str, Any]]
+ | Breakpoints
+ | None = None,
+ key: Any | None = None,
+ id: Any | None = None,
+ ref: Var | None = None,
+ class_name: Any | None = None,
+ custom_attrs: dict[str, Any | Var] | None = None,
+ on_blur: EventType[()] | None = None,
+ on_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_focus: EventType[()] | None = None,
+ on_mount: EventType[()] | None = None,
+ on_mouse_down: EventType[()] | None = None,
+ on_mouse_enter: EventType[()] | None = None,
+ on_mouse_leave: EventType[()] | None = None,
+ on_mouse_move: EventType[()] | None = None,
+ on_mouse_out: EventType[()] | None = None,
+ on_mouse_over: EventType[()] | None = None,
+ on_mouse_up: EventType[()] | None = None,
+ on_scroll: EventType[()] | None = None,
+ on_scroll_end: EventType[()] | None = None,
+ on_unmount: EventType[()] | None = None,
+ **props,
+ ) -> StrictComponent:
+ """Create the component.
+
+ Args:
+ *children: The children of the component.
+ _internal_counter: no description
+ visible_prop: A prop visible in the stub.
+ size: The size of the component.
+ style: The style of the component.
+ key: A unique key for the component.
+ id: The id for the component.
+ ref: The Var to pass as the ref to the component.
+ class_name: The class name for the component.
+ custom_attrs: Attributes passed directly to the component.
+ on_focus: Fired when the element (or some element inside of it) receives focus. For example, it is called when the user clicks on a text input.
+ on_blur: Fired when focus has left the element (or left some element inside of it). For example, it is called when the user clicks outside of a focused text input.
+ on_click: Fired when the user clicks on an element. For example, it's called when the user clicks on a button.
+ on_context_menu: Fired when the user right-clicks on an element.
+ on_double_click: Fired when the user double-clicks on an element.
+ on_mouse_down: Fired when the user presses a mouse button on an element.
+ on_mouse_enter: Fired when the mouse pointer enters the element.
+ on_mouse_leave: Fired when the mouse pointer leaves the element.
+ on_mouse_move: Fired when the mouse pointer moves over the element.
+ on_mouse_out: Fired when the mouse pointer moves out of the element.
+ on_mouse_over: Fired when the mouse pointer moves onto the element.
+ on_mouse_up: Fired when the user releases a mouse button on an element.
+ on_scroll: Fired when the user scrolls the element.
+ on_scroll_end: Fired when scrolling ends on the element.
+ on_mount: Fired when the component is mounted to the page.
+ on_unmount: Fired when the component is removed from the page. Only called during navigation, not on page refresh.
+ **props: The props of the component.
+
+ Returns:
+ The component.
+ """
diff --git a/tests/units/reflex_base/utils/pyi_generator/golden/custom_create.pyi b/tests/units/reflex_base/utils/pyi_generator/golden/custom_create.pyi
new file mode 100644
index 00000000000..3f60cc9c1f2
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/golden/custom_create.pyi
@@ -0,0 +1,83 @@
+"""Stub file for """
+
+# ------------------- DO NOT EDIT ----------------------
+# This file was generated by `reflex/utils/pyi_generator.py`!
+# ------------------------------------------------------
+from collections.abc import Mapping, Sequence
+from typing import Any
+
+from reflex_base.components.component import Component
+from reflex_base.event import EventType, PointerEventInfo
+from reflex_base.vars.base import Var
+from reflex_components_core.core.breakpoints import Breakpoints
+
+class CustomCreateComponent(Component):
+ @classmethod
+ def create(
+ cls,
+ *children,
+ custom_kwarg: str | None = "default",
+ label: Var[str] | str | None = None,
+ amount: Var[int] | int | None = None,
+ style: Sequence[Mapping[str, Any]]
+ | Mapping[str, Any]
+ | Var[Mapping[str, Any]]
+ | Breakpoints
+ | None = None,
+ key: Any | None = None,
+ id: Any | None = None,
+ ref: Var | None = None,
+ class_name: Any | None = None,
+ custom_attrs: dict[str, Any | Var] | None = None,
+ on_blur: EventType[()] | None = None,
+ on_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_focus: EventType[()] | None = None,
+ on_mount: EventType[()] | None = None,
+ on_mouse_down: EventType[()] | None = None,
+ on_mouse_enter: EventType[()] | None = None,
+ on_mouse_leave: EventType[()] | None = None,
+ on_mouse_move: EventType[()] | None = None,
+ on_mouse_out: EventType[()] | None = None,
+ on_mouse_over: EventType[()] | None = None,
+ on_mouse_up: EventType[()] | None = None,
+ on_scroll: EventType[()] | None = None,
+ on_scroll_end: EventType[()] | None = None,
+ on_unmount: EventType[()] | None = None,
+ **props,
+ ) -> CustomCreateComponent:
+ """Create a custom component with extra kwargs.
+
+ Args:
+ *children: The child components.
+ custom_kwarg: A custom keyword argument.
+ label: Display label.
+ amount: The amount.
+ style: The style of the component.
+ key: A unique key for the component.
+ id: The id for the component.
+ ref: The Var to pass as the ref to the component.
+ class_name: The class name for the component.
+ custom_attrs: Attributes passed directly to the component.
+ on_focus: Fired when the element (or some element inside of it) receives focus. For example, it is called when the user clicks on a text input.
+ on_blur: Fired when focus has left the element (or left some element inside of it). For example, it is called when the user clicks outside of a focused text input.
+ on_click: Fired when the user clicks on an element. For example, it's called when the user clicks on a button.
+ on_context_menu: Fired when the user right-clicks on an element.
+ on_double_click: Fired when the user double-clicks on an element.
+ on_mouse_down: Fired when the user presses a mouse button on an element.
+ on_mouse_enter: Fired when the mouse pointer enters the element.
+ on_mouse_leave: Fired when the mouse pointer leaves the element.
+ on_mouse_move: Fired when the mouse pointer moves over the element.
+ on_mouse_out: Fired when the mouse pointer moves out of the element.
+ on_mouse_over: Fired when the mouse pointer moves onto the element.
+ on_mouse_up: Fired when the user releases a mouse button on an element.
+ on_scroll: Fired when the user scrolls the element.
+ on_scroll_end: Fired when scrolling ends on the element.
+ on_mount: Fired when the component is mounted to the page.
+ on_unmount: Fired when the component is removed from the page. Only called during navigation, not on page refresh.
+ **props: Additional properties.
+
+ Returns:
+ The component instance.
+ """
diff --git a/tests/units/reflex_base/utils/pyi_generator/golden/inheritance.pyi b/tests/units/reflex_base/utils/pyi_generator/golden/inheritance.pyi
new file mode 100644
index 00000000000..ea1ad91d040
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/golden/inheritance.pyi
@@ -0,0 +1,229 @@
+"""Stub file for """
+
+# ------------------- DO NOT EDIT ----------------------
+# This file was generated by `reflex/utils/pyi_generator.py`!
+# ------------------------------------------------------
+from collections.abc import Mapping, Sequence
+from typing import Any
+
+from reflex_base.components.component import Component
+from reflex_base.event import EventType, PointerEventInfo
+from reflex_base.vars.base import Var
+from reflex_components_core.core.breakpoints import Breakpoints
+
+class BaseWidget(Component):
+ @classmethod
+ def create(
+ cls,
+ *children,
+ color: Var[str] | str | None = None,
+ disabled: Var[bool] | bool | None = None,
+ style: Sequence[Mapping[str, Any]]
+ | Mapping[str, Any]
+ | Var[Mapping[str, Any]]
+ | Breakpoints
+ | None = None,
+ key: Any | None = None,
+ id: Any | None = None,
+ ref: Var | None = None,
+ class_name: Any | None = None,
+ custom_attrs: dict[str, Any | Var] | None = None,
+ on_blur: EventType[()] | None = None,
+ on_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_focus: EventType[()] | None = None,
+ on_mount: EventType[()] | None = None,
+ on_mouse_down: EventType[()] | None = None,
+ on_mouse_enter: EventType[()] | None = None,
+ on_mouse_leave: EventType[()] | None = None,
+ on_mouse_move: EventType[()] | None = None,
+ on_mouse_out: EventType[()] | None = None,
+ on_mouse_over: EventType[()] | None = None,
+ on_mouse_up: EventType[()] | None = None,
+ on_scroll: EventType[()] | None = None,
+ on_scroll_end: EventType[()] | None = None,
+ on_unmount: EventType[()] | None = None,
+ **props,
+ ) -> BaseWidget:
+ """Create the component.
+
+ Args:
+ *children: The children of the component.
+ color: The widget color.
+ disabled: Whether the widget is disabled.
+ style: The style of the component.
+ key: A unique key for the component.
+ id: The id for the component.
+ ref: The Var to pass as the ref to the component.
+ class_name: The class name for the component.
+ custom_attrs: Attributes passed directly to the component.
+ on_focus: Fired when the element (or some element inside of it) receives focus. For example, it is called when the user clicks on a text input.
+ on_blur: Fired when focus has left the element (or left some element inside of it). For example, it is called when the user clicks outside of a focused text input.
+ on_click: Fired when the user clicks on an element. For example, it's called when the user clicks on a button.
+ on_context_menu: Fired when the user right-clicks on an element.
+ on_double_click: Fired when the user double-clicks on an element.
+ on_mouse_down: Fired when the user presses a mouse button on an element.
+ on_mouse_enter: Fired when the mouse pointer enters the element.
+ on_mouse_leave: Fired when the mouse pointer leaves the element.
+ on_mouse_move: Fired when the mouse pointer moves over the element.
+ on_mouse_out: Fired when the mouse pointer moves out of the element.
+ on_mouse_over: Fired when the mouse pointer moves onto the element.
+ on_mouse_up: Fired when the user releases a mouse button on an element.
+ on_scroll: Fired when the user scrolls the element.
+ on_scroll_end: Fired when scrolling ends on the element.
+ on_mount: Fired when the component is mounted to the page.
+ on_unmount: Fired when the component is removed from the page. Only called during navigation, not on page refresh.
+ **props: The props of the component.
+
+ Returns:
+ The component.
+ """
+
+class InteractiveWidget(BaseWidget):
+ @classmethod
+ def create(
+ cls,
+ *children,
+ placeholder: Var[str] | str | None = None,
+ color: Var[str] | str | None = None,
+ disabled: Var[bool] | bool | None = None,
+ style: Sequence[Mapping[str, Any]]
+ | Mapping[str, Any]
+ | Var[Mapping[str, Any]]
+ | Breakpoints
+ | None = None,
+ key: Any | None = None,
+ id: Any | None = None,
+ ref: Var | None = None,
+ class_name: Any | None = None,
+ custom_attrs: dict[str, Any | Var] | None = None,
+ on_blur: EventType[()] | None = None,
+ on_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_focus: EventType[()] | None = None,
+ on_mount: EventType[()] | None = None,
+ on_mouse_down: EventType[()] | None = None,
+ on_mouse_enter: EventType[()] | None = None,
+ on_mouse_leave: EventType[()] | None = None,
+ on_mouse_move: EventType[()] | None = None,
+ on_mouse_out: EventType[()] | None = None,
+ on_mouse_over: EventType[()] | None = None,
+ on_mouse_up: EventType[()] | None = None,
+ on_scroll: EventType[()] | None = None,
+ on_scroll_end: EventType[()] | None = None,
+ on_unmount: EventType[()] | None = None,
+ on_value_change: EventType[()] | EventType[str] | None = None,
+ **props,
+ ) -> InteractiveWidget:
+ """Create the component.
+
+ Args:
+ *children: The children of the component.
+ placeholder: Placeholder text.
+ color: The widget color.
+ disabled: Whether the widget is disabled.
+ style: The style of the component.
+ key: A unique key for the component.
+ id: The id for the component.
+ ref: The Var to pass as the ref to the component.
+ class_name: The class name for the component.
+ custom_attrs: Attributes passed directly to the component.
+ on_focus: Fired when the element (or some element inside of it) receives focus. For example, it is called when the user clicks on a text input.
+ on_blur: Fired when focus has left the element (or left some element inside of it). For example, it is called when the user clicks outside of a focused text input.
+ on_click: Fired when the user clicks on an element. For example, it's called when the user clicks on a button.
+ on_context_menu: Fired when the user right-clicks on an element.
+ on_double_click: Fired when the user double-clicks on an element.
+ on_mouse_down: Fired when the user presses a mouse button on an element.
+ on_mouse_enter: Fired when the mouse pointer enters the element.
+ on_mouse_leave: Fired when the mouse pointer leaves the element.
+ on_mouse_move: Fired when the mouse pointer moves over the element.
+ on_mouse_out: Fired when the mouse pointer moves out of the element.
+ on_mouse_over: Fired when the mouse pointer moves onto the element.
+ on_mouse_up: Fired when the user releases a mouse button on an element.
+ on_scroll: Fired when the user scrolls the element.
+ on_scroll_end: Fired when scrolling ends on the element.
+ on_mount: Fired when the component is mounted to the page.
+ on_unmount: Fired when the component is removed from the page. Only called during navigation, not on page refresh.
+ on_value_change: Fired when value changes.
+ **props: The props of the component.
+
+ Returns:
+ The component.
+ """
+
+class FancyWidget(InteractiveWidget):
+ @classmethod
+ def create(
+ cls,
+ *children,
+ border_radius: Var[str] | str | None = None,
+ placeholder: Var[str] | str | None = None,
+ color: Var[str] | str | None = None,
+ disabled: Var[bool] | bool | None = None,
+ style: Sequence[Mapping[str, Any]]
+ | Mapping[str, Any]
+ | Var[Mapping[str, Any]]
+ | Breakpoints
+ | None = None,
+ key: Any | None = None,
+ id: Any | None = None,
+ ref: Var | None = None,
+ class_name: Any | None = None,
+ custom_attrs: dict[str, Any | Var] | None = None,
+ on_blur: EventType[()] | None = None,
+ on_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_focus: EventType[()] | None = None,
+ on_mount: EventType[()] | None = None,
+ on_mouse_down: EventType[()] | None = None,
+ on_mouse_enter: EventType[()] | None = None,
+ on_mouse_leave: EventType[()] | None = None,
+ on_mouse_move: EventType[()] | None = None,
+ on_mouse_out: EventType[()] | None = None,
+ on_mouse_over: EventType[()] | None = None,
+ on_mouse_up: EventType[()] | None = None,
+ on_scroll: EventType[()] | None = None,
+ on_scroll_end: EventType[()] | None = None,
+ on_unmount: EventType[()] | None = None,
+ on_value_change: EventType[()] | EventType[str] | None = None,
+ **props,
+ ) -> FancyWidget:
+ """Create the component.
+
+ Args:
+ *children: The children of the component.
+ border_radius: The border radius.
+ placeholder: Placeholder text.
+ color: The widget color.
+ disabled: Whether the widget is disabled.
+ style: The style of the component.
+ key: A unique key for the component.
+ id: The id for the component.
+ ref: The Var to pass as the ref to the component.
+ class_name: The class name for the component.
+ custom_attrs: Attributes passed directly to the component.
+ on_focus: Fired when the element (or some element inside of it) receives focus. For example, it is called when the user clicks on a text input.
+ on_blur: Fired when focus has left the element (or left some element inside of it). For example, it is called when the user clicks outside of a focused text input.
+ on_click: Fired when the user clicks on an element. For example, it's called when the user clicks on a button.
+ on_context_menu: Fired when the user right-clicks on an element.
+ on_double_click: Fired when the user double-clicks on an element.
+ on_mouse_down: Fired when the user presses a mouse button on an element.
+ on_mouse_enter: Fired when the mouse pointer enters the element.
+ on_mouse_leave: Fired when the mouse pointer leaves the element.
+ on_mouse_move: Fired when the mouse pointer moves over the element.
+ on_mouse_out: Fired when the mouse pointer moves out of the element.
+ on_mouse_over: Fired when the mouse pointer moves onto the element.
+ on_mouse_up: Fired when the user releases a mouse button on an element.
+ on_scroll: Fired when the user scrolls the element.
+ on_scroll_end: Fired when scrolling ends on the element.
+ on_mount: Fired when the component is mounted to the page.
+ on_unmount: Fired when the component is removed from the page. Only called during navigation, not on page refresh.
+ on_value_change: Fired when value changes.
+ **props: The props of the component.
+
+ Returns:
+ The component.
+ """
diff --git a/tests/units/reflex_base/utils/pyi_generator/golden/literal_types.pyi b/tests/units/reflex_base/utils/pyi_generator/golden/literal_types.pyi
new file mode 100644
index 00000000000..e051e7fbb5e
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/golden/literal_types.pyi
@@ -0,0 +1,97 @@
+"""Stub file for """
+
+# ------------------- DO NOT EDIT ----------------------
+# This file was generated by `reflex/utils/pyi_generator.py`!
+# ------------------------------------------------------
+from collections.abc import Mapping, Sequence
+from typing import Any, Literal
+
+from reflex_base.components.component import Component
+from reflex_base.event import EventType, PointerEventInfo
+from reflex_base.vars.base import Var
+from reflex_components_core.core.breakpoints import Breakpoints
+
+LiteralSize = Literal["sm", "md", "lg", "xl"]
+LiteralVariant = Literal["solid", "outline", "ghost"]
+LiteralOrientation = Literal["horizontal", "vertical"]
+
+class ThemedComponent(Component):
+ @classmethod
+ def create(
+ cls,
+ *children,
+ size: Literal["lg", "md", "sm", "xl"]
+ | Var[Literal["lg", "md", "sm", "xl"]]
+ | None = None,
+ variant: Literal["ghost", "outline", "solid"]
+ | Var[Literal["ghost", "outline", "solid"]]
+ | None = None,
+ orientation: Literal["horizontal", "vertical"]
+ | Var[Literal["horizontal", "vertical"]]
+ | None = None,
+ color_scheme: Literal["blue", "green", "red"]
+ | Var[Literal["blue", "green", "red"]]
+ | None = None,
+ style: Sequence[Mapping[str, Any]]
+ | Mapping[str, Any]
+ | Var[Mapping[str, Any]]
+ | Breakpoints
+ | None = None,
+ key: Any | None = None,
+ id: Any | None = None,
+ ref: Var | None = None,
+ class_name: Any | None = None,
+ custom_attrs: dict[str, Any | Var] | None = None,
+ on_blur: EventType[()] | None = None,
+ on_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_focus: EventType[()] | None = None,
+ on_mount: EventType[()] | None = None,
+ on_mouse_down: EventType[()] | None = None,
+ on_mouse_enter: EventType[()] | None = None,
+ on_mouse_leave: EventType[()] | None = None,
+ on_mouse_move: EventType[()] | None = None,
+ on_mouse_out: EventType[()] | None = None,
+ on_mouse_over: EventType[()] | None = None,
+ on_mouse_up: EventType[()] | None = None,
+ on_scroll: EventType[()] | None = None,
+ on_scroll_end: EventType[()] | None = None,
+ on_unmount: EventType[()] | None = None,
+ **props,
+ ) -> ThemedComponent:
+ """Create the component.
+
+ Args:
+ *children: The children of the component.
+ size: Component size.
+ variant: Visual variant.
+ orientation: no description
+ color_scheme: A direct Literal annotation without alias.
+ style: The style of the component.
+ key: A unique key for the component.
+ id: The id for the component.
+ ref: The Var to pass as the ref to the component.
+ class_name: The class name for the component.
+ custom_attrs: Attributes passed directly to the component.
+ on_focus: Fired when the element (or some element inside of it) receives focus. For example, it is called when the user clicks on a text input.
+ on_blur: Fired when focus has left the element (or left some element inside of it). For example, it is called when the user clicks outside of a focused text input.
+ on_click: Fired when the user clicks on an element. For example, it's called when the user clicks on a button.
+ on_context_menu: Fired when the user right-clicks on an element.
+ on_double_click: Fired when the user double-clicks on an element.
+ on_mouse_down: Fired when the user presses a mouse button on an element.
+ on_mouse_enter: Fired when the mouse pointer enters the element.
+ on_mouse_leave: Fired when the mouse pointer leaves the element.
+ on_mouse_move: Fired when the mouse pointer moves over the element.
+ on_mouse_out: Fired when the mouse pointer moves out of the element.
+ on_mouse_over: Fired when the mouse pointer moves onto the element.
+ on_mouse_up: Fired when the user releases a mouse button on an element.
+ on_scroll: Fired when the user scrolls the element.
+ on_scroll_end: Fired when scrolling ends on the element.
+ on_mount: Fired when the component is mounted to the page.
+ on_unmount: Fired when the component is removed from the page. Only called during navigation, not on page refresh.
+ **props: The props of the component.
+
+ Returns:
+ The component.
+ """
diff --git a/tests/units/reflex_base/utils/pyi_generator/golden/module_level.pyi b/tests/units/reflex_base/utils/pyi_generator/golden/module_level.pyi
new file mode 100644
index 00000000000..7f7eb1e048e
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/golden/module_level.pyi
@@ -0,0 +1,90 @@
+"""Stub file for """
+
+# ------------------- DO NOT EDIT ----------------------
+# This file was generated by `reflex/utils/pyi_generator.py`!
+# ------------------------------------------------------
+from collections.abc import Mapping, Sequence
+from typing import Any, Literal
+
+from reflex_base.components.component import Component
+from reflex_base.event import EventType, PointerEventInfo
+from reflex_base.vars.base import Var
+from reflex_components_core.core.breakpoints import Breakpoints
+
+LiteralMode = Literal["light", "dark", "system"]
+DEFAULT_TIMEOUT = 30
+current_mode: LiteralMode
+
+def helper_function(x: int, y: int) -> int: ...
+def another_helper() -> None: ...
+
+class ModuleComponent(Component):
+ @classmethod
+ def create(
+ cls,
+ *children,
+ mode: Literal["dark", "light", "system"]
+ | Var[Literal["dark", "light", "system"]]
+ | None = None,
+ timeout: Var[int] | int | None = None,
+ style: Sequence[Mapping[str, Any]]
+ | Mapping[str, Any]
+ | Var[Mapping[str, Any]]
+ | Breakpoints
+ | None = None,
+ key: Any | None = None,
+ id: Any | None = None,
+ ref: Var | None = None,
+ class_name: Any | None = None,
+ custom_attrs: dict[str, Any | Var] | None = None,
+ on_blur: EventType[()] | None = None,
+ on_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_focus: EventType[()] | None = None,
+ on_mount: EventType[()] | None = None,
+ on_mouse_down: EventType[()] | None = None,
+ on_mouse_enter: EventType[()] | None = None,
+ on_mouse_leave: EventType[()] | None = None,
+ on_mouse_move: EventType[()] | None = None,
+ on_mouse_out: EventType[()] | None = None,
+ on_mouse_over: EventType[()] | None = None,
+ on_mouse_up: EventType[()] | None = None,
+ on_scroll: EventType[()] | None = None,
+ on_scroll_end: EventType[()] | None = None,
+ on_unmount: EventType[()] | None = None,
+ **props,
+ ) -> ModuleComponent:
+ """Create the component.
+
+ Args:
+ *children: The children of the component.
+ mode: The display mode.
+ timeout: Timeout in seconds.
+ style: The style of the component.
+ key: A unique key for the component.
+ id: The id for the component.
+ ref: The Var to pass as the ref to the component.
+ class_name: The class name for the component.
+ custom_attrs: Attributes passed directly to the component.
+ on_focus: Fired when the element (or some element inside of it) receives focus. For example, it is called when the user clicks on a text input.
+ on_blur: Fired when focus has left the element (or left some element inside of it). For example, it is called when the user clicks outside of a focused text input.
+ on_click: Fired when the user clicks on an element. For example, it's called when the user clicks on a button.
+ on_context_menu: Fired when the user right-clicks on an element.
+ on_double_click: Fired when the user double-clicks on an element.
+ on_mouse_down: Fired when the user presses a mouse button on an element.
+ on_mouse_enter: Fired when the mouse pointer enters the element.
+ on_mouse_leave: Fired when the mouse pointer leaves the element.
+ on_mouse_move: Fired when the mouse pointer moves over the element.
+ on_mouse_out: Fired when the mouse pointer moves out of the element.
+ on_mouse_over: Fired when the mouse pointer moves onto the element.
+ on_mouse_up: Fired when the user releases a mouse button on an element.
+ on_scroll: Fired when the user scrolls the element.
+ on_scroll_end: Fired when scrolling ends on the element.
+ on_mount: Fired when the component is mounted to the page.
+ on_unmount: Fired when the component is removed from the page. Only called during navigation, not on page refresh.
+ **props: The props of the component.
+
+ Returns:
+ The component.
+ """
diff --git a/tests/units/reflex_base/utils/pyi_generator/golden/namespace_component.pyi b/tests/units/reflex_base/utils/pyi_generator/golden/namespace_component.pyi
new file mode 100644
index 00000000000..7b34e87efe5
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/golden/namespace_component.pyi
@@ -0,0 +1,285 @@
+"""Stub file for """
+
+# ------------------- DO NOT EDIT ----------------------
+# This file was generated by `reflex/utils/pyi_generator.py`!
+# ------------------------------------------------------
+from collections.abc import Mapping, Sequence
+from typing import Any
+
+from reflex_base.components.component import Component, ComponentNamespace
+from reflex_base.event import EventType, PointerEventInfo
+from reflex_base.vars.base import Var
+from reflex_components_core.core.breakpoints import Breakpoints
+
+class DialogRoot(Component):
+ @classmethod
+ def create(
+ cls,
+ *children,
+ is_open: Var[bool] | bool | None = None,
+ style: Sequence[Mapping[str, Any]]
+ | Mapping[str, Any]
+ | Var[Mapping[str, Any]]
+ | Breakpoints
+ | None = None,
+ key: Any | None = None,
+ id: Any | None = None,
+ ref: Var | None = None,
+ class_name: Any | None = None,
+ custom_attrs: dict[str, Any | Var] | None = None,
+ on_blur: EventType[()] | None = None,
+ on_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_focus: EventType[()] | None = None,
+ on_mount: EventType[()] | None = None,
+ on_mouse_down: EventType[()] | None = None,
+ on_mouse_enter: EventType[()] | None = None,
+ on_mouse_leave: EventType[()] | None = None,
+ on_mouse_move: EventType[()] | None = None,
+ on_mouse_out: EventType[()] | None = None,
+ on_mouse_over: EventType[()] | None = None,
+ on_mouse_up: EventType[()] | None = None,
+ on_scroll: EventType[()] | None = None,
+ on_scroll_end: EventType[()] | None = None,
+ on_unmount: EventType[()] | None = None,
+ **props,
+ ) -> DialogRoot:
+ """Create the component.
+
+ Args:
+ *children: The children of the component.
+ is_open: Whether the dialog is open.
+ style: The style of the component.
+ key: A unique key for the component.
+ id: The id for the component.
+ ref: The Var to pass as the ref to the component.
+ class_name: The class name for the component.
+ custom_attrs: Attributes passed directly to the component.
+ on_focus: Fired when the element (or some element inside of it) receives focus. For example, it is called when the user clicks on a text input.
+ on_blur: Fired when focus has left the element (or left some element inside of it). For example, it is called when the user clicks outside of a focused text input.
+ on_click: Fired when the user clicks on an element. For example, it's called when the user clicks on a button.
+ on_context_menu: Fired when the user right-clicks on an element.
+ on_double_click: Fired when the user double-clicks on an element.
+ on_mouse_down: Fired when the user presses a mouse button on an element.
+ on_mouse_enter: Fired when the mouse pointer enters the element.
+ on_mouse_leave: Fired when the mouse pointer leaves the element.
+ on_mouse_move: Fired when the mouse pointer moves over the element.
+ on_mouse_out: Fired when the mouse pointer moves out of the element.
+ on_mouse_over: Fired when the mouse pointer moves onto the element.
+ on_mouse_up: Fired when the user releases a mouse button on an element.
+ on_scroll: Fired when the user scrolls the element.
+ on_scroll_end: Fired when scrolling ends on the element.
+ on_mount: Fired when the component is mounted to the page.
+ on_unmount: Fired when the component is removed from the page. Only called during navigation, not on page refresh.
+ **props: The props of the component.
+
+ Returns:
+ The component.
+ """
+
+class DialogContent(Component):
+ @classmethod
+ def create(
+ cls,
+ *children,
+ force_mount: Var[bool] | bool | None = None,
+ style: Sequence[Mapping[str, Any]]
+ | Mapping[str, Any]
+ | Var[Mapping[str, Any]]
+ | Breakpoints
+ | None = None,
+ key: Any | None = None,
+ id: Any | None = None,
+ ref: Var | None = None,
+ class_name: Any | None = None,
+ custom_attrs: dict[str, Any | Var] | None = None,
+ on_blur: EventType[()] | None = None,
+ on_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_focus: EventType[()] | None = None,
+ on_mount: EventType[()] | None = None,
+ on_mouse_down: EventType[()] | None = None,
+ on_mouse_enter: EventType[()] | None = None,
+ on_mouse_leave: EventType[()] | None = None,
+ on_mouse_move: EventType[()] | None = None,
+ on_mouse_out: EventType[()] | None = None,
+ on_mouse_over: EventType[()] | None = None,
+ on_mouse_up: EventType[()] | None = None,
+ on_scroll: EventType[()] | None = None,
+ on_scroll_end: EventType[()] | None = None,
+ on_unmount: EventType[()] | None = None,
+ **props,
+ ) -> DialogContent:
+ """Create the component.
+
+ Args:
+ *children: The children of the component.
+ force_mount: Whether to force mount.
+ style: The style of the component.
+ key: A unique key for the component.
+ id: The id for the component.
+ ref: The Var to pass as the ref to the component.
+ class_name: The class name for the component.
+ custom_attrs: Attributes passed directly to the component.
+ on_focus: Fired when the element (or some element inside of it) receives focus. For example, it is called when the user clicks on a text input.
+ on_blur: Fired when focus has left the element (or left some element inside of it). For example, it is called when the user clicks outside of a focused text input.
+ on_click: Fired when the user clicks on an element. For example, it's called when the user clicks on a button.
+ on_context_menu: Fired when the user right-clicks on an element.
+ on_double_click: Fired when the user double-clicks on an element.
+ on_mouse_down: Fired when the user presses a mouse button on an element.
+ on_mouse_enter: Fired when the mouse pointer enters the element.
+ on_mouse_leave: Fired when the mouse pointer leaves the element.
+ on_mouse_move: Fired when the mouse pointer moves over the element.
+ on_mouse_out: Fired when the mouse pointer moves out of the element.
+ on_mouse_over: Fired when the mouse pointer moves onto the element.
+ on_mouse_up: Fired when the user releases a mouse button on an element.
+ on_scroll: Fired when the user scrolls the element.
+ on_scroll_end: Fired when scrolling ends on the element.
+ on_mount: Fired when the component is mounted to the page.
+ on_unmount: Fired when the component is removed from the page. Only called during navigation, not on page refresh.
+ **props: The props of the component.
+
+ Returns:
+ The component.
+ """
+
+class DialogTitle(Component):
+ @classmethod
+ def create(
+ cls,
+ *children,
+ title_text: Var[str] | str | None = None,
+ style: Sequence[Mapping[str, Any]]
+ | Mapping[str, Any]
+ | Var[Mapping[str, Any]]
+ | Breakpoints
+ | None = None,
+ key: Any | None = None,
+ id: Any | None = None,
+ ref: Var | None = None,
+ class_name: Any | None = None,
+ custom_attrs: dict[str, Any | Var] | None = None,
+ on_blur: EventType[()] | None = None,
+ on_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_focus: EventType[()] | None = None,
+ on_mount: EventType[()] | None = None,
+ on_mouse_down: EventType[()] | None = None,
+ on_mouse_enter: EventType[()] | None = None,
+ on_mouse_leave: EventType[()] | None = None,
+ on_mouse_move: EventType[()] | None = None,
+ on_mouse_out: EventType[()] | None = None,
+ on_mouse_over: EventType[()] | None = None,
+ on_mouse_up: EventType[()] | None = None,
+ on_scroll: EventType[()] | None = None,
+ on_scroll_end: EventType[()] | None = None,
+ on_unmount: EventType[()] | None = None,
+ **props,
+ ) -> DialogTitle:
+ """Create the component.
+
+ Args:
+ *children: The children of the component.
+ title_text: The title text.
+ style: The style of the component.
+ key: A unique key for the component.
+ id: The id for the component.
+ ref: The Var to pass as the ref to the component.
+ class_name: The class name for the component.
+ custom_attrs: Attributes passed directly to the component.
+ on_focus: Fired when the element (or some element inside of it) receives focus. For example, it is called when the user clicks on a text input.
+ on_blur: Fired when focus has left the element (or left some element inside of it). For example, it is called when the user clicks outside of a focused text input.
+ on_click: Fired when the user clicks on an element. For example, it's called when the user clicks on a button.
+ on_context_menu: Fired when the user right-clicks on an element.
+ on_double_click: Fired when the user double-clicks on an element.
+ on_mouse_down: Fired when the user presses a mouse button on an element.
+ on_mouse_enter: Fired when the mouse pointer enters the element.
+ on_mouse_leave: Fired when the mouse pointer leaves the element.
+ on_mouse_move: Fired when the mouse pointer moves over the element.
+ on_mouse_out: Fired when the mouse pointer moves out of the element.
+ on_mouse_over: Fired when the mouse pointer moves onto the element.
+ on_mouse_up: Fired when the user releases a mouse button on an element.
+ on_scroll: Fired when the user scrolls the element.
+ on_scroll_end: Fired when scrolling ends on the element.
+ on_mount: Fired when the component is mounted to the page.
+ on_unmount: Fired when the component is removed from the page. Only called during navigation, not on page refresh.
+ **props: The props of the component.
+
+ Returns:
+ The component.
+ """
+
+class Dialog(ComponentNamespace):
+ root = staticmethod(DialogRoot.create)
+ content = staticmethod(DialogContent.create)
+ title = staticmethod(DialogTitle.create)
+
+ @staticmethod
+ def __call__(
+ *children,
+ is_open: Var[bool] | bool | None = None,
+ style: Sequence[Mapping[str, Any]]
+ | Mapping[str, Any]
+ | Var[Mapping[str, Any]]
+ | Breakpoints
+ | None = None,
+ key: Any | None = None,
+ id: Any | None = None,
+ ref: Var | None = None,
+ class_name: Any | None = None,
+ custom_attrs: dict[str, Any | Var] | None = None,
+ on_blur: EventType[()] | None = None,
+ on_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_focus: EventType[()] | None = None,
+ on_mount: EventType[()] | None = None,
+ on_mouse_down: EventType[()] | None = None,
+ on_mouse_enter: EventType[()] | None = None,
+ on_mouse_leave: EventType[()] | None = None,
+ on_mouse_move: EventType[()] | None = None,
+ on_mouse_out: EventType[()] | None = None,
+ on_mouse_over: EventType[()] | None = None,
+ on_mouse_up: EventType[()] | None = None,
+ on_scroll: EventType[()] | None = None,
+ on_scroll_end: EventType[()] | None = None,
+ on_unmount: EventType[()] | None = None,
+ **props,
+ ) -> DialogRoot:
+ """Create the component.
+
+ Args:
+ *children: The children of the component.
+ is_open: Whether the dialog is open.
+ style: The style of the component.
+ key: A unique key for the component.
+ id: The id for the component.
+ ref: The Var to pass as the ref to the component.
+ class_name: The class name for the component.
+ custom_attrs: Attributes passed directly to the component.
+ on_focus: Fired when the element (or some element inside of it) receives focus. For example, it is called when the user clicks on a text input.
+ on_blur: Fired when focus has left the element (or left some element inside of it). For example, it is called when the user clicks outside of a focused text input.
+ on_click: Fired when the user clicks on an element. For example, it's called when the user clicks on a button.
+ on_context_menu: Fired when the user right-clicks on an element.
+ on_double_click: Fired when the user double-clicks on an element.
+ on_mouse_down: Fired when the user presses a mouse button on an element.
+ on_mouse_enter: Fired when the mouse pointer enters the element.
+ on_mouse_leave: Fired when the mouse pointer leaves the element.
+ on_mouse_move: Fired when the mouse pointer moves over the element.
+ on_mouse_out: Fired when the mouse pointer moves out of the element.
+ on_mouse_over: Fired when the mouse pointer moves onto the element.
+ on_mouse_up: Fired when the user releases a mouse button on an element.
+ on_scroll: Fired when the user scrolls the element.
+ on_scroll_end: Fired when scrolling ends on the element.
+ on_mount: Fired when the component is mounted to the page.
+ on_unmount: Fired when the component is removed from the page. Only called during navigation, not on page refresh.
+ **props: The props of the component.
+
+ Returns:
+ The component.
+ """
+
+dialog = Dialog()
diff --git a/tests/units/reflex_base/utils/pyi_generator/golden/simple_component.pyi b/tests/units/reflex_base/utils/pyi_generator/golden/simple_component.pyi
new file mode 100644
index 00000000000..cc88208502c
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/golden/simple_component.pyi
@@ -0,0 +1,91 @@
+"""Stub file for """
+
+# ------------------- DO NOT EDIT ----------------------
+# This file was generated by `reflex/utils/pyi_generator.py`!
+# ------------------------------------------------------
+from collections.abc import Mapping, Sequence
+from typing import Any
+
+from reflex_base.components.component import Component
+from reflex_base.event import EventType, PointerEventInfo
+from reflex_base.vars.base import Var
+from reflex_components_core.core.breakpoints import Breakpoints
+
+SomeType = Any
+SOME_CONSTANT = 42
+
+class SimpleComponent(Component):
+ def public_helper(self) -> str: ...
+ @classmethod
+ def create(
+ cls,
+ *children,
+ title: Var[str] | str | None = None,
+ count: Var[int] | int | None = None,
+ is_active: Var[bool] | bool | None = None,
+ opacity: Var[float] | float | None = None,
+ label: Var[str] | str | None = None,
+ style: Sequence[Mapping[str, Any]]
+ | Mapping[str, Any]
+ | Var[Mapping[str, Any]]
+ | Breakpoints
+ | None = None,
+ key: Any | None = None,
+ id: Any | None = None,
+ ref: Var | None = None,
+ class_name: Any | None = None,
+ custom_attrs: dict[str, Any | Var] | None = None,
+ on_blur: EventType[()] | None = None,
+ on_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_focus: EventType[()] | None = None,
+ on_mount: EventType[()] | None = None,
+ on_mouse_down: EventType[()] | None = None,
+ on_mouse_enter: EventType[()] | None = None,
+ on_mouse_leave: EventType[()] | None = None,
+ on_mouse_move: EventType[()] | None = None,
+ on_mouse_out: EventType[()] | None = None,
+ on_mouse_over: EventType[()] | None = None,
+ on_mouse_up: EventType[()] | None = None,
+ on_scroll: EventType[()] | None = None,
+ on_scroll_end: EventType[()] | None = None,
+ on_unmount: EventType[()] | None = None,
+ **props,
+ ) -> SimpleComponent:
+ """Create the component.
+
+ Args:
+ *children: The children of the component.
+ title: The title displayed on the component.
+ count: The count to display.
+ is_active: Whether the component is active.
+ opacity: The opacity of the component.
+ label: An optional label with a default value.
+ style: The style of the component.
+ key: A unique key for the component.
+ id: The id for the component.
+ ref: The Var to pass as the ref to the component.
+ class_name: The class name for the component.
+ custom_attrs: Attributes passed directly to the component.
+ on_focus: Fired when the element (or some element inside of it) receives focus. For example, it is called when the user clicks on a text input.
+ on_blur: Fired when focus has left the element (or left some element inside of it). For example, it is called when the user clicks outside of a focused text input.
+ on_click: Fired when the user clicks on an element. For example, it's called when the user clicks on a button.
+ on_context_menu: Fired when the user right-clicks on an element.
+ on_double_click: Fired when the user double-clicks on an element.
+ on_mouse_down: Fired when the user presses a mouse button on an element.
+ on_mouse_enter: Fired when the mouse pointer enters the element.
+ on_mouse_leave: Fired when the mouse pointer leaves the element.
+ on_mouse_move: Fired when the mouse pointer moves over the element.
+ on_mouse_out: Fired when the mouse pointer moves out of the element.
+ on_mouse_over: Fired when the mouse pointer moves onto the element.
+ on_mouse_up: Fired when the user releases a mouse button on an element.
+ on_scroll: Fired when the user scrolls the element.
+ on_scroll_end: Fired when scrolling ends on the element.
+ on_mount: Fired when the component is mounted to the page.
+ on_unmount: Fired when the component is removed from the page. Only called during navigation, not on page refresh.
+ **props: The props of the component.
+
+ Returns:
+ The component.
+ """
diff --git a/tests/units/reflex_base/utils/pyi_generator/golden/staticmethod_namespace.pyi b/tests/units/reflex_base/utils/pyi_generator/golden/staticmethod_namespace.pyi
new file mode 100644
index 00000000000..22d04a776f6
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/golden/staticmethod_namespace.pyi
@@ -0,0 +1,100 @@
+"""Stub file for """
+
+# ------------------- DO NOT EDIT ----------------------
+# This file was generated by `reflex/utils/pyi_generator.py`!
+# ------------------------------------------------------
+from collections.abc import Mapping, Sequence
+from typing import Any
+
+from reflex_base.components.component import Component, ComponentNamespace
+from reflex_base.event import EventSpec, EventType, PointerEventInfo
+from reflex_base.vars.base import Var
+from reflex_components_core.core.breakpoints import Breakpoints
+
+class NotifyComponent(Component):
+ @classmethod
+ def create(
+ cls,
+ *children,
+ message: Var[str] | str | None = None,
+ level: Var[str] | str | None = None,
+ style: Sequence[Mapping[str, Any]]
+ | Mapping[str, Any]
+ | Var[Mapping[str, Any]]
+ | Breakpoints
+ | None = None,
+ key: Any | None = None,
+ id: Any | None = None,
+ ref: Var | None = None,
+ class_name: Any | None = None,
+ custom_attrs: dict[str, Any | Var] | None = None,
+ on_blur: EventType[()] | None = None,
+ on_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_focus: EventType[()] | None = None,
+ on_mount: EventType[()] | None = None,
+ on_mouse_down: EventType[()] | None = None,
+ on_mouse_enter: EventType[()] | None = None,
+ on_mouse_leave: EventType[()] | None = None,
+ on_mouse_move: EventType[()] | None = None,
+ on_mouse_out: EventType[()] | None = None,
+ on_mouse_over: EventType[()] | None = None,
+ on_mouse_up: EventType[()] | None = None,
+ on_scroll: EventType[()] | None = None,
+ on_scroll_end: EventType[()] | None = None,
+ on_unmount: EventType[()] | None = None,
+ **props,
+ ) -> NotifyComponent:
+ """Create the component.
+
+ Args:
+ *children: The children of the component.
+ message: The notification message.
+ level: The notification level.
+ style: The style of the component.
+ key: A unique key for the component.
+ id: The id for the component.
+ ref: The Var to pass as the ref to the component.
+ class_name: The class name for the component.
+ custom_attrs: Attributes passed directly to the component.
+ on_focus: Fired when the element (or some element inside of it) receives focus. For example, it is called when the user clicks on a text input.
+ on_blur: Fired when focus has left the element (or left some element inside of it). For example, it is called when the user clicks outside of a focused text input.
+ on_click: Fired when the user clicks on an element. For example, it's called when the user clicks on a button.
+ on_context_menu: Fired when the user right-clicks on an element.
+ on_double_click: Fired when the user double-clicks on an element.
+ on_mouse_down: Fired when the user presses a mouse button on an element.
+ on_mouse_enter: Fired when the mouse pointer enters the element.
+ on_mouse_leave: Fired when the mouse pointer leaves the element.
+ on_mouse_move: Fired when the mouse pointer moves over the element.
+ on_mouse_out: Fired when the mouse pointer moves out of the element.
+ on_mouse_over: Fired when the mouse pointer moves onto the element.
+ on_mouse_up: Fired when the user releases a mouse button on an element.
+ on_scroll: Fired when the user scrolls the element.
+ on_scroll_end: Fired when scrolling ends on the element.
+ on_mount: Fired when the component is mounted to the page.
+ on_unmount: Fired when the component is removed from the page. Only called during navigation, not on page refresh.
+ **props: The props of the component.
+
+ Returns:
+ The component.
+ """
+
+def send_notification(message: str, level: str = "info") -> EventSpec: ...
+
+class Notify(ComponentNamespace):
+ component = staticmethod(NotifyComponent.create)
+
+ @staticmethod
+ def __call__(message: str, level: str = "info", **props) -> EventSpec:
+ """Send a notification event.
+
+ Args:
+ message: The message to send.
+ level: The notification level.
+
+ Returns:
+ The event spec.
+ """
+
+notify = Notify()
diff --git a/tests/units/reflex_base/utils/pyi_generator/golden/string_event_annotations.pyi b/tests/units/reflex_base/utils/pyi_generator/golden/string_event_annotations.pyi
new file mode 100644
index 00000000000..af628c6d27f
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/golden/string_event_annotations.pyi
@@ -0,0 +1,89 @@
+"""Stub file for """
+
+# ------------------- DO NOT EDIT ----------------------
+# This file was generated by `reflex/utils/pyi_generator.py`!
+# ------------------------------------------------------
+from collections.abc import Mapping, Sequence
+from typing import Any
+
+from reflex_base.components.component import Component
+from reflex_base.event import EventType, PointerEventInfo
+from reflex_base.vars.base import Var
+from reflex_components_core.core.breakpoints import Breakpoints
+
+def on_empty_handler() -> tuple[()]: ...
+def on_string_handler(value: Var[str]) -> tuple[Var[str]]: ...
+def on_multi_handler(name: Var[str], age: Var[int]) -> tuple[Var[str], Var[int]]: ...
+
+class StringAnnotationComponent(Component):
+ @classmethod
+ def create(
+ cls,
+ *children,
+ value: Var[str] | str | None = None,
+ style: Sequence[Mapping[str, Any]]
+ | Mapping[str, Any]
+ | Var[Mapping[str, Any]]
+ | Breakpoints
+ | None = None,
+ key: Any | None = None,
+ id: Any | None = None,
+ ref: Var | None = None,
+ class_name: Any | None = None,
+ custom_attrs: dict[str, Any | Var] | None = None,
+ on_blur: EventType[()] | None = None,
+ on_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_empty: EventType[()] | None = None,
+ on_focus: EventType[()] | None = None,
+ on_mount: EventType[()] | None = None,
+ on_mouse_down: EventType[()] | None = None,
+ on_mouse_enter: EventType[()] | None = None,
+ on_mouse_leave: EventType[()] | None = None,
+ on_mouse_move: EventType[()] | None = None,
+ on_mouse_out: EventType[()] | None = None,
+ on_mouse_over: EventType[()] | None = None,
+ on_mouse_up: EventType[()] | None = None,
+ on_multi: EventType[()] | EventType[str] | EventType[str, int] | None = None,
+ on_scroll: EventType[()] | None = None,
+ on_scroll_end: EventType[()] | None = None,
+ on_string: EventType[()] | EventType[str] | None = None,
+ on_unmount: EventType[()] | None = None,
+ **props,
+ ) -> StringAnnotationComponent:
+ """Create the component.
+
+ Args:
+ *children: The children of the component.
+ value: no description
+ style: The style of the component.
+ key: A unique key for the component.
+ id: The id for the component.
+ ref: The Var to pass as the ref to the component.
+ class_name: The class name for the component.
+ custom_attrs: Attributes passed directly to the component.
+ on_focus: Fired when the element (or some element inside of it) receives focus. For example, it is called when the user clicks on a text input.
+ on_blur: Fired when focus has left the element (or left some element inside of it). For example, it is called when the user clicks outside of a focused text input.
+ on_click: Fired when the user clicks on an element. For example, it's called when the user clicks on a button.
+ on_context_menu: Fired when the user right-clicks on an element.
+ on_double_click: Fired when the user double-clicks on an element.
+ on_mouse_down: Fired when the user presses a mouse button on an element.
+ on_mouse_enter: Fired when the mouse pointer enters the element.
+ on_mouse_leave: Fired when the mouse pointer leaves the element.
+ on_mouse_move: Fired when the mouse pointer moves over the element.
+ on_mouse_out: Fired when the mouse pointer moves out of the element.
+ on_mouse_over: Fired when the mouse pointer moves onto the element.
+ on_mouse_up: Fired when the user releases a mouse button on an element.
+ on_scroll: Fired when the user scrolls the element.
+ on_scroll_end: Fired when scrolling ends on the element.
+ on_mount: Fired when the component is mounted to the page.
+ on_unmount: Fired when the component is removed from the page. Only called during navigation, not on page refresh.
+ on_empty: Fires with no args.
+ on_string: Fires with a string.
+ on_multi: Fires with name and age.
+ **props: The props of the component.
+
+ Returns:
+ The component.
+ """
diff --git a/tests/units/reflex_base/utils/pyi_generator/golden/sub_package/__init__.pyi b/tests/units/reflex_base/utils/pyi_generator/golden/sub_package/__init__.pyi
new file mode 100644
index 00000000000..9fb215635e5
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/golden/sub_package/__init__.pyi
@@ -0,0 +1,8 @@
+"""Stub file for """
+# ------------------- DO NOT EDIT ----------------------
+# This file was generated by `reflex/utils/pyi_generator.py`!
+# ------------------------------------------------------
+
+from .widget import SubWidget
+
+__all__ = ["SubWidget"]
diff --git a/tests/units/reflex_base/utils/pyi_generator/golden/sub_package/widget.pyi b/tests/units/reflex_base/utils/pyi_generator/golden/sub_package/widget.pyi
new file mode 100644
index 00000000000..d81d2740e06
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/golden/sub_package/widget.pyi
@@ -0,0 +1,79 @@
+"""Stub file for """
+
+# ------------------- DO NOT EDIT ----------------------
+# This file was generated by `reflex/utils/pyi_generator.py`!
+# ------------------------------------------------------
+from collections.abc import Mapping, Sequence
+from typing import Any
+
+from reflex_base.components.component import Component
+from reflex_base.event import EventType, PointerEventInfo
+from reflex_base.vars.base import Var
+from reflex_components_core.core.breakpoints import Breakpoints
+
+class SubWidget(Component):
+ @classmethod
+ def create(
+ cls,
+ *children,
+ name: Var[str] | str | None = None,
+ style: Sequence[Mapping[str, Any]]
+ | Mapping[str, Any]
+ | Var[Mapping[str, Any]]
+ | Breakpoints
+ | None = None,
+ key: Any | None = None,
+ id: Any | None = None,
+ ref: Var | None = None,
+ class_name: Any | None = None,
+ custom_attrs: dict[str, Any | Var] | None = None,
+ on_blur: EventType[()] | None = None,
+ on_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_focus: EventType[()] | None = None,
+ on_mount: EventType[()] | None = None,
+ on_mouse_down: EventType[()] | None = None,
+ on_mouse_enter: EventType[()] | None = None,
+ on_mouse_leave: EventType[()] | None = None,
+ on_mouse_move: EventType[()] | None = None,
+ on_mouse_out: EventType[()] | None = None,
+ on_mouse_over: EventType[()] | None = None,
+ on_mouse_up: EventType[()] | None = None,
+ on_scroll: EventType[()] | None = None,
+ on_scroll_end: EventType[()] | None = None,
+ on_unmount: EventType[()] | None = None,
+ **props,
+ ) -> SubWidget:
+ """Create the component.
+
+ Args:
+ *children: The children of the component.
+ name: Widget name.
+ style: The style of the component.
+ key: A unique key for the component.
+ id: The id for the component.
+ ref: The Var to pass as the ref to the component.
+ class_name: The class name for the component.
+ custom_attrs: Attributes passed directly to the component.
+ on_focus: Fired when the element (or some element inside of it) receives focus. For example, it is called when the user clicks on a text input.
+ on_blur: Fired when focus has left the element (or left some element inside of it). For example, it is called when the user clicks outside of a focused text input.
+ on_click: Fired when the user clicks on an element. For example, it's called when the user clicks on a button.
+ on_context_menu: Fired when the user right-clicks on an element.
+ on_double_click: Fired when the user double-clicks on an element.
+ on_mouse_down: Fired when the user presses a mouse button on an element.
+ on_mouse_enter: Fired when the mouse pointer enters the element.
+ on_mouse_leave: Fired when the mouse pointer leaves the element.
+ on_mouse_move: Fired when the mouse pointer moves over the element.
+ on_mouse_out: Fired when the mouse pointer moves out of the element.
+ on_mouse_over: Fired when the mouse pointer moves onto the element.
+ on_mouse_up: Fired when the user releases a mouse button on an element.
+ on_scroll: Fired when the user scrolls the element.
+ on_scroll_end: Fired when scrolling ends on the element.
+ on_mount: Fired when the component is mounted to the page.
+ on_unmount: Fired when the component is removed from the page. Only called during navigation, not on page refresh.
+ **props: The props of the component.
+
+ Returns:
+ The component.
+ """
diff --git a/tests/units/reflex_base/utils/pyi_generator/golden/typed_event_handlers.pyi b/tests/units/reflex_base/utils/pyi_generator/golden/typed_event_handlers.pyi
new file mode 100644
index 00000000000..2ef4b8a677a
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/golden/typed_event_handlers.pyi
@@ -0,0 +1,161 @@
+"""Stub file for """
+
+# ------------------- DO NOT EDIT ----------------------
+# This file was generated by `reflex/utils/pyi_generator.py`!
+# ------------------------------------------------------
+from collections.abc import Mapping, Sequence
+from typing import Any
+
+from reflex_base.components.component import Component
+from reflex_base.event import EventType, PointerEventInfo
+from reflex_base.vars.base import Var
+from reflex_components_core.core.breakpoints import Breakpoints
+
+def on_value_change_handler(value: Var[str]) -> tuple[Var[str]]: ...
+def on_pair_change_handler(
+ key: Var[str], value: Var[int]
+) -> tuple[Var[str], Var[int]]: ...
+
+class EventComponent(Component):
+ @classmethod
+ def create(
+ cls,
+ *children,
+ value: Var[str] | str | None = None,
+ style: Sequence[Mapping[str, Any]]
+ | Mapping[str, Any]
+ | Var[Mapping[str, Any]]
+ | Breakpoints
+ | None = None,
+ key: Any | None = None,
+ id: Any | None = None,
+ ref: Var | None = None,
+ class_name: Any | None = None,
+ custom_attrs: dict[str, Any | Var] | None = None,
+ on_blur: EventType[()] | None = None,
+ on_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_focus: EventType[()] | None = None,
+ on_item_select: EventType[()] | EventType[str] | None = None,
+ on_mount: EventType[()] | None = None,
+ on_mouse_down: EventType[()] | None = None,
+ on_mouse_enter: EventType[()] | None = None,
+ on_mouse_leave: EventType[()] | None = None,
+ on_mouse_move: EventType[()] | None = None,
+ on_mouse_out: EventType[()] | None = None,
+ on_mouse_over: EventType[()] | None = None,
+ on_mouse_up: EventType[()] | None = None,
+ on_pair_change: EventType[()] | EventType[str] | EventType[str, int] | None = None,
+ on_range_change: EventType[()] | EventType[int] | EventType[int, int] | None = None,
+ on_scroll: EventType[()] | None = None,
+ on_scroll_end: EventType[()] | None = None,
+ on_unmount: EventType[()] | None = None,
+ on_value_change: EventType[()] | EventType[str] | None = None,
+ **props,
+ ) -> EventComponent:
+ """Create the component.
+
+ Args:
+ *children: The children of the component.
+ value: A simple string value prop.
+ style: The style of the component.
+ key: A unique key for the component.
+ id: The id for the component.
+ ref: The Var to pass as the ref to the component.
+ class_name: The class name for the component.
+ custom_attrs: Attributes passed directly to the component.
+ on_focus: Fired when the element (or some element inside of it) receives focus. For example, it is called when the user clicks on a text input.
+ on_blur: Fired when focus has left the element (or left some element inside of it). For example, it is called when the user clicks outside of a focused text input.
+ on_click: Fired when the user clicks on an element. For example, it's called when the user clicks on a button.
+ on_context_menu: Fired when the user right-clicks on an element.
+ on_double_click: Fired when the user double-clicks on an element.
+ on_mouse_down: Fired when the user presses a mouse button on an element.
+ on_mouse_enter: Fired when the mouse pointer enters the element.
+ on_mouse_leave: Fired when the mouse pointer leaves the element.
+ on_mouse_move: Fired when the mouse pointer moves over the element.
+ on_mouse_out: Fired when the mouse pointer moves out of the element.
+ on_mouse_over: Fired when the mouse pointer moves onto the element.
+ on_mouse_up: Fired when the user releases a mouse button on an element.
+ on_scroll: Fired when the user scrolls the element.
+ on_scroll_end: Fired when scrolling ends on the element.
+ on_mount: Fired when the component is mounted to the page.
+ on_unmount: Fired when the component is removed from the page. Only called during navigation, not on page refresh.
+ on_value_change: Fired when the value changes.
+ on_pair_change: Fired when a key-value pair changes.
+ on_item_select: Fired when an item is selected.
+ on_range_change: Fired when the range changes.
+ **props: The props of the component.
+
+ Returns:
+ The component.
+ """
+
+class MultiSpecComponent(Component):
+ @classmethod
+ def create(
+ cls,
+ *children,
+ value: Var[str] | str | None = None,
+ style: Sequence[Mapping[str, Any]]
+ | Mapping[str, Any]
+ | Var[Mapping[str, Any]]
+ | Breakpoints
+ | None = None,
+ key: Any | None = None,
+ id: Any | None = None,
+ ref: Var | None = None,
+ class_name: Any | None = None,
+ custom_attrs: dict[str, Any | Var] | None = None,
+ on_blur: EventType[()] | None = None,
+ on_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_focus: EventType[()] | None = None,
+ on_mount: EventType[()] | None = None,
+ on_mouse_down: EventType[()] | None = None,
+ on_mouse_enter: EventType[()] | None = None,
+ on_mouse_leave: EventType[()] | None = None,
+ on_mouse_move: EventType[()] | None = None,
+ on_mouse_out: EventType[()] | None = None,
+ on_mouse_over: EventType[()] | None = None,
+ on_mouse_up: EventType[()] | None = None,
+ on_open_change: EventType[()] | EventType[bool] | None = None,
+ on_scroll: EventType[()] | None = None,
+ on_scroll_end: EventType[()] | None = None,
+ on_unmount: EventType[()] | None = None,
+ **props,
+ ) -> MultiSpecComponent:
+ """Create the component.
+
+ Args:
+ *children: The children of the component.
+ value: no description
+ style: The style of the component.
+ key: A unique key for the component.
+ id: The id for the component.
+ ref: The Var to pass as the ref to the component.
+ class_name: The class name for the component.
+ custom_attrs: Attributes passed directly to the component.
+ on_focus: Fired when the element (or some element inside of it) receives focus. For example, it is called when the user clicks on a text input.
+ on_blur: Fired when focus has left the element (or left some element inside of it). For example, it is called when the user clicks outside of a focused text input.
+ on_click: Fired when the user clicks on an element. For example, it's called when the user clicks on a button.
+ on_context_menu: Fired when the user right-clicks on an element.
+ on_double_click: Fired when the user double-clicks on an element.
+ on_mouse_down: Fired when the user presses a mouse button on an element.
+ on_mouse_enter: Fired when the mouse pointer enters the element.
+ on_mouse_leave: Fired when the mouse pointer leaves the element.
+ on_mouse_move: Fired when the mouse pointer moves over the element.
+ on_mouse_out: Fired when the mouse pointer moves out of the element.
+ on_mouse_over: Fired when the mouse pointer moves onto the element.
+ on_mouse_up: Fired when the user releases a mouse button on an element.
+ on_scroll: Fired when the user scrolls the element.
+ on_scroll_end: Fired when scrolling ends on the element.
+ on_mount: Fired when the component is mounted to the page.
+ on_unmount: Fired when the component is removed from the page. Only called during navigation, not on page refresh.
+ on_open_change: Fired when the open state changes.
+ **props: The props of the component.
+
+ Returns:
+ The component.
+ """
diff --git a/tests/units/reflex_base/utils/pyi_generator/golden/var_types.pyi b/tests/units/reflex_base/utils/pyi_generator/golden/var_types.pyi
new file mode 100644
index 00000000000..f8a98a19ce3
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/golden/var_types.pyi
@@ -0,0 +1,225 @@
+"""Stub file for """
+
+# ------------------- DO NOT EDIT ----------------------
+# This file was generated by `reflex/utils/pyi_generator.py`!
+# ------------------------------------------------------
+from collections.abc import Mapping, Sequence
+from typing import Any
+
+from reflex_base.components.component import Component
+from reflex_base.event import EventType, PointerEventInfo
+from reflex_base.vars.base import Var
+from reflex_components_core.core.breakpoints import Breakpoints
+
+class EmptyComponent(Component):
+ @classmethod
+ def create(
+ cls,
+ *children,
+ style: Sequence[Mapping[str, Any]]
+ | Mapping[str, Any]
+ | Var[Mapping[str, Any]]
+ | Breakpoints
+ | None = None,
+ key: Any | None = None,
+ id: Any | None = None,
+ ref: Var | None = None,
+ class_name: Any | None = None,
+ custom_attrs: dict[str, Any | Var] | None = None,
+ on_blur: EventType[()] | None = None,
+ on_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_focus: EventType[()] | None = None,
+ on_mount: EventType[()] | None = None,
+ on_mouse_down: EventType[()] | None = None,
+ on_mouse_enter: EventType[()] | None = None,
+ on_mouse_leave: EventType[()] | None = None,
+ on_mouse_move: EventType[()] | None = None,
+ on_mouse_out: EventType[()] | None = None,
+ on_mouse_over: EventType[()] | None = None,
+ on_mouse_up: EventType[()] | None = None,
+ on_scroll: EventType[()] | None = None,
+ on_scroll_end: EventType[()] | None = None,
+ on_unmount: EventType[()] | None = None,
+ **props,
+ ) -> EmptyComponent:
+ """Create the component.
+
+ Args:
+ *children: The children of the component.
+ style: The style of the component.
+ key: A unique key for the component.
+ id: The id for the component.
+ ref: The Var to pass as the ref to the component.
+ class_name: The class name for the component.
+ custom_attrs: Attributes passed directly to the component.
+ on_focus: Fired when the element (or some element inside of it) receives focus. For example, it is called when the user clicks on a text input.
+ on_blur: Fired when focus has left the element (or left some element inside of it). For example, it is called when the user clicks outside of a focused text input.
+ on_click: Fired when the user clicks on an element. For example, it's called when the user clicks on a button.
+ on_context_menu: Fired when the user right-clicks on an element.
+ on_double_click: Fired when the user double-clicks on an element.
+ on_mouse_down: Fired when the user presses a mouse button on an element.
+ on_mouse_enter: Fired when the mouse pointer enters the element.
+ on_mouse_leave: Fired when the mouse pointer leaves the element.
+ on_mouse_move: Fired when the mouse pointer moves over the element.
+ on_mouse_out: Fired when the mouse pointer moves out of the element.
+ on_mouse_over: Fired when the mouse pointer moves onto the element.
+ on_mouse_up: Fired when the user releases a mouse button on an element.
+ on_scroll: Fired when the user scrolls the element.
+ on_scroll_end: Fired when scrolling ends on the element.
+ on_mount: Fired when the component is mounted to the page.
+ on_unmount: Fired when the component is removed from the page. Only called during navigation, not on page refresh.
+ **props: The props of the component.
+
+ Returns:
+ The component.
+ """
+
+class EventOnlyComponent(Component):
+ @classmethod
+ def create(
+ cls,
+ *children,
+ style: Sequence[Mapping[str, Any]]
+ | Mapping[str, Any]
+ | Var[Mapping[str, Any]]
+ | Breakpoints
+ | None = None,
+ key: Any | None = None,
+ id: Any | None = None,
+ ref: Var | None = None,
+ class_name: Any | None = None,
+ custom_attrs: dict[str, Any | Var] | None = None,
+ on_blur: EventType[()] | None = None,
+ on_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_focus: EventType[()] | None = None,
+ on_mount: EventType[()] | None = None,
+ on_mouse_down: EventType[()] | None = None,
+ on_mouse_enter: EventType[()] | None = None,
+ on_mouse_leave: EventType[()] | None = None,
+ on_mouse_move: EventType[()] | None = None,
+ on_mouse_out: EventType[()] | None = None,
+ on_mouse_over: EventType[()] | None = None,
+ on_mouse_up: EventType[()] | None = None,
+ on_scroll: EventType[()] | None = None,
+ on_scroll_end: EventType[()] | None = None,
+ on_toggle: EventType[()] | EventType[bool] | None = None,
+ on_unmount: EventType[()] | None = None,
+ **props,
+ ) -> EventOnlyComponent:
+ """Create the component.
+
+ Args:
+ *children: The children of the component.
+ style: The style of the component.
+ key: A unique key for the component.
+ id: The id for the component.
+ ref: The Var to pass as the ref to the component.
+ class_name: The class name for the component.
+ custom_attrs: Attributes passed directly to the component.
+ on_focus: Fired when the element (or some element inside of it) receives focus. For example, it is called when the user clicks on a text input.
+ on_blur: Fired when focus has left the element (or left some element inside of it). For example, it is called when the user clicks outside of a focused text input.
+ on_click: Fired when the user clicks on an element. For example, it's called when the user clicks on a button.
+ on_context_menu: Fired when the user right-clicks on an element.
+ on_double_click: Fired when the user double-clicks on an element.
+ on_mouse_down: Fired when the user presses a mouse button on an element.
+ on_mouse_enter: Fired when the mouse pointer enters the element.
+ on_mouse_leave: Fired when the mouse pointer leaves the element.
+ on_mouse_move: Fired when the mouse pointer moves over the element.
+ on_mouse_out: Fired when the mouse pointer moves out of the element.
+ on_mouse_over: Fired when the mouse pointer moves onto the element.
+ on_mouse_up: Fired when the user releases a mouse button on an element.
+ on_scroll: Fired when the user scrolls the element.
+ on_scroll_end: Fired when scrolling ends on the element.
+ on_mount: Fired when the component is mounted to the page.
+ on_unmount: Fired when the component is removed from the page. Only called during navigation, not on page refresh.
+ on_toggle: Fired when toggled.
+ **props: The props of the component.
+
+ Returns:
+ The component.
+ """
+
+class VarTypesComponent(Component):
+ @classmethod
+ def create(
+ cls,
+ *children,
+ name: Var[str] | str | None = None,
+ count: Var[int] | int | None = None,
+ ratio: Var[float] | float | None = None,
+ flag: Var[bool] | bool | None = None,
+ value: Var[int | str] | int | str | None = None,
+ items: Var[list[str]] | list[str] | None = None,
+ metadata: Var[dict[str, Any]] | dict[str, Any] | None = None,
+ nested: Var[list[dict[str, Any]]] | list[dict[str, Any]] | None = None,
+ style: Sequence[Mapping[str, Any]]
+ | Mapping[str, Any]
+ | Var[Mapping[str, Any]]
+ | Breakpoints
+ | None = None,
+ key: Any | None = None,
+ id: Any | None = None,
+ ref: Var | None = None,
+ class_name: Any | None = None,
+ custom_attrs: dict[str, Any | Var] | None = None,
+ on_blur: EventType[()] | None = None,
+ on_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
+ on_focus: EventType[()] | None = None,
+ on_mount: EventType[()] | None = None,
+ on_mouse_down: EventType[()] | None = None,
+ on_mouse_enter: EventType[()] | None = None,
+ on_mouse_leave: EventType[()] | None = None,
+ on_mouse_move: EventType[()] | None = None,
+ on_mouse_out: EventType[()] | None = None,
+ on_mouse_over: EventType[()] | None = None,
+ on_mouse_up: EventType[()] | None = None,
+ on_scroll: EventType[()] | None = None,
+ on_scroll_end: EventType[()] | None = None,
+ on_unmount: EventType[()] | None = None,
+ **props,
+ ) -> VarTypesComponent:
+ """Create the component.
+
+ Args:
+ *children: The children of the component.
+ name: Basic Var types.
+ count: no description
+ ratio: no description
+ flag: no description
+ value: A string or int value.
+ items: A list of string items.
+ metadata: Metadata dictionary.
+ nested: Nested structures.
+ style: The style of the component.
+ key: A unique key for the component.
+ id: The id for the component.
+ ref: The Var to pass as the ref to the component.
+ class_name: The class name for the component.
+ custom_attrs: Attributes passed directly to the component.
+ on_focus: Fired when the element (or some element inside of it) receives focus. For example, it is called when the user clicks on a text input.
+ on_blur: Fired when focus has left the element (or left some element inside of it). For example, it is called when the user clicks outside of a focused text input.
+ on_click: Fired when the user clicks on an element. For example, it's called when the user clicks on a button.
+ on_context_menu: Fired when the user right-clicks on an element.
+ on_double_click: Fired when the user double-clicks on an element.
+ on_mouse_down: Fired when the user presses a mouse button on an element.
+ on_mouse_enter: Fired when the mouse pointer enters the element.
+ on_mouse_leave: Fired when the mouse pointer leaves the element.
+ on_mouse_move: Fired when the mouse pointer moves over the element.
+ on_mouse_out: Fired when the mouse pointer moves out of the element.
+ on_mouse_over: Fired when the mouse pointer moves onto the element.
+ on_mouse_up: Fired when the user releases a mouse button on an element.
+ on_scroll: Fired when the user scrolls the element.
+ on_scroll_end: Fired when scrolling ends on the element.
+ on_mount: Fired when the component is mounted to the page.
+ on_unmount: Fired when the component is removed from the page. Only called during navigation, not on page refresh.
+ **props: The props of the component.
+
+ Returns:
+ The component.
+ """
diff --git a/tests/units/reflex_base/utils/pyi_generator/test_regression.py b/tests/units/reflex_base/utils/pyi_generator/test_regression.py
new file mode 100644
index 00000000000..f52ca4ec07d
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/test_regression.py
@@ -0,0 +1,265 @@
+"""Regression tests for pyi_generator.
+
+Runs PyiGenerator.scan_all against a directory of curated Python files and
+compares the generated .pyi stubs against a set of golden reference files.
+
+Usage as CLI to regenerate golden files:
+ python -m tests.units.reflex_base.utils.pyi_generator --update
+
+Usage as pytest:
+ pytest tests/units/reflex_base/utils/pyi_generator/test_regression.py
+"""
+
+from __future__ import annotations
+
+import argparse
+import difflib
+import sys
+from pathlib import Path
+
+import pytest
+from reflex_base.utils.pyi_generator import PyiGenerator
+
+_HERE = Path(__file__).resolve().parent
+DATASET_DIR = _HERE / "dataset"
+GOLDEN_DIR = _HERE / "golden"
+
+_UPDATE_CMD = "python -m tests.units.reflex_base.utils.pyi_generator --update"
+
+
+def _golden_path_for(source_path: Path) -> Path:
+ """Map a dataset .py file to its golden .pyi counterpart.
+
+ Args:
+ source_path: The path to the dataset .py file.
+
+ Returns:
+ The corresponding path to the golden .pyi file.
+ """
+ relative = source_path.relative_to(DATASET_DIR)
+ return GOLDEN_DIR / relative.with_suffix(".pyi")
+
+
+def _normalize_stub(content: str) -> str:
+ """Replace the absolute-path docstring header so golden files are portable.
+
+ Args:
+ content: The raw content of the generated .pyi file.
+
+ Returns:
+ The normalized content with the dataset path replaced by a placeholder.
+ """
+ lines = content.splitlines(keepends=True)
+ normalized: list[str] = []
+ for line in lines:
+ if line.startswith('"""Stub file for '):
+ normalized.append('"""Stub file for """\n')
+ else:
+ normalized.append(line)
+ return "".join(normalized)
+
+
+def _run_generator() -> dict[Path, str]:
+ """Run PyiGenerator.scan_all on the dataset dir and collect results.
+
+ Generated .pyi files are read back and then removed from the dataset
+ tree so the working copy stays clean. A ``try/finally`` block ensures
+ generated files are always cleaned up, even if reading one of them fails.
+
+ Returns:
+ A mapping from dataset source .py files to their generated .pyi content.
+ """
+ gen = PyiGenerator()
+ gen.scan_all([str(DATASET_DIR)])
+
+ pyi_paths = [Path(pyi_str) for pyi_str, _hash in gen.written_files]
+ try:
+ results: dict[Path, str] = {}
+ for pyi_path in pyi_paths:
+ source_path = pyi_path.with_suffix(".py")
+ results[source_path] = pyi_path.read_text()
+ finally:
+ for pyi_path in pyi_paths:
+ pyi_path.unlink(missing_ok=True)
+ return results
+
+
+def update_golden_files() -> list[str]:
+ """Regenerate all golden .pyi files from the dataset.
+
+ Returns:
+ A list of relative paths to the golden files that were updated.
+ """
+ GOLDEN_DIR.mkdir(parents=True, exist_ok=True)
+ for subdir in DATASET_DIR.rglob("*"):
+ if subdir.is_dir() and subdir != DATASET_DIR:
+ (GOLDEN_DIR / subdir.relative_to(DATASET_DIR)).mkdir(
+ parents=True, exist_ok=True
+ )
+
+ generated = _run_generator()
+ updated: list[str] = []
+ for source_path, content in sorted(generated.items()):
+ golden = _golden_path_for(source_path)
+ golden.write_text(_normalize_stub(content))
+ rel = golden.relative_to(_HERE)
+ updated.append(str(rel))
+ print(f" updated: {rel}")
+
+ expected_goldens = {_golden_path_for(s) for s in generated}
+ for existing in GOLDEN_DIR.rglob("*.pyi"):
+ if existing not in expected_goldens:
+ existing.unlink()
+ print(f" removed stale: {existing.relative_to(_HERE)}")
+
+ return updated
+
+
+@pytest.fixture(scope="module")
+def generated_stubs():
+ """Run the generator once for the whole test module.
+
+ Returns:
+ A mapping from dataset source .py files to their generated .pyi content.
+ """
+ return _run_generator()
+
+
+def _existing_golden_cases() -> list[tuple[str, Path]]:
+ """Build test IDs from existing golden files (no generator run needed).
+
+ Returns:
+ A list of tuples containing test IDs and corresponding dataset source paths.
+ """
+ cases = []
+ for golden in sorted(GOLDEN_DIR.rglob("*.pyi")):
+ relative = golden.relative_to(GOLDEN_DIR)
+ source = DATASET_DIR / relative.with_suffix(".py")
+ tid = str(relative.with_suffix(".py")).replace("/", ".")
+ cases.append((tid, source))
+ return cases
+
+
+@pytest.mark.parametrize(
+ "source_path",
+ [p for _, p in _existing_golden_cases()],
+ ids=[tid for tid, _ in _existing_golden_cases()],
+)
+def test_pyi_golden(generated_stubs: dict[Path, str], source_path: Path):
+ """Compare generated .pyi output against golden reference.
+
+ Args:
+ generated_stubs: The mapping of dataset source paths to generated .pyi content.
+ source_path: The path to the dataset .py file for this test case.
+ """
+ golden_path = _golden_path_for(source_path)
+
+ content = generated_stubs.get(source_path)
+ if content is None:
+ pytest.fail(
+ f"pyi_generator produced no output for {source_path.name}, "
+ f"but a golden file exists at {golden_path}"
+ )
+
+ normalized = _normalize_stub(content)
+ expected = golden_path.read_text()
+
+ if normalized != expected:
+ diff = difflib.unified_diff(
+ expected.splitlines(keepends=True),
+ normalized.splitlines(keepends=True),
+ fromfile=f"golden/{golden_path.name}",
+ tofile=f"generated/{golden_path.name}",
+ )
+ pytest.fail(
+ f"Generated stub differs from golden reference for {source_path.name}.\n"
+ f"Run `{_UPDATE_CMD}` to regenerate.\n\n{''.join(diff)}"
+ )
+
+
+def test_no_extra_golden_files(generated_stubs: dict[Path, str]):
+ """Ensure no golden files exist without corresponding dataset sources.
+
+ Args:
+ generated_stubs: The mapping of dataset source paths to generated .pyi content.
+ """
+ expected_goldens = {_golden_path_for(s) for s in generated_stubs}
+ for existing in GOLDEN_DIR.rglob("*.pyi"):
+ assert existing in expected_goldens, (
+ f"Stale golden file {existing.relative_to(_HERE)} has no dataset source. "
+ f"Run `{_UPDATE_CMD}` to clean up."
+ )
+
+
+def test_no_missing_golden_files(generated_stubs: dict[Path, str]):
+ """Ensure every generated stub has a corresponding golden file.
+
+ Catches the case where a new dataset file is added but ``--update`` is
+ not run, so no golden reference exists and the new scenario silently
+ goes untested.
+
+ Args:
+ generated_stubs: The mapping of dataset source paths to generated .pyi content.
+ """
+ existing_goldens = set(GOLDEN_DIR.rglob("*.pyi"))
+ missing = []
+ for source_path in sorted(generated_stubs):
+ golden = _golden_path_for(source_path)
+ if golden not in existing_goldens:
+ missing.append(str(golden.relative_to(_HERE)))
+ assert not missing, (
+ f"Generated stubs have no golden files: {', '.join(missing)}. "
+ f"Run `{_UPDATE_CMD}` to create them."
+ )
+
+
+def main():
+ parser = argparse.ArgumentParser(description="pyi_generator regression test suite")
+ parser.add_argument(
+ "--update",
+ action="store_true",
+ help="Regenerate golden .pyi files from the dataset.",
+ )
+ parser.add_argument(
+ "--check",
+ action="store_true",
+ help="Check that generated stubs match golden files (CI mode).",
+ )
+ args = parser.parse_args()
+
+ if args.update:
+ print(f"Regenerating golden files from {DATASET_DIR} ...")
+ updated = update_golden_files()
+ print(
+ f"\nDone. {len(updated)} file(s) updated in {GOLDEN_DIR.relative_to(_HERE)}/"
+ )
+ print("Review the changes and commit them with your PR.")
+ elif args.check:
+ print("Checking generated stubs against golden files...")
+ generated = _run_generator()
+ failures = []
+ for source_path, content in sorted(generated.items()):
+ golden_path = _golden_path_for(source_path)
+ if not golden_path.exists():
+ failures.append(f" {source_path.name}: missing golden file")
+ continue
+ if _normalize_stub(content) != golden_path.read_text():
+ failures.append(f" {source_path.name}: differs from golden")
+ expected_goldens = {_golden_path_for(s) for s in generated}
+ for existing in sorted(GOLDEN_DIR.rglob("*.pyi")):
+ if existing not in expected_goldens:
+ failures.append(
+ f" {existing.relative_to(_HERE)}: stale golden (no dataset source)"
+ )
+ if failures:
+ print("FAILED:")
+ print("\n".join(failures))
+ print(f"\nRun `{_UPDATE_CMD}` to regenerate.")
+ sys.exit(1)
+ print("All stubs match golden files.")
+ else:
+ parser.print_help()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tests/units/reflex_base/utils/pyi_generator/test_unit.py b/tests/units/reflex_base/utils/pyi_generator/test_unit.py
new file mode 100644
index 00000000000..4bbf5107b8a
--- /dev/null
+++ b/tests/units/reflex_base/utils/pyi_generator/test_unit.py
@@ -0,0 +1,460 @@
+"""Unit tests for individual pyi_generator translation functions.
+
+Tests smaller functions in isolation using "code in -> expected code out"
+patterns. These complement the golden file regression tests by testing
+edge cases in type resolution and AST generation directly.
+"""
+
+from __future__ import annotations
+
+import ast
+import linecache
+import sys
+import types as builtin_types
+import typing
+from types import SimpleNamespace
+from typing import Any, Literal, Optional, Union
+
+import pytest
+from reflex_base.components.component import Component
+from reflex_base.utils.pyi_generator import (
+ StubGenerator,
+ _get_type_hint,
+ _is_literal,
+ _is_optional,
+ _is_union,
+ _safe_issubclass,
+ type_to_ast,
+)
+from reflex_base.vars.base import Var
+
+
+def test_is_union_typing_union():
+ assert _is_union(Union[str, int]) is True # noqa: UP007
+
+
+def test_is_union_pipe_union():
+ assert _is_union(str | int) is True
+
+
+def test_is_union_optional_is_union():
+ assert _is_union(Optional[str]) is True # noqa: UP045
+
+
+def test_is_union_plain_type():
+ assert _is_union(str) is False
+
+
+def test_is_union_none():
+ assert _is_union(None) is False
+
+
+def test_is_union_var():
+ assert _is_union(Var[str]) is False
+
+
+def test_is_optional_none_value():
+ assert _is_optional(None) is True
+
+
+def test_is_optional_none_type():
+ assert _is_optional(type(None)) is True
+
+
+def test_is_optional_optional_type():
+ assert _is_optional(Optional[str]) is True # noqa: UP045
+
+
+def test_is_optional_union_with_none():
+ assert _is_optional(str | None) is True
+
+
+def test_is_optional_plain_type():
+ assert _is_optional(str) is False
+
+
+def test_is_optional_union_without_none():
+ assert _is_optional(str | int) is False
+
+
+def test_is_literal_literal_type():
+ assert _is_literal(Literal["a", "b"]) is True
+
+
+def test_is_literal_plain_type():
+ assert _is_literal(str) is False
+
+
+def test_is_literal_none():
+ assert _is_literal(None) is False
+
+
+def test_safe_issubclass_true():
+ assert _safe_issubclass(bool, int) is True
+
+
+def test_safe_issubclass_false():
+ assert _safe_issubclass(str, int) is False
+
+
+def test_safe_issubclass_non_type():
+ assert _safe_issubclass("not a type", int) is False
+
+
+def test_safe_issubclass_none():
+ assert _safe_issubclass(None, int) is False
+
+
+@pytest.fixture
+def type_hint_globals():
+ """Provide a type_hint_globals dict with common types.
+
+ Returns:
+ A dict mapping type names to their corresponding types, including built-ins, typing constructs, and
+ custom types.
+ """
+ return {
+ "str": str,
+ "int": int,
+ "float": float,
+ "bool": bool,
+ "list": list,
+ "dict": dict,
+ "Var": Var,
+ "Any": Any,
+ "Literal": Literal,
+ "Optional": Optional,
+ "Union": Union,
+ **{name: getattr(typing, name) for name in ["Sequence", "Mapping"]},
+ }
+
+
+def test_get_type_hint_none_value(type_hint_globals):
+ assert _get_type_hint(None, type_hint_globals) == "None"
+
+
+def test_get_type_hint_none_type(type_hint_globals):
+ assert _get_type_hint(type(None), type_hint_globals) == "None"
+
+
+def test_get_type_hint_simple_optional(type_hint_globals):
+ assert _get_type_hint(str, type_hint_globals, is_optional=True) == "str | None"
+
+
+def test_get_type_hint_simple_not_optional(type_hint_globals):
+ assert _get_type_hint(str, type_hint_globals, is_optional=False) == "str"
+
+
+def test_get_type_hint_optional_union(type_hint_globals):
+ assert _get_type_hint(Optional[str], type_hint_globals) == "str | None" # noqa: UP045
+
+
+def test_get_type_hint_union_without_none(type_hint_globals):
+ result = _get_type_hint(Union[str, int], type_hint_globals, is_optional=False) # noqa: UP007
+ assert result == "int | str"
+
+
+def test_get_type_hint_union_with_none(type_hint_globals):
+ result = _get_type_hint(Union[str, int, None], type_hint_globals) # noqa: UP007
+ assert result == "int | str | None"
+
+
+def test_get_type_hint_var_expansion(type_hint_globals):
+ """Var[str] should expand to Var[str] | str."""
+ result = _get_type_hint(Var[str], type_hint_globals, is_optional=False)
+ assert result == "Var[str] | str"
+
+
+def test_get_type_hint_var_union_expansion(type_hint_globals):
+ """Var[str | int] should expand to include Var, str, and int."""
+ result = _get_type_hint(Var[str | int], type_hint_globals, is_optional=False)
+ parts = {p.strip() for p in result.split("|")}
+ assert "str" in parts
+ assert "int" in parts
+ assert any("Var[" in p for p in parts)
+
+
+def test_get_type_hint_literal(type_hint_globals):
+ result = _get_type_hint(
+ Literal["a", "b", "c"], type_hint_globals, is_optional=False
+ )
+ assert result == "Literal['a', 'b', 'c']"
+
+
+def test_type_to_ast_none_type():
+ node = type_to_ast(type(None), Component)
+ assert isinstance(node, ast.Name)
+ assert node.id == "None"
+
+
+def test_type_to_ast_none_value():
+ node = type_to_ast(None, Component)
+ assert isinstance(node, ast.Name)
+ assert node.id == "None"
+
+
+def test_type_to_ast_simple_type():
+ node = type_to_ast(str, Component)
+ assert isinstance(node, ast.Name)
+ assert node.id == "str"
+
+
+def test_type_to_ast_literal():
+ node = type_to_ast(Literal["x", "y"], Component)
+ assert isinstance(node, ast.Subscript)
+ unparsed = ast.unparse(node)
+ assert "Literal" in unparsed
+ assert "'x'" in unparsed
+ assert "'y'" in unparsed
+
+
+def test_type_to_ast_union():
+ node = type_to_ast(Union[str, int], Component) # noqa: UP007
+ assert isinstance(node, ast.Subscript)
+ unparsed = ast.unparse(node)
+ assert "str" in unparsed
+ assert "int" in unparsed
+
+
+def test_type_to_ast_generic():
+ node = type_to_ast(list[str], Component)
+ unparsed = ast.unparse(node)
+ assert "list" in unparsed
+ assert "str" in unparsed
+
+
+def test_type_to_ast_nested_generic():
+ node = type_to_ast(dict[str, list[int]], Component)
+ unparsed = ast.unparse(node)
+ assert "dict" in unparsed
+ assert "str" in unparsed
+ assert "list" in unparsed
+ assert "int" in unparsed
+
+
+_stub_gen_counter = 0
+
+
+def _generate_stub_from_source(source: str) -> str:
+ """Parse source, run StubGenerator, return unparsed result.
+
+ Args:
+ source: The Python source code to generate a stub from.
+
+ Returns:
+ The generated stub code as a string.
+ """
+ global _stub_gen_counter
+ _stub_gen_counter += 1
+ module_name = f"_pyi_test_mod_{_stub_gen_counter}"
+ filename = f"{module_name}.py"
+
+ linecache.cache[filename] = (
+ len(source),
+ None,
+ source.splitlines(keepends=True),
+ filename,
+ )
+
+ mod = builtin_types.ModuleType(module_name)
+ mod.__file__ = filename
+ sys.modules[module_name] = mod
+ try:
+ exec(compile(source, filename, "exec"), mod.__dict__)
+
+ for obj in vars(mod).values():
+ if (
+ isinstance(obj, type)
+ and issubclass(obj, Component)
+ and obj is not Component
+ ):
+ obj.__module__ = module_name
+
+ classes: dict[str, type[Component] | type[SimpleNamespace]] = {
+ name: obj
+ for name, obj in vars(mod).items()
+ if isinstance(obj, type)
+ and issubclass(obj, Component)
+ and obj is not Component
+ }
+
+ tree = ast.parse(source)
+ generator = StubGenerator(mod, classes)
+ new_tree = generator.visit(tree)
+ return ast.unparse(new_tree)
+ finally:
+ sys.modules.pop(module_name, None)
+ linecache.cache.pop(filename, None)
+
+
+def test_stub_private_method_removed():
+ source = """
+from reflex_base.components.component import Component
+from reflex_base.vars.base import Var
+
+class Foo(Component):
+ x: Var[str]
+ def _hidden(self): pass
+ def visible(self): return 1
+"""
+ result = _generate_stub_from_source(source)
+ assert "def _hidden" not in result
+ assert "def visible" in result
+ # Public method body should be blanked to ellipsis.
+ assert "return 1" not in result
+
+
+def test_stub_module_docstring_removed():
+ source = '''"""This is a module docstring."""
+from reflex_base.components.component import Component
+from reflex_base.vars.base import Var
+
+class Bar(Component):
+ y: Var[int]
+'''
+ result = _generate_stub_from_source(source)
+ assert "This is a module docstring" not in result
+ # Should still have the class and create method.
+ assert "class Bar" in result
+ assert "def create" in result
+
+
+def test_stub_future_import_removed():
+ source = """from __future__ import annotations
+from reflex_base.components.component import Component
+from reflex_base.vars.base import Var
+
+class Baz(Component):
+ z: Var[bool]
+"""
+ result = _generate_stub_from_source(source)
+ assert "__future__" not in result
+ # Default imports should be injected instead.
+ assert "from reflex_base.event import" in result
+
+
+def test_stub_class_docstring_removed():
+ source = '''
+from reflex_base.components.component import Component
+from reflex_base.vars.base import Var
+
+class DocComponent(Component):
+ """This class docstring should be removed."""
+ val: Var[str]
+'''
+ result = _generate_stub_from_source(source)
+ assert "This class docstring should be removed" not in result
+ assert "class DocComponent" in result
+
+
+def test_stub_non_annotated_assignment_removed():
+ source = """
+from reflex_base.components.component import Component
+from reflex_base.vars.base import Var
+
+class AssignComp(Component):
+ some_const = "hello"
+ val: Var[str]
+"""
+ result = _generate_stub_from_source(source)
+ assert "some_const" not in result
+ assert "hello" not in result
+
+
+def test_stub_any_assignment_preserved():
+ source = """
+from typing import Any
+from reflex_base.components.component import Component
+from reflex_base.vars.base import Var
+
+SomeAlias = Any
+
+class AnyComp(Component):
+ val: Var[str]
+"""
+ result = _generate_stub_from_source(source)
+ assert "SomeAlias = Any" in result
+
+
+def test_stub_annotated_assignment_value_blanked():
+ source = """
+from reflex_base.components.component import Component
+from reflex_base.vars.base import Var
+
+mode: str = "default"
+
+class ModeComp(Component):
+ val: Var[str]
+"""
+ result = _generate_stub_from_source(source)
+ assert "mode: str" in result
+ # Value should be stripped — only the annotation remains.
+ assert '"default"' not in result
+ assert "mode: str =" not in result
+
+
+def test_stub_classvar_preserved():
+ source = """
+from typing import ClassVar
+from reflex_base.components.component import Component
+from reflex_base.vars.base import Var
+
+class CVComp(Component):
+ allowed_types: ClassVar[list[str]] = ["A"]
+ val: Var[str]
+"""
+ result = _generate_stub_from_source(source)
+ assert "ClassVar[list[str]]" in result
+ # ClassVar props should NOT appear as create() kwargs.
+ assert "allowed_types" not in result.split("def create")[1]
+
+
+def test_stub_private_classvar_removed():
+ source = """
+from typing import ClassVar
+from reflex_base.components.component import Component
+from reflex_base.vars.base import Var
+
+class PVComp(Component):
+ _valid_children: ClassVar[list[str]] = ["A"]
+ val: Var[str]
+"""
+ result = _generate_stub_from_source(source)
+ # Private ClassVar annotations are stripped entirely.
+ assert "_valid_children" not in result
+
+
+def test_stub_public_function_body_blanked():
+ source = """
+from reflex_base.components.component import Component
+from reflex_base.vars.base import Var
+
+class FuncComp(Component):
+ val: Var[str]
+ def helper(self) -> str:
+ x = 1
+ y = 2
+ return str(x + y)
+"""
+ result = _generate_stub_from_source(source)
+ assert "def helper(self) -> str:" in result
+ assert "x = 1" not in result
+ assert "x + y" not in result
+
+
+def test_stub_create_method_generated():
+ source = """
+from reflex_base.components.component import Component, field
+from reflex_base.vars.base import Var
+
+class CreateComp(Component):
+ name: Var[str] = field(doc="The name.")
+"""
+ result = _generate_stub_from_source(source)
+ assert "@classmethod" in result
+ assert "def create(cls, *children" in result
+ # name prop should appear as a keyword arg with Var expansion.
+ assert "name:" in result
+ assert "**props" in result
+ # Return type should reference the class.
+ assert "CreateComp" in result