Skip to content
This repository was archived by the owner on May 14, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 google/cloud/sqlalchemy_spanner/requirements.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def computed_columns(self):
def computed_columns_stored(self):
return exclusions.open()

@property
def sane_rowcount(self):
return exclusions.closed()

Expand Down
4 changes: 3 additions & 1 deletion google/cloud/sqlalchemy_spanner/sqlalchemy_spanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@
@listens_for(Pool, "reset")
def reset_connection(dbapi_conn, connection_record):
"""An event of returning a connection back to a pool."""
dbapi_conn.connection.rollback()
if dbapi_conn.connection.inside_transaction:
dbapi_conn.connection.rollback()

if getattr(dbapi_conn.connection, "staleness", None) is not None:
dbapi_conn.connection.staleness = None

Expand Down
37 changes: 27 additions & 10 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class = StreamHandler
)"""


BLACK_VERSION = "black==19.10b0"
BLACK_VERSION = "black==22.3.0"
BLACK_PATHS = ["google", "test", "noxfile.py", "setup.py", "samples"]
DEFAULT_PYTHON_VERSION = "3.8"

Expand All @@ -82,10 +82,15 @@ def lint(session):
"""
session.install("flake8", BLACK_VERSION)
session.run(
"black", "--check", *BLACK_PATHS,
"black",
"--check",
*BLACK_PATHS,
)
session.run(
"flake8", "google", "test", "--max-line-length=88",
"flake8",
"google",
"test",
"--max-line-length=88",
)


Expand All @@ -101,7 +106,8 @@ def blacken(session):
"""
session.install(BLACK_VERSION)
session.run(
"black", *BLACK_PATHS,
"black",
*BLACK_PATHS,
)


Expand All @@ -128,17 +134,23 @@ def compliance_test_13(session):
)

session.install(
"pytest", "pytest-cov", "pytest-asyncio",
"pytest",
"pytest-cov",
"pytest-asyncio",
)

session.install("mock")
session.install("-e", ".[tracing]")
session.run("pip", "install", "sqlalchemy>=1.1.13,<=1.3.24", "--force-reinstall")
session.run("pip", "install", "pytest==6.2.2", "--force-reinstall")
session.run("pip", "install", "opentelemetry-api<=1.10", "--force-reinstall")
session.run("pip", "install", "opentelemetry-sdk<=1.10", "--force-reinstall")
session.run("python", "create_test_database.py")

session.run(
"py.test",
"--cov=google.cloud.sqlalchemy_spanner",
"--cov=tests",
"--cov=test",
"--cov-append",
"--cov-config=.coveragerc",
"--cov-report=",
Expand All @@ -164,7 +176,9 @@ def compliance_test_14(session):
)

session.install(
"pytest", "pytest-cov", "pytest-asyncio",
"pytest",
"pytest-cov",
"pytest-asyncio",
)

session.install("mock")
Expand All @@ -176,7 +190,7 @@ def compliance_test_14(session):
session.run(
"py.test",
"--cov=google.cloud.sqlalchemy_spanner",
"--cov=tests",
"--cov=test",
"--cov-append",
"--cov-config=.coveragerc",
"--cov-report=",
Expand Down Expand Up @@ -214,7 +228,8 @@ def migration_test(session):
session.run("python", "create_test_database.py")

project = os.getenv(
"GOOGLE_CLOUD_PROJECT", os.getenv("PROJECT_ID", "emulator-test-project"),
"GOOGLE_CLOUD_PROJECT",
os.getenv("PROJECT_ID", "emulator-test-project"),
)
db_url = (
f"spanner+spanner:///projects/{project}/instances/"
Expand Down Expand Up @@ -242,7 +257,9 @@ def migration_test(session):
with open(files[0], "r") as f:
script_code = f.read()

script_code = script_code.replace("""def upgrade():\n pass""", UPGRADE_CODE)
script_code = script_code.replace(
"""def upgrade() -> None:\n pass""", UPGRADE_CODE
)
with open(files[0], "w") as f:
f.write(script_code)

Expand Down
3 changes: 2 additions & 1 deletion samples/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
@pytest.fixture
def db_url():
project = os.getenv(
"GOOGLE_CLOUD_PROJECT", os.getenv("PROJECT_ID", "emulator-test-project"),
"GOOGLE_CLOUD_PROJECT",
os.getenv("PROJECT_ID", "emulator-test-project"),
)
db_url = (
f"spanner:///projects/{project}/instances/"
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

[tool:pytest]
addopts= --tb native -v -r fxX --maxfail=25 -p no:warnings
python_files=test/*test_*.py
python_classes=*Test

[sqla_testing]
requirement_cls=google.cloud.sqlalchemy_spanner.requirements:Requirements
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
name = "sqlalchemy-spanner"
description = "SQLAlchemy dialect integrated into Cloud Spanner database"
dependencies = [
"sqlalchemy>=1.1.13, <=1.3.23",
"sqlalchemy>=1.1.13",
"google-cloud-spanner>=3.12.0",
"alembic",
]
Expand Down
3 changes: 2 additions & 1 deletion test/_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@


PROJECT = os.getenv(
"GOOGLE_CLOUD_PROJECT", os.getenv("PROJECT_ID", "emulator-test-project"),
"GOOGLE_CLOUD_PROJECT",
os.getenv("PROJECT_ID", "emulator-test-project"),
)
DB_URL = (
f"spanner:///projects/{PROJECT}/instances/"
Expand Down
12 changes: 8 additions & 4 deletions test/benchmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ def __init__(self):
self._many_rows = []
self._many_rows2 = []
birth_date = datetime.date(1998, 10, 6)
picture = base64.b64encode(u"123".encode())
picture = base64.b64encode("123".encode())
for num in self._many_rows_ids:
self._many_rows.append(
{
Expand Down Expand Up @@ -216,7 +216,9 @@ def __init__(self):
super().__init__()
self._engine = create_engine(
"spanner:///projects/{project}/instances/{instance}/databases/{db}".format(
project=PROJECT, instance=INSTANCE, db=DATABASE,
project=PROJECT,
instance=INSTANCE,
db=DATABASE,
)
)
metadata = MetaData(bind=self._engine)
Expand Down Expand Up @@ -260,13 +262,15 @@ def insert_one_row_with_fetch_after(self):
@measure_execution_time
def insert_many_rows(self):
self._conn.execute(
self._table.insert(), self._many_rows,
self._table.insert(),
self._many_rows,
)

@measure_execution_time
def insert_many_rows_with_mutations(self):
self._conn.execute(
self._table.insert(), self._many_rows2,
self._table.insert(),
self._many_rows2,
)

@measure_execution_time
Expand Down
21 changes: 16 additions & 5 deletions test/test_suite_13.py
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,10 @@ def _test_get_unique_constraints(self, schema=None):

reflected_metadata = MetaData()
reflected = Table(
"testtbl", reflected_metadata, autoload_with=orig_meta.bind, schema=schema,
"testtbl",
reflected_metadata,
autoload_with=orig_meta.bind,
schema=schema,
)

# test "deduplicates for index" logic. MySQL and Oracle
Expand Down Expand Up @@ -1079,7 +1082,9 @@ def test_render_literal_numeric(self):
Overriding the test to avoid the same failure.
"""
self._literal_round_trip(
Numeric(precision=8, scale=4), [15.7563], [decimal.Decimal("15.7563")],
Numeric(precision=8, scale=4),
[15.7563],
[decimal.Decimal("15.7563")],
)
self._literal_round_trip(
Numeric(precision=8, scale=4),
Expand All @@ -1098,7 +1103,9 @@ def test_render_literal_numeric_asfloat(self):
Overriding the test to avoid the same failure.
"""
self._literal_round_trip(
Numeric(precision=8, scale=4, asdecimal=False), [15.7563], [15.7563],
Numeric(precision=8, scale=4, asdecimal=False),
[15.7563],
[15.7563],
)
self._literal_round_trip(
Numeric(precision=8, scale=4, asdecimal=False),
Expand Down Expand Up @@ -1193,7 +1200,9 @@ def test_float_as_decimal(self):
Overriding the test to avoid the same failure.
"""
self._do_test(
Float(precision=8, asdecimal=True), [15.7563], [decimal.Decimal("15.7563")],
Float(precision=8, asdecimal=True),
[15.7563],
[decimal.Decimal("15.7563")],
)

self._do_test(
Expand Down Expand Up @@ -1742,7 +1751,9 @@ def define_tables(cls, metadata):
if testing.requires.computed_columns_stored.enabled:
t.append_column(
Column(
"computed_stored", Integer, Computed("normal - 42", persisted=True),
"computed_stored",
Integer,
Computed("normal - 42", persisted=True),
)
)
if testing.requires.schemas.enabled:
Expand Down
27 changes: 21 additions & 6 deletions test/test_suite_14.py
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,9 @@ def test_reflect_bytes_column_max_len(self):
"""
metadata = MetaData(self.bind)
Table(
"bytes_table", metadata, Column("TestColumn", LargeBinary, nullable=False),
"bytes_table",
metadata,
Column("TestColumn", LargeBinary, nullable=False),
)
metadata.create_all()

Expand Down Expand Up @@ -600,7 +602,10 @@ def test_get_unique_constraints(self, metadata, connection, use_schema):

reflected_metadata = MetaData()
reflected = Table(
"testtbl", reflected_metadata, autoload_with=connection, schema=schema,
"testtbl",
reflected_metadata,
autoload_with=connection,
schema=schema,
)

# test "deduplicates for index" logic. MySQL and Oracle
Expand Down Expand Up @@ -964,7 +969,9 @@ def test_limit_render_multiple_times(self, connection):
u = union(select(stmt), select(stmt)).subquery().select()

self._assert_result(
connection, u, [(2,)],
connection,
u,
[(2,)],
)


Expand Down Expand Up @@ -1939,7 +1946,9 @@ def define_tables(cls, metadata):
if testing.requires.computed_columns_stored.enabled:
t.append_column(
Column(
"computed_stored", Integer, Computed("normal - 42", persisted=True),
"computed_stored",
Integer,
Computed("normal - 42", persisted=True),
)
)

Expand All @@ -1960,11 +1969,17 @@ def test_get_column_returns_persisted_with_schema(self):
)
if testing.requires.computed_columns_virtual.enabled:
self.check_column(
data, "computed_virtual", "normal/2", False,
data,
"computed_virtual",
"normal/2",
False,
)
if testing.requires.computed_columns_stored.enabled:
self.check_column(
data, "computed_stored", "normal-42", True,
data,
"computed_stored",
"normal-42",
True,
)

@pytest.mark.skip("Default values are not supported.")
Expand Down
7 changes: 4 additions & 3 deletions test/unit/test_opentelemetry_tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def _make_rpc_error(error_cls, trailing_metadata=None):
# Skip all of these tests if we don't have OpenTelemetry
if HAS_OPENTELEMETRY_INSTALLED:

class TestNoTracing(OpenTelemetryBase):
class NoTracingTest(OpenTelemetryBase):
def setup(self):
self._temp_opentelemetry = sys.modules["opentelemetry"]

Expand All @@ -47,7 +47,7 @@ def test_no_trace_call(self):
with _opentelemetry_tracing.trace_call("Test") as no_span:
assert no_span is None

class TestTracing(OpenTelemetryBase):
class TracingTest(OpenTelemetryBase):
def test_trace_call(self):
extra_attributes = {
"attribute1": "value1",
Expand Down Expand Up @@ -96,7 +96,8 @@ def test_trace_error(self):

with pytest.raises(GoogleAPICallError):
with _opentelemetry_tracing.trace_call(
"CloudSpannerSqlAlchemy.Test", extra_attributes,
"CloudSpannerSqlAlchemy.Test",
extra_attributes,
) as span:
from google.api_core.exceptions import InvalidArgument

Expand Down