def python_import(self) -> imp.Import: """Return the Python import for this type.""" # If there is no naming object, this is a special case for operation. # FIXME(#34): OperationType does not work well. Fix or expunge it. if not self.api_naming: return imp.Import( package=self.package, module=self.module, alias=self.module_alias, ) # If this is part of the proto package that we are generating, # rewrite the package to our structure. if self.proto_package.startswith(self.api_naming.proto_package): return imp.Import( package=self.api_naming.module_namespace + (self.api_naming.versioned_module_name, ) + self.subpackage + ('types', ), module=self.module, alias=self.module_alias, ) # Return the standard import. return imp.Import( package=self.package, module=f'{self.module}_pb2', alias=self.module_alias if self.module_alias else self.module, )
def python_import(self) -> imp.Import: """Return the Python import for this type.""" # If there is no naming object, then this is a special case for # Python types. # # FIXME: This does not attempt to do an isinstance check on PythonType # to avoid a circular dependency. # That part is fine, but a check for the absence of `api_naming` is # less than ideal; the condition works, but it is a weak correlation # that may not hold up over time. if not self.api_naming: return imp.Import( package=self.package, module=self.module, alias=self.module_alias, ) # If this is part of the proto package that we are generating, # rewrite the package to our structure. if self.proto_package.startswith(self.api_naming.proto_package): return imp.Import( package=self.api_naming.module_namespace + (self.api_naming.versioned_module_name, ) + self.subpackage + ('types', ), module=self.module, alias=self.module_alias, ) # Return the standard import. return imp.Import( package=self.package, module=f'{self.module}_pb2', )
def test_service_python_modules_lro(): service = make_service_with_method_options() assert service.python_modules == ( imp.Import(package=('foo',), module='bar'), imp.Import(package=('foo',), module='baz'), imp.Import(package=('foo',), module='qux'), imp.Import(package=('google', 'api_core'), module='operation'), )
def test_service_python_modules_lro(): service = make_service_with_method_options() method = service.methods['DoBigThing'] imports = {i.ident.python_import for i in method.ref_types} assert imports == { imp.Import(package=('foo', ), module='bar'), imp.Import(package=('foo', ), module='baz'), imp.Import(package=('foo', ), module='qux'), imp.Import(package=('google', 'api_core'), module='operation'), }
def test_str_eq(): i1 = imp.Import(package=('foo', 'bar'), module='baz') i2 = imp.Import(package=('foo', 'bar'), module='baz') i3 = imp.Import(package=('foo', 'bar'), module='baz', alias='bacon') j1 = imp.Import(package=('foo', 'bar'), module='not_baz') k1 = imp.Import(package=('spam', 'eggs'), module='baz') assert i1 == i2 assert i1 == i3 assert i2 == i3 assert i1 != j1 assert i1 != k1
def test_service_python_modules(): service = make_service(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'), )) assert service.python_modules == ( imp.Import(package=('a', 'b', 'v1'), module='c'), imp.Import(package=('foo',), module='bacon'), imp.Import(package=('foo',), module='bar'), imp.Import(package=('foo',), module='baz'), imp.Import(package=('x', 'y', 'v1'), module='z'), )
def test_service_python_modules(): service = make_service(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'), )) imports = set() for m in service.methods.values(): imports = imports.union({i.ident.python_import for i in m.ref_types}) assert imports == { imp.Import(package=('a', 'b', 'v1'), module='c'), imp.Import(package=('foo', ), module='bacon'), imp.Import(package=('foo', ), module='bar'), imp.Import(package=('foo', ), module='baz'), imp.Import(package=('x', 'y', 'v1'), module='z'), }
def test_python_modules_nested(): fd = ( make_file_pb2( name='dep.proto', package='google.dep', messages=(make_message_pb2(name='ImportedMessage', fields=()), ), ), make_file_pb2( name='common.proto', package='google.example.v1.common', messages=(make_message_pb2(name='Bar'), ), ), make_file_pb2( name='foo.proto', package='google.example.v1', messages=( make_message_pb2( name='GetFooRequest', fields=( make_field_pb2(name='primitive', number=2, type=1), make_field_pb2( name='foo', number=3, type=1, type_name='.google.example.v1.GetFooRequest.Foo', ), ), nested_type=(make_message_pb2( name='Foo', fields=(make_field_pb2( name='imported_message', number=1, type_name='.google.dep.ImportedMessage'), ), ), ), ), make_message_pb2( name='GetFooResponse', fields=(make_field_pb2( name='foo', number=1, type_name='.google.example.v1.GetFooRequest.Foo', ), ), ), ), services=(descriptor_pb2.ServiceDescriptorProto( name='FooService', method=(descriptor_pb2.MethodDescriptorProto( name='GetFoo', input_type='google.example.v1.GetFooRequest', output_type='google.example.v1.GetFooResponse', ), ), ), ), ), ) api_schema = api.API.build(fd, package='google.example.v1') assert api_schema.protos['foo.proto'].python_modules == (imp.Import( package=('google', 'dep'), module='dep_pb2'), )
def test_service_python_modules_signature(): service = make_service_with_method_options( in_fields=( descriptor_pb2.FieldDescriptorProto(name='secs', type=5), descriptor_pb2.FieldDescriptorProto( name='d', type=14, # enum type_name='a.b.c.v2.D', ), ), method_signature='secs,d', ) # type=5 is int, so nothing is added. assert service.python_modules == ( imp.Import(package=('a', 'b', 'c'), module='v2'), imp.Import(package=('foo',), module='bar'), imp.Import(package=('foo',), module='baz'), imp.Import(package=('foo',), module='qux'), imp.Import(package=('google', 'api_core'), module='operation'), )
def test_service_python_modules_signature(): service = make_service_with_method_options( in_fields=( # type=5 is int, so nothing is added. descriptor_pb2.FieldDescriptorProto(name='secs', type=5), descriptor_pb2.FieldDescriptorProto( name='d', type=14, # enum type_name='a.b.c.v2.D', ), ), method_signature='secs,d', ) # Ensure that the service will have the expected imports. method = service.methods['DoBigThing'] imports = {i.ident.python_import for i in method.ref_types} assert imports == { imp.Import(package=('a', 'b', 'c'), module='v2'), imp.Import(package=('foo', ), module='bar'), imp.Import(package=('foo', ), module='baz'), imp.Import(package=('foo', ), module='qux'), imp.Import(package=('google', 'api_core'), module='operation'), imp.Import(package=('google', 'api_core'), module='operation_async'), }
def test_proto_names_import_collision_flattening(): lro_proto = api.Proto.build(make_file_pb2( name='operations.proto', package='google.longrunning', messages=(make_message_pb2(name='Operation'), ), ), file_to_generate=False, naming=make_naming()) fd = ( make_file_pb2( name='mollusc.proto', package='google.animalia.mollusca', messages=( make_message_pb2(name='Mollusc', ), make_message_pb2(name='MolluscResponse', ), make_message_pb2(name='MolluscMetadata', ), ), ), make_file_pb2( name='squid.proto', package='google.animalia.mollusca', messages=( make_message_pb2( name='IdentifySquidRequest', fields=(make_field_pb2( name='mollusc', number=1, type_name='.google.animalia.mollusca.Mollusc'), ), ), make_message_pb2( name='IdentifySquidResponse', fields=(), ), ), services=(descriptor_pb2.ServiceDescriptorProto( name='SquidIdentificationService', method=(descriptor_pb2.MethodDescriptorProto( name='IdentifyMollusc', input_type='google.animalia.mollusca.IdentifySquidRequest', output_type='google.longrunning.Operation', ), ), ), ), ), ) method_options = fd[1].service[0].method[0].options # Notice that a signature field collides with the name of an imported module method_options.Extensions[client_pb2.method_signature].append('mollusc') method_options.Extensions[operations_pb2.operation_info].MergeFrom( operations_pb2.OperationInfo( response_type='google.animalia.mollusca.MolluscResponse', metadata_type='google.animalia.mollusca.MolluscMetadata', )) api_schema = api.API.build(fd, package='google.animalia.mollusca', prior_protos={ 'google/longrunning/operations.proto': lro_proto, }) actual_imports = { ref_type.ident.python_import for service in api_schema.services.values() for method in service.methods.values() for ref_type in method.ref_types } expected_imports = { imp.Import( package=('google', 'animalia', 'mollusca', 'types'), module='mollusc', alias='gam_mollusc', ), imp.Import( package=('google', 'animalia', 'mollusca', 'types'), module='squid', ), imp.Import( package=('google', 'api_core'), module='operation', ), imp.Import( package=('google', 'api_core'), module='operation_async', ), } assert expected_imports == actual_imports method = (api_schema. services['google.animalia.mollusca.SquidIdentificationService']. methods['IdentifyMollusc']) actual_response_import = method.lro.response_type.ident.python_import expected_response_import = imp.Import( package=('google', 'animalia', 'mollusca', 'types'), module='mollusc', alias='gam_mollusc', ) assert actual_response_import == expected_response_import
def test_str_alias(): i = imp.Import(package=('foo', 'bar'), module='baz', alias='bacon') assert str(i) == 'from foo.bar import baz as bacon'
def test_str_no_package(): i = imp.Import(package=(), module='baz') assert str(i) == 'import baz'
def test_str(): i = imp.Import(package=('foo', 'bar'), module='baz') assert str(i) == 'from foo.bar import baz'
def test_api_build(): # Put together a couple of minimal protos. fd = ( make_file_pb2( name='dep.proto', package='google.dep', messages=(make_message_pb2(name='ImportedMessage', fields=()), ), ), make_file_pb2( name='common.proto', package='google.example.v1.common', messages=(make_message_pb2(name='Bar'), ), ), make_file_pb2( name='foo.proto', package='google.example.v1', messages=( make_message_pb2(name='Foo', fields=()), make_message_pb2( name='GetFooRequest', fields=( make_field_pb2( name='imported_message', number=1, type_name='.google.dep.ImportedMessage'), make_field_pb2(name='primitive', number=2, type=1), )), make_message_pb2(name='GetFooResponse', fields=(make_field_pb2( name='foo', number=1, type_name='.google.example.v1.Foo'), )), ), services=(descriptor_pb2.ServiceDescriptorProto( name='FooService', method=(descriptor_pb2.MethodDescriptorProto( name='GetFoo', input_type='google.example.v1.GetFooRequest', output_type='google.example.v1.GetFooResponse', ), ), ), ), ), ) # Create an API with those protos. api_schema = api.API.build(fd, package='google.example.v1') # Establish that the API has the data expected. assert isinstance(api_schema, api.API) assert len(api_schema.all_protos) == 3 assert len(api_schema.protos) == 2 assert 'google.dep.ImportedMessage' not in api_schema.messages assert 'google.example.v1.common.Bar' in api_schema.messages assert 'google.example.v1.Foo' in api_schema.messages assert 'google.example.v1.GetFooRequest' in api_schema.messages assert 'google.example.v1.GetFooResponse' in api_schema.messages assert 'google.example.v1.FooService' in api_schema.services assert len(api_schema.enums) == 0 assert api_schema.protos['foo.proto'].python_modules == (imp.Import( package=('google', 'dep'), module='dep_pb2'), ) assert api_schema.requires_package(('google', 'example', 'v1')) assert not api_schema.requires_package(('elgoog', 'example', 'v1')) # Establish that the subpackages work. assert 'common' in api_schema.subpackages sub = api_schema.subpackages['common'] assert len(sub.protos) == 1 assert 'google.example.v1.common.Bar' in sub.messages assert 'google.example.v1.Foo' not in sub.messages
def test_str_untyped_api_core(): i = imp.Import(package=('foo', 'api_core'), module='baz', alias='bacon') assert str(i) == 'from foo.api_core import baz as bacon # type: ignore'
def test_str_untyped_pb2(): i = imp.Import(package=('foo', 'bar'), module='baz_pb2', alias='bacon') assert str(i) == 'from foo.bar import baz_pb2 as bacon # type: ignore'