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.
Files changed (33) hide show
  1. {tracktolib-0.67.0 → tracktolib-0.69.0}/PKG-INFO +115 -2
  2. tracktolib-0.69.0/README.md +235 -0
  3. {tracktolib-0.67.0 → tracktolib-0.69.0}/pyproject.toml +15 -6
  4. {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/api.py +21 -22
  5. tracktolib-0.69.0/tracktolib/cf/__init__.py +8 -0
  6. tracktolib-0.69.0/tracktolib/cf/client.py +149 -0
  7. tracktolib-0.69.0/tracktolib/cf/types.py +17 -0
  8. tracktolib-0.69.0/tracktolib/gh/__init__.py +11 -0
  9. tracktolib-0.69.0/tracktolib/gh/client.py +206 -0
  10. tracktolib-0.69.0/tracktolib/gh/types.py +203 -0
  11. {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/http_utils.py +1 -1
  12. {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/logs.py +1 -1
  13. tracktolib-0.69.0/tracktolib/notion/__init__.py +44 -0
  14. tracktolib-0.69.0/tracktolib/notion/blocks.py +459 -0
  15. tracktolib-0.69.0/tracktolib/notion/cache.py +202 -0
  16. {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/notion/fetch.py +121 -5
  17. tracktolib-0.69.0/tracktolib/notion/markdown.py +468 -0
  18. {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/notion/models.py +26 -0
  19. tracktolib-0.69.0/tracktolib/notion/utils.py +567 -0
  20. {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/pg/__init__.py +10 -10
  21. {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/pg/query.py +1 -1
  22. {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/pg/utils.py +5 -5
  23. {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/pg_sync.py +5 -7
  24. {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/pg_utils.py +1 -4
  25. {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/s3/niquests.py +235 -32
  26. {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/s3/s3.py +1 -1
  27. {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/utils.py +48 -3
  28. tracktolib-0.67.0/README.md +0 -126
  29. tracktolib-0.67.0/tracktolib/notion/__init__.py +0 -0
  30. {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/__init__.py +0 -0
  31. {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/s3/__init__.py +0 -0
  32. {tracktolib-0.67.0 → tracktolib-0.69.0}/tracktolib/s3/minio.py +1 -1
  33. {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.67.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
+ [![Python versions](https://img.shields.io/pypi/pyversions/tracktolib)](https://pypi.python.org/pypi/tracktolib)
4
+ [![Latest PyPI version](https://img.shields.io/pypi/v/tracktolib?logo=pypi)](https://pypi.python.org/pypi/tracktolib)
5
+ [![CI](https://github.com/Tracktor/tracktolib/actions/workflows/ci.yml/badge.svg)](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.67.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
- "niquests>=3.17.0"
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>=3.17.0",
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.67.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 collections.abc import Mapping
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
- get_type_hints,
14
- get_args,
15
- TypedDict,
11
+ Literal,
12
+ Mapping,
13
+ Sequence,
16
14
  TypeAlias,
17
- Type,
18
- ClassVar,
15
+ TypedDict,
16
+ get_args,
19
17
  get_origin,
18
+ get_type_hints,
20
19
  )
21
20
 
22
- from .utils import json_serial, get_first_line
21
+ from .utils import get_first_line, json_serial
23
22
 
24
23
  try:
25
- from fastapi import params, APIRouter
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 starlette.status
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: Type[BaseModel | None | Sequence[BaseModel]] | None
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: Type[B] | None = None,
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: Type[B] | None = None,
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: Type[B] | None = None,
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: Type[B] | None = None,
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: Type[B] | None = None,
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: Type[B] | None = None,
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: Type[B], status: int | None = None) -> dict:
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__}]"
@@ -0,0 +1,8 @@
1
+ from .client import CloudflareDNSClient, CloudflareError
2
+ from .types import DnsRecord
3
+
4
+ __all__ = [
5
+ "CloudflareDNSClient",
6
+ "CloudflareError",
7
+ "DnsRecord",
8
+ ]