Skip to content

Commit 9746062

Browse files
authored
tests: allow prerelease dependency versions under Python 3.9 (#479)
Also, drop use of 'pytz', which is no longer depended on by `google-api-core` / `google-cloud-core`. Instead, use either `datetime.timezone.utc` or `google.cloud._helpers.UTC`, depending on usage.
1 parent 5629bac commit 9746062

File tree

9 files changed

+107
-67
lines changed

9 files changed

+107
-67
lines changed

docs/snapshot-usage.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ reads as of a given timestamp:
2424
.. code:: python
2525
2626
import datetime
27-
from pytz import UTC
28-
TIMESTAMP = datetime.datetime.utcnow().replace(tzinfo=UTC)
27+
TIMESTAMP = datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc)
2928
3029
with database.snapshot(read_timestamp=TIMESTAMP) as snapshot:
3130
...

noxfile.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,11 @@ def default(session):
105105
*session.posargs,
106106
)
107107

108+
# XXX Work around Kokoro image's older pip, which borks the OT install.
109+
session.run("pip", "install", "--upgrade", "pip")
108110
session.install("-e", ".[tracing]", "-c", constraints_path)
111+
# XXX: Dump installed versions to debug OT issue
112+
session.run("pip", "list")
109113

110114
# Run py.test against the unit tests with OpenTelemetry.
111115
session.run(

owlbot.py

Lines changed: 65 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,16 @@
2323

2424
common = gcp.CommonTemplates()
2525

26-
# This is a customized version of the s.get_staging_dirs() function from synthtool to
27-
# cater for copying 3 different folders from googleapis-gen
28-
# which are spanner, spanner/admin/instance and spanner/admin/database.
29-
# Source https://github.com/googleapis/synthtool/blob/master/synthtool/transforms.py#L280
26+
3027
def get_staging_dirs(
31-
default_version: Optional[str] = None, sub_directory: Optional[str] = None
28+
# This is a customized version of the s.get_staging_dirs() function
29+
# from synthtool to # cater for copying 3 different folders from
30+
# googleapis-gen:
31+
# spanner, spanner/admin/instance and spanner/admin/database.
32+
# Source:
33+
# https://github.com/googleapis/synthtool/blob/master/synthtool/transforms.py#L280
34+
default_version: Optional[str] = None,
35+
sub_directory: Optional[str] = None,
3236
) -> List[Path]:
3337
"""Returns the list of directories, one per version, copied from
3438
https://github.com/googleapis/googleapis-gen. Will return in lexical sorting
@@ -63,46 +67,69 @@ def get_staging_dirs(
6367
else:
6468
return []
6569

70+
6671
spanner_default_version = "v1"
6772
spanner_admin_instance_default_version = "v1"
6873
spanner_admin_database_default_version = "v1"
6974

7075
for library in get_staging_dirs(spanner_default_version, "spanner"):
7176
# Work around gapic generator bug https://github.com/googleapis/gapic-generator-python/issues/902
72-
s.replace(library / f"google/cloud/spanner_{library.name}/types/transaction.py",
73-
r""".
77+
s.replace(
78+
library / f"google/cloud/spanner_{library.name}/types/transaction.py",
79+
r""".
7480
Attributes:""",
75-
r""".\n
81+
r""".\n
7682
Attributes:""",
7783
)
7884

7985
# Work around gapic generator bug https://github.com/googleapis/gapic-generator-python/issues/902
80-
s.replace(library / f"google/cloud/spanner_{library.name}/types/transaction.py",
81-
r""".
86+
s.replace(
87+
library / f"google/cloud/spanner_{library.name}/types/transaction.py",
88+
r""".
8289
Attributes:""",
83-
r""".\n
90+
r""".\n
8491
Attributes:""",
8592
)
8693

8794
# Remove headings from docstring. Requested change upstream in cl/377290854 due to https://google.aip.dev/192#formatting.
88-
s.replace(library / f"google/cloud/spanner_{library.name}/types/transaction.py",
95+
s.replace(
96+
library / f"google/cloud/spanner_{library.name}/types/transaction.py",
8997
"""\n ==.*?==\n""",
9098
":",
9199
)
92100

93101
# Remove headings from docstring. Requested change upstream in cl/377290854 due to https://google.aip.dev/192#formatting.
94-
s.replace(library / f"google/cloud/spanner_{library.name}/types/transaction.py",
102+
s.replace(
103+
library / f"google/cloud/spanner_{library.name}/types/transaction.py",
95104
"""\n --.*?--\n""",
96105
":",
97106
)
98107

99-
s.move(library, excludes=["google/cloud/spanner/**", "*.*", "docs/index.rst", "google/cloud/spanner_v1/__init__.py"])
108+
s.move(
109+
library,
110+
excludes=[
111+
"google/cloud/spanner/**",
112+
"*.*",
113+
"docs/index.rst",
114+
"google/cloud/spanner_v1/__init__.py",
115+
],
116+
)
100117

101-
for library in get_staging_dirs(spanner_admin_instance_default_version, "spanner_admin_instance"):
102-
s.move(library, excludes=["google/cloud/spanner_admin_instance/**", "*.*", "docs/index.rst"])
118+
for library in get_staging_dirs(
119+
spanner_admin_instance_default_version, "spanner_admin_instance"
120+
):
121+
s.move(
122+
library,
123+
excludes=["google/cloud/spanner_admin_instance/**", "*.*", "docs/index.rst"],
124+
)
103125

104-
for library in get_staging_dirs(spanner_admin_database_default_version, "spanner_admin_database"):
105-
s.move(library, excludes=["google/cloud/spanner_admin_database/**", "*.*", "docs/index.rst"])
126+
for library in get_staging_dirs(
127+
spanner_admin_database_default_version, "spanner_admin_database"
128+
):
129+
s.move(
130+
library,
131+
excludes=["google/cloud/spanner_admin_database/**", "*.*", "docs/index.rst"],
132+
)
106133

107134
s.remove_staging_dirs()
108135

@@ -116,9 +143,11 @@ def get_staging_dirs(
116143
s.replace(
117144
".kokoro/build.sh",
118145
"# Remove old nox",
119-
"# Set up creating a new instance for each system test run\n"
120-
"export GOOGLE_CLOUD_TESTS_CREATE_SPANNER_INSTANCE=true\n"
121-
"\n\g<0>",
146+
"""\
147+
# Set up creating a new instance for each system test run
148+
export GOOGLE_CLOUD_TESTS_CREATE_SPANNER_INSTANCE=true
149+
150+
# Remove old nox""",
122151
)
123152

124153
# Update samples folder in CONTRIBUTING.rst
@@ -134,15 +163,21 @@ def get_staging_dirs(
134163
# Customize noxfile.py
135164
# ----------------------------------------------------------------------------
136165

166+
137167
def place_before(path, text, *before_text, escape=None):
138168
replacement = "\n".join(before_text) + "\n" + text
139169
if escape:
140170
for c in escape:
141-
text = text.replace(c, '\\' + c)
171+
text = text.replace(c, "\\" + c)
142172
s.replace([path], text, replacement)
143173

174+
144175
open_telemetry_test = """
176+
# XXX Work around Kokoro image's older pip, which borks the OT install.
177+
session.run("pip", "install", "--upgrade", "pip")
145178
session.install("-e", ".[tracing]", "-c", constraints_path)
179+
# XXX: Dump installed versions to debug OT issue
180+
session.run("pip", "list")
146181
147182
# Run py.test against the unit tests with OpenTelemetry.
148183
session.run(
@@ -164,10 +199,10 @@ def place_before(path, text, *before_text, escape=None):
164199
"noxfile.py",
165200
"@nox.session(python=UNIT_TEST_PYTHON_VERSIONS)",
166201
open_telemetry_test,
167-
escape="()"
202+
escape="()",
168203
)
169204

170-
skip_tests_if_env_var_not_set ="""# Sanity check: Only run tests if the environment variable is set.
205+
skip_tests_if_env_var_not_set = """# Sanity check: Only run tests if the environment variable is set.
171206
if not os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", "") and not os.environ.get(
172207
"SPANNER_EMULATOR_HOST", ""
173208
):
@@ -180,7 +215,7 @@ def place_before(path, text, *before_text, escape=None):
180215
"noxfile.py",
181216
"# Install pyopenssl for mTLS testing.",
182217
skip_tests_if_env_var_not_set,
183-
escape="()"
218+
escape="()",
184219
)
185220

186221
s.replace(
@@ -190,25 +225,25 @@ def place_before(path, text, *before_text, escape=None):
190225
"--cov=tests/unit",""",
191226
"""\"--cov=google.cloud.spanner",
192227
"--cov=google.cloud",
193-
"--cov=tests.unit","""
228+
"--cov=tests.unit",""",
194229
)
195230

196231
s.replace(
197232
"noxfile.py",
198-
"""session.install\("-e", "."\)""",
199-
"""session.install("-e", ".[tracing]")"""
233+
r"""session.install\("-e", "."\)""",
234+
"""session.install("-e", ".[tracing]")""",
200235
)
201236

202237
s.replace(
203238
"noxfile.py",
204-
"""# Install all test dependencies, then install this package into the
239+
r"""# Install all test dependencies, then install this package into the
205240
# virtualenv's dist-packages.
206241
session.install\("mock", "pytest", "google-cloud-testutils", "-c", constraints_path\)
207242
session.install\("-e", ".", "-c", constraints_path\)""",
208243
"""# Install all test dependencies, then install this package into the
209244
# virtualenv's dist-packages.
210245
session.install("mock", "pytest", "google-cloud-testutils", "-c", constraints_path)
211-
session.install("-e", ".[tracing]", "-c", constraints_path)"""
246+
session.install("-e", ".[tracing]", "-c", constraints_path)""",
212247
)
213248

214249
s.shell.run(["nox", "-s", "blacken"], hide_output=False)

samples/samples/conftest.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import pytest
2525
from test_utils import retry
2626

27+
retry_429 = retry.RetryErrors(exceptions.ResourceExhausted, delay=15)
28+
2729

2830
@pytest.fixture(scope="module")
2931
def sample_name():
@@ -47,7 +49,7 @@ def scrub_instance_ignore_not_found(to_scrub):
4749
for backup_pb in to_scrub.list_backups():
4850
backup.Backup.from_pb(backup_pb, to_scrub).delete()
4951

50-
to_scrub.delete()
52+
retry_429(to_scrub.delete)()
5153
except exceptions.NotFound:
5254
pass
5355

@@ -107,7 +109,6 @@ def sample_instance(
107109
"created": str(int(time.time())),
108110
},
109111
)
110-
retry_429 = retry.RetryErrors(exceptions.ResourceExhausted, delay=15)
111112
op = retry_429(sample_instance.create)()
112113
op.result(120) # block until completion
113114

@@ -143,7 +144,6 @@ def multi_region_instance(
143144
"created": str(int(time.time()))
144145
},
145146
)
146-
retry_429 = retry.RetryErrors(exceptions.ResourceExhausted, delay=15)
147147
op = retry_429(multi_region_instance.create)()
148148
op.result(120) # block until completion
149149

samples/samples/snippets.py

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
from google.cloud import spanner
3131
from google.cloud.spanner_v1 import param_types
3232

33+
OPERATION_TIMEOUT_SECONDS = 240
34+
3335

3436
# [START spanner_create_instance]
3537
def create_instance(instance_id):
@@ -55,7 +57,7 @@ def create_instance(instance_id):
5557
operation = instance.create()
5658

5759
print("Waiting for operation to complete...")
58-
operation.result(120)
60+
operation.result(OPERATION_TIMEOUT_SECONDS)
5961

6062
print("Created instance {}".format(instance_id))
6163

@@ -87,7 +89,7 @@ def create_instance_with_processing_units(instance_id, processing_units):
8789
operation = instance.create()
8890

8991
print("Waiting for operation to complete...")
90-
operation.result(120)
92+
operation.result(OPERATION_TIMEOUT_SECONDS)
9193

9294
print("Created instance {} with {} processing units".format(
9395
instance_id, instance.processing_units))
@@ -170,7 +172,7 @@ def create_database(instance_id, database_id):
170172
operation = database.create()
171173

172174
print("Waiting for operation to complete...")
173-
operation.result(120)
175+
operation.result(OPERATION_TIMEOUT_SECONDS)
174176

175177
print("Created database {} on instance {}".format(database_id, instance_id))
176178

@@ -206,7 +208,7 @@ def create_database_with_encryption_key(instance_id, database_id, kms_key_name):
206208
operation = database.create()
207209

208210
print("Waiting for operation to complete...")
209-
operation.result(120)
211+
operation.result(OPERATION_TIMEOUT_SECONDS)
210212

211213
print("Database {} created with encryption key {}".format(
212214
database.name, database.encryption_config.kms_key_name))
@@ -245,7 +247,7 @@ def create_database_with_default_leader(
245247
operation = database.create()
246248

247249
print("Waiting for operation to complete...")
248-
operation.result(120)
250+
operation.result(OPERATION_TIMEOUT_SECONDS)
249251

250252
database.reload()
251253

@@ -271,7 +273,7 @@ def update_database_with_default_leader(
271273

272274
operation = database.update_ddl(["ALTER DATABASE {}"
273275
" SET OPTIONS (default_leader = '{}')".format(database_id, default_leader)])
274-
operation.result(120)
276+
operation.result(OPERATION_TIMEOUT_SECONDS)
275277

276278
database.reload()
277279

@@ -499,7 +501,7 @@ def add_index(instance_id, database_id):
499501
)
500502

501503
print("Waiting for operation to complete...")
502-
operation.result(120)
504+
operation.result(OPERATION_TIMEOUT_SECONDS)
503505

504506
print("Added the AlbumsByAlbumTitle index.")
505507

@@ -598,7 +600,7 @@ def add_storing_index(instance_id, database_id):
598600
)
599601

600602
print("Waiting for operation to complete...")
601-
operation.result(120)
603+
operation.result(OPERATION_TIMEOUT_SECONDS)
602604

603605
print("Added the AlbumsByAlbumTitle2 index.")
604606

@@ -651,7 +653,7 @@ def add_column(instance_id, database_id):
651653
)
652654

653655
print("Waiting for operation to complete...")
654-
operation.result(120)
656+
operation.result(OPERATION_TIMEOUT_SECONDS)
655657

656658
print("Added the MarketingBudget column.")
657659

@@ -816,7 +818,7 @@ def create_table_with_timestamp(instance_id, database_id):
816818
)
817819

818820
print("Waiting for operation to complete...")
819-
operation.result(120)
821+
operation.result(OPERATION_TIMEOUT_SECONDS)
820822

821823
print(
822824
"Created Performances table on database {} on instance {}".format(
@@ -871,7 +873,7 @@ def add_timestamp_column(instance_id, database_id):
871873
)
872874

873875
print("Waiting for operation to complete...")
874-
operation.result(120)
876+
operation.result(OPERATION_TIMEOUT_SECONDS)
875877

876878
print(
877879
'Altered table "Albums" on database {} on instance {}.'.format(
@@ -964,7 +966,7 @@ def add_numeric_column(instance_id, database_id):
964966
operation = database.update_ddl(["ALTER TABLE Venues ADD COLUMN Revenue NUMERIC"])
965967

966968
print("Waiting for operation to complete...")
967-
operation.result(120)
969+
operation.result(OPERATION_TIMEOUT_SECONDS)
968970

969971
print(
970972
'Altered table "Venues" on database {} on instance {}.'.format(
@@ -1564,7 +1566,7 @@ def create_table_with_datatypes(instance_id, database_id):
15641566
)
15651567

15661568
print("Waiting for operation to complete...")
1567-
operation.result(120)
1569+
operation.result(OPERATION_TIMEOUT_SECONDS)
15681570

15691571
print(
15701572
"Created Venues table on database {} on instance {}".format(

0 commit comments

Comments
 (0)