Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,10 @@ from google.iam.v1 import policy_pb2 # type: ignore
{% endfilter %}
{{ shared_macros.add_google_api_core_version_header_import(service.version) }}

{% if api.all_method_settings.values()|map(attribute="auto_populated_fields", default=[])|list %}
_UUID4_RE = re.compile(r"{{ uuid4_re }}")
{% endif %}

{% with uuid4_re = "[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}" %}

def client_cert_source_callback():
return b"cert bytes", b"key bytes"
Expand Down Expand Up @@ -692,7 +694,7 @@ def test_{{ method_name }}_empty_call():
{% if method_settings is not none %}
{% for auto_populated_field in method_settings.auto_populated_fields %}
# Ensure that the uuid4 field is set according to AIP 4235
assert re.fullmatch(r"{{ uuid4_re }}", args[0].{{ auto_populated_field }})
assert _UUID4_RE.match(args[0].{{ auto_populated_field }})
# clear UUID field so that the check below succeeds
args[0].{{ auto_populated_field }} = None
{% endfor %}
Expand Down Expand Up @@ -730,7 +732,7 @@ def test_{{ method_name }}_non_empty_request_with_auto_populated_field():
{% if method_settings is not none %}
{% for auto_populated_field in method_settings.auto_populated_fields %}
# Ensure that the uuid4 field is set according to AIP 4235
assert re.fullmatch(r"{{ uuid4_re }}", args[0].{{ auto_populated_field }})
assert _UUID4_RE.match(args[0].{{ auto_populated_field }})
# clear UUID field so that the check below succeeds
args[0].{{ auto_populated_field }} = None
{% endfor %}
Expand Down Expand Up @@ -2488,5 +2490,4 @@ def test_client_ctx():
pass
close.assert_called()

{% endwith %}{# uuid4_re #}
{% endblock %}
3 changes: 3 additions & 0 deletions packages/gapic-generator/gapic/generator/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ def __init__(self, opts: Options) -> None:
self._env.tests["str_field_pb"] = utils.is_str_field_pb
self._env.tests["msg_field_pb"] = utils.is_msg_field_pb

# Add global variables.
self._env.globals["uuid4_re"] = utils.UUID4_RE

self._sample_configs = opts.sample_configs

def get_response(self, api_schema: api.API, opts: Options) -> CodeGeneratorResponse:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ CRED_INFO_JSON = {
"principal": "service-account@example.com",
}
CRED_INFO_STRING = json.dumps(CRED_INFO_JSON)
{% if api.all_method_settings.values()|map(attribute="auto_populated_fields", default=[])|list %}
_UUID4_RE = re.compile(r"{{ uuid4_re }}")
{% endif %}


async def mock_async_gen(data, chunk_size=1):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def test_{{ method_name }}_non_empty_request_with_auto_populated_field():
{% if method_settings is not none %}
{% for auto_populated_field in method_settings.auto_populated_fields %}
# Ensure that the uuid4 field is set according to AIP 4235
assert re.fullmatch(r"{{ get_uuid4_re() }}", args[0].{{ auto_populated_field }})
assert _UUID4_RE.fullmatch(args[0].{{ auto_populated_field }})
request_msg.{{ auto_populated_field }} = args[0].{{ auto_populated_field }}
{% endfor %}
{% endif %}{# if method_settings is not none #}
Expand Down Expand Up @@ -1208,7 +1208,7 @@ def test_{{ method_name }}_rest_required_fields(request_type={{ method.input.ide
# Ensure that the uuid4 field is set according to AIP 4235
for i, (key, value) in enumerate(req.call_args.kwargs['params']):
if key == "{{ auto_populated_field|camel_case }}":
assert re.fullmatch(r"{{ get_uuid4_re() }}", value)
assert _UUID4_RE.match(value)
break

# Include {{ auto_populated_field|camel_case }} within expected_params with value mock.ANY
Expand Down Expand Up @@ -1565,7 +1565,7 @@ def test_{{ method_name }}_rest_no_http_options():
{% if method_settings is not none %}
{% for auto_populated_field in method_settings.auto_populated_fields %}
# Ensure that the uuid4 field is set according to AIP 4235
assert re.fullmatch(r"{{ get_uuid4_re() }}", args[0].{{ auto_populated_field }})
assert _UUID4_RE.fullmatch(args[0].{{ auto_populated_field }})
request_msg.{{ auto_populated_field }} = args[0].{{ auto_populated_field }}
{% endfor %}{# for auto_populated_field in method_settings.auto_populated_fields #}
{% endif %}{# if method_settings is not none #}
Expand Down Expand Up @@ -2196,7 +2196,7 @@ def test_initialize_client_w_{{transport_name}}():
{% endmacro %}{# empty_call_test #}

{% macro get_uuid4_re() -%}
[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}
{{ uuid4_re }}
{%- endmacro %}{# uuid_re #}

{% macro routing_parameter_test(service, api, transport, is_async) %}
Expand Down
2 changes: 2 additions & 0 deletions packages/gapic-generator/gapic/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from gapic.utils.code import nth
from gapic.utils.code import partition
from gapic.utils.code import make_private
from gapic.utils.constants import UUID4_RE
from gapic.utils.doc import doc
from gapic.utils.filename import to_valid_filename
from gapic.utils.filename import to_valid_module_name
Expand Down Expand Up @@ -52,5 +53,6 @@
"to_camel_case",
"to_valid_filename",
"to_valid_module_name",
"UUID4_RE",
"wrap",
)
16 changes: 16 additions & 0 deletions packages/gapic-generator/gapic/utils/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# The regex for a UUID4 as specified in AIP-4235.
UUID4_RE = r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}"
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
"principal": "service-account@example.com",
}
CRED_INFO_STRING = json.dumps(CRED_INFO_JSON)
_UUID4_RE = re.compile(r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}")


async def mock_async_gen(data, chunk_size=1):
Expand Down Expand Up @@ -1947,7 +1948,7 @@ def test_create_job_non_empty_request_with_auto_populated_field():
job_id='job_id_value',
)
# Ensure that the uuid4 field is set according to AIP 4235
assert re.fullmatch(r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}", args[0].request_id)
assert _UUID4_RE.fullmatch(args[0].request_id)
request_msg.request_id = args[0].request_id
assert args[0] == request_msg

Expand Down Expand Up @@ -2293,7 +2294,7 @@ def test_delete_job_non_empty_request_with_auto_populated_field():
name='name_value',
)
# Ensure that the uuid4 field is set according to AIP 4235
assert re.fullmatch(r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}", args[0].request_id)
assert _UUID4_RE.fullmatch(args[0].request_id)
request_msg.request_id = args[0].request_id
assert args[0] == request_msg

Expand Down Expand Up @@ -2606,7 +2607,7 @@ def test_cancel_job_non_empty_request_with_auto_populated_field():
name='name_value',
)
# Ensure that the uuid4 field is set according to AIP 4235
assert re.fullmatch(r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}", args[0].request_id)
assert _UUID4_RE.fullmatch(args[0].request_id)
request_msg.request_id = args[0].request_id
assert args[0] == request_msg

Expand Down Expand Up @@ -4204,7 +4205,7 @@ def test_create_job_rest_required_fields(request_type=storage_batch_operations.C
# Ensure that the uuid4 field is set according to AIP 4235
for i, (key, value) in enumerate(req.call_args.kwargs['params']):
if key == "requestId":
assert re.fullmatch(r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}", value)
assert _UUID4_RE.match(value)
break

# Include requestId within expected_params with value mock.ANY
Expand Down Expand Up @@ -4382,7 +4383,7 @@ def test_delete_job_rest_required_fields(request_type=storage_batch_operations.D
# Ensure that the uuid4 field is set according to AIP 4235
for i, (key, value) in enumerate(req.call_args.kwargs['params']):
if key == "requestId":
assert re.fullmatch(r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}", value)
assert _UUID4_RE.match(value)
break

# Include requestId within expected_params with value mock.ANY
Expand Down Expand Up @@ -4558,7 +4559,7 @@ def test_cancel_job_rest_required_fields(request_type=storage_batch_operations.C
# Ensure that the uuid4 field is set according to AIP 4235
for i, (key, value) in enumerate(req.call_args.kwargs['params']):
if key == "requestId":
assert re.fullmatch(r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}", value)
assert _UUID4_RE.match(value)
break

# Include requestId within expected_params with value mock.ANY
Expand Down Expand Up @@ -5193,7 +5194,7 @@ def test_create_job_empty_call_grpc():
_, args, _ = call.mock_calls[0]
request_msg = storage_batch_operations.CreateJobRequest()
# Ensure that the uuid4 field is set according to AIP 4235
assert re.fullmatch(r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}", args[0].request_id)
assert _UUID4_RE.fullmatch(args[0].request_id)
request_msg.request_id = args[0].request_id
assert args[0] == request_msg

Expand All @@ -5218,7 +5219,7 @@ def test_delete_job_empty_call_grpc():
_, args, _ = call.mock_calls[0]
request_msg = storage_batch_operations.DeleteJobRequest()
# Ensure that the uuid4 field is set according to AIP 4235
assert re.fullmatch(r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}", args[0].request_id)
assert _UUID4_RE.fullmatch(args[0].request_id)
request_msg.request_id = args[0].request_id
assert args[0] == request_msg

Expand All @@ -5243,7 +5244,7 @@ def test_cancel_job_empty_call_grpc():
_, args, _ = call.mock_calls[0]
request_msg = storage_batch_operations.CancelJobRequest()
# Ensure that the uuid4 field is set according to AIP 4235
assert re.fullmatch(r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}", args[0].request_id)
assert _UUID4_RE.fullmatch(args[0].request_id)
request_msg.request_id = args[0].request_id
assert args[0] == request_msg

Expand Down Expand Up @@ -5388,7 +5389,7 @@ async def test_create_job_empty_call_grpc_asyncio():
_, args, _ = call.mock_calls[0]
request_msg = storage_batch_operations.CreateJobRequest()
# Ensure that the uuid4 field is set according to AIP 4235
assert re.fullmatch(r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}", args[0].request_id)
assert _UUID4_RE.fullmatch(args[0].request_id)
request_msg.request_id = args[0].request_id
assert args[0] == request_msg

Expand All @@ -5415,7 +5416,7 @@ async def test_delete_job_empty_call_grpc_asyncio():
_, args, _ = call.mock_calls[0]
request_msg = storage_batch_operations.DeleteJobRequest()
# Ensure that the uuid4 field is set according to AIP 4235
assert re.fullmatch(r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}", args[0].request_id)
assert _UUID4_RE.fullmatch(args[0].request_id)
request_msg.request_id = args[0].request_id
assert args[0] == request_msg

Expand Down Expand Up @@ -5443,7 +5444,7 @@ async def test_cancel_job_empty_call_grpc_asyncio():
_, args, _ = call.mock_calls[0]
request_msg = storage_batch_operations.CancelJobRequest()
# Ensure that the uuid4 field is set according to AIP 4235
assert re.fullmatch(r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}", args[0].request_id)
assert _UUID4_RE.fullmatch(args[0].request_id)
request_msg.request_id = args[0].request_id
assert args[0] == request_msg

Expand Down Expand Up @@ -6695,7 +6696,7 @@ def test_create_job_empty_call_rest():
_, args, _ = call.mock_calls[0]
request_msg = storage_batch_operations.CreateJobRequest()
# Ensure that the uuid4 field is set according to AIP 4235
assert re.fullmatch(r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}", args[0].request_id)
assert _UUID4_RE.fullmatch(args[0].request_id)
request_msg.request_id = args[0].request_id
assert args[0] == request_msg

Expand All @@ -6719,7 +6720,7 @@ def test_delete_job_empty_call_rest():
_, args, _ = call.mock_calls[0]
request_msg = storage_batch_operations.DeleteJobRequest()
# Ensure that the uuid4 field is set according to AIP 4235
assert re.fullmatch(r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}", args[0].request_id)
assert _UUID4_RE.fullmatch(args[0].request_id)
request_msg.request_id = args[0].request_id
assert args[0] == request_msg

Expand All @@ -6743,7 +6744,7 @@ def test_cancel_job_empty_call_rest():
_, args, _ = call.mock_calls[0]
request_msg = storage_batch_operations.CancelJobRequest()
# Ensure that the uuid4 field is set according to AIP 4235
assert re.fullmatch(r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}", args[0].request_id)
assert _UUID4_RE.fullmatch(args[0].request_id)
request_msg.request_id = args[0].request_id
assert args[0] == request_msg

Expand Down
Loading