1
0

test_object.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. import dataclasses
  2. import pytest
  3. from sqlalchemy.orm import DeclarativeBase, Mapped, MappedAsDataclass, mapped_column
  4. from typing_extensions import assert_type
  5. import reflex as rx
  6. from reflex.utils.types import GenericType
  7. from reflex.vars.base import Var
  8. from reflex.vars.object import LiteralObjectVar, ObjectVar
  9. from reflex.vars.sequence import ArrayVar
  10. class Bare:
  11. """A bare class with a single attribute."""
  12. quantity: int = 0
  13. @rx.serializer
  14. def serialize_bare(obj: Bare) -> dict:
  15. """A serializer for the bare class.
  16. Args:
  17. obj: The object to serialize.
  18. Returns:
  19. A dictionary with the quantity attribute.
  20. """
  21. return {"quantity": obj.quantity}
  22. class Base(rx.Base):
  23. """A reflex base class with a single attribute."""
  24. quantity: int = 0
  25. class SqlaBase(DeclarativeBase, MappedAsDataclass):
  26. """Sqlalchemy declarative mapping base class."""
  27. pass
  28. class SqlaModel(SqlaBase):
  29. """A sqlalchemy model with a single attribute."""
  30. __tablename__: str = "sqla_model"
  31. id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True, init=False)
  32. quantity: Mapped[int] = mapped_column(default=0)
  33. @dataclasses.dataclass
  34. class Dataclass:
  35. """A dataclass with a single attribute."""
  36. quantity: int = 0
  37. class ObjectState(rx.State):
  38. """A reflex state with bare, base and sqlalchemy base vars."""
  39. bare: rx.Field[Bare] = rx.field(Bare())
  40. bare_optional: rx.Field[Bare | None] = rx.field(None)
  41. base: rx.Field[Base] = rx.field(Base())
  42. base_optional: rx.Field[Base | None] = rx.field(None)
  43. sqlamodel: rx.Field[SqlaModel] = rx.field(SqlaModel())
  44. sqlamodel_optional: rx.Field[SqlaModel | None] = rx.field(None)
  45. dataclass: rx.Field[Dataclass] = rx.field(Dataclass())
  46. dataclass_optional: rx.Field[Dataclass | None] = rx.field(None)
  47. base_list: rx.Field[list[Base]] = rx.field([Base()])
  48. @pytest.mark.parametrize("type_", [Base, Bare, SqlaModel, Dataclass])
  49. def test_var_create(type_: type[Base | Bare | SqlaModel | Dataclass]) -> None:
  50. my_object = type_()
  51. var = Var.create(my_object)
  52. assert var._var_type is type_
  53. assert isinstance(var, ObjectVar)
  54. quantity = var.quantity
  55. assert quantity._var_type is int
  56. @pytest.mark.parametrize("type_", [Base, Bare, SqlaModel, Dataclass])
  57. def test_literal_create(type_: GenericType) -> None:
  58. my_object = type_()
  59. var = LiteralObjectVar.create(my_object)
  60. assert var._var_type is type_
  61. quantity = var.quantity
  62. assert quantity._var_type is int
  63. @pytest.mark.parametrize("type_", [Base, Bare, SqlaModel, Dataclass])
  64. def test_guess(type_: type[Base | Bare | SqlaModel | Dataclass]) -> None:
  65. my_object = type_()
  66. var = Var.create(my_object)
  67. var = var.guess_type()
  68. assert var._var_type is type_
  69. assert isinstance(var, ObjectVar)
  70. quantity = var.quantity
  71. assert quantity._var_type is int
  72. @pytest.mark.parametrize("type_", [Base, Bare, SqlaModel, Dataclass])
  73. def test_state(type_: GenericType) -> None:
  74. attr_name = type_.__name__.lower()
  75. var = getattr(ObjectState, attr_name)
  76. assert var._var_type is type_
  77. quantity = var.quantity
  78. assert quantity._var_type is int
  79. @pytest.mark.parametrize("type_", [Base, Bare, SqlaModel, Dataclass])
  80. def test_state_to_operation(type_: GenericType) -> None:
  81. attr_name = type_.__name__.lower()
  82. original_var = getattr(ObjectState, attr_name)
  83. var = original_var.to(ObjectVar, type_)
  84. assert var._var_type is type_
  85. var = original_var.to(ObjectVar)
  86. assert var._var_type is type_
  87. def test_typing() -> None:
  88. # Bare
  89. var = ObjectState.bare.to(ObjectVar)
  90. _ = assert_type(var, ObjectVar[Bare])
  91. # Base
  92. var = ObjectState.base
  93. _ = assert_type(var, ObjectVar[Base])
  94. optional_var = ObjectState.base_optional
  95. _ = assert_type(optional_var, ObjectVar[Base | None])
  96. list_var = ObjectState.base_list
  97. _ = assert_type(list_var, ArrayVar[list[Base]])
  98. list_var_0 = list_var[0]
  99. _ = assert_type(list_var_0, ObjectVar[Base])
  100. # Sqla
  101. var = ObjectState.sqlamodel
  102. _ = assert_type(var, ObjectVar[SqlaModel])
  103. optional_var = ObjectState.sqlamodel_optional
  104. _ = assert_type(optional_var, ObjectVar[SqlaModel | None])
  105. list_var = ObjectState.base_list
  106. _ = assert_type(list_var, ArrayVar[list[Base]])
  107. list_var_0 = list_var[0]
  108. _ = assert_type(list_var_0, ObjectVar[Base])
  109. # Dataclass
  110. var = ObjectState.dataclass
  111. _ = assert_type(var, ObjectVar[Dataclass])
  112. optional_var = ObjectState.dataclass_optional
  113. _ = assert_type(optional_var, ObjectVar[Dataclass | None])
  114. list_var = ObjectState.base_list
  115. _ = assert_type(list_var, ArrayVar[list[Base]])
  116. list_var_0 = list_var[0]
  117. _ = assert_type(list_var_0, ObjectVar[Base])