diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 495b4e58f..71a5adf30 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -37,7 +37,7 @@ env: jobs: tests: - name: Test on ${{ matrix.python-version }} (${{ matrix.session }}) / ${{ matrix.os }} + name: "Test on ${{ matrix.python-version }} (${{ matrix.session }}) / ${{ matrix.os }} / SQLAlchemy: ${{ matrix.sqlalchemy }}" runs-on: ${{ matrix.os }} env: NOXSESSION: ${{ matrix.session }} @@ -47,9 +47,11 @@ jobs: session: [tests] os: ["ubuntu-latest", "macos-latest", "windows-latest"] python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] + sqlalchemy: ["2.*"] include: - - { session: doctest, python-version: "3.10", os: "ubuntu-latest" } - - { session: mypy, python-version: "3.8", os: "ubuntu-latest" } + - { session: tests, python-version: "3.11", os: "ubuntu-latest", sqlalchemy: "1.*" } + - { session: doctest, python-version: "3.10", os: "ubuntu-latest", sqlalchemy: "2.*" } + - { session: mypy, python-version: "3.8", os: "ubuntu-latest", sqlalchemy: "2.*" } steps: - name: Check out the repository @@ -86,6 +88,8 @@ jobs: nox --version - name: Run Nox + env: + SQLALCHEMY_VERSION: ${{ matrix.sqlalchemy }} run: | nox --python=${{ matrix.python-version }} diff --git a/noxfile.py b/noxfile.py index 4c4949413..7f65b8f21 100644 --- a/noxfile.py +++ b/noxfile.py @@ -85,6 +85,14 @@ def tests(session: Session) -> None: session.install(".[s3]") session.install(*test_dependencies) + sqlalchemy_version = os.environ.get("SQLALCHEMY_VERSION") + if sqlalchemy_version: + # Bypass nox-poetry use of --constraint so we can install a version of + # SQLAlchemy that doesn't match what's in poetry.lock. + session.poetry.session.install( # type: ignore[attr-defined] + f"sqlalchemy=={sqlalchemy_version}", + ) + try: session.run( "coverage", @@ -95,9 +103,6 @@ def tests(session: Session) -> None: "-v", "--durations=10", *session.posargs, - env={ - "SQLALCHEMY_WARN_20": "1", - }, ) finally: if session.interactive: diff --git a/poetry.lock b/poetry.lock index 9334d6645..96a31a297 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2346,20 +2346,6 @@ postgresql-psycopg2cffi = ["psycopg2cffi"] pymysql = ["pymysql", "pymysql (<1)"] sqlcipher = ["sqlcipher3-binary"] -[[package]] -name = "sqlalchemy2-stubs" -version = "0.0.2a35" -description = "Typing Stubs for SQLAlchemy 1.4" -optional = false -python-versions = ">=3.6" -files = [ - {file = "sqlalchemy2-stubs-0.0.2a35.tar.gz", hash = "sha256:bd5d530697d7e8c8504c7fe792ef334538392a5fb7aa7e4f670bfacdd668a19d"}, - {file = "sqlalchemy2_stubs-0.0.2a35-py3-none-any.whl", hash = "sha256:593784ff9fc0dc2ded1895e3322591689db3be06f3ca006e3ef47640baf2d38a"}, -] - -[package.dependencies] -typing-extensions = ">=3.7.4" - [[package]] name = "termcolor" version = "2.3.0" @@ -2712,4 +2698,4 @@ testing = ["pytest", "pytest-durations"] [metadata] lock-version = "2.0" python-versions = "<3.12,>=3.7.1" -content-hash = "ef713a1192d52c92e45d00697c48d51df216f225476d2a5744954302b438dc8e" +content-hash = "9ac1398cdb5cd011452f152cbd95412139f320881bb2d27855dc52253b313332" diff --git a/pyproject.toml b/pyproject.toml index bdf111925..f70055d1d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,7 +52,7 @@ memoization = ">=0.3.2,<0.5.0" jsonpath-ng = "^1.5.3" joblib = "^1.0.1" inflection = "^0.5.1" -sqlalchemy = "^1.4" +sqlalchemy = ">=1.4,<3.0" python-dotenv = ">=0.20,<0.22" typing-extensions = "^4.2.0" simplejson = "^3.17.6" @@ -109,7 +109,6 @@ numpy = [ { version = ">=1.22", python = ">=3.8" }, ] requests-mock = "^1.10.0" -sqlalchemy2-stubs = {version = "^0.0.2a32", allow-prereleases = true} types-jsonschema = "^4.17.0.6" types-python-dateutil = "^2.8.19" types-pytz = ">=2022.7.1.2,<2024.0.0.0" @@ -132,9 +131,6 @@ exclude = ".*simpleeval.*" [tool.pytest.ini_options] addopts = '-vvv --ignore=singer_sdk/helpers/_simpleeval.py -m "not external"' -filterwarnings = [ - "error::sqlalchemy.exc.RemovedIn20Warning", -] markers = [ "external: Tests relying on external resources", "windows: Tests that only run on Windows", @@ -190,9 +186,6 @@ fail_under = 82 [tool.mypy] exclude = "tests" files = "singer_sdk" -plugins = [ - "sqlalchemy.ext.mypy.plugin", -] python_version = "3.8" warn_unused_configs = true warn_unused_ignores = true diff --git a/singer_sdk/sinks/sql.py b/singer_sdk/sinks/sql.py index 6b6f8d121..02fd307b9 100644 --- a/singer_sdk/sinks/sql.py +++ b/singer_sdk/sinks/sql.py @@ -322,11 +322,7 @@ def bulk_insert_records( if isinstance(insert_sql, str): insert_sql = sqlalchemy.text(insert_sql) - conformed_records = ( - [self.conform_record(record) for record in records] - if isinstance(records, list) - else (self.conform_record(record) for record in records) - ) + conformed_records = [self.conform_record(record) for record in records] self.logger.info("Inserting with SQL: %s", insert_sql) with self.connector._connect() as conn, conn.begin(): conn.execute(insert_sql, conformed_records) diff --git a/tests/conftest.py b/tests/conftest.py index cb201c9a1..25319c015 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -8,6 +8,7 @@ import typing as t import pytest +from sqlalchemy import __version__ as sqlalchemy_version from singer_sdk import typing as th from singer_sdk.sinks import BatchSink @@ -39,6 +40,11 @@ def pytest_runtest_setup(item): pytest.skip(f"cannot run on platform {system}") +def pytest_report_header() -> list[str]: + """Return a list of strings to be displayed in the header of the report.""" + return [f"sqlalchemy: {sqlalchemy_version}"] + + @pytest.fixture(scope="class") def outdir() -> t.Generator[str, None, None]: """Create a temporary directory for cookiecutters and target output."""