tracktolib 0.48.0__tar.gz → 0.49.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.
@@ -1,18 +1,17 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tracktolib
3
- Version: 0.48.0
3
+ Version: 0.49.0
4
4
  Summary: Utility library for python
5
5
  Home-page: https://github.com/tracktor/tracktolib
6
6
  License: MIT
7
7
  Keywords: utility
8
8
  Author: Julien Brayere
9
9
  Author-email: julien.brayere@tracktor.fr
10
- Requires-Python: >=3.10,<4.0
10
+ Requires-Python: >=3.12,<4.0
11
11
  Classifier: License :: OSI Approved :: MIT License
12
12
  Classifier: Operating System :: OS Independent
13
13
  Classifier: Programming Language :: Python :: 3
14
- Classifier: Programming Language :: Python :: 3.10
15
- Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
16
15
  Provides-Extra: api
17
16
  Provides-Extra: http
18
17
  Provides-Extra: logs
@@ -21,16 +20,17 @@ Provides-Extra: pg-sync
21
20
  Provides-Extra: s3
22
21
  Provides-Extra: s3-minio
23
22
  Provides-Extra: tests
24
- Requires-Dist: aiobotocore (>=2.9.0); extra == "s3"
25
- Requires-Dist: asyncpg (>=0.27.0); extra == "pg"
26
- Requires-Dist: deepdiff (>=6.6.0); extra == "tests"
27
- Requires-Dist: fastapi (>=0.103.2); extra == "api"
28
- Requires-Dist: httpx (>=0.25.0); extra == "http"
29
- Requires-Dist: minio (>=7.2.0); extra == "s3-minio"
30
- Requires-Dist: psycopg (>=3.1.12); extra == "pg-sync"
31
- Requires-Dist: pydantic (>=2); extra == "api"
32
- Requires-Dist: python-json-logger (>=2.0.4); extra == "logs"
33
- Requires-Dist: rich (>=13.6.0); extra == "pg"
23
+ Requires-Dist: aiobotocore (>=2.9.0) ; extra == "s3"
24
+ Requires-Dist: asyncpg (>=0.27.0) ; extra == "pg"
25
+ Requires-Dist: deepdiff (>=6.6.0) ; extra == "tests"
26
+ Requires-Dist: fastapi (>=0.103.2) ; extra == "api"
27
+ Requires-Dist: httpx (>=0.25.0) ; extra == "http"
28
+ Requires-Dist: minio (>=7.2.0) ; extra == "s3-minio"
29
+ Requires-Dist: psycopg (>=3.1.12) ; extra == "pg-sync"
30
+ Requires-Dist: pycryptodome (>=3.20.0) ; extra == "s3-minio"
31
+ Requires-Dist: pydantic (>=2) ; extra == "api"
32
+ Requires-Dist: python-json-logger (>=2.0.4) ; extra == "logs"
33
+ Requires-Dist: rich (>=13.6.0) ; extra == "pg"
34
34
  Project-URL: Repository, https://github.com/tracktor/tracktolib
35
35
  Description-Content-Type: text/markdown
36
36
 
@@ -80,7 +80,7 @@ To use the functions, create a `Connection` using psycopg: `conn = psycopg2.conn
80
80
  *fetch_one*
81
81
 
82
82
  ```python
83
- from pg.pg_sync import (
83
+ from tracktolib.pg.pg_sync import (
84
84
  insert_many, fetch_one, fetch_count, fetch_all
85
85
  )
86
86
 
@@ -44,7 +44,7 @@ To use the functions, create a `Connection` using psycopg: `conn = psycopg2.conn
44
44
  *fetch_one*
45
45
 
46
46
  ```python
47
- from pg.pg_sync import (
47
+ from tracktolib.pg.pg_sync import (
48
48
  insert_many, fetch_one, fetch_count, fetch_all
49
49
  )
50
50
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "tracktolib"
3
- version = "0.48.0"
3
+ version = "0.49.0"
4
4
  description = "Utility library for python"
5
5
  authors = ["Julien Brayere <julien.brayere@tracktor.fr>"]
6
6
  license = "MIT"
@@ -16,11 +16,13 @@ include = [
16
16
  ]
17
17
 
18
18
  [tool.poetry.dependencies]
19
- python = ">=3.10,<4.0"
19
+ python = ">=3.12,<4.0"
20
20
 
21
21
  python-json-logger = { version = ">=2.0.4", optional = true }
22
22
  psycopg = { version = ">=3.1.12", optional = true }
23
23
  minio = { version = ">=7.2.0", optional = true }
24
+ # Needed for minio, otherwise it raises ModuleNotFoundError: No module named 'Crypto.Cipher'
25
+ pycryptodome = { version = ">=3.20.0", optional = true }
24
26
  aiobotocore = { version = ">=2.9.0", optional = true }
25
27
  deepdiff = { version = ">=6.6.0", optional = true }
26
28
  httpx = { version = ">=0.25.0", optional = true }
@@ -29,11 +31,10 @@ pydantic = { version = ">=2", optional = true }
29
31
  asyncpg = ">=0.27.0"
30
32
  rich = { version = ">=13.6.0", optional = true }
31
33
 
32
-
33
34
  [tool.poetry.extras]
34
35
  logs = ["python-json-logger"]
35
36
  pg-sync = ["psycopg"]
36
- s3-minio = ["minio"]
37
+ s3-minio = ["minio", "pycryptodome"]
37
38
  s3 = ["aiobotocore"]
38
39
  tests = ["deepdiff"]
39
40
  http = ["httpx"]
@@ -41,14 +42,20 @@ api = ["fastapi", "pydantic"]
41
42
  pg = ["asyncpg", "rich"]
42
43
 
43
44
  [tool.poetry.group.dev.dependencies]
44
- pyright = "^1.1.284"
45
45
  commitizen = "^3.11.0"
46
- pytest = "^7.2.0"
47
- pytest-cov = "^4.0.0"
48
- pydantic = ">=2,<3"
49
- ruff = "^0.1.6"
46
+ pytest-cov = "^5.0.0"
47
+ pytest = "^8.2.2"
48
+ pyright = "^1.1.371"
49
+ ruff = "^0.5.2"
50
+ pydantic = "^2.8.2"
50
51
  # Issue for mac with trackit version of multidict
51
- multidict = ">=6.0.5"
52
+ multidict = "^6.0.5"
53
+ fastapi ="^0.111.1"
54
+ httpx = "^0.27.0"
55
+ psycopg = "^3.2.1"
56
+ minio = "^7.2.7"
57
+ pycryptodome = "^3.20.0"
58
+ aiobotocore = "^2.13.1"
52
59
 
53
60
  [build-system]
54
61
  requires = ["poetry-core"]
@@ -60,19 +67,21 @@ testpaths = [
60
67
  "tests"
61
68
  ]
62
69
  python_files = "*.py"
63
- filterwarnings = ["ignore:::.*minio.api*",
64
- "ignore:.*urllib3.contrib.pyopenssl.*:DeprecationWarning"]
70
+ filterwarnings = [
71
+ "ignore::DeprecationWarning",
72
+ "ignore::PendingDeprecationWarning"
73
+ ]
65
74
 
66
75
  [tool.pyright]
67
76
  include = ["tracktolib", "tests"]
68
77
  exclude = []
69
78
 
70
- pythonVersion = "3.10"
79
+ pythonVersion = "3.12"
71
80
  pythonPlatform = "Linux"
72
81
 
73
82
  [tool.commitizen]
74
83
  name = "cz_conventional_commits"
75
- version = "0.48.0"
84
+ version = "0.49.0"
76
85
  tag_format = "$version"
77
86
  version_files = [
78
87
  "pyproject.toml:version"
@@ -82,11 +91,11 @@ bump_message = "release $current_version → $new_version [skip ci]"
82
91
 
83
92
  [tool.ruff]
84
93
  line-length = 120
85
- target-version = "py310"
94
+ target-version = "py312"
86
95
  # Waiting for fix: https://github.com/charliermarsh/ruff/issues/282
87
- ignore = ["E999"]
96
+ #ignore = ["E999"]
88
97
 
89
- [tool.ruff.per-file-ignores]
98
+ [tool.ruff.lint.per-file-ignores]
90
99
  "__init__.py" = [
91
100
  # imported but unused
92
101
  "F401",
@@ -96,10 +105,10 @@ ignore = ["E999"]
96
105
  "F405"
97
106
  ]
98
107
 
99
- [tool.ruff.flake8-quotes]
108
+ [tool.ruff.lint.flake8-quotes]
100
109
  docstring-quotes = "double"
101
110
  inline-quotes = "single"
102
111
 
103
- [tool.ruff.flake8-tidy-imports]
112
+ [tool.ruff.lint.flake8-tidy-imports]
104
113
  # Disallow all relative imports.
105
114
  ban-relative-imports = "all"
@@ -44,7 +44,7 @@ def Depends(
44
44
  use_cache: bool = True,
45
45
  ) -> D:
46
46
  """TODO: add support for __call__ (maybe see https://github.com/python/typing/discussions/1106 ?)"""
47
- return params.Depends(dependency, use_cache=use_cache) # pyright: ignore [reportGeneralTypeIssues]
47
+ return params.Depends(dependency, use_cache=use_cache) # pyright: ignore [reportReturnType]
48
48
 
49
49
 
50
50
  B = TypeVar("B", bound=BaseModel | None | Sequence[BaseModel])
@@ -319,7 +319,8 @@ class CamelCaseModel(BaseModel):
319
319
 
320
320
 
321
321
  def check_status(resp, status: int = starlette.status.HTTP_200_OK):
322
- assert resp.status_code == status, json.dumps(resp.json(), indent=4)
322
+ if resp.status_code != status:
323
+ raise AssertionError(json.dumps(resp.json(), indent=4))
323
324
 
324
325
 
325
326
  def generate_list_name_model(model: Type[B], status: int | None = None) -> dict:
@@ -22,8 +22,7 @@ async def download_file(
22
22
  on_response: Callable[[httpx.Response], None] | None = None,
23
23
  params: QueryParamTypes | None = None,
24
24
  headers: dict[str, str] | None = None,
25
- ):
26
- ...
25
+ ): ...
27
26
 
28
27
 
29
28
  @typing.overload
@@ -37,8 +36,7 @@ async def download_file(
37
36
  on_response: Callable[[httpx.Response], None] | None = None,
38
37
  params: QueryParamTypes | None = None,
39
38
  headers: dict[str, str] | None = None,
40
- ):
41
- ...
39
+ ): ...
42
40
 
43
41
 
44
42
  async def download_file(
@@ -33,8 +33,7 @@ def init_logging(
33
33
  version: str,
34
34
  *,
35
35
  stream_handler: logging.StreamHandler | None = None,
36
- ) -> tuple[CustomJsonFormatter, logging.StreamHandler]:
37
- ...
36
+ ) -> tuple[CustomJsonFormatter, logging.StreamHandler]: ...
38
37
 
39
38
 
40
39
  @overload
@@ -44,8 +43,7 @@ def init_logging(
44
43
  version: str,
45
44
  *,
46
45
  stream_handler: logging.StreamHandler | None = None,
47
- ) -> tuple[logging.Formatter, logging.StreamHandler]:
48
- ...
46
+ ) -> tuple[logging.Formatter, logging.StreamHandler]: ...
49
47
 
50
48
 
51
49
  def init_logging(
@@ -321,8 +321,7 @@ async def insert_many(
321
321
  @overload
322
322
  async def insert_returning(
323
323
  conn: _Connection, table: str, item: dict, returning: str, on_conflict: OnConflict | None = None, fill: bool = False
324
- ) -> Any | None:
325
- ...
324
+ ) -> Any | None: ...
326
325
 
327
326
 
328
327
  @overload
@@ -333,8 +332,7 @@ async def insert_returning(
333
332
  returning: list[str],
334
333
  on_conflict: OnConflict | None = None,
335
334
  fill: bool = False,
336
- ) -> asyncpg.Record | None:
337
- ...
335
+ ) -> asyncpg.Record | None: ...
338
336
 
339
337
 
340
338
  async def insert_returning(
@@ -388,8 +386,7 @@ async def update_returning(
388
386
  where: str | None = None,
389
387
  keys: list[str] | None = None,
390
388
  start_from: int | None = None,
391
- ) -> Any | None:
392
- ...
389
+ ) -> Any | None: ...
393
390
 
394
391
 
395
392
  @overload
@@ -403,8 +400,7 @@ async def update_returning(
403
400
  where: str | None = None,
404
401
  keys: list[str] | None = None,
405
402
  start_from: int | None = None,
406
- ) -> asyncpg.Record | None:
407
- ...
403
+ ) -> asyncpg.Record | None: ...
408
404
 
409
405
 
410
406
  @overload
@@ -418,8 +414,7 @@ async def update_returning(
418
414
  where: str | None = None,
419
415
  keys: list[str] | None = None,
420
416
  start_from: int | None = None,
421
- ) -> asyncpg.Record | None:
422
- ...
417
+ ) -> asyncpg.Record | None: ...
423
418
 
424
419
 
425
420
  async def update_returning(
@@ -1,5 +1,5 @@
1
1
  from pathlib import Path
2
- from typing import Iterable, Any, overload, Literal, cast
2
+ from typing import Iterable, Any, overload, Literal, cast, Optional
3
3
 
4
4
  from typing_extensions import LiteralString
5
5
 
@@ -32,18 +32,15 @@ def fetch_count(engine: Connection, table: str, *args, where: str | None = None)
32
32
 
33
33
 
34
34
  @overload
35
- def fetch_one(engine: Connection, query: Query, *args, required: Literal[False]) -> dict | None:
36
- ...
35
+ def fetch_one(engine: Connection, query: Query, *args, required: Literal[False]) -> dict | None: ...
37
36
 
38
37
 
39
38
  @overload
40
- def fetch_one(engine: Connection, query: Query, *args, required: Literal[True]) -> dict:
41
- ...
39
+ def fetch_one(engine: Connection, query: Query, *args, required: Literal[True]) -> dict: ...
42
40
 
43
41
 
44
42
  @overload
45
- def fetch_one(engine: Connection, query: Query, *args) -> dict | None:
46
- ...
43
+ def fetch_one(engine: Connection, query: Query, *args) -> dict | None: ...
47
44
 
48
45
 
49
46
  def fetch_one(engine: Connection, query: Query, *args, required: bool = False) -> dict | None:
@@ -121,7 +118,7 @@ def insert_csv(
121
118
  schema: LiteralString,
122
119
  table: LiteralString,
123
120
  csv_path: Path,
124
- query: Query | None = None,
121
+ query: Optional[Query] = None,
125
122
  *,
126
123
  exclude_columns: Iterable[str] | None = None,
127
124
  delimiter: LiteralString = ",",
@@ -10,6 +10,8 @@ except ImportError:
10
10
  def download_bucket(minio: Minio, bucket_name: str, output_dir: Path) -> list[Path]:
11
11
  files = []
12
12
  for obj in minio.list_objects(bucket_name, recursive=True):
13
+ if obj.object_name is None:
14
+ raise ValueError("object_name is empty")
13
15
  data = minio.get_object(bucket_name, obj.object_name)
14
16
  _file = output_dir / obj.object_name
15
17
  _file.parent.mkdir(exist_ok=True, parents=True)
@@ -22,7 +24,11 @@ def download_bucket(minio: Minio, bucket_name: str, output_dir: Path) -> list[Pa
22
24
 
23
25
 
24
26
  def bucket_rm(minio: Minio, bucket_name: str):
25
- names = [DeleteObject(x.object_name) for x in minio.list_objects(bucket_name, recursive=True)]
27
+ names = [
28
+ DeleteObject(x.object_name)
29
+ for x in minio.list_objects(bucket_name, recursive=True)
30
+ if x.object_name is not None
31
+ ]
26
32
  errors = minio.remove_objects(bucket_name, names)
27
33
  errors = list(errors)
28
34
  if errors:
@@ -31,4 +37,4 @@ def bucket_rm(minio: Minio, bucket_name: str):
31
37
 
32
38
 
33
39
  def upload_object(minio: Minio, bucket_name: str, object_name: str, path: Path):
34
- minio.fput_object(bucket_name, object_name, path.absolute())
40
+ minio.fput_object(bucket_name, object_name, str(path.absolute()))
@@ -1,6 +1,5 @@
1
1
  import pprint
2
2
  from typing import Iterable
3
- import warnings
4
3
 
5
4
  try:
6
5
  import deepdiff
@@ -8,11 +7,6 @@ except ImportError:
8
7
  raise ImportError('Please install deepdiff or tracktolib with "tests" to use this module')
9
8
 
10
9
 
11
- def get_uuid(i: int = 0):
12
- warnings.warn("Please use uuid.UUID(int=i) instead", DeprecationWarning)
13
- return f"00000000-0000-0000-0000-000000{i:06}"
14
-
15
-
16
10
  def assert_equals(d1: dict | Iterable, d2: dict | Iterable, *, ignore_order: bool = False):
17
11
  diff = deepdiff.DeepDiff(d1, d2, ignore_order=ignore_order)
18
12
  assert not diff, pprint.pprint(diff)
@@ -58,18 +58,15 @@ def import_module(path: Path):
58
58
 
59
59
 
60
60
  @overload
61
- def get_chunks(it: Iterable[T], size: int, *, as_list: Literal[False]) -> Iterator[Iterable[T]]:
62
- ...
61
+ def get_chunks(it: Iterable[T], size: int, *, as_list: Literal[False]) -> Iterator[Iterable[T]]: ...
63
62
 
64
63
 
65
64
  @overload
66
- def get_chunks(it: Iterable[T], size: int, *, as_list: Literal[True]) -> Iterator[list[T]]:
67
- ...
65
+ def get_chunks(it: Iterable[T], size: int, *, as_list: Literal[True]) -> Iterator[list[T]]: ...
68
66
 
69
67
 
70
68
  @overload
71
- def get_chunks(it: Iterable[T], size: int) -> Iterator[list[T]]:
72
- ...
69
+ def get_chunks(it: Iterable[T], size: int) -> Iterator[list[T]]: ...
73
70
 
74
71
 
75
72
  def get_chunks(it: Iterable[T], size: int, *, as_list: bool = True) -> Iterator[Iterable[T]]:
@@ -125,13 +122,11 @@ def to_camel_case(string: str) -> str:
125
122
 
126
123
 
127
124
  @overload
128
- def dict_to_camel(d: dict) -> dict:
129
- ...
125
+ def dict_to_camel(d: dict) -> dict: ...
130
126
 
131
127
 
132
128
  @overload
133
- def dict_to_camel(d: list[dict]) -> list[dict]:
134
- ...
129
+ def dict_to_camel(d: list[dict]) -> list[dict]: ...
135
130
 
136
131
 
137
132
  def dict_to_camel(d: dict | list):
@@ -152,13 +147,11 @@ def dict_to_camel(d: dict | list):
152
147
 
153
148
 
154
149
  @overload
155
- def rm_keys(data: dict, keys: list[str]) -> dict:
156
- ...
150
+ def rm_keys(data: dict, keys: list[str]) -> dict: ...
157
151
 
158
152
 
159
153
  @overload
160
- def rm_keys(data: list[dict], keys: list[str]) -> list[dict]:
161
- ...
154
+ def rm_keys(data: list[dict], keys: list[str]) -> list[dict]: ...
162
155
 
163
156
 
164
157
  def rm_keys(data: dict | list[dict], keys: list[str]):
@@ -1,38 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- from setuptools import setup
3
-
4
- packages = \
5
- ['tracktolib', 'tracktolib.pg', 'tracktolib.s3']
6
-
7
- package_data = \
8
- {'': ['*']}
9
-
10
- extras_require = \
11
- {':extra == "pg"': ['asyncpg>=0.27.0'],
12
- 'api': ['fastapi>=0.103.2', 'pydantic>=2'],
13
- 'http': ['httpx>=0.25.0'],
14
- 'logs': ['python-json-logger>=2.0.4'],
15
- 'pg': ['rich>=13.6.0'],
16
- 'pg-sync': ['psycopg>=3.1.12'],
17
- 's3': ['aiobotocore>=2.9.0'],
18
- 's3-minio': ['minio>=7.2.0'],
19
- 'tests': ['deepdiff>=6.6.0']}
20
-
21
- setup_kwargs = {
22
- 'name': 'tracktolib',
23
- 'version': '0.48.0',
24
- 'description': 'Utility library for python',
25
- 'long_description': "# Tracktolib\n\n[![Python versions](https://img.shields.io/pypi/pyversions/tracktolib)](https://pypi.python.org/pypi/tracktolib)\n[![Latest PyPI version](https://img.shields.io/pypi/v/tracktolib?logo=pypi)](https://pypi.python.org/pypi/tracktolib)\n[![CircleCI](https://circleci.com/gh/Tracktor/tracktolib/tree/master.svg?style=shield)](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
- 'author': 'Julien Brayere',
27
- 'author_email': 'julien.brayere@tracktor.fr',
28
- 'maintainer': 'None',
29
- 'maintainer_email': 'None',
30
- 'url': 'https://github.com/tracktor/tracktolib',
31
- 'packages': packages,
32
- 'package_data': package_data,
33
- 'extras_require': extras_require,
34
- 'python_requires': '>=3.10,<4.0',
35
- }
36
-
37
-
38
- setup(**setup_kwargs)
File without changes