Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pydantic v2 still not compatible with Reflex 0.4.6 loosened requirements? #3019

Closed
TimChild opened this issue Apr 5, 2024 · 4 comments · Fixed by #3026
Closed

Pydantic v2 still not compatible with Reflex 0.4.6 loosened requirements? #3019

TimChild opened this issue Apr 5, 2024 · 4 comments · Fixed by #3026

Comments

@TimChild
Copy link
Contributor

TimChild commented Apr 5, 2024

Describe the bug
I see in the notes for the v0.4.6 release that the requirements for reflex were loosened to allow Pydantic v2, however, I'm still running into an issue with reflex depending on reflex-hosting-cli which depends on pydantic < 2.

Poetry error:

...
Because reflex-hosting-cli (0.1.10) depends on pydantic (>=1.10.2,<2.0.0)
...

It seems like #2777 was about this issue, and was closed with #2796, but I guess the reflex-hosting-cli part was not addressed yet?

Is there going to be a new release of the hosting-cli with loosened dependencies soon?

Other related issues and PRs:
#1539

To Reproduce
Steps to reproduce the behavior:

  • Init new poetry project
  • Add pydantic>=2.0.0 as a dependency
  • Try to add reflex as another dependency

Expected behavior
Should be solvable given the loosend requirements for reflex

Specifics (please complete the following information):

  • Python Version: 3.11
  • Reflex Version: v0.4.6
  • OS: Windows/Linux
  • Poetry: 1.7.0
@masenf
Copy link
Collaborator

masenf commented Apr 5, 2024

Even after relaxing the reflex-hosting-cli pydantic pin, there is still a fundamental incompatibility with Reflex using v1 (imported from v2) and SQLModel changing how it works based on which pydantic version is installed.

I'm looking into the issue in the next few days, but I think Reflex will need to fully go to pydantic v2 and drop v1 support entirely.

@TimChild
Copy link
Contributor Author

TimChild commented Apr 5, 2024

Yep... I'm running into those issues now too... (I temporarily copied the reflex-hosting-cli and loosened the pydantic requirements to try it out).

I think you are right that the best option is for Reflex to go fully to pydantic v2 (very excited for this!!!). In the meantime, I have had some success with this hacky solution...

@contextlib.contextmanager
def pydantic_v1_patch():
    """
    A context manager that patches the Pydantic module to mimic v1 behaviour
    """
    patched_modules = [
        "pydantic",
        "pydantic.fields",
        "pydantic.errors",
        "pydantic.main",
    ]
    originals = {module: sys.modules.get(module) for module in patched_modules}
    try:
        import pydantic.v1
        sys.modules["pydantic"] = pydantic.v1
        sys.modules["pydantic.fields"] = pydantic.v1.fields
        sys.modules["pydantic.main"] = pydantic.v1.main
        sys.modules["pydantic.errors"] = pydantic.v1.errors
        print("Patched Pydantic to v1")
        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]
        print("Restored Pydantic to original")


with pydantic_v1_patch():
    import sqlmodel as sqlmodel

I.e. importing sqlmodel in a context where it thinks pydantic v1 is installed before anything reflex related.

Additionally, I think there is a small mistake in the reflex repo at reflex/utils/types.py:32:

try:
    # TODO The type checking guard can be removed once
    # reflex-hosting-cli tools are compatible with pydantic v2

    if not TYPE_CHECKING:
        # import pydantic.v1.fields as ModelField   # <<< This is wrong
        from pydantic.v1.fields import ModelField  # <<< Should be this
    else:
        raise ModuleNotFoundError
except ModuleNotFoundError:
    from pydantic.fields import ModelField

I think a full migration to v2 is best, but maybe worth considering this as an option in the meantime since anyone using SQLModel with reflex will anyway be using pydantic v1 currently.

@masenf
Copy link
Collaborator

masenf commented Apr 5, 2024

This is a cool albeit super hacky approach. My plan was to just let the Model use pydantic v2, even tho everything else is using v1... but that's a lot more code change.

I kinda like your hack for the next few releases until we can get our full v2 migration merged in (0.5.0 is the milestone for that)

@TimChild
Copy link
Contributor Author

TimChild commented Apr 5, 2024

Yep, surely is hacky, but as you say, might be a good temporary solution until 0.5.0.

masenf added a commit that referenced this issue Apr 6, 2024
When importing sqlmodel, we need to fake like pydantic v2 is actually v1 for
compatibility with Reflex's rx.Base (which is still based on pydantic v1
BaseModel)

Inspired by #3019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants