Force pydantic v1 for sqlmodel compatibility (#3026)

This commit is contained in:
Masen Furer 2024-04-11 13:42:30 -07:00 committed by GitHub
parent 9073a2781b
commit d7abcd45de
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 58 additions and 4 deletions

View File

@ -76,4 +76,10 @@ jobs:
export PYTHONUNBUFFERED=1
export REDIS_URL=redis://localhost:6379
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

View File

@ -11,7 +11,7 @@ try:
# reflex-hosting-cli tools are compatible with pydantic v2
if not TYPE_CHECKING:
import pydantic.v1.fields as ModelField
from pydantic.v1.fields import ModelField
else:
raise ModuleNotFoundError
except ModuleNotFoundError:

View File

@ -16,12 +16,12 @@ import alembic.script
import alembic.util
import sqlalchemy
import sqlalchemy.orm
import sqlmodel
from reflex import constants
from reflex.base import Base
from reflex.config import get_config
from reflex.utils import console
from reflex.utils.compat import sqlmodel
def get_engine(url: str | None = None):

43
reflex/utils/compat.py Normal file
View 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

View File

@ -29,7 +29,7 @@ try:
# reflex-hosting-cli tools are compatible with pydantic v2
if not TYPE_CHECKING:
import pydantic.v1.fields as ModelField
from pydantic.v1.fields import ModelField
else:
raise ModuleNotFoundError
except ModuleNotFoundError:

View File

@ -1,12 +1,17 @@
from typing import Dict, List, Set, Tuple
import pytest
from pydantic import ValidationError
from reflex.components import box, foreach, text, theme
from reflex.components.core import Foreach
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):
"""A state for testing the ForEach component."""