Force pydantic v1 for sqlmodel compatibility (#3026)
This commit is contained in:
parent
9073a2781b
commit
d7abcd45de
6
.github/workflows/unit_tests.yml
vendored
6
.github/workflows/unit_tests.yml
vendored
@ -76,4 +76,10 @@ jobs:
|
|||||||
export PYTHONUNBUFFERED=1
|
export PYTHONUNBUFFERED=1
|
||||||
export REDIS_URL=redis://localhost:6379
|
export REDIS_URL=redis://localhost:6379
|
||||||
poetry run pytest tests --cov --no-cov-on-fail --cov-report=
|
poetry run pytest tests --cov --no-cov-on-fail --cov-report=
|
||||||
|
# Change to explicitly install v1 when reflex-hosting-cli is compatible with v2
|
||||||
|
- name: Run unit tests w/ pydantic v2
|
||||||
|
run: |
|
||||||
|
export PYTHONUNBUFFERED=1
|
||||||
|
poetry run pip install "pydantic>2"
|
||||||
|
poetry run pytest tests --cov --no-cov-on-fail --cov-report=
|
||||||
- run: poetry run coverage html
|
- run: poetry run coverage html
|
||||||
|
@ -11,7 +11,7 @@ try:
|
|||||||
# reflex-hosting-cli tools are compatible with pydantic v2
|
# reflex-hosting-cli tools are compatible with pydantic v2
|
||||||
|
|
||||||
if not TYPE_CHECKING:
|
if not TYPE_CHECKING:
|
||||||
import pydantic.v1.fields as ModelField
|
from pydantic.v1.fields import ModelField
|
||||||
else:
|
else:
|
||||||
raise ModuleNotFoundError
|
raise ModuleNotFoundError
|
||||||
except ModuleNotFoundError:
|
except ModuleNotFoundError:
|
||||||
|
@ -16,12 +16,12 @@ import alembic.script
|
|||||||
import alembic.util
|
import alembic.util
|
||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
import sqlalchemy.orm
|
import sqlalchemy.orm
|
||||||
import sqlmodel
|
|
||||||
|
|
||||||
from reflex import constants
|
from reflex import constants
|
||||||
from reflex.base import Base
|
from reflex.base import Base
|
||||||
from reflex.config import get_config
|
from reflex.config import get_config
|
||||||
from reflex.utils import console
|
from reflex.utils import console
|
||||||
|
from reflex.utils.compat import sqlmodel
|
||||||
|
|
||||||
|
|
||||||
def get_engine(url: str | None = None):
|
def get_engine(url: str | None = None):
|
||||||
|
43
reflex/utils/compat.py
Normal file
43
reflex/utils/compat.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
"""Compatibility hacks and helpers."""
|
||||||
|
|
||||||
|
import contextlib
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def pydantic_v1_patch():
|
||||||
|
"""A context manager that patches the Pydantic module to mimic v1 behaviour.
|
||||||
|
|
||||||
|
Yields:
|
||||||
|
None when the Pydantic module is patched.
|
||||||
|
"""
|
||||||
|
patched_modules = [
|
||||||
|
"pydantic",
|
||||||
|
"pydantic.fields",
|
||||||
|
"pydantic.errors",
|
||||||
|
"pydantic.main",
|
||||||
|
]
|
||||||
|
originals = {module: sys.modules.get(module) for module in patched_modules}
|
||||||
|
try:
|
||||||
|
import pydantic.v1 # type: ignore
|
||||||
|
|
||||||
|
sys.modules["pydantic.fields"] = pydantic.v1.fields # type: ignore
|
||||||
|
sys.modules["pydantic.main"] = pydantic.v1.main # type: ignore
|
||||||
|
sys.modules["pydantic.errors"] = pydantic.v1.errors # type: ignore
|
||||||
|
sys.modules["pydantic"] = pydantic.v1
|
||||||
|
yield
|
||||||
|
except (ImportError, AttributeError):
|
||||||
|
# pydantic v1 is already installed
|
||||||
|
yield
|
||||||
|
finally:
|
||||||
|
# Restore the original Pydantic module
|
||||||
|
for k, original in originals.items():
|
||||||
|
if k in sys.modules:
|
||||||
|
if original:
|
||||||
|
sys.modules[k] = original
|
||||||
|
else:
|
||||||
|
del sys.modules[k]
|
||||||
|
|
||||||
|
|
||||||
|
with pydantic_v1_patch():
|
||||||
|
import sqlmodel as sqlmodel
|
@ -29,7 +29,7 @@ try:
|
|||||||
# reflex-hosting-cli tools are compatible with pydantic v2
|
# reflex-hosting-cli tools are compatible with pydantic v2
|
||||||
|
|
||||||
if not TYPE_CHECKING:
|
if not TYPE_CHECKING:
|
||||||
import pydantic.v1.fields as ModelField
|
from pydantic.v1.fields import ModelField
|
||||||
else:
|
else:
|
||||||
raise ModuleNotFoundError
|
raise ModuleNotFoundError
|
||||||
except ModuleNotFoundError:
|
except ModuleNotFoundError:
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
from typing import Dict, List, Set, Tuple
|
from typing import Dict, List, Set, Tuple
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from pydantic import ValidationError
|
|
||||||
|
|
||||||
from reflex.components import box, foreach, text, theme
|
from reflex.components import box, foreach, text, theme
|
||||||
from reflex.components.core import Foreach
|
from reflex.components.core import Foreach
|
||||||
from reflex.state import BaseState
|
from reflex.state import BaseState
|
||||||
|
|
||||||
|
try:
|
||||||
|
# When pydantic v2 is installed
|
||||||
|
from pydantic.v1 import ValidationError # type: ignore
|
||||||
|
except ImportError:
|
||||||
|
from pydantic import ValidationError
|
||||||
|
|
||||||
|
|
||||||
class ForEachState(BaseState):
|
class ForEachState(BaseState):
|
||||||
"""A state for testing the ForEach component."""
|
"""A state for testing the ForEach component."""
|
||||||
|
Loading…
Reference in New Issue
Block a user