Skip to content

Commit c928620

Browse files
committed
Adds ExternalCatalogTableOptions and tests
1 parent 86c504d commit c928620

File tree

4 files changed

+110
-12
lines changed

4 files changed

+110
-12
lines changed

google/cloud/bigquery/external_config.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,7 +1109,7 @@ def __init__(
11091109
self.storage_descriptor = storage_descriptor
11101110

11111111
@property
1112-
def connection_id(self):
1112+
def connection_id(self) -> Optional[str]:
11131113
"""Optional. The connection specifying the credentials to be
11141114
used to read external storage, such as Azure Blob, Cloud Storage, or
11151115
S3. The connection is needed to read the open source table from
@@ -1125,7 +1125,7 @@ def connection_id(self, value: Optional[str]):
11251125
self._properties["connectionId"] = value
11261126

11271127
@property
1128-
def parameters(self) -> Any:
1128+
def parameters(self) -> Union[Dict[str, Any], None]:
11291129
"""Optional. A map of key value pairs defining the parameters and
11301130
properties of the open source table. Corresponds with hive meta
11311131
store table parameters. Maximum size of 4Mib.
@@ -1150,7 +1150,7 @@ def storage_descriptor(self) -> Any:
11501150
return None
11511151

11521152
@storage_descriptor.setter
1153-
def storage_descriptor(self, value):
1153+
def storage_descriptor(self, value: Union[schema.StorageDescriptor, dict, None]):
11541154
value = _helpers._isinstance_or_raise(
11551155
value, (schema.StorageDescriptor, dict), none_allowed=True
11561156
)

google/cloud/bigquery/magics/magics.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
bigquery_magics = None
5757

5858

59-
IPYTHON_USER_AGENT = "ipython-{}".format(IPython.__version__)
59+
IPYTHON_USER_AGENT = "ipython-{}".format(IPython.__version__) # type: ignore
6060

6161

6262
class Context(object):

google/cloud/bigquery/table.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,7 +1026,9 @@ def table_constraints(self) -> Optional["TableConstraints"]:
10261026
return table_constraints
10271027

10281028
@property
1029-
def external_catalog_table_options(self):
1029+
def external_catalog_table_options(
1030+
self,
1031+
) -> Optional[external_config.ExternalCatalogTableOptions]:
10301032
"""Options defining open source compatible datasets living in the
10311033
BigQuery catalog. Contains metadata of open source database, schema
10321034
or namespace represented by the current dataset."""
@@ -1035,17 +1037,26 @@ def external_catalog_table_options(self):
10351037
self._PROPERTY_TO_API_FIELD["external_catalog_table_options"]
10361038
)
10371039
if prop is not None:
1038-
prop = external_config.ExternalCatalogTableOptions.from_api_repr(prop)
1039-
return prop
1040+
return external_config.ExternalCatalogTableOptions.from_api_repr(prop)
1041+
return None
10401042

10411043
@external_catalog_table_options.setter
1042-
def external_catalog_table_options(self, value):
1044+
def external_catalog_table_options(
1045+
self, value: Union[external_config.ExternalCatalogTableOptions, dict, None]
1046+
):
10431047
value = _helpers._isinstance_or_raise(
1044-
value, external_config.ExternalCatalogTableOptions, none_allowed=True
1048+
value,
1049+
(external_config.ExternalCatalogTableOptions, dict),
1050+
none_allowed=True,
10451051
)
1046-
self._properties[
1047-
self._PROPERTY_TO_API_FIELD["external_catalog_table_options"]
1048-
] = value.to_api_repr()
1052+
if isinstance(value, external_config.ExternalCatalogTableOptions):
1053+
self._properties[
1054+
self._PROPERTY_TO_API_FIELD["external_catalog_table_options"]
1055+
] = value.to_api_repr()
1056+
else:
1057+
self._properties[
1058+
self._PROPERTY_TO_API_FIELD["external_catalog_table_options"]
1059+
] = value
10491060

10501061
@classmethod
10511062
def from_string(cls, full_table_id: str) -> "Table":

tests/unit/test_table.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
from google.cloud.bigquery import _versions_helpers
3232
from google.cloud.bigquery import exceptions
33+
from google.cloud.bigquery import external_config
3334
from google.cloud.bigquery.table import TableReference
3435
from google.cloud.bigquery.dataset import DatasetReference
3536

@@ -5879,6 +5880,92 @@ def test_from_api_repr_only_foreign_keys_resource(self):
58795880
self.assertIsNotNone(instance.foreign_keys)
58805881

58815882

5883+
class TestExternalCatalogTableOptions:
5884+
PROJECT = "test-project"
5885+
DATASET_ID = "test_dataset"
5886+
TABLE_ID = "coffee_table"
5887+
DATASET = DatasetReference(PROJECT, DATASET_ID)
5888+
TABLEREF = DATASET.table(TABLE_ID)
5889+
5890+
@staticmethod
5891+
def _get_target_class(self):
5892+
from google.cloud.bigquery.table import Table
5893+
5894+
return Table
5895+
5896+
def _make_one(self, *args, **kw):
5897+
return self._get_target_class(self)(*args, **kw)
5898+
5899+
EXTERNALCATALOGTABLEOPTIONS = {
5900+
"connection_id": "connection123",
5901+
"parameters": {"key": "value"},
5902+
"storage_descriptor": {
5903+
"input_format": "testpath.to.OrcInputFormat",
5904+
"location_uri": "gs://test/path/",
5905+
"output_format": "testpath.to.OrcOutputFormat",
5906+
"serde_info": {
5907+
"serialization_library": "testpath.to.LazySimpleSerDe",
5908+
"name": "serde_lib_name",
5909+
"parameters": {"key": "value"},
5910+
},
5911+
},
5912+
}
5913+
5914+
def test_external_catalog_table_options_default_initialization(self):
5915+
table = self._make_one(self.TABLEREF)
5916+
5917+
assert table.external_catalog_table_options is None
5918+
5919+
def test_external_catalog_table_options_valid_inputs(self):
5920+
table = self._make_one(self.TABLEREF)
5921+
5922+
# supplied in api_repr format
5923+
table.external_catalog_table_options = self.EXTERNALCATALOGTABLEOPTIONS
5924+
result = table.external_catalog_table_options.to_api_repr()
5925+
expected = self.EXTERNALCATALOGTABLEOPTIONS
5926+
assert result == expected
5927+
5928+
# supplied in obj format
5929+
ecto = external_config.ExternalCatalogTableOptions.from_api_repr(
5930+
self.EXTERNALCATALOGTABLEOPTIONS
5931+
)
5932+
assert isinstance(ecto, external_config.ExternalCatalogTableOptions)
5933+
5934+
table.external_catalog_table_options = ecto
5935+
result = table.external_catalog_table_options.to_api_repr()
5936+
expected = self.EXTERNALCATALOGTABLEOPTIONS
5937+
assert result == expected
5938+
5939+
def test_external_catalog_table_options_invalid_input(self):
5940+
table = self._make_one(self.TABLEREF)
5941+
5942+
# invalid on the whole
5943+
with pytest.raises(TypeError) as e:
5944+
table.external_catalog_table_options = 123
5945+
5946+
# Looking for the first word from the string "Pass <variable> as..."
5947+
assert "Pass " in str(e.value)
5948+
5949+
def test_external_catalog_table_options_to_api_repr(self):
5950+
table = self._make_one(self.TABLEREF)
5951+
5952+
table.external_catalog_table_options = self.EXTERNALCATALOGTABLEOPTIONS
5953+
result = table.external_catalog_table_options.to_api_repr()
5954+
expected = self.EXTERNALCATALOGTABLEOPTIONS
5955+
assert result == expected
5956+
5957+
def test_external_catalog_table_options_from_api_repr(self):
5958+
table = self._make_one(self.TABLEREF)
5959+
5960+
table.external_catalog_table_options = self.EXTERNALCATALOGTABLEOPTIONS
5961+
ecto = external_config.ExternalCatalogTableOptions.from_api_repr(
5962+
self.EXTERNALCATALOGTABLEOPTIONS
5963+
)
5964+
result = ecto.to_api_repr()
5965+
expected = self.EXTERNALCATALOGTABLEOPTIONS
5966+
assert result == expected
5967+
5968+
58825969
@pytest.mark.parametrize(
58835970
"table_path",
58845971
(

0 commit comments

Comments
 (0)