
* use serializer system * add checks for unsupported operands * and and or are now supported * format * remove unnecessary call to JSON * put base before rest * fix failing testcase * add hinting to get static analysis to complain * damn * big changes * get typeguard from extensions * please darglint * dangit darglint * remove one from vars * add without data and use it in plotly * DARGLINT * change format for special props * add pyi * delete instances of Var.create * modify client state to work * fixed so much * remove every Var.create * delete all basevar stuff * checkpoint * fix pyi * get older python to work * dangit darglint * add simple fix to last failing testcase * remove var name unwrapped and put client state on immutable var * fix older python * fox event issues * change forms pyi * make test less strict * use rx state directly * add typeignore to page_id * implement foreach * delete .web states folder silly * update reflex chakra * fix issue when on mount or on unmount is not set * nuke Var * run pyi * import immutablevar in critical location * delete unwrap vars * bring back array ref * fix style props in app * /health endpoint for K8 Liveness and Readiness probes (#3855) * Added API Endpoint * Added API Endpoint * Added Unit Tests * Added Unit Tests * main * Apply suggestions from Code Review * Fix Ruff Formatting * Update Socket Events * Async Functions * Update find_replace (#3886) * [REF-3592]Promote `rx.progress` from radix themes (#3878) * Promote `rx.progress` from radix themes * fix pyi * add warning when accessing `rx._x.progress` * Use correct flexgen backend URL (#3891) * Remove demo template (#3888) * gitignore .web (#3885) * update overflowY in AUTO_HEIGHT_JS from hidden to scroll (#3882) * Retain mutability inside `async with self` block (#3884) When emitting a state update, restore `_self_mutable` to the value it had previously so that `yield` in the middle of `async with self` does not result in an immutable StateProxy. Fix #3869 * Include child imports in markdown component_map (#3883) If a component in the markdown component_map contains children components, use `_get_all_imports` to recursively enumerate them. Fix #3880 * [REF-3570] Remove deprecated REDIS_URL syntax (#3892) * mixin computed vars should only be applied to highest level state (#3833) * improve state hierarchy validation, drop old testing special case (#3894) * fix var dependency dicts (#3842) * Adding array to array pluck operation. (#3868) * fix initial state without cv fallback (#3670) * add fragment to foreach (#3877) * Update docker-example (#3324) * /health endpoint for K8 Liveness and Readiness probes (#3855) * Added API Endpoint * Added API Endpoint * Added Unit Tests * Added Unit Tests * main * Apply suggestions from Code Review * Fix Ruff Formatting * Update Socket Events * Async Functions * /health endpoint for K8 Liveness and Readiness probes (#3855) * Added API Endpoint * Added API Endpoint * Added Unit Tests * Added Unit Tests * main * Apply suggestions from Code Review * Fix Ruff Formatting * Update Socket Events * Async Functions * Merge branch 'main' into use-old-serializer-in-literalvar * [REF-3570] Remove deprecated REDIS_URL syntax (#3892) * /health endpoint for K8 Liveness and Readiness probes (#3855) * Added API Endpoint * Added API Endpoint * Added Unit Tests * Added Unit Tests * main * Apply suggestions from Code Review * Fix Ruff Formatting * Update Socket Events * Async Functions * [REF-3570] Remove deprecated REDIS_URL syntax (#3892) * remove extra var Co-authored-by: Masen Furer <m_github@0x26.net> * resolve typo * write better doc for var.create * return var value when we know it's literal var * fix unit test * less bloat for ToOperations * simplify ImmutableComputedVar.__get__ (#3902) * simplify ImmutableComputedVar.__get__ * ruff it --------- Co-authored-by: Samarth Bhadane <samarthbhadane119@gmail.com> Co-authored-by: Elijah Ahianyo <elijahahianyo@gmail.com> Co-authored-by: Masen Furer <m_github@0x26.net> Co-authored-by: benedikt-bartscher <31854409+benedikt-bartscher@users.noreply.github.com> Co-authored-by: Vishnu Deva <vishnu.deva12@gmail.com> Co-authored-by: abulvenz <a.eismann@senbax.de>
230 lines
6.7 KiB
Python
230 lines
6.7 KiB
Python
import datetime
|
|
from enum import Enum
|
|
from pathlib import Path
|
|
from typing import Any, Dict, Type
|
|
|
|
import pytest
|
|
|
|
from reflex.base import Base
|
|
from reflex.components.core.colors import Color
|
|
from reflex.ivars.base import ImmutableVar, LiteralVar
|
|
from reflex.utils import serializers
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"type_,expected",
|
|
[(str, True), (dict, True), (Dict[int, int], True), (Enum, True)],
|
|
)
|
|
def test_has_serializer(type_: Type, expected: bool):
|
|
"""Test that has_serializer returns the correct value.
|
|
|
|
|
|
Args:
|
|
type_: The type to check.
|
|
expected: The expected result.
|
|
"""
|
|
assert serializers.has_serializer(type_) == expected
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"type_,expected",
|
|
[
|
|
(datetime.datetime, serializers.serialize_datetime),
|
|
(datetime.date, serializers.serialize_datetime),
|
|
(datetime.time, serializers.serialize_datetime),
|
|
(datetime.timedelta, serializers.serialize_datetime),
|
|
(Enum, serializers.serialize_enum),
|
|
],
|
|
)
|
|
def test_get_serializer(type_: Type, expected: serializers.Serializer):
|
|
"""Test that get_serializer returns the correct value.
|
|
|
|
|
|
Args:
|
|
type_: The type to check.
|
|
expected: The expected result.
|
|
"""
|
|
assert serializers.get_serializer(type_) == expected
|
|
|
|
|
|
def test_add_serializer():
|
|
"""Test that adding a serializer works."""
|
|
|
|
class Foo:
|
|
"""A test class."""
|
|
|
|
def __init__(self, name: str):
|
|
self.name = name
|
|
|
|
def serialize_foo(value: Foo) -> str:
|
|
"""Serialize an foo to a string.
|
|
|
|
Args:
|
|
value: The value to serialize.
|
|
|
|
Returns:
|
|
The serialized value.
|
|
"""
|
|
return value.name
|
|
|
|
# Initially there should be no serializer for int.
|
|
assert not serializers.has_serializer(Foo)
|
|
assert serializers.serialize(Foo("hi")) is None
|
|
|
|
# Register the serializer.
|
|
assert serializers.serializer(serialize_foo) == serialize_foo
|
|
|
|
# There should now be a serializer for int.
|
|
assert serializers.has_serializer(Foo)
|
|
assert serializers.get_serializer(Foo) == serialize_foo
|
|
assert serializers.serialize(Foo("hi")) == "hi"
|
|
|
|
# Remove the serializer.
|
|
serializers.SERIALIZERS.pop(Foo)
|
|
# LRU cache will still have the serializer, so we need to clear it.
|
|
assert serializers.has_serializer(Foo)
|
|
serializers.get_serializer.cache_clear()
|
|
assert not serializers.has_serializer(Foo)
|
|
|
|
|
|
class StrEnum(str, Enum):
|
|
"""An enum also inheriting from str."""
|
|
|
|
FOO = "foo"
|
|
BAR = "bar"
|
|
|
|
|
|
class TestEnum(Enum):
|
|
"""A lone enum class."""
|
|
|
|
FOO = "foo"
|
|
BAR = "bar"
|
|
|
|
|
|
class EnumWithPrefix(Enum):
|
|
"""An enum with a serializer adding a prefix."""
|
|
|
|
FOO = "foo"
|
|
BAR = "bar"
|
|
|
|
|
|
@serializers.serializer
|
|
def serialize_EnumWithPrefix(enum: EnumWithPrefix) -> str:
|
|
return "prefix_" + enum.value
|
|
|
|
|
|
class BaseSubclass(Base):
|
|
"""A class inheriting from Base for testing."""
|
|
|
|
ts: datetime.timedelta = datetime.timedelta(1, 1, 1)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"value,expected",
|
|
[
|
|
("test", "test"),
|
|
(1, "1"),
|
|
(1.0, "1.0"),
|
|
(True, "true"),
|
|
(False, "false"),
|
|
(None, "null"),
|
|
([1, 2, 3], "[1, 2, 3]"),
|
|
([1, "2", 3.0], '[1, "2", 3.0]'),
|
|
([{"key": 1}, {"key": 2}], '[({ ["key"] : 1 }), ({ ["key"] : 2 })]'),
|
|
(StrEnum.FOO, "foo"),
|
|
([StrEnum.FOO, StrEnum.BAR], '["foo", "bar"]'),
|
|
(
|
|
{"key1": [1, 2, 3], "key2": [StrEnum.FOO, StrEnum.BAR]},
|
|
'({ ["key1"] : [1, 2, 3], ["key2"] : ["foo", "bar"] })',
|
|
),
|
|
(EnumWithPrefix.FOO, "prefix_foo"),
|
|
([EnumWithPrefix.FOO, EnumWithPrefix.BAR], '["prefix_foo", "prefix_bar"]'),
|
|
(
|
|
{"key1": EnumWithPrefix.FOO, "key2": EnumWithPrefix.BAR},
|
|
'({ ["key1"] : "prefix_foo", ["key2"] : "prefix_bar" })',
|
|
),
|
|
(TestEnum.FOO, "foo"),
|
|
([TestEnum.FOO, TestEnum.BAR], '["foo", "bar"]'),
|
|
(
|
|
{"key1": TestEnum.FOO, "key2": TestEnum.BAR},
|
|
'({ ["key1"] : "foo", ["key2"] : "bar" })',
|
|
),
|
|
(
|
|
BaseSubclass(ts=datetime.timedelta(1, 1, 1)),
|
|
'({ ["ts"] : "1 day, 0:00:01.000001" })',
|
|
),
|
|
(
|
|
[1, LiteralVar.create("hi"), ImmutableVar.create("bye")],
|
|
'[1, "hi", bye]',
|
|
),
|
|
(
|
|
(1, LiteralVar.create("hi"), ImmutableVar.create("bye")),
|
|
'[1, "hi", bye]',
|
|
),
|
|
({1: 2, 3: 4}, "({ [1] : 2, [3] : 4 })"),
|
|
(
|
|
{1: LiteralVar.create("hi"), 3: ImmutableVar.create("bye")},
|
|
'({ [1] : "hi", [3] : bye })',
|
|
),
|
|
(datetime.datetime(2021, 1, 1, 1, 1, 1, 1), "2021-01-01 01:01:01.000001"),
|
|
(datetime.date(2021, 1, 1), "2021-01-01"),
|
|
(datetime.time(1, 1, 1, 1), "01:01:01.000001"),
|
|
(datetime.timedelta(1, 1, 1), "1 day, 0:00:01.000001"),
|
|
(
|
|
[datetime.timedelta(1, 1, 1), datetime.timedelta(1, 1, 2)],
|
|
'["1 day, 0:00:01.000001", "1 day, 0:00:01.000002"]',
|
|
),
|
|
(Color(color="slate", shade=1), "var(--slate-1)"),
|
|
(Color(color="orange", shade=1, alpha=True), "var(--orange-a1)"),
|
|
(Color(color="accent", shade=1, alpha=True), "var(--accent-a1)"),
|
|
],
|
|
)
|
|
def test_serialize(value: Any, expected: str):
|
|
"""Test that serialize returns the correct value.
|
|
|
|
|
|
Args:
|
|
value: The value to serialize.
|
|
expected: The expected result.
|
|
"""
|
|
assert serializers.serialize(value) == expected
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"value,expected,exp_var_is_string",
|
|
[
|
|
("test", '"test"', False),
|
|
(1, "1", False),
|
|
(1.0, "1.0", False),
|
|
(True, "true", False),
|
|
(False, "false", False),
|
|
([1, 2, 3], "[1, 2, 3]", False),
|
|
([{"key": 1}, {"key": 2}], '[({ ["key"] : 1 }), ({ ["key"] : 2 })]', False),
|
|
(StrEnum.FOO, '"foo"', False),
|
|
([StrEnum.FOO, StrEnum.BAR], '["foo", "bar"]', False),
|
|
(
|
|
BaseSubclass(ts=datetime.timedelta(1, 1, 1)),
|
|
'({ ["ts"] : "1 day, 0:00:01.000001" })',
|
|
False,
|
|
),
|
|
(
|
|
datetime.datetime(2021, 1, 1, 1, 1, 1, 1),
|
|
'"2021-01-01 01:01:01.000001"',
|
|
True,
|
|
),
|
|
(Color(color="slate", shade=1), '"var(--slate-1)"', True),
|
|
(BaseSubclass, '"BaseSubclass"', True),
|
|
(Path("."), '"."', True),
|
|
],
|
|
)
|
|
def test_serialize_var_to_str(value: Any, expected: str, exp_var_is_string: bool):
|
|
"""Test that serialize with `to=str` passed to a Var is marked with _var_is_string.
|
|
|
|
Args:
|
|
value: The value to serialize.
|
|
expected: The expected result.
|
|
exp_var_is_string: The expected value of _var_is_string.
|
|
"""
|
|
v = LiteralVar.create(value)
|
|
assert str(v) == expected
|