google-cloud-storage 2.18.0__tar.gz → 2.18.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 (72) hide show
  1. {google_cloud_storage-2.18.0/google_cloud_storage.egg-info → google_cloud_storage-2.18.2}/PKG-INFO +2 -2
  2. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/google/cloud/storage/transfer_manager.py +2 -1
  3. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/google/cloud/storage/version.py +1 -1
  4. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2/google_cloud_storage.egg-info}/PKG-INFO +2 -2
  5. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/google_cloud_storage.egg-info/requires.txt +1 -1
  6. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/setup.py +1 -1
  7. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/conformance/test_conformance.py +13 -0
  8. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/system/test_transfer_manager.py +57 -0
  9. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/unit/test_transfer_manager.py +51 -0
  10. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/LICENSE +0 -0
  11. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/MANIFEST.in +0 -0
  12. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/README.rst +0 -0
  13. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/google/cloud/storage/__init__.py +0 -0
  14. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/google/cloud/storage/_helpers.py +0 -0
  15. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/google/cloud/storage/_http.py +0 -0
  16. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/google/cloud/storage/_opentelemetry_tracing.py +0 -0
  17. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/google/cloud/storage/_signing.py +0 -0
  18. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/google/cloud/storage/acl.py +0 -0
  19. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/google/cloud/storage/batch.py +0 -0
  20. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/google/cloud/storage/blob.py +0 -0
  21. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/google/cloud/storage/bucket.py +0 -0
  22. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/google/cloud/storage/client.py +0 -0
  23. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/google/cloud/storage/constants.py +0 -0
  24. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/google/cloud/storage/fileio.py +0 -0
  25. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/google/cloud/storage/hmac_key.py +0 -0
  26. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/google/cloud/storage/iam.py +0 -0
  27. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/google/cloud/storage/notification.py +0 -0
  28. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/google/cloud/storage/retry.py +0 -0
  29. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/google_cloud_storage.egg-info/SOURCES.txt +0 -0
  30. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/google_cloud_storage.egg-info/dependency_links.txt +0 -0
  31. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/google_cloud_storage.egg-info/not-zip-safe +0 -0
  32. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/google_cloud_storage.egg-info/top_level.txt +0 -0
  33. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/setup.cfg +0 -0
  34. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/__init__.py +0 -0
  35. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/conformance/README.md +0 -0
  36. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/conformance/__init__.py +0 -0
  37. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/conformance/conftest.py +0 -0
  38. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/conformance/retry_strategy_test_data.json +0 -0
  39. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/data/CloudPlatform_128px_Retina.png +0 -0
  40. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/data/five-point-one-mb-file.zip +0 -0
  41. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/data/simple.txt +0 -0
  42. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/perf/README.md +0 -0
  43. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/perf/_perf_utils.py +0 -0
  44. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/perf/benchmarking.py +0 -0
  45. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/perf/profile_w1r3.py +0 -0
  46. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/system/__init__.py +0 -0
  47. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/system/_helpers.py +0 -0
  48. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/system/conftest.py +0 -0
  49. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/system/test__signing.py +0 -0
  50. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/system/test_blob.py +0 -0
  51. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/system/test_bucket.py +0 -0
  52. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/system/test_client.py +0 -0
  53. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/system/test_fileio.py +0 -0
  54. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/system/test_hmac_key_metadata.py +0 -0
  55. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/system/test_kms_integration.py +0 -0
  56. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/system/test_notification.py +0 -0
  57. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/unit/__init__.py +0 -0
  58. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/unit/test__helpers.py +0 -0
  59. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/unit/test__http.py +0 -0
  60. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/unit/test__opentelemetry_tracing.py +0 -0
  61. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/unit/test__signing.py +0 -0
  62. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/unit/test_acl.py +0 -0
  63. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/unit/test_batch.py +0 -0
  64. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/unit/test_blob.py +0 -0
  65. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/unit/test_bucket.py +0 -0
  66. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/unit/test_client.py +0 -0
  67. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/unit/test_fileio.py +0 -0
  68. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/unit/test_hmac_key.py +0 -0
  69. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/unit/test_notification.py +0 -0
  70. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/unit/test_retry.py +0 -0
  71. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/unit/url_signer_v4_test_account.json +0 -0
  72. {google_cloud_storage-2.18.0 → google_cloud_storage-2.18.2}/tests/unit/url_signer_v4_test_data.json +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: google-cloud-storage
3
- Version: 2.18.0
3
+ Version: 2.18.2
4
4
  Summary: Google Cloud Storage API client library
5
5
  Home-page: https://github.com/googleapis/python-storage
6
6
  Author: Google LLC
@@ -25,7 +25,7 @@ License-File: LICENSE
25
25
  Requires-Dist: google-auth<3.0dev,>=2.26.1
26
26
  Requires-Dist: google-api-core<3.0.0dev,>=2.15.0
27
27
  Requires-Dist: google-cloud-core<3.0dev,>=2.3.0
28
- Requires-Dist: google-resumable-media>=2.6.0
28
+ Requires-Dist: google-resumable-media>=2.7.2
29
29
  Requires-Dist: requests<3.0.0dev,>=2.18.0
30
30
  Requires-Dist: google-crc32c<2.0dev,>=1.0
31
31
  Provides-Extra: protobuf
@@ -30,6 +30,7 @@ from google.api_core import exceptions
30
30
  from google.cloud.storage import Client
31
31
  from google.cloud.storage import Blob
32
32
  from google.cloud.storage.blob import _get_host_name
33
+ from google.cloud.storage.blob import _quote
33
34
  from google.cloud.storage.constants import _DEFAULT_TIMEOUT
34
35
  from google.cloud.storage._helpers import _api_core_retry_to_resumable_media_retry
35
36
  from google.cloud.storage.retry import DEFAULT_RETRY
@@ -1083,7 +1084,7 @@ def upload_chunks_concurrently(
1083
1084
 
1084
1085
  hostname = _get_host_name(client._connection)
1085
1086
  url = "{hostname}/{bucket}/{blob}".format(
1086
- hostname=hostname, bucket=bucket.name, blob=blob.name
1087
+ hostname=hostname, bucket=bucket.name, blob=_quote(blob.name)
1087
1088
  )
1088
1089
 
1089
1090
  base_headers, object_metadata, content_type = blob._get_upload_arguments(
@@ -12,4 +12,4 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- __version__ = "2.18.0"
15
+ __version__ = "2.18.2"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: google-cloud-storage
3
- Version: 2.18.0
3
+ Version: 2.18.2
4
4
  Summary: Google Cloud Storage API client library
5
5
  Home-page: https://github.com/googleapis/python-storage
6
6
  Author: Google LLC
@@ -25,7 +25,7 @@ License-File: LICENSE
25
25
  Requires-Dist: google-auth<3.0dev,>=2.26.1
26
26
  Requires-Dist: google-api-core<3.0.0dev,>=2.15.0
27
27
  Requires-Dist: google-cloud-core<3.0dev,>=2.3.0
28
- Requires-Dist: google-resumable-media>=2.6.0
28
+ Requires-Dist: google-resumable-media>=2.7.2
29
29
  Requires-Dist: requests<3.0.0dev,>=2.18.0
30
30
  Requires-Dist: google-crc32c<2.0dev,>=1.0
31
31
  Provides-Extra: protobuf
@@ -1,7 +1,7 @@
1
1
  google-auth<3.0dev,>=2.26.1
2
2
  google-api-core<3.0.0dev,>=2.15.0
3
3
  google-cloud-core<3.0dev,>=2.3.0
4
- google-resumable-media>=2.6.0
4
+ google-resumable-media>=2.7.2
5
5
  requests<3.0.0dev,>=2.18.0
6
6
  google-crc32c<2.0dev,>=1.0
7
7
 
@@ -31,7 +31,7 @@ dependencies = [
31
31
  "google-auth >= 2.26.1, < 3.0dev",
32
32
  "google-api-core >= 2.15.0, <3.0.0dev",
33
33
  "google-cloud-core >= 2.3.0, < 3.0dev",
34
- "google-resumable-media >= 2.6.0",
34
+ "google-resumable-media >= 2.7.2",
35
35
  "requests >= 2.18.0, < 3.0.0dev",
36
36
  "google-crc32c >= 1.0, < 2.0dev",
37
37
  ]
@@ -115,6 +115,17 @@ def blob_download_to_filename_chunked(client, _preconditions, **resources):
115
115
  assert stored_contents == data
116
116
 
117
117
 
118
+ def blob_download_to_filename_range(client, _preconditions, **resources):
119
+ bucket = resources.get("bucket")
120
+ file, data = resources.get("file_data")
121
+ blob = client.bucket(bucket.name).blob(file.name)
122
+ with tempfile.NamedTemporaryFile() as temp_f:
123
+ blob.download_to_filename(temp_f.name, start=1024, end=512 * 1024)
124
+ with open(temp_f.name, "r") as file_obj:
125
+ stored_contents = file_obj.read()
126
+ assert stored_contents == data[1024 : 512 * 1024 + 1]
127
+
128
+
118
129
  def client_download_blob_to_file(client, _preconditions, **resources):
119
130
  bucket = resources.get("bucket")
120
131
  file, data = resources.get("file_data")
@@ -748,6 +759,7 @@ method_mapping = {
748
759
  client_download_blob_to_file,
749
760
  blob_download_to_filename,
750
761
  blob_download_to_filename_chunked,
762
+ blob_download_to_filename_range,
751
763
  blob_download_as_bytes,
752
764
  blob_download_as_text,
753
765
  blobreader_read,
@@ -756,6 +768,7 @@ method_mapping = {
756
768
  client_download_blob_to_file,
757
769
  blob_download_to_filename,
758
770
  blob_download_to_filename_chunked,
771
+ blob_download_to_filename_range,
759
772
  blob_download_as_bytes,
760
773
  blob_download_as_text,
761
774
  blobreader_read,
@@ -245,6 +245,8 @@ def test_upload_chunks_concurrently(shared_bucket, file_data, blobs_to_delete):
245
245
  chunk_size = 5 * 1024 * 1024 # Minimum supported by XML MPU API
246
246
  assert os.path.getsize(filename) > chunk_size # Won't make a good test otherwise
247
247
 
248
+ blobs_to_delete.append(upload_blob)
249
+
248
250
  transfer_manager.upload_chunks_concurrently(
249
251
  filename,
250
252
  upload_blob,
@@ -418,3 +420,58 @@ def test_upload_chunks_concurrently_with_kms(
418
420
  source_contents = sf.read()
419
421
  temp_contents = tmp.read()
420
422
  assert source_contents == temp_contents
423
+
424
+
425
+ def test_upload_chunks_concurrently_with_quoted_blob_names(
426
+ shared_bucket, file_data, blobs_to_delete
427
+ ):
428
+ source_file = file_data["big"]
429
+ filename = source_file["path"]
430
+ blob_name = "../example_bucket/mpu_file"
431
+ upload_blob = shared_bucket.blob(blob_name)
432
+ chunk_size = 5 * 1024 * 1024 # Minimum supported by XML MPU API
433
+ assert os.path.getsize(filename) > chunk_size # Won't make a good test otherwise
434
+
435
+ blobs_to_delete.append(upload_blob)
436
+
437
+ # If the blob name is not quoted/encoded at all, this will result in a 403.
438
+ transfer_manager.upload_chunks_concurrently(
439
+ filename, upload_blob, chunk_size=chunk_size, deadline=DEADLINE
440
+ )
441
+
442
+ with tempfile.NamedTemporaryFile() as tmp:
443
+ # If the blob name is not quoted correctly, this will result in a 404.
444
+ download_blob = shared_bucket.blob(blob_name)
445
+ download_blob.download_to_file(tmp)
446
+ tmp.seek(0)
447
+
448
+ with open(source_file["path"], "rb") as sf:
449
+ source_contents = sf.read()
450
+ temp_contents = tmp.read()
451
+ assert source_contents == temp_contents
452
+
453
+ # Test emoji names are not mangled.
454
+ blob_name = "\U0001f681" # Helicopter emoji
455
+ upload_blob = shared_bucket.blob(blob_name)
456
+ chunk_size = 5 * 1024 * 1024 # Minimum supported by XML MPU API
457
+ assert os.path.getsize(filename) > chunk_size # Won't make a good test otherwise
458
+
459
+ blobs_to_delete.append(upload_blob)
460
+
461
+ transfer_manager.upload_chunks_concurrently(
462
+ filename,
463
+ upload_blob,
464
+ chunk_size=chunk_size,
465
+ deadline=DEADLINE,
466
+ worker_type=transfer_manager.THREAD,
467
+ )
468
+
469
+ with tempfile.NamedTemporaryFile() as tmp:
470
+ download_blob = shared_bucket.blob(blob_name)
471
+ download_blob.download_to_file(tmp)
472
+ tmp.seek(0)
473
+
474
+ with open(source_file["path"], "rb") as sf:
475
+ source_contents = sf.read()
476
+ temp_contents = tmp.read()
477
+ assert source_contents == temp_contents
@@ -794,6 +794,57 @@ def test_upload_chunks_concurrently():
794
794
  part_mock.upload.assert_called_with(transport)
795
795
 
796
796
 
797
+ def test_upload_chunks_concurrently_quotes_urls():
798
+ bucket = mock.Mock()
799
+ bucket.name = "bucket"
800
+ bucket.client = _PickleableMockClient(identify_as_client=True)
801
+ transport = bucket.client._http
802
+ bucket.user_project = None
803
+
804
+ blob = Blob(b"../wrongbucket/blob", bucket)
805
+ blob.content_type = FAKE_CONTENT_TYPE
806
+ quoted_url = "https://example.com/bucket/..%2Fwrongbucket%2Fblob"
807
+
808
+ FILENAME = "file_a.txt"
809
+ SIZE = 2048
810
+
811
+ container_mock = mock.Mock()
812
+ container_mock.upload_id = "abcd"
813
+ part_mock = mock.Mock()
814
+ ETAG = "efgh"
815
+ part_mock.etag = ETAG
816
+ container_cls_mock = mock.Mock(return_value=container_mock)
817
+
818
+ with mock.patch("os.path.getsize", return_value=SIZE), mock.patch(
819
+ "google.cloud.storage.transfer_manager.XMLMPUContainer", new=container_cls_mock
820
+ ), mock.patch(
821
+ "google.cloud.storage.transfer_manager.XMLMPUPart", return_value=part_mock
822
+ ):
823
+ transfer_manager.upload_chunks_concurrently(
824
+ FILENAME,
825
+ blob,
826
+ chunk_size=SIZE // 2,
827
+ worker_type=transfer_manager.THREAD,
828
+ )
829
+
830
+ container_mock.initiate.assert_called_once_with(
831
+ transport=transport, content_type=blob.content_type
832
+ )
833
+ container_mock.register_part.assert_any_call(1, ETAG)
834
+ container_mock.register_part.assert_any_call(2, ETAG)
835
+ container_mock.finalize.assert_called_once_with(bucket.client._http)
836
+
837
+ assert container_mock._retry_strategy.max_sleep == 60.0
838
+ assert container_mock._retry_strategy.max_cumulative_retry == 120.0
839
+ assert container_mock._retry_strategy.max_retries is None
840
+
841
+ container_cls_mock.assert_called_once_with(
842
+ quoted_url, FILENAME, headers=mock.ANY
843
+ )
844
+
845
+ part_mock.upload.assert_called_with(transport)
846
+
847
+
797
848
  def test_upload_chunks_concurrently_passes_concurrency_options():
798
849
  bucket = mock.Mock()
799
850
  bucket.name = "bucket"