Skip to content

Commit 8d8a53a

Browse files
authored
fix: remove utcnow usage (#1215)
* fix: replace utcnow in Bucket * replace utcnow in signing * update constant and tests * update datetime in post policy * replace utcnow in system tests * replace tzinfo
1 parent f4cf041 commit 8d8a53a

File tree

14 files changed

+114
-139
lines changed

14 files changed

+114
-139
lines changed

google/cloud/storage/_helpers.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"""
1919

2020
import base64
21+
import datetime
2122
from hashlib import md5
2223
import os
2324
from urllib.parse import urlsplit
@@ -77,6 +78,12 @@
7778
"object, or None, instead."
7879
)
7980

81+
# _NOW() returns the current local date and time.
82+
# It is preferred to use timezone-aware datetimes _NOW(_UTC),
83+
# which returns the current UTC date and time.
84+
_NOW = datetime.datetime.now
85+
_UTC = datetime.timezone.utc
86+
8087

8188
def _get_storage_emulator_override():
8289
return os.environ.get(STORAGE_EMULATOR_ENV_VAR, None)

google/cloud/storage/_signing.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,13 @@
2828
from google.auth import exceptions
2929
from google.auth.transport import requests
3030
from google.cloud import _helpers
31+
from google.cloud.storage._helpers import _NOW
32+
from google.cloud.storage._helpers import _UTC
3133

3234

33-
NOW = datetime.datetime.utcnow # To be replaced by tests.
35+
# `google.cloud.storage._signing.NOW` is deprecated.
36+
# Use `_NOW(_UTC)` instead.
37+
NOW = datetime.datetime.utcnow
3438

3539
SERVICE_ACCOUNT_URL = (
3640
"https://googleapis.dev/python/google-api-core/latest/"
@@ -103,7 +107,7 @@ def get_expiration_seconds_v2(expiration):
103107
"""
104108
# If it's a timedelta, add it to `now` in UTC.
105109
if isinstance(expiration, datetime.timedelta):
106-
now = NOW().replace(tzinfo=_helpers.UTC)
110+
now = _NOW(_UTC)
107111
expiration = now + expiration
108112

109113
# If it's a datetime, convert to a timestamp.
@@ -141,15 +145,14 @@ def get_expiration_seconds_v4(expiration):
141145
"timedelta. Got %s" % type(expiration)
142146
)
143147

144-
now = NOW().replace(tzinfo=_helpers.UTC)
148+
now = _NOW(_UTC)
145149

146150
if isinstance(expiration, int):
147151
seconds = expiration
148152

149153
if isinstance(expiration, datetime.datetime):
150154
if expiration.tzinfo is None:
151155
expiration = expiration.replace(tzinfo=_helpers.UTC)
152-
153156
expiration = expiration - now
154157

155158
if isinstance(expiration, datetime.timedelta):
@@ -638,7 +641,7 @@ def get_v4_now_dtstamps():
638641
:rtype: str, str
639642
:returns: Current timestamp, datestamp.
640643
"""
641-
now = NOW()
644+
now = _NOW(_UTC).replace(tzinfo=None)
642645
timestamp = now.strftime("%Y%m%dT%H%M%SZ")
643646
datestamp = now.date().strftime("%Y%m%d")
644647
return timestamp, datestamp

google/cloud/storage/bucket.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,15 @@
2323

2424
from google.api_core import datetime_helpers
2525
from google.cloud._helpers import _datetime_to_rfc3339
26-
from google.cloud._helpers import _NOW
2726
from google.cloud._helpers import _rfc3339_nanos_to_datetime
2827
from google.cloud.exceptions import NotFound
2928
from google.api_core.iam import Policy
3029
from google.cloud.storage import _signing
3130
from google.cloud.storage._helpers import _add_etag_match_headers
3231
from google.cloud.storage._helpers import _add_generation_match_parameters
32+
from google.cloud.storage._helpers import _NOW
3333
from google.cloud.storage._helpers import _PropertyMixin
34+
from google.cloud.storage._helpers import _UTC
3435
from google.cloud.storage._helpers import _scalar_property
3536
from google.cloud.storage._helpers import _validate_name
3637
from google.cloud.storage._signing import generate_signed_url_v2
@@ -3186,7 +3187,7 @@ def generate_upload_policy(self, conditions, expiration=None, client=None):
31863187
_signing.ensure_signed_credentials(credentials)
31873188

31883189
if expiration is None:
3189-
expiration = _NOW() + datetime.timedelta(hours=1)
3190+
expiration = _NOW(_UTC).replace(tzinfo=None) + datetime.timedelta(hours=1)
31903191

31913192
conditions = conditions + [{"bucket": self.name}]
31923193

google/cloud/storage/client.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,21 @@
2626
from google.auth.credentials import AnonymousCredentials
2727

2828
from google.api_core import page_iterator
29-
from google.cloud._helpers import _LocalStack, _NOW
29+
from google.cloud._helpers import _LocalStack
3030
from google.cloud.client import ClientWithProject
3131
from google.cloud.exceptions import NotFound
3232

33+
from google.cloud.storage._helpers import _bucket_bound_hostname_url
34+
from google.cloud.storage._helpers import _get_api_endpoint_override
3335
from google.cloud.storage._helpers import _get_environ_project
34-
from google.cloud.storage._helpers import _use_client_cert
3536
from google.cloud.storage._helpers import _get_storage_emulator_override
36-
from google.cloud.storage._helpers import _get_api_endpoint_override
37-
from google.cloud.storage._helpers import _STORAGE_HOST_TEMPLATE
38-
from google.cloud.storage._helpers import _bucket_bound_hostname_url
37+
from google.cloud.storage._helpers import _use_client_cert
38+
from google.cloud.storage._helpers import _virtual_hosted_style_base_url
3939
from google.cloud.storage._helpers import _DEFAULT_UNIVERSE_DOMAIN
4040
from google.cloud.storage._helpers import _DEFAULT_SCHEME
41-
from google.cloud.storage._helpers import _virtual_hosted_style_base_url
41+
from google.cloud.storage._helpers import _STORAGE_HOST_TEMPLATE
42+
from google.cloud.storage._helpers import _NOW
43+
from google.cloud.storage._helpers import _UTC
4244

4345
from google.cloud.storage._http import Connection
4446
from google.cloud.storage._signing import (
@@ -1707,7 +1709,7 @@ def generate_signed_post_policy_v4(
17071709
conditions += required_conditions
17081710

17091711
# calculate policy expiration time
1710-
now = _NOW()
1712+
now = _NOW(_UTC).replace(tzinfo=None)
17111713
if expiration is None:
17121714
expiration = now + datetime.timedelta(hours=1)
17131715

tests/system/test__signing.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
from google.api_core import path_template
2424
from google.cloud import iam_credentials_v1
25+
from google.cloud.storage._helpers import _NOW
26+
from google.cloud.storage._helpers import _UTC
2527
from . import _helpers
2628

2729

@@ -63,7 +65,7 @@ def test_create_signed_list_blobs_url_v2(storage_client, signing_bucket, no_mtls
6365
def test_create_signed_list_blobs_url_v2_w_expiration(
6466
storage_client, signing_bucket, no_mtls
6567
):
66-
now = datetime.datetime.utcnow()
68+
now = _NOW(_UTC).replace(tzinfo=None)
6769
delta = datetime.timedelta(seconds=10)
6870

6971
_create_signed_list_blobs_url_helper(
@@ -85,7 +87,7 @@ def test_create_signed_list_blobs_url_v4(storage_client, signing_bucket, no_mtls
8587
def test_create_signed_list_blobs_url_v4_w_expiration(
8688
storage_client, signing_bucket, no_mtls
8789
):
88-
now = datetime.datetime.utcnow()
90+
now = _NOW(_UTC).replace(tzinfo=None)
8991
delta = datetime.timedelta(seconds=10)
9092
_create_signed_list_blobs_url_helper(
9193
storage_client,
@@ -158,7 +160,7 @@ def test_create_signed_read_url_v4(storage_client, signing_bucket, no_mtls):
158160
def test_create_signed_read_url_v2_w_expiration(
159161
storage_client, signing_bucket, no_mtls
160162
):
161-
now = datetime.datetime.utcnow()
163+
now = _NOW(_UTC).replace(tzinfo=None)
162164
delta = datetime.timedelta(seconds=10)
163165

164166
_create_signed_read_url_helper(
@@ -169,7 +171,7 @@ def test_create_signed_read_url_v2_w_expiration(
169171
def test_create_signed_read_url_v4_w_expiration(
170172
storage_client, signing_bucket, no_mtls
171173
):
172-
now = datetime.datetime.utcnow()
174+
now = _NOW(_UTC).replace(tzinfo=None)
173175
delta = datetime.timedelta(seconds=10)
174176
_create_signed_read_url_helper(
175177
storage_client, signing_bucket, expiration=now + delta, version="v4"
@@ -391,14 +393,15 @@ def test_generate_signed_post_policy_v4(
391393
with open(blob_name, "wb") as f:
392394
f.write(payload)
393395

396+
now = _NOW(_UTC).replace(tzinfo=None)
394397
policy = storage_client.generate_signed_post_policy_v4(
395398
bucket_name,
396399
blob_name,
397400
conditions=[
398401
{"bucket": bucket_name},
399402
["starts-with", "$Content-Type", "text/pla"],
400403
],
401-
expiration=datetime.datetime.utcnow() + datetime.timedelta(hours=1),
404+
expiration=now + datetime.timedelta(hours=1),
402405
fields={"content-type": "text/plain"},
403406
)
404407
with open(blob_name, "r") as f:
@@ -424,14 +427,15 @@ def test_generate_signed_post_policy_v4_invalid_field(
424427
with open(blob_name, "wb") as f:
425428
f.write(payload)
426429

430+
now = _NOW(_UTC).replace(tzinfo=None)
427431
policy = storage_client.generate_signed_post_policy_v4(
428432
bucket_name,
429433
blob_name,
430434
conditions=[
431435
{"bucket": bucket_name},
432436
["starts-with", "$Content-Type", "text/pla"],
433437
],
434-
expiration=datetime.datetime.utcnow() + datetime.timedelta(hours=1),
438+
expiration=now + datetime.timedelta(hours=1),
435439
fields={"x-goog-random": "invalid_field", "content-type": "text/plain"},
436440
)
437441
with open(blob_name, "r") as f:

tests/system/test_blob.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1120,6 +1120,9 @@ def test_blob_update_storage_class_large_file(
11201120

11211121

11221122
def test_object_retention_lock(storage_client, buckets_to_delete, blobs_to_delete):
1123+
from google.cloud.storage._helpers import _NOW
1124+
from google.cloud.storage._helpers import _UTC
1125+
11231126
# Test bucket created with object retention enabled
11241127
new_bucket_name = _helpers.unique_name("object-retention")
11251128
created_bucket = _helpers.retry_429_503(storage_client.create_bucket)(
@@ -1131,7 +1134,7 @@ def test_object_retention_lock(storage_client, buckets_to_delete, blobs_to_delet
11311134
# Test create object with object retention enabled
11321135
payload = b"Hello World"
11331136
mode = "Unlocked"
1134-
current_time = datetime.datetime.utcnow()
1137+
current_time = _NOW(_UTC).replace(tzinfo=None)
11351138
expiration_time = current_time + datetime.timedelta(seconds=10)
11361139
blob = created_bucket.blob("object-retention-lock")
11371140
blob.retention.mode = mode

tests/system/test_hmac_key_metadata.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616

1717
import pytest
1818

19-
from google.cloud import _helpers as _cloud_helpers
20-
2119
from . import _helpers
2220

2321

@@ -32,9 +30,12 @@ def ensure_hmac_key_deleted(hmac_key):
3230

3331
@pytest.fixture
3432
def scrubbed_hmac_keys(storage_client):
33+
from google.cloud.storage._helpers import _NOW
34+
from google.cloud.storage._helpers import _UTC
35+
3536
before_hmac_keys = set(storage_client.list_hmac_keys())
3637

37-
now = datetime.datetime.utcnow().replace(tzinfo=_cloud_helpers.UTC)
38+
now = _NOW(_UTC)
3839
yesterday = now - datetime.timedelta(days=1)
3940

4041
# Delete any HMAC keys older than a day.

tests/system/test_transfer_manager.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -267,10 +267,10 @@ def test_upload_chunks_concurrently(shared_bucket, file_data, blobs_to_delete):
267267
def test_upload_chunks_concurrently_with_metadata(
268268
shared_bucket, file_data, blobs_to_delete
269269
):
270-
import datetime
271-
from google.cloud._helpers import UTC
270+
from google.cloud.storage._helpers import _NOW
271+
from google.cloud.storage._helpers import _UTC
272272

273-
now = datetime.datetime.utcnow().replace(tzinfo=UTC)
273+
now = _NOW(_UTC)
274274
custom_metadata = {"key_a": "value_a", "key_b": "value_b"}
275275

276276
METADATA = {

0 commit comments

Comments
 (0)