22
22
23
23
import base64
24
24
import copy
25
- from typing import FrozenSet , Iterable , Optional
25
+ from typing import FrozenSet , Iterable , Optional , Union
26
26
27
27
from google .cloud .bigquery ._helpers import _to_bytes
28
28
from google .cloud .bigquery ._helpers import _bytes_to_json
29
29
from google .cloud .bigquery ._helpers import _int_or_none
30
30
from google .cloud .bigquery ._helpers import _str_or_none
31
- from google .cloud .bigquery .format_options import ParquetOptions
31
+ from google .cloud .bigquery .format_options import AvroOptions , ParquetOptions
32
32
from google .cloud .bigquery .schema import SchemaField
33
33
34
34
@@ -548,7 +548,13 @@ def from_api_repr(cls, resource: dict) -> "GoogleSheetsOptions":
548
548
return config
549
549
550
550
551
- _OPTION_CLASSES = (BigtableOptions , CSVOptions , GoogleSheetsOptions , ParquetOptions )
551
+ _OPTION_CLASSES = (
552
+ AvroOptions ,
553
+ BigtableOptions ,
554
+ CSVOptions ,
555
+ GoogleSheetsOptions ,
556
+ ParquetOptions ,
557
+ )
552
558
553
559
554
560
class HivePartitioningOptions (object ):
@@ -646,11 +652,6 @@ class ExternalConfig(object):
646
652
647
653
def __init__ (self , source_format ):
648
654
self ._properties = {"sourceFormat" : source_format }
649
- self ._options = None
650
- for optcls in _OPTION_CLASSES :
651
- if source_format == optcls ._SOURCE_FORMAT :
652
- self ._options = optcls ()
653
- break
654
655
655
656
@property
656
657
def source_format (self ):
@@ -663,9 +664,17 @@ def source_format(self):
663
664
return self ._properties ["sourceFormat" ]
664
665
665
666
@property
666
- def options (self ):
667
- """Optional[Dict[str, Any]]: Source-specific options."""
668
- return self ._options
667
+ def options (self ) -> Optional [Union [_OPTION_CLASSES ]]:
668
+ """Source-specific options."""
669
+ for optcls in _OPTION_CLASSES :
670
+ if self .source_format == optcls ._SOURCE_FORMAT :
671
+ options = optcls ()
672
+ self ._properties .setdefault (optcls ._RESOURCE_NAME , {})
673
+ options ._properties = self ._properties [optcls ._RESOURCE_NAME ]
674
+ return options
675
+
676
+ # No matching source format found.
677
+ return None
669
678
670
679
@property
671
680
def autodetect (self ):
@@ -815,23 +824,120 @@ def schema(self, value):
815
824
self ._properties ["schema" ] = prop
816
825
817
826
@property
818
- def parquet_options (self ):
819
- """Optional[google.cloud.bigquery.format_options.ParquetOptions]: Additional
820
- properties to set if ``sourceFormat`` is set to PARQUET.
827
+ def avro_options (self ) -> Optional [AvroOptions ]:
828
+ """Additional properties to set if ``sourceFormat`` is set to AVRO.
829
+
830
+ See:
831
+ https://cloud.google.com/bigquery/docs/reference/rest/v2/tables#ExternalDataConfiguration.FIELDS.avro_options
832
+ """
833
+ if self .source_format == ExternalSourceFormat .AVRO :
834
+ self ._properties .setdefault (AvroOptions ._RESOURCE_NAME , {})
835
+ resource = self ._properties .get (AvroOptions ._RESOURCE_NAME )
836
+ if resource is None :
837
+ return None
838
+ options = AvroOptions ()
839
+ options ._properties = resource
840
+ return options
841
+
842
+ @avro_options .setter
843
+ def avro_options (self , value ):
844
+ if self .source_format != ExternalSourceFormat .AVRO :
845
+ msg = f"Cannot set Avro options, source format is { self .source_format } "
846
+ raise TypeError (msg )
847
+ self ._properties [AvroOptions ._RESOURCE_NAME ] = value ._properties
848
+
849
+ @property
850
+ def bigtable_options (self ) -> Optional [BigtableOptions ]:
851
+ """Additional properties to set if ``sourceFormat`` is set to BIGTABLE.
852
+
853
+ See:
854
+ https://cloud.google.com/bigquery/docs/reference/rest/v2/tables#ExternalDataConfiguration.FIELDS.bigtable_options
855
+ """
856
+ if self .source_format == ExternalSourceFormat .BIGTABLE :
857
+ self ._properties .setdefault (BigtableOptions ._RESOURCE_NAME , {})
858
+ resource = self ._properties .get (BigtableOptions ._RESOURCE_NAME )
859
+ if resource is None :
860
+ return None
861
+ options = BigtableOptions ()
862
+ options ._properties = resource
863
+ return options
864
+
865
+ @bigtable_options .setter
866
+ def bigtable_options (self , value ):
867
+ if self .source_format != ExternalSourceFormat .BIGTABLE :
868
+ msg = f"Cannot set Bigtable options, source format is { self .source_format } "
869
+ raise TypeError (msg )
870
+ self ._properties [BigtableOptions ._RESOURCE_NAME ] = value ._properties
871
+
872
+ @property
873
+ def csv_options (self ) -> Optional [CSVOptions ]:
874
+ """Additional properties to set if ``sourceFormat`` is set to CSV.
875
+
876
+ See:
877
+ https://cloud.google.com/bigquery/docs/reference/rest/v2/tables#ExternalDataConfiguration.FIELDS.csv_options
878
+ """
879
+ if self .source_format == ExternalSourceFormat .CSV :
880
+ self ._properties .setdefault (CSVOptions ._RESOURCE_NAME , {})
881
+ resource = self ._properties .get (CSVOptions ._RESOURCE_NAME )
882
+ if resource is None :
883
+ return None
884
+ options = CSVOptions ()
885
+ options ._properties = resource
886
+ return options
887
+
888
+ @csv_options .setter
889
+ def csv_options (self , value ):
890
+ if self .source_format != ExternalSourceFormat .CSV :
891
+ msg = f"Cannot set CSV options, source format is { self .source_format } "
892
+ raise TypeError (msg )
893
+ self ._properties [CSVOptions ._RESOURCE_NAME ] = value ._properties
894
+
895
+ @property
896
+ def google_sheets_options (self ) -> Optional [GoogleSheetsOptions ]:
897
+ """Additional properties to set if ``sourceFormat`` is set to
898
+ GOOGLE_SHEETS.
899
+
900
+ See:
901
+ https://cloud.google.com/bigquery/docs/reference/rest/v2/tables#ExternalDataConfiguration.FIELDS.google_sheets_options
902
+ """
903
+ if self .source_format == ExternalSourceFormat .GOOGLE_SHEETS :
904
+ self ._properties .setdefault (GoogleSheetsOptions ._RESOURCE_NAME , {})
905
+ resource = self ._properties .get (GoogleSheetsOptions ._RESOURCE_NAME )
906
+ if resource is None :
907
+ return None
908
+ options = GoogleSheetsOptions ()
909
+ options ._properties = resource
910
+ return options
911
+
912
+ @google_sheets_options .setter
913
+ def google_sheets_options (self , value ):
914
+ if self .source_format != ExternalSourceFormat .GOOGLE_SHEETS :
915
+ msg = f"Cannot set Google Sheets options, source format is { self .source_format } "
916
+ raise TypeError (msg )
917
+ self ._properties [GoogleSheetsOptions ._RESOURCE_NAME ] = value ._properties
918
+
919
+ @property
920
+ def parquet_options (self ) -> Optional [ParquetOptions ]:
921
+ """Additional properties to set if ``sourceFormat`` is set to PARQUET.
821
922
822
923
See:
823
924
https://cloud.google.com/bigquery/docs/reference/rest/v2/tables#ExternalDataConfiguration.FIELDS.parquet_options
824
925
"""
825
- if self .source_format != ExternalSourceFormat .PARQUET :
926
+ if self .source_format == ExternalSourceFormat .PARQUET :
927
+ self ._properties .setdefault (ParquetOptions ._RESOURCE_NAME , {})
928
+ resource = self ._properties .get (ParquetOptions ._RESOURCE_NAME )
929
+ if resource is None :
826
930
return None
827
- return self ._options
931
+ options = ParquetOptions ()
932
+ options ._properties = resource
933
+ return options
828
934
829
935
@parquet_options .setter
830
936
def parquet_options (self , value ):
831
937
if self .source_format != ExternalSourceFormat .PARQUET :
832
938
msg = f"Cannot set Parquet options, source format is { self .source_format } "
833
939
raise TypeError (msg )
834
- self ._options = value
940
+ self ._properties [ ParquetOptions . _RESOURCE_NAME ] = value . _properties
835
941
836
942
def to_api_repr (self ) -> dict :
837
943
"""Build an API representation of this object.
@@ -841,10 +947,6 @@ def to_api_repr(self) -> dict:
841
947
A dictionary in the format used by the BigQuery API.
842
948
"""
843
949
config = copy .deepcopy (self ._properties )
844
- if self .options is not None :
845
- r = self .options .to_api_repr ()
846
- if r != {}:
847
- config [self .options ._RESOURCE_NAME ] = r
848
950
return config
849
951
850
952
@classmethod
@@ -862,10 +964,5 @@ def from_api_repr(cls, resource: dict) -> "ExternalConfig":
862
964
ExternalConfig: Configuration parsed from ``resource``.
863
965
"""
864
966
config = cls (resource ["sourceFormat" ])
865
- for optcls in _OPTION_CLASSES :
866
- opts = resource .get (optcls ._RESOURCE_NAME )
867
- if opts is not None :
868
- config ._options = optcls .from_api_repr (opts )
869
- break
870
967
config ._properties = copy .deepcopy (resource )
871
968
return config
0 commit comments