3434from gapic .schema import wrappers
3535from gapic .schema import naming as api_naming
3636from gapic .utils import cached_property
37+ from gapic .utils import nth
3738from gapic .utils import to_snake_case
3839from gapic .utils import RESERVED_NAMES
3940
@@ -556,14 +557,42 @@ def _load_children(self,
556557 answer [wrapped .name ] = wrapped
557558 return answer
558559
560+ def _get_oneofs (self ,
561+ oneof_pbs : Sequence [descriptor_pb2 .OneofDescriptorProto ],
562+ address : metadata .Address , path : Tuple [int , ...],
563+ ) -> Dict [str , wrappers .Oneof ]:
564+ """Return a dictionary of wrapped oneofs for the given message.
565+
566+ Args:
567+ oneof_fields (Sequence[~.descriptor_pb2.OneofDescriptorProto]): A
568+ sequence of protobuf field objects.
569+ address (~.metadata.Address): An address object denoting the
570+ location of these oneofs.
571+ path (Tuple[int]): The source location path thus far, as
572+ understood by ``SourceCodeInfo.Location``.
573+
574+ Returns:
575+ Mapping[str, ~.wrappers.Oneof]: A ordered mapping of
576+ :class:`~.wrappers.Oneof` objects.
577+ """
578+ # Iterate over the oneofs and collect them into a dictionary.
579+ answer = collections .OrderedDict (
580+ (oneof_pb .name , wrappers .Oneof (oneof_pb = oneof_pb ))
581+ for i , oneof_pb in enumerate (oneof_pbs )
582+ )
583+
584+ # Done; return the answer.
585+ return answer
586+
559587 def _get_fields (self ,
560588 field_pbs : Sequence [descriptor_pb2 .FieldDescriptorProto ],
561589 address : metadata .Address , path : Tuple [int , ...],
590+ oneofs : Optional [Dict [str , wrappers .Oneof ]] = None
562591 ) -> Dict [str , wrappers .Field ]:
563592 """Return a dictionary of wrapped fields for the given message.
564593
565594 Args:
566- fields (Sequence[~.descriptor_pb2.FieldDescriptorProto]): A
595+ field_pbs (Sequence[~.descriptor_pb2.FieldDescriptorProto]): A
567596 sequence of protobuf field objects.
568597 address (~.metadata.Address): An address object denoting the
569598 location of these fields.
@@ -585,7 +614,13 @@ def _get_fields(self,
585614 # first) and this will be None. This case is addressed in the
586615 # `_load_message` method.
587616 answer : Dict [str , wrappers .Field ] = collections .OrderedDict ()
588- for field_pb , i in zip (field_pbs , range (0 , sys .maxsize )):
617+ for i , field_pb in enumerate (field_pbs ):
618+ is_oneof = oneofs and field_pb .oneof_index > 0
619+ oneof_name = nth (
620+ (oneofs or {}).keys (),
621+ field_pb .oneof_index
622+ ) if is_oneof else None
623+
589624 answer [field_pb .name ] = wrappers .Field (
590625 field_pb = field_pb ,
591626 enum = self .api_enums .get (field_pb .type_name .lstrip ('.' )),
@@ -594,6 +629,7 @@ def _get_fields(self,
594629 address = address .child (field_pb .name , path + (i ,)),
595630 documentation = self .docs .get (path + (i ,), self .EMPTY ),
596631 ),
632+ oneof = oneof_name ,
597633 )
598634
599635 # Done; return the answer.
@@ -779,19 +815,25 @@ def _load_message(self,
779815 loader = self ._load_message ,
780816 path = path + (3 ,),
781817 )
782- # self._load_children(message.oneof_decl, loader=self._load_field,
783- # address=nested_addr, info=info.get(8, {}))
818+
819+ oneofs = self ._get_oneofs (
820+ message_pb .oneof_decl ,
821+ address = address ,
822+ path = path + (7 ,),
823+ )
784824
785825 # Create a dictionary of all the fields for this message.
786826 fields = self ._get_fields (
787827 message_pb .field ,
788828 address = address ,
789829 path = path + (2 ,),
830+ oneofs = oneofs ,
790831 )
791832 fields .update (self ._get_fields (
792833 message_pb .extension ,
793834 address = address ,
794835 path = path + (6 ,),
836+ oneofs = oneofs ,
795837 ))
796838
797839 # Create a message correspoding to this descriptor.
@@ -804,6 +846,7 @@ def _load_message(self,
804846 address = address ,
805847 documentation = self .docs .get (path , self .EMPTY ),
806848 ),
849+ oneofs = oneofs ,
807850 )
808851 return self .proto_messages [address .proto ]
809852
0 commit comments