python3-commons 0.6.6__tar.gz → 0.6.8__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.
- {python3_commons-0.6.6/src/python3_commons.egg-info → python3_commons-0.6.8}/PKG-INFO +1 -1
- {python3_commons-0.6.6 → python3_commons-0.6.8}/pyproject.toml +1 -2
- python3_commons-0.6.8/src/python3_commons/api_client.py +56 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/src/python3_commons/audit.py +12 -8
- {python3_commons-0.6.6 → python3_commons-0.6.8}/src/python3_commons/helpers.py +38 -18
- {python3_commons-0.6.6 → python3_commons-0.6.8}/src/python3_commons/object_storage.py +1 -1
- {python3_commons-0.6.6 → python3_commons-0.6.8}/src/python3_commons/serializers/msgspec.py +15 -1
- {python3_commons-0.6.6 → python3_commons-0.6.8/src/python3_commons.egg-info}/PKG-INFO +1 -1
- {python3_commons-0.6.6 → python3_commons-0.6.8}/tests/conftest.py +10 -2
- python3_commons-0.6.8/tests/test_msgspec.py +56 -0
- python3_commons-0.6.6/src/python3_commons/api_client.py +0 -44
- python3_commons-0.6.6/tests/test_msgspec.py +0 -33
- {python3_commons-0.6.6 → python3_commons-0.6.8}/.coveragerc +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/.github/workflows/python-publish.yaml +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/.gitignore +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/AUTHORS.rst +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/CHANGELOG.rst +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/LICENSE +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/README.md +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/README.rst +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/docs/Makefile +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/docs/_static/.gitignore +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/docs/authors.rst +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/docs/changelog.rst +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/docs/conf.py +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/docs/index.rst +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/docs/license.rst +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/requirements.txt +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/requirements_dev.txt +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/requirements_test.txt +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/setup.cfg +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/setup.py +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/src/python3_commons/__init__.py +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/src/python3_commons/conf.py +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/src/python3_commons/db.py +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/src/python3_commons/fs.py +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/src/python3_commons/logging/__init__.py +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/src/python3_commons/logging/filters.py +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/src/python3_commons/logging/formatters.py +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/src/python3_commons/serializers/__init__.py +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/src/python3_commons/serializers/json.py +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/src/python3_commons/serializers/msgpack.py +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/src/python3_commons.egg-info/SOURCES.txt +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/src/python3_commons.egg-info/dependency_links.txt +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/src/python3_commons.egg-info/requires.txt +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/src/python3_commons.egg-info/top_level.txt +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/tests/test_audit.py +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/tests/test_helpers.py +0 -0
- {python3_commons-0.6.6 → python3_commons-0.6.8}/tests/test_msgpack.py +0 -0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "python3-commons"
|
7
|
-
version = "0.6.
|
7
|
+
version = "0.6.8"
|
8
8
|
description = "Re-usable Python3 code"
|
9
9
|
authors = [
|
10
10
|
{name = "Oleg Korsak", email = "kamikaze.is.waiting.you@gmail.com"}
|
@@ -48,7 +48,6 @@ exclude = ["tests"]
|
|
48
48
|
|
49
49
|
[tool.pytest.ini_options]
|
50
50
|
addopts = [
|
51
|
-
"--cov python3_commons --cov-report term-missing",
|
52
51
|
"--verbose"
|
53
52
|
]
|
54
53
|
norecursedirs = ["dist", "build", ".tox"]
|
@@ -0,0 +1,56 @@
|
|
1
|
+
from contextlib import asynccontextmanager
|
2
|
+
from datetime import datetime, UTC
|
3
|
+
from typing import AsyncGenerator, Literal, Mapping, Sequence
|
4
|
+
|
5
|
+
from aiohttp import ClientSession
|
6
|
+
from aiohttp.web_response import Response
|
7
|
+
from pydantic import HttpUrl
|
8
|
+
|
9
|
+
from python3_commons import audit
|
10
|
+
from python3_commons.conf import s3_settings
|
11
|
+
from python3_commons.helpers import request_to_curl
|
12
|
+
|
13
|
+
|
14
|
+
@asynccontextmanager
|
15
|
+
async def request(
|
16
|
+
client: ClientSession,
|
17
|
+
base_url: HttpUrl,
|
18
|
+
uri: str,
|
19
|
+
query: Mapping | None = None,
|
20
|
+
method: Literal['get', 'post', 'put', 'patch', 'options', 'head', 'delete'] = 'get',
|
21
|
+
headers: Mapping | None = None,
|
22
|
+
json: Mapping | Sequence | str | None = None,
|
23
|
+
data: bytes | None = None,
|
24
|
+
audit_name: str | None = None
|
25
|
+
) -> AsyncGenerator[Response]:
|
26
|
+
now = datetime.now(tz=UTC)
|
27
|
+
date_path = now.strftime('%Y/%m/%d')
|
28
|
+
timestamp = now.strftime('%H%M%S_%f')
|
29
|
+
uri_path = uri[:-1] if uri.endswith('/') else uri
|
30
|
+
uri_path = uri_path[1:] if uri_path.startswith('/') else uri_path
|
31
|
+
url = f'{base_url}{uri}'
|
32
|
+
|
33
|
+
if audit_name:
|
34
|
+
curl_request = None
|
35
|
+
|
36
|
+
if method == 'get':
|
37
|
+
if query:
|
38
|
+
curl_request = request_to_curl(url, query, method, headers)
|
39
|
+
else:
|
40
|
+
curl_request = request_to_curl(url, query, method, headers, json, data)
|
41
|
+
|
42
|
+
if curl_request:
|
43
|
+
await audit.write_audit_data(
|
44
|
+
s3_settings,
|
45
|
+
f'{date_path}/{audit_name}/{uri_path}/{method}_{timestamp}_request.txt',
|
46
|
+
curl_request.encode('utf-8')
|
47
|
+
)
|
48
|
+
|
49
|
+
client_method = getattr(client, method)
|
50
|
+
|
51
|
+
if method == 'get':
|
52
|
+
async with client_method(url, params=query) as response:
|
53
|
+
yield response
|
54
|
+
else:
|
55
|
+
async with client_method(url, params=query, json=json, data=data) as response:
|
56
|
+
yield response
|
@@ -3,6 +3,7 @@ import io
|
|
3
3
|
import logging
|
4
4
|
import tarfile
|
5
5
|
from bz2 import BZ2Compressor
|
6
|
+
from collections import deque
|
6
7
|
from datetime import datetime, timedelta, UTC
|
7
8
|
from typing import Generator, Iterable
|
8
9
|
from uuid import uuid4
|
@@ -42,8 +43,7 @@ class GeneratedStream(io.BytesIO):
|
|
42
43
|
except StopIteration:
|
43
44
|
break
|
44
45
|
else:
|
45
|
-
self.write(chunk)
|
46
|
-
total_written_size += len(chunk)
|
46
|
+
total_written_size += self.write(chunk)
|
47
47
|
|
48
48
|
self.seek(0)
|
49
49
|
|
@@ -69,7 +69,7 @@ class GeneratedStream(io.BytesIO):
|
|
69
69
|
|
70
70
|
def generate_archive(objects: Iterable[tuple[str, datetime, bytes]],
|
71
71
|
chunk_size: int = 4096) -> Generator[bytes, None, None]:
|
72
|
-
buffer =
|
72
|
+
buffer = deque()
|
73
73
|
|
74
74
|
with tarfile.open(fileobj=buffer, mode='w') as archive:
|
75
75
|
for name, last_modified, content in objects:
|
@@ -79,18 +79,22 @@ def generate_archive(objects: Iterable[tuple[str, datetime, bytes]],
|
|
79
79
|
info.mtime = last_modified.timestamp()
|
80
80
|
archive.addfile(info, io.BytesIO(content))
|
81
81
|
|
82
|
-
buffer.
|
82
|
+
buffer_length = buffer.tell()
|
83
83
|
|
84
|
-
while
|
84
|
+
while buffer_length >= chunk_size:
|
85
|
+
buffer.seek(0)
|
85
86
|
chunk = buffer.read(chunk_size)
|
87
|
+
chunk_len = len(chunk)
|
86
88
|
|
87
89
|
if not chunk:
|
88
90
|
break
|
89
91
|
|
90
92
|
yield chunk
|
91
93
|
|
92
|
-
|
93
|
-
|
94
|
+
buffer.seek(0)
|
95
|
+
buffer.truncate(chunk_len)
|
96
|
+
buffer.seek(0, io.SEEK_END)
|
97
|
+
buffer_length = buffer.tell()
|
94
98
|
|
95
99
|
while True:
|
96
100
|
chunk = buffer.read(chunk_size)
|
@@ -145,7 +149,7 @@ async def archive_audit_data(root_path: str = 'audit'):
|
|
145
149
|
if objects := object_storage.get_objects(bucket_name, date_path, recursive=True):
|
146
150
|
logger.info(f'Compacting files in: {date_path}')
|
147
151
|
|
148
|
-
generator = generate_archive(objects, chunk_size=
|
152
|
+
generator = generate_archive(objects, chunk_size=900_000)
|
149
153
|
bzip2_generator = generate_bzip2(generator)
|
150
154
|
archive_stream = GeneratedStream(bzip2_generator)
|
151
155
|
|
@@ -1,10 +1,13 @@
|
|
1
|
-
import datetime
|
2
1
|
import logging
|
3
2
|
import shlex
|
4
3
|
import threading
|
5
|
-
|
4
|
+
from datetime import date, datetime, timedelta
|
6
5
|
from decimal import Decimal, ROUND_HALF_UP
|
7
|
-
from
|
6
|
+
from json import dumps
|
7
|
+
from typing import Literal, Mapping, Sequence
|
8
|
+
from urllib.parse import urlencode
|
9
|
+
|
10
|
+
from python3_commons.serializers.json import CustomJSONEncoder
|
8
11
|
|
9
12
|
logger = logging.getLogger(__name__)
|
10
13
|
|
@@ -30,23 +33,23 @@ class SingletonMeta(type):
|
|
30
33
|
return instance
|
31
34
|
|
32
35
|
|
33
|
-
def date_from_string(string: str, fmt: str = '%d.%m.%Y') ->
|
36
|
+
def date_from_string(string: str, fmt: str = '%d.%m.%Y') -> date:
|
34
37
|
try:
|
35
|
-
return datetime.
|
38
|
+
return datetime.strptime(string, fmt).date()
|
36
39
|
except ValueError:
|
37
|
-
return
|
40
|
+
return date.fromisoformat(string)
|
38
41
|
|
39
42
|
|
40
|
-
def datetime_from_string(string: str) -> datetime
|
43
|
+
def datetime_from_string(string: str) -> datetime:
|
41
44
|
try:
|
42
|
-
return datetime.
|
45
|
+
return datetime.strptime(string, '%d.%m.%Y %H:%M:%S')
|
43
46
|
except ValueError:
|
44
|
-
return datetime.
|
47
|
+
return datetime.fromisoformat(string)
|
45
48
|
|
46
49
|
|
47
50
|
def date_range(start_date, end_date):
|
48
51
|
for n in range(int((end_date - start_date).days + 1)):
|
49
|
-
yield start_date +
|
52
|
+
yield start_date + timedelta(days=n)
|
50
53
|
|
51
54
|
|
52
55
|
def tries(times):
|
@@ -72,16 +75,33 @@ def round_decimal(value: Decimal, decimal_places=2, rounding_mode=ROUND_HALF_UP)
|
|
72
75
|
return value
|
73
76
|
|
74
77
|
|
75
|
-
def request_to_curl(
|
76
|
-
|
78
|
+
def request_to_curl(
|
79
|
+
url: str,
|
80
|
+
query: Mapping | None = None,
|
81
|
+
method: Literal['get', 'post', 'put', 'patch', 'options', 'head', 'delete'] = 'get',
|
82
|
+
headers: Mapping | None = None,
|
83
|
+
json: Mapping | Sequence | str | None = None,
|
84
|
+
data: bytes | None = None
|
85
|
+
) -> str:
|
86
|
+
if query:
|
87
|
+
url = f'{url}?{urlencode(query)}'
|
88
|
+
|
89
|
+
curl_cmd = ['curl', '-i', '-X', method.upper(), shlex.quote(url)]
|
90
|
+
|
91
|
+
if headers:
|
92
|
+
for key, value in headers.items():
|
93
|
+
header_line = f'{key}: {value}'
|
94
|
+
curl_cmd.append('-H')
|
95
|
+
curl_cmd.append(shlex.quote(header_line))
|
77
96
|
|
78
|
-
|
79
|
-
header_line = f'{key}: {value}'
|
97
|
+
if json:
|
80
98
|
curl_cmd.append('-H')
|
81
|
-
curl_cmd.append(shlex.quote(
|
99
|
+
curl_cmd.append(shlex.quote('Content-Type: application/json'))
|
82
100
|
|
83
|
-
|
84
|
-
curl_cmd.append(
|
85
|
-
|
101
|
+
curl_cmd.append('-d')
|
102
|
+
curl_cmd.append(shlex.quote(dumps(json, cls=CustomJSONEncoder)))
|
103
|
+
elif data:
|
104
|
+
curl_cmd.append('-d')
|
105
|
+
curl_cmd.append(shlex.quote(data.decode('utf-8')))
|
86
106
|
|
87
107
|
return ' '.join(curl_cmd)
|
@@ -42,7 +42,7 @@ def get_absolute_path(path: str) -> str:
|
|
42
42
|
return path
|
43
43
|
|
44
44
|
|
45
|
-
def put_object(bucket_name: str, path: str, data: io.BytesIO, length: int, part_size: int = 0) -> str:
|
45
|
+
def put_object(bucket_name: str, path: str, data: io.BytesIO, length: int, part_size: int = 0) -> str | None:
|
46
46
|
if s3_client := ObjectStorage(s3_settings).get_client():
|
47
47
|
result = s3_client.put_object(bucket_name, path, data, length, part_size=part_size)
|
48
48
|
|
@@ -7,7 +7,7 @@ from datetime import datetime, date
|
|
7
7
|
from typing import Any
|
8
8
|
|
9
9
|
from msgspec import msgpack
|
10
|
-
from msgspec.msgpack import Ext
|
10
|
+
from msgspec.msgpack import encode, Ext
|
11
11
|
|
12
12
|
from python3_commons.serializers.json import CustomJSONEncoder
|
13
13
|
|
@@ -42,6 +42,20 @@ def ext_hook(code: int, data: memoryview) -> Any:
|
|
42
42
|
|
43
43
|
MSGPACK_ENCODER = msgpack.Encoder(enc_hook=enc_hook)
|
44
44
|
MSGPACK_DECODER = msgpack.Decoder(ext_hook=ext_hook)
|
45
|
+
MSGPACK_DECODER_NATIVE = msgpack.Decoder()
|
46
|
+
|
47
|
+
|
48
|
+
def serialize_msgpack_native(data) -> bytes:
|
49
|
+
return encode(data)
|
50
|
+
|
51
|
+
|
52
|
+
def deserialize_msgpack_native(data: bytes, data_type=None):
|
53
|
+
if data_type:
|
54
|
+
result = msgpack.decode(data, type=data_type)
|
55
|
+
else:
|
56
|
+
result = MSGPACK_DECODER_NATIVE.decode(data)
|
57
|
+
|
58
|
+
return result
|
45
59
|
|
46
60
|
|
47
61
|
def serialize_msgpack(data) -> bytes:
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from dataclasses import dataclass
|
2
2
|
from datetime import datetime, date
|
3
3
|
from decimal import Decimal
|
4
|
+
from uuid import UUID, uuid4
|
4
5
|
|
5
6
|
import msgspec
|
6
7
|
import pytest
|
@@ -40,6 +41,11 @@ def data_dataclass():
|
|
40
41
|
)
|
41
42
|
|
42
43
|
|
44
|
+
class SubStruc(msgspec.Struct):
|
45
|
+
uid: UUID
|
46
|
+
name: str
|
47
|
+
|
48
|
+
|
43
49
|
class TestStruct(msgspec.Struct):
|
44
50
|
a: int
|
45
51
|
b: str
|
@@ -47,17 +53,19 @@ class TestStruct(msgspec.Struct):
|
|
47
53
|
d: datetime
|
48
54
|
e: date
|
49
55
|
f: Decimal
|
56
|
+
sub: SubStruc
|
50
57
|
|
51
58
|
|
52
59
|
@pytest.fixture
|
53
|
-
def data_struct():
|
60
|
+
def data_struct() -> TestStruct:
|
54
61
|
return TestStruct(
|
55
62
|
a=1,
|
56
63
|
b='B',
|
57
64
|
c=None,
|
58
65
|
d=datetime(2023, 7, 25, 1, 2, 3),
|
59
66
|
e=date(2023, 7, 24),
|
60
|
-
f=Decimal('1.23')
|
67
|
+
f=Decimal('1.23'),
|
68
|
+
sub=SubStruc(uid=uuid4(), name='sub-struct')
|
61
69
|
)
|
62
70
|
|
63
71
|
|
@@ -0,0 +1,56 @@
|
|
1
|
+
from decimal import Decimal
|
2
|
+
|
3
|
+
from python3_commons.serializers import msgspec
|
4
|
+
|
5
|
+
|
6
|
+
def test_encode_decode_dict_to_msgpack(data_dict):
|
7
|
+
"""
|
8
|
+
enc_hook is not being called on complex types like dict
|
9
|
+
"""
|
10
|
+
expected_result = {
|
11
|
+
'A': 1,
|
12
|
+
'B': 'B',
|
13
|
+
'C': None,
|
14
|
+
'D': '2023-07-25T01:02:03',
|
15
|
+
'E': '2023-07-24',
|
16
|
+
'F': '1.23',
|
17
|
+
}
|
18
|
+
binary_data = msgspec.serialize_msgpack(data_dict)
|
19
|
+
|
20
|
+
assert msgspec.deserialize_msgpack(binary_data) == data_dict
|
21
|
+
|
22
|
+
|
23
|
+
def test_encode_decode_dataclass_to_msgpack(data_dataclass):
|
24
|
+
binary_data = msgspec.serialize_msgpack(data_dataclass)
|
25
|
+
|
26
|
+
assert msgspec.deserialize_msgpack(binary_data, data_type=data_dataclass.__class__) == data_dataclass
|
27
|
+
|
28
|
+
|
29
|
+
def test_encode_decode_struct_to_msgpack(data_struct):
|
30
|
+
binary_data = msgspec.serialize_msgpack(data_struct)
|
31
|
+
decoded_struct = msgspec.deserialize_msgpack(binary_data, data_struct.__class__)
|
32
|
+
|
33
|
+
assert decoded_struct == data_struct
|
34
|
+
|
35
|
+
|
36
|
+
def test_encode_decode_struct_to_msgpack_native(data_struct):
|
37
|
+
binary_data = msgspec.serialize_msgpack_native(data_struct)
|
38
|
+
decoded_struct = msgspec.deserialize_msgpack_native(binary_data, data_struct.__class__)
|
39
|
+
|
40
|
+
assert decoded_struct == data_struct
|
41
|
+
|
42
|
+
|
43
|
+
def test_encode_decode_decimal_to_msgpack():
|
44
|
+
value = Decimal('1.2345')
|
45
|
+
binary_data = msgspec.serialize_msgpack(value)
|
46
|
+
decoded_value = msgspec.deserialize_msgpack(binary_data, Decimal)
|
47
|
+
|
48
|
+
assert decoded_value == value
|
49
|
+
|
50
|
+
|
51
|
+
def test_encode_decode_str_to_msgpack():
|
52
|
+
value = '1.2345'
|
53
|
+
binary_data = msgspec.serialize_msgpack(value)
|
54
|
+
decoded_value = msgspec.deserialize_msgpack(binary_data)
|
55
|
+
|
56
|
+
assert decoded_value == value
|
@@ -1,44 +0,0 @@
|
|
1
|
-
from contextlib import asynccontextmanager
|
2
|
-
from datetime import datetime, UTC
|
3
|
-
from typing import Literal, Mapping
|
4
|
-
from urllib.parse import urlencode
|
5
|
-
|
6
|
-
import aiohttp
|
7
|
-
from pydantic import HttpUrl
|
8
|
-
|
9
|
-
from python3_commons import audit
|
10
|
-
from python3_commons.conf import s3_settings
|
11
|
-
from python3_commons.helpers import request_to_curl
|
12
|
-
|
13
|
-
|
14
|
-
@asynccontextmanager
|
15
|
-
async def request(
|
16
|
-
base_url: HttpUrl,
|
17
|
-
uri: str,
|
18
|
-
params: Mapping | None = None,
|
19
|
-
method: Literal['get', 'post', 'patch', 'put', 'delete'] = 'get',
|
20
|
-
audit_name: str | None = None,
|
21
|
-
):
|
22
|
-
now = datetime.now(tz=UTC)
|
23
|
-
date_path = now.strftime('%Y/%m/%d')
|
24
|
-
timestamp = now.strftime('%H%M%S_%f')
|
25
|
-
uri_path = uri[:-1] if uri.endswith('/') else uri
|
26
|
-
uri_path = uri_path[1:] if uri_path.startswith('/') else uri_path
|
27
|
-
url = f'{base_url}{uri}'
|
28
|
-
|
29
|
-
if params:
|
30
|
-
url_with_params = f'{url}?{urlencode(params)}'
|
31
|
-
|
32
|
-
if audit_name:
|
33
|
-
curl_request = request_to_curl(url_with_params, method, {}, None)
|
34
|
-
await audit.write_audit_data(
|
35
|
-
s3_settings,
|
36
|
-
f'{date_path}/{audit_name}/{uri_path}/{method}_{timestamp}_request.txt',
|
37
|
-
curl_request.encode('utf-8')
|
38
|
-
)
|
39
|
-
|
40
|
-
async with aiohttp.ClientSession() as client:
|
41
|
-
client_method = getattr(client, method)
|
42
|
-
|
43
|
-
async with client_method(url, params=params) as response:
|
44
|
-
yield response
|
@@ -1,33 +0,0 @@
|
|
1
|
-
from msgspec import Struct
|
2
|
-
|
3
|
-
from python3_commons.serializers import msgspec
|
4
|
-
|
5
|
-
|
6
|
-
class AStruct(Struct):
|
7
|
-
pass
|
8
|
-
|
9
|
-
|
10
|
-
def test_encode_decode_dict_to_msgpack(data_dict):
|
11
|
-
expected_result = {
|
12
|
-
'A': 1,
|
13
|
-
'B': 'B',
|
14
|
-
'C': None,
|
15
|
-
'D': '2023-07-25T01:02:03',
|
16
|
-
'E': '2023-07-24',
|
17
|
-
'F': '1.23',
|
18
|
-
}
|
19
|
-
binary_data = msgspec.serialize_msgpack(data_dict)
|
20
|
-
|
21
|
-
assert msgspec.deserialize_msgpack(binary_data) == expected_result
|
22
|
-
|
23
|
-
|
24
|
-
def test_encode_decode_dataclass_to_msgpack(data_dataclass):
|
25
|
-
binary_data = msgspec.serialize_msgpack(data_dataclass)
|
26
|
-
|
27
|
-
assert msgspec.deserialize_msgpack(binary_data, data_type=data_dataclass.__class__) == data_dataclass
|
28
|
-
|
29
|
-
|
30
|
-
def test_encode_decode_struct_to_msgpack(data_struct):
|
31
|
-
binary_data = msgspec.serialize_msgpack(data_struct)
|
32
|
-
|
33
|
-
assert msgspec.deserialize_msgpack(binary_data, data_type=data_struct.__class__) == data_struct
|
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
|
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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{python3_commons-0.6.6 → python3_commons-0.6.8}/src/python3_commons.egg-info/dependency_links.txt
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|