python3-commons 0.5.16__tar.gz → 0.5.18__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.
Potentially problematic release.
This version of python3-commons might be problematic. Click here for more details.
- {python3_commons-0.5.16/src/python3_commons.egg-info → python3_commons-0.5.18}/PKG-INFO +1 -1
- {python3_commons-0.5.16 → python3_commons-0.5.18}/src/python3_commons/audit.py +23 -10
- {python3_commons-0.5.16 → python3_commons-0.5.18}/src/python3_commons/helpers.py +22 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/src/python3_commons/object_storage.py +21 -23
- {python3_commons-0.5.16 → python3_commons-0.5.18}/src/python3_commons/serializers/msgspec.py +6 -2
- python3_commons-0.5.18/src/python3_commons/stream_tar.py +105 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18/src/python3_commons.egg-info}/PKG-INFO +1 -1
- {python3_commons-0.5.16 → python3_commons-0.5.18}/src/python3_commons.egg-info/SOURCES.txt +1 -0
- python3_commons-0.5.18/tests/test_audit.py +29 -0
- python3_commons-0.5.16/tests/test_audit.py +0 -10
- {python3_commons-0.5.16 → python3_commons-0.5.18}/.coveragerc +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/.github/workflows/python-publish.yaml +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/.gitignore +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/AUTHORS.rst +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/CHANGELOG.rst +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/LICENSE +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/README.md +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/README.rst +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/docs/Makefile +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/docs/_static/.gitignore +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/docs/authors.rst +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/docs/changelog.rst +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/docs/conf.py +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/docs/index.rst +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/docs/license.rst +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/pyproject.toml +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/requirements.txt +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/requirements_dev.txt +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/requirements_test.txt +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/setup.cfg +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/setup.py +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/src/python3_commons/__init__.py +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/src/python3_commons/conf.py +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/src/python3_commons/db.py +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/src/python3_commons/fs.py +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/src/python3_commons/logging/__init__.py +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/src/python3_commons/logging/filters.py +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/src/python3_commons/logging/formatter.py +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/src/python3_commons/serializers/__init__.py +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/src/python3_commons/serializers/json.py +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/src/python3_commons/serializers/msgpack.py +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/src/python3_commons.egg-info/dependency_links.txt +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/src/python3_commons.egg-info/not-zip-safe +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/src/python3_commons.egg-info/requires.txt +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/src/python3_commons.egg-info/top_level.txt +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/tests/conftest.py +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/tests/test_msgpack.py +0 -0
- {python3_commons-0.5.16 → python3_commons-0.5.18}/tests/test_msgspec.py +0 -0
|
@@ -13,7 +13,7 @@ from zeep.wsdl.definitions import AbstractOperation
|
|
|
13
13
|
|
|
14
14
|
from python3_commons import object_storage
|
|
15
15
|
from python3_commons.conf import S3Settings, s3_settings
|
|
16
|
-
from python3_commons.object_storage import
|
|
16
|
+
from python3_commons.object_storage import ObjectStorage
|
|
17
17
|
|
|
18
18
|
logger = logging.getLogger(__name__)
|
|
19
19
|
|
|
@@ -24,16 +24,27 @@ class GeneratedStream(io.BytesIO):
|
|
|
24
24
|
self.generator = generator
|
|
25
25
|
|
|
26
26
|
def read(self, size: int = -1):
|
|
27
|
-
if size
|
|
28
|
-
|
|
27
|
+
if size < 0:
|
|
28
|
+
while True:
|
|
29
|
+
try:
|
|
30
|
+
chunk = next(self.generator)
|
|
31
|
+
except StopIteration:
|
|
32
|
+
break
|
|
33
|
+
else:
|
|
34
|
+
self.write(chunk)
|
|
35
|
+
else:
|
|
36
|
+
total_written_size = 0
|
|
29
37
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
38
|
+
while total_written_size < size:
|
|
39
|
+
try:
|
|
40
|
+
chunk = next(self.generator)
|
|
41
|
+
except StopIteration:
|
|
42
|
+
break
|
|
43
|
+
else:
|
|
44
|
+
self.write(chunk)
|
|
45
|
+
total_written_size += len(chunk)
|
|
35
46
|
|
|
36
|
-
|
|
47
|
+
self.seek(0)
|
|
37
48
|
|
|
38
49
|
if chunk := super().read(size):
|
|
39
50
|
pos = self.tell()
|
|
@@ -44,6 +55,8 @@ class GeneratedStream(io.BytesIO):
|
|
|
44
55
|
if unread_data_size > 0:
|
|
45
56
|
buf[:unread_data_size] = buf[pos:pos+unread_data_size]
|
|
46
57
|
|
|
58
|
+
del buf
|
|
59
|
+
|
|
47
60
|
self.seek(0)
|
|
48
61
|
self.truncate(unread_data_size)
|
|
49
62
|
|
|
@@ -82,7 +95,7 @@ def generate_archive(objects: Iterable[tuple[str, datetime, bytes]],
|
|
|
82
95
|
def write_audit_data_sync(settings: S3Settings, key: str, data: bytes):
|
|
83
96
|
if settings.s3_secret_access_key:
|
|
84
97
|
try:
|
|
85
|
-
client =
|
|
98
|
+
client = ObjectStorage(settings).get_client()
|
|
86
99
|
absolute_path = object_storage.get_absolute_path(f'audit/{key}')
|
|
87
100
|
|
|
88
101
|
client.put_object(settings.s3_bucket, absolute_path, io.BytesIO(data), len(data))
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import datetime
|
|
2
2
|
import logging
|
|
3
3
|
import shlex
|
|
4
|
+
import threading
|
|
4
5
|
|
|
5
6
|
from decimal import Decimal, ROUND_HALF_UP
|
|
6
7
|
from typing import Mapping
|
|
@@ -8,6 +9,27 @@ from typing import Mapping
|
|
|
8
9
|
logger = logging.getLogger(__name__)
|
|
9
10
|
|
|
10
11
|
|
|
12
|
+
class SingletonMeta(type):
|
|
13
|
+
"""
|
|
14
|
+
A metaclass that creates a Singleton base class when called.
|
|
15
|
+
"""
|
|
16
|
+
_instances = {}
|
|
17
|
+
_lock = threading.Lock()
|
|
18
|
+
|
|
19
|
+
def __call__(cls, *args, **kwargs):
|
|
20
|
+
try:
|
|
21
|
+
return cls._instances[cls]
|
|
22
|
+
except KeyError:
|
|
23
|
+
with cls._lock:
|
|
24
|
+
try:
|
|
25
|
+
return cls._instances[cls]
|
|
26
|
+
except KeyError:
|
|
27
|
+
instance = super(SingletonMeta, cls).__call__(*args, **kwargs)
|
|
28
|
+
cls._instances[cls] = instance
|
|
29
|
+
|
|
30
|
+
return instance
|
|
31
|
+
|
|
32
|
+
|
|
11
33
|
def date_from_string(string: str, fmt: str = '%d.%m.%Y') -> datetime.date:
|
|
12
34
|
try:
|
|
13
35
|
return datetime.datetime.strptime(string, fmt).date()
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import io
|
|
2
2
|
import logging
|
|
3
|
+
from contextlib import contextmanager
|
|
3
4
|
from datetime import datetime
|
|
4
5
|
from typing import Generator, Iterable
|
|
5
6
|
|
|
@@ -8,16 +9,17 @@ from minio.datatypes import Object
|
|
|
8
9
|
from minio.deleteobjects import DeleteObject, DeleteError
|
|
9
10
|
|
|
10
11
|
from python3_commons.conf import s3_settings, S3Settings
|
|
12
|
+
from python3_commons.helpers import SingletonMeta
|
|
11
13
|
|
|
12
14
|
logger = logging.getLogger(__name__)
|
|
13
|
-
__CLIENT = None
|
|
14
15
|
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
class ObjectStorage(metaclass=SingletonMeta):
|
|
18
|
+
def __init__(self, settings: S3Settings):
|
|
19
|
+
if not s3_settings.s3_endpoint_url:
|
|
20
|
+
raise ValueError('s3_settings.s3_endpoint_url must be set')
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
__CLIENT = Minio(
|
|
22
|
+
self._client = Minio(
|
|
21
23
|
settings.s3_endpoint_url,
|
|
22
24
|
region=settings.s3_region_name,
|
|
23
25
|
access_key=settings.s3_access_key_id.get_secret_value(),
|
|
@@ -26,7 +28,8 @@ def get_s3_client(settings: S3Settings) -> Minio:
|
|
|
26
28
|
cert_check=settings.s3_cert_verify
|
|
27
29
|
)
|
|
28
30
|
|
|
29
|
-
|
|
31
|
+
def get_client(self) -> Minio:
|
|
32
|
+
return self._client
|
|
30
33
|
|
|
31
34
|
|
|
32
35
|
def get_absolute_path(path: str) -> str:
|
|
@@ -40,9 +43,7 @@ def get_absolute_path(path: str) -> str:
|
|
|
40
43
|
|
|
41
44
|
|
|
42
45
|
def put_object(bucket_name: str, path: str, data: io.BytesIO, length: int, part_size: int = 0) -> str:
|
|
43
|
-
s3_client
|
|
44
|
-
|
|
45
|
-
if s3_client:
|
|
46
|
+
if s3_client := ObjectStorage(s3_settings).get_client():
|
|
46
47
|
result = s3_client.put_object(bucket_name, path, data, length, part_size=part_size)
|
|
47
48
|
|
|
48
49
|
logger.debug(f'Stored object into object storage: {bucket_name}:{path}')
|
|
@@ -52,10 +53,9 @@ def put_object(bucket_name: str, path: str, data: io.BytesIO, length: int, part_
|
|
|
52
53
|
logger.warning(f'No S3 client available, skipping object put')
|
|
53
54
|
|
|
54
55
|
|
|
56
|
+
@contextmanager
|
|
55
57
|
def get_object_stream(bucket_name: str, path: str):
|
|
56
|
-
s3_client
|
|
57
|
-
|
|
58
|
-
if s3_client:
|
|
58
|
+
if s3_client := ObjectStorage(s3_settings).get_client():
|
|
59
59
|
logger.debug(f'Getting object from object storage: {bucket_name}:{path}')
|
|
60
60
|
|
|
61
61
|
try:
|
|
@@ -65,19 +65,17 @@ def get_object_stream(bucket_name: str, path: str):
|
|
|
65
65
|
|
|
66
66
|
raise
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
yield response
|
|
69
|
+
|
|
70
|
+
response.close()
|
|
71
|
+
response.release_conn()
|
|
69
72
|
else:
|
|
70
73
|
logger.warning(f'No S3 client available, skipping object put')
|
|
71
74
|
|
|
72
75
|
|
|
73
76
|
def get_object(bucket_name: str, path: str) -> bytes:
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
try:
|
|
77
|
-
body = response.read()
|
|
78
|
-
finally:
|
|
79
|
-
response.close()
|
|
80
|
-
response.release_conn()
|
|
77
|
+
with get_object_stream(bucket_name, path) as stream:
|
|
78
|
+
body = stream.read()
|
|
81
79
|
|
|
82
80
|
logger.debug(f'Loaded object from object storage: {bucket_name}:{path}')
|
|
83
81
|
|
|
@@ -85,7 +83,7 @@ def get_object(bucket_name: str, path: str) -> bytes:
|
|
|
85
83
|
|
|
86
84
|
|
|
87
85
|
def list_objects(bucket_name: str, prefix: str, recursive: bool = True) -> Generator[Object, None, None]:
|
|
88
|
-
s3_client =
|
|
86
|
+
s3_client = ObjectStorage(s3_settings).get_client()
|
|
89
87
|
|
|
90
88
|
yield from s3_client.list_objects(bucket_name, prefix=prefix, recursive=recursive)
|
|
91
89
|
|
|
@@ -104,13 +102,13 @@ def get_objects(bucket_name: str, path: str,
|
|
|
104
102
|
|
|
105
103
|
|
|
106
104
|
def remove_object(bucket_name: str, object_name: str):
|
|
107
|
-
s3_client =
|
|
105
|
+
s3_client = ObjectStorage(s3_settings).get_client()
|
|
108
106
|
s3_client.remove_object(bucket_name, object_name)
|
|
109
107
|
|
|
110
108
|
|
|
111
109
|
def remove_objects(bucket_name: str, prefix: str = None,
|
|
112
110
|
object_names: Iterable[str] = None) -> Iterable[DeleteError] | None:
|
|
113
|
-
s3_client =
|
|
111
|
+
s3_client = ObjectStorage(s3_settings).get_client()
|
|
114
112
|
|
|
115
113
|
if prefix:
|
|
116
114
|
delete_object_list = map(
|
{python3_commons-0.5.16 → python3_commons-0.5.18}/src/python3_commons/serializers/msgspec.py
RENAMED
|
@@ -40,8 +40,12 @@ def ext_hook(code: int, data: memoryview) -> Any:
|
|
|
40
40
|
raise NotImplementedError(f'Extension type code {code} is not supported')
|
|
41
41
|
|
|
42
42
|
|
|
43
|
+
MSGPACK_ENCODER = msgpack.Encoder(enc_hook=enc_hook)
|
|
44
|
+
MSGPACK_DECODER = msgpack.Decoder(ext_hook=ext_hook)
|
|
45
|
+
|
|
46
|
+
|
|
43
47
|
def serialize_msgpack(data) -> bytes:
|
|
44
|
-
result =
|
|
48
|
+
result = MSGPACK_ENCODER.encode(data)
|
|
45
49
|
|
|
46
50
|
return result
|
|
47
51
|
|
|
@@ -50,6 +54,6 @@ def deserialize_msgpack(data: bytes, data_type=None):
|
|
|
50
54
|
if data_type:
|
|
51
55
|
result = msgpack.decode(data, type=data_type)
|
|
52
56
|
else:
|
|
53
|
-
result =
|
|
57
|
+
result = MSGPACK_DECODER.decode(data)
|
|
54
58
|
|
|
55
59
|
return result
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
import tarfile
|
|
5
|
+
from io import BytesIO
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
BLOCK_SIZE = 4096
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class FileStream(object):
|
|
13
|
+
def __init__(self):
|
|
14
|
+
self.buffer = BytesIO()
|
|
15
|
+
self.offset = 0
|
|
16
|
+
|
|
17
|
+
def write(self, chunk):
|
|
18
|
+
self.buffer.write(chunk)
|
|
19
|
+
self.offset += len(chunk)
|
|
20
|
+
|
|
21
|
+
def tell(self):
|
|
22
|
+
return self.offset
|
|
23
|
+
|
|
24
|
+
def close(self):
|
|
25
|
+
self.buffer.close()
|
|
26
|
+
|
|
27
|
+
def pop(self):
|
|
28
|
+
value = self.buffer.getvalue()
|
|
29
|
+
self.buffer.seek(0)
|
|
30
|
+
self.buffer.truncate()
|
|
31
|
+
|
|
32
|
+
return value
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def stream_build_tar(in_filename, streaming_fp):
|
|
36
|
+
tar = tarfile.TarFile.open('test.tar.gz', 'w|gz', streaming_fp)
|
|
37
|
+
|
|
38
|
+
stat = os.stat(in_filename)
|
|
39
|
+
|
|
40
|
+
tar_info = tarfile.TarInfo(in_filename)
|
|
41
|
+
|
|
42
|
+
# Note that you can get this information from the storage backend,
|
|
43
|
+
# but it's valid for either to raise a NotImplementedError, so it's
|
|
44
|
+
# important to check.
|
|
45
|
+
#
|
|
46
|
+
# Things like the mode or ownership won't be available.
|
|
47
|
+
tar_info.mtime = stat.st_mtime
|
|
48
|
+
tar_info.size = stat.st_size
|
|
49
|
+
|
|
50
|
+
# Note that we don't pass a fileobj, so we don't write any data
|
|
51
|
+
# through addfile. We'll do this ourselves.
|
|
52
|
+
tar.addfile(tar_info)
|
|
53
|
+
|
|
54
|
+
yield
|
|
55
|
+
|
|
56
|
+
with open(in_filename, 'rb') as in_fp:
|
|
57
|
+
total_size = 0
|
|
58
|
+
|
|
59
|
+
while True:
|
|
60
|
+
s = in_fp.read(BLOCK_SIZE)
|
|
61
|
+
|
|
62
|
+
if len(s) > 0:
|
|
63
|
+
tar.fileobj.write(s)
|
|
64
|
+
|
|
65
|
+
yield
|
|
66
|
+
|
|
67
|
+
if len(s) < BLOCK_SIZE:
|
|
68
|
+
blocks, remainder = divmod(tar_info.size, tarfile.BLOCKSIZE)
|
|
69
|
+
|
|
70
|
+
if remainder > 0:
|
|
71
|
+
tar.fileobj.write(tarfile.NUL *
|
|
72
|
+
(tarfile.BLOCKSIZE - remainder))
|
|
73
|
+
|
|
74
|
+
yield
|
|
75
|
+
|
|
76
|
+
blocks += 1
|
|
77
|
+
|
|
78
|
+
tar.offset += blocks * tarfile.BLOCKSIZE
|
|
79
|
+
break
|
|
80
|
+
|
|
81
|
+
tar.close()
|
|
82
|
+
|
|
83
|
+
yield
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def main():
|
|
87
|
+
if len(sys.argv) != 3:
|
|
88
|
+
print('Usage: %s in_filename out_filename' % sys.argv[0])
|
|
89
|
+
sys.exit(1)
|
|
90
|
+
|
|
91
|
+
in_filename = sys.argv[1]
|
|
92
|
+
out_filename = sys.argv[2]
|
|
93
|
+
|
|
94
|
+
streaming_fp = FileStream()
|
|
95
|
+
|
|
96
|
+
with open(out_filename, 'wb') as out_fp:
|
|
97
|
+
for i in stream_build_tar(in_filename, streaming_fp):
|
|
98
|
+
s = streaming_fp.pop()
|
|
99
|
+
|
|
100
|
+
if len(s) > 0:
|
|
101
|
+
print('Writing %d bytes...' % len(s))
|
|
102
|
+
out_fp.write(s)
|
|
103
|
+
out_fp.flush()
|
|
104
|
+
|
|
105
|
+
print('Wrote tar file to %s' % out_filename)
|
|
@@ -26,6 +26,7 @@ src/python3_commons/db.py
|
|
|
26
26
|
src/python3_commons/fs.py
|
|
27
27
|
src/python3_commons/helpers.py
|
|
28
28
|
src/python3_commons/object_storage.py
|
|
29
|
+
src/python3_commons/stream_tar.py
|
|
29
30
|
src/python3_commons.egg-info/PKG-INFO
|
|
30
31
|
src/python3_commons.egg-info/SOURCES.txt
|
|
31
32
|
src/python3_commons.egg-info/dependency_links.txt
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from io import BytesIO
|
|
2
|
+
|
|
3
|
+
from python3_commons.audit import GeneratedStream, generate_archive
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_generated_stream(s3_file_objects):
|
|
7
|
+
expected_data = b''
|
|
8
|
+
generator = generate_archive(s3_file_objects, chunk_size=5 * 1024 * 1024)
|
|
9
|
+
archive_stream = GeneratedStream(generator)
|
|
10
|
+
archived_data = archive_stream.read()
|
|
11
|
+
|
|
12
|
+
with open('/tmp/test.tar', 'wb') as f:
|
|
13
|
+
f.write(archived_data)
|
|
14
|
+
|
|
15
|
+
assert archived_data == expected_data
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_generated_stream_by_chunks(s3_file_objects):
|
|
19
|
+
expected_data = b''
|
|
20
|
+
generator = generate_archive(s3_file_objects, chunk_size=2)
|
|
21
|
+
archive_stream = GeneratedStream(generator)
|
|
22
|
+
archived_data = BytesIO()
|
|
23
|
+
|
|
24
|
+
with open('/tmp/test_chunked.tar', 'wb') as f:
|
|
25
|
+
while chunk := archive_stream.read(2):
|
|
26
|
+
f.write(chunk)
|
|
27
|
+
archived_data.write(chunk)
|
|
28
|
+
|
|
29
|
+
assert archived_data.getvalue() == expected_data
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
from python3_commons.audit import GeneratedStream, generate_archive
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
def test_generated_stream(s3_file_objects):
|
|
5
|
-
expected_data = b''
|
|
6
|
-
generator = generate_archive(s3_file_objects, chunk_size=5 * 1024 * 1024)
|
|
7
|
-
archive_stream = GeneratedStream(generator)
|
|
8
|
-
archived_data = archive_stream.read()
|
|
9
|
-
|
|
10
|
-
assert archived_data == expected_data
|
|
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.5.16 → python3_commons-0.5.18}/src/python3_commons/serializers/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{python3_commons-0.5.16 → python3_commons-0.5.18}/src/python3_commons/serializers/msgpack.py
RENAMED
|
File without changes
|
{python3_commons-0.5.16 → python3_commons-0.5.18}/src/python3_commons.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python3_commons-0.5.16 → python3_commons-0.5.18}/src/python3_commons.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|