compat.py 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. """Compatibility hacks and helpers."""
  2. import contextlib
  3. import sys
  4. from typing import Any
  5. async def windows_hot_reload_lifespan_hack():
  6. """[REF-3164] A hack to fix hot reload on Windows.
  7. Uvicorn has an issue stopping itself on Windows after detecting changes in
  8. the filesystem.
  9. This workaround repeatedly prints and flushes null characters to stderr,
  10. which seems to allow the uvicorn server to exit when the CTRL-C signal is
  11. sent from the reloader process.
  12. Don't ask me why this works, I discovered it by accident - masenf.
  13. """
  14. import asyncio
  15. import sys
  16. try:
  17. while True:
  18. sys.stderr.write("\0")
  19. sys.stderr.flush()
  20. await asyncio.sleep(0.5)
  21. except asyncio.CancelledError:
  22. pass
  23. @contextlib.contextmanager
  24. def pydantic_v1_patch():
  25. """A context manager that patches the Pydantic module to mimic v1 behaviour.
  26. Yields:
  27. None when the Pydantic module is patched.
  28. """
  29. import pydantic
  30. if pydantic.__version__.startswith("1."):
  31. # pydantic v1 is already installed
  32. yield
  33. return
  34. patched_modules = [
  35. "pydantic",
  36. "pydantic.fields",
  37. "pydantic.errors",
  38. "pydantic.main",
  39. ]
  40. originals = {module: sys.modules.get(module) for module in patched_modules}
  41. try:
  42. import pydantic.v1
  43. sys.modules["pydantic.fields"] = pydantic.v1.fields # pyright: ignore [reportAttributeAccessIssue]
  44. sys.modules["pydantic.main"] = pydantic.v1.main # pyright: ignore [reportAttributeAccessIssue]
  45. sys.modules["pydantic.errors"] = pydantic.v1.errors # pyright: ignore [reportAttributeAccessIssue]
  46. sys.modules["pydantic"] = pydantic.v1
  47. yield
  48. except (ImportError, AttributeError):
  49. # pydantic v1 is already installed
  50. yield
  51. finally:
  52. # Restore the original Pydantic module
  53. for k, original in originals.items():
  54. if k in sys.modules:
  55. if original:
  56. sys.modules[k] = original
  57. else:
  58. del sys.modules[k]
  59. with pydantic_v1_patch():
  60. import sqlmodel as sqlmodel
  61. def sqlmodel_field_has_primary_key(field: Any) -> bool:
  62. """Determines if a field is a priamary.
  63. Args:
  64. field: a rx.model field
  65. Returns:
  66. If field is a primary key (Bool)
  67. """
  68. if getattr(field.field_info, "primary_key", None) is True:
  69. return True
  70. if getattr(field.field_info, "sa_column", None) is None:
  71. return False
  72. return bool(getattr(field.field_info.sa_column, "primary_key", None))