tracktolib 0.67.0__tar.gz → 0.69.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.
- {tracktolib-0.67.0 → tracktolib-0.69.0}/PKG-INFO +115 -2
- tracktolib-0.69.0/README.md +235 -0
- {tracktolib-0.67.0 → tracktolib-0.69.0}/pyproject.toml +15 -6
- {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/api.py +21 -22
- tracktolib-0.69.0/tracktolib/cf/__init__.py +8 -0
- tracktolib-0.69.0/tracktolib/cf/client.py +149 -0
- tracktolib-0.69.0/tracktolib/cf/types.py +17 -0
- tracktolib-0.69.0/tracktolib/gh/__init__.py +11 -0
- tracktolib-0.69.0/tracktolib/gh/client.py +206 -0
- tracktolib-0.69.0/tracktolib/gh/types.py +203 -0
- {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/http_utils.py +1 -1
- {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/logs.py +1 -1
- tracktolib-0.69.0/tracktolib/notion/__init__.py +44 -0
- tracktolib-0.69.0/tracktolib/notion/blocks.py +459 -0
- tracktolib-0.69.0/tracktolib/notion/cache.py +202 -0
- {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/notion/fetch.py +121 -5
- tracktolib-0.69.0/tracktolib/notion/markdown.py +468 -0
- {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/notion/models.py +26 -0
- tracktolib-0.69.0/tracktolib/notion/utils.py +567 -0
- {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/pg/__init__.py +10 -10
- {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/pg/query.py +1 -1
- {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/pg/utils.py +5 -5
- {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/pg_sync.py +5 -7
- {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/pg_utils.py +1 -4
- {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/s3/niquests.py +235 -32
- {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/s3/s3.py +1 -1
- {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/utils.py +48 -3
- tracktolib-0.67.0/README.md +0 -126
- tracktolib-0.67.0/tracktolib/notion/__init__.py +0 -0
- {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/__init__.py +0 -0
- {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/s3/__init__.py +0 -0
- {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/s3/minio.py +1 -1
- {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/tests.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tracktolib
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.69.0
|
|
4
4
|
Summary: Utility library for python
|
|
5
5
|
Keywords: utility
|
|
6
6
|
Author-email: julien.brayere@tracktor.fr
|
|
@@ -12,6 +12,8 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.14
|
|
13
13
|
Requires-Dist: fastapi>=0.103.2 ; extra == 'api'
|
|
14
14
|
Requires-Dist: pydantic>=2 ; extra == 'api'
|
|
15
|
+
Requires-Dist: niquests>=3.17.0 ; extra == 'cf'
|
|
16
|
+
Requires-Dist: niquests>=3.17.0 ; extra == 'gh'
|
|
15
17
|
Requires-Dist: httpx>=0.25.0 ; extra == 'http'
|
|
16
18
|
Requires-Dist: python-json-logger>=3.2.1 ; extra == 'logs'
|
|
17
19
|
Requires-Dist: niquests>=3.17.0 ; extra == 'notion'
|
|
@@ -26,6 +28,8 @@ Requires-Dist: niquests>=3.17.0 ; extra == 's3-niquests'
|
|
|
26
28
|
Requires-Dist: deepdiff>=8.1.0 ; extra == 'tests'
|
|
27
29
|
Requires-Python: >=3.12, <4.0
|
|
28
30
|
Provides-Extra: api
|
|
31
|
+
Provides-Extra: cf
|
|
32
|
+
Provides-Extra: gh
|
|
29
33
|
Provides-Extra: http
|
|
30
34
|
Provides-Extra: logs
|
|
31
35
|
Provides-Extra: notion
|
|
@@ -126,12 +130,42 @@ uv add tracktolib[s3-minio]
|
|
|
126
130
|
|
|
127
131
|
### s3-niquests
|
|
128
132
|
|
|
129
|
-
Async S3 helpers using [niquests](https://github.com/jawah/niquests) and [botocore](https://github.com/boto/botocore).
|
|
133
|
+
Async S3 helpers using [niquests](https://github.com/jawah/niquests) and [botocore](https://github.com/boto/botocore) presigned URLs.
|
|
130
134
|
|
|
131
135
|
```bash
|
|
132
136
|
uv add tracktolib[s3-niquests]
|
|
133
137
|
```
|
|
134
138
|
|
|
139
|
+
```python
|
|
140
|
+
from tracktolib.s3.niquests import S3Session
|
|
141
|
+
|
|
142
|
+
async with S3Session(
|
|
143
|
+
endpoint_url='http://localhost:9000',
|
|
144
|
+
access_key='...',
|
|
145
|
+
secret_key='...',
|
|
146
|
+
region='us-east-1',
|
|
147
|
+
) as s3:
|
|
148
|
+
# Object operations
|
|
149
|
+
await s3.put_object('bucket', 'path/file.txt', b'content')
|
|
150
|
+
content = await s3.get_object('bucket', 'path/file.txt')
|
|
151
|
+
await s3.delete_object('bucket', 'path/file.txt')
|
|
152
|
+
|
|
153
|
+
# Streaming upload (multipart for large files)
|
|
154
|
+
async def data_stream():
|
|
155
|
+
yield b'chunk1'
|
|
156
|
+
yield b'chunk2'
|
|
157
|
+
await s3.file_upload('bucket', 'large-file.bin', data_stream())
|
|
158
|
+
|
|
159
|
+
# Bucket policy management
|
|
160
|
+
policy = {'Version': '2012-10-17', 'Statement': [...]}
|
|
161
|
+
await s3.put_bucket_policy('bucket', policy)
|
|
162
|
+
await s3.get_bucket_policy('bucket')
|
|
163
|
+
await s3.delete_bucket_policy('bucket')
|
|
164
|
+
|
|
165
|
+
# Empty a bucket (delete all objects)
|
|
166
|
+
deleted_count = await s3.empty_bucket('bucket')
|
|
167
|
+
```
|
|
168
|
+
|
|
135
169
|
### http (deprecated)
|
|
136
170
|
|
|
137
171
|
HTTP client helpers using [httpx](https://www.python-httpx.org/).
|
|
@@ -156,6 +190,85 @@ Notion API helpers using [niquests](https://github.com/jawah/niquests).
|
|
|
156
190
|
uv add tracktolib[notion]
|
|
157
191
|
```
|
|
158
192
|
|
|
193
|
+
```python
|
|
194
|
+
import niquests
|
|
195
|
+
from tracktolib.notion.fetch import fetch_database, get_notion_headers
|
|
196
|
+
from tracktolib.notion.cache import NotionCache
|
|
197
|
+
|
|
198
|
+
async with niquests.AsyncSession() as session:
|
|
199
|
+
session.headers.update(get_notion_headers())
|
|
200
|
+
|
|
201
|
+
# Without cache
|
|
202
|
+
db = await fetch_database(session, "database-id")
|
|
203
|
+
|
|
204
|
+
# With persistent cache (stored in ~/.cache/tracktolib/notion/cache.json)
|
|
205
|
+
cache = NotionCache()
|
|
206
|
+
db = await fetch_database(session, "database-id", cache=cache)
|
|
207
|
+
|
|
208
|
+
# Check cached databases
|
|
209
|
+
cache.get_databases() # All cached databases
|
|
210
|
+
cache.get_database("db-id") # Specific database (id, title, properties, cached_at)
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### gh
|
|
214
|
+
|
|
215
|
+
GitHub API helpers using [niquests](https://github.com/jawah/niquests).
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
uv add tracktolib[gh]
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
```python
|
|
222
|
+
from tracktolib.gh import GitHubClient
|
|
223
|
+
|
|
224
|
+
async with GitHubClient() as gh: # Uses GITHUB_TOKEN env var
|
|
225
|
+
# Issue comments
|
|
226
|
+
comments = await gh.get_issue_comments("owner/repo", 123)
|
|
227
|
+
await gh.create_issue_comment("owner/repo", 123, "Hello!")
|
|
228
|
+
await gh.delete_comments_with_marker("owner/repo", 123, "<!-- bot -->")
|
|
229
|
+
|
|
230
|
+
# Labels
|
|
231
|
+
labels = await gh.get_issue_labels("owner/repo", 123)
|
|
232
|
+
await gh.add_labels("owner/repo", 123, ["bug", "priority"])
|
|
233
|
+
await gh.remove_label("owner/repo", 123, "wontfix")
|
|
234
|
+
|
|
235
|
+
# Deployments
|
|
236
|
+
deploys = await gh.get_deployments("owner/repo", environment="production")
|
|
237
|
+
await gh.mark_deployment_inactive("owner/repo", "preview-123")
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### cf
|
|
241
|
+
|
|
242
|
+
Cloudflare DNS API helpers using [niquests](https://github.com/jawah/niquests).
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
uv add tracktolib[cf]
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
```python
|
|
249
|
+
from tracktolib.cf import CloudflareDNSClient
|
|
250
|
+
|
|
251
|
+
async with CloudflareDNSClient() as cf: # Uses CLOUDFLARE_API_TOKEN and CLOUDFLARE_ZONE_ID env vars
|
|
252
|
+
# Get a DNS record
|
|
253
|
+
record = await cf.get_dns_record("app.example.com", "CNAME")
|
|
254
|
+
|
|
255
|
+
# Create a DNS record
|
|
256
|
+
record = await cf.create_dns_record(
|
|
257
|
+
"app.example.com",
|
|
258
|
+
"target.example.com",
|
|
259
|
+
record_type="CNAME",
|
|
260
|
+
ttl=60,
|
|
261
|
+
proxied=True,
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
# Delete by ID or name
|
|
265
|
+
await cf.delete_dns_record(record["id"])
|
|
266
|
+
await cf.delete_dns_record_by_name("app.example.com", "CNAME")
|
|
267
|
+
|
|
268
|
+
# Check existence
|
|
269
|
+
exists = await cf.dns_record_exists("app.example.com")
|
|
270
|
+
```
|
|
271
|
+
|
|
159
272
|
### tests
|
|
160
273
|
|
|
161
274
|
Testing utilities using [deepdiff](https://github.com/seperman/deepdiff).
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
# Tracktolib
|
|
2
|
+
|
|
3
|
+
[](https://pypi.python.org/pypi/tracktolib)
|
|
4
|
+
[](https://pypi.python.org/pypi/tracktolib)
|
|
5
|
+
[](https://github.com/Tracktor/tracktolib/actions/workflows/ci.yml)
|
|
6
|
+
|
|
7
|
+
Tracktor Swiss-knife Utility library.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
uv add tracktolib
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
With specific extras:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
uv add tracktolib[pg,api]
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Modules
|
|
22
|
+
|
|
23
|
+
### logs
|
|
24
|
+
|
|
25
|
+
Utility functions to initialize logging formatting and streams.
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
import logging
|
|
29
|
+
from tracktolib.logs import init_logging
|
|
30
|
+
|
|
31
|
+
logger = logging.getLogger()
|
|
32
|
+
formatter, stream_handler = init_logging(logger, 'json', version='0.0.1')
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### pg
|
|
36
|
+
|
|
37
|
+
Async PostgreSQL helpers using [asyncpg](https://github.com/MagicStack/asyncpg).
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
uv add tracktolib[pg]
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### pg-sync
|
|
44
|
+
|
|
45
|
+
Sync PostgreSQL helpers using [psycopg](https://www.psycopg.org/psycopg3/) (v3).
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
uv add tracktolib[pg-sync]
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
from psycopg import connect
|
|
53
|
+
from tracktolib.pg_sync import insert_many, fetch_one, fetch_count, fetch_all
|
|
54
|
+
|
|
55
|
+
conn = connect('postgresql://user:pass@localhost/db')
|
|
56
|
+
|
|
57
|
+
data = [
|
|
58
|
+
{'foo': 'bar', 'value': 1},
|
|
59
|
+
{'foo': 'baz', 'value': 2}
|
|
60
|
+
]
|
|
61
|
+
insert_many(conn, 'public.test', data)
|
|
62
|
+
|
|
63
|
+
query = 'SELECT foo from public.test order by value asc'
|
|
64
|
+
value = fetch_one(conn, query, required=True) # {'foo': 'bar'}, raises if not found
|
|
65
|
+
|
|
66
|
+
assert fetch_count(conn, 'public.test') == 2
|
|
67
|
+
|
|
68
|
+
query = 'SELECT * from public.test order by value asc'
|
|
69
|
+
assert fetch_all(conn, query) == data
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### s3
|
|
73
|
+
|
|
74
|
+
Async S3 helpers using [aiobotocore](https://github.com/aio-libs/aiobotocore).
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
uv add tracktolib[s3]
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### s3-minio
|
|
81
|
+
|
|
82
|
+
S3 helpers using [minio](https://min.io/docs/minio/linux/developers/python/API.html).
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
uv add tracktolib[s3-minio]
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### s3-niquests
|
|
89
|
+
|
|
90
|
+
Async S3 helpers using [niquests](https://github.com/jawah/niquests) and [botocore](https://github.com/boto/botocore) presigned URLs.
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
uv add tracktolib[s3-niquests]
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from tracktolib.s3.niquests import S3Session
|
|
98
|
+
|
|
99
|
+
async with S3Session(
|
|
100
|
+
endpoint_url='http://localhost:9000',
|
|
101
|
+
access_key='...',
|
|
102
|
+
secret_key='...',
|
|
103
|
+
region='us-east-1',
|
|
104
|
+
) as s3:
|
|
105
|
+
# Object operations
|
|
106
|
+
await s3.put_object('bucket', 'path/file.txt', b'content')
|
|
107
|
+
content = await s3.get_object('bucket', 'path/file.txt')
|
|
108
|
+
await s3.delete_object('bucket', 'path/file.txt')
|
|
109
|
+
|
|
110
|
+
# Streaming upload (multipart for large files)
|
|
111
|
+
async def data_stream():
|
|
112
|
+
yield b'chunk1'
|
|
113
|
+
yield b'chunk2'
|
|
114
|
+
await s3.file_upload('bucket', 'large-file.bin', data_stream())
|
|
115
|
+
|
|
116
|
+
# Bucket policy management
|
|
117
|
+
policy = {'Version': '2012-10-17', 'Statement': [...]}
|
|
118
|
+
await s3.put_bucket_policy('bucket', policy)
|
|
119
|
+
await s3.get_bucket_policy('bucket')
|
|
120
|
+
await s3.delete_bucket_policy('bucket')
|
|
121
|
+
|
|
122
|
+
# Empty a bucket (delete all objects)
|
|
123
|
+
deleted_count = await s3.empty_bucket('bucket')
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### http (deprecated)
|
|
127
|
+
|
|
128
|
+
HTTP client helpers using [httpx](https://www.python-httpx.org/).
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
uv add tracktolib[http]
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### api
|
|
135
|
+
|
|
136
|
+
FastAPI utilities using [fastapi](https://fastapi.tiangolo.com/) and [pydantic](https://docs.pydantic.dev/).
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
uv add tracktolib[api]
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### notion
|
|
143
|
+
|
|
144
|
+
Notion API helpers using [niquests](https://github.com/jawah/niquests).
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
uv add tracktolib[notion]
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
import niquests
|
|
152
|
+
from tracktolib.notion.fetch import fetch_database, get_notion_headers
|
|
153
|
+
from tracktolib.notion.cache import NotionCache
|
|
154
|
+
|
|
155
|
+
async with niquests.AsyncSession() as session:
|
|
156
|
+
session.headers.update(get_notion_headers())
|
|
157
|
+
|
|
158
|
+
# Without cache
|
|
159
|
+
db = await fetch_database(session, "database-id")
|
|
160
|
+
|
|
161
|
+
# With persistent cache (stored in ~/.cache/tracktolib/notion/cache.json)
|
|
162
|
+
cache = NotionCache()
|
|
163
|
+
db = await fetch_database(session, "database-id", cache=cache)
|
|
164
|
+
|
|
165
|
+
# Check cached databases
|
|
166
|
+
cache.get_databases() # All cached databases
|
|
167
|
+
cache.get_database("db-id") # Specific database (id, title, properties, cached_at)
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### gh
|
|
171
|
+
|
|
172
|
+
GitHub API helpers using [niquests](https://github.com/jawah/niquests).
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
uv add tracktolib[gh]
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
```python
|
|
179
|
+
from tracktolib.gh import GitHubClient
|
|
180
|
+
|
|
181
|
+
async with GitHubClient() as gh: # Uses GITHUB_TOKEN env var
|
|
182
|
+
# Issue comments
|
|
183
|
+
comments = await gh.get_issue_comments("owner/repo", 123)
|
|
184
|
+
await gh.create_issue_comment("owner/repo", 123, "Hello!")
|
|
185
|
+
await gh.delete_comments_with_marker("owner/repo", 123, "<!-- bot -->")
|
|
186
|
+
|
|
187
|
+
# Labels
|
|
188
|
+
labels = await gh.get_issue_labels("owner/repo", 123)
|
|
189
|
+
await gh.add_labels("owner/repo", 123, ["bug", "priority"])
|
|
190
|
+
await gh.remove_label("owner/repo", 123, "wontfix")
|
|
191
|
+
|
|
192
|
+
# Deployments
|
|
193
|
+
deploys = await gh.get_deployments("owner/repo", environment="production")
|
|
194
|
+
await gh.mark_deployment_inactive("owner/repo", "preview-123")
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### cf
|
|
198
|
+
|
|
199
|
+
Cloudflare DNS API helpers using [niquests](https://github.com/jawah/niquests).
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
uv add tracktolib[cf]
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
```python
|
|
206
|
+
from tracktolib.cf import CloudflareDNSClient
|
|
207
|
+
|
|
208
|
+
async with CloudflareDNSClient() as cf: # Uses CLOUDFLARE_API_TOKEN and CLOUDFLARE_ZONE_ID env vars
|
|
209
|
+
# Get a DNS record
|
|
210
|
+
record = await cf.get_dns_record("app.example.com", "CNAME")
|
|
211
|
+
|
|
212
|
+
# Create a DNS record
|
|
213
|
+
record = await cf.create_dns_record(
|
|
214
|
+
"app.example.com",
|
|
215
|
+
"target.example.com",
|
|
216
|
+
record_type="CNAME",
|
|
217
|
+
ttl=60,
|
|
218
|
+
proxied=True,
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
# Delete by ID or name
|
|
222
|
+
await cf.delete_dns_record(record["id"])
|
|
223
|
+
await cf.delete_dns_record_by_name("app.example.com", "CNAME")
|
|
224
|
+
|
|
225
|
+
# Check existence
|
|
226
|
+
exists = await cf.dns_record_exists("app.example.com")
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### tests
|
|
230
|
+
|
|
231
|
+
Testing utilities using [deepdiff](https://github.com/seperman/deepdiff).
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
uv add tracktolib[tests]
|
|
235
|
+
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "tracktolib"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.69.0"
|
|
4
4
|
authors = [
|
|
5
5
|
{ email = "julien.brayere@tracktor.fr" }
|
|
6
6
|
]
|
|
@@ -46,11 +46,13 @@ pg = [
|
|
|
46
46
|
"asyncpg>=0.27.0",
|
|
47
47
|
"rich>=13.6.0",
|
|
48
48
|
]
|
|
49
|
-
notion = [
|
|
50
|
-
|
|
51
|
-
]
|
|
49
|
+
notion = ["niquests>=3.17.0"]
|
|
50
|
+
gh = ["niquests>=3.17.0"]
|
|
51
|
+
cf = ["niquests>=3.17.0"]
|
|
52
52
|
|
|
53
53
|
[dependency-groups]
|
|
54
|
+
niquests = ["niquests>=3.17.0"]
|
|
55
|
+
|
|
54
56
|
dev = [
|
|
55
57
|
"pytest-cov>=7.0.0,<8",
|
|
56
58
|
"pytest>=9.0.1,<10",
|
|
@@ -66,9 +68,11 @@ dev = [
|
|
|
66
68
|
"pycryptodome>=3.23.0",
|
|
67
69
|
"aiobotocore==2.15.2",
|
|
68
70
|
# niquests for s3-niquests tests (botocore comes from aiobotocore)
|
|
69
|
-
"niquests
|
|
71
|
+
{ include-group = "niquests" },
|
|
70
72
|
"python-json-logger>=3.2.0",
|
|
71
73
|
"prek>=0.2.30",
|
|
74
|
+
"datamodel-code-generator>=0.53.0",
|
|
75
|
+
"pytest-asyncio>=1.3.0",
|
|
72
76
|
]
|
|
73
77
|
|
|
74
78
|
bump = [
|
|
@@ -98,6 +102,8 @@ filterwarnings = [
|
|
|
98
102
|
"ignore::DeprecationWarning",
|
|
99
103
|
"ignore::PendingDeprecationWarning"
|
|
100
104
|
]
|
|
105
|
+
asyncio_mode = "auto"
|
|
106
|
+
asyncio_default_fixture_loop_scope = "function"
|
|
101
107
|
|
|
102
108
|
[tool.pyright]
|
|
103
109
|
include = ["tracktolib", "tests"]
|
|
@@ -108,7 +114,7 @@ pythonPlatform = "Linux"
|
|
|
108
114
|
|
|
109
115
|
[tool.commitizen]
|
|
110
116
|
name = "cz_conventional_commits"
|
|
111
|
-
version = "0.
|
|
117
|
+
version = "0.69.0"
|
|
112
118
|
tag_format = "$version"
|
|
113
119
|
version_files = [
|
|
114
120
|
"pyproject.toml:version"
|
|
@@ -122,6 +128,9 @@ changelog_file = "CHANGELOG.md"
|
|
|
122
128
|
line-length = 120
|
|
123
129
|
target-version = "py314"
|
|
124
130
|
|
|
131
|
+
[tool.ruff.lint]
|
|
132
|
+
# I: isort - consolidates duplicate imports
|
|
133
|
+
extend-select = ["I"]
|
|
125
134
|
|
|
126
135
|
[tool.ruff.lint.per-file-ignores]
|
|
127
136
|
"__init__.py" = [
|
|
@@ -1,32 +1,31 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import warnings
|
|
3
|
-
from
|
|
4
|
-
from dataclasses import field, dataclass
|
|
3
|
+
from dataclasses import dataclass, field
|
|
5
4
|
from inspect import getdoc
|
|
6
5
|
from typing import (
|
|
7
|
-
Callable,
|
|
8
6
|
Any,
|
|
9
|
-
Literal,
|
|
10
|
-
Sequence,
|
|
11
7
|
AsyncIterator,
|
|
8
|
+
Callable,
|
|
9
|
+
ClassVar,
|
|
12
10
|
Coroutine,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
Literal,
|
|
12
|
+
Mapping,
|
|
13
|
+
Sequence,
|
|
16
14
|
TypeAlias,
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
TypedDict,
|
|
16
|
+
get_args,
|
|
19
17
|
get_origin,
|
|
18
|
+
get_type_hints,
|
|
20
19
|
)
|
|
21
20
|
|
|
22
|
-
from .utils import
|
|
21
|
+
from .utils import get_first_line, json_serial
|
|
23
22
|
|
|
24
23
|
try:
|
|
25
|
-
|
|
24
|
+
import starlette.status
|
|
25
|
+
from fastapi import APIRouter, params
|
|
26
26
|
from fastapi.responses import JSONResponse
|
|
27
|
-
from pydantic.alias_generators import to_camel
|
|
28
27
|
from pydantic import BaseModel, ConfigDict
|
|
29
|
-
import
|
|
28
|
+
from pydantic.alias_generators import to_camel
|
|
30
29
|
except ImportError:
|
|
31
30
|
raise ImportError('Please install fastapi, pydantic or tracktolib with "api" to use this module')
|
|
32
31
|
|
|
@@ -61,7 +60,7 @@ class MethodMeta(TypedDict):
|
|
|
61
60
|
status_code: StatusCode
|
|
62
61
|
dependencies: Dependencies
|
|
63
62
|
path: str | None
|
|
64
|
-
response_model:
|
|
63
|
+
response_model: type[BaseModel | None | Sequence[BaseModel]] | None
|
|
65
64
|
openapi_extra: dict[str, Any] | None
|
|
66
65
|
name: str | None
|
|
67
66
|
summary: str | None
|
|
@@ -82,7 +81,7 @@ class Endpoint:
|
|
|
82
81
|
status_code: StatusCode = None,
|
|
83
82
|
dependencies: Dependencies = None,
|
|
84
83
|
path: str | None = None,
|
|
85
|
-
model:
|
|
84
|
+
model: type[B] | None = None,
|
|
86
85
|
openapi_extra: dict[str, Any] | None = None,
|
|
87
86
|
name: str | None = None,
|
|
88
87
|
summary: str | None = None,
|
|
@@ -109,7 +108,7 @@ class Endpoint:
|
|
|
109
108
|
status_code: StatusCode = None,
|
|
110
109
|
dependencies: Dependencies = None,
|
|
111
110
|
path: str | None = None,
|
|
112
|
-
model:
|
|
111
|
+
model: type[B] | None = None,
|
|
113
112
|
openapi_extra: dict[str, Any] | None = None,
|
|
114
113
|
name: str | None = None,
|
|
115
114
|
summary: str | None = None,
|
|
@@ -135,7 +134,7 @@ class Endpoint:
|
|
|
135
134
|
status_code: StatusCode = None,
|
|
136
135
|
dependencies: Dependencies = None,
|
|
137
136
|
path: str | None = None,
|
|
138
|
-
model:
|
|
137
|
+
model: type[B] | None = None,
|
|
139
138
|
openapi_extra: dict[str, Any] | None = None,
|
|
140
139
|
name: str | None = None,
|
|
141
140
|
summary: str | None = None,
|
|
@@ -161,7 +160,7 @@ class Endpoint:
|
|
|
161
160
|
status_code: StatusCode = None,
|
|
162
161
|
dependencies: Dependencies = None,
|
|
163
162
|
path: str | None = None,
|
|
164
|
-
model:
|
|
163
|
+
model: type[B] | None = None,
|
|
165
164
|
openapi_extra: dict[str, Any] | None = None,
|
|
166
165
|
name: str | None = None,
|
|
167
166
|
summary: str | None = None,
|
|
@@ -187,7 +186,7 @@ class Endpoint:
|
|
|
187
186
|
status_code: StatusCode = None,
|
|
188
187
|
dependencies: Dependencies = None,
|
|
189
188
|
path: str | None = None,
|
|
190
|
-
model:
|
|
189
|
+
model: type[B] | None = None,
|
|
191
190
|
openapi_extra: dict[str, Any] | None = None,
|
|
192
191
|
name: str | None = None,
|
|
193
192
|
summary: str | None = None,
|
|
@@ -216,7 +215,7 @@ def _get_method_wrapper[B: _BaseModelBound](
|
|
|
216
215
|
status_code: StatusCode = None,
|
|
217
216
|
dependencies: Dependencies = None,
|
|
218
217
|
path: str | None = None,
|
|
219
|
-
model:
|
|
218
|
+
model: type[B] | None = None,
|
|
220
219
|
openapi_extra: dict[str, Any] | None = None,
|
|
221
220
|
name: str | None = None,
|
|
222
221
|
summary: str | None = None,
|
|
@@ -335,7 +334,7 @@ def check_status(resp, status: int = starlette.status.HTTP_200_OK):
|
|
|
335
334
|
raise AssertionError(json.dumps(resp.json(), indent=4))
|
|
336
335
|
|
|
337
336
|
|
|
338
|
-
def generate_list_name_model[B: _BaseModelBound](model:
|
|
337
|
+
def generate_list_name_model[B: _BaseModelBound](model: type[B], status: int | None = None) -> dict:
|
|
339
338
|
_status = "200" if status is None else str(status)
|
|
340
339
|
if get_origin(model) and get_origin(model) is list:
|
|
341
340
|
_title = f"Array[{get_args(model)[0].__name__}]"
|