Skip to content

Commit 6eb89f7

Browse files
committed
fix(generator): address PR review comments for request-id centralization and clean up allowed private templates
1 parent 82aa10c commit 6eb89f7

6 files changed

Lines changed: 60 additions & 73 deletions

File tree

packages/gapic-generator/gapic/generator/generator.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@
3737
from google.protobuf.compiler.plugin_pb2 import CodeGeneratorResponse
3838

3939

40+
ALLOWED_PRIVATE_TEMPLATES = (
41+
"__init__.py.j2",
42+
"_compat.py.j2",
43+
)
44+
45+
4046
class Generator:
4147
"""A protoc code generator for client libraries.
4248
@@ -118,9 +124,9 @@ def get_response(self, api_schema: api.API, opts: Options) -> CodeGeneratorRespo
118124
# and instead of iterating over it/them, we iterate over samples
119125
# and plug those into the template.
120126
for template_name in client_templates:
121-
# Quick check: Skip "private" templates.
127+
# Quick check: Skip "private" templates except explicitly allowed ones.
122128
filename = template_name.split("/")[-1]
123-
if filename.startswith("_") and filename not in ("__init__.py.j2", "_compat.py.j2"):
129+
if filename.startswith("_") and filename not in ALLOWED_PRIVATE_TEMPLATES:
124130
continue
125131

126132
# Append to the output files dictionary.
@@ -266,9 +272,6 @@ def _render_template(
266272
if not opts.metadata and template_name.endswith("gapic_metadata.json.j2"):
267273
return answer
268274

269-
270-
271-
272275
# Disables generation of an unversioned Python package for this client
273276
# library. This means that the module names will need to be versioned in
274277
# import statements. For example `import google.cloud.library_v2` instead

packages/gapic-generator/gapic/templates/%namespace/%name_%version/%sub/_compat.py.j2

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ except ImportError:
142142

143143

144144
try:
145-
from google.api_core.gapic_v1.request import setup_request_id # type: ignore
145+
from google.api_core.gapic_v1.requests import setup_request_id # type: ignore
146146
except ImportError:
147147
# TODO(https://github.com/googleapis/google-cloud-python/issues/17813): Remove this fallback when google-api-core >= 2.26.0 is the minimum required version.
148148
def setup_request_id(request, field_name: str, is_proto3_optional: bool):
@@ -153,10 +153,11 @@ except ImportError:
153153
field_name (str): The name of the field to populate.
154154
is_proto3_optional (bool): Whether the field is proto3 optional.
155155
"""
156-
request_id_val = str(uuid.uuid4())
157156
if request is None:
158157
return
159158

159+
request_id_val = str(uuid.uuid4())
160+
160161
if isinstance(request, dict):
161162
if is_proto3_optional:
162163
if field_name not in request or request[field_name] is None:
@@ -172,6 +173,13 @@ except ImportError:
172173
setattr(request, field_name, request_id_val)
173174
except (AttributeError, ValueError):
174175
# Proto-plus messages or other objects
176+
if hasattr(request, "_pb"):
177+
try:
178+
if not request._pb.HasField(field_name):
179+
setattr(request, field_name, request_id_val)
180+
return
181+
except (AttributeError, ValueError):
182+
pass
175183
if getattr(request, field_name, None) is None:
176184
setattr(request, field_name, request_id_val)
177185
else:

packages/gapic-generator/noxfile.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,9 @@ def __call__(self, frag):
150150
constraints_path = str(
151151
f"{tmp_dir}/testing/constraints-{self.session.python}.txt"
152152
)
153-
self.session.install(tmp_dir, "-e", ".", "-qqq", "-r", constraints_path)
153+
self.session.install(tmp_dir, "-e", ".", "--no-build-isolation", "-qqq", "-r", constraints_path)
154+
155+
self.session.install("-e", "../google-api-core", "--no-build-isolation", "-qqq")
154156

155157
# Run the fragment's generated unit tests.
156158
# Don't bother parallelizing them: we already parallelize
@@ -246,6 +248,9 @@ def showcase_library(
246248

247249
# Install gapic-generator-python
248250
session.install("-e", ".")
251+
# Install local editable google-api-core for monorepo development testing.
252+
# On Python 3.10 below, google-api-core<2.28 is installed to validate
253+
# fallback compatibility against released versions of google-api-core.
249254
session.install("-e", "../google-api-core")
250255

251256
# Install grpcio-tools for protoc
@@ -375,12 +380,14 @@ def showcase_library(
375380
)
376381
extras = "[async_rest]"
377382

378-
session.install("-e", f"{tmp_dir}{extras}", "-r", constraints_path)
383+
session.install("-e", f"{tmp_dir}{extras}", "--no-build-isolation", "-r", constraints_path)
379384
else:
380385
# The ads templates do not have constraints files.
381386
# See https://github.com/googleapis/gapic-generator-python/issues/1788
382387
# Install the library without a constraints file.
383-
session.install("-e", tmp_dir)
388+
session.install("-e", tmp_dir, "--no-build-isolation")
389+
390+
session.install("-e", "../google-api-core", "--no-build-isolation")
384391

385392
yield tmp_dir
386393

packages/gapic-generator/tests/integration/goldens/storagebatchoperations/google/cloud/storagebatchoperations_v1/_compat.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import uuid
1818

1919
try:
20-
from google.api_core.gapic_v1.request import setup_request_id # type: ignore
20+
from google.api_core.gapic_v1.requests import setup_request_id # type: ignore
2121
except ImportError:
2222
# TODO(https://github.com/googleapis/google-cloud-python/issues/17813): Remove this fallback when google-api-core >= 2.26.0 is the minimum required version.
2323
def setup_request_id(request, field_name: str, is_proto3_optional: bool):
@@ -48,7 +48,14 @@ def setup_request_id(request, field_name: str, is_proto3_optional: bool):
4848
setattr(request, field_name, request_id_val)
4949
except (AttributeError, ValueError):
5050
# Proto-plus messages or other objects
51-
if not getattr(request, field_name, None):
51+
if hasattr(request, "_pb"):
52+
try:
53+
if not request._pb.HasField(field_name):
54+
setattr(request, field_name, request_id_val)
55+
return
56+
except (AttributeError, ValueError):
57+
pass
58+
if getattr(request, field_name, None) is None:
5259
setattr(request, field_name, request_id_val)
5360
else:
5461
if not getattr(request, field_name, None):

packages/gapic-generator/tests/integration/goldens/storagebatchoperations/tests/unit/gapic/storagebatchoperations_v1/test__compat.py

Lines changed: 0 additions & 57 deletions
This file was deleted.

packages/gapic-generator/tests/unit/generator/test_generator.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,6 @@ def test_get_response_ignores_private_files():
117117
list_templates.return_value = [
118118
"foo/bar/baz.py.j2",
119119
"foo/bar/_base.py.j2",
120-
"foo/bar/__init__.py.j2",
121-
"foo/bar/_compat.py.j2",
122120
"molluscs/squid/sample.py.j2",
123121
]
124122
with mock.patch.object(jinja2.Environment, "get_template") as get_template:
@@ -130,13 +128,34 @@ def test_get_response_ignores_private_files():
130128
get_template.assert_has_calls(
131129
[
132130
mock.call("molluscs/squid/sample.py.j2"),
131+
mock.call("foo/bar/baz.py.j2"),
132+
]
133+
)
134+
assert len(cgr.file) == 1
135+
136+
137+
def test_get_response_renders_allowed_private_templates():
138+
generator_obj = make_generator()
139+
with mock.patch.object(jinja2.FileSystemLoader, "list_templates") as list_templates:
140+
list_templates.return_value = [
141+
"foo/bar/__init__.py.j2",
142+
"foo/bar/_compat.py.j2",
143+
"foo/bar/_ignored.py.j2",
144+
]
145+
with mock.patch.object(jinja2.Environment, "get_template") as get_template:
146+
get_template.return_value = jinja2.Template("I am a template result.")
147+
cgr = generator_obj.get_response(
148+
api_schema=make_api(), opts=Options.build("")
149+
)
150+
list_templates.assert_called_once()
151+
get_template.assert_has_calls(
152+
[
133153
mock.call("foo/bar/__init__.py.j2"),
134154
mock.call("foo/bar/_compat.py.j2"),
135-
mock.call("foo/bar/baz.py.j2"),
136155
],
137156
any_order=True,
138157
)
139-
assert len(cgr.file) == 3
158+
assert len(cgr.file) == 2
140159

141160

142161
def test_get_response_fails_invalid_file_paths():

0 commit comments

Comments
 (0)