Skip to content

Commit 71b2f4e

Browse files
committed
feat: delegate request-id setup to public method_helpers
Updates generator templates and goldens to import public method_helpers from google-api-core gapic_v1 and call setup_request_id helper. Removes duplicate setup_request_id test logic from generated client unit tests.
1 parent 1ef0340 commit 71b2f4e

4 files changed

Lines changed: 6 additions & 194 deletions

File tree

packages/gapic-generator/gapic/templates/%namespace/%name_%version/%sub/services/%service/client.py.j2

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ from google.api_core import exceptions as core_exceptions
3030
from google.api_core import extended_operation
3131
{% endif %}
3232
from google.api_core import gapic_v1
33+
{% if api.all_method_settings.values()|map(attribute="auto_populated_fields", default=[])|select|list %}
34+
from google.api_core.gapic_v1 import method_helpers
35+
{% endif %}
3336
from google.api_core import retry as retries
3437
from google.auth import credentials as ga_credentials # type: ignore
3538
from google.auth.transport import mtls # type: ignore
@@ -463,26 +466,7 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta):
463466
field_name (str): The name of the field to populate.
464467
is_proto3_optional (bool): Whether the field is proto3 optional.
465468
"""
466-
if isinstance(request, dict):
467-
if is_proto3_optional:
468-
if field_name not in request:
469-
request[field_name] = str(uuid.uuid4())
470-
elif not request.get(field_name):
471-
request[field_name] = str(uuid.uuid4())
472-
return
473-
474-
if is_proto3_optional:
475-
try:
476-
# Pure protobuf messages
477-
if not request.HasField(field_name):
478-
setattr(request, field_name, str(uuid.uuid4()))
479-
except (AttributeError, ValueError):
480-
# Proto-plus messages or other objects
481-
if field_name not in request:
482-
setattr(request, field_name, str(uuid.uuid4()))
483-
else:
484-
if not getattr(request, field_name):
485-
setattr(request, field_name, str(uuid.uuid4()))
469+
method_helpers.setup_request_id(request, field_name, is_proto3_optional)
486470
{% endif %}
487471

488472
def _add_cred_info_for_auth_errors(

packages/gapic-generator/gapic/templates/tests/unit/gapic/%name_%version/%sub/test_%service.py.j2

Lines changed: 0 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -434,84 +434,6 @@ def test__add_cred_info_for_auth_errors_no_get_cred_info(error_code):
434434
client._add_cred_info_for_auth_errors(error)
435435
assert error.details == []
436436

437-
{% if api.all_method_settings.values()|map(attribute="auto_populated_fields", default=[])|select|list %}
438-
def test__setup_request_id():
439-
class MockRequest:
440-
def __init__(self, **kwargs):
441-
for k, v in kwargs.items():
442-
setattr(self, k, v)
443-
def __contains__(self, key):
444-
return hasattr(self, key)
445-
446-
class MockProtoRequest:
447-
def __init__(self, **kwargs):
448-
for k, v in kwargs.items():
449-
setattr(self, k, v)
450-
def HasField(self, key):
451-
return hasattr(self, key)
452-
453-
# Test with proto3 optional field not in request
454-
request = MockRequest()
455-
{{ service.client_name }}._setup_request_id(request, "request_id", True)
456-
assert re.match(r"{{ test_macros.get_uuid4_re() }}", request.request_id)
457-
458-
# Test with proto3 optional field already in request
459-
request = MockRequest(request_id="already_set")
460-
{{ service.client_name }}._setup_request_id(request, "request_id", True)
461-
assert request.request_id == "already_set"
462-
463-
# Test with non-proto3 optional field empty
464-
request = MockRequest(request_id="")
465-
{{ service.client_name }}._setup_request_id(request, "request_id", False)
466-
assert re.match(r"{{ test_macros.get_uuid4_re() }}", request.request_id)
467-
468-
# Test with non-proto3 optional field already set
469-
request = MockRequest(request_id="already_set")
470-
{{ service.client_name }}._setup_request_id(request, "request_id", False)
471-
assert request.request_id == "already_set"
472-
473-
# Test with proto3 optional field not in request (MockProtoRequest)
474-
request = MockProtoRequest()
475-
{{ service.client_name }}._setup_request_id(request, "request_id", True)
476-
assert re.match(r"{{ test_macros.get_uuid4_re() }}", request.request_id)
477-
478-
# Test with proto3 optional field already in request (MockProtoRequest)
479-
request = MockProtoRequest(request_id="already_set")
480-
{{ service.client_name }}._setup_request_id(request, "request_id", True)
481-
assert request.request_id == "already_set"
482-
483-
# Test with ValueError
484-
class MockValueErrorRequest:
485-
def HasField(self, key):
486-
raise ValueError("Mismatched field")
487-
def __contains__(self, key):
488-
return hasattr(self, key)
489-
490-
request = MockValueErrorRequest()
491-
{{ service.client_name }}._setup_request_id(request, "request_id", True)
492-
assert re.match(r"{{ test_macros.get_uuid4_re() }}", request.request_id)
493-
494-
# Test with dict and proto3 optional field not in request
495-
request = {}
496-
{{ service.client_name }}._setup_request_id(request, "request_id", True)
497-
assert re.match(r"{{ test_macros.get_uuid4_re() }}", request["request_id"])
498-
499-
# Test with dict and proto3 optional field already in request
500-
request = {"request_id": "already_set"}
501-
{{ service.client_name }}._setup_request_id(request, "request_id", True)
502-
assert request["request_id"] == "already_set"
503-
504-
# Test with dict and non-proto3 optional field empty
505-
request = {"request_id": ""}
506-
{{ service.client_name }}._setup_request_id(request, "request_id", False)
507-
assert re.match(r"{{ test_macros.get_uuid4_re() }}", request["request_id"])
508-
509-
# Test with dict and non-proto3 optional field already set
510-
request = {"request_id": "already_set"}
511-
{{ service.client_name }}._setup_request_id(request, "request_id", False)
512-
assert request["request_id"] == "already_set"
513-
514-
{% endif %}
515437
@pytest.mark.parametrize("client_class,transport_name", [
516438
{% if 'grpc' in opts.transport %}
517439
({{ service.client_name }}, "grpc"),

packages/gapic-generator/tests/integration/goldens/storagebatchoperations/google/cloud/storagebatchoperations_v1/services/storage_batch_operations/client.py

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from google.api_core import client_options as client_options_lib
2929
from google.api_core import exceptions as core_exceptions
3030
from google.api_core import gapic_v1
31+
from google.api_core.gapic_v1 import method_helpers
3132
from google.api_core import retry as retries
3233
from google.auth import credentials as ga_credentials # type: ignore
3334
from google.auth.transport import mtls # type: ignore
@@ -480,26 +481,7 @@ def _setup_request_id(request, field_name: str, is_proto3_optional: bool):
480481
field_name (str): The name of the field to populate.
481482
is_proto3_optional (bool): Whether the field is proto3 optional.
482483
"""
483-
if isinstance(request, dict):
484-
if is_proto3_optional:
485-
if field_name not in request:
486-
request[field_name] = str(uuid.uuid4())
487-
elif not request.get(field_name):
488-
request[field_name] = str(uuid.uuid4())
489-
return
490-
491-
if is_proto3_optional:
492-
try:
493-
# Pure protobuf messages
494-
if not request.HasField(field_name):
495-
setattr(request, field_name, str(uuid.uuid4()))
496-
except (AttributeError, ValueError):
497-
# Proto-plus messages or other objects
498-
if field_name not in request:
499-
setattr(request, field_name, str(uuid.uuid4()))
500-
else:
501-
if not getattr(request, field_name):
502-
setattr(request, field_name, str(uuid.uuid4()))
484+
method_helpers.setup_request_id(request, field_name, is_proto3_optional)
503485

504486
def _add_cred_info_for_auth_errors(
505487
self,

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

Lines changed: 0 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -351,82 +351,6 @@ def test__add_cred_info_for_auth_errors_no_get_cred_info(error_code):
351351
client._add_cred_info_for_auth_errors(error)
352352
assert error.details == []
353353

354-
def test__setup_request_id():
355-
class MockRequest:
356-
def __init__(self, **kwargs):
357-
for k, v in kwargs.items():
358-
setattr(self, k, v)
359-
def __contains__(self, key):
360-
return hasattr(self, key)
361-
362-
class MockProtoRequest:
363-
def __init__(self, **kwargs):
364-
for k, v in kwargs.items():
365-
setattr(self, k, v)
366-
def HasField(self, key):
367-
return hasattr(self, key)
368-
369-
# Test with proto3 optional field not in request
370-
request = MockRequest()
371-
StorageBatchOperationsClient._setup_request_id(request, "request_id", True)
372-
assert re.match(r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}", request.request_id)
373-
374-
# Test with proto3 optional field already in request
375-
request = MockRequest(request_id="already_set")
376-
StorageBatchOperationsClient._setup_request_id(request, "request_id", True)
377-
assert request.request_id == "already_set"
378-
379-
# Test with non-proto3 optional field empty
380-
request = MockRequest(request_id="")
381-
StorageBatchOperationsClient._setup_request_id(request, "request_id", False)
382-
assert re.match(r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}", request.request_id)
383-
384-
# Test with non-proto3 optional field already set
385-
request = MockRequest(request_id="already_set")
386-
StorageBatchOperationsClient._setup_request_id(request, "request_id", False)
387-
assert request.request_id == "already_set"
388-
389-
# Test with proto3 optional field not in request (MockProtoRequest)
390-
request = MockProtoRequest()
391-
StorageBatchOperationsClient._setup_request_id(request, "request_id", True)
392-
assert re.match(r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}", request.request_id)
393-
394-
# Test with proto3 optional field already in request (MockProtoRequest)
395-
request = MockProtoRequest(request_id="already_set")
396-
StorageBatchOperationsClient._setup_request_id(request, "request_id", True)
397-
assert request.request_id == "already_set"
398-
399-
# Test with ValueError
400-
class MockValueErrorRequest:
401-
def HasField(self, key):
402-
raise ValueError("Mismatched field")
403-
def __contains__(self, key):
404-
return hasattr(self, key)
405-
406-
request = MockValueErrorRequest()
407-
StorageBatchOperationsClient._setup_request_id(request, "request_id", True)
408-
assert re.match(r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}", request.request_id)
409-
410-
# Test with dict and proto3 optional field not in request
411-
request = {}
412-
StorageBatchOperationsClient._setup_request_id(request, "request_id", True)
413-
assert re.match(r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}", request["request_id"])
414-
415-
# Test with dict and proto3 optional field already in request
416-
request = {"request_id": "already_set"}
417-
StorageBatchOperationsClient._setup_request_id(request, "request_id", True)
418-
assert request["request_id"] == "already_set"
419-
420-
# Test with dict and non-proto3 optional field empty
421-
request = {"request_id": ""}
422-
StorageBatchOperationsClient._setup_request_id(request, "request_id", False)
423-
assert re.match(r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}", request["request_id"])
424-
425-
# Test with dict and non-proto3 optional field already set
426-
request = {"request_id": "already_set"}
427-
StorageBatchOperationsClient._setup_request_id(request, "request_id", False)
428-
assert request["request_id"] == "already_set"
429-
430354
@pytest.mark.parametrize("client_class,transport_name", [
431355
(StorageBatchOperationsClient, "grpc"),
432356
(StorageBatchOperationsAsyncClient, "grpc_asyncio"),

0 commit comments

Comments
 (0)