fix: import sqlalchemy.ext.asyncio lazily so reflex.model loads without greenlet
All Submissions:
- Have you followed the guidelines stated in CONTRIBUTING.md file?
- Have you checked to ensure there aren't any other open Pull Requests for the desired changed?
Type of change
- Bug fix (non-breaking change which fixes an issue)
Changes To Core Features:
- Have you added an explanation of what your changes do and why you'd like us to include them?
- Have you written new tests for your core changes, as applicable?
- Have you successfully ran tests with your changes locally?
Description
reflex/model.py imported sqlalchemy.ext.asyncio at module level. SQLAlchemy 2.1 only installs greenlet with its asyncio extra, and without it that import raises ImportError. So import reflex.model, and with it rx.ModelRegistry, rx.session and rx.Model, failed even for apps that never use async sessions.
sqlalchemy.ext.asyncio and sqlmodel's AsyncSession (which imports the same module) are no longer imported at module level, only under TYPE_CHECKING for the annotations. get_async_engine and asession import them when called, so with greenlet installed nothing changes, and without it reflex.model imports fine and those two raise the greenlet ImportError on first use.
Before / After, in a fresh venv with SQLAlchemy 2.1.3 and no greenlet:
# before (upstream/main)
$ python -c "import reflex as rx; rx.ModelRegistry"
ImportError: The SQLAlchemy asyncio module requires that the Python 'greenlet' library is installed. ...
$ python -c "import reflex.model"
File ".../reflex/model.py", line 69, in <module>
ImportError: The SQLAlchemy asyncio module requires that the Python 'greenlet' library is installed. ...
# after
$ python -c "import reflex as rx; rx.ModelRegistry" # no error
$ python -c "import reflex.model; print('ok')"
ok
I could not exercise rx.session() itself on 2.1, since sqlmodel still requires SQLAlchemy < 2.1. The regression test covers it by blocking sqlalchemy.ext.asyncio in a subprocess.
Fixes #7421