Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support SQLAlchemy 2.0, raise minimum required version to 1.4.x #1053

Merged
merged 74 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from 71 commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
ffc491f
feat!: Support SQLAlchemy 2.0, drop support for 1.x
sharoonthomas Oct 26, 2023
c7f2751
Merge branch 'main' into sqla2
nayaknishant Nov 9, 2023
c74a0b9
constraints updated
nayaknishant Nov 2, 2023
001759e
🦉 Updates from OwlBot post-processor
gcf-owl-bot[bot] Nov 2, 2023
bc5725f
fixing README.rst
nayaknishant Nov 7, 2023
8d5c2cc
fixing README.rst
nayaknishant Nov 7, 2023
4a355c4
upping sqlalchemy version in constraints-3.8.txt
nayaknishant Nov 9, 2023
0079d11
adding 2.0 version restrictions to owlbot.py
nayaknishant Nov 9, 2023
89ea48e
🦉 Updates from OwlBot post-processor
gcf-owl-bot[bot] Nov 9, 2023
39b0d66
fix for
nayaknishant Nov 15, 2023
1e81318
Updated some compliance tests for sqla2 and bq
kiraksi Dec 1, 2023
eeffbe6
Addressed snippet errors
kiraksi Dec 2, 2023
02921c2
revert bad commit
kiraksi Dec 2, 2023
1e9a72e
More compliance tests checking
kiraksi Dec 5, 2023
a84af4b
reformatted with black
kiraksi Dec 5, 2023
c09a676
Changed more compliance tests, updated requirements for testing
kiraksi Dec 8, 2023
6999f62
Merge remote-tracking branch 'origin' into sqla2
chalmerlowe Dec 8, 2023
00274e0
Fixed attributeerror in failing sample test
kiraksi Dec 8, 2023
cb34e6b
Fixed geolography test failing issue
kiraksi Dec 11, 2023
08d93b0
Minor tweaks to tests and code
chalmerlowe Dec 11, 2023
a377a31
Merge branch 'main' of github.com:googleapis/python-bigquery-sqlalche…
chalmerlowe Dec 11, 2023
2492a0c
Merge branch 'sqla2' into sqla2
chalmerlowe Dec 11, 2023
4a5c291
🦉 Updates from OwlBot post-processor
gcf-owl-bot[bot] Dec 11, 2023
c4c9976
Fixed small error in compliance tests, added pip freeze for owl bot t…
kiraksi Dec 11, 2023
60735ff
merged from branch
kiraksi Dec 11, 2023
2612a70
Fixed some failing compliance tests by reformatting
kiraksi Dec 12, 2023
5d3d850
Added UuidTest to compliance tests
kiraksi Dec 13, 2023
a708987
merged main branch
kiraksi Dec 14, 2023
a3a4ee6
Moved back sqlalchemy constraints to 1.4
kiraksi Dec 15, 2023
a71e1ee
Update testing/constraints-3.8.txt
tswast Dec 15, 2023
708ec59
Fixed minimum version of sqlalchemy for 1.4 backwards compatibility
kiraksi Dec 18, 2023
9a9bc6b
Bumping support for sqlalchemy 1.4.16 for sample tests
kiraksi Dec 18, 2023
740bfcd
Bump setup.py sqlalchemy to 1.4.16
kiraksi Dec 18, 2023
75038b0
Updated compliance sqlalchemy to 1.4.16
kiraksi Dec 18, 2023
3c50f7d
Merge branch 'main' into sqla2
chalmerlowe Dec 19, 2023
455dbeb
Fixed broken code in last merged main, as we need to avoid duplicate …
kiraksi Dec 19, 2023
da9f228
modified tests for join order variation in 1.4 vs 2.0
kiraksi Dec 20, 2023
59f0a4e
typo
kiraksi Dec 20, 2023
9e8d4e7
Modified one compliance StringTest thats been flaky
kiraksi Dec 20, 2023
c0016ee
Merge branch 'main' into sqla2
kiraksi Jan 10, 2024
5503877
Updated docs
kiraksi Jan 10, 2024
b4010e1
minor fixes to noxfile and README
kiraksi Jan 12, 2024
07a1e65
Merge branch 'main' into sqla2
chalmerlowe Jan 12, 2024
1e54e77
🦉 Updates from OwlBot post-processor
gcf-owl-bot[bot] Jan 16, 2024
e95aee1
cleaned up code from review, removed unnecessary code and files
kiraksi Jan 17, 2024
b8f8f21
Update tests/sqlalchemy_dialect_compliance/test_dialect_compliance.py
chalmerlowe Jan 17, 2024
03fb7f7
Merge branch 'main' into sqla2
kiraksi Jan 17, 2024
dcc89f7
create development release 1.11.0.dev0 branch
kiraksi Jan 25, 2024
67cb7bd
chore: cleanup compliance tests for sqlalchemy migration (#1013)
kiraksi Jan 29, 2024
f3cb2d1
Revert "chore: cleanup compliance tests for sqlalchemy migration" (#1…
kiraksi Jan 29, 2024
19d9ce2
chore: fix coverage tests sqlalchemy 2.0 migration (#987)
kiraksi Jan 29, 2024
59408a5
chore: sqlalchemy test compliance suite cleanup (#1018)
kiraksi Jan 30, 2024
1bbf9eb
create development release 1.11.0.dev1 branch
kiraksi Jan 30, 2024
5cfc280
feat: grouping sets, rollup and cube compatibility
kiraksi Jan 31, 2024
0c4cf07
create development release 1.11.0.dev2
kiraksi Feb 1, 2024
310cfa7
Merge branch 'development-build-v1.11.0.dev2' into grouping-rollup-cube
kiraksi Feb 1, 2024
e82f5dd
test commit to run kokooro tests
kiraksi Feb 1, 2024
ece7f1f
removed unnecessary clause function changes, edited tests
kiraksi Feb 1, 2024
68afc39
test basic implementation of group_by_clause and visit_label
kiraksi Feb 1, 2024
bd38a5e
fixed render label as label assignment
kiraksi Feb 6, 2024
5154814
added test case
kiraksi Feb 6, 2024
033d329
reformat logic
kiraksi Feb 8, 2024
0c882b9
test commit
kiraksi Feb 8, 2024
87a75dc
create development build 1.11.0.dev3
kiraksi Feb 12, 2024
a3cacd3
chore: add more grouping sets/rollup/cube tests (#1029)
kiraksi Feb 20, 2024
34edb6d
update changelog
kiraksi Feb 20, 2024
35763e6
Merge branch 'main' into development-build-v1.11.0.dev3
tswast Apr 2, 2024
bcedd9c
revert changelog
tswast Apr 2, 2024
924003e
remove note
tswast Apr 2, 2024
dfbfcc3
don't install prerelease in compliance session
tswast Apr 2, 2024
853e5fd
sync owlbot
tswast Apr 2, 2024
b8fd194
Update tests/sqlalchemy_dialect_compliance/test_dialect_compliance.py
chalmerlowe Apr 3, 2024
eda4813
make results order not matter
tswast Apr 3, 2024
82c372a
🦉 Updates from OwlBot post-processor
gcf-owl-bot[bot] Apr 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Maksym Voitko
Maxim Zudilov (mxmzdlv)
Maxime Beauchemin (mistercrunch)
Romain Rigaux
Sharoon Thomas (sharoonthomas)
Sumedh Sakdeo
Tim Swast (tswast)
Vince Broz
Expand Down
7 changes: 3 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ In order to use this library, you first need to go through the following steps:
.. _Enable the BigQuery Storage API.: https://console.cloud.google.com/apis/library/bigquery.googleapis.com
.. _Setup Authentication.: https://googleapis.dev/python/google-api-core/latest/auth.html

.. note::
This library is only compatible with SQLAlchemy versions < 2.0.0

Installation
------------
Expand Down Expand Up @@ -108,7 +106,8 @@ SQLAlchemy
from sqlalchemy.schema import *
engine = create_engine('bigquery://project')
table = Table('dataset.table', MetaData(bind=engine), autoload=True)
print(select([func.count('*')], from_obj=table).scalar())
print(select([func.count('*')], from_obj=table().scalar())


Project
^^^^^^^
Expand Down Expand Up @@ -281,7 +280,7 @@ If you need additional control, you can supply a BigQuery client of your own:

engine = create_engine(
'bigquery://some-project/some-dataset?user_supplied_client=True',
connect_args={'client': custom_bq_client},
connect_args={'client': custom_bq_client},
)


Expand Down
4 changes: 1 addition & 3 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -368,8 +368,6 @@ def compliance(session):
if not os.path.exists(system_test_folder_path):
session.skip("Compliance tests were not found")

session.install("--pre", "grpcio")
session.install("--pre", "--no-deps", "--upgrade", "sqlalchemy<2.0.0")
session.install(
"mock",
"pytest",
Expand Down Expand Up @@ -543,7 +541,7 @@ def prerelease_deps(session):

prerel_deps = [
"protobuf",
"sqlalchemy<2.0.0",
"sqlalchemy",
# dependency of grpc
"six",
"googleapis-common-protos",
Expand Down
75 changes: 34 additions & 41 deletions owlbot.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,17 @@
system_test_extras=extras,
system_test_extras_by_python=extras_by_python,
)
s.move(templated_files, excludes=[
# sqlalchemy-bigquery was originally licensed MIT
"LICENSE",
"docs/multiprocessing.rst",
# exclude gh actions as credentials are needed for tests
".github/workflows",
"README.rst",
])
s.move(
templated_files,
excludes=[
# sqlalchemy-bigquery was originally licensed MIT
"LICENSE",
"docs/multiprocessing.rst",
# exclude gh actions as credentials are needed for tests
".github/workflows",
"README.rst",
],
)

# ----------------------------------------------------------------------------
# Fixup files
Expand All @@ -59,7 +62,7 @@
[".coveragerc"],
"google/cloud/__init__.py",
"sqlalchemy_bigquery/requirements.py",
)
)

s.replace(
["noxfile.py"],
Expand All @@ -75,49 +78,43 @@


s.replace(
["noxfile.py"], "--cov=google", "--cov=sqlalchemy_bigquery",
["noxfile.py"],
"--cov=google",
"--cov=sqlalchemy_bigquery",
)


s.replace(
["noxfile.py"],
["noxfile.py"],
"\+ SYSTEM_TEST_EXTRAS",
"",
)


s.replace(
["noxfile.py"],
'''"protobuf",
# dependency of grpc''',
'''"protobuf",
"sqlalchemy<2.0.0",
# dependency of grpc''',
""""protobuf",
# dependency of grpc""",
""""protobuf",
"sqlalchemy",
# dependency of grpc""",
)


s.replace(
["noxfile.py"],
r"def default\(session\)",
"def default(session, install_extras=True)",
"def default(session, install_extras=True)",
)




def place_before(path, text, *before_text, escape=None):
replacement = "\n".join(before_text) + "\n" + text
if escape:
for c in escape:
text = text.replace(c, '\\' + c)
text = text.replace(c, "\\" + c)
s.replace([path], text, replacement)

place_before(
"noxfile.py",
"SYSTEM_TEST_PYTHON_VERSIONS=",
"",
"# We're using two Python versions to test with sqlalchemy 1.3 and 1.4.",
)

place_before(
"noxfile.py",
Expand All @@ -126,15 +123,15 @@ def place_before(path, text, *before_text, escape=None):
)


install_logic = '''
install_logic = """
if install_extras and session.python in ["3.11", "3.12"]:
install_target = ".[geography,alembic,tests,bqstorage]"
elif install_extras:
install_target = ".[all]"
else:
install_target = "."
session.install("-e", install_target, "-c", constraints_path)
'''
"""

place_before(
"noxfile.py",
Expand Down Expand Up @@ -162,8 +159,6 @@ def compliance(session):
if not os.path.exists(system_test_folder_path):
session.skip("Compliance tests were not found")

session.install("--pre", "grpcio")
session.install("--pre", "--no-deps", "--upgrade", "sqlalchemy<2.0.0")
session.install(
"mock",
"pytest",
Expand Down Expand Up @@ -206,12 +201,11 @@ def compliance(session):
'''

place_before(
"noxfile.py",
"@nox.session(python=DEFAULT_PYTHON_VERSION)\n"
"def cover(session):",
compliance,
escape="()",
)
"noxfile.py",
"@nox.session(python=DEFAULT_PYTHON_VERSION)\n" "def cover(session):",
compliance,
escape="()",
)

s.replace(["noxfile.py"], '"alabaster"', '"alabaster", "geoalchemy2", "shapely"')

Expand Down Expand Up @@ -267,11 +261,10 @@ def system_noextras(session):

place_before(
"noxfile.py",
"@nox.session(python=SYSTEM_TEST_PYTHON_VERSIONS[-1])\n"
"def compliance(session):",
"@nox.session(python=SYSTEM_TEST_PYTHON_VERSIONS[-1])\n" "def compliance(session):",
system_noextras,
escape="()[]",
)
)


# Add DB config for SQLAlchemy dialect test suite.
Expand All @@ -288,7 +281,7 @@ def system_noextras(session):
[tool:pytest]
addopts= --tb native -v -r fxX -p no:warnings
python_files=tests/*test_*.py
"""
""",
)

# ----------------------------------------------------------------------------
Expand All @@ -299,7 +292,7 @@ def system_noextras(session):
python.py_samples(skip_readmes=True)

s.replace(
["./samples/snippets/noxfile.py"],
["./samples/snippets/noxfile.py"],
"""session.install\("-e", _get_repo_root\(\)\)""",
"""session.install("-e", _get_repo_root())
else:
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,9 @@ def readme():
# Until this issue is closed
# 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,<4.0.0dev",
"google-cloud-bigquery>=3.3.6,<4.0.0dev",
"packaging",
"sqlalchemy>=1.2.0,<2.0.0dev",
"sqlalchemy>=1.4.16,<3.0.0dev",
],
extras_require=extras,
python_requires=">=3.8, <3.13",
Expand Down
44 changes: 12 additions & 32 deletions sqlalchemy_bigquery/_struct.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,14 @@
# 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.

import packaging.version
import sqlalchemy.sql.default_comparator
import sqlalchemy.sql.sqltypes
import sqlalchemy.types

from . import base

sqlalchemy_1_4_or_more = packaging.version.parse(
sqlalchemy.__version__
) >= packaging.version.parse("1.4")

if sqlalchemy_1_4_or_more:
import sqlalchemy.sql.coercions
import sqlalchemy.sql.roles
import sqlalchemy.sql.coercions
import sqlalchemy.sql.roles


def _get_subtype_col_spec(type_):
Expand Down Expand Up @@ -103,34 +97,20 @@ def _setup_getitem(self, name):
def __getattr__(self, name):
if name.lower() in self.expr.type._STRUCT_byname:
return self[name]
else:
raise AttributeError(name)

comparator_factory = Comparator


# In the implementations of _field_index below, we're stealing from
# the JSON type implementation, but the code to steal changed in
# 1.4. :/

if sqlalchemy_1_4_or_more:

def _field_index(self, name, operator):
return sqlalchemy.sql.coercions.expect(
sqlalchemy.sql.roles.BinaryElementRole,
name,
expr=self.expr,
operator=operator,
bindparam_type=sqlalchemy.types.String(),
)

else:

def _field_index(self, name, operator):
return sqlalchemy.sql.default_comparator._check_literal(
self.expr,
operator,
name,
bindparam_type=sqlalchemy.types.String(),
)
def _field_index(self, name, operator):
return sqlalchemy.sql.coercions.expect(
sqlalchemy.sql.roles.BinaryElementRole,
name,
expr=self.expr,
operator=operator,
bindparam_type=sqlalchemy.types.String(),
)


def struct_getitem_op(a, b):
Expand Down
Loading