cloud-files 6.4.0__tar.gz → 6.4.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.
- {cloud_files-6.4.0 → cloud_files-6.4.2}/ChangeLog +13 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/PKG-INFO +1 -1
- {cloud_files-6.4.0 → cloud_files-6.4.2}/automated_test.py +22 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/cloud_files.egg-info/PKG-INFO +1 -1
- cloud_files-6.4.2/cloud_files.egg-info/pbr.json +1 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/cloudfiles.py +1 -1
- {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/connectionpools.py +10 -2
- {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/interfaces.py +2 -1
- {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/scheduler.py +4 -6
- {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/threaded_queue.py +0 -2
- {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles_cli/cloudfiles_cli.py +10 -4
- cloud_files-6.4.0/cloud_files.egg-info/pbr.json +0 -1
- {cloud_files-6.4.0 → cloud_files-6.4.2}/.github/workflows/test-suite.yml +0 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/AUTHORS +0 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/LICENSE +0 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/MANIFEST.in +0 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/README.md +0 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/cloud_files.egg-info/SOURCES.txt +0 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/cloud_files.egg-info/dependency_links.txt +0 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/cloud_files.egg-info/entry_points.txt +0 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/cloud_files.egg-info/not-zip-safe +0 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/cloud_files.egg-info/requires.txt +0 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/cloud_files.egg-info/top_level.txt +0 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/__init__.py +0 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/compression.py +0 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/exceptions.py +0 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/gcs.py +0 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/lib.py +0 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/monitoring.py +0 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/paths.py +0 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/resumable_tools.py +0 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/secrets.py +0 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/typing.py +0 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles_cli/LICENSE +0 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles_cli/__init__.py +0 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles_cli/listing_db.py +0 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/requirements.txt +0 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/setup.cfg +0 -0
- {cloud_files-6.4.0 → cloud_files-6.4.2}/setup.py +0 -0
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
CHANGES
|
|
2
2
|
=======
|
|
3
3
|
|
|
4
|
+
6.4.2
|
|
5
|
+
-----
|
|
6
|
+
|
|
7
|
+
* fix: Dell ECS does not implement the correct checksum behavior for multipart files
|
|
8
|
+
* fix: also consider crc32c
|
|
9
|
+
* docs: mention comparison of byte sizes
|
|
10
|
+
* fix: use same locking filename for reading and writing (#132)
|
|
11
|
+
|
|
12
|
+
6.4.1
|
|
13
|
+
-----
|
|
14
|
+
|
|
15
|
+
* refactor: control default threads from CloudFiles not multiple globals
|
|
16
|
+
|
|
4
17
|
6.4.0
|
|
5
18
|
-----
|
|
6
19
|
|
|
@@ -146,6 +146,28 @@ def test_read_write_py_objects_mem():
|
|
|
146
146
|
|
|
147
147
|
cf.delete(["my_set", "my_set2"])
|
|
148
148
|
|
|
149
|
+
def test_reader_and_writer_share_a_lock():
|
|
150
|
+
import os, tempfile
|
|
151
|
+
import cloudfiles.interfaces as cfi
|
|
152
|
+
from cloudfiles import CloudFiles
|
|
153
|
+
|
|
154
|
+
seen = []
|
|
155
|
+
real = cfi.fasteners.InterProcessReaderWriterLock
|
|
156
|
+
|
|
157
|
+
class Recording(real):
|
|
158
|
+
def __init__(self, path, *a, **k):
|
|
159
|
+
seen.append(os.path.basename(path))
|
|
160
|
+
super().__init__(path, *a, **k)
|
|
161
|
+
|
|
162
|
+
cfi.fasteners.InterProcessReaderWriterLock = Recording
|
|
163
|
+
try:
|
|
164
|
+
cf = CloudFiles("file://" + tempfile.mkdtemp(), locking=True)
|
|
165
|
+
cf.put("chunk", b"data" * 100, compress="gzip")
|
|
166
|
+
cf.get("chunk")
|
|
167
|
+
assert seen[0] == seen[-1], f"write locked {seen[0]}, read locked {seen[-1]}"
|
|
168
|
+
finally:
|
|
169
|
+
cfi.fasteners.InterProcessReaderWriterLock = real
|
|
170
|
+
|
|
149
171
|
@pytest.mark.parametrize("protocol", ('mem', 'file', 's3'))#'gs'))
|
|
150
172
|
def test_get_json_order(s3, protocol):
|
|
151
173
|
from cloudfiles import CloudFiles
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"git_version": "fff3997", "is_release": true}
|
|
@@ -39,7 +39,7 @@ from .lib import (
|
|
|
39
39
|
from .monitoring import TransmissionMonitor, IOEnum
|
|
40
40
|
from .paths import ALIASES, find_common_buckets
|
|
41
41
|
from .secrets import CLOUD_FILES_DIR, CLOUD_FILES_LOCK_DIR
|
|
42
|
-
from .threaded_queue import ThreadedQueue
|
|
42
|
+
from .threaded_queue import ThreadedQueue
|
|
43
43
|
from .typing import (
|
|
44
44
|
CompressType, GetPathType, PutScalarType,
|
|
45
45
|
PutType, ParallelType, SecretsType
|
|
@@ -116,9 +116,17 @@ class S3ConnectionPool(ConnectionPool):
|
|
|
116
116
|
if endpoint is not None:
|
|
117
117
|
additional_args['endpoint_url'] = endpoint
|
|
118
118
|
|
|
119
|
-
config =
|
|
119
|
+
config = {}
|
|
120
120
|
if no_sign_request:
|
|
121
|
-
config =
|
|
121
|
+
config['signature_version'] = UNSIGNED
|
|
122
|
+
|
|
123
|
+
if endpoint is not None:
|
|
124
|
+
config['request_checksum_calculation'] = "when_required"
|
|
125
|
+
|
|
126
|
+
if len(config) == 0:
|
|
127
|
+
config = None
|
|
128
|
+
else:
|
|
129
|
+
config = Config(**config)
|
|
122
130
|
|
|
123
131
|
return boto3.client(
|
|
124
132
|
's3',
|
|
@@ -208,6 +208,7 @@ class FileInterface(StorageInterface):
|
|
|
208
208
|
storage_class=None
|
|
209
209
|
):
|
|
210
210
|
path = self.get_path_to_file(file_path)
|
|
211
|
+
lock_path = path
|
|
211
212
|
compress_ext = self.get_extension(compress)
|
|
212
213
|
_, ext = os.path.splitext(path)
|
|
213
214
|
if ext != compress_ext:
|
|
@@ -236,7 +237,7 @@ class FileInterface(StorageInterface):
|
|
|
236
237
|
with open(path, 'wb') as f:
|
|
237
238
|
f.write(content)
|
|
238
239
|
|
|
239
|
-
return self.io_with_lock(do_put_file,
|
|
240
|
+
return self.io_with_lock(do_put_file, lock_path, exclusive=True)
|
|
240
241
|
|
|
241
242
|
def _try_extensions(self, file_path:str, fn:Callable, null_return:Any):
|
|
242
243
|
global EXT_TEST_SEQUENCE
|
|
@@ -3,13 +3,11 @@ import sys
|
|
|
3
3
|
import gevent.monkey
|
|
4
4
|
from tqdm import tqdm
|
|
5
5
|
|
|
6
|
-
from .threaded_queue import ThreadedQueue
|
|
6
|
+
from .threaded_queue import ThreadedQueue
|
|
7
7
|
from .lib import totalfn
|
|
8
8
|
|
|
9
|
-
DEFAULT_THREADS = 20
|
|
10
|
-
|
|
11
9
|
def schedule_threaded_jobs(
|
|
12
|
-
fns, concurrency
|
|
10
|
+
fns, concurrency,
|
|
13
11
|
progress=None, total=None, count_return=False
|
|
14
12
|
):
|
|
15
13
|
|
|
@@ -42,7 +40,7 @@ def schedule_threaded_jobs(
|
|
|
42
40
|
return results
|
|
43
41
|
|
|
44
42
|
def schedule_green_jobs(
|
|
45
|
-
fns, concurrency
|
|
43
|
+
fns, concurrency,
|
|
46
44
|
progress=None, total=None, count_return=False
|
|
47
45
|
):
|
|
48
46
|
import gevent.pool
|
|
@@ -114,7 +112,7 @@ def schedule_single_threaded_jobs(
|
|
|
114
112
|
return results
|
|
115
113
|
|
|
116
114
|
def schedule_jobs(
|
|
117
|
-
fns, concurrency
|
|
115
|
+
fns, concurrency,
|
|
118
116
|
progress=None, total=None, green=None,
|
|
119
117
|
count_return=False
|
|
120
118
|
):
|
|
@@ -1024,9 +1024,11 @@ def populate_md5(
|
|
|
1024
1024
|
@click.option('--part-size', default=None, help="For S3, compute multipart hashes using this part size in bytes.", show_default=True)
|
|
1025
1025
|
def verify(source, target, only_matching, verbose, md5, multipart_threshold, part_size):
|
|
1026
1026
|
"""
|
|
1027
|
-
|
|
1027
|
+
Compares source and target directories to check
|
|
1028
|
+
if filenames and sizes match. Optionally it can
|
|
1029
|
+
validate if the checksums of two files or two directories
|
|
1028
1030
|
match. These tags are usually either md5 or crc32c
|
|
1029
|
-
generated strings. These are not secure hashes so they
|
|
1031
|
+
generated strings. These are not secure hashes so they
|
|
1030
1032
|
will only catch accidental changes to files, not
|
|
1031
1033
|
intentionally malicious changes.
|
|
1032
1034
|
"""
|
|
@@ -1097,16 +1099,20 @@ def verify(source, target, only_matching, verbose, md5, multipart_threshold, par
|
|
|
1097
1099
|
continue
|
|
1098
1100
|
elif not (
|
|
1099
1101
|
(
|
|
1100
|
-
(sm
|
|
1102
|
+
(sm.get("ETag", None) and tm.get("ETag", None))
|
|
1101
1103
|
and (
|
|
1102
1104
|
sm["ETag"] == tm["ETag"]
|
|
1103
1105
|
or md5_equal(sm["ETag"], tm["ETag"])
|
|
1104
1106
|
)
|
|
1105
1107
|
)
|
|
1106
1108
|
or (
|
|
1107
|
-
sm
|
|
1109
|
+
(sm.get("Content-Md5", None) and tm.get("Content-Md5", None))
|
|
1108
1110
|
and md5_equal(sm["Content-Md5"], tm["Content-Md5"])
|
|
1109
1111
|
)
|
|
1112
|
+
or (
|
|
1113
|
+
(sm.get("Content-Crc32c", None) and tm.get("Content-Crc32c", None))
|
|
1114
|
+
and sm["Content-Crc32c"] == tm["Content-Crc32c"]
|
|
1115
|
+
)
|
|
1110
1116
|
):
|
|
1111
1117
|
failed_files.append(filename)
|
|
1112
1118
|
continue
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"git_version": "f7253bf", "is_release": true}
|
|
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
|