Skip to content

Commit fe434fc

Browse files
Gurov Ilyafrankyn
andauthored
refactor(storage): deprecate Bucket.create() and requester_pays (#49)
* refactor(storage): deprecate Bucket.create() and requester_pays * add_test_to_increase_cover * resolve conflicts * resolve conflicts * add new way of setting requester_pays into doclines Co-authored-by: Frank Natividad <[email protected]>
1 parent 0e5c082 commit fe434fc

File tree

5 files changed

+203
-259
lines changed

5 files changed

+203
-259
lines changed

docs/snippets.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ def storage_get_started(client, to_delete):
5151
@snippet
5252
def client_bucket_acl(client, to_delete):
5353
bucket_name = "system-test-bucket"
54-
bucket = client.bucket(bucket_name)
55-
bucket.create()
54+
client.create_bucket(bucket_name)
5655

5756
# [START client_bucket_acl]
5857
client = storage.Client()

google/cloud/storage/bucket.py

Lines changed: 14 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -693,7 +693,7 @@ def create(
693693
predefined_default_object_acl=None,
694694
timeout=_DEFAULT_TIMEOUT,
695695
):
696-
"""Creates current bucket.
696+
"""DEPRECATED. Creates current bucket.
697697
698698
If the bucket already exists, will raise
699699
:class:`google.cloud.exceptions.Conflict`.
@@ -737,44 +737,24 @@ def create(
737737
Can also be passed as a tuple (connect_timeout, read_timeout).
738738
See :meth:`requests.Session.request` documentation for details.
739739
"""
740+
warnings.warn(
741+
"Bucket.create() is deprecated and will be removed in future."
742+
"Use Client.create_bucket() instead.",
743+
PendingDeprecationWarning,
744+
stacklevel=1,
745+
)
740746
if self.user_project is not None:
741747
raise ValueError("Cannot create bucket with 'user_project' set.")
742748

743749
client = self._require_client(client)
744-
745-
if project is None:
746-
project = client.project
747-
748-
if project is None:
749-
raise ValueError("Client project not set: pass an explicit project.")
750-
751-
query_params = {"project": project}
752-
753-
if predefined_acl is not None:
754-
predefined_acl = BucketACL.validate_predefined(predefined_acl)
755-
query_params["predefinedAcl"] = predefined_acl
756-
757-
if predefined_default_object_acl is not None:
758-
predefined_default_object_acl = DefaultObjectACL.validate_predefined(
759-
predefined_default_object_acl
760-
)
761-
query_params["predefinedDefaultObjectAcl"] = predefined_default_object_acl
762-
763-
properties = {key: self._properties[key] for key in self._changes}
764-
properties["name"] = self.name
765-
766-
if location is not None:
767-
properties["location"] = location
768-
769-
api_response = client._connection.api_request(
770-
method="POST",
771-
path="/b",
772-
query_params=query_params,
773-
data=properties,
774-
_target_object=self,
750+
client.create_bucket(
751+
bucket_or_name=self,
752+
project=project,
753+
location=location,
754+
predefined_acl=predefined_acl,
755+
predefined_default_object_acl=predefined_default_object_acl,
775756
timeout=timeout,
776757
)
777-
self._set_properties(api_response)
778758

779759
def patch(self, client=None, timeout=_DEFAULT_TIMEOUT):
780760
"""Sends all changed properties in a PATCH request.
@@ -1908,7 +1888,7 @@ def requester_pays(self):
19081888
def requester_pays(self, value):
19091889
"""Update whether requester pays for API requests for this bucket.
19101890
1911-
See https://cloud.google.com/storage/docs/<DOCS-MISSING> for
1891+
See https://cloud.google.com/storage/docs/using-requester-pays for
19121892
details.
19131893
19141894
:type value: convertible to boolean

google/cloud/storage/client.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414

1515
"""Client for interacting with the Google Cloud Storage API."""
1616

17+
import warnings
1718
import functools
18-
1919
import google.api_core.client_options
2020

2121
from google.auth.credentials import AnonymousCredentials
@@ -373,8 +373,9 @@ def create_bucket(
373373
]):
374374
The bucket resource to pass or name to create.
375375
requester_pays (bool):
376-
Optional. Whether requester pays for API requests for this
377-
bucket and its blobs.
376+
DEPRECATED. Use Bucket().requester_pays instead.
377+
Optional. Whether requester pays for API requests for
378+
this bucket and its blobs.
378379
project (str):
379380
Optional. The project under which the bucket is to be created.
380381
If not passed, uses the project set on the client.
@@ -435,6 +436,11 @@ def create_bucket(
435436
raise ValueError("Client project not set: pass an explicit project.")
436437

437438
if requester_pays is not None:
439+
warnings.warn(
440+
"requester_pays arg is deprecated. Use Bucket().requester_pays instead.",
441+
PendingDeprecationWarning,
442+
stacklevel=1,
443+
)
438444
bucket.requester_pays = requester_pays
439445

440446
query_params = {"project": project}

tests/unit/test_bucket.py

Lines changed: 45 additions & 217 deletions
Original file line numberDiff line numberDiff line change
@@ -615,223 +615,6 @@ def api_request(cls, *args, **kwargs):
615615
expected_cw = [((), expected_called_kwargs)]
616616
self.assertEqual(_FakeConnection._called_with, expected_cw)
617617

618-
def test_create_w_user_project(self):
619-
from google.cloud.storage.client import Client
620-
621-
PROJECT = "PROJECT"
622-
BUCKET_NAME = "bucket-name"
623-
USER_PROJECT = "user-project-123"
624-
625-
client = Client(project=PROJECT)
626-
client._base_connection = _Connection()
627-
628-
bucket = self._make_one(client, BUCKET_NAME, user_project=USER_PROJECT)
629-
630-
with self.assertRaises(ValueError):
631-
bucket.create()
632-
633-
def test_create_w_missing_client_project(self):
634-
from google.cloud.storage.client import Client
635-
636-
BUCKET_NAME = "bucket-name"
637-
638-
client = Client(project=None)
639-
bucket = self._make_one(client, BUCKET_NAME)
640-
641-
with self.assertRaises(ValueError):
642-
bucket.create()
643-
644-
def test_create_w_explicit_project(self):
645-
from google.cloud.storage.client import Client
646-
647-
PROJECT = "PROJECT"
648-
BUCKET_NAME = "bucket-name"
649-
OTHER_PROJECT = "other-project-123"
650-
DATA = {"name": BUCKET_NAME}
651-
connection = _make_connection(DATA)
652-
653-
client = Client(project=PROJECT)
654-
client._base_connection = connection
655-
656-
bucket = self._make_one(client, BUCKET_NAME)
657-
bucket.create(project=OTHER_PROJECT)
658-
connection.api_request.assert_called_once_with(
659-
method="POST",
660-
path="/b",
661-
query_params={"project": OTHER_PROJECT},
662-
data=DATA,
663-
_target_object=bucket,
664-
timeout=self._get_default_timeout(),
665-
)
666-
667-
def test_create_w_explicit_location(self):
668-
from google.cloud.storage.client import Client
669-
670-
PROJECT = "PROJECT"
671-
BUCKET_NAME = "bucket-name"
672-
LOCATION = "us-central1"
673-
DATA = {"location": LOCATION, "name": BUCKET_NAME}
674-
675-
connection = _make_connection(
676-
DATA, "{'location': 'us-central1', 'name': 'bucket-name'}"
677-
)
678-
679-
client = Client(project=PROJECT)
680-
client._base_connection = connection
681-
682-
bucket = self._make_one(client, BUCKET_NAME)
683-
bucket.create(location=LOCATION)
684-
685-
connection.api_request.assert_called_once_with(
686-
method="POST",
687-
path="/b",
688-
data=DATA,
689-
_target_object=bucket,
690-
query_params={"project": "PROJECT"},
691-
timeout=self._get_default_timeout(),
692-
)
693-
self.assertEqual(bucket.location, LOCATION)
694-
695-
def test_create_hit(self):
696-
from google.cloud.storage.client import Client
697-
698-
PROJECT = "PROJECT"
699-
BUCKET_NAME = "bucket-name"
700-
DATA = {"name": BUCKET_NAME}
701-
connection = _make_connection(DATA)
702-
client = Client(project=PROJECT)
703-
client._base_connection = connection
704-
705-
bucket = self._make_one(client=client, name=BUCKET_NAME)
706-
bucket.create(timeout=42)
707-
708-
connection.api_request.assert_called_once_with(
709-
method="POST",
710-
path="/b",
711-
query_params={"project": PROJECT},
712-
data=DATA,
713-
_target_object=bucket,
714-
timeout=42,
715-
)
716-
717-
def test_create_w_extra_properties(self):
718-
from google.cloud.storage.client import Client
719-
720-
BUCKET_NAME = "bucket-name"
721-
PROJECT = "PROJECT"
722-
CORS = [
723-
{
724-
"maxAgeSeconds": 60,
725-
"methods": ["*"],
726-
"origin": ["https://example.com/frontend"],
727-
"responseHeader": ["X-Custom-Header"],
728-
}
729-
]
730-
LIFECYCLE_RULES = [{"action": {"type": "Delete"}, "condition": {"age": 365}}]
731-
LOCATION = "eu"
732-
LABELS = {"color": "red", "flavor": "cherry"}
733-
STORAGE_CLASS = "NEARLINE"
734-
DATA = {
735-
"name": BUCKET_NAME,
736-
"cors": CORS,
737-
"lifecycle": {"rule": LIFECYCLE_RULES},
738-
"location": LOCATION,
739-
"storageClass": STORAGE_CLASS,
740-
"versioning": {"enabled": True},
741-
"billing": {"requesterPays": True},
742-
"labels": LABELS,
743-
}
744-
745-
connection = _make_connection(DATA)
746-
client = Client(project=PROJECT)
747-
client._base_connection = connection
748-
749-
bucket = self._make_one(client=client, name=BUCKET_NAME)
750-
bucket.cors = CORS
751-
bucket.lifecycle_rules = LIFECYCLE_RULES
752-
bucket.storage_class = STORAGE_CLASS
753-
bucket.versioning_enabled = True
754-
bucket.requester_pays = True
755-
bucket.labels = LABELS
756-
bucket.create(location=LOCATION)
757-
758-
connection.api_request.assert_called_once_with(
759-
method="POST",
760-
path="/b",
761-
query_params={"project": PROJECT},
762-
data=DATA,
763-
_target_object=bucket,
764-
timeout=self._get_default_timeout(),
765-
)
766-
767-
def test_create_w_predefined_acl_invalid(self):
768-
from google.cloud.storage.client import Client
769-
770-
PROJECT = "PROJECT"
771-
BUCKET_NAME = "bucket-name"
772-
DATA = {"name": BUCKET_NAME}
773-
connection = _Connection(DATA)
774-
client = Client(project=PROJECT)
775-
client._base_connection = connection
776-
bucket = self._make_one(client=client, name=BUCKET_NAME)
777-
778-
with self.assertRaises(ValueError):
779-
bucket.create(predefined_acl="bogus")
780-
781-
def test_create_w_predefined_acl_valid(self):
782-
from google.cloud.storage.client import Client
783-
784-
PROJECT = "PROJECT"
785-
BUCKET_NAME = "bucket-name"
786-
DATA = {"name": BUCKET_NAME}
787-
connection = _Connection(DATA)
788-
client = Client(project=PROJECT)
789-
client._base_connection = connection
790-
bucket = self._make_one(client=client, name=BUCKET_NAME)
791-
bucket.create(predefined_acl="publicRead")
792-
793-
kw, = connection._requested
794-
self.assertEqual(kw["method"], "POST")
795-
self.assertEqual(kw["path"], "/b")
796-
expected_qp = {"project": PROJECT, "predefinedAcl": "publicRead"}
797-
self.assertEqual(kw["query_params"], expected_qp)
798-
self.assertEqual(kw["data"], DATA)
799-
self.assertEqual(kw["timeout"], self._get_default_timeout())
800-
801-
def test_create_w_predefined_default_object_acl_invalid(self):
802-
from google.cloud.storage.client import Client
803-
804-
PROJECT = "PROJECT"
805-
BUCKET_NAME = "bucket-name"
806-
DATA = {"name": BUCKET_NAME}
807-
connection = _Connection(DATA)
808-
client = Client(project=PROJECT)
809-
client._base_connection = connection
810-
bucket = self._make_one(client=client, name=BUCKET_NAME)
811-
812-
with self.assertRaises(ValueError):
813-
bucket.create(predefined_default_object_acl="bogus")
814-
815-
def test_create_w_predefined_default_object_acl_valid(self):
816-
from google.cloud.storage.client import Client
817-
818-
PROJECT = "PROJECT"
819-
BUCKET_NAME = "bucket-name"
820-
DATA = {"name": BUCKET_NAME}
821-
connection = _Connection(DATA)
822-
client = Client(project=PROJECT)
823-
client._base_connection = connection
824-
bucket = self._make_one(client=client, name=BUCKET_NAME)
825-
bucket.create(predefined_default_object_acl="publicRead")
826-
827-
kw, = connection._requested
828-
self.assertEqual(kw["method"], "POST")
829-
self.assertEqual(kw["path"], "/b")
830-
expected_qp = {"project": PROJECT, "predefinedDefaultObjectAcl": "publicRead"}
831-
self.assertEqual(kw["query_params"], expected_qp)
832-
self.assertEqual(kw["data"], DATA)
833-
self.assertEqual(kw["timeout"], self._get_default_timeout())
834-
835618
def test_acl_property(self):
836619
from google.cloud.storage.acl import BucketACL
837620

@@ -2013,6 +1796,51 @@ def test_versioning_enabled_getter(self):
20131796
bucket = self._make_one(name=NAME, properties=before)
20141797
self.assertEqual(bucket.versioning_enabled, True)
20151798

1799+
@mock.patch("warnings.warn")
1800+
def test_create_deprecated(self, mock_warn):
1801+
from google.cloud.storage.client import Client
1802+
1803+
PROJECT = "PROJECT"
1804+
BUCKET_NAME = "bucket-name"
1805+
DATA = {"name": BUCKET_NAME}
1806+
connection = _make_connection(DATA)
1807+
client = Client(project=PROJECT)
1808+
client._base_connection = connection
1809+
1810+
bucket = self._make_one(client=client, name=BUCKET_NAME)
1811+
bucket.create()
1812+
1813+
connection.api_request.assert_called_once_with(
1814+
method="POST",
1815+
path="/b",
1816+
query_params={"project": PROJECT},
1817+
data=DATA,
1818+
_target_object=bucket,
1819+
timeout=self._get_default_timeout(),
1820+
)
1821+
1822+
mock_warn.assert_called_with(
1823+
"Bucket.create() is deprecated and will be removed in future."
1824+
"Use Client.create_bucket() instead.",
1825+
PendingDeprecationWarning,
1826+
stacklevel=1,
1827+
)
1828+
1829+
def test_create_w_user_project(self):
1830+
from google.cloud.storage.client import Client
1831+
1832+
PROJECT = "PROJECT"
1833+
BUCKET_NAME = "bucket-name"
1834+
DATA = {"name": BUCKET_NAME}
1835+
connection = _make_connection(DATA)
1836+
client = Client(project=PROJECT)
1837+
client._base_connection = connection
1838+
1839+
bucket = self._make_one(client=client, name=BUCKET_NAME)
1840+
bucket._user_project = "USER_PROJECT"
1841+
with self.assertRaises(ValueError):
1842+
bucket.create()
1843+
20161844
def test_versioning_enabled_setter(self):
20171845
NAME = "name"
20181846
bucket = self._make_one(name=NAME)

0 commit comments

Comments
 (0)