File: test_pyproject_reading.py

package info (click to toggle)
setuptools-scm 9.2.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,108 kB
  • sloc: python: 7,068; sh: 18; makefile: 7
file content (181 lines) | stat: -rw-r--r-- 6,855 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
from __future__ import annotations

from pathlib import Path
from unittest.mock import Mock

import pytest

from setuptools_scm._integration.pyproject_reading import has_build_package_with_extra
from setuptools_scm._integration.pyproject_reading import read_pyproject


class TestPyProjectReading:
    """Test the pyproject reading functionality."""

    def test_read_pyproject_missing_file_raises(self, tmp_path: Path) -> None:
        """Test that read_pyproject raises FileNotFoundError when file is missing."""
        with pytest.raises(FileNotFoundError):
            read_pyproject(path=tmp_path / "nonexistent.toml")

    def test_read_pyproject_existing_file(self, tmp_path: Path) -> None:
        """Test that read_pyproject reads existing files correctly."""
        # Create a simple pyproject.toml
        pyproject_content = """
[build-system]
requires = ["setuptools>=80", "setuptools-scm>=8"]
build-backend = "setuptools.build_meta"

[project]
name = "test-package"
dynamic = ["version"]

[tool.setuptools_scm]
"""
        pyproject_file = tmp_path / "pyproject.toml"
        pyproject_file.write_text(pyproject_content, encoding="utf-8")

        result = read_pyproject(path=pyproject_file)

        assert result.path == pyproject_file
        assert result.tool_name == "setuptools_scm"
        assert result.is_required is True
        assert result.section_present is True
        assert result.project_present is True
        assert result.project.get("name") == "test-package"


class TestBuildPackageWithExtra:
    """Test the has_build_package_with_extra function."""

    def test_has_simple_extra(self) -> None:
        """Test that simple extra is detected correctly."""
        requires = ["setuptools-scm[simple]"]
        assert (
            has_build_package_with_extra(requires, "setuptools-scm", "simple") is True
        )

    def test_has_no_simple_extra(self) -> None:
        """Test that missing simple extra is detected correctly."""
        requires = ["setuptools-scm"]
        assert (
            has_build_package_with_extra(requires, "setuptools-scm", "simple") is False
        )

    def test_has_different_extra(self) -> None:
        """Test that different extra is not detected as simple."""
        requires = ["setuptools-scm[toml]"]
        assert (
            has_build_package_with_extra(requires, "setuptools-scm", "simple") is False
        )

    def test_has_multiple_extras_including_simple(self) -> None:
        """Test that simple extra is detected when multiple extras are present."""
        requires = ["setuptools-scm[simple,toml]"]
        assert (
            has_build_package_with_extra(requires, "setuptools-scm", "simple") is True
        )

    def test_different_package_with_simple_extra(self) -> None:
        """Test that simple extra on different package is not detected."""
        requires = ["other-package[simple]"]
        assert (
            has_build_package_with_extra(requires, "setuptools-scm", "simple") is False
        )

    def test_version_specifier_with_extra(self) -> None:
        """Test that version specifiers work correctly with extras."""
        requires = ["setuptools-scm[simple]>=8.0"]
        assert (
            has_build_package_with_extra(requires, "setuptools-scm", "simple") is True
        )

    def test_complex_requirement_with_extra(self) -> None:
        """Test that complex requirements with extras work correctly."""
        requires = ["setuptools-scm[simple]>=8.0,<9.0"]
        assert (
            has_build_package_with_extra(requires, "setuptools-scm", "simple") is True
        )

    def test_empty_requires_list(self) -> None:
        """Test that empty requires list returns False."""
        requires: list[str] = []
        assert (
            has_build_package_with_extra(requires, "setuptools-scm", "simple") is False
        )

    def test_invalid_requirement_string(self) -> None:
        """Test that invalid requirement strings are handled gracefully."""
        requires = ["invalid requirement string"]
        assert (
            has_build_package_with_extra(requires, "setuptools-scm", "simple") is False
        )


def test_read_pyproject_with_given_definition(monkeypatch: pytest.MonkeyPatch) -> None:
    """Test that read_pyproject reads existing files correctly."""
    monkeypatch.setattr(
        "setuptools_scm._integration.pyproject_reading.read_toml_content",
        Mock(side_effect=FileNotFoundError("this test should not read")),
    )

    res = read_pyproject(
        _given_definition={
            "build-system": {"requires": ["setuptools-scm[simple]"]},
            "project": {"name": "test-package", "dynamic": ["version"]},
        }
    )

    assert res.should_infer()


def test_read_pyproject_with_setuptools_dynamic_version_warns() -> None:
    """Test that warning is issued when version inference is enabled."""
    with pytest.warns(
        UserWarning,
        match=r"pyproject\.toml: at \[tool\.setuptools\.dynamic\]",
    ):
        pyproject_data = read_pyproject(
            _given_definition={
                "build-system": {"requires": ["setuptools-scm[simple]"]},
                "project": {"name": "test-package", "dynamic": ["version"]},
                "tool": {
                    "setuptools": {
                        "dynamic": {"version": {"attr": "test_package.__version__"}}
                    }
                },
            }
        )
    assert pyproject_data.project_version is None


def test_read_pyproject_with_setuptools_dynamic_version_no_warn_when_file_finder_only() -> (
    None
):
    """Test that no warning is issued when only file finder is used (no version inference)."""
    # When setuptools-scm is used only for file finding (no [tool.setuptools_scm] section,
    # no [simple] extra, version not in dynamic), it's valid to use tool.setuptools.dynamic.version
    import warnings

    with warnings.catch_warnings(record=True) as warning_list:
        warnings.simplefilter("always")
        pyproject_data = read_pyproject(
            _given_definition={
                "build-system": {"requires": ["setuptools-scm"]},
                "project": {"name": "test-package", "version": "1.0.0"},
                "tool": {
                    "setuptools": {
                        "dynamic": {"version": {"attr": "test_package.__version__"}}
                    }
                },
            }
        )

    # Filter to check for the dynamic version warning specifically
    relevant_warnings = [
        w for w in warning_list if "tool.setuptools.dynamic" in str(w.message)
    ]
    assert len(relevant_warnings) == 0, (
        "Should not warn about tool.setuptools.dynamic when only using file finder"
    )
    assert pyproject_data.project_version == "1.0.0"
    assert not pyproject_data.should_infer()