@@ -315,7 +315,7 @@ def _get_comments(self, scl: SourceCodeLocation) -> List[str]:
315315
316316 return lines
317317
318- def _write_deprecation_warning (self , scl : SourceCodeLocation , default_message : str ) -> None :
318+ def _get_deprecation_message (self , scl : SourceCodeLocation , default_message : str ) -> str :
319319 msg = default_message
320320 if not self .use_default_depreaction_warnings and (comments := self ._get_comments (scl )):
321321 # Make sure the comment string is a valid python string literal
@@ -327,6 +327,10 @@ def _write_deprecation_warning(self, scl: SourceCodeLocation, default_message: s
327327 except SyntaxError as e :
328328 print (f"Warning: Deprecation comment { joined } could not be parsed as a python string literal. Using default deprecation message. { e } " , file = sys .stderr )
329329 pass
330+ return msg
331+
332+ def _write_deprecation_warning (self , scl : SourceCodeLocation , default_message : str ) -> None :
333+ msg = self ._get_deprecation_message (scl , default_message )
330334 self ._write_line (
331335 '@{}("""{}""")' ,
332336 self ._import ("warnings" , "deprecated" ),
@@ -387,16 +391,33 @@ def write_enum_values(
387391 values : Iterable [Tuple [int , d .EnumValueDescriptorProto ]],
388392 value_type : str ,
389393 scl_prefix : SourceCodeLocation ,
394+ * ,
395+ as_properties : bool = False ,
390396 ) -> None :
391397 for i , val in values :
392398 if val .name in PYTHON_RESERVED :
393399 continue
394400
395401 scl = scl_prefix + [i ]
396- self ._write_line (
397- f"{ val .name } : { value_type } # { val .number } " ,
398- )
399- self ._write_comments (scl )
402+ # Class level
403+ if as_properties :
404+ self ._write_line ("@property" )
405+ if val .options .deprecated :
406+ self ._write_deprecation_warning (
407+ scl + [d .EnumValueDescriptorProto .OPTIONS_FIELD_NUMBER ] + [d .EnumOptions .DEPRECATED_FIELD_NUMBER ],
408+ "This enum value has been marked as deprecated using proto enum value options." ,
409+ )
410+ self ._write_line (
411+ f"def { val .name } (self) -> { value_type } : { '' if self ._has_comments (scl ) else '...' } # { val .number } " ,
412+ )
413+ with self ._indent ():
414+ self ._write_comments (scl )
415+ # Module level
416+ else :
417+ self ._write_line (
418+ f"{ val .name } : { value_type } # { val .number } " ,
419+ )
420+ self ._write_comments (scl )
400421
401422 def write_module_attributes (self ) -> None :
402423 wl = self ._write_line
@@ -443,6 +464,7 @@ def write_enums(
443464 [(i , v ) for i , v in enumerate (enum_proto .value ) if v .name not in PROTO_ENUM_RESERVED ],
444465 value_type_helper_fq ,
445466 scl + [d .EnumDescriptorProto .VALUE_FIELD_NUMBER ],
467+ as_properties = True ,
446468 )
447469 wl ("" )
448470
@@ -461,6 +483,7 @@ def write_enums(
461483 if prefix == "" :
462484 wl ("" )
463485
486+ # Write the module level constants for enum values
464487 self .write_enum_values (
465488 enumerate (enum_proto .value ),
466489 value_type_fq ,
@@ -878,7 +901,7 @@ def write_grpc_servicer_context(self) -> None:
878901 wl ("..." )
879902 wl ("" )
880903
881- def write_grpc_stub_methods (self , service : d .ServiceDescriptorProto , scl_prefix : SourceCodeLocation , * , is_async : bool , both : bool = False , ignore_assignment_errors : bool = False ) -> None :
904+ def write_grpc_stub_methods (self , service : d .ServiceDescriptorProto , scl_prefix : SourceCodeLocation , * , is_async : bool , both : bool = False , ignore_override_errors : bool = False ) -> None :
882905 wl = self ._write_line
883906 methods = [(i , m ) for i , m in enumerate (service .method ) if m .name not in PYTHON_RESERVED ]
884907 if not methods :
@@ -889,17 +912,20 @@ def type_str(method: d.MethodDescriptorProto, is_async: bool) -> str:
889912
890913 for i , method in methods :
891914 scl = scl_prefix + [d .ServiceDescriptorProto .METHOD_FIELD_NUMBER , i ]
892- if both :
893- wl (
894- "{}: {}[{}, {}]" ,
895- method .name ,
896- self ._import ("typing" , "Union" ),
897- type_str (method , is_async = False ),
898- type_str (method , is_async = True ),
915+ wl ("@property" )
916+ if method .options .deprecated :
917+ self ._write_deprecation_warning (
918+ scl + [d .MethodDescriptorProto .OPTIONS_FIELD_NUMBER ] + [d .MethodOptions .DEPRECATED_FIELD_NUMBER ],
919+ "This method has been marked as deprecated using proto method options." ,
899920 )
921+ if both :
922+ 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 " " )
900923 else :
901- wl ("{}: {}{}" , method .name , type_str (method , is_async = is_async ), "" if not ignore_assignment_errors else " # type: ignore[assignment]" )
902- self ._write_comments (scl )
924+ 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]" )
925+ if self ._has_comments (scl ):
926+ with self ._indent ():
927+ if not self ._write_comments (scl ):
928+ wl ("..." )
903929
904930 def write_grpc_methods (self , service : d .ServiceDescriptorProto , scl_prefix : SourceCodeLocation ) -> None :
905931 wl = self ._write_line
0 commit comments