Skip to content

Commit 1490a8a

Browse files
committed
Revert "feat: support SQLAlchemy 2.0, raise minimum required version to 1.4.x (googleapis#1053)"
This reverts commit 7a4c3c2.
1 parent fd9e6f1 commit 1490a8a

22 files changed

+579
-1005
lines changed

AUTHORS

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ Maksym Voitko
1919
Maxim Zudilov (mxmzdlv)
2020
Maxime Beauchemin (mistercrunch)
2121
Romain Rigaux
22-
Sharoon Thomas (sharoonthomas)
2322
Sumedh Sakdeo
2423
Tim Swast (tswast)
2524
Vince Broz

README.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ In order to use this library, you first need to go through the following steps:
3434
.. _Enable the BigQuery Storage API.: https://console.cloud.google.com/apis/library/bigquery.googleapis.com
3535
.. _Setup Authentication.: https://googleapis.dev/python/google-api-core/latest/auth.html
3636

37+
.. note::
38+
This library is only compatible with SQLAlchemy versions < 2.0.0
3739

3840
Installation
3941
------------
@@ -106,8 +108,7 @@ SQLAlchemy
106108
from sqlalchemy.schema import *
107109
engine = create_engine('bigquery://project')
108110
table = Table('dataset.table', MetaData(bind=engine), autoload=True)
109-
print(select([func.count('*')], from_obj=table().scalar())
110-
111+
print(select([func.count('*')], from_obj=table).scalar())
111112
112113
Project
113114
^^^^^^^
@@ -280,7 +281,7 @@ If you need additional control, you can supply a BigQuery client of your own:
280281
281282
engine = create_engine(
282283
'bigquery://some-project/some-dataset?user_supplied_client=True',
283-
connect_args={'client': custom_bq_client},
284+
connect_args={'client': custom_bq_client},
284285
)
285286
286287

noxfile.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,8 @@ def compliance(session):
368368
if not os.path.exists(system_test_folder_path):
369369
session.skip("Compliance tests were not found")
370370

371+
session.install("--pre", "grpcio")
372+
session.install("--pre", "--no-deps", "--upgrade", "sqlalchemy<2.0.0")
371373
session.install(
372374
"mock",
373375
"pytest",
@@ -541,7 +543,7 @@ def prerelease_deps(session):
541543

542544
prerel_deps = [
543545
"protobuf",
544-
"sqlalchemy",
546+
"sqlalchemy<2.0.0",
545547
# dependency of grpc
546548
"six",
547549
"googleapis-common-protos",

owlbot.py

Lines changed: 41 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,14 @@
4242
system_test_extras=extras,
4343
system_test_extras_by_python=extras_by_python,
4444
)
45-
s.move(
46-
templated_files,
47-
excludes=[
48-
# sqlalchemy-bigquery was originally licensed MIT
49-
"LICENSE",
50-
"docs/multiprocessing.rst",
51-
# exclude gh actions as credentials are needed for tests
52-
".github/workflows",
53-
"README.rst",
54-
],
55-
)
45+
s.move(templated_files, excludes=[
46+
# sqlalchemy-bigquery was originally licensed MIT
47+
"LICENSE",
48+
"docs/multiprocessing.rst",
49+
# exclude gh actions as credentials are needed for tests
50+
".github/workflows",
51+
"README.rst",
52+
])
5653

5754
# ----------------------------------------------------------------------------
5855
# Fixup files
@@ -62,7 +59,7 @@
6259
[".coveragerc"],
6360
"google/cloud/__init__.py",
6461
"sqlalchemy_bigquery/requirements.py",
65-
)
62+
)
6663

6764
s.replace(
6865
["noxfile.py"],
@@ -78,43 +75,49 @@
7875

7976

8077
s.replace(
81-
["noxfile.py"],
82-
"--cov=google",
83-
"--cov=sqlalchemy_bigquery",
78+
["noxfile.py"], "--cov=google", "--cov=sqlalchemy_bigquery",
8479
)
8580

8681

8782
s.replace(
88-
["noxfile.py"],
83+
["noxfile.py"],
8984
"\+ SYSTEM_TEST_EXTRAS",
9085
"",
9186
)
9287

9388

9489
s.replace(
9590
["noxfile.py"],
96-
""""protobuf",
97-
# dependency of grpc""",
98-
""""protobuf",
99-
"sqlalchemy",
100-
# dependency of grpc""",
91+
'''"protobuf",
92+
# dependency of grpc''',
93+
'''"protobuf",
94+
"sqlalchemy<2.0.0",
95+
# dependency of grpc''',
10196
)
10297

10398

10499
s.replace(
105100
["noxfile.py"],
106101
r"def default\(session\)",
107-
"def default(session, install_extras=True)",
102+
"def default(session, install_extras=True)",
108103
)
109104

110105

106+
107+
111108
def place_before(path, text, *before_text, escape=None):
112109
replacement = "\n".join(before_text) + "\n" + text
113110
if escape:
114111
for c in escape:
115-
text = text.replace(c, "\\" + c)
112+
text = text.replace(c, '\\' + c)
116113
s.replace([path], text, replacement)
117114

115+
place_before(
116+
"noxfile.py",
117+
"SYSTEM_TEST_PYTHON_VERSIONS=",
118+
"",
119+
"# We're using two Python versions to test with sqlalchemy 1.3 and 1.4.",
120+
)
118121

119122
place_before(
120123
"noxfile.py",
@@ -123,15 +126,15 @@ def place_before(path, text, *before_text, escape=None):
123126
)
124127

125128

126-
install_logic = """
129+
install_logic = '''
127130
if install_extras and session.python in ["3.11", "3.12"]:
128131
install_target = ".[geography,alembic,tests,bqstorage]"
129132
elif install_extras:
130133
install_target = ".[all]"
131134
else:
132135
install_target = "."
133136
session.install("-e", install_target, "-c", constraints_path)
134-
"""
137+
'''
135138

136139
place_before(
137140
"noxfile.py",
@@ -159,6 +162,8 @@ def compliance(session):
159162
if not os.path.exists(system_test_folder_path):
160163
session.skip("Compliance tests were not found")
161164
165+
session.install("--pre", "grpcio")
166+
session.install("--pre", "--no-deps", "--upgrade", "sqlalchemy<2.0.0")
162167
session.install(
163168
"mock",
164169
"pytest",
@@ -201,11 +206,12 @@ def compliance(session):
201206
'''
202207

203208
place_before(
204-
"noxfile.py",
205-
"@nox.session(python=DEFAULT_PYTHON_VERSION)\n" "def cover(session):",
206-
compliance,
207-
escape="()",
208-
)
209+
"noxfile.py",
210+
"@nox.session(python=DEFAULT_PYTHON_VERSION)\n"
211+
"def cover(session):",
212+
compliance,
213+
escape="()",
214+
)
209215

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

@@ -261,10 +267,11 @@ def system_noextras(session):
261267

262268
place_before(
263269
"noxfile.py",
264-
"@nox.session(python=SYSTEM_TEST_PYTHON_VERSIONS[-1])\n" "def compliance(session):",
270+
"@nox.session(python=SYSTEM_TEST_PYTHON_VERSIONS[-1])\n"
271+
"def compliance(session):",
265272
system_noextras,
266273
escape="()[]",
267-
)
274+
)
268275

269276

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

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

294301
s.replace(
295-
["./samples/snippets/noxfile.py"],
302+
["./samples/snippets/noxfile.py"],
296303
"""session.install\("-e", _get_repo_root\(\)\)""",
297304
"""session.install("-e", _get_repo_root())
298305
else:

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,9 @@ def readme():
9999
# Until this issue is closed
100100
# https://github.com/googleapis/google-cloud-python/issues/10566
101101
"google-auth>=1.25.0,<3.0.0dev", # Work around pip wack.
102-
"google-cloud-bigquery>=3.3.6,<4.0.0dev",
102+
"google-cloud-bigquery>=2.25.2,<4.0.0dev",
103103
"packaging",
104-
"sqlalchemy>=1.4.16,<3.0.0dev",
104+
"sqlalchemy>=1.2.0,<2.0.0dev",
105105
],
106106
extras_require=extras,
107107
python_requires=">=3.8, <3.13",

sqlalchemy_bigquery/_struct.py

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,20 @@
1717
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1818
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1919

20+
import packaging.version
2021
import sqlalchemy.sql.default_comparator
2122
import sqlalchemy.sql.sqltypes
2223
import sqlalchemy.types
2324

2425
from . import base
2526

26-
import sqlalchemy.sql.coercions
27-
import sqlalchemy.sql.roles
27+
sqlalchemy_1_4_or_more = packaging.version.parse(
28+
sqlalchemy.__version__
29+
) >= packaging.version.parse("1.4")
30+
31+
if sqlalchemy_1_4_or_more:
32+
import sqlalchemy.sql.coercions
33+
import sqlalchemy.sql.roles
2834

2935

3036
def _get_subtype_col_spec(type_):
@@ -97,20 +103,34 @@ def _setup_getitem(self, name):
97103
def __getattr__(self, name):
98104
if name.lower() in self.expr.type._STRUCT_byname:
99105
return self[name]
100-
else:
101-
raise AttributeError(name)
102106

103107
comparator_factory = Comparator
104108

105109

106-
def _field_index(self, name, operator):
107-
return sqlalchemy.sql.coercions.expect(
108-
sqlalchemy.sql.roles.BinaryElementRole,
109-
name,
110-
expr=self.expr,
111-
operator=operator,
112-
bindparam_type=sqlalchemy.types.String(),
113-
)
110+
# In the implementations of _field_index below, we're stealing from
111+
# the JSON type implementation, but the code to steal changed in
112+
# 1.4. :/
113+
114+
if sqlalchemy_1_4_or_more:
115+
116+
def _field_index(self, name, operator):
117+
return sqlalchemy.sql.coercions.expect(
118+
sqlalchemy.sql.roles.BinaryElementRole,
119+
name,
120+
expr=self.expr,
121+
operator=operator,
122+
bindparam_type=sqlalchemy.types.String(),
123+
)
124+
125+
else:
126+
127+
def _field_index(self, name, operator):
128+
return sqlalchemy.sql.default_comparator._check_literal(
129+
self.expr,
130+
operator,
131+
name,
132+
bindparam_type=sqlalchemy.types.String(),
133+
)
114134

115135

116136
def struct_getitem_op(a, b):

0 commit comments

Comments
 (0)