
If pydantic v1 is already installed, there is no reason to restore the original pydantic modules, which seems to introduce subtle incompatibilities with some pydantic versions. Perform the pydantic version check early on and exit for v1 before doing anything with the sys.modules. Fix #3642
72 lines
2.0 KiB
Python
72 lines
2.0 KiB
Python
"""Compatibility hacks and helpers."""
|
|
|
|
import contextlib
|
|
import sys
|
|
|
|
|
|
async def windows_hot_reload_lifespan_hack():
|
|
"""[REF-3164] A hack to fix hot reload on Windows.
|
|
|
|
Uvicorn has an issue stopping itself on Windows after detecting changes in
|
|
the filesystem.
|
|
|
|
This workaround repeatedly prints and flushes null characters to stderr,
|
|
which seems to allow the uvicorn server to exit when the CTRL-C signal is
|
|
sent from the reloader process.
|
|
|
|
Don't ask me why this works, I discovered it by accident - masenf.
|
|
"""
|
|
import asyncio
|
|
import sys
|
|
|
|
while True:
|
|
sys.stderr.write("\0")
|
|
sys.stderr.flush()
|
|
await asyncio.sleep(0.5)
|
|
|
|
|
|
@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.
|
|
"""
|
|
import pydantic
|
|
|
|
if pydantic.__version__.startswith("1."):
|
|
# pydantic v1 is already installed
|
|
yield
|
|
return
|
|
|
|
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
|