tracktolib 0.47.0__tar.gz → 0.47.2__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.47.0 → tracktolib-0.47.2}/PKG-INFO +1 -1
- {tracktolib-0.47.0 → tracktolib-0.47.2}/pyproject.toml +2 -2
- {tracktolib-0.47.0 → tracktolib-0.47.2}/setup.py +1 -1
- {tracktolib-0.47.0 → tracktolib-0.47.2}/tracktolib/api.py +51 -3
- {tracktolib-0.47.0 → tracktolib-0.47.2}/tracktolib/pg/utils.py +1 -1
- {tracktolib-0.47.0 → tracktolib-0.47.2}/tracktolib/pg_sync.py +5 -2
- {tracktolib-0.47.0 → tracktolib-0.47.2}/tracktolib/utils.py +5 -0
- {tracktolib-0.47.0 → tracktolib-0.47.2}/LICENSE +0 -0
- {tracktolib-0.47.0 → tracktolib-0.47.2}/README.md +0 -0
- {tracktolib-0.47.0 → tracktolib-0.47.2}/tracktolib/__init__.py +0 -0
- {tracktolib-0.47.0 → tracktolib-0.47.2}/tracktolib/http_utils.py +0 -0
- {tracktolib-0.47.0 → tracktolib-0.47.2}/tracktolib/logs.py +0 -0
- {tracktolib-0.47.0 → tracktolib-0.47.2}/tracktolib/pg/__init__.py +0 -0
- {tracktolib-0.47.0 → tracktolib-0.47.2}/tracktolib/pg/query.py +0 -0
- {tracktolib-0.47.0 → tracktolib-0.47.2}/tracktolib/pg_utils.py +0 -0
- {tracktolib-0.47.0 → tracktolib-0.47.2}/tracktolib/s3/__init__.py +0 -0
- {tracktolib-0.47.0 → tracktolib-0.47.2}/tracktolib/s3/minio.py +0 -0
- {tracktolib-0.47.0 → tracktolib-0.47.2}/tracktolib/s3/s3.py +0 -0
- {tracktolib-0.47.0 → tracktolib-0.47.2}/tracktolib/tests.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "tracktolib"
|
|
3
|
-
version = "0.47.
|
|
3
|
+
version = "0.47.2"
|
|
4
4
|
description = "Utility library for python"
|
|
5
5
|
authors = ["Julien Brayere <julien.brayere@tracktor.fr>"]
|
|
6
6
|
license = "MIT"
|
|
@@ -70,7 +70,7 @@ pythonPlatform = "Linux"
|
|
|
70
70
|
|
|
71
71
|
[tool.commitizen]
|
|
72
72
|
name = "cz_conventional_commits"
|
|
73
|
-
version = "0.47.
|
|
73
|
+
version = "0.47.2"
|
|
74
74
|
tag_format = "$version"
|
|
75
75
|
version_files = [
|
|
76
76
|
"pyproject.toml:version"
|
|
@@ -20,7 +20,7 @@ extras_require = \
|
|
|
20
20
|
|
|
21
21
|
setup_kwargs = {
|
|
22
22
|
'name': 'tracktolib',
|
|
23
|
-
'version': '0.47.
|
|
23
|
+
'version': '0.47.2',
|
|
24
24
|
'description': 'Utility library for python',
|
|
25
25
|
'long_description': "# Tracktolib\n\n[](https://pypi.python.org/pypi/tracktolib)\n[](https://pypi.python.org/pypi/tracktolib)\n[](https://app.circleci.com/pipelines/github/Tracktor/tracktolib?branch=master)\n\nUtility library for python\n\n# Installation\n\nYou can choose to not install all the dependencies by specifying\nthe [extra](https://python-poetry.org/docs/cli/#options-4) parameter such as:\n\n```bash\npoetry add tracktolib@latest -E pg-sync -E tests --group dev \n```\n\nHere we only install the utilities using `psycopg` (pg-sync) and `deepdiff` (tests) for the dev environment.\n\n# Utilities\n\n- **log**\n\nUtility functions for logging.\n\n```python\nimport logging\nfrom tracktolib.logs import init_logging\n\nlogger = logging.getLogger()\nformatter, stream_handler = init_logging(logger, 'json', version='0.0.1')\n```\n\n- **pg**\n\nUtility functions for [asyncpg](https://github.com/MagicStack/asyncpg)\n\n- **pg-sync**\n\nUtility functions based on psycopg such as `fetch_one`, `insert_many`, `fetch_count` ...\n\nTo use the functions, create a `Connection` using psycopg: `conn = psycopg2.connect()`\n\n*fetch_one*\n\n```python\nfrom pg.pg_sync import (\n insert_many, fetch_one, fetch_count, fetch_all\n)\n\ndata = [\n {'foo': 'bar', 'value': 1},\n {'foo': 'baz', 'value': 2}\n]\ninsert_many(conn, 'public.test', data) # Will insert the 2 dict\nquery = 'SELECT foo from public.test order by value asc'\nvalue = fetch_one(conn, query, required=True) # Will return {'foo': 'bar'}, raise an error is not found\nassert fetch_count(conn, 'public.test') == 2\nquery = 'SELECT * from public.test order by value asc'\nassert fetch_all(conn, query) == data\n\n```\n\n- **tests**\n\nUtility functions for testing\n\n- **s3-minio**\n\nUtility functions for [minio](https://min.io/docs/minio/linux/developers/python/API.html)\n\n- **s3**\n\nUtility functions for [aiobotocore](https://github.com/aio-libs/aiobotocore)\n\n- **logs**\n\nUtility functions to initialize the logging formatting and streams\n\n- **http**\n\nUtility functions using [httpx](https://www.python-httpx.org/)\n\n- **api**\n\nUtility functions using [fastapi](https://fastapi.tiangolo.com/)\n",
|
|
26
26
|
'author': 'Julien Brayere',
|
|
@@ -19,7 +19,7 @@ from typing import (
|
|
|
19
19
|
get_origin,
|
|
20
20
|
)
|
|
21
21
|
|
|
22
|
-
from .utils import json_serial
|
|
22
|
+
from .utils import json_serial, get_first_line
|
|
23
23
|
|
|
24
24
|
try:
|
|
25
25
|
from fastapi import params, APIRouter
|
|
@@ -66,6 +66,9 @@ class MethodMeta(TypedDict):
|
|
|
66
66
|
path: str | None
|
|
67
67
|
response_model: Type[BaseModel | None | Sequence[BaseModel]] | None
|
|
68
68
|
openapi_extra: dict[str, Any] | None
|
|
69
|
+
name: str | None
|
|
70
|
+
summary: str | None
|
|
71
|
+
description: str | None
|
|
69
72
|
|
|
70
73
|
|
|
71
74
|
@dataclass
|
|
@@ -83,6 +86,9 @@ class Endpoint:
|
|
|
83
86
|
path: str | None = None,
|
|
84
87
|
model: Type[B] | None = None,
|
|
85
88
|
openapi_extra: dict[str, Any] | None = None,
|
|
89
|
+
name: str | None = None,
|
|
90
|
+
summary: str | None = None,
|
|
91
|
+
description: str | None = None,
|
|
86
92
|
):
|
|
87
93
|
return _get_method_wrapper(
|
|
88
94
|
cls=self,
|
|
@@ -92,6 +98,9 @@ class Endpoint:
|
|
|
92
98
|
path=path,
|
|
93
99
|
model=model,
|
|
94
100
|
openapi_extra=openapi_extra,
|
|
101
|
+
name=name,
|
|
102
|
+
summary=summary,
|
|
103
|
+
description=description,
|
|
95
104
|
)
|
|
96
105
|
|
|
97
106
|
def post(
|
|
@@ -102,6 +111,9 @@ class Endpoint:
|
|
|
102
111
|
path: str | None = None,
|
|
103
112
|
model: Type[B] | None = None,
|
|
104
113
|
openapi_extra: dict[str, Any] | None = None,
|
|
114
|
+
name: str | None = None,
|
|
115
|
+
summary: str | None = None,
|
|
116
|
+
description: str | None = None,
|
|
105
117
|
):
|
|
106
118
|
return _get_method_wrapper(
|
|
107
119
|
cls=self,
|
|
@@ -111,6 +123,9 @@ class Endpoint:
|
|
|
111
123
|
path=path,
|
|
112
124
|
model=model,
|
|
113
125
|
openapi_extra=openapi_extra,
|
|
126
|
+
name=name,
|
|
127
|
+
summary=summary,
|
|
128
|
+
description=description,
|
|
114
129
|
)
|
|
115
130
|
|
|
116
131
|
def put(
|
|
@@ -120,6 +135,9 @@ class Endpoint:
|
|
|
120
135
|
path: str | None = None,
|
|
121
136
|
model: Type[B] | None = None,
|
|
122
137
|
openapi_extra: dict[str, Any] | None = None,
|
|
138
|
+
name: str | None = None,
|
|
139
|
+
summary: str | None = None,
|
|
140
|
+
description: str | None = None,
|
|
123
141
|
):
|
|
124
142
|
return _get_method_wrapper(
|
|
125
143
|
cls=self,
|
|
@@ -129,6 +147,9 @@ class Endpoint:
|
|
|
129
147
|
path=path,
|
|
130
148
|
model=model,
|
|
131
149
|
openapi_extra=openapi_extra,
|
|
150
|
+
name=name,
|
|
151
|
+
summary=summary,
|
|
152
|
+
description=description,
|
|
132
153
|
)
|
|
133
154
|
|
|
134
155
|
def delete(
|
|
@@ -138,6 +159,9 @@ class Endpoint:
|
|
|
138
159
|
path: str | None = None,
|
|
139
160
|
model: Type[B] | None = None,
|
|
140
161
|
openapi_extra: dict[str, Any] | None = None,
|
|
162
|
+
name: str | None = None,
|
|
163
|
+
summary: str | None = None,
|
|
164
|
+
description: str | None = None,
|
|
141
165
|
):
|
|
142
166
|
return _get_method_wrapper(
|
|
143
167
|
cls=self,
|
|
@@ -147,6 +171,9 @@ class Endpoint:
|
|
|
147
171
|
path=path,
|
|
148
172
|
model=model,
|
|
149
173
|
openapi_extra=openapi_extra,
|
|
174
|
+
name=name,
|
|
175
|
+
summary=summary,
|
|
176
|
+
description=description,
|
|
150
177
|
)
|
|
151
178
|
|
|
152
179
|
def patch(
|
|
@@ -156,6 +183,9 @@ class Endpoint:
|
|
|
156
183
|
path: str | None = None,
|
|
157
184
|
model: Type[B] | None = None,
|
|
158
185
|
openapi_extra: dict[str, Any] | None = None,
|
|
186
|
+
name: str | None = None,
|
|
187
|
+
summary: str | None = None,
|
|
188
|
+
description: str | None = None,
|
|
159
189
|
):
|
|
160
190
|
return _get_method_wrapper(
|
|
161
191
|
cls=self,
|
|
@@ -165,6 +195,9 @@ class Endpoint:
|
|
|
165
195
|
path=path,
|
|
166
196
|
model=model,
|
|
167
197
|
openapi_extra=openapi_extra,
|
|
198
|
+
name=name,
|
|
199
|
+
summary=summary,
|
|
200
|
+
description=description,
|
|
168
201
|
)
|
|
169
202
|
|
|
170
203
|
|
|
@@ -177,6 +210,9 @@ def _get_method_wrapper(
|
|
|
177
210
|
path: str | None = None,
|
|
178
211
|
model: Type[B] | None = None,
|
|
179
212
|
openapi_extra: dict[str, Any] | None = None,
|
|
213
|
+
name: str | None = None,
|
|
214
|
+
summary: str | None = None,
|
|
215
|
+
description: str | None = None,
|
|
180
216
|
):
|
|
181
217
|
def _set_method_wrapper(func: EnpointFn):
|
|
182
218
|
if model is not None:
|
|
@@ -193,6 +229,9 @@ def _get_method_wrapper(
|
|
|
193
229
|
"path": path,
|
|
194
230
|
"response_model": model,
|
|
195
231
|
"openapi_extra": _openapi_extra,
|
|
232
|
+
"name": name,
|
|
233
|
+
"summary": summary,
|
|
234
|
+
"description": description,
|
|
196
235
|
}
|
|
197
236
|
cls._methods[method] = _meta
|
|
198
237
|
|
|
@@ -223,6 +262,9 @@ def add_endpoint(
|
|
|
223
262
|
_dependencies = _meta["dependencies"]
|
|
224
263
|
_path = _meta["path"]
|
|
225
264
|
_response_model = _meta["response_model"]
|
|
265
|
+
_name = _meta.get("name")
|
|
266
|
+
_summary = _meta.get("summary")
|
|
267
|
+
_description = _meta.get("description")
|
|
226
268
|
if not _response_model:
|
|
227
269
|
try:
|
|
228
270
|
_response_model = _get_return_type(_fn)
|
|
@@ -231,15 +273,21 @@ def add_endpoint(
|
|
|
231
273
|
|
|
232
274
|
full_path = path if not _path else f"{path}/{_path}"
|
|
233
275
|
|
|
234
|
-
|
|
276
|
+
description = getdoc(_fn)
|
|
277
|
+
if not description:
|
|
235
278
|
warnings.warn(f"Docstring is missing for {_method} {path}")
|
|
279
|
+
else:
|
|
280
|
+
_name = _name if _name else get_first_line(description)
|
|
281
|
+
_summary = _summary if _summary else get_first_line(description)
|
|
236
282
|
|
|
237
283
|
# Todo: add warning name is not None
|
|
238
284
|
router.add_api_route(
|
|
239
285
|
full_path,
|
|
240
286
|
_fn,
|
|
241
287
|
methods=[_method],
|
|
242
|
-
name=
|
|
288
|
+
name=_name,
|
|
289
|
+
summary=_summary,
|
|
290
|
+
description=description,
|
|
243
291
|
response_model=_response_model,
|
|
244
292
|
status_code=_status_code,
|
|
245
293
|
dependencies=[*(_dependencies or []), *(dependencies or [])],
|
|
@@ -13,7 +13,7 @@ try:
|
|
|
13
13
|
import asyncpg
|
|
14
14
|
from rich.progress import Progress
|
|
15
15
|
except ImportError:
|
|
16
|
-
raise ImportError('Please install tracktolib with "pg" to use this module')
|
|
16
|
+
raise ImportError('Please install asyncpg, rich or tracktolib with "pg" to use this module')
|
|
17
17
|
|
|
18
18
|
from asyncpg.exceptions import (
|
|
19
19
|
CheckViolationError,
|
|
@@ -126,9 +126,12 @@ def insert_csv(
|
|
|
126
126
|
exclude_columns: Iterable[str] | None = None,
|
|
127
127
|
delimiter: LiteralString = ",",
|
|
128
128
|
block_size: int = 1000,
|
|
129
|
+
on_conflict: LiteralString = "ON CONFLICT DO NOTHING",
|
|
129
130
|
):
|
|
130
|
-
|
|
131
|
-
|
|
131
|
+
_columns = cast(LiteralString, csv_path.open().readline())
|
|
132
|
+
_tmp_table, _tmp_query, _insert_query = get_tmp_table_query(
|
|
133
|
+
schema, table, columns=_columns.split(","), on_conflict=on_conflict
|
|
134
|
+
)
|
|
132
135
|
_query: Query = query or cast(
|
|
133
136
|
LiteralString,
|
|
134
137
|
f"""
|
|
@@ -184,3 +184,8 @@ def deep_reload(m: ModuleType):
|
|
|
184
184
|
sub_mods = [_mod for _mod in sys.modules if _mod == m.__name__ or _mod.startswith(f"{m.__name__}.")]
|
|
185
185
|
for pkg in sorted(sub_mods, key=lambda item: item.count("."), reverse=True):
|
|
186
186
|
importlib.reload(sys.modules[pkg])
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def get_first_line(lines: str) -> str:
|
|
190
|
+
_lines = lines.split("\n")
|
|
191
|
+
return _lines[0] if _lines else lines
|
|
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
|