-
Notifications
You must be signed in to change notification settings - Fork 1.7k
chore(generator): move setup_request_id into compat layer
#17739
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
hebaalazzeh
wants to merge
94
commits into
main
Choose a base branch
from
feat/gapic-generator-centralization-request-id
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
94 commits
Select commit
Hold shift + click to select a range
79f3668
feat(api-core): move request-id auto-population logic to gapic_v1 pub…
hebaalazzeh 62fbcc8
refactor(api-core): rename gapic_v1.method_helpers to gapic_v1.reques…
hebaalazzeh 20adea6
chore: address PR review comments for gapic centralization request ID
hebaalazzeh f03ac7c
feat(api-core): move request-id auto-population logic to gapic_v1 pub…
hebaalazzeh 2cc27b5
feat: delegate request-id setup to public method_helpers
hebaalazzeh 9c2121c
refactor: use request module instead of method_helpers in gapic-gener…
hebaalazzeh dbc7307
refactor(api-core): rename gapic_v1.method_helpers to gapic_v1.reques…
hebaalazzeh 5f1b721
chore: address PR review comments for gapic centralization request ID
hebaalazzeh 99cee8e
chore: remove private _setup_request_id and call setup_request_id hel…
hebaalazzeh 4ff1910
test(api-core): update UUID regex in test_request.py
hebaalazzeh 77f97c8
refactor(api-core): rename request.py to requests.py for consistency
hebaalazzeh 7fdf94e
Merge branch 'feat/gapic-centralization-api-core-request-id' into fea…
hebaalazzeh 37ad06f
refactor(generator): update templates and goldens to use requests ins…
hebaalazzeh b9e2c62
fix(api-core): handle dictionary requests with None value in setup_re…
hebaalazzeh 6bb65bc
merge branch 'feat/gapic-centralization-api-core-request-id' into fea…
hebaalazzeh 0482ae6
fix(api-core): remove redundant request.py and test_request.py, sort …
hebaalazzeh 31ae5ec
Merge remote-tracking branch 'origin/main' into feat/gapic-generator-…
hebaalazzeh 2001c79
feat(generator): add _compat.py fallback for setup_request_id
hebaalazzeh 2d1d2a5
fix(generator): add type ignore to requests import in compat template…
hebaalazzeh 9e169f8
fix(generator): add coverage pragma comments for fallback path in com…
hebaalazzeh 5af5222
Merge remote-tracking branch 'origin/main' into feat/gapic-generator-…
hebaalazzeh 6ef6dd4
Merge remote-tracking branch 'origin/main' into feat/gapic-generator-…
hebaalazzeh 61aaabb
chore(generator): update golden client.py files with setup_request_id…
hebaalazzeh 0b2ceb2
fix(generator): add utf-8 coding header to _compat.py.j2 template
hebaalazzeh 3204cea
chore(generator): update storagebatchoperations client.py and async_c…
hebaalazzeh 3e6b78c
refactor(generator): optimize setup_request_id uuid creation and link…
hebaalazzeh 1e6b56e
docs(generator): update TODO issue link to #17813 in _compat.py
hebaalazzeh ea8d263
chore: trigger Kokoro system tests build rerun
hebaalazzeh 8e9f505
fix(generator): add pragma no cover to setup_request_id definition in…
hebaalazzeh 142d337
fix(generator): add module level pragma no cover to _compat.py to pre…
hebaalazzeh e5f8e13
fix(generator): only generate _compat.py if API schema contains auto_…
hebaalazzeh 905d2b1
fix(generator): fix proto-plus field check in setup_request_id fallback
hebaalazzeh 7b7668c
fix(generator): revert goldens without auto_populated_fields and fix …
hebaalazzeh 536a20e
fix(generator): remove encoding and pragma no cover from _compat.py h…
hebaalazzeh a8105ff
fix(generator): remove unused get_uuid4_re macro
hebaalazzeh e243bbd
fix(generator): update fallback proto-plus check to exactly match api…
hebaalazzeh 926eb3c
fix(generator): rename requests import to request to match api-core
hebaalazzeh 22d569d
fix(generator): fix broken diff in client.py and duplicate wrapper in…
hebaalazzeh c4eb2d9
test(generator): add tests for _compat.py fallback
hebaalazzeh ebc6bd9
fix(generator): update storagebatchoperations goldens to reflect setu…
hebaalazzeh eb08c77
fix(generator): add storagebatchoperations goldens missing files
hebaalazzeh e052b61
fix(generator): address remaining PR review comments
hebaalazzeh 44e43ce
fix(generator): always generate _compat.py and remove downstream unit…
hebaalazzeh 6f07478
fix(generator): use unified _compat.py.j2
hebaalazzeh 82aa10c
fix(generator): install local google-api-core in nox test sessions
hebaalazzeh 6eb89f7
fix(generator): address PR review comments for request-id centralizat…
hebaalazzeh a25e3fb
docs(templates): add explanatory comment for has_auto_populated_field…
hebaalazzeh 9770a1e
refactor(schema): encapsulate has_auto_populated_fields on Service wr…
hebaalazzeh e09ddec
chore(generator): remove unnecessary session.install('-e', '../google…
hebaalazzeh e047593
test(schema): add unit test for Service.has_auto_populated_fields to …
hebaalazzeh f813e56
docs(generator): clarify lower-bound google-api-core version comment …
hebaalazzeh 0aa48cd
docs(templates): clarify google-api-core version comment in _compat.p…
hebaalazzeh 4f6baaa
feat(templates): generate _compat.py for all integration test goldens
hebaalazzeh c5218d8
fix(templates): resolve UndefinedError by moving auto_populated_field…
hebaalazzeh 4709121
fix(templates): fix setup_request_id import module name and add pragm…
hebaalazzeh dbd4f5f
feat(templates): remove pragmas from _compat.py and add test_compat.p…
hebaalazzeh 5b77291
fix(test): update test_compat template and goldens for complete branc…
hebaalazzeh 7a22cc3
fix(coverage): add # pragma: NO COVER to compatibility fallback block…
hebaalazzeh f454c14
ci: add retry flags to curl commands in gapic-generator-tests workflow
hebaalazzeh fd17594
Merge origin/main into feat/gapic-generator-centralization-request-id
hebaalazzeh 7fbb8f8
fix(compat): add type annotations and ignores to _compat template and…
hebaalazzeh 022f2ad
fix(coverage): add test cases for _pb proto-plus requests in google-a…
hebaalazzeh 0dc81e3
fix(generator): add --no-deps when installing local google-api-core i…
hebaalazzeh 4a279f2
fix(generator): type annotate self._client_options and update workflo…
hebaalazzeh ee9cd96
chore(generator): revert unrelated golden files to match origin/main
hebaalazzeh 77a80a8
chore(generator): revert setup.py and WORKSPACE changes
hebaalazzeh 1919ee2
chore(ci): revert gapic-generator-tests.yml to origin/main
hebaalazzeh e3b439f
chore(generator): clean up test_service.py and noxfile.py
hebaalazzeh 0e5ebca
fix(generator): restore noxfile.py and add local google-api-core inst…
hebaalazzeh fa8fbae
fix(generator): fix import group formatting in _compat.py template an…
hebaalazzeh 4b50876
chore(generator): restore get_uuid4_re macro in test_macros.j2
hebaalazzeh 86352b4
chore(api-core): revert requests.py and test_requests.py to origin/main
hebaalazzeh ddacf0d
chore(generator): remove unused get_uuid4_re macro from test_macros.j2
hebaalazzeh 492bf63
fix(generator): pass MYPY_CONFIG_FILE to mypy in showcase_mypy session
hebaalazzeh 09bea02
fix(generator): add --no-build-isolation when installing local google…
hebaalazzeh b7577b2
fix(generator): remove --no-build-isolation and specify package-data …
hebaalazzeh 0055127
fix(generator): update self._client_options in golden client.py files…
hebaalazzeh d0b42c8
ci: trigger Bazel integration test check for goldens
hebaalazzeh 8dbac4c
chore: revert google-api-core pyproject.toml edit
hebaalazzeh dd49e39
chore(generator): revert noxfile.py mypy command and restore test_gen…
hebaalazzeh 30199d5
wip
hebaalazzeh dca70f5
wip
hebaalazzeh 64d4933
Merge branch 'main' into feat/gapic-generator-centralization-request-id
hebaalazzeh 9ef2569
Merge branch 'main' into feat/gapic-generator-centralization-request-id
hebaalazzeh 4ee805e
revert noxfile
hebaalazzeh 0012d51
fix compat layer
hebaalazzeh adf2e80
update goldens
hebaalazzeh 99f66c8
Merge branch 'main' into feat/gapic-generator-centralization-request-id
hebaalazzeh 20af454
clean up
hebaalazzeh 430cf9d
clean up
hebaalazzeh 0433a86
revert test generator
hebaalazzeh f8a5b9e
clean up test service
hebaalazzeh c892809
revert change to test service
hebaalazzeh 1df077f
revert whitespace
hebaalazzeh File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -12,4 +12,53 @@ falling back to the local implementation if not present. #} | |||||||
| {# TODO(https://github.com/googleapis/google-cloud-python/issues/17883): | ||||||||
| Backfill compatibility functions being removed from the client layer. #} | ||||||||
|
|
||||||||
| from typing import Union | ||||||||
| import uuid | ||||||||
|
|
||||||||
| import google.protobuf.message | ||||||||
|
|
||||||||
|
|
||||||||
| def setup_request_id( | ||||||||
| request: Union[google.protobuf.message.Message, dict, None], | ||||||||
| field_name: str, | ||||||||
| is_proto3_optional: bool, | ||||||||
| ) -> None: | ||||||||
| """Populate a UUID4 field in the request if it is not already set. | ||||||||
|
|
||||||||
| This helper is used to ensure request idempotency by automatically | ||||||||
| generating a unique identifier (such as `request_id`) for requests | ||||||||
| that support it. If a request is retried, the same identifier can be | ||||||||
| sent on subsequent retries, allowing the server to recognize the retried | ||||||||
| request and prevent duplicate processing (e.g., creating duplicate | ||||||||
| resources). | ||||||||
|
|
||||||||
| Args: | ||||||||
| request (Union[google.protobuf.message.Message, dict]): The | ||||||||
| request object. | ||||||||
| field_name (str): The name of the field to populate. | ||||||||
| is_proto3_optional (bool): Whether the field is proto3 optional. | ||||||||
| """ | ||||||||
| if request is None: | ||||||||
| return | ||||||||
|
|
||||||||
| if isinstance(request, dict): | ||||||||
| if is_proto3_optional: | ||||||||
| if field_name not in request or request[field_name] is None: | ||||||||
| request[field_name] = str(uuid.uuid4()) | ||||||||
| elif not request.get(field_name): | ||||||||
| request[field_name] = str(uuid.uuid4()) | ||||||||
| return | ||||||||
|
|
||||||||
| if is_proto3_optional: | ||||||||
| try: | ||||||||
| # Pure protobuf messages | ||||||||
| if not request.HasField(field_name): | ||||||||
| setattr(request, field_name, str(uuid.uuid4())) | ||||||||
| except (AttributeError, ValueError): | ||||||||
| # Proto-plus messages or other objects | ||||||||
| if not getattr(request, field_name, None): | ||||||||
| setattr(request, field_name, str(uuid.uuid4())) | ||||||||
| else: | ||||||||
| if not getattr(request, field_name, None): | ||||||||
| setattr(request, field_name, str(uuid.uuid4())) | ||||||||
| {% endblock %} | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -9,4 +9,91 @@ google-api-core has the functions in `_compat.py.j2`. #} | |||||||
| {# TODO(https://github.com/googleapis/google-cloud-python/issues/17883): | ||||||||
| Backfill compatibility functions tests being removed from the client layer. #} | ||||||||
|
|
||||||||
|
|
||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| import re | ||||||||
| import pytest | ||||||||
|
|
||||||||
| {% set package_path = api.naming.module_namespace|join('.') + "." + api.naming.versioned_module_name %} | ||||||||
| from {{package_path}}._compat import setup_request_id | ||||||||
|
|
||||||||
| class MockRequest: | ||||||||
| def __init__(self, **kwargs): | ||||||||
| for k, v in kwargs.items(): | ||||||||
| setattr(self, k, v) | ||||||||
|
|
||||||||
| def __contains__(self, key): | ||||||||
| return hasattr(self, key) | ||||||||
|
|
||||||||
|
|
||||||||
| class MockProtoRequest: | ||||||||
| def __init__(self, **kwargs): | ||||||||
| for k, v in kwargs.items(): | ||||||||
| setattr(self, k, v) | ||||||||
|
|
||||||||
| def HasField(self, key): | ||||||||
| return hasattr(self, key) | ||||||||
|
|
||||||||
|
|
||||||||
| class MockValueErrorRequest: | ||||||||
| def HasField(self, key): | ||||||||
| raise ValueError("Mismatched field") | ||||||||
|
|
||||||||
| def __contains__(self, key): | ||||||||
| return hasattr(self, key) | ||||||||
|
|
||||||||
| UUID_REGEX = r"[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}" | ||||||||
|
|
||||||||
| @pytest.mark.parametrize( | ||||||||
| "request_obj, is_proto3_optional, expected", | ||||||||
| [ | ||||||||
| (MockRequest(), True, "uuid"), | ||||||||
| (MockRequest(request_id="already_set"), True, "already_set"), | ||||||||
| (MockRequest(request_id=""), False, "uuid"), | ||||||||
| (MockRequest(request_id="already_set"), False, "already_set"), | ||||||||
| (MockProtoRequest(), True, "uuid"), | ||||||||
| (MockProtoRequest(request_id="already_set"), True, "already_set"), | ||||||||
| (MockValueErrorRequest(), True, "uuid"), | ||||||||
| ({}, True, "uuid"), | ||||||||
| ({"request_id": None}, True, "uuid"), | ||||||||
| ({"request_id": "already_set"}, True, "already_set"), | ||||||||
| ({"request_id": ""}, False, "uuid"), | ||||||||
| ({"request_id": None}, False, "uuid"), | ||||||||
| ({"request_id": "already_set"}, False, "already_set"), | ||||||||
| (None, True, "none"), | ||||||||
| ], | ||||||||
| ids=[ | ||||||||
| "proto3_optional_not_in_request", | ||||||||
| "proto3_optional_already_in_request", | ||||||||
| "non_proto3_optional_empty", | ||||||||
| "non_proto3_optional_already_set", | ||||||||
| "proto3_optional_not_in_request_proto", | ||||||||
| "proto3_optional_already_in_request_proto", | ||||||||
| "value_error_fallback", | ||||||||
| "dict_proto3_optional_not_in_request", | ||||||||
| "dict_proto3_optional_value_none", | ||||||||
| "dict_proto3_optional_already_in_request", | ||||||||
| "dict_non_proto3_optional_empty", | ||||||||
| "dict_non_proto3_optional_value_none", | ||||||||
| "dict_non_proto3_optional_already_set", | ||||||||
| "none_request", | ||||||||
| ], | ||||||||
| ) | ||||||||
| def test_setup_request_id(request_obj, is_proto3_optional, expected): | ||||||||
| setup_request_id(request_obj, "request_id", is_proto3_optional) | ||||||||
|
|
||||||||
| if expected == "none": | ||||||||
| assert request_obj is None | ||||||||
| return | ||||||||
|
|
||||||||
| value = ( | ||||||||
| request_obj["request_id"] | ||||||||
| if isinstance(request_obj, dict) | ||||||||
| else request_obj.request_id | ||||||||
| ) | ||||||||
|
|
||||||||
| if expected == "uuid": | ||||||||
| assert re.match(UUID_REGEX, value) | ||||||||
| else: | ||||||||
| assert value == expected | ||||||||
|
|
||||||||
| {% endblock %} | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.