servicekit 0.6.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-0.6.0/PKG-INFO +185 -0
- servicekit-0.6.0/README.md +149 -0
- servicekit-0.6.0/pyproject.toml +149 -0
- servicekit-0.6.0/src/servicekit/.DS_Store +0 -0
- servicekit-0.6.0/src/servicekit/__init__.py +88 -0
- servicekit-0.6.0/src/servicekit/api/.DS_Store +0 -0
- servicekit-0.6.0/src/servicekit/api/__init__.py +72 -0
- servicekit-0.6.0/src/servicekit/api/app.py +225 -0
- servicekit-0.6.0/src/servicekit/api/apps/.DS_Store +0 -0
- servicekit-0.6.0/src/servicekit/api/apps/landing/index.html +146 -0
- servicekit-0.6.0/src/servicekit/api/apps/landing/manifest.json +8 -0
- servicekit-0.6.0/src/servicekit/api/auth.py +162 -0
- servicekit-0.6.0/src/servicekit/api/crud.py +366 -0
- servicekit-0.6.0/src/servicekit/api/dependencies.py +69 -0
- servicekit-0.6.0/src/servicekit/api/middleware.py +163 -0
- servicekit-0.6.0/src/servicekit/api/monitoring.py +100 -0
- servicekit-0.6.0/src/servicekit/api/pagination.py +27 -0
- servicekit-0.6.0/src/servicekit/api/registration.py +287 -0
- servicekit-0.6.0/src/servicekit/api/router.py +28 -0
- servicekit-0.6.0/src/servicekit/api/routers/__init__.py +18 -0
- servicekit-0.6.0/src/servicekit/api/routers/health.py +114 -0
- servicekit-0.6.0/src/servicekit/api/routers/job.py +126 -0
- servicekit-0.6.0/src/servicekit/api/routers/metrics.py +47 -0
- servicekit-0.6.0/src/servicekit/api/routers/system.py +77 -0
- servicekit-0.6.0/src/servicekit/api/service_builder.py +793 -0
- servicekit-0.6.0/src/servicekit/api/sse.py +23 -0
- servicekit-0.6.0/src/servicekit/api/utilities.py +80 -0
- servicekit-0.6.0/src/servicekit/database.py +262 -0
- servicekit-0.6.0/src/servicekit/exceptions.py +138 -0
- servicekit-0.6.0/src/servicekit/gunicorn.conf.py +109 -0
- servicekit-0.6.0/src/servicekit/logging.py +98 -0
- servicekit-0.6.0/src/servicekit/manager.py +311 -0
- servicekit-0.6.0/src/servicekit/models.py +26 -0
- servicekit-0.6.0/src/servicekit/py.typed +0 -0
- servicekit-0.6.0/src/servicekit/repository.py +173 -0
- servicekit-0.6.0/src/servicekit/scheduler.py +302 -0
- servicekit-0.6.0/src/servicekit/schemas.py +184 -0
- servicekit-0.6.0/src/servicekit/types.py +94 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: servicekit
|
|
3
|
+
Version: 0.6.0
|
|
4
|
+
Summary: Async SQLAlchemy framework with FastAPI integration - reusable foundation for building data services
|
|
5
|
+
Keywords: fastapi,sqlalchemy,async,database,rest-api,crud,framework
|
|
6
|
+
Author: Morten Hansen
|
|
7
|
+
Author-email: Morten Hansen <morten@winterop.com>
|
|
8
|
+
License: AGPL-3.0-or-later
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Classifier: Framework :: FastAPI
|
|
15
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
16
|
+
Classifier: Topic :: Database
|
|
17
|
+
Requires-Dist: aiosqlite>=0.21.0
|
|
18
|
+
Requires-Dist: alembic>=1.17.0
|
|
19
|
+
Requires-Dist: fastapi[standard]>=0.119.1
|
|
20
|
+
Requires-Dist: gunicorn>=23.0.0
|
|
21
|
+
Requires-Dist: opentelemetry-api>=1.37.0
|
|
22
|
+
Requires-Dist: opentelemetry-exporter-prometheus>=0.58b0
|
|
23
|
+
Requires-Dist: opentelemetry-instrumentation-fastapi>=0.58b0
|
|
24
|
+
Requires-Dist: opentelemetry-instrumentation-sqlalchemy>=0.58b0
|
|
25
|
+
Requires-Dist: opentelemetry-sdk>=1.37.0
|
|
26
|
+
Requires-Dist: pydantic>=2.12.0
|
|
27
|
+
Requires-Dist: python-ulid>=3.1.0
|
|
28
|
+
Requires-Dist: sqlalchemy[asyncio]>=2.0.43
|
|
29
|
+
Requires-Dist: structlog>=24.4.0
|
|
30
|
+
Requires-Python: >=3.13, <3.14
|
|
31
|
+
Project-URL: Documentation, https://winterop-com.github.io/servicekit
|
|
32
|
+
Project-URL: Homepage, https://github.com/winterop-com/servicekit
|
|
33
|
+
Project-URL: Issues, https://github.com/winterop-com/servicekit/issues
|
|
34
|
+
Project-URL: Repository, https://github.com/winterop-com/servicekit
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
# Servicekit
|
|
38
|
+
|
|
39
|
+
[](https://github.com/winterop-com/servicekit/actions/workflows/ci.yml)
|
|
40
|
+
[](https://pypi.org/project/servicekit/)
|
|
41
|
+
[](https://codecov.io/gh/winterop-com/servicekit)
|
|
42
|
+
[](https://www.python.org/downloads/)
|
|
43
|
+
[](https://www.gnu.org/licenses/agpl-3.0)
|
|
44
|
+
[](https://winterop-com.github.io/servicekit/)
|
|
45
|
+
|
|
46
|
+
> Async SQLAlchemy framework with FastAPI integration - reusable foundation for building data services
|
|
47
|
+
|
|
48
|
+
Servicekit is a framework-agnostic core library providing foundational infrastructure for building async Python services with FastAPI and SQLAlchemy.
|
|
49
|
+
|
|
50
|
+
## Features
|
|
51
|
+
|
|
52
|
+
- **Database Layer**: Async SQLAlchemy with SQLite support, connection pooling, and automatic migrations
|
|
53
|
+
- **Repository Pattern**: Generic repository base classes for data access
|
|
54
|
+
- **Manager Pattern**: Business logic layer with lifecycle hooks
|
|
55
|
+
- **CRUD API**: Auto-generated REST endpoints with full CRUD operations
|
|
56
|
+
- **Authentication**: API key middleware with file and environment variable support
|
|
57
|
+
- **Job Scheduling**: Async job scheduler with concurrency control
|
|
58
|
+
- **App Hosting**: Mount static web applications alongside your API
|
|
59
|
+
- **Monitoring**: Prometheus metrics and OpenTelemetry integration
|
|
60
|
+
- **Health Checks**: Flexible health check system with SSE streaming support
|
|
61
|
+
- **Error Handling**: RFC 9457 Problem Details for HTTP APIs
|
|
62
|
+
- **Logging**: Structured logging with request context
|
|
63
|
+
|
|
64
|
+
## Installation
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
pip install servicekit
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Quick Start
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
from servicekit.api import BaseServiceBuilder, ServiceInfo
|
|
74
|
+
|
|
75
|
+
app = (
|
|
76
|
+
BaseServiceBuilder(info=ServiceInfo(display_name="My Service"))
|
|
77
|
+
.with_health()
|
|
78
|
+
.with_database("sqlite+aiosqlite:///./data.db")
|
|
79
|
+
.build()
|
|
80
|
+
)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Architecture
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
servicekit/
|
|
87
|
+
├── database.py # Database, SqliteDatabase, SqliteDatabaseBuilder
|
|
88
|
+
├── models.py # Base, Entity ORM classes
|
|
89
|
+
├── repository.py # Repository, BaseRepository
|
|
90
|
+
├── manager.py # Manager, BaseManager
|
|
91
|
+
├── schemas.py # EntityIn, EntityOut, PaginatedResponse
|
|
92
|
+
├── scheduler.py # JobScheduler, AIOJobScheduler
|
|
93
|
+
├── exceptions.py # Error classes
|
|
94
|
+
├── logging.py # Structured logging
|
|
95
|
+
├── types.py # ULIDType, JsonSafe
|
|
96
|
+
└── api/ # FastAPI framework layer
|
|
97
|
+
├── router.py # Router base class
|
|
98
|
+
├── crud.py # CrudRouter, CrudPermissions
|
|
99
|
+
├── auth.py # API key authentication
|
|
100
|
+
├── app.py # Static app hosting
|
|
101
|
+
├── middleware.py # Error handlers, logging
|
|
102
|
+
└── routers/ # Health, Jobs, System, Metrics
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Key Components
|
|
106
|
+
|
|
107
|
+
### BaseServiceBuilder
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
from servicekit.api import BaseServiceBuilder, ServiceInfo
|
|
111
|
+
|
|
112
|
+
app = (
|
|
113
|
+
BaseServiceBuilder(info=ServiceInfo(display_name="My Service"))
|
|
114
|
+
.with_health() # Health check endpoint
|
|
115
|
+
.with_database(url) # Database configuration
|
|
116
|
+
.with_jobs(max_concurrency=10) # Job scheduler
|
|
117
|
+
.with_auth() # API key authentication
|
|
118
|
+
.with_monitoring() # Prometheus metrics
|
|
119
|
+
.with_app("./webapp") # Static web app
|
|
120
|
+
.include_router(custom_router) # Custom routes
|
|
121
|
+
.build()
|
|
122
|
+
)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Repository Pattern
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
from servicekit import BaseRepository, Entity
|
|
129
|
+
from sqlalchemy.orm import Mapped, mapped_column
|
|
130
|
+
|
|
131
|
+
class User(Entity):
|
|
132
|
+
__tablename__ = "users"
|
|
133
|
+
name: Mapped[str] = mapped_column()
|
|
134
|
+
email: Mapped[str] = mapped_column()
|
|
135
|
+
|
|
136
|
+
class UserRepository(BaseRepository[User, ULID]):
|
|
137
|
+
def __init__(self, session: AsyncSession):
|
|
138
|
+
super().__init__(session, User)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### CRUD Router
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
from servicekit.api import CrudRouter, CrudPermissions
|
|
145
|
+
|
|
146
|
+
router = CrudRouter.create(
|
|
147
|
+
prefix="/api/v1/users",
|
|
148
|
+
tags=["Users"],
|
|
149
|
+
entity_in_type=UserIn,
|
|
150
|
+
entity_out_type=UserOut,
|
|
151
|
+
manager_factory=get_user_manager,
|
|
152
|
+
permissions=CrudPermissions(create=True, read=True, update=True, delete=False)
|
|
153
|
+
)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
## Examples
|
|
158
|
+
|
|
159
|
+
See the `examples/` directory for complete working examples:
|
|
160
|
+
|
|
161
|
+
- `core_api.py` - Basic CRUD service
|
|
162
|
+
- `job_scheduler_api.py` - Background job execution
|
|
163
|
+
- `app_hosting_api.py` - Hosting static web apps
|
|
164
|
+
- `auth_basic.py` - API key authentication
|
|
165
|
+
- `monitoring_api.py` - Prometheus metrics
|
|
166
|
+
|
|
167
|
+
## Documentation
|
|
168
|
+
|
|
169
|
+
See `docs/` for comprehensive guides and API reference.
|
|
170
|
+
|
|
171
|
+
## Testing
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
make test # Run tests
|
|
175
|
+
make lint # Run linter
|
|
176
|
+
make coverage # Test coverage
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## License
|
|
180
|
+
|
|
181
|
+
AGPL-3.0-or-later
|
|
182
|
+
|
|
183
|
+
## Related Projects
|
|
184
|
+
|
|
185
|
+
- **[chapkit](https://github.com/dhis2-chap/chapkit)** - Domain modules (artifacts, configs, tasks, ML workflows) built on servicekit ([docs](https://dhis2-chap.github.io/chapkit))
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# Servicekit
|
|
2
|
+
|
|
3
|
+
[](https://github.com/winterop-com/servicekit/actions/workflows/ci.yml)
|
|
4
|
+
[](https://pypi.org/project/servicekit/)
|
|
5
|
+
[](https://codecov.io/gh/winterop-com/servicekit)
|
|
6
|
+
[](https://www.python.org/downloads/)
|
|
7
|
+
[](https://www.gnu.org/licenses/agpl-3.0)
|
|
8
|
+
[](https://winterop-com.github.io/servicekit/)
|
|
9
|
+
|
|
10
|
+
> Async SQLAlchemy framework with FastAPI integration - reusable foundation for building data services
|
|
11
|
+
|
|
12
|
+
Servicekit is a framework-agnostic core library providing foundational infrastructure for building async Python services with FastAPI and SQLAlchemy.
|
|
13
|
+
|
|
14
|
+
## Features
|
|
15
|
+
|
|
16
|
+
- **Database Layer**: Async SQLAlchemy with SQLite support, connection pooling, and automatic migrations
|
|
17
|
+
- **Repository Pattern**: Generic repository base classes for data access
|
|
18
|
+
- **Manager Pattern**: Business logic layer with lifecycle hooks
|
|
19
|
+
- **CRUD API**: Auto-generated REST endpoints with full CRUD operations
|
|
20
|
+
- **Authentication**: API key middleware with file and environment variable support
|
|
21
|
+
- **Job Scheduling**: Async job scheduler with concurrency control
|
|
22
|
+
- **App Hosting**: Mount static web applications alongside your API
|
|
23
|
+
- **Monitoring**: Prometheus metrics and OpenTelemetry integration
|
|
24
|
+
- **Health Checks**: Flexible health check system with SSE streaming support
|
|
25
|
+
- **Error Handling**: RFC 9457 Problem Details for HTTP APIs
|
|
26
|
+
- **Logging**: Structured logging with request context
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install servicekit
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Quick Start
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
from servicekit.api import BaseServiceBuilder, ServiceInfo
|
|
38
|
+
|
|
39
|
+
app = (
|
|
40
|
+
BaseServiceBuilder(info=ServiceInfo(display_name="My Service"))
|
|
41
|
+
.with_health()
|
|
42
|
+
.with_database("sqlite+aiosqlite:///./data.db")
|
|
43
|
+
.build()
|
|
44
|
+
)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Architecture
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
servicekit/
|
|
51
|
+
├── database.py # Database, SqliteDatabase, SqliteDatabaseBuilder
|
|
52
|
+
├── models.py # Base, Entity ORM classes
|
|
53
|
+
├── repository.py # Repository, BaseRepository
|
|
54
|
+
├── manager.py # Manager, BaseManager
|
|
55
|
+
├── schemas.py # EntityIn, EntityOut, PaginatedResponse
|
|
56
|
+
├── scheduler.py # JobScheduler, AIOJobScheduler
|
|
57
|
+
├── exceptions.py # Error classes
|
|
58
|
+
├── logging.py # Structured logging
|
|
59
|
+
├── types.py # ULIDType, JsonSafe
|
|
60
|
+
└── api/ # FastAPI framework layer
|
|
61
|
+
├── router.py # Router base class
|
|
62
|
+
├── crud.py # CrudRouter, CrudPermissions
|
|
63
|
+
├── auth.py # API key authentication
|
|
64
|
+
├── app.py # Static app hosting
|
|
65
|
+
├── middleware.py # Error handlers, logging
|
|
66
|
+
└── routers/ # Health, Jobs, System, Metrics
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Key Components
|
|
70
|
+
|
|
71
|
+
### BaseServiceBuilder
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
from servicekit.api import BaseServiceBuilder, ServiceInfo
|
|
75
|
+
|
|
76
|
+
app = (
|
|
77
|
+
BaseServiceBuilder(info=ServiceInfo(display_name="My Service"))
|
|
78
|
+
.with_health() # Health check endpoint
|
|
79
|
+
.with_database(url) # Database configuration
|
|
80
|
+
.with_jobs(max_concurrency=10) # Job scheduler
|
|
81
|
+
.with_auth() # API key authentication
|
|
82
|
+
.with_monitoring() # Prometheus metrics
|
|
83
|
+
.with_app("./webapp") # Static web app
|
|
84
|
+
.include_router(custom_router) # Custom routes
|
|
85
|
+
.build()
|
|
86
|
+
)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Repository Pattern
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from servicekit import BaseRepository, Entity
|
|
93
|
+
from sqlalchemy.orm import Mapped, mapped_column
|
|
94
|
+
|
|
95
|
+
class User(Entity):
|
|
96
|
+
__tablename__ = "users"
|
|
97
|
+
name: Mapped[str] = mapped_column()
|
|
98
|
+
email: Mapped[str] = mapped_column()
|
|
99
|
+
|
|
100
|
+
class UserRepository(BaseRepository[User, ULID]):
|
|
101
|
+
def __init__(self, session: AsyncSession):
|
|
102
|
+
super().__init__(session, User)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### CRUD Router
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
from servicekit.api import CrudRouter, CrudPermissions
|
|
109
|
+
|
|
110
|
+
router = CrudRouter.create(
|
|
111
|
+
prefix="/api/v1/users",
|
|
112
|
+
tags=["Users"],
|
|
113
|
+
entity_in_type=UserIn,
|
|
114
|
+
entity_out_type=UserOut,
|
|
115
|
+
manager_factory=get_user_manager,
|
|
116
|
+
permissions=CrudPermissions(create=True, read=True, update=True, delete=False)
|
|
117
|
+
)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
## Examples
|
|
122
|
+
|
|
123
|
+
See the `examples/` directory for complete working examples:
|
|
124
|
+
|
|
125
|
+
- `core_api.py` - Basic CRUD service
|
|
126
|
+
- `job_scheduler_api.py` - Background job execution
|
|
127
|
+
- `app_hosting_api.py` - Hosting static web apps
|
|
128
|
+
- `auth_basic.py` - API key authentication
|
|
129
|
+
- `monitoring_api.py` - Prometheus metrics
|
|
130
|
+
|
|
131
|
+
## Documentation
|
|
132
|
+
|
|
133
|
+
See `docs/` for comprehensive guides and API reference.
|
|
134
|
+
|
|
135
|
+
## Testing
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
make test # Run tests
|
|
139
|
+
make lint # Run linter
|
|
140
|
+
make coverage # Test coverage
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## License
|
|
144
|
+
|
|
145
|
+
AGPL-3.0-or-later
|
|
146
|
+
|
|
147
|
+
## Related Projects
|
|
148
|
+
|
|
149
|
+
- **[chapkit](https://github.com/dhis2-chap/chapkit)** - Domain modules (artifacts, configs, tasks, ML workflows) built on servicekit ([docs](https://dhis2-chap.github.io/chapkit))
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "servicekit"
|
|
3
|
+
version = "0.6.0"
|
|
4
|
+
description = "Async SQLAlchemy framework with FastAPI integration - reusable foundation for building data services"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [{ name = "Morten Hansen", email = "morten@winterop.com" }]
|
|
7
|
+
license = { text = "AGPL-3.0-or-later" }
|
|
8
|
+
requires-python = ">=3.13,<3.14"
|
|
9
|
+
keywords = [
|
|
10
|
+
"fastapi",
|
|
11
|
+
"sqlalchemy",
|
|
12
|
+
"async",
|
|
13
|
+
"database",
|
|
14
|
+
"rest-api",
|
|
15
|
+
"crud",
|
|
16
|
+
"framework",
|
|
17
|
+
]
|
|
18
|
+
classifiers = [
|
|
19
|
+
"Development Status :: 3 - Alpha",
|
|
20
|
+
"Intended Audience :: Developers",
|
|
21
|
+
"License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"Programming Language :: Python :: 3.13",
|
|
24
|
+
"Framework :: FastAPI",
|
|
25
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
26
|
+
"Topic :: Database",
|
|
27
|
+
]
|
|
28
|
+
dependencies = [
|
|
29
|
+
"aiosqlite>=0.21.0",
|
|
30
|
+
"alembic>=1.17.0",
|
|
31
|
+
"fastapi[standard]>=0.119.1",
|
|
32
|
+
"gunicorn>=23.0.0",
|
|
33
|
+
"opentelemetry-api>=1.37.0",
|
|
34
|
+
"opentelemetry-exporter-prometheus>=0.58b0",
|
|
35
|
+
"opentelemetry-instrumentation-fastapi>=0.58b0",
|
|
36
|
+
"opentelemetry-instrumentation-sqlalchemy>=0.58b0",
|
|
37
|
+
"opentelemetry-sdk>=1.37.0",
|
|
38
|
+
"pydantic>=2.12.0",
|
|
39
|
+
"python-ulid>=3.1.0",
|
|
40
|
+
"sqlalchemy[asyncio]>=2.0.43",
|
|
41
|
+
"structlog>=24.4.0",
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
[project.optional-dependencies]
|
|
45
|
+
|
|
46
|
+
[project.urls]
|
|
47
|
+
Homepage = "https://github.com/winterop-com/servicekit"
|
|
48
|
+
Repository = "https://github.com/winterop-com/servicekit"
|
|
49
|
+
Issues = "https://github.com/winterop-com/servicekit/issues"
|
|
50
|
+
Documentation = "https://winterop-com.github.io/servicekit"
|
|
51
|
+
|
|
52
|
+
[dependency-groups]
|
|
53
|
+
dev = [
|
|
54
|
+
"coverage[toml]>=7.6.0",
|
|
55
|
+
"mypy>=1.18.2",
|
|
56
|
+
"pytest>=8.4.2",
|
|
57
|
+
"pytest-cov>=5.0.0",
|
|
58
|
+
"pytest-asyncio>=1.2.0",
|
|
59
|
+
"ruff>=0.14.0",
|
|
60
|
+
"pyright>=1.1.407",
|
|
61
|
+
"mkdocs>=1.6.0",
|
|
62
|
+
"mkdocs-material>=9.5.0",
|
|
63
|
+
"mkdocstrings[python]>=0.26.0",
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
[build-system]
|
|
67
|
+
requires = ["uv_build>=0.9.0,<0.10.0"]
|
|
68
|
+
build-backend = "uv_build"
|
|
69
|
+
|
|
70
|
+
[tool.ruff]
|
|
71
|
+
target-version = "py313"
|
|
72
|
+
line-length = 120
|
|
73
|
+
|
|
74
|
+
[tool.ruff.lint]
|
|
75
|
+
fixable = ["ALL"]
|
|
76
|
+
select = ["E", "W", "F", "I", "D"]
|
|
77
|
+
ignore = ["D203", "D213"]
|
|
78
|
+
|
|
79
|
+
[tool.ruff.lint.pydocstyle]
|
|
80
|
+
convention = "google"
|
|
81
|
+
|
|
82
|
+
[tool.ruff.lint.per-file-ignores]
|
|
83
|
+
"tests/**/*.py" = ["D"]
|
|
84
|
+
"**/__init__.py" = ["D104"]
|
|
85
|
+
"src/**/*.py" = ["D102", "D105", "D107"]
|
|
86
|
+
"examples/**/*.py" = []
|
|
87
|
+
|
|
88
|
+
[tool.ruff.format]
|
|
89
|
+
quote-style = "double"
|
|
90
|
+
indent-style = "space"
|
|
91
|
+
skip-magic-trailing-comma = false
|
|
92
|
+
docstring-code-format = true
|
|
93
|
+
docstring-code-line-length = "dynamic"
|
|
94
|
+
|
|
95
|
+
[tool.pytest.ini_options]
|
|
96
|
+
asyncio_mode = "auto"
|
|
97
|
+
testpaths = ["tests"]
|
|
98
|
+
norecursedirs = ["examples", ".git", ".venv", "__pycache__"]
|
|
99
|
+
|
|
100
|
+
[tool.coverage.run]
|
|
101
|
+
branch = true
|
|
102
|
+
dynamic_context = "test_function"
|
|
103
|
+
relative_files = true
|
|
104
|
+
source = ["servicekit"]
|
|
105
|
+
|
|
106
|
+
[tool.coverage.report]
|
|
107
|
+
exclude_also = ["if TYPE_CHECKING:"]
|
|
108
|
+
precision = 2
|
|
109
|
+
show_missing = true
|
|
110
|
+
skip_covered = true
|
|
111
|
+
|
|
112
|
+
[tool.mypy]
|
|
113
|
+
python_version = "3.13"
|
|
114
|
+
warn_return_any = true
|
|
115
|
+
warn_unused_configs = true
|
|
116
|
+
disallow_untyped_defs = true
|
|
117
|
+
check_untyped_defs = true
|
|
118
|
+
disallow_any_unimported = true
|
|
119
|
+
no_implicit_optional = true
|
|
120
|
+
warn_unused_ignores = true
|
|
121
|
+
strict_equality = true
|
|
122
|
+
mypy_path = ["src", "typings"]
|
|
123
|
+
|
|
124
|
+
[[tool.mypy.overrides]]
|
|
125
|
+
module = "tests.*"
|
|
126
|
+
disallow_untyped_defs = false
|
|
127
|
+
|
|
128
|
+
[[tool.mypy.overrides]]
|
|
129
|
+
module = "examples.*"
|
|
130
|
+
ignore_missing_imports = true
|
|
131
|
+
disallow_untyped_defs = false
|
|
132
|
+
ignore_errors = true
|
|
133
|
+
|
|
134
|
+
[tool.pyright]
|
|
135
|
+
include = ["src", "tests", "examples"]
|
|
136
|
+
pythonVersion = "3.13"
|
|
137
|
+
typeCheckingMode = "strict"
|
|
138
|
+
useLibraryCodeForTypes = true
|
|
139
|
+
reportPrivateUsage = false
|
|
140
|
+
reportUnusedFunction = false
|
|
141
|
+
reportUnknownMemberType = false
|
|
142
|
+
reportUnknownArgumentType = false
|
|
143
|
+
reportUnknownLambdaType = false
|
|
144
|
+
reportUnknownParameterType = false
|
|
145
|
+
reportUnknownVariableType = false
|
|
146
|
+
reportMissingTypeArgument = false
|
|
147
|
+
reportMissingTypeStubs = false
|
|
148
|
+
reportMissingImports = "none"
|
|
149
|
+
reportMissingModuleSource = "none"
|
|
Binary file
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""Core framework components - generic interfaces and base classes."""
|
|
2
|
+
|
|
3
|
+
# ruff: noqa: F401
|
|
4
|
+
|
|
5
|
+
# Read version from package metadata - must be before internal imports
|
|
6
|
+
try:
|
|
7
|
+
from importlib.metadata import version as _get_version
|
|
8
|
+
|
|
9
|
+
__version__ = _get_version("servicekit")
|
|
10
|
+
except Exception:
|
|
11
|
+
__version__ = "unknown"
|
|
12
|
+
|
|
13
|
+
# Base infrastructure (framework-agnostic)
|
|
14
|
+
from .database import Database, SqliteDatabase, SqliteDatabaseBuilder
|
|
15
|
+
from .exceptions import (
|
|
16
|
+
BadRequestError,
|
|
17
|
+
ConflictError,
|
|
18
|
+
ErrorType,
|
|
19
|
+
ForbiddenError,
|
|
20
|
+
InvalidULIDError,
|
|
21
|
+
NotFoundError,
|
|
22
|
+
ServicekitException,
|
|
23
|
+
UnauthorizedError,
|
|
24
|
+
ValidationError,
|
|
25
|
+
)
|
|
26
|
+
from .logging import add_request_context, clear_request_context, configure_logging, get_logger, reset_request_context
|
|
27
|
+
from .manager import BaseManager, LifecycleHooks, Manager
|
|
28
|
+
from .models import Base, Entity
|
|
29
|
+
from .repository import BaseRepository, Repository
|
|
30
|
+
from .scheduler import InMemoryScheduler, Scheduler
|
|
31
|
+
from .schemas import (
|
|
32
|
+
BulkOperationError,
|
|
33
|
+
BulkOperationResult,
|
|
34
|
+
EntityIn,
|
|
35
|
+
EntityOut,
|
|
36
|
+
JobRecord,
|
|
37
|
+
JobStatus,
|
|
38
|
+
PaginatedResponse,
|
|
39
|
+
ProblemDetail,
|
|
40
|
+
)
|
|
41
|
+
from .types import JsonSafe, ULIDType
|
|
42
|
+
|
|
43
|
+
__all__ = [
|
|
44
|
+
# Version
|
|
45
|
+
"__version__",
|
|
46
|
+
# Base infrastructure
|
|
47
|
+
"Database",
|
|
48
|
+
"SqliteDatabase",
|
|
49
|
+
"SqliteDatabaseBuilder",
|
|
50
|
+
"Repository",
|
|
51
|
+
"BaseRepository",
|
|
52
|
+
"Manager",
|
|
53
|
+
"LifecycleHooks",
|
|
54
|
+
"BaseManager",
|
|
55
|
+
# ORM and types
|
|
56
|
+
"Base",
|
|
57
|
+
"Entity",
|
|
58
|
+
"ULIDType",
|
|
59
|
+
"JsonSafe",
|
|
60
|
+
# Schemas
|
|
61
|
+
"EntityIn",
|
|
62
|
+
"EntityOut",
|
|
63
|
+
"PaginatedResponse",
|
|
64
|
+
"BulkOperationResult",
|
|
65
|
+
"BulkOperationError",
|
|
66
|
+
"ProblemDetail",
|
|
67
|
+
"JobRecord",
|
|
68
|
+
"JobStatus",
|
|
69
|
+
# Job scheduling
|
|
70
|
+
"Scheduler",
|
|
71
|
+
"InMemoryScheduler",
|
|
72
|
+
# Exceptions
|
|
73
|
+
"ErrorType",
|
|
74
|
+
"ServicekitException",
|
|
75
|
+
"NotFoundError",
|
|
76
|
+
"ValidationError",
|
|
77
|
+
"ConflictError",
|
|
78
|
+
"InvalidULIDError",
|
|
79
|
+
"BadRequestError",
|
|
80
|
+
"UnauthorizedError",
|
|
81
|
+
"ForbiddenError",
|
|
82
|
+
# Logging
|
|
83
|
+
"configure_logging",
|
|
84
|
+
"get_logger",
|
|
85
|
+
"add_request_context",
|
|
86
|
+
"clear_request_context",
|
|
87
|
+
"reset_request_context",
|
|
88
|
+
]
|
|
Binary file
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""FastAPI framework layer - routers, middleware, utilities."""
|
|
2
|
+
|
|
3
|
+
from .app import App, AppInfo, AppLoader, AppManager, AppManifest
|
|
4
|
+
from .auth import APIKeyMiddleware, load_api_keys_from_env, load_api_keys_from_file, validate_api_key_format
|
|
5
|
+
from .crud import CrudPermissions, CrudRouter
|
|
6
|
+
from .dependencies import (
|
|
7
|
+
get_app_manager,
|
|
8
|
+
get_database,
|
|
9
|
+
get_scheduler,
|
|
10
|
+
get_session,
|
|
11
|
+
set_app_manager,
|
|
12
|
+
set_database,
|
|
13
|
+
set_scheduler,
|
|
14
|
+
)
|
|
15
|
+
from .middleware import add_error_handlers, add_logging_middleware, database_error_handler, validation_error_handler
|
|
16
|
+
from .pagination import PaginationParams, create_paginated_response
|
|
17
|
+
from .router import Router
|
|
18
|
+
from .routers import HealthRouter, HealthState, HealthStatus, JobRouter, SystemInfo, SystemRouter
|
|
19
|
+
from .service_builder import BaseServiceBuilder, ServiceInfo
|
|
20
|
+
from .sse import SSE_HEADERS, format_sse_event, format_sse_model_event
|
|
21
|
+
from .utilities import build_location_url, run_app
|
|
22
|
+
|
|
23
|
+
__all__ = [
|
|
24
|
+
# Base router classes
|
|
25
|
+
"Router",
|
|
26
|
+
"CrudRouter",
|
|
27
|
+
"CrudPermissions",
|
|
28
|
+
# Service builder
|
|
29
|
+
"BaseServiceBuilder",
|
|
30
|
+
"ServiceInfo",
|
|
31
|
+
# App system
|
|
32
|
+
"App",
|
|
33
|
+
"AppInfo",
|
|
34
|
+
"AppLoader",
|
|
35
|
+
"AppManifest",
|
|
36
|
+
"AppManager",
|
|
37
|
+
# Authentication
|
|
38
|
+
"APIKeyMiddleware",
|
|
39
|
+
"load_api_keys_from_env",
|
|
40
|
+
"load_api_keys_from_file",
|
|
41
|
+
"validate_api_key_format",
|
|
42
|
+
# Dependencies
|
|
43
|
+
"get_app_manager",
|
|
44
|
+
"set_app_manager",
|
|
45
|
+
"get_database",
|
|
46
|
+
"set_database",
|
|
47
|
+
"get_session",
|
|
48
|
+
"get_scheduler",
|
|
49
|
+
"set_scheduler",
|
|
50
|
+
# Middleware
|
|
51
|
+
"add_error_handlers",
|
|
52
|
+
"add_logging_middleware",
|
|
53
|
+
"database_error_handler",
|
|
54
|
+
"validation_error_handler",
|
|
55
|
+
# Pagination
|
|
56
|
+
"PaginationParams",
|
|
57
|
+
"create_paginated_response",
|
|
58
|
+
# System routers
|
|
59
|
+
"HealthRouter",
|
|
60
|
+
"HealthState",
|
|
61
|
+
"HealthStatus",
|
|
62
|
+
"JobRouter",
|
|
63
|
+
"SystemRouter",
|
|
64
|
+
"SystemInfo",
|
|
65
|
+
# SSE utilities
|
|
66
|
+
"SSE_HEADERS",
|
|
67
|
+
"format_sse_event",
|
|
68
|
+
"format_sse_model_event",
|
|
69
|
+
# Utilities
|
|
70
|
+
"build_location_url",
|
|
71
|
+
"run_app",
|
|
72
|
+
]
|