Skip to content

Commit ad71754

Browse files
committed
feat: Adds ForeignTypeInfo class and tests (#2110)
* Adds ForeignTypeInfo class and tests * Tweak to docstring * minor adjustment in test to enhance code coverage * Updates spacing in docstrings * More updates to spacing in docstrings.
1 parent 04a335c commit ad71754

File tree

2 files changed

+131
-4
lines changed

2 files changed

+131
-4
lines changed

google/cloud/bigquery/schema.py

+62-2
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,63 @@ def to_api_repr(self) -> dict:
560560
return answer
561561

562562

563+
class ForeignTypeInfo:
564+
"""Metadata about the foreign data type definition such as the system in which the
565+
type is defined.
566+
567+
Args:
568+
type_system (str): Required. Specifies the system which defines the
569+
foreign data type.
570+
571+
TypeSystem enum currently includes:
572+
* "TYPE_SYSTEM_UNSPECIFIED"
573+
* "HIVE"
574+
"""
575+
576+
def __init__(self, type_system: Optional[str] = None):
577+
self._properties: Dict[str, Any] = {}
578+
self.type_system = type_system
579+
580+
@property
581+
def type_system(self) -> Optional[str]:
582+
"""Required. Specifies the system which defines the foreign data
583+
type."""
584+
585+
return self._properties.get("typeSystem")
586+
587+
@type_system.setter
588+
def type_system(self, value: Optional[str]):
589+
value = _helpers._isinstance_or_raise(value, str, none_allowed=True)
590+
self._properties["typeSystem"] = value
591+
592+
def to_api_repr(self) -> dict:
593+
"""Build an API representation of this object.
594+
595+
Returns:
596+
Dict[str, Any]:
597+
A dictionary in the format used by the BigQuery API.
598+
"""
599+
600+
return self._properties
601+
602+
@classmethod
603+
def from_api_repr(cls, api_repr: Dict[str, Any]) -> "ForeignTypeInfo":
604+
"""Factory: constructs an instance of the class (cls)
605+
given its API representation.
606+
607+
Args:
608+
api_repr (Dict[str, Any]):
609+
API representation of the object to be instantiated.
610+
611+
Returns:
612+
An instance of the class initialized with data from 'api_repr'.
613+
"""
614+
615+
config = cls()
616+
config._properties = api_repr
617+
return config
618+
619+
563620
class SerDeInfo:
564621
"""Serializer and deserializer information.
565622
@@ -625,6 +682,7 @@ def parameters(self, value: Optional[dict[str, str]] = None):
625682

626683
def to_api_repr(self) -> dict:
627684
"""Build an API representation of this object.
685+
628686
Returns:
629687
Dict[str, Any]:
630688
A dictionary in the format used by the BigQuery API.
@@ -635,11 +693,13 @@ def to_api_repr(self) -> dict:
635693
def from_api_repr(cls, api_repr: dict) -> SerDeInfo:
636694
"""Factory: constructs an instance of the class (cls)
637695
given its API representation.
696+
638697
Args:
639-
resource (Dict[str, Any]):
698+
api_repr (Dict[str, Any]):
640699
API representation of the object to be instantiated.
700+
641701
Returns:
642-
An instance of the class initialized with data from 'resource'.
702+
An instance of the class initialized with data from 'api_repr'.
643703
"""
644704
config = cls("PLACEHOLDER")
645705
config._properties = api_repr

tests/unit/test_schema.py

+69-2
Original file line numberDiff line numberDiff line change
@@ -1128,6 +1128,73 @@ def test_to_api_repr_parameterized(field, api):
11281128
assert SchemaField(**field).to_api_repr() == api
11291129

11301130

1131+
class TestForeignTypeInfo:
1132+
"""Tests for ForeignTypeInfo objects."""
1133+
1134+
@staticmethod
1135+
def _get_target_class():
1136+
from google.cloud.bigquery.schema import ForeignTypeInfo
1137+
1138+
return ForeignTypeInfo
1139+
1140+
def _make_one(self, *args, **kw):
1141+
return self._get_target_class()(*args, **kw)
1142+
1143+
@pytest.mark.parametrize(
1144+
"type_system,expected",
1145+
[
1146+
(None, None),
1147+
("TYPE_SYSTEM_UNSPECIFIED", "TYPE_SYSTEM_UNSPECIFIED"),
1148+
("HIVE", "HIVE"),
1149+
],
1150+
)
1151+
def test_ctor_valid_input(self, type_system, expected):
1152+
result = self._make_one(type_system=type_system)
1153+
1154+
assert result.type_system == expected
1155+
1156+
def test_ctor_invalid_input(self):
1157+
with pytest.raises(TypeError) as e:
1158+
self._make_one(type_system=123)
1159+
1160+
# Looking for the first word from the string "Pass <variable> as..."
1161+
assert "Pass " in str(e.value)
1162+
1163+
@pytest.mark.parametrize(
1164+
"type_system,expected",
1165+
[
1166+
("TYPE_SYSTEM_UNSPECIFIED", {"typeSystem": "TYPE_SYSTEM_UNSPECIFIED"}),
1167+
("HIVE", {"typeSystem": "HIVE"}),
1168+
(None, {"typeSystem": None}),
1169+
],
1170+
)
1171+
def test_to_api_repr(self, type_system, expected):
1172+
result = self._make_one(type_system=type_system)
1173+
1174+
assert result.to_api_repr() == expected
1175+
1176+
def test_from_api_repr(self):
1177+
"""GIVEN an api representation of a ForeignTypeInfo object (i.e. api_repr)
1178+
WHEN converted into a ForeignTypeInfo object using from_api_repr()
1179+
THEN it will have the same representation in dict format as a ForeignTypeInfo
1180+
object made directly (via _make_one()) and represented in dict format.
1181+
"""
1182+
api_repr = {
1183+
"typeSystem": "TYPE_SYSTEM_UNSPECIFIED",
1184+
}
1185+
1186+
expected = self._make_one(
1187+
type_system="TYPE_SYSTEM_UNSPECIFIED",
1188+
)
1189+
1190+
klass = self._get_target_class()
1191+
result = klass.from_api_repr(api_repr)
1192+
1193+
# We convert both to dict format because these classes do not have a
1194+
# __eq__() method to facilitate direct equality comparisons.
1195+
assert result.to_api_repr() == expected.to_api_repr()
1196+
1197+
11311198
class TestSerDeInfo:
11321199
"""Tests for the SerDeInfo class."""
11331200

@@ -1190,9 +1257,9 @@ def test_to_api_repr(self):
11901257
assert serde_info.to_api_repr() == expected_repr
11911258

11921259
def test_from_api_repr(self):
1193-
"""GIVEN an api representation of a SerDeInfo object (i.e. resource)
1260+
"""GIVEN an api representation of a SerDeInfo object (i.e. api_repr)
11941261
WHEN converted into a SerDeInfo object using from_api_repr()
1195-
THEN it will have the representation in dict format as a SerDeInfo
1262+
THEN it will have the same representation in dict format as a SerDeInfo
11961263
object made directly (via _make_one()) and represented in dict format.
11971264
"""
11981265
api_repr = {

0 commit comments

Comments
 (0)