@@ -284,7 +284,7 @@ def _get_comments(self, scl: SourceCodeLocation) -> List[str]:
284284
285285 return lines
286286
287- def _write_deprecation_warning (self , scl : SourceCodeLocation , default_message : str ) -> None :
287+ def _get_deprecation_message (self , scl : SourceCodeLocation , default_message : str ) -> str :
288288 msg = default_message
289289 if not self .use_default_depreaction_warnings and (comments := self ._get_comments (scl )):
290290 # Make sure the comment string is a valid python string literal
@@ -296,6 +296,10 @@ def _write_deprecation_warning(self, scl: SourceCodeLocation, default_message: s
296296 except SyntaxError as e :
297297 print (f"Warning: Deprecation comment { joined } could not be parsed as a python string literal. Using default deprecation message. { e } " , file = sys .stderr )
298298 pass
299+ return msg
300+
301+ def _write_deprecation_warning (self , scl : SourceCodeLocation , default_message : str ) -> None :
302+ msg = self ._get_deprecation_message (scl , default_message )
299303 self ._write_line (
300304 '@{}("""{}""")' ,
301305 self ._import ("warnings" , "deprecated" ),
@@ -356,16 +360,33 @@ def write_enum_values(
356360 values : Iterable [Tuple [int , d .EnumValueDescriptorProto ]],
357361 value_type : str ,
358362 scl_prefix : SourceCodeLocation ,
363+ * ,
364+ as_properties : bool = False ,
359365 ) -> None :
360366 for i , val in values :
361367 if val .name in PYTHON_RESERVED :
362368 continue
363369
364370 scl = scl_prefix + [i ]
365- self ._write_line (
366- f"{ val .name } : { value_type } # { val .number } " ,
367- )
368- self ._write_comments (scl )
371+ # Class level
372+ if as_properties :
373+ self ._write_line ("@property" )
374+ if val .options .deprecated :
375+ self ._write_deprecation_warning (
376+ scl + [d .EnumValueDescriptorProto .OPTIONS_FIELD_NUMBER ] + [d .EnumOptions .DEPRECATED_FIELD_NUMBER ],
377+ "This enum value has been marked as deprecated using proto enum value options." ,
378+ )
379+ self ._write_line (
380+ f"def { val .name } (self) -> { value_type } : { '' if self ._has_comments (scl ) else '...' } # { val .number } " ,
381+ )
382+ with self ._indent ():
383+ self ._write_comments (scl )
384+ # Module level
385+ else :
386+ self ._write_line (
387+ f"{ val .name } : { value_type } # { val .number } " ,
388+ )
389+ self ._write_comments (scl )
369390
370391 def write_module_attributes (self ) -> None :
371392 wl = self ._write_line
@@ -412,6 +433,7 @@ def write_enums(
412433 [(i , v ) for i , v in enumerate (enum .value ) if v .name not in PROTO_ENUM_RESERVED ],
413434 value_type_helper_fq ,
414435 scl + [d .EnumDescriptorProto .VALUE_FIELD_NUMBER ],
436+ as_properties = True ,
415437 )
416438 wl ("" )
417439
@@ -430,6 +452,7 @@ def write_enums(
430452 if prefix == "" :
431453 wl ("" )
432454
455+ # Write the module level constants for enum values
433456 self .write_enum_values (
434457 enumerate (enum .value ),
435458 value_type_fq ,
@@ -811,7 +834,7 @@ def write_grpc_async_hacks(self) -> None:
811834 wl ("..." )
812835 wl ("" )
813836
814- def write_grpc_stub_methods (self , service : d .ServiceDescriptorProto , scl_prefix : SourceCodeLocation , * , is_async : bool , both : bool = False , ignore_assignment_errors : bool = False ) -> None :
837+ def write_grpc_stub_methods (self , service : d .ServiceDescriptorProto , scl_prefix : SourceCodeLocation , * , is_async : bool , both : bool = False , ignore_override_errors : bool = False ) -> None :
815838 wl = self ._write_line
816839 methods = [(i , m ) for i , m in enumerate (service .method ) if m .name not in PYTHON_RESERVED ]
817840 if not methods :
@@ -822,17 +845,20 @@ def type_str(method: d.MethodDescriptorProto, is_async: bool) -> str:
822845
823846 for i , method in methods :
824847 scl = scl_prefix + [d .ServiceDescriptorProto .METHOD_FIELD_NUMBER , i ]
825- if both :
826- wl (
827- "{}: {}[{}, {}]" ,
828- method .name ,
829- self ._import ("typing" , "Union" ),
830- type_str (method , is_async = False ),
831- type_str (method , is_async = True ),
848+ wl ("@property" )
849+ if method .options .deprecated :
850+ self ._write_deprecation_warning (
851+ scl + [d .MethodDescriptorProto .OPTIONS_FIELD_NUMBER ] + [d .MethodOptions .DEPRECATED_FIELD_NUMBER ],
852+ "This method has been marked as deprecated using proto method options." ,
832853 )
854+ if both :
855+ wl ("def {}(self) -> {}[{}, {}]:{}" , method .name , self ._import ("typing" , "Union" ), type_str (method , is_async = False ), type_str (method , is_async = True ), " ..." if not self ._has_comments (scl ) else " " )
833856 else :
834- wl ("{}: {}{}" , method .name , type_str (method , is_async = is_async ), "" if not ignore_assignment_errors else " # type: ignore[assignment]" )
835- self ._write_comments (scl )
857+ wl ("def {}(self) -> {}:{}{}" , method .name , type_str (method , is_async = is_async ), " ..." if not self ._has_comments (scl ) else "" , "" if not ignore_override_errors else " # type: ignore[override]" )
858+ if self ._has_comments (scl ):
859+ with self ._indent ():
860+ if not self ._write_comments (scl ):
861+ wl ("..." )
836862
837863 def write_grpc_methods (self , service : d .ServiceDescriptorProto , scl_prefix : SourceCodeLocation ) -> None :
838864 wl = self ._write_line
@@ -924,7 +950,7 @@ def write_grpc_services(
924950 if self ._write_comments (scl ):
925951 wl ("" )
926952 wl ("def __init__(self, channel: {}) -> None: ..." , self ._import ("grpc.aio" , "Channel" ))
927- self .write_grpc_stub_methods (service , scl , is_async = True , ignore_assignment_errors = True )
953+ self .write_grpc_stub_methods (service , scl , is_async = True , ignore_override_errors = True )
928954 wl ("" )
929955
930956 # The service definition interface
0 commit comments