Skip to content

Commit 907b77c

Browse files
committed
Updates enums, schema, and tests, plus linting
1 parent a24dfbc commit 907b77c

File tree

4 files changed

+66
-39
lines changed

4 files changed

+66
-39
lines changed

google/cloud/bigquery/enums.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -248,9 +248,9 @@ class KeyResultStatementKind:
248248
class StandardSqlTypeNames(str, enum.Enum):
249249
"""Enum of allowed SQL type names in schema.SchemaField.
250250
251-
Datatype used in GoogleSQL.
251+
Datatype used in GoogleSQL.
252252
"""
253-
253+
254254
def _generate_next_value_(name, start, count, last_values):
255255
return name
256256

@@ -273,7 +273,7 @@ def _generate_next_value_(name, start, count, last_values):
273273
STRUCT = enum.auto()
274274
RANGE = enum.auto()
275275
FOREIGN = enum.auto() # NOTE: FOREIGN acts as a wrapper for data types
276-
# not natively understood by BigQuery unless translated
276+
# not natively understood by BigQuery unless translated
277277

278278

279279
class EntityTypes(str, enum.Enum):
@@ -317,7 +317,7 @@ class SqlTypeNames(str, enum.Enum):
317317
INTERVAL = "INTERVAL" # NOTE: not available in legacy types
318318
RANGE = "RANGE" # NOTE: not available in legacy types
319319
FOREIGN = "FOREIGN" # NOTE: FOREIGN acts as a wrapper for data types
320-
# not natively understood by BigQuery unless translated
320+
# not natively understood by BigQuery unless translated
321321

322322

323323
class WriteDisposition(object):

google/cloud/bigquery/schema.py

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,34 @@ class SchemaField(object):
171171
the type is RANGE, this field is required. Possible values for the
172172
field element type of a RANGE include `DATE`, `DATETIME` and
173173
`TIMESTAMP`.
174-
TODO: add docstring here.
174+
175+
rounding_mode: Union[RoundingMode, str, None]
176+
Specifies the rounding mode to be used when storing values of
177+
NUMERIC and BIGNUMERIC type.
178+
179+
Unspecified will default to using ROUND_HALF_AWAY_FROM_ZERO.
180+
181+
ROUND_HALF_AWAY_FROM_ZERO rounds half values away from zero
182+
when applying precision and scale upon writing of NUMERIC and BIGNUMERIC
183+
values.
184+
For Scale: 0
185+
1.1, 1.2, 1.3, 1.4 => 1
186+
1.5, 1.6, 1.7, 1.8, 1.9 => 2
187+
188+
ROUND_HALF_EVEN rounds half values to the nearest even value
189+
when applying precision and scale upon writing of NUMERIC and BIGNUMERIC
190+
values.
191+
For Scale: 0
192+
1.1, 1.2, 1.3, 1.4 => 1
193+
1.5 => 2
194+
1.6, 1.7, 1.8, 1.9 => 2
195+
2.5 => 2
196+
197+
foreign_type_definition: Optional[str]
198+
Definition of the foreign data type.
199+
200+
Only valid for top-level schema fields (not nested fields).
201+
If the type is FOREIGN, this field is required.
175202
"""
176203

177204
def __init__(
@@ -191,7 +218,7 @@ def __init__(
191218
foreign_type_definition: Optional[str] = None,
192219
):
193220
self._properties: Dict[str, Any] = {}
194-
221+
195222
self._properties["name"] = name
196223
if mode is not None:
197224
self._properties["mode"] = mode.upper()
@@ -219,16 +246,18 @@ def __init__(
219246
self._properties["roundingMode"] = rounding_mode
220247
if isinstance(foreign_type_definition, str):
221248
self._properties["foreignTypeDefinition"] = foreign_type_definition
222-
223-
# The order of operations is important:
249+
250+
# The order of operations is important:
224251
# If field_type is FOREIGN, then foreign_type_definition must be set.
225252
if field_type != "FOREIGN":
226253
self._properties["type"] = field_type
227254
else:
228255
if self._properties.get("foreignTypeDefinition") is None:
229-
raise ValueError("If the 'field_type' is 'FOREIGN', then 'foreign_type_definition' is required.")
256+
raise ValueError(
257+
"If the 'field_type' is 'FOREIGN', then 'foreign_type_definition' is required."
258+
)
230259
self._properties["type"] = field_type
231-
260+
232261
self._fields = tuple(fields)
233262

234263
@staticmethod
@@ -355,26 +384,8 @@ def range_element_type(self):
355384

356385
@property
357386
def rounding_mode(self):
358-
"""Specifies the rounding mode to be used when storing values of
387+
"""Enum that specifies the rounding mode to be used when storing values of
359388
NUMERIC and BIGNUMERIC type.
360-
361-
Unspecified will default to using ROUND_HALF_AWAY_FROM_ZERO.
362-
363-
ROUND_HALF_AWAY_FROM_ZERO rounds half values away from zero
364-
when applying precision and scale upon writing of NUMERIC and BIGNUMERIC
365-
values.
366-
For Scale: 0
367-
1.1, 1.2, 1.3, 1.4 => 1
368-
1.5, 1.6, 1.7, 1.8, 1.9 => 2
369-
370-
ROUND_HALF_EVEN rounds half values to the nearest even value
371-
when applying precision and scale upon writing of NUMERIC and BIGNUMERIC
372-
values.
373-
For Scale: 0
374-
1.1, 1.2, 1.3, 1.4 => 1
375-
1.5 => 2
376-
1.6, 1.7, 1.8, 1.9 => 2
377-
2.5 => 2
378389
"""
379390
return self._properties.get("roundingMode")
380391

tests/unit/test_schema.py

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,7 @@ def test_to_standard_sql_simple_type(self):
326326
("GEOGRAPHY", bigquery.StandardSqlTypeNames.GEOGRAPHY),
327327
)
328328
for legacy_type, standard_type in examples:
329-
330-
field = self._make_one("some_field", legacy_type)
329+
field = self._make_one("some_field", legacy_type)
331330
standard_field = field.to_standard_sql()
332331
self.assertEqual(standard_field.name, "some_field")
333332
self.assertEqual(standard_field.type.type_kind, standard_type)
@@ -487,15 +486,31 @@ def test_to_standard_sql_unknown_type(self):
487486
bigquery.StandardSqlTypeNames.TYPE_KIND_UNSPECIFIED,
488487
)
489488

490-
def test_to_standard_sql_foreign_type(self):
491-
examples = (
492-
("FOREIGN", bigquery.StandardSqlTypeNames.FOREIGN, "INTEGER"),
489+
def test_to_standard_sql_foreign_type_valid(self):
490+
legacy_type = "FOREIGN"
491+
standard_type = bigquery.StandardSqlTypeNames.FOREIGN
492+
foreign_type_definition = "INTEGER"
493+
494+
field = self._make_one(
495+
"some_field",
496+
field_type=legacy_type,
497+
foreign_type_definition=foreign_type_definition,
493498
)
494-
for legacy_type, standard_type, foreign_type_definition in examples:
495-
field = self._make_one("some_field", legacy_type, foreign_type_definition=foreign_type_definition)
496-
standard_field = field.to_standard_sql()
497-
self.assertEqual(standard_field.name, "some_field")
498-
self.assertEqual(standard_field.type.type_kind, standard_type)
499+
standard_field = field.to_standard_sql()
500+
self.assertEqual(standard_field.name, "some_field")
501+
self.assertEqual(standard_field.type.type_kind, standard_type)
502+
503+
def test_to_standard_sql_foreign_type_invalid(self):
504+
legacy_type = "FOREIGN"
505+
foreign_type_definition = None
506+
507+
with self.assertRaises(ValueError) as context:
508+
self._make_one(
509+
"some_field",
510+
field_type=legacy_type,
511+
foreign_type_definition=foreign_type_definition,
512+
)
513+
self.assertTrue("If the 'field_type'" in context.exception.args[0])
499514

500515
def test___eq___wrong_type(self):
501516
field = self._make_one("test", "STRING")

tests/unit/test_table.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5928,6 +5928,7 @@ def test_external_catalog_table_options_setter(
59285928
result = table.to_api_repr()
59295929
assert result == expected
59305930

5931+
59315932
@pytest.mark.parametrize("preserve_order", [True, False])
59325933
def test_to_arrow_iterable_w_bqstorage_max_stream_count(preserve_order):
59335934
pytest.importorskip("pandas")

0 commit comments

Comments
 (0)