@@ -123,8 +123,29 @@ def generate_urn_files(out_dir, api_path):
123123 This is executed at build time rather than dynamically on import to ensure
124124 that it is compatible with static type checkers like mypy.
125125 """
126- from google ._upb import _message
127126 from google .protobuf import message
127+ from google .protobuf .internal import api_implementation
128+ if api_implementation .Type () == 'python' :
129+ from google .protobuf .internal import containers
130+ repeated_types = (
131+ list ,
132+ containers .RepeatedScalarFieldContainer ,
133+ containers .RepeatedCompositeFieldContainer )
134+ elif api_implementation .Type () == 'upb' :
135+ from google ._upb import _message
136+ repeated_types = (
137+ list ,
138+ _message .RepeatedScalarContainer ,
139+ _message .RepeatedCompositeContainer )
140+ elif api_implementation .Type () == 'cpp' :
141+ from google .protobuf .pyext import _message
142+ repeated_types = (
143+ list ,
144+ _message .RepeatedScalarContainer ,
145+ _message .RepeatedCompositeContainer )
146+ else :
147+ raise TypeError (
148+ "Unknown proto implementation: " + api_implementation .Type ())
128149
129150 class Context (object ):
130151 INDENT = ' '
@@ -175,13 +196,7 @@ def is_enum_type(obj):
175196 def python_repr (self , obj ):
176197 if isinstance (obj , message .Message ):
177198 return self .message_repr (obj )
178- elif isinstance (
179- obj ,
180- (
181- list ,
182- _message .RepeatedScalarContainer ,
183- _message .RepeatedCompositeContainer ,
184- )): # pylint: disable=c-extension-no-member
199+ elif isinstance (obj , repeated_types ):
185200 return '[%s]' % ', ' .join (self .python_repr (x ) for x in obj )
186201 else :
187202 return repr (obj )
@@ -501,20 +516,21 @@ def generate_proto_files(force=False):
501516 with PythonPath (grpcio_install_loc ):
502517 from grpc_tools import protoc
503518 builtin_protos = pkg_resources .resource_filename ('grpc_tools' , '_proto' )
504- args = ([sys .executable ] + # expecting to be called from command line
505- ['--proto_path=%s' % builtin_protos ] +
506- ['--proto_path=%s' % d
507- for d in proto_dirs ] + ['--python_out=%s' % PYTHON_OUTPUT_PATH ] +
508- ['--plugin=protoc-gen-mypy=%s' % protoc_gen_mypy ] +
509- # new version of mypy-protobuf converts None to zero default value
510- # and remove Optional from the param type annotation. This causes
511- # some mypy errors. So to mitigate and fall back to old behavior,
512- # use `relax_strict_optional_primitives` flag. more at
513- # https://github.com/nipunn1313/mypy-protobuf/tree/main#relax_strict_optional_primitives # pylint:disable=line-too-long
514- ['--mypy_out=relax_strict_optional_primitives:%s' % PYTHON_OUTPUT_PATH ] +
515- # TODO(robertwb): Remove the prefix once it's the default.
516- ['--grpc_python_out=grpc_2_0:%s' % PYTHON_OUTPUT_PATH ] +
517- proto_files )
519+ args = (
520+ [sys .executable ] + # expecting to be called from command line
521+ ['--proto_path=%s' % builtin_protos ] +
522+ ['--proto_path=%s' % d
523+ for d in proto_dirs ] + ['--python_out=%s' % PYTHON_OUTPUT_PATH ] +
524+ ['--plugin=protoc-gen-mypy=%s' % protoc_gen_mypy ] +
525+ # new version of mypy-protobuf converts None to zero default value
526+ # and remove Optional from the param type annotation. This causes
527+ # some mypy errors. So to mitigate and fall back to old behavior,
528+ # use `relax_strict_optional_primitives` flag. more at
529+ # https://github.com/nipunn1313/mypy-protobuf/tree/main#relax_strict_optional_primitives # pylint:disable=line-too-long
530+ ['--mypy_out=relax_strict_optional_primitives:%s' % PYTHON_OUTPUT_PATH
531+ ] +
532+ # TODO(robertwb): Remove the prefix once it's the default.
533+ ['--grpc_python_out=grpc_2_0:%s' % PYTHON_OUTPUT_PATH ] + proto_files )
518534
519535 LOG .info ('Regenerating Python proto definitions (%s).' % regenerate_reason )
520536 ret_code = protoc .main (args )
0 commit comments