diff --git a/.devcontainer/setup_env.sh b/.devcontainer/setup_env.sh index 6c9b9b2aa..74ede9590 100644 --- a/.devcontainer/setup_env.sh +++ b/.devcontainer/setup_env.sh @@ -9,6 +9,6 @@ docker compose up -d pip install uv # Use a workspace-local virtualenv so package installs do not fail on user permissions. -uv pip install -r dev_requirements.txt +uv pip install -e . --group dev source .venv/bin/activate pre-commit install diff --git a/.github/scripts/verify_version.py b/.github/scripts/verify_version.py new file mode 100755 index 000000000..5d39fb4b5 --- /dev/null +++ b/.github/scripts/verify_version.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +"""Verify the packaged version matches the release git tag. + +Usage: + python .github/scripts/verify_version.py + +The tag typically comes from ``$GITHUB_REF_NAME`` and may be prefixed with +``v`` (e.g. ``v1.9.1``). The leading ``v`` is stripped before comparison. + +Exits 0 on match, 1 on mismatch, 2 on usage error. +""" +from __future__ import annotations + +import re +import sys +from pathlib import Path + +REPO_ROOT = Path(__file__).resolve().parents[2] +VERSION_FILE = REPO_ROOT / "dbt" / "adapters" / "sqlserver" / "__version__.py" +VERSION_RE = re.compile(r"""version\s*=\s*["'](?P.+?)["']""") + + +def read_package_version(version_file: Path = VERSION_FILE) -> str: + match = VERSION_RE.search(version_file.read_text()) + if not match: + raise ValueError(f"could not find version in {version_file}") + return match.group("version") + + +def main(argv: list[str]) -> int: + if len(argv) != 2: + print("usage: verify_version.py ", file=sys.stderr) + return 2 + tag_version = argv[1].lstrip("v") + pkg_version = read_package_version() + if tag_version != pkg_version: + print( + f"Git tag {tag_version!r} does not match " f"package version {pkg_version!r}", + file=sys.stderr, + ) + return 1 + return 0 + + +if __name__ == "__main__": + sys.exit(main(sys.argv)) diff --git a/.github/workflows/integration-tests-sqlserver.yml b/.github/workflows/integration-tests-sqlserver.yml index db767608b..8094b0b44 100644 --- a/.github/workflows/integration-tests-sqlserver.yml +++ b/.github/workflows/integration-tests-sqlserver.yml @@ -11,13 +11,9 @@ on: # yamllint disable-line rule:truthy - 'tests/functional/**' - 'devops/**' - 'docker-compose.yml' - - 'dev_requirements.txt' - '**/*.lock' - '.locks/**' - 'pyproject.toml' - - 'setup.cfg' - - 'setup.py' - - 'MANIFEST.in' - 'pytest.ini' - '.github/workflows/integration-tests-sqlserver.yml' pull_request: @@ -29,13 +25,9 @@ on: # yamllint disable-line rule:truthy - 'tests/functional/**' - 'devops/**' - 'docker-compose.yml' - - 'dev_requirements.txt' - '**/*.lock' - '.locks/**' - 'pyproject.toml' - - 'setup.cfg' - - 'setup.py' - - 'MANIFEST.in' - 'pytest.ini' - '.github/workflows/integration-tests-sqlserver.yml' schedule: @@ -46,7 +38,7 @@ jobs: name: Regular strategy: matrix: - python_version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + python_version: ["3.10", "3.11", "3.12", "3.13"] msodbc_version: ["17", "18"] sqlserver_version: ["2017", "2019", "2022"] collation: ["SQL_Latin1_General_CP1_CS_AS", "SQL_Latin1_General_CP1_CI_AS"] @@ -70,7 +62,7 @@ jobs: run: pip install uv - name: Install dependencies - run: uv pip install --system -r dev_requirements.txt + run: uv pip install --system -e ".[pyodbc]" --group dev - name: Run functional tests run: pytest -ra -v tests/functional --profile "ci_sql_server" diff --git a/.github/workflows/release-version.yml b/.github/workflows/release-version.yml index a19c0a8fa..4711bbace 100644 --- a/.github/workflows/release-version.yml +++ b/.github/workflows/release-version.yml @@ -15,16 +15,13 @@ jobs: - uses: actions/setup-python@v6 with: - python-version: '3.9' + python-version: '3.10' - - name: Install uv - run: pip install uv + - name: Install build tooling + run: pip install build twine - - name: Install dependencies - run: uv pip install --system -r dev_requirements.txt - - - name: Verify version match - run: python setup.py verify + - name: Verify version matches tag + run: python .github/scripts/verify_version.py "${{ github.ref_name }}" - name: Initialize .pypirc run: | @@ -34,5 +31,5 @@ jobs: - name: Build and publish package run: | - python setup.py sdist bdist_wheel + python -m build twine upload dist/* diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index c88acd060..a461bac2a 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -18,7 +18,7 @@ jobs: name: Unit tests strategy: matrix: - python_version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + python_version: ["3.10", "3.11", "3.12", "3.13"] runs-on: ubuntu-latest permissions: contents: read @@ -36,7 +36,7 @@ jobs: run: pip install uv - name: Install dependencies - run: uv pip install --system -r dev_requirements.txt + run: uv pip install --system -e ".[pyodbc]" --group dev - name: Run unit tests run: pytest -n auto -ra -v tests/unit diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index cfbc714ed..000000000 --- a/MANIFEST.in +++ /dev/null @@ -1 +0,0 @@ -recursive-include dbt/include *.sql *.yml *.md diff --git a/Makefile b/Makefile index 70828d4a2..defc31e1c 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ THREADS ?= auto .PHONY: dev dev: ## Installs adapter in develop mode along with development dependencies @\ - uv pip install -r dev_requirements.txt && pre-commit install + uv pip install -e . --group dev && pre-commit install .PHONY: mypy mypy: ## Runs mypy against staged changes for static type checking. diff --git a/dbt/adapters/sqlserver/py.typed b/dbt/adapters/sqlserver/py.typed new file mode 100644 index 000000000..e69de29bb diff --git a/dev_requirements.txt b/dev_requirements.txt deleted file mode 100644 index 239825e67..000000000 --- a/dev_requirements.txt +++ /dev/null @@ -1,24 +0,0 @@ - -dbt-tests-adapter>=1.9.0,<2.0 - -ruff -black==24.8.0 -bumpversion -flake8 -flaky -freezegun==1.4.0 -ipdb -mypy==1.11.2 -pip-tools -pre-commit -pytest -pytest-dotenv -pytest-csv -pytest-xdist -pytz -tox>=3.13 -twine -wheel -pyodbc -azure-identity --e . diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..069a684c8 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,81 @@ +[build-system] +requires = ["setuptools>=68", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "dbt-sqlserver" +description = "A Microsoft SQL Server adapter plugin for dbt" +readme = "README.md" +license = { text = "MIT" } +authors = [ + { name = "Mikael Ene" }, + { name = "Anders Swanson" }, + { name = "Sam Debruyn" }, + { name = "Cor Zuurmond" }, + { name = "Cody Scott" }, +] +requires-python = ">=3.10" +classifiers = [ + "Development Status :: 5 - Production/Stable", + "License :: OSI Approved :: MIT License", + "Operating System :: Microsoft :: Windows", + "Operating System :: MacOS :: MacOS X", + "Operating System :: POSIX :: Linux", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", +] +dependencies = [ + "dbt-core>=1.9.0,<2.0", + "dbt-common>=1.0,<2.0", + "dbt-adapters>=1.11.0,<2.0", +] +dynamic = ["version"] + +[project.optional-dependencies] +azure = [ + "azure-identity>=1.12.0", +] +pyodbc = [ + "pyodbc>=5.2.0", +] + +[dependency-groups] +dev = [ + "dbt-tests-adapter>=1.9.0,<2.0", + "azure-identity>=1.12.0", + "build", + "bumpversion", + "flaky", + "freezegun==1.4.0", + "ipdb", + "mypy==1.11.2", + "pre-commit", + "pytest", + "pytest-csv", + "pytest-dotenv", + "pytest-xdist", + "pytz", + "ruff", + "tox>=3.13", + "twine", +] + +[project.urls] +"Setup & configuration" = "https://docs.getdbt.com/reference/warehouse-profiles/mssql-profile" +"Documentation & usage" = "https://docs.getdbt.com/reference/resource-configs/mssql-configs" +"Changelog" = "https://github.com/dbt-msft/dbt-sqlserver/blob/master/CHANGELOG.md" +"Issue Tracker" = "https://github.com/dbt-msft/dbt-sqlserver/issues" +"Source" = "https://github.com/dbt-msft/dbt-sqlserver" + +[tool.setuptools.dynamic] +version = { attr = "dbt.adapters.sqlserver.__version__.version" } + +[tool.setuptools.packages.find] +include = ["dbt", "dbt.*"] +namespaces = true + +[tool.setuptools.package-data] +"dbt" = ["include/**/*.sql", "include/**/*.yml", "include/**/*.md"] +"dbt.adapters.sqlserver" = ["py.typed"] diff --git a/setup.py b/setup.py deleted file mode 100644 index 61640e915..000000000 --- a/setup.py +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env python -import os -import re -import sys - -from setuptools import find_namespace_packages, setup -from setuptools.command.install import install - -package_name = "dbt-sqlserver" -authors_list = ["Mikael Ene", "Anders Swanson", "Sam Debruyn", "Cor Zuurmond", "Cody Scott"] -dbt_version = "1.9" -description = """A Microsoft SQL Server adapter plugin for dbt""" - -this_directory = os.path.abspath(os.path.dirname(__file__)) -with open(os.path.join(this_directory, "README.md")) as f: - long_description = f.read() - - -# get this from a separate file -def _dbt_sqlserver_version(): - _version_path = os.path.join(this_directory, "dbt", "adapters", "sqlserver", "__version__.py") - _version_pattern = r"""version\s*=\s*["'](.+)["']""" - with open(_version_path) as f: - match = re.search(_version_pattern, f.read().strip()) - if match is None: - raise ValueError(f"invalid version at {_version_path}") - return match.group(1) - - -package_version = _dbt_sqlserver_version() - -# the package version should be the dbt version, with maybe some things on the -# ends of it. (0.18.1 vs 0.18.1a1, 0.18.1.1, ...) -if not package_version.startswith(dbt_version): - raise ValueError( - f"Invalid setup.py: package_version={package_version} must start with " - f"dbt_version={dbt_version}" - ) - - -class VerifyVersionCommand(install): - """Custom command to verify that the git tag matches our version""" - - description = "Verify that the git tag matches our version" - - def run(self): - tag = os.getenv("GITHUB_REF_NAME") - tag_without_prefix = tag[1:] - - if tag_without_prefix != package_version: - info = "Git tag: {0} does not match the version of this app: {1}".format( - tag_without_prefix, package_version - ) - sys.exit(info) - - -setup( - name=package_name, - version=package_version, - description=description, - long_description=long_description, - long_description_content_type="text/markdown", - license="MIT", - author=", ".join(authors_list), - url="https://github.com/dbt-msft/dbt-sqlserver", - packages=find_namespace_packages(include=["dbt", "dbt.*"]), - include_package_data=True, - install_requires=[ - "dbt-core>=1.9.0,<2.0", - "dbt-common>=1.0,<2.0", - "dbt-adapters>=1.11.0,<2.0", - "pyodbc>=5.2.0", - ], - cmdclass={ - "verify": VerifyVersionCommand, - }, - classifiers=[ - "Development Status :: 5 - Production/Stable", - "License :: OSI Approved :: MIT License", - "Operating System :: Microsoft :: Windows", - "Operating System :: MacOS :: MacOS X", - "Operating System :: POSIX :: Linux", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.13", - ], - project_urls={ - "Setup & configuration": "https://docs.getdbt.com/reference/warehouse-profiles/mssql-profile", # noqa: E501 - "Documentation & usage": "https://docs.getdbt.com/reference/resource-configs/mssql-configs", # noqa: E501 - "Changelog": "https://github.com/dbt-msft/dbt-sqlserver/blob/master/CHANGELOG.md", # noqa: E501 - "Issue Tracker": "https://github.com/dbt-msft/dbt-sqlserver/issues", # noqa: E501 - }, -)