28 from grpc_tools
import protoc
33 _MESSAGES_IMPORT = b
'import "messages.proto";'
34 _SPLIT_NAMESPACE = b
'package grpc_protoc_plugin.invocation_testing.split;'
35 _COMMON_NAMESPACE = b
'package grpc_protoc_plugin.invocation_testing;'
37 _RELATIVE_PROTO_PATH =
'relative_proto_path'
38 _RELATIVE_PYTHON_OUT =
'relative_python_out'
41 @contextlib.contextmanager
43 old_system_path = sys.path[:]
44 sys.path = sys.path[0:1] + path_insertion + sys.path[1:]
46 sys.path = old_system_path
53 for path_components
in path_components_sequence:
55 for path_component
in path_components:
56 relative_path = path.join(thus_far, path_component)
57 if relative_path
not in created:
58 os.makedirs(path.join(root, relative_path))
59 created.add(relative_path)
60 thus_far = path.join(thus_far, path_component)
64 messages_proto_relative_file_name_bytes):
65 package_substitution = (b
'package grpc_protoc_plugin.invocation_testing.' +
66 test_name_bytes + b
';')
67 common_namespace_substituted = proto_content.replace(
68 _COMMON_NAMESPACE, package_substitution)
69 split_namespace_substituted = common_namespace_substituted.replace(
70 _SPLIT_NAMESPACE, package_substitution)
71 message_import_replaced = split_namespace_substituted.replace(
73 b
'import "' + messages_proto_relative_file_name_bytes + b
'";')
74 return message_import_replaced
78 for subdirectory, _, _
in os.walk(directory):
79 init_file_name = path.join(subdirectory,
'__init__.py')
80 with open(init_file_name,
'wb')
as init_file:
89 def Call(self, request, context):
93 def _protoc(proto_path, python_out, grpc_python_out_flag, grpc_python_out,
94 absolute_proto_file_names):
97 '--proto_path={}'.
format(proto_path),
99 if python_out
is not None:
100 args.append(
'--python_out={}'.
format(python_out))
101 if grpc_python_out
is not None:
102 args.append(
'--grpc_python_out={}:{}'.
format(grpc_python_out_flag,
104 args.extend(absolute_proto_file_names)
105 return protoc.main(args)
111 return 'Mid2016ProtocStyle'
116 def protoc(self, proto_path, python_out, absolute_proto_file_names):
117 return (
_protoc(proto_path, python_out,
'grpc_1_0', python_out,
118 absolute_proto_file_names),)
124 return 'SingleProtocExecutionProtocStyle'
129 def protoc(self, proto_path, python_out, absolute_proto_file_names):
130 return (
_protoc(proto_path, python_out,
'grpc_2_0', python_out,
131 absolute_proto_file_names),)
137 return 'ProtoBeforeGrpcProtocStyle'
142 def protoc(self, proto_path, python_out, absolute_proto_file_names):
143 pb2_protoc_exit_code =
_protoc(proto_path, python_out,
None,
None,
144 absolute_proto_file_names)
145 pb2_grpc_protoc_exit_code =
_protoc(proto_path,
None,
'grpc_2_0',
147 absolute_proto_file_names)
148 return pb2_protoc_exit_code, pb2_grpc_protoc_exit_code
154 return 'GrpcBeforeProtoProtocStyle'
159 def protoc(self, proto_path, python_out, absolute_proto_file_names):
160 pb2_grpc_protoc_exit_code =
_protoc(proto_path,
None,
'grpc_2_0',
162 absolute_proto_file_names)
163 pb2_protoc_exit_code =
_protoc(proto_path, python_out,
None,
None,
164 absolute_proto_file_names)
165 return pb2_grpc_protoc_exit_code, pb2_protoc_exit_code
176 @unittest.skipIf(platform.python_implementation() ==
'PyPy',
177 'Skip test if run with PyPy!')
178 class _Test(six.with_metaclass(abc.ABCMeta, unittest.TestCase)):
181 self.
_directory = tempfile.mkdtemp(suffix=self.NAME, dir=
'.')
188 proto_directories_and_names = {
190 self.MESSAGES_PROTO_RELATIVE_DIRECTORY_NAMES,
191 self.MESSAGES_PROTO_FILE_NAME,
194 self.SERVICES_PROTO_RELATIVE_DIRECTORY_NAMES,
195 self.SERVICES_PROTO_FILE_NAME,
198 messages_proto_relative_file_name_forward_slashes =
'/'.join(
199 self.MESSAGES_PROTO_RELATIVE_DIRECTORY_NAMES +
200 (self.MESSAGES_PROTO_FILE_NAME,))
203 (relative_proto_directory_names
for relative_proto_directory_names,
204 _
in proto_directories_and_names))
206 for relative_directory_names, file_name
in proto_directories_and_names:
207 absolute_proto_file_name = path.join(
208 self.
_proto_path, *relative_directory_names + (file_name,))
209 raw_proto_content = pkgutil.get_data(
210 'tests.protoc_plugin.protos.invocation_testing',
211 path.join(*relative_directory_names + (file_name,)))
213 raw_proto_content, self.NAME.
encode(),
214 messages_proto_relative_file_name_forward_slashes.encode())
215 with open(absolute_proto_file_name,
'wb')
as proto_file:
216 proto_file.write(massaged_proto_content)
223 protoc_exit_codes = self.PROTOC_STYLE.
protoc(
225 for protoc_exit_code
in protoc_exit_codes:
226 self.assertEqual(0, protoc_exit_code)
230 generated_modules = {}
231 expected_generated_full_module_names = {
232 self.EXPECTED_MESSAGES_PB2,
233 self.EXPECTED_SERVICES_PB2,
234 self.EXPECTED_SERVICES_PB2_GRPC,
237 for full_module_name
in expected_generated_full_module_names:
238 module = importlib.import_module(full_module_name)
239 generated_modules[full_module_name] = module
244 self.EXPECTED_SERVICES_PB2_GRPC]
247 if self.PROTOC_STYLE.grpc_in_pb2_expected():
257 self.
_services_pb2.DESCRIPTOR.services_by_name[
'TestService']
259 services_module.TestServiceStub
260 services_module.TestServiceServicer
261 services_module.add_TestServiceServicer_to_server
267 server = test_common.test_server()
268 services_module.add_TestServiceServicer_to_server(
270 port = server.add_insecure_port(
'[::]:0')
273 stub = services_module.TestServiceStub(channel)
282 name =
'{}{}'.
format(
'SplitProto' if split_proto
else 'SameProto',
284 attributes[
'NAME'] = name
287 attributes[
'MESSAGES_PROTO_RELATIVE_DIRECTORY_NAMES'] = (
291 attributes[
'MESSAGES_PROTO_FILE_NAME'] =
'messages.proto'
292 attributes[
'SERVICES_PROTO_RELATIVE_DIRECTORY_NAMES'] = (
294 attributes[
'SERVICES_PROTO_FILE_NAME'] =
'services.proto'
295 attributes[
'EXPECTED_MESSAGES_PB2'] =
'split_messages.sub.messages_pb2'
296 attributes[
'EXPECTED_SERVICES_PB2'] =
'split_services.services_pb2'
297 attributes[
'EXPECTED_SERVICES_PB2_GRPC'] = (
298 'split_services.services_pb2_grpc')
300 attributes[
'MESSAGES_PROTO_RELATIVE_DIRECTORY_NAMES'] = ()
301 attributes[
'MESSAGES_PROTO_FILE_NAME'] =
'same.proto'
302 attributes[
'SERVICES_PROTO_RELATIVE_DIRECTORY_NAMES'] = ()
303 attributes[
'SERVICES_PROTO_FILE_NAME'] =
'same.proto'
304 attributes[
'EXPECTED_MESSAGES_PB2'] =
'same_pb2'
305 attributes[
'EXPECTED_SERVICES_PB2'] =
'same_pb2'
306 attributes[
'EXPECTED_SERVICES_PB2_GRPC'] =
'same_pb2_grpc'
308 attributes[
'PROTOC_STYLE'] = protoc_style
310 attributes[
'__module__'] = _Test.__module__
312 return type(
'{}Test'.
format(name), (_Test,), attributes)
320 for protoc_style
in _PROTOC_STYLES:
326 loader.loadTestsFromTestCase(test_case_class)
328 return unittest.TestSuite(tests=tests)
331 if __name__ ==
'__main__':
332 unittest.main(verbosity=2)