Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 101 additions & 27 deletions reflex/components/markdown/markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,84 @@
NO_PROPS_TAGS = ("ul", "ol", "li")


def _h1(value: object):
from reflex.components.radix.themes.typography.heading import Heading

return Heading.create(value, as_="h1", size="6", margin_y="0.5em")


def _h2(value: object):
from reflex.components.radix.themes.typography.heading import Heading

return Heading.create(value, as_="h2", size="5", margin_y="0.5em")


def _h3(value: object):
from reflex.components.radix.themes.typography.heading import Heading

return Heading.create(value, as_="h3", size="4", margin_y="0.5em")


def _h4(value: object):
from reflex.components.radix.themes.typography.heading import Heading

return Heading.create(value, as_="h4", size="3", margin_y="0.5em")


def _h5(value: object):
from reflex.components.radix.themes.typography.heading import Heading

return Heading.create(value, as_="h5", size="2", margin_y="0.5em")


def _h6(value: object):
from reflex.components.radix.themes.typography.heading import Heading

return Heading.create(value, as_="h6", size="1", margin_y="0.5em")


def _p(value: object):
from reflex.components.radix.themes.typography.text import Text

return Text.create(value, margin_y="1em")


def _ul(value: object):
from reflex.components.radix.themes.layout.list import UnorderedList

return UnorderedList.create(value, margin_y="1em")


def _ol(value: object):
from reflex.components.radix.themes.layout.list import OrderedList

return OrderedList.create(value, margin_y="1em")


def _li(value: object):
from reflex.components.radix.themes.layout.list import ListItem

return ListItem.create(value, margin_y="0.5em")


def _a(value: object):
from reflex.components.radix.themes.typography.link import Link

return Link.create(value)


def _code(value: object):
from reflex.components.radix.themes.typography.code import Code

return Code.create(value)


def _codeblock(value: object, **props):
from reflex.components.datadisplay.code import CodeBlock

return CodeBlock.create(value, margin_y="1em", wrap_long_lines=True, **props)


# Component Mapping
@lru_cache
def get_base_component_map() -> dict[str, Callable]:
Expand All @@ -46,33 +124,20 @@ def get_base_component_map() -> dict[str, Callable]:
Returns:
The base component map.
"""
from reflex.components.datadisplay.code import CodeBlock
from reflex.components.radix.themes.layout.list import (
ListItem,
OrderedList,
UnorderedList,
)
from reflex.components.radix.themes.typography.code import Code
from reflex.components.radix.themes.typography.heading import Heading
from reflex.components.radix.themes.typography.link import Link
from reflex.components.radix.themes.typography.text import Text

return {
"h1": lambda value: Heading.create(value, as_="h1", size="6", margin_y="0.5em"),
"h2": lambda value: Heading.create(value, as_="h2", size="5", margin_y="0.5em"),
"h3": lambda value: Heading.create(value, as_="h3", size="4", margin_y="0.5em"),
"h4": lambda value: Heading.create(value, as_="h4", size="3", margin_y="0.5em"),
"h5": lambda value: Heading.create(value, as_="h5", size="2", margin_y="0.5em"),
"h6": lambda value: Heading.create(value, as_="h6", size="1", margin_y="0.5em"),
"p": lambda value: Text.create(value, margin_y="1em"),
"ul": lambda value: UnorderedList.create(value, margin_y="1em"),
"ol": lambda value: OrderedList.create(value, margin_y="1em"),
"li": lambda value: ListItem.create(value, margin_y="0.5em"),
"a": lambda value: Link.create(value),
"code": lambda value: Code.create(value),
"codeblock": lambda value, **props: CodeBlock.create(
value, margin_y="1em", wrap_long_lines=True, **props
),
"h1": _h1,
"h2": _h2,
"h3": _h3,
"h4": _h4,
"h5": _h5,
"h6": _h6,
"p": _p,
"ul": _ul,
"ol": _ol,
"li": _li,
"a": _a,
"code": _code,
"codeblock": _codeblock,
}


Expand Down Expand Up @@ -413,7 +478,16 @@ def _get_map_fn_custom_code_from_children(
@staticmethod
def _component_map_hash(component_map: dict) -> str:
inp = str(
{tag: component(_MOCK_ARG) for tag, component in component_map.items()}
{
tag: (
f"{component.__module__}.{component.__qualname__}"
if (
"<" not in component.__name__
) # simple way to check against lambdas
else component(_MOCK_ARG)
)
for tag, component in component_map.items()
}
).encode()
return md5(inp).hexdigest()

Expand Down
1 change: 1 addition & 0 deletions reflex/utils/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ def is_literal(cls: GenericType) -> bool:
return getattr(cls, "__origin__", None) is Literal


@lru_cache
def has_args(cls: type) -> bool:
"""Check if the class has generic parameters.

Expand Down
128 changes: 104 additions & 24 deletions reflex/vars/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1527,6 +1527,82 @@ def _create_literal_var(
def __post_init__(self):
"""Post-initialize the var."""

@classmethod
def _get_all_var_data_without_creating_var(
cls,
value: Any,
) -> VarData | None:
return cls.create(value)._get_all_var_data()
Comment thread
adhami3310 marked this conversation as resolved.

@classmethod
def _get_all_var_data_without_creating_var_dispatch(
cls,
value: Any,
) -> VarData | None:
"""Get all the var data without creating a var.

Args:
value: The value to get the var data from.

Returns:
The var data or None.

Raises:
TypeError: If the value is not a supported type for LiteralVar.
"""
from .object import LiteralObjectVar
from .sequence import LiteralStringVar

if isinstance(value, Var):
return value._get_all_var_data()

for literal_subclass, var_subclass in _var_literal_subclasses[::-1]:
if isinstance(value, var_subclass.python_types):
return literal_subclass._get_all_var_data_without_creating_var(value)

if (
(as_var_method := getattr(value, "_as_var", None)) is not None
and callable(as_var_method)
and isinstance((resulting_var := as_var_method()), Var)
):
return resulting_var._get_all_var_data()

from reflex.event import EventHandler
from reflex.utils.format import get_event_handler_parts

if isinstance(value, EventHandler):
return Var(
_js_expr=".".join(filter(None, get_event_handler_parts(value)))
)._get_all_var_data()

serialized_value = serializers.serialize(value)
if serialized_value is not None:
if isinstance(serialized_value, Mapping):
return LiteralObjectVar._get_all_var_data_without_creating_var(
serialized_value
)
if isinstance(serialized_value, str):
return LiteralStringVar._get_all_var_data_without_creating_var(
serialized_value
)
return LiteralVar._get_all_var_data_without_creating_var_dispatch(
serialized_value
)

if dataclasses.is_dataclass(value) and not isinstance(value, type):
return LiteralObjectVar._get_all_var_data_without_creating_var(
{
k: (None if callable(v) else v)
for k, v in dataclasses.asdict(value).items()
}
)

if isinstance(value, range):
return None

msg = f"Unsupported type {type(value)} for LiteralVar. Tried to create a LiteralVar from {value}."
raise TypeError(msg)

@property
def _var_value(self) -> Any:
msg = "LiteralVar subclasses must implement the _var_value property."
Expand Down Expand Up @@ -1688,30 +1764,30 @@ def figure_out_type(value: Any) -> types.GenericType:
Returns:
The type of the value.
"""
if isinstance(value, Var):
return value._var_type
type_ = type(value)
if has_args(type_):
return type_
if isinstance(value, list):
if not value:
return Sequence[NoReturn]
return Sequence[unionize(*(figure_out_type(v) for v in value))]
if isinstance(value, set):
return set[unionize(*(figure_out_type(v) for v in value))]
if isinstance(value, tuple):
if not value:
return tuple[NoReturn, ...]
if len(value) <= 5:
return tuple[tuple(figure_out_type(v) for v in value)]
return tuple[unionize(*(figure_out_type(v) for v in value)), ...]
if isinstance(value, Mapping):
if not value:
return Mapping[NoReturn, NoReturn]
return Mapping[
unionize(*(figure_out_type(k) for k in value)),
unionize(*(figure_out_type(v) for v in value.values())),
]
if isinstance(value, (list, set, tuple, Mapping, Var)):
if isinstance(value, Var):
return value._var_type
if has_args(value_type := type(value)):
return value_type
if isinstance(value, list):
if not value:
return Sequence[NoReturn]
return Sequence[unionize(*{figure_out_type(v) for v in value[:100]})]
if isinstance(value, set):
return set[unionize(*{figure_out_type(v) for v in value})]
if isinstance(value, tuple):
if not value:
return tuple[NoReturn, ...]
if len(value) <= 5:
return tuple[tuple(figure_out_type(v) for v in value)]
return tuple[unionize(*{figure_out_type(v) for v in value[:100]}), ...]
if isinstance(value, Mapping):
if not value:
return Mapping[NoReturn, NoReturn]
return Mapping[
unionize(*{figure_out_type(k) for k in list(value.keys())[:100]}),
unionize(*{figure_out_type(v) for v in list(value.values())[:100]}),
]
return type(value)


Expand Down Expand Up @@ -2883,6 +2959,10 @@ def json(self) -> str:
"""
return "null"

@classmethod
def _get_all_var_data_without_creating_var(cls, value: None) -> VarData | None:
return None

@classmethod
def create(
cls,
Expand Down
36 changes: 28 additions & 8 deletions reflex/vars/color.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,23 @@ class LiteralColorVar(CachedVarOperation, LiteralVar, ColorVar):

_var_value: Color = dataclasses.field(default_factory=lambda: Color(color="black"))

@classmethod
def _get_all_var_data_without_creating_var(
cls,
value: Color,
) -> VarData | None:
return VarData.merge(
LiteralStringVar._get_all_var_data_without_creating_var(value.color)
if isinstance(value.color, str)
else value.color._get_all_var_data(),
value.alpha._get_all_var_data()
if not isinstance(value.alpha, bool)
else None,
value.shade._get_all_var_data()
if not isinstance(value.shade, int)
else None,
)

@classmethod
def create(
cls,
Expand Down Expand Up @@ -111,14 +128,17 @@ def _cached_get_all_var_data(self) -> VarData | None:
The var data.
"""
return VarData.merge(
*[
LiteralVar.create(var)._get_all_var_data()
for var in (
self._var_value.color,
self._var_value.alpha,
self._var_value.shade,
)
],
LiteralStringVar._get_all_var_data_without_creating_var(
self._var_value.color
)
if isinstance(self._var_value.color, str)
else self._var_value.color._get_all_var_data(),
self._var_value.alpha._get_all_var_data()
if not isinstance(self._var_value.alpha, bool)
else None,
self._var_value.shade._get_all_var_data()
if not isinstance(self._var_value.shade, int)
else None,
self._var_data,
)

Expand Down
8 changes: 6 additions & 2 deletions reflex/vars/datetime.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,14 @@ def date_compare_operation(
class LiteralDatetimeVar(LiteralVar, DateTimeVar):
"""Base class for immutable datetime and date vars."""

_var_value: datetime | date = dataclasses.field(default=datetime.now())
_var_value: date = dataclasses.field(default=datetime.now())
Comment thread
adhami3310 marked this conversation as resolved.

@classmethod
def create(cls, value: datetime | date, _var_data: VarData | None = None):
def _get_all_var_data_without_creating_var(cls, value: date) -> VarData | None:
return None

@classmethod
def create(cls, value: date, _var_data: VarData | None = None):
Comment thread
adhami3310 marked this conversation as resolved.
"""Create a new instance of the class.

Args:
Expand Down
Loading