diff --git a/.github/workflows/python-tests.yml b/.github/workflows/python-tests.yml index 89815baa..37a03761 100644 --- a/.github/workflows/python-tests.yml +++ b/.github/workflows/python-tests.yml @@ -121,6 +121,23 @@ jobs: - name: Publish package to PyPI uses: pypa/gh-action-pypi-publish@release/v1 + upload-release-assets: + runs-on: ubuntu-latest + if: github.event_name == 'release' && github.event.action == 'published' + needs: [test] + permissions: + contents: write + steps: + - uses: actions/download-artifact@v4 + with: + name: Packages + path: dist + - name: Upload release assets + uses: softprops/action-gh-release@v2 + with: + files: dist/* + fail_on_unmatched_files: true + test-pypi-upload: runs-on: ubuntu-latest if: github.event_name == 'push' && github.ref == 'refs/heads/main' diff --git a/CHANGELOG.md b/CHANGELOG.md index d77e15ad..673cf02b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## v9.1.1 + +### fixed + +- fix #1194: correctly handle version keyword when pyproject metadata is missing + + ## v9.0.3 ### fixed diff --git a/src/setuptools_scm/_integration/setuptools.py b/src/setuptools_scm/_integration/setuptools.py index 6a98656a..9c9733e7 100644 --- a/src/setuptools_scm/_integration/setuptools.py +++ b/src/setuptools_scm/_integration/setuptools.py @@ -38,7 +38,13 @@ def _warn_on_old_setuptools(_version: str = setuptools.__version__) -> None: def _log_hookstart(hook: str, dist: setuptools.Distribution) -> None: - log.debug("%s %s %s %r", hook, id(dist), id(dist.metadata), vars(dist.metadata)) + log.debug( + "%s %s %s %r", + hook, + id(dist), + id(dist.metadata), + {**vars(dist.metadata), "long_description": ...}, + ) def get_keyword_overrides( diff --git a/src/setuptools_scm/_integration/version_inference.py b/src/setuptools_scm/_integration/version_inference.py index 5fd4991e..51f42cd5 100644 --- a/src/setuptools_scm/_integration/version_inference.py +++ b/src/setuptools_scm/_integration/version_inference.py @@ -154,13 +154,15 @@ def get_version_inference_config( # Handle missing configuration if not pyproject_data.is_required and not pyproject_data.section_present: - # If there are overrides, proceed with inference (explicit use_scm_version) + # If version_keyword was called (overrides is not None), activate setuptools_scm + # This handles both use_scm_version=True (empty {}) and use_scm_version={config} if overrides is not None: return VersionInferenceConfig( dist_name=dist_name, pyproject_data=pyproject_data, overrides=overrides, ) + # If infer_version was called (overrides is None), only activate with config return VersionInferenceNoOp() # Handle missing project section when required @@ -168,6 +170,7 @@ def get_version_inference_config( pyproject_data.is_required and not pyproject_data.section_present and not pyproject_data.project_present + and overrides is None # Only return NoOp for infer_version, not version_keyword ): return VersionInferenceNoOp() diff --git a/testing/test_integration.py b/testing/test_integration.py index 89dc9cda..467cbdf7 100644 --- a/testing/test_integration.py +++ b/testing/test_integration.py @@ -1305,3 +1305,38 @@ def test_infer_version_logs_debug_when_missing_dynamic_version( # Verify that version was not set due to configuration issue assert dist.metadata.version is None + + +@pytest.mark.issue("xmlsec-regression") +def test_xmlsec_download_regression( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + """Test that pip download works for xmlsec package without causing setuptools_scm regression. + + This test ensures that downloading and building xmlsec from source doesn't fail + due to setuptools_scm issues when using --no-build-isolation. + """ + # Set up environment with setuptools_scm debug enabled + monkeypatch.setenv("SETUPTOOLS_SCM_DEBUG", "1") + monkeypatch.setenv("COLUMNS", "150") + + # Run pip download command with no-binary and no-build-isolation + try: + subprocess.run( + [ + *(sys.executable, "-m", "pip", "download"), + *("--no-binary", "xmlsec"), + "--no-build-isolation", + "-v", + "xmlsec==1.3.16", + ], + cwd=tmp_path, + text=True, + timeout=300, + check=True, + ) + except subprocess.CalledProcessError as e: + pytest.fail(f"pip download failed: {e}", pytrace=False) + + # The success of the subprocess.run call above means the regression is fixed. + # pip download succeeded without setuptools_scm causing version conflicts. diff --git a/testing/test_version_inference.py b/testing/test_version_inference.py index d6911358..5bdd2861 100644 --- a/testing/test_version_inference.py +++ b/testing/test_version_inference.py @@ -81,26 +81,70 @@ def test_no_pyproject_toml(self) -> None: # and not call get_version_inference_config at all. # This test is no longer needed as pyproject_data is always required. - def test_no_setuptools_scm_config(self) -> None: - """Test that we don't infer when setuptools-scm is not configured.""" + def test_no_setuptools_scm_config_infer_version(self) -> None: + """Test that we don't infer when setuptools-scm is not configured and infer_version called.""" result = get_version_inference_config( dist_name="test_package", current_version=None, pyproject_data=PyProjectData.for_testing(False, False, True), + overrides=None, # infer_version call ) assert isinstance(result, VersionInferenceNoOp) - def test_setuptools_scm_required_no_project_section(self) -> None: - """Test that we don't infer when setuptools-scm is required but no project section.""" + def test_no_setuptools_scm_config_version_keyword(self) -> None: + """Test that we DO infer when setuptools-scm is not configured but use_scm_version=True.""" + result = get_version_inference_config( + dist_name="test_package", + current_version=None, + pyproject_data=PyProjectData.for_testing(False, False, True), + overrides={}, # version_keyword call with use_scm_version=True + ) + + assert isinstance(result, VersionInferenceConfig) + assert result.dist_name == "test_package" + assert result.overrides == {} + + def test_setuptools_scm_required_no_project_section_infer_version(self) -> None: + """Test that we don't infer when setuptools-scm is required but no project section and infer_version called.""" result = get_version_inference_config( dist_name="test_package", current_version=None, pyproject_data=PyProjectData.for_testing(True, False, False), + overrides=None, # infer_version call ) assert isinstance(result, VersionInferenceNoOp) + def test_setuptools_scm_required_no_project_section_version_keyword(self) -> None: + """Test that we DO infer when setuptools-scm is required but no project section and use_scm_version=True.""" + result = get_version_inference_config( + dist_name="test_package", + current_version=None, + pyproject_data=PyProjectData.for_testing(True, False, False), + overrides={}, # version_keyword call with use_scm_version=True + ) + + assert isinstance(result, VersionInferenceConfig) + assert result.dist_name == "test_package" + assert result.overrides == {} + + def test_setuptools_scm_required_no_project_section_version_keyword_with_config( + self, + ) -> None: + """Test that we DO infer when setuptools-scm is required but no project section and use_scm_version={config}.""" + overrides = {"version_scheme": "calver"} + result = get_version_inference_config( + dist_name="test_package", + current_version=None, + pyproject_data=PyProjectData.for_testing(True, False, False), + overrides=overrides, # version_keyword call with use_scm_version={config} + ) + + assert isinstance(result, VersionInferenceConfig) + assert result.dist_name == "test_package" + assert result.overrides == overrides + def test_setuptools_scm_required_with_project_section(self) -> None: """Test that we infer when setuptools-scm is required and project section exists.""" result = get_version_inference_config(