Skip to content

Rework VDOM construction and type hints #1281

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Feb 27, 2025
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ filterwarnings = """
ignore::DeprecationWarning:uvicorn.*
ignore::DeprecationWarning:websockets.*
ignore::UserWarning:tests.test_core.test_vdom
ignore::UserWarning:tests.test_pyscript.test_components
ignore::UserWarning:tests.test_utils
"""
testpaths = "tests"
xfail_strict = true
Expand Down
4 changes: 2 additions & 2 deletions src/reactpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
use_state,
)
from reactpy.core.layout import Layout
from reactpy.core.vdom import vdom
from reactpy.core.vdom import Vdom
from reactpy.pyscript.components import pyscript_component
from reactpy.utils import Ref, reactpy_to_string, string_to_reactpy

Expand All @@ -29,6 +29,7 @@
__all__ = [
"Layout",
"Ref",
"Vdom",
"component",
"config",
"create_context",
Expand All @@ -52,7 +53,6 @@
"use_ref",
"use_scope",
"use_state",
"vdom",
"web",
"widgets",
]
34 changes: 22 additions & 12 deletions src/reactpy/_html.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from __future__ import annotations

from collections.abc import Sequence
from typing import TYPE_CHECKING, ClassVar
from typing import TYPE_CHECKING, ClassVar, overload

from reactpy.core.vdom import custom_vdom_constructor, make_vdom_constructor
from reactpy.core.vdom import Vdom

if TYPE_CHECKING:
from reactpy.types import (
Expand Down Expand Up @@ -176,6 +176,14 @@ class SvgConstructor:

__cache__: ClassVar[dict[str, VdomDictConstructor]] = {}

@overload
def __call__(
self, attributes: VdomAttributes, /, *children: VdomChildren
) -> VdomDict: ...

@overload
def __call__(self, *children: VdomChildren) -> VdomDict: ...

def __call__(
self, *attributes_and_children: VdomAttributes | VdomChildren
) -> VdomDict:
Expand All @@ -187,8 +195,8 @@ def __getattr__(self, value: str) -> VdomDictConstructor:
if value in self.__cache__:
return self.__cache__[value]

self.__cache__[value] = make_vdom_constructor(
value, allow_children=value not in NO_CHILDREN_ALLOWED_SVG
self.__cache__[value] = Vdom(
tagName=value, allow_children=value not in NO_CHILDREN_ALLOWED_SVG
)

return self.__cache__[value]
Expand Down Expand Up @@ -261,6 +269,7 @@ def __getattr__(self, value: str) -> VdomDictConstructor:
tspan: VdomDictConstructor
use: VdomDictConstructor
view: VdomDictConstructor
svg: VdomDictConstructor


class HtmlConstructor:
Expand All @@ -275,8 +284,9 @@ class HtmlConstructor:

# ruff: noqa: N815
__cache__: ClassVar[dict[str, VdomDictConstructor]] = {
"script": custom_vdom_constructor(_script),
"fragment": custom_vdom_constructor(_fragment),
"script": Vdom(tagName="script", custom_constructor=_script),
"fragment": Vdom(tagName="", custom_constructor=_fragment),
"svg": SvgConstructor(),
}

def __getattr__(self, value: str) -> VdomDictConstructor:
Expand All @@ -285,15 +295,15 @@ def __getattr__(self, value: str) -> VdomDictConstructor:
if value in self.__cache__:
return self.__cache__[value]

self.__cache__[value] = make_vdom_constructor(
value, allow_children=value not in NO_CHILDREN_ALLOWED_HTML_BODY
self.__cache__[value] = Vdom(
tagName=value, allow_children=value not in NO_CHILDREN_ALLOWED_HTML_BODY
)

return self.__cache__[value]

# HTML elements, written out here for auto-complete purposes
# The actual elements are created dynamically in the __getattr__ method.
# Elements other than these can still be created.
# Standard HTML elements are written below for auto-complete purposes
# The actual elements are created dynamically when __getattr__ is called.
# Elements other than those type-hinted below can still be created.
a: VdomDictConstructor
abbr: VdomDictConstructor
address: VdomDictConstructor
Expand Down Expand Up @@ -410,7 +420,7 @@ def __getattr__(self, value: str) -> VdomDictConstructor:
# Special Case: SVG elements
# Since SVG elements have a different set of allowed children, they are
# separated into a different constructor, and are accessed via `html.svg.example()`
svg: SvgConstructor = SvgConstructor()
svg: SvgConstructor


html = HtmlConstructor()
Loading