Skip to content

Commit

Permalink
BigQuery: Add StandardSqlDataTypes enum to BigQuery (#8782)
Browse files Browse the repository at this point in the history
* Add StandardSqlDataTypes enum to BigQuery

This is a convenience enum that contains scalar SQL data types
constants (a subsset of types defined in the gapic enum generated
from the .proto definitions).

* Move StandardSqlDataTypes tests under enums/ dir

* Treat GEOGRAPHY as scalar SQL type in enum

* Use more descriptive name in generator expression

* Replace enum out of sync warning with a loud test

* Add Enums section to BigQuery API reference docs
  • Loading branch information
plamut committed Jul 30, 2019
1 parent fc03d4d commit 7e6f83d
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 0 deletions.
10 changes: 10 additions & 0 deletions bigquery/docs/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,16 @@ Magics

magics


Enums
=====

.. autosummary::
:toctree: generated

enums.StandardSqlDataTypes


Additional Types
================

Expand Down
2 changes: 2 additions & 0 deletions bigquery/google/cloud/bigquery/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
from google.cloud.bigquery.dataset import AccessEntry
from google.cloud.bigquery.dataset import Dataset
from google.cloud.bigquery.dataset import DatasetReference
from google.cloud.bigquery.enums import StandardSqlDataTypes
from google.cloud.bigquery.external_config import ExternalConfig
from google.cloud.bigquery.external_config import BigtableOptions
from google.cloud.bigquery.external_config import BigtableColumnFamily
Expand Down Expand Up @@ -130,6 +131,7 @@
"Encoding",
"QueryPriority",
"SchemaUpdateOption",
"StandardSqlDataTypes",
"SourceFormat",
"WriteDisposition",
]
Expand Down
69 changes: 69 additions & 0 deletions bigquery/google/cloud/bigquery/enums.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import re

import enum
import six

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


_SQL_SCALAR_TYPES = frozenset(
(
"INT64",
"BOOL",
"FLOAT64",
"STRING",
"BYTES",
"TIMESTAMP",
"DATE",
"TIME",
"DATETIME",
"GEOGRAPHY",
"NUMERIC",
)
)

_SQL_NONSCALAR_TYPES = frozenset(("TYPE_KIND_UNSPECIFIED", "ARRAY", "STRUCT"))


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
),
)

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

new_doc = "\n".join(
six.moves.filterfalse(skip_pattern.search, orig_doc.splitlines())
)
new_enum.__doc__ = "An Enum of scalar SQL types.\n" + new_doc

return new_enum


StandardSqlDataTypes = _make_sql_scalars_enum()
13 changes: 13 additions & 0 deletions bigquery/tests/unit/enums/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright 2019, Google LLC All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
73 changes: 73 additions & 0 deletions bigquery/tests/unit/enums/test_standard_sql_data_types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import pytest


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

return enums


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

return StandardSqlDataTypes


@pytest.fixture
def gapic_enum():
"""The referential autogenerated enum the enum under test is based on."""
from google.cloud.bigquery_v2.gapic.enums import StandardSqlDataType

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"):
assert name in enum_under_test.__members__

# the enum members must match those in the original gapic enum
for member in enum_under_test:
assert member.name in gapic_enum.__members__
assert member.value == gapic_enum[member.name].value

# check a few members that should *not* be copied over from the gapic enum
for name in ("STRUCT", "ARRAY"):
assert name in gapic_enum.__members__
assert name not in enum_under_test.__members__


def test_standard_sql_types_enum_docstring(enum_under_test, gapic_enum):
assert "STRUCT (int):" not in enum_under_test.__doc__
assert "BOOL (int):" in enum_under_test.__doc__
assert "TIME (int):" in enum_under_test.__doc__

# All lines in the docstring should actually come from the original docstring,
# except for the header.
assert "An Enum of scalar SQL types." in enum_under_test.__doc__
doc_lines = enum_under_test.__doc__.splitlines()
assert set(doc_lines[1:]) <= set(gapic_enum.__doc__.splitlines())

0 comments on commit 7e6f83d

Please sign in to comment.