From c2babba09a11b0c98da9f772c6720bf2f440386a Mon Sep 17 00:00:00 2001 From: SvenKlaassen Date: Thu, 20 Nov 2025 20:29:23 +0100 Subject: [PATCH 1/6] update version number to 0.11.0 --- doc/conf.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index 24cb70124..3a1299684 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -23,7 +23,7 @@ author = "Bach, P., Chernozhukov, V., Klaassen, S., Kurz, M. S., and Spindler, M." # The full version, including alpha/beta/rc tags -release = "0.11.dev0" +release = "0.11.0" # -- General configuration --------------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index 2ada0ba8c..1ac60410c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "DoubleML" -version = "0.11.dev0" +version = "0.11.0" description = "Double Machine Learning in Python" readme = {file = "README.md", content-type = "text/markdown"} authors = [ From bab702827ce9e6f3c58171657c2cd38a9d8926e9 Mon Sep 17 00:00:00 2001 From: SvenKlaassen Date: Thu, 4 Dec 2025 14:58:33 +0100 Subject: [PATCH 2/6] Enhance CI workflow: update verification steps for TestPyPI and PyPI --- .github/workflows/deploy_pkg.yml | 46 +++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy_pkg.yml b/.github/workflows/deploy_pkg.yml index f104e4ca1..9b161055c 100644 --- a/.github/workflows/deploy_pkg.yml +++ b/.github/workflows/deploy_pkg.yml @@ -4,6 +4,7 @@ on: release: types: - published + workflow_dispatch: jobs: build: @@ -14,6 +15,7 @@ jobs: - uses: actions/checkout@v4 with: persist-credentials: false + fetch-depth: 0 # Required for dynamic versioning - name: Install python uses: actions/setup-python@v5 @@ -56,11 +58,34 @@ jobs: uses: pypa/gh-action-pypi-publish@release/v1 with: repository-url: https://test.pypi.org/legacy/ + skip-existing: true # Prevents failure on re-runs + + verify-testpypi: + name: Verify TestPyPI Install 🕵️ + needs: publish-to-testpypi + runs-on: ubuntu-latest + steps: + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Wait for TestPyPI indexing + run: sleep 30 + + - name: Install from TestPyPI + # --extra-index-url allows pip to find dependencies (pandas, numpy) on the real PyPI + run: | + pip install --pre --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ DoubleML + + - name: Import Smoke Test + run: python -c "import doubleml; print(f'Successfully imported DoubleML version {doubleml.__version__}')" + publish-to-pypi: name: Publish to PyPI 🚀 - needs: publish-to-testpypi + needs: verify-testpypi runs-on: ubuntu-latest + if: github.event_name == 'release' # Do not publish on workflow_dispatch environment: name: pypi url: https://pypi.org/p/DoubleML @@ -76,3 +101,22 @@ jobs: - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@release/v1 + + verify-pypi: + name: Verify PyPI Install 🕵️ + needs: publish-to-pypi + runs-on: ubuntu-latest + if: github.event_name == 'release' + steps: + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Wait for PyPI indexing + run: sleep 60 + + - name: Install from PyPI + run: pip install DoubleML==${{ github.ref_name }} + + - name: Import Smoke Test + run: python -c "import doubleml; print(f'Successfully imported DoubleML version {doubleml.__version__}')" From fbd256b485232b3b881293c0927d443c99da1a6e Mon Sep 17 00:00:00 2001 From: SvenKlaassen Date: Fri, 5 Dec 2025 09:47:11 +0100 Subject: [PATCH 3/6] Update TestPyPI installation steps: increase wait time and add conditional for workflow_dispatch --- .github/workflows/deploy_pkg.yml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/.github/workflows/deploy_pkg.yml b/.github/workflows/deploy_pkg.yml index 9b161055c..74b3c1e69 100644 --- a/.github/workflows/deploy_pkg.yml +++ b/.github/workflows/deploy_pkg.yml @@ -68,24 +68,28 @@ jobs: - uses: actions/setup-python@v5 with: python-version: "3.12" - + - name: Wait for TestPyPI indexing - run: sleep 30 + run: sleep 60 - name: Install from TestPyPI # --extra-index-url allows pip to find dependencies (pandas, numpy) on the real PyPI - run: | - pip install --pre --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ DoubleML + if: github.event_name == 'release' + run: pip install --pre --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ "DoubleML==${{ github.ref_name }}" + + - name: Install from TestPyPI (workflow_dispatch) + # For manual runs, install the latest pre-release version + if: github.event_name == 'workflow_dispatch' + run: pip install --pre --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ DoubleML - name: Import Smoke Test run: python -c "import doubleml; print(f'Successfully imported DoubleML version {doubleml.__version__}')" - publish-to-pypi: name: Publish to PyPI 🚀 needs: verify-testpypi runs-on: ubuntu-latest - if: github.event_name == 'release' # Do not publish on workflow_dispatch + if: github.event_name == 'release' # Do not publish on workflow_dispatch environment: name: pypi url: https://pypi.org/p/DoubleML @@ -116,7 +120,7 @@ jobs: run: sleep 60 - name: Install from PyPI - run: pip install DoubleML==${{ github.ref_name }} + run: pip install "DoubleML==${{ github.ref_name }}" - name: Import Smoke Test run: python -c "import doubleml; print(f'Successfully imported DoubleML version {doubleml.__version__}')" From d102a459116b1e1d3554216d86f64866a1c61219 Mon Sep 17 00:00:00 2001 From: SvenKlaassen Date: Fri, 5 Dec 2025 12:14:21 +0100 Subject: [PATCH 4/6] Update version handling and dependencies in project configuration --- .github/workflows/pytest.yml | 2 +- .gitignore | 3 +++ doc/conf.py | 4 +++- doubleml/__init__.py | 12 +++++++++--- pyproject.toml | 9 +++++++-- 5 files changed, 23 insertions(+), 7 deletions(-) diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index 6cab94cb2..163dd3999 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -32,7 +32,7 @@ jobs: steps: - uses: actions/checkout@v4 with: - fetch-depth: 2 + fetch-depth: 0 # allow version retrieval with setuptools_scm - name: Set up Python ${{ matrix.config.python-version }} uses: actions/setup-python@v5 diff --git a/.gitignore b/.gitignore index 306442b15..5934c80cf 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,6 @@ MANIFEST *.vscode .flake8 .coverage + +# Setuptools SCM +doubleml/_version.py diff --git a/doc/conf.py b/doc/conf.py index 8671eb07d..cc50d9b09 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -13,6 +13,8 @@ import os import sys +import doubleml + sys.path.insert(0, os.path.abspath("..")) @@ -23,7 +25,7 @@ author = "Bach, P., Chernozhukov, V., Klaassen, S., Kurz, M. S., and Spindler, M." # The full version, including alpha/beta/rc tags -release = "0.12.dev0" +release = doubleml.__version__ # -- General configuration --------------------------------------------------- diff --git a/doubleml/__init__.py b/doubleml/__init__.py index cb3891bac..f83206eee 100644 --- a/doubleml/__init__.py +++ b/doubleml/__init__.py @@ -1,5 +1,3 @@ -import importlib.metadata - from .data import DoubleMLClusterData, DoubleMLData, DoubleMLDIDData, DoubleMLPanelData, DoubleMLRDDData, DoubleMLSSMData from .did.did import DoubleMLDID from .did.did_cs import DoubleMLDIDCS @@ -46,4 +44,12 @@ "DoubleMLLPLR", ] -__version__ = importlib.metadata.version("doubleml") +try: + from ._version import version as __version__ +except ImportError: + import importlib.metadata + + try: + __version__ = importlib.metadata.version("doubleml") + except importlib.metadata.PackageNotFoundError: + __version__ = "0.0.0+unknown" diff --git a/pyproject.toml b/pyproject.toml index eb80c7124..b94ee51f5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,10 @@ [build-system] -requires = ["setuptools>=65", "wheel"] +requires = ["setuptools>=80", "wheel", "setuptools-scm>=8"] build-backend = "setuptools.build_meta" [project] name = "DoubleML" -version = "0.12.dev0" +dynamic = ["version"] description = "Double Machine Learning in Python" readme = {file = "README.md", content-type = "text/markdown"} license = {file = "LICENSE"} @@ -56,6 +56,11 @@ Documentation = "https://docs.doubleml.org" Source = "https://github.com/DoubleML/doubleml-for-py" "Bug Tracker" = "https://github.com/DoubleML/doubleml-for-py/issues" +[tool.setuptools_scm] +version_scheme = "post-release" +local_scheme = "dirty-tag" +write_to = "doubleml/_version.py" + [tool.pytest.ini_options] markers = [ "ci: mark a test as a continuous integration test which will be executed in github actions.", From a701cebc8bc4267a0b5760679753614b01b12ce7 Mon Sep 17 00:00:00 2001 From: SvenKlaassen Date: Fri, 5 Dec 2025 12:44:15 +0100 Subject: [PATCH 5/6] Update version scheme in setuptools_scm to guess-next-dev --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index b94ee51f5..46f90a22f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,7 +57,7 @@ Source = "https://github.com/DoubleML/doubleml-for-py" "Bug Tracker" = "https://github.com/DoubleML/doubleml-for-py/issues" [tool.setuptools_scm] -version_scheme = "post-release" +version_scheme = "guess-next-dev" local_scheme = "dirty-tag" write_to = "doubleml/_version.py" From 4c42c0e8b2aaece2aa62fea92c4bf2a83b616375 Mon Sep 17 00:00:00 2001 From: SvenKlaassen Date: Fri, 5 Dec 2025 14:26:47 +0100 Subject: [PATCH 6/6] Add unit tests for version handling in doubleml package --- doubleml/tests/test_init.py | 38 +++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 doubleml/tests/test_init.py diff --git a/doubleml/tests/test_init.py b/doubleml/tests/test_init.py new file mode 100644 index 000000000..07ee295fc --- /dev/null +++ b/doubleml/tests/test_init.py @@ -0,0 +1,38 @@ +import importlib +import sys +from unittest.mock import patch + +import pytest + + +@pytest.mark.ci +def test_version_from_version_file(): + """Test version is imported from _version.py when available.""" + import doubleml + + assert hasattr(doubleml, "__version__") + assert isinstance(doubleml.__version__, str) + + +@pytest.mark.ci +def test_version_fallback_to_metadata(): + """Test fallback to importlib.metadata when _version.py is missing.""" + with patch.dict(sys.modules, {"doubleml._version": None}): + with patch("importlib.metadata.version", return_value="1.2.3"): + # Re-import to trigger the fallback + importlib.reload(importlib.import_module("doubleml")) + import doubleml + + assert doubleml.__version__ == "1.2.3" + + +@pytest.mark.ci +def test_version_fallback_to_unknown(): + """Test fallback to 0.0.0+unknown when package not found.""" + mock_error = importlib.metadata.PackageNotFoundError() + with patch.dict(sys.modules, {"doubleml._version": None}): + with patch("importlib.metadata.version", side_effect=mock_error): + importlib.reload(importlib.import_module("doubleml")) + import doubleml + + assert doubleml.__version__ == "0.0.0+unknown"