diff --git a/.repo-metadata.json b/.repo-metadata.json index e551b994..741b6322 100644 --- a/.repo-metadata.json +++ b/.repo-metadata.json @@ -2,7 +2,7 @@ "name": "sqlalchemy-bigquery", "name_pretty": "SQLAlchemy dialect for BigQuery", "client_documentation": "https://googleapis.dev/python/sqlalchemy-bigquery/latest/index.html", - "release_level": "beta", + "release_level": "preview", "language": "python", "library_type": "INTEGRATION", "repo": "googleapis/python-bigquery-sqlalchemy", diff --git a/CHANGELOG.md b/CHANGELOG.md index 43637720..08bb2534 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,13 @@ Older versions of this project were distributed as [pybigquery][0]. [2]: https://pypi.org/project/pybigquery/#history +## [1.3.0](https://www.github.com/googleapis/python-bigquery-sqlalchemy/compare/v1.2.2...v1.3.0) (2021-12-31) + + +### Features + +* Enable support for 3.10 ([#381](https://www.github.com/googleapis/python-bigquery-sqlalchemy/issues/381)) ([4b3505b](https://www.github.com/googleapis/python-bigquery-sqlalchemy/commit/4b3505b3d3a4293ea127fc3c483e3e7de04fbd04)) + ### [1.2.2](https://www.github.com/googleapis/python-bigquery-sqlalchemy/compare/v1.2.1...v1.2.2) (2021-10-29) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 779aa5a1..3a6be172 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -22,7 +22,7 @@ In order to add a feature: documentation. - The feature must work fully on the following CPython versions: - 3.6, 3.7, 3.8 and 3.9 on both UNIX and Windows. + 3.6, 3.7, 3.8, 3.9 and 3.10 on both UNIX and Windows. - The feature must not add unnecessary dependencies (where "unnecessary" is of course subjective, but new dependencies should @@ -72,7 +72,7 @@ We use `nox `__ to instrument our tests. - To run a single unit test:: - $ nox -s unit-3.9 -- -k + $ nox -s unit-3.10 -- -k .. note:: @@ -143,12 +143,12 @@ Running System Tests $ nox -s system # Run a single system test - $ nox -s system-3.9 -- -k + $ nox -s system-3.10 -- -k .. note:: - System tests are only configured to run under Python 3.8 and 3.9. + System tests are only configured to run under Python 3.8 and 3.10. For expediency, we do not run them in older versions of Python 3. This alone will not run the tests. You'll need to change some local @@ -225,11 +225,13 @@ We support: - `Python 3.7`_ - `Python 3.8`_ - `Python 3.9`_ +- `Python 3.10`_ .. _Python 3.6: https://docs.python.org/3.6/ .. _Python 3.7: https://docs.python.org/3.7/ .. _Python 3.8: https://docs.python.org/3.8/ .. _Python 3.9: https://docs.python.org/3.9/ +.. _Python 3.10: https://docs.python.org/3.10/ Supported versions can be found in our ``noxfile.py`` `config`_. diff --git a/noxfile.py b/noxfile.py index 823c72c2..ce847c57 100644 --- a/noxfile.py +++ b/noxfile.py @@ -30,8 +30,8 @@ DEFAULT_PYTHON_VERSION = "3.8" # We're using two Python versions to test with sqlalchemy 1.3 and 1.4. -SYSTEM_TEST_PYTHON_VERSIONS = ["3.8", "3.9"] -UNIT_TEST_PYTHON_VERSIONS = ["3.6", "3.7", "3.8", "3.9"] +SYSTEM_TEST_PYTHON_VERSIONS = ["3.8", "3.10"] +UNIT_TEST_PYTHON_VERSIONS = ["3.6", "3.7", "3.8", "3.9", "3.10"] CURRENT_DIRECTORY = pathlib.Path(__file__).parent.absolute() @@ -100,7 +100,7 @@ def default(session): if session.python == "3.8": extras = "[tests,alembic]" - elif session.python == "3.9": + elif session.python == "3.10": extras = "[tests,geography]" else: extras = "[tests]" @@ -158,7 +158,7 @@ def system(session): session.install("mock", "pytest", "google-cloud-testutils", "-c", constraints_path) if session.python == "3.8": extras = "[tests,alembic]" - elif session.python == "3.9": + elif session.python == "3.10": extras = "[tests,geography]" else: extras = "[tests]" @@ -212,7 +212,7 @@ def compliance(session): ) if session.python == "3.8": extras = "[tests,alembic]" - elif session.python == "3.9": + elif session.python == "3.10": extras = "[tests,geography]" else: extras = "[tests]" diff --git a/owlbot.py b/owlbot.py index c3735f3e..c007d936 100644 --- a/owlbot.py +++ b/owlbot.py @@ -30,11 +30,11 @@ extras = ["tests"] extras_by_python = { "3.8": ["tests", "alembic"], - "3.9": ["tests", "geography"], + "3.10": ["tests", "geography"], } templated_files = common.py_library( - unit_test_python_versions=["3.6", "3.7", "3.8", "3.9"], - system_test_python_versions=["3.8", "3.9"], + unit_test_python_versions=["3.6", "3.7", "3.8", "3.9", "3.10"], + system_test_python_versions=["3.8", "3.10"], cov_level=100, unit_test_extras=extras, unit_test_extras_by_python=extras_by_python, @@ -136,7 +136,7 @@ def compliance(session): ) if session.python == "3.8": extras = "[tests,alembic]" - elif session.python == "3.9": + elif session.python == "3.10": extras = "[tests,geography]" else: extras = "[tests]" diff --git a/samples/snippets/requirements-test.txt b/samples/snippets/requirements-test.txt index ade1580c..e865c0b5 100644 --- a/samples/snippets/requirements-test.txt +++ b/samples/snippets/requirements-test.txt @@ -1,12 +1,19 @@ attrs==21.2.0 -google-cloud-testutils==1.2.0 -importlib-metadata==4.8.1 +cachetools==4.2.4 +click==8.0.3 +google-auth==2.3.3 +google-cloud-testutils==1.3.1 +importlib-metadata==4.8.3 iniconfig==1.1.1 packaging==21.0 pluggy==1.0.0 py==1.10.0 +pyasn1==0.4.8 +pyasn1-modules==0.2.8 pyparsing==3.0.2 pytest==6.2.5 +rsa==4.8 +six==1.16.0 toml==0.10.2 -typing-extensions==3.10.0.2 +typing-extensions==4.0.1 zipp==3.6.0 diff --git a/samples/snippets/requirements.txt b/samples/snippets/requirements.txt index 69731ae7..17296ff0 100644 --- a/samples/snippets/requirements.txt +++ b/samples/snippets/requirements.txt @@ -1,66 +1,37 @@ -aiocontextvars==0.2.2 -attrs==21.2.0 +alembic==1.7.5 cachetools==4.2.4 certifi==2021.10.8 -cffi==1.15.0 charset-normalizer==2.0.7 -click==8.0.3 -click-plugins==1.1.1 -cligj==0.7.2 -contextvars==2.4 -dataclasses==0.6; python_version < '3.7' -Deprecated==1.2.13 -Fiona==1.8.20 future==0.18.2 -GeoAlchemy2==0.9.4 -geopandas==0.9.0; python_version < '3.7' -geopandas==0.10.0; python_version >= '3.7' -google-api-core==2.2.0 +geoalchemy2==0.9.4 +google-api-core[grpc]==2.2.0 google-auth==2.3.2 -google-cloud-bigquery==2.28.1 -google-cloud-bigquery-storage==2.9.1 +google-cloud-bigquery==2.31.0 google-cloud-core==2.1.0 google-crc32c==1.3.0 google-resumable-media==2.1.0 googleapis-common-protos==1.53.0 greenlet==1.1.2 -grpcio==1.41.1 +grpcio==1.43.0 +grpcio-status==1.43.0 idna==3.3 -immutables==0.16 -importlib-metadata==4.8.1 -libcst==0.3.21 -munch==2.5.0 -mypy-extensions==0.4.3 -numpy==1.19.5; python_version < '3.7' -numpy==1.21.2; python_version >= '3.7' -opentelemetry-api==1.6.2 -opentelemetry-instrumentation==0.25b2 -opentelemetry-sdk==1.6.2 -opentelemetry-semantic-conventions==0.25b2 +importlib-metadata==4.8.3 +importlib-resources==5.4.0 +mako==1.1.6 +markupsafe==2.0.1 packaging==21.0 -pandas==1.1.5; python_version < '3.7' -pandas==1.3.2; python_version >= '3.7' proto-plus==1.19.7 protobuf==3.19.0 -pyarrow==6.0.0 pyasn1==0.4.8 pyasn1-modules==0.2.8 -pycparser==2.20 pyparsing==3.0.2 -pyproj==3.0.1; python_version < '3.7' -pyproj==3.1.0; python_version >= '3.7' python-dateutil==2.8.2 pytz==2021.3 -PyYAML==6.0 requests==2.26.0 rsa==4.7.2 -Shapely==1.8.0 +shapely==1.8.0 six==1.16.0 -SQLAlchemy==1.4.26 -sqlalchemy-bigquery==1.2.1 -tqdm==4.62.3 -typing-extensions==3.10.0.2 -typing-inspect==0.7.1 +sqlalchemy==1.4.26 +typing-extensions==4.0.1 urllib3==1.26.7 -wrapt==1.13.2 zipp==3.6.0 diff --git a/setup.py b/setup.py index 7efe0f9b..eef5b754 100644 --- a/setup.py +++ b/setup.py @@ -73,6 +73,7 @@ def readme(): "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", "Operating System :: OS Independent", "Topic :: Database :: Front-Ends", ], @@ -84,11 +85,16 @@ def readme(): # https://github.com/googleapis/google-cloud-python/issues/10566 "google-auth>=1.25.0,<3.0.0dev", # Work around pip wack. "google-cloud-bigquery>=2.25.2,<3.0.0dev", - "sqlalchemy>=1.2.0,<1.5.0dev", + # Temporarily set maximimum sqlalchemy to a known-working version while + # we debug failing compliance tests. See: + # https://github.com/googleapis/python-bigquery-sqlalchemy/issues/386 + # and + # https://github.com/googleapis/python-bigquery-sqlalchemy/issues/385 + "sqlalchemy>=1.2.0,<=1.4.25", "future", ], extras_require=extras, - python_requires=">=3.6, <3.10", + python_requires=">=3.6, <3.11", tests_require=["packaging", "pytz"], entry_points={ "sqlalchemy.dialects": ["bigquery = sqlalchemy_bigquery:BigQueryDialect"] diff --git a/sqlalchemy_bigquery/version.py b/sqlalchemy_bigquery/version.py index 24e37be5..8af70f2e 100644 --- a/sqlalchemy_bigquery/version.py +++ b/sqlalchemy_bigquery/version.py @@ -17,4 +17,4 @@ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__version__ = "1.2.2" +__version__ = "1.3.0" diff --git a/tests/system/test_alembic.py b/tests/system/test_alembic.py index 81c686d1..6c4736c8 100644 --- a/tests/system/test_alembic.py +++ b/tests/system/test_alembic.py @@ -23,6 +23,7 @@ from sqlalchemy import Column, DateTime, Integer, String import google.api_core.exceptions +from google.cloud.bigquery import SchemaField alembic = pytest.importorskip("alembic") @@ -43,10 +44,7 @@ def get_table(table_name, data="table"): if data == "table": return table elif data == "schema": - return [ - repr(s).replace(", (), None)", ")").replace(", None)", ")") - for s in table.schema - ] + return table.schema else: raise ValueError(data) except google.api_core.exceptions.NotFound: @@ -78,9 +76,9 @@ def test_alembic_scenario(alembic_table): Column("description", String(200)), ) assert alembic_table("account", "schema") == [ - "SchemaField('id', 'INTEGER', 'REQUIRED', None, (), ())", - "SchemaField('name', 'STRING(50)', 'REQUIRED', 'The name', (), ())", - "SchemaField('description', 'STRING(200)', 'NULLABLE', None, (), ())", + SchemaField("id", "INTEGER", "REQUIRED"), + SchemaField("name", "STRING(50)", "REQUIRED", description="The name"), + SchemaField("description", "STRING(200)"), ] op.bulk_insert( @@ -103,11 +101,10 @@ def test_alembic_scenario(alembic_table): ) assert alembic_table("account", "schema") == [ - "SchemaField('id', 'INTEGER', 'REQUIRED', None, (), ())", - "SchemaField('name', 'STRING(50)', 'REQUIRED', 'The name', (), ())", - "SchemaField('description', 'STRING(200)', 'NULLABLE', None, (), ())", - "SchemaField('last_transaction_date', 'DATETIME', 'NULLABLE', 'when updated'" - ", (), ())", + SchemaField("id", "INTEGER", "REQUIRED"), + SchemaField("name", "STRING(50)", "REQUIRED", description="The name"), + SchemaField("description", "STRING(200)"), + SchemaField("last_transaction_date", "DATETIME", description="when updated"), ] op.create_table( @@ -123,8 +120,8 @@ def test_alembic_scenario(alembic_table): op.drop_column("account_w_comment", "description") assert alembic_table("account_w_comment", "schema") == [ - "SchemaField('id', 'INTEGER', 'REQUIRED', None, (), ())", - "SchemaField('name', 'STRING(50)', 'REQUIRED', 'The name', (), ())", + SchemaField("id", "INTEGER", "REQUIRED"), + SchemaField("name", "STRING(50)", "REQUIRED", description="The name"), ] op.drop_table("account_w_comment") @@ -133,11 +130,10 @@ def test_alembic_scenario(alembic_table): op.rename_table("account", "accounts") assert alembic_table("account") is None assert alembic_table("accounts", "schema") == [ - "SchemaField('id', 'INTEGER', 'REQUIRED', None, (), ())", - "SchemaField('name', 'STRING(50)', 'REQUIRED', 'The name', (), ())", - "SchemaField('description', 'STRING(200)', 'NULLABLE', None, (), ())", - "SchemaField('last_transaction_date', 'DATETIME', 'NULLABLE', 'when updated'" - ", (), ())", + SchemaField("id", "INTEGER", "REQUIRED"), + SchemaField("name", "STRING(50)", "REQUIRED", description="The name"), + SchemaField("description", "STRING(200)"), + SchemaField("last_transaction_date", "DATETIME", description="when updated"), ] op.drop_table("accounts") assert alembic_table("accounts") is None @@ -157,9 +153,9 @@ def test_alembic_scenario(alembic_table): # nullable: op.alter_column("transactions", "amount", True) assert alembic_table("transactions", "schema") == [ - "SchemaField('account', 'INTEGER', 'REQUIRED', None, (), ())", - "SchemaField('transaction_time', 'DATETIME', 'REQUIRED', None, (), ())", - "SchemaField('amount', 'NUMERIC(11, 2)', 'NULLABLE', None, (), ())", + SchemaField("account", "INTEGER", "REQUIRED"), + SchemaField("transaction_time", "DATETIME", "REQUIRED"), + SchemaField("amount", "NUMERIC(11, 2)"), ] op.create_table_comment("transactions", "Transaction log")