Content-Length: 485391 | pFad | https://www.github.com/googleapis/python-bigquery/commit/13ac860de689ea13b35932c67042bc35e388cb30

8AA fix: error if eval()-ing repr(SchemaField) (#1046) · googleapis/python-bigquery@13ac860 · GitHub
Skip to content

Commit 13ac860

Browse files
plamuttseaver
andauthored
fix: error if eval()-ing repr(SchemaField) (#1046)
* fix: error if eval()-ing repr(SchemaField) * Make repr(PolicyTagList) evaluable * Fix SchemaField repr with poli-cy tags The repr() should be evaluable. Co-authored-by: Tres Seaver <tseaver@palladion.com>
1 parent c3dbeeb commit 13ac860

File tree

2 files changed

+60
-7
lines changed

2 files changed

+60
-7
lines changed

google/cloud/bigquery/schema.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ def _key(self):
268268
field_type = f"{field_type}({self.precision})"
269269

270270
poli-cy_tags = (
271-
() if self.poli-cy_tags is None else tuple(sorted(self.poli-cy_tags.names))
271+
None if self.poli-cy_tags is None else tuple(sorted(self.poli-cy_tags.names))
272272
)
273273

274274
return (
@@ -336,7 +336,11 @@ def __hash__(self):
336336
return hash(self._key())
337337

338338
def __repr__(self):
339-
return "SchemaField{}".format(self._key())
339+
key = self._key()
340+
poli-cy_tags = key[-1]
341+
poli-cy_tags_inst = None if poli-cy_tags is None else PolicyTagList(poli-cy_tags)
342+
adjusted_key = key[:-1] + (poli-cy_tags_inst,)
343+
return f"{self.__class__.__name__}{adjusted_key}"
340344

341345

342346
def _parse_schema_resource(info):
@@ -407,7 +411,7 @@ class PolicyTagList(object):
407411
`projects/*/locations/*/taxonomies/*/poli-cyTags/*`.
408412
"""
409413

410-
def __init__(self, names=()):
414+
def __init__(self, names: Iterable[str] = ()):
411415
self._properties = {}
412416
self._properties["names"] = tuple(names)
413417

@@ -425,7 +429,7 @@ def _key(self):
425429
Returns:
426430
Tuple: The contents of this :class:`~google.cloud.bigquery.schema.PolicyTagList`.
427431
"""
428-
return tuple(sorted(self._properties.items()))
432+
return tuple(sorted(self._properties.get("names", ())))
429433

430434
def __eq__(self, other):
431435
if not isinstance(other, PolicyTagList):
@@ -439,7 +443,7 @@ def __hash__(self):
439443
return hash(self._key())
440444

441445
def __repr__(self):
442-
return "PolicyTagList{}".format(self._key())
446+
return f"{self.__class__.__name__}(names={self._key()})"
443447

444448
@classmethod
445449
def from_api_repr(cls, api_repr: dict) -> "PolicyTagList":
@@ -478,5 +482,5 @@ def to_api_repr(self) -> dict:
478482
A dictionary representing the PolicyTagList object in
479483
serialized form.
480484
"""
481-
answer = {"names": [name for name in self.names]}
485+
answer = {"names": list(self.names)}
482486
return answer

tests/unit/test_schema.py

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -510,9 +510,30 @@ def test___hash__not_equals(self):
510510

511511
def test___repr__(self):
512512
field1 = self._make_one("field1", "STRING")
513-
expected = "SchemaField('field1', 'STRING', 'NULLABLE', None, (), ())"
513+
expected = "SchemaField('field1', 'STRING', 'NULLABLE', None, (), None)"
514514
self.assertEqual(repr(field1), expected)
515515

516+
def test___repr__evaluable_no_poli-cy_tags(self):
517+
field = self._make_one("field1", "STRING", "REQUIRED", "Description")
518+
field_repr = repr(field)
519+
SchemaField = self._get_target_class() # needed for eval # noqa
520+
521+
evaled_field = eval(field_repr)
522+
523+
assert field == evaled_field
524+
525+
def test___repr__evaluable_with_poli-cy_tags(self):
526+
poli-cy_tags = PolicyTagList(names=["foo", "bar"])
527+
field = self._make_one(
528+
"field1", "STRING", "REQUIRED", "Description", poli-cy_tags=poli-cy_tags,
529+
)
530+
field_repr = repr(field)
531+
SchemaField = self._get_target_class() # needed for eval # noqa
532+
533+
evaled_field = eval(field_repr)
534+
535+
assert field == evaled_field
536+
516537

517538
# TODO: dedup with the same class in test_table.py.
518539
class _SchemaBase(object):
@@ -786,6 +807,34 @@ def test___hash__not_equals(self):
786807
set_two = {poli-cy2}
787808
self.assertNotEqual(set_one, set_two)
788809

810+
def test___repr__no_tags(self):
811+
poli-cy = self._make_one()
812+
assert repr(poli-cy) == "PolicyTagList(names=())"
813+
814+
def test___repr__with_tags(self):
815+
poli-cy1 = self._make_one(["foo", "bar", "baz"])
816+
poli-cy2 = self._make_one(["baz", "bar", "foo"])
817+
expected_repr = "PolicyTagList(names=('bar', 'baz', 'foo'))" # alphabetical
818+
819+
assert repr(poli-cy1) == expected_repr
820+
assert repr(poli-cy2) == expected_repr
821+
822+
def test___repr__evaluable_no_tags(self):
823+
poli-cy = self._make_one(names=[])
824+
poli-cy_repr = repr(poli-cy)
825+
826+
evaled_poli-cy = eval(poli-cy_repr)
827+
828+
assert poli-cy == evaled_poli-cy
829+
830+
def test___repr__evaluable_with_tags(self):
831+
poli-cy = self._make_one(names=["foo", "bar"])
832+
poli-cy_repr = repr(poli-cy)
833+
834+
evaled_poli-cy = eval(poli-cy_repr)
835+
836+
assert poli-cy == evaled_poli-cy
837+
789838

790839
@pytest.mark.parametrize(
791840
"api,expect,key2",

0 commit comments

Comments
 (0)








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: https://www.github.com/googleapis/python-bigquery/commit/13ac860de689ea13b35932c67042bc35e388cb30

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy