diff --git a/.github/workflows/release_schedule.yaml b/.github/workflows/release_schedule.yaml deleted file mode 100644 index dabdb70..0000000 --- a/.github/workflows/release_schedule.yaml +++ /dev/null @@ -1,71 +0,0 @@ -name: Generate release schedule artifacts -on: - schedule: - # At 00:00 on day-of-month 2 in every 3rd month. (i.e. every quarter) - # 2nd is chosen to avoid fencepost errors - - cron: "0 0 2 */3 *" - push: - branches: - - "main" - # On demand - workflow_dispatch: - -jobs: - create-artifacts: - runs-on: ubuntu-latest - permissions: - contents: write - steps: - - name: Checkout - uses: actions/checkout@v5 - with: - # We're going to make a tag that we can we release so we'll need the full history for that - fetch-depth: 0 - - - uses: prefix-dev/setup-pixi@v0.9.2 - with: - pixi-version: "v0.49.0" - - - name: Generate artifacts - run: | - pixi run generate-schedule --locked - - - name: Test json artifact - run: | - cat schedule.json | jq - - - name: setup git - run: | - # git will complain if we don't do this first - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - - - name: determine tag name - id: tag_name - run: | - echo "TAG_NAME=$(date '+%Y-Q%q')" >> "$GITHUB_OUTPUT" - - name: Commit artifacts and create tag - env: - GH_TOKEN: ${{ secrets.RELEASE_PAT }} - run: | - git add -f schedule.md chart.md schedule.json - git commit -m "generate schedule for ${{ steps.tag_name.outputs.TAG_NAME }} release" || echo "No changes to commit" - git tag ${{ steps.tag_name.outputs.TAG_NAME }} - git push origin main - git push origin tag ${{ steps.tag_name.outputs.TAG_NAME }} - - - name: Publish github release - uses: softprops/action-gh-release@v2 - env: - GH_TOKEN: ${{ secrets.RELEASE_PAT }} - with: - generate_release_notes: true - tag_name: ${{ steps.tag_name.outputs.TAG_NAME }} - make_latest: true - files: | - schedule.md - chart.md - schedule.json - -permissions: - contents: write diff --git a/action.yaml b/action.yaml index 3cfa502..ddbdbd6 100644 --- a/action.yaml +++ b/action.yaml @@ -35,19 +35,19 @@ runs: using: "composite" steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Set up Git shell: bash run: | git config user.name "Scientific Python [bot]" git config user.email "scientific-python@users.noreply.github.com" - - uses: prefix-dev/setup-pixi@v0.9.3 + - uses: prefix-dev/setup-pixi@82d477f15f3a381dbcc8adc1206ce643fe110fb7 # v0.9.3 name: Setup Pixi with: pixi-version: v0.49.0 manifest-path: ${{ github.action_path }}/pyproject.toml - name: Fetch Schedule from release - uses: robinraju/release-downloader@v1.3 + uses: robinraju/release-downloader@daf26c55d821e836577a15f77d86ddc078948b05 # v1.12 with: repository: "savente93/SPEC0-schedule" latest: true @@ -71,7 +71,7 @@ runs: fi - name: Create Pull Request if: ${{ fromJSON(inputs.create_pr) && fromJSON(steps.changes.outputs.changes_detected) }} - uses: peter-evans/create-pull-request@v7 + uses: peter-evans/create-pull-request@84ae59a2cdc2258d6fa0732dd66352dddae2a412 # v7.0.2 with: token: ${{ inputs.token }} commit-message: ${{ inputs.commit_msg }} diff --git a/spec0_action/__init__.py b/spec0_action/__init__.py index 85307fb..c5a422b 100644 --- a/spec0_action/__init__.py +++ b/spec0_action/__init__.py @@ -23,7 +23,7 @@ def update_pyproject_dependencies(dependencies: dict, schedule: SupportSchedule) # Iterate by idx because we want to update it inplace for i in range(len(dependencies)): dep_str = dependencies[i] - pkg, extras, spec = parse_pep_dependency(dep_str) + pkg, extras, spec, env = parse_pep_dependency(dep_str) if isinstance(spec, Url) or pkg not in schedule["packages"]: continue @@ -36,9 +36,9 @@ def update_pyproject_dependencies(dependencies: dict, schedule: SupportSchedule) continue if not extras: - new_dep_str = f"{pkg}{repr_spec_set(spec)}" + new_dep_str = f"{pkg}{repr_spec_set(spec)}{env or ''}" else: - new_dep_str = f"{pkg}{extras}{repr_spec_set(spec)}" + new_dep_str = f"{pkg}{extras}{repr_spec_set(spec)}{env or ''}" dependencies[i] = new_dep_str diff --git a/spec0_action/parsing.py b/spec0_action/parsing.py index 85575bf..c4bbf57 100644 --- a/spec0_action/parsing.py +++ b/spec0_action/parsing.py @@ -12,7 +12,9 @@ Url: TypeAlias = ParseResult # Slightly modified version of https://packaging.python.org/en/latest/specifications/dependency-specifiers/#names -PEP_PACKAGE_IDENT_RE = compile(r"(?im)^([A-Z0-9][A-Z0-9._-]*)(\[[A-Z0-9._,-]+\])?(.*)$") +PEP_PACKAGE_IDENT_RE = compile( + r"(?im)^([A-Z0-9][A-Z0-9._-]*)(\[[A-Z0-9._,-]+\])?([^;]*)(;.*)?$" +) class SupportSchedule(TypedDict): @@ -64,12 +66,12 @@ def read_schedule(path: Path | str) -> Sequence[SupportSchedule]: def parse_pep_dependency( dep_str: str, -) -> Tuple[str, str | None, SpecifierSet | Url | None]: +) -> Tuple[str, str | None, SpecifierSet | Url | None, str | None]: match = PEP_PACKAGE_IDENT_RE.match(dep_str) if match is None: raise ValueError("Could not find any valid python package identifier") - pkg, extras, spec_str = match.groups() + pkg, extras, spec_str, env = match.groups() extras = extras or None @@ -80,7 +82,7 @@ def parse_pep_dependency( else: spec = SpecifierSet(spec_str) - return (pkg, extras, spec) + return (pkg, extras, spec, env) def is_url_spec(str_spec: str | None) -> bool: diff --git a/tests/test_data/pyproject.toml b/tests/test_data/pyproject.toml index f289a6f..9198b2a 100644 --- a/tests/test_data/pyproject.toml +++ b/tests/test_data/pyproject.toml @@ -8,9 +8,13 @@ build-backend = "setuptools.build_meta" [project] name = "setuptools_test" +version = "0.1.0" requires-python = ">=3.11" dependencies = [ - 'numpy>=1.20.0,<2', 'pandas>=1.0.0,<3', 'xarray>=2021.1.0', + "ipython>=8.7.0,<4", + "numpy[foo,bar]>=1.10.0,<2", + "scikit-learn>1.2,<1.4;sys_platform=='win32'", + "scikit-learn>1.2;sys_platform!='win32'" ] diff --git a/tests/test_data/pyproject_pixi.toml b/tests/test_data/pyproject_pixi.toml index b06e4c5..959d181 100644 --- a/tests/test_data/pyproject_pixi.toml +++ b/tests/test_data/pyproject_pixi.toml @@ -4,7 +4,12 @@ name = "tests" description = "This is just a dummy package for testing the spec 0 update github action and should not be used" requires-python = ">=3.10" version = "0.1.0" -dependencies = ["ipython>=8.7.0,<4", "numpy[foo,bar]>=1.10.0,<2"] +dependencies = [ + "ipython>=8.7.0,<4", + "numpy[foo,bar]>=1.10.0,<2", + "scikit-learn>1.2,<1.4;sys_platform=='win32'", + "scikit-learn>1.2;sys_platform!='win32'" +] [build-system] build-backend = "hatchling.build" diff --git a/tests/test_data/pyproject_pixi_updated.toml b/tests/test_data/pyproject_pixi_updated.toml index a780ef7..21e724b 100644 --- a/tests/test_data/pyproject_pixi_updated.toml +++ b/tests/test_data/pyproject_pixi_updated.toml @@ -4,8 +4,12 @@ name = "tests" description = "This is just a dummy package for testing the spec 0 update github action and should not be used" requires-python = ">=3.11" version = "0.1.0" -dependencies = ["ipython>=8.8.0,<4", "numpy[foo,bar]>=1.25.0,<2"] - +dependencies = [ + "ipython>=8.8.0,<4", + "numpy[foo,bar]>=1.25.0,<2", + "scikit-learn>=1.3.0,<1.4;sys_platform=='win32'", + "scikit-learn>=1.3.0;sys_platform!='win32'" +] [build-system] build-backend = "hatchling.build" requires = ["hatchling"] diff --git a/tests/test_data/pyproject_updated.toml b/tests/test_data/pyproject_updated.toml index 8698dbb..83741ec 100644 --- a/tests/test_data/pyproject_updated.toml +++ b/tests/test_data/pyproject_updated.toml @@ -8,9 +8,13 @@ build-backend = "setuptools.build_meta" [project] name = "setuptools_test" +version = "0.1.0" requires-python = ">=3.11" dependencies = [ - 'numpy>=1.25.0,<2', 'pandas>=1.0.0,<3', 'xarray>=2023.1.0', + "ipython>=8.8.0,<4", + "numpy[foo,bar]>=1.25.0,<2", + "scikit-learn>=1.3.0,<1.4;sys_platform=='win32'", + "scikit-learn>=1.3.0;sys_platform!='win32'" ] diff --git a/tests/test_parsing.py b/tests/test_parsing.py index dfdf253..3ba094f 100644 --- a/tests/test_parsing.py +++ b/tests/test_parsing.py @@ -22,46 +22,61 @@ def test_parsing_incorrect(): def test_pep_dependency_parsing(): matplotlib_str = "matplotlib" - pkg, features, spec = parse_pep_dependency(matplotlib_str) + pkg, features, spec, env = parse_pep_dependency(matplotlib_str) assert pkg == "matplotlib", pkg assert features is None, features assert spec is None, spec + assert env is None, env def test_pep_dependency_parsing_with_spec_and_optional_dep(): matplotlib_str = "matplotlib[foo,bar]>=3.7.0,<4" - pkg, features, spec = parse_pep_dependency(matplotlib_str) + pkg, features, spec, env = parse_pep_dependency(matplotlib_str) assert pkg == "matplotlib", pkg assert features == "[foo,bar]", features assert spec == SpecifierSet(">=3.7.0,<4"), spec + assert env is None, env def test_pep_dependency_parsing_with_spec(): matplotlib_str = "matplotlib>=3.7.0,<4" - pkg, features, spec = parse_pep_dependency(matplotlib_str) + pkg, features, spec, env = parse_pep_dependency(matplotlib_str) assert pkg == "matplotlib", pkg assert features is None, features assert spec == SpecifierSet(">=3.7.0,<4"), spec + assert env is None, env def test_pep_dependency_parsing_with_url_spec(): dep_str = "matplotlib @ https://github.com/pypa/pip/archive/1.3.1.zip#sha1=da9234ee9982d4bbb3c72346a6de940a148ea686" - pkg, features, spec = parse_pep_dependency(dep_str) + pkg, features, spec, env = parse_pep_dependency(dep_str) assert pkg == "matplotlib", pkg assert features is None, features assert spec == urlparse( " https://github.com/pypa/pip/archive/1.3.1.zip#sha1=da9234ee9982d4bbb3c72346a6de940a148ea686" ), spec + assert env is None, env def test_pep_dependency_parsing_extra_restrictions(): matplotlib_str = "matplotlib>=3.7.0,<4,!=3.8.14" - pkg, features, spec = parse_pep_dependency(matplotlib_str) + pkg, features, spec, env = parse_pep_dependency(matplotlib_str) assert pkg == "matplotlib", pkg assert features is None, features assert spec == SpecifierSet("!=3.8.14,<4,>=3.7.0"), spec + assert env is None, env + + +def test_pep_dependency_parsing_with_environment_marker(): + matplotlib_str = "matplotlib>=3.7.0,<4;sys_platform != 'win32'" + pkg, features, spec, env = parse_pep_dependency(matplotlib_str) + + assert pkg == "matplotlib", pkg + assert features is None, features + assert spec == SpecifierSet(">=3.7.0,<4"), spec + assert env == ";sys_platform != 'win32'", env