def make_service_with_method_options( *, http_rule: http_pb2.HttpRule = None, method_signature: str = '', in_fields: typing.Tuple[desc.FieldDescriptorProto] = () ) -> wrappers.Service: # Declare a method with options enabled for long-running operations and # field headers. method = get_method( 'DoBigThing', 'foo.bar.ThingRequest', 'google.longrunning.operations_pb2.Operation', lro_response_type='foo.baz.ThingResponse', lro_metadata_type='foo.qux.ThingMetadata', in_fields=in_fields, http_rule=http_rule, method_signature=method_signature, ) # Define a service descriptor. service_pb = desc.ServiceDescriptorProto(name='ThingDoer') # Return a service object to test. return wrappers.Service( service_pb=service_pb, methods={method.name: method}, )
def _load_service( self, service: descriptor_pb2.ServiceDescriptorProto, address: metadata.Address, path: Tuple[int], ) -> wrappers.Service: """Load comments for a service and its methods.""" address = address.child(service.name, path) # Put together a dictionary of the service's methods. methods = self._get_methods( service.method, service_address=address, path=path + (2, ), ) # Load the comments for the service itself. self.proto_services[address.proto] = wrappers.Service( meta=metadata.Metadata( address=address, documentation=self.docs.get(path, self.EMPTY), ), methods=methods, service_pb=service, ) return self.proto_services[address.proto]
def test_get_filenames_with_service(): g = generator.Generator(api_schema=make_api(naming=make_naming( namespace=(), name='Spam', version='v2'), )) template_name = '$name/$service/foo.py.j2' assert g._get_filenames( template_name, context={ 'service': wrappers.Service( methods=[], service_pb=descriptor_pb2.ServiceDescriptorProto(name='Eggs'), ), }) == ('spam/eggs/foo.py', )
def make_service(name: str = 'Placeholder', host: str = '', methods: typing.Tuple[wrappers.Method] = (), scopes: typing.Tuple[str] = ()) -> wrappers.Service: # Define a service descriptor, and set a host and oauth scopes if # appropriate. service_pb = descriptor_pb2.ServiceDescriptorProto(name=name) if host: service_pb.options.Extensions[client_pb2.default_host] = host service_pb.options.Extensions[client_pb2.oauth_scopes] = ','.join(scopes) # Return a service object to test. return wrappers.Service( service_pb=service_pb, methods={m.name: m for m in methods}, )
def test_get_filename_with_service(): g = make_generator() template_name = "%name/%service/foo.py.j2" assert (g._get_filename( template_name, api_schema=make_api(naming=make_naming(namespace=(), name="Spam", version="v2"), ), context={ "service": wrappers.Service( methods=[], service_pb=descriptor_pb2.ServiceDescriptorProto(name="Eggs"), visible_resources={}, ), }, ) == "spam/eggs/foo.py")
def make_service( name: str = "Placeholder", host: str = "", methods: typing.Tuple[wrappers.Method] = (), scopes: typing.Tuple[str] = (), visible_resources: typing.Optional[typing.Mapping[ str, wrappers.CommonResource]] = None, ) -> wrappers.Service: visible_resources = visible_resources or {} # Define a service descriptor, and set a host and oauth scopes if # appropriate. service_pb = desc.ServiceDescriptorProto(name=name) if host: service_pb.options.Extensions[client_pb2.default_host] = host service_pb.options.Extensions[client_pb2.oauth_scopes] = ','.join(scopes) # Return a service object to test. return wrappers.Service( service_pb=service_pb, methods={m.name: m for m in methods}, visible_resources=visible_resources, )
def make_service(name: str = 'Placeholder', host: str = '', scopes: typing.Tuple[str] = ()) -> wrappers.Service: # Declare a few methods, with messages in distinct packages. methods = ( get_method('DoThing', 'foo.bar.ThingRequest', 'foo.baz.ThingResponse'), get_method('Jump', 'foo.bacon.JumpRequest', 'foo.bacon.JumpResponse'), get_method('Yawn', 'a.b.v1.c.YawnRequest', 'x.y.v1.z.YawnResponse'), ) # Define a service descriptor, and set a host and oauth scopes if # appropriate. service_pb = descriptor_pb2.ServiceDescriptorProto(name=name) if host: service_pb.options.Extensions[annotations_pb2.default_host] = host service_pb.options.Extensions[annotations_pb2.oauth].scopes.extend(scopes) # Return a service object to test. return wrappers.Service( service_pb=service_pb, methods={m.name: m for m in methods}, )
def test_generate_sample_basic(): # Note: the sample integration tests are needfully large # and difficult to eyeball parse. They are intended to be integration tests # that catch errors in behavior that is emergent from combining smaller features # or in features that are sufficiently small and trivial that it doesn't make sense # to have standalone tests. input_type = DummyMessage( type="REQUEST TYPE", fields={ "classify_target": DummyField(message=DummyMessage( type="CLASSIFY TYPE", fields={ "video": DummyField(message=DummyMessage(type="VIDEO TYPE"), ), "location_annotation": DummyField(message=DummyMessage(type="LOCATION TYPE"), ) }, )) }) api_naming = naming.NewNaming(name="MolluscClient", namespace=("molluscs", "v1")) service = wrappers.Service( service_pb=namedtuple('service_pb', ['name'])('MolluscService'), methods={ "Classify": DummyMethod(input=input_type, output=message_factory("$resp.taxonomy"), flattened_fields={ "classify_target": DummyField(name="classify_target") }) }, visible_resources={}, ) schema = DummyApiSchema( services={"animalia.mollusca.v1.Mollusc": service}, naming=api_naming, ) sample = { "service": "animalia.mollusca.v1.Mollusc", "rpc": "Classify", "id": "mollusc_classify_sync", "description": "Determine the full taxonomy of input mollusc", "request": [{ "field": "classify_target.video", "value": "path/to/mollusc/video.mkv", "input_parameter": "video", "value_is_file": True }, { "field": "classify_target.location_annotation", "value": "New Zealand", "input_parameter": "location" }], "response": [{ "print": ['Mollusc is a "%s"', "$resp.taxonomy"] }] } sample_str = samplegen.generate_sample( sample, schema, env.get_template('examples/sample.py.j2')) sample_id = ("mollusc_classify_sync") expected_str = '''# -*- coding: utf-8 -*- # Copyright 2020 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 # # http://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. # # DO NOT EDIT! This is a generated sample ("request", "%s") # # To install the latest published package dependency, execute the following: # pip3 install molluscs-v1-molluscclient # [START %s] from google import auth from google.auth import credentials from molluscs.v1.molluscclient.services.mollusc_service import MolluscServiceClient def sample_classify(video, location): """Determine the full taxonomy of input mollusc""" client = MolluscServiceClient( credentials=credentials.AnonymousCredentials(), transport="grpc", ) classify_target = {} # video = "path/to/mollusc/video.mkv" with open(video, "rb") as f: classify_target["video"] = f.read() # location = "New Zealand" classify_target["location_annotation"] = location response = client.classify(classify_target=classify_target) print("Mollusc is a \\"{}\\"".format(response.taxonomy)) # [END %s] def main(): import argparse parser = argparse.ArgumentParser() parser.add_argument("--video", type=str, default="path/to/mollusc/video.mkv") parser.add_argument("--location", type=str, default="New Zealand") args = parser.parse_args() sample_classify(args.video, args.location) if __name__ == "__main__": main() ''' % (sample_id, sample_id, sample_id) assert sample_str == expected_str
def test_generate_sample_basic(): # Note: the sample integration tests are needfully large # and difficult to eyeball parse. They are intended to be integration tests # that catch errors in behavior that is emergent from combining smaller features # or in features that are sufficiently small and trivial that it doesn't make sense # to have standalone tests. input_type = DummyMessage( type="REQUEST TYPE", fields={ "classify_target": DummyField(message=DummyMessage( type="CLASSIFY TYPE", fields={ "video": DummyField(message=DummyMessage(type="VIDEO TYPE"), ), "location_annotation": DummyField(message=DummyMessage(type="LOCATION TYPE"), ) }, )) }, ident=DummyIdent(name="molluscs.v1.ClassifyRequest")) api_naming = naming.NewNaming(name="MolluscClient", namespace=("molluscs", "v1")) service = wrappers.Service( service_pb=namedtuple('service_pb', ['name'])('MolluscService'), methods={ "Classify": DummyMethod(input=input_type, output=message_factory("$resp.taxonomy"), flattened_fields={ "classify_target": DummyField(name="classify_target") }) }, visible_resources={}, ) schema = DummyApiSchema( services={"animalia.mollusca.v1.Mollusc": service}, naming=api_naming, ) sample = { "service": "animalia.mollusca.v1.Mollusc", "rpc": "Classify", "id": "mollusc_classify_sync", "description": "Determine the full taxonomy of input mollusc", "request": [{ "field": "classify_target.video", "value": "path/to/mollusc/video.mkv", "input_parameter": "video", "value_is_file": True }, { "field": "classify_target.location_annotation", "value": "New Zealand", "input_parameter": "location" }], "response": [{ "print": ['Mollusc is a "%s"', "$resp.taxonomy"] }] } sample_str = samplegen.generate_sample( sample, schema, env.get_template('examples/sample.py.j2')) assert sample_str == golden_snippet("sample_basic.py")
def test_generate_sample_void_method(): input_type = DummyMessage( type="REQUEST TYPE", fields={ "classify_target": DummyField(message=DummyMessage( type="CLASSIFY TYPE", fields={ "video": DummyField(message=DummyMessage(type="VIDEO TYPE"), ), "location_annotation": DummyField(message=DummyMessage(type="LOCATION TYPE"), ) }, )) }, ident=DummyIdent(name="molluscs.v1.ClassifyRequest")) api_naming = naming.NewNaming(name="MolluscClient", namespace=("molluscs", "v1")) service = wrappers.Service( service_pb=namedtuple('service_pb', ['name'])('MolluscService'), methods={ "Classify": DummyMethod(void=True, input=input_type, output=message_factory("$resp.taxonomy"), flattened_fields={ "classify_target": DummyField(name="classify_target") }) }, visible_resources={}, ) schema = DummyApiSchema( services={"animalia.mollusca.v1.Mollusc": service}, naming=api_naming, ) sample = { "service": "animalia.mollusca.v1.Mollusc", "rpc": "Classify", "id": "mollusc_classify_sync", "description": "Determine the full taxonomy of input mollusc", "request": [{ "field": "classify_target.video", "value": "path/to/mollusc/video.mkv", "input_parameter": "video", "value_is_file": True }, { "field": "classify_target.location_annotation", "value": "New Zealand", "input_parameter": "location" }] } sample_str = samplegen.generate_sample( sample, schema, env.get_template('examples/sample.py.j2')) assert sample_str == golden_snippet("sample_basic_void_method.py")
def test_generate_sample_basic(): # Note: the sample integration tests are needfully large # and difficult to eyeball parse. They are intended to be integration tests # that catch errors in behavior that is emergent from combining smaller features # or in features that are sufficiently small and trivial that it doesn't make sense # to have standalone tests. classify_target_field = DummyField( name="classify_target", type=DummyMessageTypePB(name="ClassifyTarget"), message=DummyMessage( type="CLASSIFY TYPE", fields={ "video": DummyField( type=DummyMessageTypePB(name="Video"), message=DummyMessage(type="VIDEO TYPE"), ), "location_annotation": DummyField( type=DummyMessageTypePB(name="Location"), message=DummyMessage(type="LOCATION TYPE"), ) }, ), ident=DummyIdent(sphinx="molluscs_v1.ClassifyTarget") ) input_type = DummyMessage( type="REQUEST TYPE", fields={ "classify_target": classify_target_field }, ident=DummyIdent(name="molluscs.v1.ClassifyRequest", sphinx="molluscs_v1.classify_request") ) output_type = DummyMessage( type="RESPONSE TYPE", fields={ "classification": DummyField( type=DummyMessageTypePB(name="Classification"), ) }, ident=DummyIdent(sphinx="molluscs_v1.classification") ) api_naming = naming.NewNaming( name="MolluscClient", namespace=("molluscs", "v1")) service = wrappers.Service( service_pb=namedtuple('service_pb', ['name'])('MolluscService'), methods={ "Classify": DummyMethod( name="Classify", input=input_type, output=message_factory("$resp.taxonomy"), client_output=output_type, flattened_fields={ "classify_target": classify_target_field } ) }, visible_resources={}, ) schema = DummyApiSchema( services={"animalia.mollusca.v1.Mollusc": service}, naming=api_naming, ) sample = {"service": "animalia.mollusca.v1.Mollusc", "region_tag": "molluscs_generated_molluscs_v1_Mollusc_Classify_sync", "rpc": "Classify", "id": "mollusc_classify_sync", "description": "Determine the full taxonomy of input mollusc", "request": [ {"field": "classify_target.video", "value": "path/to/mollusc/video.mkv", "input_parameter": "video", "value_is_file": True}, {"field": "classify_target.location_annotation", "value": "New Zealand", "input_parameter": "location"} ], "response": [{"print": ['Mollusc is a "%s"', "$resp.taxonomy"]}]} sample_str, metadata = samplegen.generate_sample( sample, schema, env.get_template('examples/sample.py.j2') ) assert sample_str == golden_snippet("sample_basic.py") assert json_format.MessageToDict(metadata) == { 'regionTag': 'molluscs_generated_molluscs_v1_Mollusc_Classify_sync', 'description': 'Sample for Classify', 'language': 'PYTHON', 'clientMethod': { 'shortName': 'classify', 'fullName': 'molluscs.v1.molluscclient.MolluscServiceClient.classify', 'parameters': [ {'type': 'molluscs_v1.classify_request', 'name': 'request'}, {'type': 'molluscs_v1.ClassifyTarget', 'name': 'classify_target'}, {'type': 'google.api_core.retry.Retry', 'name': 'retry'}, {'type': 'float', 'name': 'timeout'}, {'type': 'Sequence[Tuple[str, str]', 'name': 'metadata'} ], 'resultType': 'molluscs_v1.classification', 'client': { 'shortName': 'MolluscServiceClient', 'fullName': 'molluscs.v1.molluscclient.MolluscServiceClient' }, 'method': { 'shortName': 'Classify', 'fullName': '.MolluscService.Classify', 'service': {'shortName': 'MolluscService', 'fullName': '.MolluscService'}} }, 'canonical': True, 'origin': 'API_DEFINITION' }
def test_generate_sample_void_method(): classify_target_field = DummyField( name="classify_target", type=DummyMessageTypePB(name="ClassifyTarget"), message=DummyMessage( type="CLASSIFY TYPE", fields={ "video": DummyField( type=DummyMessageTypePB(name="Video"), message=DummyMessage(type="VIDEO TYPE"), ), "location_annotation": DummyField( type=DummyMessageTypePB(name="Location"), message=DummyMessage(type="LOCATION TYPE"), ) }, ), ident=DummyIdent(sphinx="molluscs_v1.ClassifyTarget") ) input_type = DummyMessage( type="REQUEST TYPE", fields={ "classify_target": classify_target_field }, ident=DummyIdent(name="molluscs.v1.ClassifyRequest", sphinx="molluscs_v1.classify_request") ) api_naming = naming.NewNaming( name="MolluscClient", namespace=("molluscs", "v1")) service = wrappers.Service( service_pb=namedtuple('service_pb', ['name'])('MolluscService'), methods={ "Classify": DummyMethod( name="Classify", client_output=DummyIdent(name="classify", sphinx="classify"), void=True, input=input_type, output=message_factory("$resp.taxonomy"), flattened_fields={ "classify_target": classify_target_field, } ) }, visible_resources={}, ) schema = DummyApiSchema( services={"animalia.mollusca.v1.Mollusc": service}, naming=api_naming, ) sample = {"service": "animalia.mollusca.v1.Mollusc", "region_tag": "molluscs_generated_molluscs_v1_Mollusc_Classify_sync", "rpc": "Classify", "id": "mollusc_classify_sync", "description": "Determine the full taxonomy of input mollusc", "request": [ {"field": "classify_target.video", "value": "path/to/mollusc/video.mkv", "input_parameter": "video", "value_is_file": True}, {"field": "classify_target.location_annotation", "value": "New Zealand", "input_parameter": "location"} ]} sample_str, metadata = samplegen.generate_sample( sample, schema, env.get_template('examples/sample.py.j2') ) assert sample_str == golden_snippet("sample_basic_void_method.py") assert json_format.MessageToDict(metadata) == { 'regionTag': 'molluscs_generated_molluscs_v1_Mollusc_Classify_sync', 'description': 'Sample for Classify', 'language': 'PYTHON', 'clientMethod': { 'shortName': 'classify', 'fullName': 'molluscs.v1.molluscclient.MolluscServiceClient.classify', 'parameters': [ {'type': 'molluscs_v1.classify_request', 'name': 'request'}, {'type': 'molluscs_v1.ClassifyTarget', 'name': 'classify_target'}, {'type': 'google.api_core.retry.Retry', 'name': 'retry'}, {'type': 'float', 'name': 'timeout'}, {'type': 'Sequence[Tuple[str, str]', 'name': 'metadata'} ], 'client': { 'shortName': 'MolluscServiceClient', 'fullName': 'molluscs.v1.molluscclient.MolluscServiceClient' }, 'method': { 'shortName': 'Classify', 'fullName': '.MolluscService.Classify', 'service': {'shortName': 'MolluscService', 'fullName': '.MolluscService'} } }, 'canonical': True, 'origin': 'API_DEFINITION' }
def test_generate_sample_basic(): # Note: the sample integration tests are needfully large # and difficult to eyeball parse. They are intended to be integration tests # that catch errors in behavior that is emergent from combining smaller features # or in features that are sufficiently small and trivial that it doesn't make sense # to have standalone tests. input_type = DummyMessage( type="REQUEST TYPE", fields={ "classify_request": DummyField(message=DummyMessage( type="CLASSIFY TYPE", fields={ "video": DummyField(message=DummyMessage(type="VIDEO TYPE"), ), "location_annotation": DummyField(message=DummyMessage(type="LOCATION TYPE"), ) }, )) }) api_naming = naming.Naming(name="MolluscClient", namespace=("molluscs", "v1")) service = wrappers.Service( service_pb=namedtuple('service_pb', ['name'])('MolluscClient'), methods={ "Classify": DummyMethod(input=input_type, output=message_factory("$resp.taxonomy")) }) schema = DummyApiSchema( services={"animalia.mollusca.v1.Mollusc": service}, naming=api_naming, ) sample = { "service": "animalia.mollusca.v1.Mollusc", "rpc": "Classify", "id": "mollusc_classify_sync", "description": "Determine the full taxonomy of input mollusc", "request": [{ "field": "classify_request.video", "value": "'path/to/mollusc/video.mkv'", "input_parameter": "video", "value_is_file": True }, { "field": "classify_request.location_annotation", "value": "'New Zealand'", "input_parameter": "location" }], "response": [{ "print": ["Mollusc is a %s", "$resp.taxonomy"] }] } sample_str = samplegen.generate_sample( sample, schema, env.get_template('examples/sample.py.j2')) sample_id = ("mollusc_classify_sync") expected_str = '''# TODO: add a copyright # TODO: add a license # # DO NOT EDIT! This is a generated sample ("request", "%s") # # To install the latest published package dependency, execute the following: # pip3 install molluscs-v1-molluscclient # [START %s] from google import auth from google.auth import credentials from molluscs.v1.molluscclient.services.mollusc_client import MolluscClient def sample_classify(video, location): """Determine the full taxonomy of input mollusc""" client = MolluscClient( credentials=credentials.AnonymousCredentials(), transport="grpc", ) classify_request = {} # video = 'path/to/mollusc/video.mkv' with open(video, "rb") as f: classify_request["video"] = f.read() # location = 'New Zealand' classify_request["location_annotation"] = location response = client.classify(classify_request) print("Mollusc is a {}".format(response.taxonomy)) # [END %s] def main(): import argparse parser = argparse.ArgumentParser() parser.add_argument("--video", type=str, default='path/to/mollusc/video.mkv') parser.add_argument("--location", type=str, default='New Zealand') args = parser.parse_args() sample_classify(args.video, args.location) if __name__ == "__main__": main() ''' % (sample_id, sample_id, sample_id) assert sample_str == expected_str