From 116b32c03d6a4f433e19829f117dea0440be1e40 Mon Sep 17 00:00:00 2001 From: vam-google Date: Thu, 1 Sep 2022 16:07:29 -0700 Subject: [PATCH 1/2] fix: Fix remaining REST transport issues This includes: 1) Use message-based transcoding logic instead of dictionary-based. This fixes multiple bugs caused by dict-json-object representation mismatches fro protobuf objects. This also removes a lot of `json->dict->object->proto-plus` object conversion overhead, which was slow and very error-prone. Now all transcodding and rest-transport-specific logic is executed in terms of native protobuf (`_pb`) stubs objects. No dicts, no proto-plus, no unnecessary conversions. 2) Fix for non-proto-plus objects in rest.py transport and in tests. This essential for APIs which have IAM methods defined on their surface. 3) Fix support for Any field in tests 4) Fix creation of mock_values (do `mock_value1` instead of `mock_value_1`, since `mock_value_1` causes issues for FieldMask mocks --- gapic/schema/metadata.py | 6 +- gapic/schema/wrappers.py | 28 ++++-- .../services/%service/transports/rest.py.j2 | 40 +++++---- .../%name_%version/%sub/test_%service.py.j2 | 4 +- .../gapic/%name_%version/%sub/test_macros.j2 | 88 ++++++++++++++----- .../services/iam_credentials/async_client.py | 2 +- .../services/iam_credentials/client.py | 2 +- ...credentials_generate_access_token_async.py | 2 +- ..._credentials_generate_access_token_sync.py | 2 +- .../logging_service_v2/async_client.py | 4 +- .../services/logging_service_v2/client.py | 4 +- ...gging_service_v2_list_log_entries_async.py | 2 +- ...ogging_service_v2_list_log_entries_sync.py | 2 +- ...gging_service_v2_tail_log_entries_async.py | 2 +- ...ogging_service_v2_tail_log_entries_sync.py | 2 +- tests/unit/schema/wrappers/test_field.py | 39 +++++++- 16 files changed, 161 insertions(+), 68 deletions(-) diff --git a/gapic/schema/metadata.py b/gapic/schema/metadata.py index 5bd23e1b52..d53c002e67 100644 --- a/gapic/schema/metadata.py +++ b/gapic/schema/metadata.py @@ -92,7 +92,7 @@ def __str__(self) -> str: # This module is from a different proto package # Most commonly happens for a common proto # https://pypi.org/project/googleapis-common-protos/ - if not self.proto_package.startswith(self.api_naming.proto_package): + if self.is_external_type: module_name = f'{self.module}_pb2' # Return the dot-separated Python identifier. @@ -102,6 +102,10 @@ def __str__(self) -> str: # Return the Python identifier. return '.'.join(self.parent + (self.name,)) + @property + def is_external_type(self): + return not self.proto_package.startswith(self.api_naming.proto_package) + @cached_property def __cached_string_repr(self): return "({})".format( diff --git a/gapic/schema/wrappers.py b/gapic/schema/wrappers.py index d66fe03a48..87a5b45980 100644 --- a/gapic/schema/wrappers.py +++ b/gapic/schema/wrappers.py @@ -128,10 +128,19 @@ def recursive_mock_original_type(field): # Not worth the hassle, just return an empty map. return {} - msg_dict = { - f.name: recursive_mock_original_type(f) - for f in field.message.fields.values() - } + adr = field.type.meta.address + if adr.name == "Any" and adr.package == ("google", "protobuf"): + # If it is Any type pack a random but validly encoded type, + # Duration in this specific case. + msg_dict = { + "type_url": "type.googleapis.com/google.protobuf.Duration", + "value": b'\x08\x0c\x10\xdb\x07', + } + else: + msg_dict = { + f.name: recursive_mock_original_type(f) + for f in field.message.fields.values() + } return [msg_dict] if field.repeated else msg_dict @@ -237,9 +246,16 @@ def primitive_mock(self, suffix: int = 0) -> Union[bool, str, bytes, int, float, if self.type.python_type == bool: answer = True elif self.type.python_type == str: - answer = f"{self.name}_value_{suffix}" if suffix else f"{self.name}_value" + if self.name == "type_url": + # It is most likely a mock for Any type. We don't really care + # which mock value to put, so lets put a value which makes + # Any deserializer happy, which will wtill work even if it + # is not Any. + answer = "type.googleapis.com/google.protobuf.Empty" + else: + answer = f"{self.name}_value{suffix}" if suffix else f"{self.name}_value" elif self.type.python_type == bytes: - answer_str = f"{self.name}_blob_{suffix}" if suffix else f"{self.name}_blob" + answer_str = f"{self.name}_blob{suffix}" if suffix else f"{self.name}_blob" answer = bytes(answer_str, encoding="utf-8") elif self.type.python_type == int: answer = sum([ord(i) for i in self.name]) + suffix diff --git a/gapic/templates/%namespace/%name_%version/%sub/services/%service/transports/rest.py.j2 b/gapic/templates/%namespace/%name_%version/%sub/services/%service/transports/rest.py.j2 index c8491b5acb..9f6489af27 100644 --- a/gapic/templates/%namespace/%name_%version/%sub/services/%service/transports/rest.py.j2 +++ b/gapic/templates/%namespace/%name_%version/%sub/services/%service/transports/rest.py.j2 @@ -15,9 +15,9 @@ from google.api_core import rest_streaming from google.api_core import path_template from google.api_core import gapic_v1 +from google.protobuf import json_format {% if service.has_lro %} from google.api_core import operations_v1 -from google.protobuf import json_format {% endif %} from requests import __version__ as requests_version import dataclasses @@ -328,20 +328,19 @@ class {{service.name}}RestTransport({{service.name}}Transport): {% endfor %}{# rule in method.http_options #} ] request, metadata = self._interceptor.pre_{{ method.name|snake_case }}(request, metadata) - request_kwargs = {{method.input.ident}}.to_dict(request) - transcoded_request = path_template.transcode( - http_options, **request_kwargs) + {% if method.input.ident.is_external_type %} + pb_request = request + {% else %} + pb_request = {{method.input.ident}}.pb(request) + {% endif %} + transcoded_request = path_template.transcode(http_options, pb_request) {% set body_spec = method.http_options[0].body %} {%- if body_spec %} # Jsonify the request body - body = {% if body_spec == '*' -%} - {{method.input.ident}}.to_json( - {{method.input.ident}}(transcoded_request['body']), - {% else -%} - {{method.input.fields[body_spec].type.ident}}.to_json( - {{method.input.fields[body_spec].type.ident}}(transcoded_request['body']), - {% endif %}{# body_spec == "*" #} + + body = json_format.MessageToJson( + transcoded_request['body'], including_default_value_fields=False, use_integers_for_enums={{ opts.rest_numeric_enums }} ) @@ -351,12 +350,11 @@ class {{service.name}}RestTransport({{service.name}}Transport): method = transcoded_request['method'] # Jsonify the query params - query_params = json.loads({{method.input.ident}}.to_json( - {{method.input.ident}}(transcoded_request['query_params']), + query_params = json.loads(json_format.MessageToJson( + transcoded_request['query_params'], including_default_value_fields=False, - use_integers_for_enums={{ opts.rest_numeric_enums }} + use_integers_for_enums={{ opts.rest_numeric_enums }}, )) - {% if method.input.required_fields %} query_params.update(self._get_unset_required_fields(query_params)) {% endif %}{# required fields #} @@ -391,10 +389,14 @@ class {{service.name}}RestTransport({{service.name}}Transport): {% elif method.server_streaming %} resp = rest_streaming.ResponseIterator(response, {{method.output.ident}}) {% else %} - resp = {{method.output.ident}}.from_json( - response.content, - ignore_unknown_fields=True - ) + resp = {{method.output.ident}}() + {% if method.output.ident.is_external_type %} + pb_resp = resp + {% else %} + pb_resp = {{method.output.ident}}.pb(resp) + {% endif %} + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) {% endif %}{# method.lro #} resp = self._interceptor.post_{{ method.name|snake_case }}(resp) return resp diff --git a/gapic/templates/tests/unit/gapic/%name_%version/%sub/test_%service.py.j2 b/gapic/templates/tests/unit/gapic/%name_%version/%sub/test_%service.py.j2 index 1d58164908..3e166c029c 100644 --- a/gapic/templates/tests/unit/gapic/%name_%version/%sub/test_%service.py.j2 +++ b/gapic/templates/tests/unit/gapic/%name_%version/%sub/test_%service.py.j2 @@ -15,6 +15,7 @@ import grpc from grpc.experimental import aio {% if "rest" in opts.transport %} from collections.abc import Iterable +from google.protobuf import json_format import json {% endif %} import math @@ -51,9 +52,6 @@ from google.api_core import future from google.api_core import operation from google.api_core import operations_v1 from google.longrunning import operations_pb2 -{% if "rest" in opts.transport %} -from google.protobuf import json_format -{% endif %}{# rest transport #} {% endif %}{# lro #} {% if api.has_location_mixin %} from google.cloud.location import locations_pb2 diff --git a/gapic/templates/tests/unit/gapic/%name_%version/%sub/test_macros.j2 b/gapic/templates/tests/unit/gapic/%name_%version/%sub/test_macros.j2 index 9158aea9fa..532070be3b 100644 --- a/gapic/templates/tests/unit/gapic/%name_%version/%sub/test_macros.j2 +++ b/gapic/templates/tests/unit/gapic/%name_%version/%sub/test_macros.j2 @@ -855,7 +855,7 @@ def test_{{ method_name }}_rest(request_type): request_init["{{ field.name }}"] = {{ field.merged_mock_value(method.http_options[0].sample_request(method).get(field.name)) }} {% endif %} {% endfor %} - request = request_type(request_init) + request = request_type(**request_init) {% if method.client_streaming %} requests = [request] {% endif %} @@ -902,11 +902,19 @@ def test_{{ method_name }}_rest(request_type): json_return_value = '' {% elif method.lro %} json_return_value = json_format.MessageToJson(return_value) - {% elif method.server_streaming %} - json_return_value = "[{}]".format({{ method.output.ident }}.to_json(return_value)) {% else %} - json_return_value = {{ method.output.ident }}.to_json(return_value) + {% if method.output.ident.is_external_type %} + pb_return_value = return_value + {% else %} + pb_return_value = {{ method.output.ident }}.pb(return_value) {% endif %} + json_return_value = json_format.MessageToJson(pb_return_value) + {% endif %} + + {% if method.server_streaming %} + json_return_value = "[{}]".format(json_return_value) + {% endif %} + response_value._content = json_return_value.encode('UTF-8') req.return_value = response_value {% if method.client_streaming %} @@ -965,12 +973,17 @@ def test_{{ method_name }}_rest_required_fields(request_type={{ method.input.ide request_init["{{ req_field.name }}"] = {{ req_field.type.python_type(req_field.field_pb.default_value or 0) }} {% endif %}{# default is str #} {% endfor %} - request = request_type(request_init) - jsonified_request = json.loads(request_type.to_json( - request, + request = request_type(**request_init) + {% if method.input.ident.is_external_type %} + pb_request = request + {% else %} + pb_request = request_type.pb(request) + {% endif %} + jsonified_request = json.loads(json_format.MessageToJson( + pb_request, including_default_value_fields=False, use_integers_for_enums=False - )) + )) # verify fields with default values are dropped {% for req_field in method.input.required_fields if req_field.is_primitive and req_field.name in method.query_params %} @@ -978,7 +991,7 @@ def test_{{ method_name }}_rest_required_fields(request_type={{ method.input.ide assert "{{ field_name }}" not in jsonified_request {% endfor %} - unset_fields = transport_class(credentials=ga_credentials.AnonymousCredentials()).{{ method.name | snake_case }}._get_unset_required_fields(jsonified_request) + unset_fields = transport_class(credentials=ga_credentials.AnonymousCredentials()).{{ method.transport_safe_name | snake_case }}._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with default values are now present @@ -994,7 +1007,7 @@ def test_{{ method_name }}_rest_required_fields(request_type={{ method.input.ide jsonified_request["{{ field_name }}"] = {{ mock_value }} {% endfor %} - unset_fields = transport_class(credentials=ga_credentials.AnonymousCredentials()).{{ method.name | snake_case }}._get_unset_required_fields(jsonified_request) + unset_fields = transport_class(credentials=ga_credentials.AnonymousCredentials()).{{ method.transport_safe_name | snake_case }}._get_unset_required_fields(jsonified_request) {% if method.query_params %} # Check that path parameters and body parameters are not mixing in. assert not set(unset_fields) - set(({% for param in method.query_params|sort %}"{{param}}", {% endfor %})) @@ -1014,7 +1027,7 @@ def test_{{ method_name }}_rest_required_fields(request_type={{ method.input.ide credentials=ga_credentials.AnonymousCredentials(), transport='rest', ) - request = request_type(request_init) + request = request_type(**request_init) # Designate an appropriate value for the returned response. {% if method.void %} @@ -1032,13 +1045,18 @@ def test_{{ method_name }}_rest_required_fields(request_type={{ method.input.ide with mock.patch.object(path_template, 'transcode') as transcode: # A uri without fields and an empty body will force all the # request fields to show up in the query_params. + {% if method.input.ident.is_external_type %} + pb_request = request + {% else %} + pb_request = request_type.pb(request) + {% endif %} transcode_result = { 'uri': 'v1/sample_method', 'method': "{{ method.http_options[0].method }}", - 'query_params': request_init, + 'query_params': pb_request, } {% if method.http_options[0].body %} - transcode_result['body'] = {} + transcode_result['body'] = pb_request {% endif %} transcode.return_value = transcode_result @@ -1048,11 +1066,19 @@ def test_{{ method_name }}_rest_required_fields(request_type={{ method.input.ide json_return_value = '' {% elif method.lro %} json_return_value = json_format.MessageToJson(return_value) - {% elif method.server_streaming %} - json_return_value = "[{}]".format({{ method.output.ident }}.to_json(return_value)) {% else %} - json_return_value = {{ method.output.ident }}.to_json(return_value) + + {% if method.output.ident.is_external_type %} + pb_return_value = return_value + {% else %} + pb_return_value = {{ method.output.ident }}.pb(return_value) + {% endif %} + json_return_value = json_format.MessageToJson(pb_return_value) + {% endif %} + {% if method.server_streaming %} + json_return_value = "[{}]".format(json_return_value) {% endif %} + response_value._content = json_return_value.encode('UTF-8') req.return_value = response_value @@ -1115,8 +1141,17 @@ def test_{{ method_name }}_rest_interceptors(null_interceptor): {% if not method.void %} post.assert_not_called() {% endif %} - - transcode.return_value = {"method": "post", "uri": "my_uri", "body": None, "query_params": {},} + {% if method.input.ident.is_external_type %} + pb_message = {{ method.input.ident }}() + {% else %} + pb_message = {{ method.input.ident }}.pb({{ method.input.ident }}()) + {% endif %} + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } req.return_value = Response() req.return_value.status_code = 200 @@ -1164,7 +1199,7 @@ def test_{{ method_name }}_rest_bad_request(transport: str = 'rest', request_typ request_init["{{ field.name }}"] = {{ field.merged_mock_value(method.http_options[0].sample_request(method).get(field.name)) }} {% endif %} {% endfor %} - request = request_type(request_init) + request = request_type(**request_init) {% if method.client_streaming %} requests = [request] {% endif %} @@ -1222,12 +1257,17 @@ def test_{{ method_name }}_rest_flattened(): json_return_value = '' {% elif method.lro %} json_return_value = json_format.MessageToJson(return_value) - {% elif method.server_streaming %} - json_return_value = "[{}]".format({{ method.output.ident }}.to_json(return_value)) {% else %} - json_return_value = {{ method.output.ident }}.to_json(return_value) + {% if method.output.ident.is_external_type %} + pb_return_value = return_value + {% else %} + pb_return_value = {{ method.output.ident }}.pb(return_value) + {% endif %} + json_return_value = json_format.MessageToJson(pb_return_value) + {% endif %} + {% if method.server_streaming %} + json_return_value = "[{}]".format(json_return_value) {% endif %} - response_value._content = json_return_value.encode('UTF-8') req.return_value = response_value @@ -1342,7 +1382,7 @@ def test_{{ method_name }}_rest_pager(transport: str = 'rest'): return_values = tuple(Response() for i in response) for return_val, response_val in zip(return_values, response): {% if method.server_streaming %} - response_val = "[{}]".format({{ method.output.ident }}.to_json(response_val)) + response_val = "[{}]".format(response_val) {% endif %} return_val._content = response_val.encode('UTF-8') return_val.status_code = 200 diff --git a/tests/integration/goldens/credentials/google/iam/credentials_v1/services/iam_credentials/async_client.py b/tests/integration/goldens/credentials/google/iam/credentials_v1/services/iam_credentials/async_client.py index 8306403e4d..7c75fb16f8 100644 --- a/tests/integration/goldens/credentials/google/iam/credentials_v1/services/iam_credentials/async_client.py +++ b/tests/integration/goldens/credentials/google/iam/credentials_v1/services/iam_credentials/async_client.py @@ -219,7 +219,7 @@ async def sample_generate_access_token(): # Initialize request argument(s) request = credentials_v1.GenerateAccessTokenRequest( name="name_value", - scope=['scope_value_1', 'scope_value_2'], + scope=['scope_value1', 'scope_value2'], ) # Make the request diff --git a/tests/integration/goldens/credentials/google/iam/credentials_v1/services/iam_credentials/client.py b/tests/integration/goldens/credentials/google/iam/credentials_v1/services/iam_credentials/client.py index 70ec15e547..f94c44d21a 100644 --- a/tests/integration/goldens/credentials/google/iam/credentials_v1/services/iam_credentials/client.py +++ b/tests/integration/goldens/credentials/google/iam/credentials_v1/services/iam_credentials/client.py @@ -407,7 +407,7 @@ def sample_generate_access_token(): # Initialize request argument(s) request = credentials_v1.GenerateAccessTokenRequest( name="name_value", - scope=['scope_value_1', 'scope_value_2'], + scope=['scope_value1', 'scope_value2'], ) # Make the request diff --git a/tests/integration/goldens/credentials/samples/generated_samples/iamcredentials_v1_generated_iam_credentials_generate_access_token_async.py b/tests/integration/goldens/credentials/samples/generated_samples/iamcredentials_v1_generated_iam_credentials_generate_access_token_async.py index d2fb32cff1..825f6c072c 100644 --- a/tests/integration/goldens/credentials/samples/generated_samples/iamcredentials_v1_generated_iam_credentials_generate_access_token_async.py +++ b/tests/integration/goldens/credentials/samples/generated_samples/iamcredentials_v1_generated_iam_credentials_generate_access_token_async.py @@ -34,7 +34,7 @@ async def sample_generate_access_token(): # Initialize request argument(s) request = credentials_v1.GenerateAccessTokenRequest( name="name_value", - scope=['scope_value_1', 'scope_value_2'], + scope=['scope_value1', 'scope_value2'], ) # Make the request diff --git a/tests/integration/goldens/credentials/samples/generated_samples/iamcredentials_v1_generated_iam_credentials_generate_access_token_sync.py b/tests/integration/goldens/credentials/samples/generated_samples/iamcredentials_v1_generated_iam_credentials_generate_access_token_sync.py index 93e49f178c..16be47cf95 100644 --- a/tests/integration/goldens/credentials/samples/generated_samples/iamcredentials_v1_generated_iam_credentials_generate_access_token_sync.py +++ b/tests/integration/goldens/credentials/samples/generated_samples/iamcredentials_v1_generated_iam_credentials_generate_access_token_sync.py @@ -34,7 +34,7 @@ def sample_generate_access_token(): # Initialize request argument(s) request = credentials_v1.GenerateAccessTokenRequest( name="name_value", - scope=['scope_value_1', 'scope_value_2'], + scope=['scope_value1', 'scope_value2'], ) # Make the request diff --git a/tests/integration/goldens/logging/google/cloud/logging_v2/services/logging_service_v2/async_client.py b/tests/integration/goldens/logging/google/cloud/logging_v2/services/logging_service_v2/async_client.py index 4948fbc3cd..f74115ea9a 100644 --- a/tests/integration/goldens/logging/google/cloud/logging_v2/services/logging_service_v2/async_client.py +++ b/tests/integration/goldens/logging/google/cloud/logging_v2/services/logging_service_v2/async_client.py @@ -506,7 +506,7 @@ async def sample_list_log_entries(): # Initialize request argument(s) request = logging_v2.ListLogEntriesRequest( - resource_names=['resource_names_value_1', 'resource_names_value_2'], + resource_names=['resource_names_value1', 'resource_names_value2'], ) # Make the request @@ -867,7 +867,7 @@ async def sample_tail_log_entries(): # Initialize request argument(s) request = logging_v2.TailLogEntriesRequest( - resource_names=['resource_names_value_1', 'resource_names_value_2'], + resource_names=['resource_names_value1', 'resource_names_value2'], ) # This method expects an iterator which contains diff --git a/tests/integration/goldens/logging/google/cloud/logging_v2/services/logging_service_v2/client.py b/tests/integration/goldens/logging/google/cloud/logging_v2/services/logging_service_v2/client.py index bb4155398c..c386f0920f 100644 --- a/tests/integration/goldens/logging/google/cloud/logging_v2/services/logging_service_v2/client.py +++ b/tests/integration/goldens/logging/google/cloud/logging_v2/services/logging_service_v2/client.py @@ -677,7 +677,7 @@ def sample_list_log_entries(): # Initialize request argument(s) request = logging_v2.ListLogEntriesRequest( - resource_names=['resource_names_value_1', 'resource_names_value_2'], + resource_names=['resource_names_value1', 'resource_names_value2'], ) # Make the request @@ -1015,7 +1015,7 @@ def sample_tail_log_entries(): # Initialize request argument(s) request = logging_v2.TailLogEntriesRequest( - resource_names=['resource_names_value_1', 'resource_names_value_2'], + resource_names=['resource_names_value1', 'resource_names_value2'], ) # This method expects an iterator which contains diff --git a/tests/integration/goldens/logging/samples/generated_samples/logging_v2_generated_logging_service_v2_list_log_entries_async.py b/tests/integration/goldens/logging/samples/generated_samples/logging_v2_generated_logging_service_v2_list_log_entries_async.py index 4a8692b04e..fa7ad59dba 100644 --- a/tests/integration/goldens/logging/samples/generated_samples/logging_v2_generated_logging_service_v2_list_log_entries_async.py +++ b/tests/integration/goldens/logging/samples/generated_samples/logging_v2_generated_logging_service_v2_list_log_entries_async.py @@ -33,7 +33,7 @@ async def sample_list_log_entries(): # Initialize request argument(s) request = logging_v2.ListLogEntriesRequest( - resource_names=['resource_names_value_1', 'resource_names_value_2'], + resource_names=['resource_names_value1', 'resource_names_value2'], ) # Make the request diff --git a/tests/integration/goldens/logging/samples/generated_samples/logging_v2_generated_logging_service_v2_list_log_entries_sync.py b/tests/integration/goldens/logging/samples/generated_samples/logging_v2_generated_logging_service_v2_list_log_entries_sync.py index 062075af90..29d1dc7d13 100644 --- a/tests/integration/goldens/logging/samples/generated_samples/logging_v2_generated_logging_service_v2_list_log_entries_sync.py +++ b/tests/integration/goldens/logging/samples/generated_samples/logging_v2_generated_logging_service_v2_list_log_entries_sync.py @@ -33,7 +33,7 @@ def sample_list_log_entries(): # Initialize request argument(s) request = logging_v2.ListLogEntriesRequest( - resource_names=['resource_names_value_1', 'resource_names_value_2'], + resource_names=['resource_names_value1', 'resource_names_value2'], ) # Make the request diff --git a/tests/integration/goldens/logging/samples/generated_samples/logging_v2_generated_logging_service_v2_tail_log_entries_async.py b/tests/integration/goldens/logging/samples/generated_samples/logging_v2_generated_logging_service_v2_tail_log_entries_async.py index 3e77920f81..7a937948cd 100644 --- a/tests/integration/goldens/logging/samples/generated_samples/logging_v2_generated_logging_service_v2_tail_log_entries_async.py +++ b/tests/integration/goldens/logging/samples/generated_samples/logging_v2_generated_logging_service_v2_tail_log_entries_async.py @@ -33,7 +33,7 @@ async def sample_tail_log_entries(): # Initialize request argument(s) request = logging_v2.TailLogEntriesRequest( - resource_names=['resource_names_value_1', 'resource_names_value_2'], + resource_names=['resource_names_value1', 'resource_names_value2'], ) # This method expects an iterator which contains diff --git a/tests/integration/goldens/logging/samples/generated_samples/logging_v2_generated_logging_service_v2_tail_log_entries_sync.py b/tests/integration/goldens/logging/samples/generated_samples/logging_v2_generated_logging_service_v2_tail_log_entries_sync.py index ee1108b33f..a38e7b14d3 100644 --- a/tests/integration/goldens/logging/samples/generated_samples/logging_v2_generated_logging_service_v2_tail_log_entries_sync.py +++ b/tests/integration/goldens/logging/samples/generated_samples/logging_v2_generated_logging_service_v2_tail_log_entries_sync.py @@ -33,7 +33,7 @@ def sample_tail_log_entries(): # Initialize request argument(s) request = logging_v2.TailLogEntriesRequest( - resource_names=['resource_names_value_1', 'resource_names_value_2'], + resource_names=['resource_names_value1', 'resource_names_value2'], ) # This method expects an iterator which contains diff --git a/tests/unit/schema/wrappers/test_field.py b/tests/unit/schema/wrappers/test_field.py index d89bdf66ac..f23a2c9d85 100644 --- a/tests/unit/schema/wrappers/test_field.py +++ b/tests/unit/schema/wrappers/test_field.py @@ -283,7 +283,7 @@ def test_mock_value_repeated(): def test_mock_value_original_type_repeated(): field = make_field(name='foo_bar', type='TYPE_STRING', label=3) assert field.mock_value_original_type == [ - "foo_bar_value_1", "foo_bar_value_2"] + "foo_bar_value1", "foo_bar_value2"] def test_mock_value_map(): @@ -353,10 +353,38 @@ def test_mock_value_message(): def test_mock_value_original_type_message(): + any_message_subfields = collections.OrderedDict(( + ('type_url', make_field(name='type_url', number=1, type='TYPE_STRING')), + ('value', make_field(name='value', number=2, type='TYPE_BYTES')), + )) + + any_message = wrappers.MessageType( + fields=any_message_subfields, + message_pb=descriptor_pb2.DescriptorProto(name='Any', field=[ + i.field_pb for i in any_message_subfields.values() + ]), + meta=metadata.Metadata(address=metadata.Address( + module='bogus', + name='Any', + package=('google', 'protobuf') + )), + nested_enums={}, + nested_messages={}, + ) + + any_field = make_field( + name='surprise', + type='TYPE_MESSAGE', + type_name='google.protobuf.Any', + message=any_message + ) + subfields = collections.OrderedDict(( ('foo', make_field(name='foo', type='TYPE_INT32')), - ('bar', make_field(name='bar', type='TYPE_STRING')) + ('bar', make_field(name='bar', type='TYPE_STRING')), + ('surprise', any_field), )) + message = wrappers.MessageType( fields=subfields, message_pb=descriptor_pb2.DescriptorProto(name='Message', field=[ @@ -378,7 +406,9 @@ def test_mock_value_original_type_message(): mock = field.mock_value_original_type - assert mock == {"foo": 324, "bar": "bar_value"} + assert mock == {"foo": 324, "bar": "bar_value", "surprise": { + "type_url": "type.googleapis.com/google.protobuf.Duration", + "value": b"\x08\x0c\x10\xdb\x07"}} # Messages by definition aren't primitive with pytest.raises(TypeError): @@ -403,6 +433,9 @@ def test_mock_value_original_type_message(): assert entry_field.mock_value_original_type == {} + assert any_message.fields['type_url'].primitive_mock( + ) == "type.googleapis.com/google.protobuf.Empty" + def test_merged_mock_value_message(): subfields = collections.OrderedDict(( From 5a8dcd4f0bcd66f3f05f9edcc4cfad9f4e13a918 Mon Sep 17 00:00:00 2001 From: vam-google Date: Fri, 2 Sep 2022 12:37:22 -0700 Subject: [PATCH 2/2] update setup template to depend on latest api-core --- gapic/templates/setup.py.j2 | 4 ++-- tests/integration/goldens/asset/setup.py | 2 +- tests/integration/goldens/credentials/setup.py | 2 +- tests/integration/goldens/eventarc/setup.py | 2 +- tests/integration/goldens/logging/setup.py | 2 +- tests/integration/goldens/redis/setup.py | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/gapic/templates/setup.py.j2 b/gapic/templates/setup.py.j2 index 45bead1a4a..07dc062976 100644 --- a/gapic/templates/setup.py.j2 +++ b/gapic/templates/setup.py.j2 @@ -32,9 +32,9 @@ setuptools.setup( install_requires=( {# TODO(dovs): remove when 1.x deprecation is complete #} {% if 'rest' in opts.transport %} - 'google-api-core[grpc] >= 2.8.0, < 3.0.0dev', + 'google-api-core[grpc] >= 2.10.0, < 3.0.0dev', {% else %} - 'google-api-core[grpc] >= 2.8.0, < 3.0.0dev', + 'google-api-core[grpc] >= 2.10.0, < 3.0.0dev', {% endif %} 'libcst >= 0.2.5', 'googleapis-common-protos >= 1.55.0, <2.0.0dev', diff --git a/tests/integration/goldens/asset/setup.py b/tests/integration/goldens/asset/setup.py index 385d78bdea..017d5d80c3 100644 --- a/tests/integration/goldens/asset/setup.py +++ b/tests/integration/goldens/asset/setup.py @@ -37,7 +37,7 @@ platforms='Posix; MacOS X; Windows', include_package_data=True, install_requires=( - 'google-api-core[grpc] >= 2.8.0, < 3.0.0dev', + 'google-api-core[grpc] >= 2.10.0, < 3.0.0dev', 'libcst >= 0.2.5', 'googleapis-common-protos >= 1.55.0, <2.0.0dev', 'proto-plus >= 1.19.7', diff --git a/tests/integration/goldens/credentials/setup.py b/tests/integration/goldens/credentials/setup.py index 056323e24b..6925f8df33 100644 --- a/tests/integration/goldens/credentials/setup.py +++ b/tests/integration/goldens/credentials/setup.py @@ -37,7 +37,7 @@ platforms='Posix; MacOS X; Windows', include_package_data=True, install_requires=( - 'google-api-core[grpc] >= 2.8.0, < 3.0.0dev', + 'google-api-core[grpc] >= 2.10.0, < 3.0.0dev', 'libcst >= 0.2.5', 'googleapis-common-protos >= 1.55.0, <2.0.0dev', 'proto-plus >= 1.19.7', diff --git a/tests/integration/goldens/eventarc/setup.py b/tests/integration/goldens/eventarc/setup.py index 86fc0557d3..7fd9b0f202 100644 --- a/tests/integration/goldens/eventarc/setup.py +++ b/tests/integration/goldens/eventarc/setup.py @@ -37,7 +37,7 @@ platforms='Posix; MacOS X; Windows', include_package_data=True, install_requires=( - 'google-api-core[grpc] >= 2.8.0, < 3.0.0dev', + 'google-api-core[grpc] >= 2.10.0, < 3.0.0dev', 'libcst >= 0.2.5', 'googleapis-common-protos >= 1.55.0, <2.0.0dev', 'proto-plus >= 1.19.7', diff --git a/tests/integration/goldens/logging/setup.py b/tests/integration/goldens/logging/setup.py index c07123193e..c15839ee03 100644 --- a/tests/integration/goldens/logging/setup.py +++ b/tests/integration/goldens/logging/setup.py @@ -37,7 +37,7 @@ platforms='Posix; MacOS X; Windows', include_package_data=True, install_requires=( - 'google-api-core[grpc] >= 2.8.0, < 3.0.0dev', + 'google-api-core[grpc] >= 2.10.0, < 3.0.0dev', 'libcst >= 0.2.5', 'googleapis-common-protos >= 1.55.0, <2.0.0dev', 'proto-plus >= 1.19.7', diff --git a/tests/integration/goldens/redis/setup.py b/tests/integration/goldens/redis/setup.py index 28544f8e65..5b8ea93e9d 100644 --- a/tests/integration/goldens/redis/setup.py +++ b/tests/integration/goldens/redis/setup.py @@ -37,7 +37,7 @@ platforms='Posix; MacOS X; Windows', include_package_data=True, install_requires=( - 'google-api-core[grpc] >= 2.8.0, < 3.0.0dev', + 'google-api-core[grpc] >= 2.10.0, < 3.0.0dev', 'libcst >= 0.2.5', 'googleapis-common-protos >= 1.55.0, <2.0.0dev', 'proto-plus >= 1.19.7',