Skip to content

Commit

Permalink
Replace enum out of sync warning with a loud test
Browse files Browse the repository at this point in the history
  • Loading branch information
plamut committed Jul 26, 2019
1 parent ec6ccd8 commit 07b9029
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 63 deletions.
54 changes: 20 additions & 34 deletions bigquery/google/cloud/bigquery/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,62 +13,48 @@
# limitations under the License.

import re
import warnings

import enum
import six

from google.cloud.bigquery_v2.gapic import enums as gapic_enums


def _make_sql_scalars_enum():
"""Create an enum based on a gapic enum containing only SQL scalar types."""
sql_scalar_types = frozenset(
(
"INT64",
"BOOL",
"FLOAT64",
"STRING",
"BYTES",
"TIMESTAMP",
"DATE",
"TIME",
"DATETIME",
"GEOGRAPHY",
"NUMERIC",
)
_SQL_SCALAR_TYPES = frozenset(
(
"INT64",
"BOOL",
"FLOAT64",
"STRING",
"BYTES",
"TIMESTAMP",
"DATE",
"TIME",
"DATETIME",
"GEOGRAPHY",
"NUMERIC",
)
excluded_members = frozenset(("TYPE_KIND_UNSPECIFIED", "ARRAY", "STRUCT"))
)

# Sanity check - we do not want the new enum to go out of sync with the original
# enum from gapic.
# ASSUMPTION: No existing types are ever renamed or deleted, we only try to
# detect cases when new types are introduced.
gapic_names = set(type_.name for type_ in gapic_enums.StandardSqlDataType.TypeKind)
anticipated_names = sql_scalar_types | excluded_members
unhandled_names = gapic_names - anticipated_names
_SQL_NONSCALAR_TYPES = frozenset(("TYPE_KIND_UNSPECIFIED", "ARRAY", "STRUCT"))

if unhandled_names:
msg = (
"The StandardSqlDataTypes enum migh be out of sync with the "
"original StandardSqlDataType.TypeKind enum from gapic. Check "
"enum members: {}".format(", ".join(unhandled_names))
)
warnings.warn(msg, UserWarning)

def _make_sql_scalars_enum():
"""Create an enum based on a gapic enum containing only SQL scalar types."""

new_enum = enum.Enum(
"StandardSqlDataTypes",
(
(member.name, member.value)
for member in gapic_enums.StandardSqlDataType.TypeKind
if member.name in sql_scalar_types
if member.name in _SQL_SCALAR_TYPES
),
)

# make sure the docstring for the new enum is also correct
orig_doc = gapic_enums.StandardSqlDataType.TypeKind.__doc__
skip_pattern = re.compile(
"|".join(excluded_members)
"|".join(_SQL_NONSCALAR_TYPES)
+ "|because a JSON object" # the second description line of STRUCT member
)

Expand Down
44 changes: 15 additions & 29 deletions bigquery/tests/unit/enums/test_standard_sql_data_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import enum
import mock
import pytest
import six


@pytest.fixture
def module_under_test():
from google.cloud.bigquery import enums

return enums


@pytest.fixture
Expand All @@ -33,6 +37,14 @@ def gapic_enum():
return StandardSqlDataType.TypeKind


def test_all_gapic_enum_members_are_known(module_under_test, gapic_enum):
gapic_names = set(type_.name for type_ in gapic_enum)
anticipated_names = (
module_under_test._SQL_SCALAR_TYPES | module_under_test._SQL_NONSCALAR_TYPES
)
assert not (gapic_names - anticipated_names) # no unhandled names


def test_standard_sql_types_enum_members(enum_under_test, gapic_enum):
# check the presence of a few typical SQL types
for name in ("INT64", "FLOAT64", "DATE", "BOOL", "GEOGRAPHY"):
Expand All @@ -57,29 +69,3 @@ def test_standard_sql_types_enum_docstring(enum_under_test, gapic_enum):
# all lines in the docstring should actually come from the original docstring
doc_lines = enum_under_test.__doc__.splitlines()
assert set(doc_lines) <= set(gapic_enum.__doc__.splitlines())


def test_standard_sql_types_enum_warning_on_new_added_types(gapic_enum):
class ReplacementEnum(enum.IntEnum):
"""Fake enum with some new database types."""

INT64 = 2
TIMESTAMP = 19
TROOLEAN = 911 # One of {True, False, FileNotFound}. (OMG, help!)

gapic_enum_patch = mock.patch(
"google.cloud.bigquery_v2.gapic.enums.StandardSqlDataType.TypeKind",
new=ReplacementEnum,
)

from google.cloud.bigquery import enums

with pytest.warns(UserWarning) as warn_record, gapic_enum_patch:
enums = six.moves.reload_module(enums)

try:
warning_msg = str(warn_record[0].message)
assert "StandardSqlDataTypes" in warning_msg
assert "out of sync" in warning_msg
finally:
six.moves.reload_module(enums) # regenerate enum with original gapic enum

0 comments on commit 07b9029

Please sign in to comment.