fastapi-viewsets 1.2.0__tar.gz → 1.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/PKG-INFO +1 -1
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/fastapi_viewsets/orm/sqlalchemy_adapter.py +12 -6
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/fastapi_viewsets.egg-info/PKG-INFO +1 -1
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/fastapi_viewsets.egg-info/SOURCES.txt +1 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/pyproject.toml +5 -3
- fastapi_viewsets-1.2.1/tests/test_async_driver_missing.py +57 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/LICENSE +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/README.md +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/fastapi_viewsets/__init__.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/fastapi_viewsets/_compat.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/fastapi_viewsets/_register.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/fastapi_viewsets/async_base.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/fastapi_viewsets/async_utils.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/fastapi_viewsets/constants.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/fastapi_viewsets/db_conf.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/fastapi_viewsets/orm/__init__.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/fastapi_viewsets/orm/base.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/fastapi_viewsets/orm/factory.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/fastapi_viewsets/orm/peewee_adapter.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/fastapi_viewsets/orm/tortoise_adapter.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/fastapi_viewsets/utils.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/fastapi_viewsets.egg-info/dependency_links.txt +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/fastapi_viewsets.egg-info/requires.txt +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/fastapi_viewsets.egg-info/top_level.txt +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/setup.cfg +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/setup.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/tests/test_adapter_methods_coverage.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/tests/test_async_base_viewset.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/tests/test_async_utils.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/tests/test_backward_compatibility.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/tests/test_base_viewset.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/tests/test_coverage_gaps.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/tests/test_db_conf.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/tests/test_db_conf_extended.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/tests/test_edge_cases.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/tests/test_error_handling.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/tests/test_exception_handling.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/tests/test_integration.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/tests/test_missing_coverage.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/tests/test_orm_adapters.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/tests/test_orm_adapters_extended.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/tests/test_utils.py +0 -0
- {fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/tests/test_viewsets_with_adapters.py +0 -0
{fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/fastapi_viewsets/orm/sqlalchemy_adapter.py
RENAMED
|
@@ -67,19 +67,25 @@ class SQLAlchemyAdapter(BaseORMAdapter):
|
|
|
67
67
|
|
|
68
68
|
self.Base.query = self.db_session.query_property()
|
|
69
69
|
|
|
70
|
-
# Setup async engine and session
|
|
70
|
+
# Setup async engine and session.
|
|
71
|
+
#
|
|
72
|
+
# The async engine is best-effort: if the matching async DB-API
|
|
73
|
+
# driver (aiosqlite, asyncpg, aiomysql, ...) is not installed we
|
|
74
|
+
# fall back to ``async_engine = None`` so that purely synchronous
|
|
75
|
+
# usage still works. The error is re-raised lazily from
|
|
76
|
+
# :meth:`get_async_session` with installation hints.
|
|
71
77
|
if async_engine:
|
|
72
78
|
self.async_engine = async_engine
|
|
73
|
-
elif async_database_url:
|
|
74
|
-
self.async_engine = create_async_engine(async_database_url, echo=False)
|
|
75
79
|
else:
|
|
76
|
-
|
|
77
|
-
async_url = self._get_async_database_url()
|
|
80
|
+
async_url = async_database_url or self._get_async_database_url()
|
|
78
81
|
try:
|
|
79
82
|
self.async_engine = create_async_engine(async_url, echo=False)
|
|
80
83
|
except Exception:
|
|
84
|
+
# Missing async DB-API driver (aiosqlite/asyncpg/aiomysql),
|
|
85
|
+
# or no async dialect for this URL — degrade to sync-only mode.
|
|
86
|
+
# The error is re-raised lazily from ``get_async_session``.
|
|
81
87
|
self.async_engine = None
|
|
82
|
-
|
|
88
|
+
|
|
83
89
|
if self.async_engine:
|
|
84
90
|
self.AsyncSessionLocal = async_sessionmaker(
|
|
85
91
|
self.async_engine,
|
|
@@ -24,6 +24,7 @@ fastapi_viewsets/orm/sqlalchemy_adapter.py
|
|
|
24
24
|
fastapi_viewsets/orm/tortoise_adapter.py
|
|
25
25
|
tests/test_adapter_methods_coverage.py
|
|
26
26
|
tests/test_async_base_viewset.py
|
|
27
|
+
tests/test_async_driver_missing.py
|
|
27
28
|
tests/test_async_utils.py
|
|
28
29
|
tests/test_backward_compatibility.py
|
|
29
30
|
tests/test_base_viewset.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "fastapi_viewsets"
|
|
7
|
-
version = "1.2.
|
|
7
|
+
version = "1.2.1"
|
|
8
8
|
description = "DRF-style viewsets for FastAPI with SQLAlchemy/Tortoise/Peewee adapters and Pydantic v2 support."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -51,8 +51,10 @@ Homepage = "https://github.com/svalench/fastapi_viewsets"
|
|
|
51
51
|
Issues = "https://github.com/svalench/fastapi_viewsets/issues"
|
|
52
52
|
Changelog = "https://github.com/svalench/fastapi_viewsets/blob/main/RELEASE_NOTES.md"
|
|
53
53
|
|
|
54
|
-
[tool.setuptools]
|
|
55
|
-
|
|
54
|
+
[tool.setuptools.packages.find]
|
|
55
|
+
where = ["."]
|
|
56
|
+
include = ["fastapi_viewsets*"]
|
|
57
|
+
exclude = ["tests*"]
|
|
56
58
|
|
|
57
59
|
[tool.black]
|
|
58
60
|
line-length = 100
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""Regression test for v1.2.1.
|
|
2
|
+
|
|
3
|
+
When ``async_database_url`` is provided but the corresponding async DB-API
|
|
4
|
+
driver (e.g. ``aiosqlite``) is not installed, ``SQLAlchemyAdapter.__init__``
|
|
5
|
+
must degrade gracefully to sync-only mode instead of raising
|
|
6
|
+
``ModuleNotFoundError`` at construction time.
|
|
7
|
+
|
|
8
|
+
Regression introduced in v1.2.0 where ``ORMFactory.get_adapter_from_env``
|
|
9
|
+
started always passing an explicit ``async_database_url`` to the adapter,
|
|
10
|
+
bypassing the existing best-effort ``try/except`` on the URL-conversion path.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from unittest.mock import patch
|
|
14
|
+
|
|
15
|
+
import pytest
|
|
16
|
+
|
|
17
|
+
from fastapi_viewsets.orm.sqlalchemy_adapter import SQLAlchemyAdapter
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _import_error(*_args, **_kwargs):
|
|
21
|
+
raise ModuleNotFoundError("No module named 'aiosqlite'")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_explicit_async_url_without_driver_falls_back_to_sync():
|
|
25
|
+
"""Adapter must not raise when async driver is missing."""
|
|
26
|
+
with patch(
|
|
27
|
+
"fastapi_viewsets.orm.sqlalchemy_adapter.create_async_engine",
|
|
28
|
+
side_effect=_import_error,
|
|
29
|
+
):
|
|
30
|
+
adapter = SQLAlchemyAdapter(
|
|
31
|
+
database_url="sqlite:///:memory:",
|
|
32
|
+
async_database_url="sqlite+aiosqlite:///:memory:",
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
assert adapter.async_engine is None
|
|
36
|
+
assert adapter.AsyncSessionLocal is None
|
|
37
|
+
|
|
38
|
+
# Sync session must keep working.
|
|
39
|
+
session = adapter.get_session()
|
|
40
|
+
assert session is not None
|
|
41
|
+
session.close()
|
|
42
|
+
|
|
43
|
+
# Async session must raise a helpful runtime error (not at __init__).
|
|
44
|
+
with pytest.raises(RuntimeError, match="async database driver"):
|
|
45
|
+
adapter.get_async_session()
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def test_auto_converted_async_url_without_driver_falls_back_to_sync():
|
|
49
|
+
"""Same fallback when ``async_database_url`` is auto-derived."""
|
|
50
|
+
with patch(
|
|
51
|
+
"fastapi_viewsets.orm.sqlalchemy_adapter.create_async_engine",
|
|
52
|
+
side_effect=_import_error,
|
|
53
|
+
):
|
|
54
|
+
adapter = SQLAlchemyAdapter(database_url="sqlite:///:memory:")
|
|
55
|
+
|
|
56
|
+
assert adapter.async_engine is None
|
|
57
|
+
assert adapter.AsyncSessionLocal is None
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_viewsets-1.2.0 → fastapi_viewsets-1.2.1}/fastapi_viewsets.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|