servicekit 3.0.0__tar.gz → 3.1.0__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.
- {servicekit-3.0.0 → servicekit-3.1.0}/PKG-INFO +1 -1
- {servicekit-3.0.0 → servicekit-3.1.0}/pyproject.toml +11 -2
- {servicekit-3.0.0 → servicekit-3.1.0}/pyproject.toml.orig +3 -3
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/api/monitoring.py +2 -1
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/api/registration.py +1 -1
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/api/service_builder.py +3 -3
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/database.py +3 -2
- {servicekit-3.0.0 → servicekit-3.1.0}/README.md +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/__init__.py +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/alembic/env.py +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/alembic/script.py.mako +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/alembic/versions/20251010_0927_4d869b5fb06e_initial_schema.py +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/api/__init__.py +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/api/app.py +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/api/apps/landing/index.html +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/api/apps/landing/manifest.json +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/api/auth.py +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/api/crud.py +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/api/dependencies.py +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/api/middleware.py +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/api/pagination.py +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/api/router.py +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/api/routers/__init__.py +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/api/routers/health.py +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/api/routers/job.py +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/api/routers/metrics.py +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/api/routers/system.py +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/api/sse.py +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/api/utilities.py +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/exceptions.py +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/gunicorn.conf.py +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/logging.py +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/manager.py +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/models.py +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/py.typed +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/repository.py +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/scheduler.py +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/schemas.py +0 -0
- {servicekit-3.0.0 → servicekit-3.1.0}/src/servicekit/types.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: servicekit
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.1.0
|
|
4
4
|
Summary: Async SQLAlchemy framework with FastAPI integration - reusable foundation for building data services
|
|
5
5
|
Keywords: fastapi,sqlalchemy,async,database,rest-api,crud,framework
|
|
6
6
|
Author: Morten Hansen
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "servicekit"
|
|
3
|
-
version = "3.
|
|
3
|
+
version = "3.1.0"
|
|
4
4
|
description = "Async SQLAlchemy framework with FastAPI integration - reusable foundation for building data services"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.13,<3.14"
|
|
@@ -84,6 +84,7 @@ select = [
|
|
|
84
84
|
"F",
|
|
85
85
|
"I",
|
|
86
86
|
"D",
|
|
87
|
+
"S",
|
|
87
88
|
]
|
|
88
89
|
ignore = [
|
|
89
90
|
"D203",
|
|
@@ -97,7 +98,15 @@ known-third-party = ["alembic"]
|
|
|
97
98
|
convention = "google"
|
|
98
99
|
|
|
99
100
|
[tool.ruff.lint.per-file-ignores]
|
|
100
|
-
"tests/**/*.py" = [
|
|
101
|
+
"tests/**/*.py" = [
|
|
102
|
+
"D",
|
|
103
|
+
"S101",
|
|
104
|
+
"S104",
|
|
105
|
+
"S105",
|
|
106
|
+
"S108",
|
|
107
|
+
"S603",
|
|
108
|
+
"S607",
|
|
109
|
+
]
|
|
101
110
|
"**/__init__.py" = ["D104"]
|
|
102
111
|
"src/**/*.py" = [
|
|
103
112
|
"D102",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "servicekit"
|
|
3
|
-
version = "3.
|
|
3
|
+
version = "3.1.0"
|
|
4
4
|
description = "Async SQLAlchemy framework with FastAPI integration - reusable foundation for building data services"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [{ name = "Morten Hansen", email = "morten@dhis2.org" }]
|
|
@@ -73,7 +73,7 @@ line-length = 120
|
|
|
73
73
|
|
|
74
74
|
[tool.ruff.lint]
|
|
75
75
|
fixable = ["ALL"]
|
|
76
|
-
select = ["E", "W", "F", "I", "D"]
|
|
76
|
+
select = ["E", "W", "F", "I", "D", "S"]
|
|
77
77
|
ignore = ["D203", "D213"]
|
|
78
78
|
|
|
79
79
|
[tool.ruff.lint.isort]
|
|
@@ -83,7 +83,7 @@ known-third-party = ["alembic"]
|
|
|
83
83
|
convention = "google"
|
|
84
84
|
|
|
85
85
|
[tool.ruff.lint.per-file-ignores]
|
|
86
|
-
"tests/**/*.py" = ["D"]
|
|
86
|
+
"tests/**/*.py" = ["D", "S101", "S104", "S105", "S108", "S603", "S607"]
|
|
87
87
|
"**/__init__.py" = ["D104"]
|
|
88
88
|
"src/**/*.py" = ["D102", "D105", "D107"]
|
|
89
89
|
"examples/**/*.py" = []
|
|
@@ -56,7 +56,8 @@ def setup_monitoring(
|
|
|
56
56
|
# Auto-instrument SQLAlchemy - only once globally
|
|
57
57
|
if not _sqlalchemy_instrumented:
|
|
58
58
|
try:
|
|
59
|
-
|
|
59
|
+
# The instrumentor's declared range lags SQLAlchemy releases (0.66b1 stops below 2.1) and works on 2.1.
|
|
60
|
+
SQLAlchemyInstrumentor().instrument(skip_dep_check=True)
|
|
60
61
|
_sqlalchemy_instrumented = True
|
|
61
62
|
except RuntimeError:
|
|
62
63
|
# Already instrumented
|
|
@@ -39,7 +39,7 @@ type DependencyOverride = Callable[..., object]
|
|
|
39
39
|
type LifespanFactory = Callable[[FastAPI], AsyncContextManager[None]]
|
|
40
40
|
|
|
41
41
|
# Header the readiness probe sends and expects echoed back, so it only accepts its own app
|
|
42
|
-
_READINESS_TOKEN_HEADER = "x-servicekit-readiness-token"
|
|
42
|
+
_READINESS_TOKEN_HEADER = "x-servicekit-readiness-token" # noqa: S105
|
|
43
43
|
_DEFAULT_LOCAL_PORT = 8000
|
|
44
44
|
|
|
45
45
|
|
|
@@ -998,7 +998,7 @@ async def _wait_until_ready(
|
|
|
998
998
|
timeout: float = 30.0,
|
|
999
999
|
) -> int | None:
|
|
1000
1000
|
"""Poll the candidate local ports until this app serves requests, returning the ready port or None."""
|
|
1001
|
-
import httpx
|
|
1001
|
+
import httpx2 as httpx
|
|
1002
1002
|
|
|
1003
1003
|
path = health_path or "/"
|
|
1004
1004
|
check_kind = "health" if health_path else "tcp"
|
|
@@ -1010,7 +1010,7 @@ async def _wait_until_ready(
|
|
|
1010
1010
|
try:
|
|
1011
1011
|
async with httpx.AsyncClient() as client:
|
|
1012
1012
|
response = await client.get(f"http://127.0.0.1:{port}{path}", headers=headers, timeout=2.0)
|
|
1013
|
-
except
|
|
1013
|
+
except httpx.TransportError:
|
|
1014
1014
|
continue
|
|
1015
1015
|
# Something else listening on a candidate port (e.g. the orchestrator itself) is not us
|
|
1016
1016
|
if response.headers.get(_READINESS_TOKEN_HEADER) != token:
|
|
@@ -211,8 +211,9 @@ class SqliteDatabase(Database):
|
|
|
211
211
|
try:
|
|
212
212
|
async with self.engine.begin() as conn:
|
|
213
213
|
await conn.exec_driver_sql("PRAGMA wal_checkpoint(TRUNCATE);")
|
|
214
|
-
except Exception:
|
|
215
|
-
|
|
214
|
+
except Exception as e:
|
|
215
|
+
# Don't fail dispose on checkpoint error
|
|
216
|
+
get_logger(__name__).warning("database.wal_checkpoint_failed", error=str(e))
|
|
216
217
|
await super().dispose()
|
|
217
218
|
|
|
218
219
|
|
|
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
|
|
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
|