Skip to content

Commit be6d15d

Browse files
committed
Adds ForeignTypeInfo test_from_api_repr
1 parent 561a97b commit be6d15d

File tree

3 files changed

+134
-80
lines changed

3 files changed

+134
-80
lines changed

google/cloud/bigquery/schema.py

Lines changed: 58 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,7 @@ def _to_schema_fields(schema):
501501
sequence is not a :class:`~google.cloud.bigquery.schema.SchemaField`
502502
instance or a compatible mapping representation of the field.
503503
"""
504+
504505
for field in schema:
505506
if not isinstance(field, (SchemaField, collections.abc.Mapping)):
506507
raise ValueError(
@@ -598,59 +599,59 @@ def to_api_repr(self) -> dict:
598599
return answer
599600

600601

601-
class TableSchema:
602-
"""Schema of a table
602+
# class TableSchema:
603+
# """Schema of a table
603604

604-
Args:
605-
fields (Optional[list]): Describes the fields in a table.
606-
foreignTypeInfo (Optional[str]): Specifies metadata of the foreign data type
607-
definition in field schema.
608-
"""
605+
# Args:
606+
# fields (Optional[list]): Describes the fields in a table.
607+
# foreignTypeInfo (Optional[str]): Specifies metadata of the foreign data type
608+
# definition in field schema.
609+
# """
609610

610-
def __init__(
611-
self, fields: Optional[list] = None, foreign_type_info: Optional[str] = None
612-
):
613-
self._properties = {}
614-
self.fields = fields
615-
self.foreign_type_info = foreign_type_info
611+
# def __init__(
612+
# self, fields: Optional[list] = None, foreign_type_info: Optional[str] = None
613+
# ):
614+
# self._properties = {}
615+
# self.fields = fields
616+
# self.foreign_type_info = foreign_type_info
616617

617-
@property
618-
def fields(self) -> Any:
619-
"""Describes the fields in a table."""
618+
# @property
619+
# def fields(self) -> Any:
620+
# """Describes the fields in a table."""
620621

621-
return self._properties.get("fields")
622+
# return self._properties.get("fields")
622623

623-
@fields.setter
624-
def fields(self, value: list, dtype: str) -> str:
625-
value = _isinstance_or_raise(value, list, none_allowed=True)
626-
self._properties["fields"] = value
624+
# @fields.setter
625+
# def fields(self, value: list, dtype: str) -> str:
626+
# value = _isinstance_or_raise(value, list, none_allowed=True)
627+
# self._properties["fields"] = value
627628

628-
@property
629-
def foreign_type_info(self) -> Any:
630-
"""Optional. Specifies metadata of the foreign data type definition in
631-
field schema (TableFieldSchema.foreign_type_definition)."""
629+
# @property
630+
# def foreign_type_info(self) -> Any:
631+
# """Optional. Specifies metadata of the foreign data type definition in
632+
# field schema (TableFieldSchema.foreign_type_definition)."""
632633

633-
return self._properties.get("foreignTypeInfo")
634+
# return self._properties.get("foreignTypeInfo")
634635

635-
@foreign_type_info.setter
636-
def foreign_type_info(self, value: str, dtype: str) -> str:
637-
if not isinstance(value, str):
638-
raise ValueError(
639-
f"Pass {value} as a '{repr(dtype)}'." f"Got {type(value)}."
640-
)
641-
self._properties["foreignTypeInfo"] = value
636+
# @foreign_type_info.setter
637+
# def foreign_type_info(self, value: str, dtype: str) -> str:
638+
# if not isinstance(value, str):
639+
# raise ValueError(
640+
# f"Pass {value} as a '{repr(dtype)}'." f"Got {type(value)}."
641+
# )
642+
# self._properties["foreignTypeInfo"] = value
642643

643-
def to_api_repr(self) -> dict:
644-
"""Build an API representation of this object.
644+
# def to_api_repr(self) -> dict:
645+
# """Build an API representation of this object.
645646

646-
Returns:
647-
Dict[str, Any]:
648-
A dictionary in the format used by the BigQuery API.
649-
"""
650-
return copy.deepcopy(self._properties)
647+
# Returns:
648+
# Dict[str, Any]:
649+
# A dictionary in the format used by the BigQuery API.
650+
# """
651+
# return copy.deepcopy(self._properties)
651652

652-
def from_api_repr(self, resource):
653-
return _from_api_repr(self, resource)
653+
# def from_api_repr(self, resource):
654+
# return _from_api_repr(self, resource)
654655

655656

656657
class ForeignTypeInfo:
@@ -686,9 +687,22 @@ def to_api_repr(self) -> dict:
686687
A dictionary in the format used by the BigQuery API.
687688
"""
688689
return copy.deepcopy(self._properties)
690+
691+
@classmethod
692+
def from_api_repr(cls, resource):
693+
"""Factory: constructs an instance of the class (cls)
694+
given its API representation.
689695
690-
def from_api_repr(self, resource):
691-
return _from_api_repr(self, resource)
696+
Args:
697+
resource (Dict[str, Any]):
698+
API representation of the object to be instantiated.
699+
700+
Returns:
701+
An instance of the class initialized with data from 'resource'.
702+
"""
703+
config = cls()
704+
config._properties = copy.deepcopy(resource)
705+
return config
692706

693707

694708
class StorageDescriptor:

tests/unit/test_schema.py

Lines changed: 56 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
ForeignTypeInfo,
2020
StorageDescriptor,
2121
SerDeInfo,
22-
TableSchema,
22+
# TODO: delete this line...TableSchema,
2323
)
2424

2525
import unittest
@@ -1159,6 +1159,26 @@ def test_to_api_repr(self, type_system, expected):
11591159
result = self._make_one(type_system=type_system)
11601160
assert result.to_api_repr() == expected
11611161

1162+
def test_from_api_repr(self):
1163+
"""GIVEN an api representation of a ForeignTypeInfo object (i.e. resource)
1164+
WHEN converted into a ForeignTypeInfo object using from_api_repr() and
1165+
displayed as a dict
1166+
THEN it will have the same representation a ForeignTypeInfo object created
1167+
directly (via _make_one()) and displayed as a dict.
1168+
"""
1169+
resource = {
1170+
"typeSystem": "TYPE_SYSTEM_UNSPECIFIED"
1171+
}
1172+
1173+
expected = self._make_one(
1174+
type_system="TYPE_SYSTEM_UNSPECIFIED"
1175+
)
1176+
1177+
klass = self._get_target_class()
1178+
result = klass.from_api_repr(resource)
1179+
1180+
assert result.to_api_repr() == expected.to_api_repr()
1181+
11621182

11631183
class TestStorageDescriptor:
11641184
"""Tests for the StorageDescriptor class."""
@@ -1316,39 +1336,39 @@ def test_to_api_repr(self):
13161336

13171337
# TODO: needs a from_api_repr() test.
13181338

1319-
@pytest.fixture
1320-
def _make_foreign_type_info():
1321-
return ForeignTypeInfo(
1322-
type_system="TODO_fake_type_system",
1323-
)
1324-
1325-
1326-
class TestTableSchema:
1327-
@staticmethod
1328-
def _get_target_class():
1329-
return TableSchema
1330-
1331-
def _make_one(self, *args, **kwargs):
1332-
return self._get_target_class()(*args, **kwargs)
1333-
1334-
def test_ctor_valid_input(self, _make_foreign_type_info):
1335-
table_schema = self._make_one(
1336-
fields="TODO needs a fields object",
1337-
foreign_type_info=_make_foreign_type_info.to_api_repr(),
1338-
)
1339-
# Test default constructors
1340-
# Create expected TableSchema object
1341-
# * use target_class
1342-
# * use make_one
1343-
# Create result TableSchema object
1344-
# compare the two
1345-
assert False
1346-
1347-
def test_ctor_invalid_input(self):
1348-
assert False
1349-
1350-
def test_to_api_repr(self):
1351-
assert False
1339+
# @pytest.fixture
1340+
# def _make_foreign_type_info():
1341+
# return ForeignTypeInfo(
1342+
# type_system="TODO_fake_type_system",
1343+
# )
1344+
1345+
1346+
# class TestTableSchema:
1347+
# @staticmethod
1348+
# def _get_target_class():
1349+
# return TableSchema
1350+
1351+
# def _make_one(self, *args, **kwargs):
1352+
# return self._get_target_class()(*args, **kwargs)
1353+
1354+
# def test_ctor_valid_input(self, _make_foreign_type_info):
1355+
# table_schema = self._make_one(
1356+
# fields="TODO needs a fields object",
1357+
# foreign_type_info=_make_foreign_type_info.to_api_repr(),
1358+
# )
1359+
# # Test default constructors
1360+
# # Create expected TableSchema object
1361+
# # * use target_class
1362+
# # * use make_one
1363+
# # Create result TableSchema object
1364+
# # compare the two
1365+
# assert False
1366+
1367+
# def test_ctor_invalid_input(self):
1368+
# assert False
1369+
1370+
# def test_to_api_repr(self):
1371+
# assert False
13521372

1353-
def test_from_api_repr(self):
1354-
assert False
1373+
# def test_from_api_repr(self):
1374+
# assert False

tests/unit/test_table.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,26 @@ def test_ctor_w_schema(self):
570570

571571
self.assertEqual(table.schema, [full_name, age])
572572

573+
def test_ctor_w_schema_klass(self):
574+
from google.cloud.bigquery.schema import SchemaField
575+
from google.cloud.bigquery.schema import Schema
576+
577+
578+
dataset = DatasetReference(self.PROJECT, self.DS_ID)
579+
table_ref = dataset.table(self.TABLE_NAME)
580+
full_name = SchemaField("full_name", "STRING", mode="REQUIRED")
581+
age = SchemaField("age", "INTEGER", mode="REQUIRED")
582+
# ONLY CHANGE IN THE BODY OF THE TEST
583+
schema = Schema(foreign_type_info="EXAMPLE FTF", fields=[full_name, age])
584+
585+
table = self._make_one(table_ref, schema=schema)
586+
print(f"DINOSAUR: {schema}\n{dir(schema)}\n{type(schema)}\n{type(table.schema)}")
587+
self.assertEqual(table.schema, [full_name, age])
588+
# ADDITIONAL CHECK TEST
589+
self.assertEqual(table.schema.foreign_type_info, "EXAMPLE FTF")
590+
591+
592+
573593
def test_ctor_string(self):
574594
table = self._make_one("some-project.some_dset.some_tbl")
575595
self.assertEqual(table.project, "some-project")

0 commit comments

Comments
 (0)