Browse Source

added changes for datetime (#1745)

* added changes for datetime

* fixed formatting

* fixed darglint issue

* test_state: check for other datetime module classes

* utils/types.py: use issubclass check

fix docstring copy/paste issue

* utils/format.py: reuse types.is_datetime check

---------

Co-authored-by: Masen Furer <m_github@0x26.net>
wassaf shahzad 1 year ago
parent
commit
e99d6723bc
3 changed files with 74 additions and 0 deletions
  1. 4 0
      reflex/utils/format.py
  2. 14 0
      reflex/utils/types.py
  3. 56 0
      tests/test_state.py

+ 4 - 0
reflex/utils/format.py

@@ -513,6 +513,10 @@ def format_state(value: Any) -> Any:
             "data": format_dataframe_values(value),
         }
 
+    # Convert datetime objects to str.
+    if types.is_datetime(type(value)):
+        return str(value)
+
     # Convert Image objects to base64.
     if types.is_image(type(value)):
         return format_image_data(value)  # type: ignore

+ 14 - 0
reflex/utils/types.py

@@ -4,6 +4,7 @@ from __future__ import annotations
 
 import contextlib
 import typing
+from datetime import date, datetime, time, timedelta
 from typing import Any, Callable, Type, Union, _GenericAlias  # type: ignore
 
 from reflex.base import Base
@@ -168,6 +169,18 @@ def is_figure(value: Type) -> bool:
     return value.__name__ == "Figure"
 
 
+def is_datetime(value: Type) -> bool:
+    """Check if the given value is a datetime object.
+
+    Args:
+        value: The value to check.
+
+    Returns:
+        Whether the value is a date, datetime, time, or timedelta.
+    """
+    return issubclass(value, (date, datetime, time, timedelta))
+
+
 def is_valid_var_type(var: Type) -> bool:
     """Check if the given value is a valid prop type.
 
@@ -182,6 +195,7 @@ def is_valid_var_type(var: Type) -> bool:
         or is_dataframe(var)
         or is_figure(var)
         or is_image(var)
+        or is_datetime(var)
     )
 
 

+ 56 - 0
tests/test_state.py

@@ -1,5 +1,6 @@
 from __future__ import annotations
 
+import datetime
 import functools
 from typing import Dict, List
 
@@ -37,6 +38,7 @@ class TestState(State):
     obj: Object = Object()
     complex: Dict[int, Object] = {1: Object(), 2: Object()}
     fig: Figure = Figure()
+    dt: datetime.datetime = datetime.datetime.fromisoformat("1989-11-09T18:53:00+01:00")
 
     @ComputedVar
     def sum(self) -> float:
@@ -202,6 +204,7 @@ def test_class_vars(test_state):
         "sum",
         "upper",
         "fig",
+        "dt",
     }
 
 
@@ -267,6 +270,58 @@ def test_dict(test_state):
     )
 
 
+def test_format_state(test_state):
+    """Test that the format state is correct.
+
+    Args:
+        test_state: A state.
+    """
+    formatted_state = format.format_state(test_state.dict())
+    exp_formatted_state = {
+        "array": [1, 2, 3.14],
+        "child_state": {"count": 23, "grandchild_state": {"value2": ""}, "value": ""},
+        "child_state2": {"value": ""},
+        "complex": {
+            1: {"prop1": 42, "prop2": "hello"},
+            2: {"prop1": 42, "prop2": "hello"},
+        },
+        "dt": "1989-11-09 18:53:00+01:00",
+        "fig": [],
+        "is_hydrated": False,
+        "key": "",
+        "map_key": "a",
+        "mapping": {"a": [1, 2, 3], "b": [4, 5, 6]},
+        "num1": 0,
+        "num2": 3.14,
+        "obj": {"prop1": 42, "prop2": "hello"},
+        "sum": 3.14,
+        "upper": "",
+    }
+    assert formatted_state == exp_formatted_state
+
+
+def test_format_state_datetime():
+    """Test that the format state is correct for datetime classes."""
+
+    class DateTimeState(State):
+        d: datetime.date = datetime.date.fromisoformat("1989-11-09")
+        dt: datetime.datetime = datetime.datetime.fromisoformat(
+            "1989-11-09T18:53:00+01:00"
+        )
+        t: datetime.time = datetime.time.fromisoformat("18:53:00+01:00")
+        td: datetime.timedelta = datetime.timedelta(days=11, minutes=11)
+
+    formatted_state = format.format_state(DateTimeState().dict())
+    exp_formatted_state = {
+        "d": "1989-11-09",
+        "dt": "1989-11-09 18:53:00+01:00",
+        "is_hydrated": False,
+        "t": "18:53:00+01:00",
+        "td": "11 days, 0:11:00",
+    }
+    assert formatted_state == exp_formatted_state
+
+
 def test_default_setters(test_state):
     """Test that we can set default values.
 
@@ -575,6 +630,7 @@ def test_reset(test_state, child_state):
         "array",
         "map_key",
         "mapping",
+        "dt",
     }
 
     # The dirty vars should be reset.