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.
Files changed (39) hide show
  1. {cloud_files-6.4.0 → cloud_files-6.4.2}/ChangeLog +13 -0
  2. {cloud_files-6.4.0 → cloud_files-6.4.2}/PKG-INFO +1 -1
  3. {cloud_files-6.4.0 → cloud_files-6.4.2}/automated_test.py +22 -0
  4. {cloud_files-6.4.0 → cloud_files-6.4.2}/cloud_files.egg-info/PKG-INFO +1 -1
  5. cloud_files-6.4.2/cloud_files.egg-info/pbr.json +1 -0
  6. {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/cloudfiles.py +1 -1
  7. {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/connectionpools.py +10 -2
  8. {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/interfaces.py +2 -1
  9. {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/scheduler.py +4 -6
  10. {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/threaded_queue.py +0 -2
  11. {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles_cli/cloudfiles_cli.py +10 -4
  12. cloud_files-6.4.0/cloud_files.egg-info/pbr.json +0 -1
  13. {cloud_files-6.4.0 → cloud_files-6.4.2}/.github/workflows/test-suite.yml +0 -0
  14. {cloud_files-6.4.0 → cloud_files-6.4.2}/AUTHORS +0 -0
  15. {cloud_files-6.4.0 → cloud_files-6.4.2}/LICENSE +0 -0
  16. {cloud_files-6.4.0 → cloud_files-6.4.2}/MANIFEST.in +0 -0
  17. {cloud_files-6.4.0 → cloud_files-6.4.2}/README.md +0 -0
  18. {cloud_files-6.4.0 → cloud_files-6.4.2}/cloud_files.egg-info/SOURCES.txt +0 -0
  19. {cloud_files-6.4.0 → cloud_files-6.4.2}/cloud_files.egg-info/dependency_links.txt +0 -0
  20. {cloud_files-6.4.0 → cloud_files-6.4.2}/cloud_files.egg-info/entry_points.txt +0 -0
  21. {cloud_files-6.4.0 → cloud_files-6.4.2}/cloud_files.egg-info/not-zip-safe +0 -0
  22. {cloud_files-6.4.0 → cloud_files-6.4.2}/cloud_files.egg-info/requires.txt +0 -0
  23. {cloud_files-6.4.0 → cloud_files-6.4.2}/cloud_files.egg-info/top_level.txt +0 -0
  24. {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/__init__.py +0 -0
  25. {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/compression.py +0 -0
  26. {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/exceptions.py +0 -0
  27. {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/gcs.py +0 -0
  28. {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/lib.py +0 -0
  29. {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/monitoring.py +0 -0
  30. {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/paths.py +0 -0
  31. {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/resumable_tools.py +0 -0
  32. {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/secrets.py +0 -0
  33. {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles/typing.py +0 -0
  34. {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles_cli/LICENSE +0 -0
  35. {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles_cli/__init__.py +0 -0
  36. {cloud_files-6.4.0 → cloud_files-6.4.2}/cloudfiles_cli/listing_db.py +0 -0
  37. {cloud_files-6.4.0 → cloud_files-6.4.2}/requirements.txt +0 -0
  38. {cloud_files-6.4.0 → cloud_files-6.4.2}/setup.cfg +0 -0
  39. {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
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cloud-files
3
- Version: 6.4.0
3
+ Version: 6.4.2
4
4
  Summary: Fast access to cloud storage and local FS.
5
5
  Home-page: https://github.com/seung-lab/cloud-files/
6
6
  Author: William Silversmith
@@ -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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cloud-files
3
- Version: 6.4.0
3
+ Version: 6.4.2
4
4
  Summary: Fast access to cloud storage and local FS.
5
5
  Home-page: https://github.com/seung-lab/cloud-files/
6
6
  Author: William Silversmith
@@ -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, DEFAULT_THREADS
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 = None
119
+ config = {}
120
120
  if no_sign_request:
121
- config = Config(signature_version=UNSIGNED)
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, path, exclusive=True)
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, DEFAULT_THREADS
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=DEFAULT_THREADS,
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=DEFAULT_THREADS,
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=DEFAULT_THREADS,
115
+ fns, concurrency,
118
116
  progress=None, total=None, green=None,
119
117
  count_return=False
120
118
  ):
@@ -5,8 +5,6 @@ import time
5
5
 
6
6
  from tqdm import tqdm
7
7
 
8
- DEFAULT_THREADS = 20
9
-
10
8
  class ThreadedQueue(object):
11
9
  """Grant threaded task processing to any derived class."""
12
10
  def __init__(self, n_threads, queue_size=0, progress=None):
@@ -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
- Validates checksums of two files or two directories
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["ETag"] and tm["ETag"])
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["Content-Md5"] and tm["Content-Md5"]
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