From d76d2fb6ae8606ee5b0b63e01aa75439695edb20 Mon Sep 17 00:00:00 2001 From: Michael Hall Date: Tue, 24 Sep 2024 14:54:43 +1000 Subject: [PATCH 1/8] refactor: remove unused LibrariesIO source --- conda_forge_tick/update_sources.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/conda_forge_tick/update_sources.py b/conda_forge_tick/update_sources.py index 32d621911..4d0403cbf 100644 --- a/conda_forge_tick/update_sources.py +++ b/conda_forge_tick/update_sources.py @@ -616,20 +616,6 @@ def get_version(self, url: str) -> Optional[str]: return latest -class LibrariesIO(VersionFromFeed): - name = "LibrariesIO" - - def get_url(self, meta_yaml) -> Optional[str]: - urls = meta_yaml["url"] - if not isinstance(meta_yaml["url"], list): - urls = [urls] - for url in urls: - if self.url_contains not in url: - continue - pkg = self.package_name(url) - return f"https://libraries.io/{self.name}/{pkg}/versions.atom" - - class NVIDIA(AbstractSource): """Like BaseRawURL but it embeds logic based on NVIDIA's packaging schema.""" From 57e41f354f88fa0e69d4472ab584d86d3639ee0d Mon Sep 17 00:00:00 2001 From: Michael Hall Date: Tue, 24 Sep 2024 16:19:56 +1000 Subject: [PATCH 2/8] feat: add crates.io source --- conda_forge_tick/update_sources.py | 46 ++++++++++ conda_forge_tick/update_upstream_versions.py | 2 + tests/test_update_sources.py | 90 ++++++++++++++++++++ 3 files changed, 138 insertions(+) create mode 100644 tests/test_update_sources.py diff --git a/conda_forge_tick/update_sources.py b/conda_forge_tick/update_sources.py index 4d0403cbf..61dc8c677 100644 --- a/conda_forge_tick/update_sources.py +++ b/conda_forge_tick/update_sources.py @@ -2,11 +2,13 @@ import collections.abc import copy import functools +import json import logging import re import subprocess import typing import urllib.parse +from pathlib import Path from typing import Iterator, List, Optional import feedparser @@ -694,3 +696,47 @@ def get_url(self, meta_yaml) -> Optional[str]: def get_version(self, url: str) -> Optional[str]: return url # = next version, same as in BaseRawURL + + +class CratesIO(AbstractSource): + name = "CratesIO" + + def get_url(self, meta_yaml) -> Optional[str]: + if "crates.io" not in meta_yaml["url"]: + return None + + pkg = Path(meta_yaml["url"]).parts[5] + tier = self._tier_directory(pkg) + + return f"https://index.crates.io/{tier}" + + def get_version(self, url: str) -> Optional[str]: + r = requests.get(url) + + if not r.ok: + return None + + # the response body is a newline-delimited JSON stream, with the latest version + # being the last line + latest = json.loads(r.text.splitlines()[-1]) + + return latest.get("vers") + + @staticmethod + def _tier_directory(package: str) -> str: + """Depending on the length of the package name, the tier directory structure + will differ. + Documented here: https://doc.rust-lang.org/cargo/reference/registry-index.html#index-files + """ + if not package: + raise ValueError("Package name cannot be empty") + + name_len = len(package) + + if name_len <= 2: + return f"{name_len}/{package}" + elif name_len == 3: + return f"{name_len}/{package[0]}/{package}" + else: + return f"{package[0:2]}/{package[2:4]}/{package}" + diff --git a/conda_forge_tick/update_upstream_versions.py b/conda_forge_tick/update_upstream_versions.py index 931ab4aa7..51c787c5f 100644 --- a/conda_forge_tick/update_upstream_versions.py +++ b/conda_forge_tick/update_upstream_versions.py @@ -32,6 +32,7 @@ from conda_forge_tick.lazy_json_backends import LazyJson, dumps from conda_forge_tick.update_sources import ( CRAN, + CratesIO, NPM, NVIDIA, AbstractSource, @@ -418,6 +419,7 @@ def all_version_sources(): return ( PyPI(), CRAN(), + CratesIO(), NPM(), ROSDistro(), RawURL(), diff --git a/tests/test_update_sources.py b/tests/test_update_sources.py new file mode 100644 index 000000000..98c2f592c --- /dev/null +++ b/tests/test_update_sources.py @@ -0,0 +1,90 @@ +from conda_forge_tick.update_sources import CratesIO +from unittest.mock import patch, Mock + +import pytest + + +class TestCratesIOTierDirectory: + def test_four_or_more_characters(self): + pkg = "rasusa" + + actual = CratesIO._tier_directory(pkg) + expected = "ra/su/rasusa" + + assert actual == expected + + def test_four_characters(self): + pkg = "psdm" + + actual = CratesIO._tier_directory(pkg) + expected = "ps/dm/psdm" + + assert actual == expected + + def test_three_characters(self): + pkg = "syn" + + actual = CratesIO._tier_directory(pkg) + expected = "3/s/syn" + + assert actual == expected + + def test_two_characters(self): + pkg = "it" + + actual = CratesIO._tier_directory(pkg) + expected = "2/it" + + assert actual == expected + + def test_one_character(self): + pkg = "a" + + actual = CratesIO._tier_directory(pkg) + expected = "1/a" + + assert actual == expected + + def test_empty_string(self): + pkg = "" + + with pytest.raises(ValueError): + CratesIO._tier_directory(pkg) + + +class TestCratesIOGetVersion: + def test_valid_package(self): + # as far as I can tell, this package has not had a new version in the last 9 + # years, so it should be safe to use for testing as we don't expect the version + # to change + pkg = "gopher" + tier = CratesIO._tier_directory(pkg) + url = f"https://index.crates.io/{tier}" + + actual = CratesIO().get_version(url) + expected = "0.0.3" + + assert actual == expected + + def test_invalid_package(self): + pkg = "shdfbshbvjhbvhsbhsb" + tier = CratesIO._tier_directory(pkg) + url = f"https://index.crates.io/{tier}" + + result = CratesIO().get_version(url) + assert result is None + + @patch('conda_forge_tick.update_sources.requests.get') + def test_empty_package(self, mock_get): + pkg = "syn" + tier = CratesIO._tier_directory(pkg) + url = f"https://index.crates.io/{tier}" + + # Mock response + mock_response = Mock() + mock_response.ok = True + mock_response.text = '{"name": "syn"}' + mock_get.return_value = mock_response + + result = CratesIO().get_version(url) + assert result is None From 44821a03debf5ce825b93d33ae0f1f17a41123a6 Mon Sep 17 00:00:00 2001 From: Michael Hall Date: Tue, 24 Sep 2024 16:35:10 +1000 Subject: [PATCH 3/8] chore: fmt --- conda_forge_tick/update_sources.py | 1 - tests/test_update_sources.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/conda_forge_tick/update_sources.py b/conda_forge_tick/update_sources.py index 61dc8c677..25e7b6fa0 100644 --- a/conda_forge_tick/update_sources.py +++ b/conda_forge_tick/update_sources.py @@ -739,4 +739,3 @@ def _tier_directory(package: str) -> str: return f"{name_len}/{package[0]}/{package}" else: return f"{package[0:2]}/{package[2:4]}/{package}" - diff --git a/tests/test_update_sources.py b/tests/test_update_sources.py index 98c2f592c..3e1a09221 100644 --- a/tests/test_update_sources.py +++ b/tests/test_update_sources.py @@ -74,7 +74,7 @@ def test_invalid_package(self): result = CratesIO().get_version(url) assert result is None - @patch('conda_forge_tick.update_sources.requests.get') + @patch("conda_forge_tick.update_sources.requests.get") def test_empty_package(self, mock_get): pkg = "syn" tier = CratesIO._tier_directory(pkg) From aeda613c8ec8761a851f026a0fb96d548e616f64 Mon Sep 17 00:00:00 2001 From: Michael Hall Date: Tue, 24 Sep 2024 16:41:29 +1000 Subject: [PATCH 4/8] chore: lint --- conda_forge_tick/update_upstream_versions.py | 2 +- tests/test_update_sources.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/conda_forge_tick/update_upstream_versions.py b/conda_forge_tick/update_upstream_versions.py index 51c787c5f..0e2052622 100644 --- a/conda_forge_tick/update_upstream_versions.py +++ b/conda_forge_tick/update_upstream_versions.py @@ -32,10 +32,10 @@ from conda_forge_tick.lazy_json_backends import LazyJson, dumps from conda_forge_tick.update_sources import ( CRAN, - CratesIO, NPM, NVIDIA, AbstractSource, + CratesIO, Github, GithubReleases, IncrementAlphaRawURL, diff --git a/tests/test_update_sources.py b/tests/test_update_sources.py index 3e1a09221..76bf86a99 100644 --- a/tests/test_update_sources.py +++ b/tests/test_update_sources.py @@ -1,8 +1,9 @@ -from conda_forge_tick.update_sources import CratesIO -from unittest.mock import patch, Mock +from unittest.mock import Mock, patch import pytest +from conda_forge_tick.update_sources import CratesIO + class TestCratesIOTierDirectory: def test_four_or_more_characters(self): From 1ef8b85e33dd8e27a7c28db36f867be17fe70755 Mon Sep 17 00:00:00 2001 From: Michael Hall Date: Thu, 26 Sep 2024 07:56:29 +1000 Subject: [PATCH 5/8] revert: "refactor: remove unused LibrariesIO source" This reverts commit d76d2fb6ae8606ee5b0b63e01aa75439695edb20. --- conda_forge_tick/update_sources.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/conda_forge_tick/update_sources.py b/conda_forge_tick/update_sources.py index 25e7b6fa0..4bad98673 100644 --- a/conda_forge_tick/update_sources.py +++ b/conda_forge_tick/update_sources.py @@ -618,6 +618,20 @@ def get_version(self, url: str) -> Optional[str]: return latest +class LibrariesIO(VersionFromFeed): + name = "LibrariesIO" + + def get_url(self, meta_yaml) -> Optional[str]: + urls = meta_yaml["url"] + if not isinstance(meta_yaml["url"], list): + urls = [urls] + for url in urls: + if self.url_contains not in url: + continue + pkg = self.package_name(url) + return f"https://libraries.io/{self.name}/{pkg}/versions.atom" + + class NVIDIA(AbstractSource): """Like BaseRawURL but it embeds logic based on NVIDIA's packaging schema.""" From 78082eea9b7beab73a850a22c56ee53b06eb27fe Mon Sep 17 00:00:00 2001 From: Michael Hall Date: Thu, 26 Sep 2024 08:52:08 +1000 Subject: [PATCH 6/8] test: add CratesIO to test default sources --- tests/test_upstream_versions.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_upstream_versions.py b/tests/test_upstream_versions.py index f15e0ca71..6115f520a 100644 --- a/tests/test_upstream_versions.py +++ b/tests/test_upstream_versions.py @@ -1254,6 +1254,7 @@ def test_update_upstream_versions_no_packages_to_update( default_sources = ( "PyPI", "CRAN", + "CratesIO", "NPM", "ROSDistro", "RawURL", From f0d24b431c1ee1a829be6163dd749e1b373ea5a3 Mon Sep 17 00:00:00 2001 From: Michael Hall Date: Thu, 26 Sep 2024 10:03:37 +1000 Subject: [PATCH 7/8] test: add full test for crates.io source --- tests/test_upstream_versions.py | 35 +++++++++++++++++++++++++ tests/test_yaml/version_wbg-rand.yaml | 37 +++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 tests/test_yaml/version_wbg-rand.yaml diff --git a/tests/test_upstream_versions.py b/tests/test_upstream_versions.py index 6115f520a..1bc587db6 100644 --- a/tests/test_upstream_versions.py +++ b/tests/test_upstream_versions.py @@ -17,6 +17,7 @@ NPM, NVIDIA, AbstractSource, + CratesIO, Github, GithubReleases, PyPI, @@ -1719,3 +1720,37 @@ def test_github_releases(tmpdir, url, feedstock_version): ghr = GithubReleases() url = ghr.get_url(meta_yaml) assert VersionOrder(ghr.get_version(url)) > VersionOrder(feedstock_version) + + +def test_latest_version_cratesio(tmpdir): + name = "wbg-rand" + recipe_path = os.path.join(YAML_PATH, "version_wbg-rand.yaml") + curr_ver = "0.4.0" + ver = "0.4.1" + source = CratesIO() + + with open(recipe_path) as fd: + inp = fd.read() + + pmy = LazyJson(os.path.join(str(tmpdir), "cf-scripts-test.json")) + with pmy as _pmy: + yml = parse_meta_yaml(inp) + _pmy.update(yml["source"]) + _pmy.update( + { + "feedstock_name": name, + "version": curr_ver, + "raw_meta_yaml": inp, + "meta_yaml": yml, + }, + ) + + attempt = get_latest_version(name, pmy, [source], use_container=False) + if ver is None: + assert attempt["new_version"] is not False + assert attempt["new_version"] != curr_ver + assert VersionOrder(attempt["new_version"]) > VersionOrder(curr_ver) + elif ver is False: + assert attempt["new_version"] is ver + else: + assert ver == attempt["new_version"] diff --git a/tests/test_yaml/version_wbg-rand.yaml b/tests/test_yaml/version_wbg-rand.yaml new file mode 100644 index 000000000..064dbb1ff --- /dev/null +++ b/tests/test_yaml/version_wbg-rand.yaml @@ -0,0 +1,37 @@ +package: + name: wbg-rand + version: "0.4.0" + +source: + url: https://crates.io/api/v1/crates/wbg-rand/0.4.0/download + fn: "wbg-rand-0.4.0.tar.gz" + sha256: 5505e10cb191f56fed835c35baf4ac97b5466148a13fbcaeb1173198b1a52b4c + +build: + number: 0 + skip: true # [win] + +requirements: + build: + - {{ compiler('rust') }} + - {{ compiler('c') }} + - {{ stdlib("c") }} + - cargo-bundle-licenses + +test: + commands: + - echo "This is a placeholder for the test section" + +about: + home: https://github.com/alexcrichton/wbg-rand + summary: 'Random numbers for wasm32-unknown-unknown in Rust' + description: | + Implementation of rand for wasm32-unknown-unknown in Rust using #[wasm_bindgen]. + license: MIT AND Apache-2.0 + license_file: + - LICENSE-MIT + - LICENSE-APACHE + +extra: + recipe-maintainers: + - mbhall88 \ No newline at end of file From 7ca7367ccd7b158577c6264d6c2b3f99d11bc02a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 26 Sep 2024 00:07:27 +0000 Subject: [PATCH 8/8] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/test_yaml/version_wbg-rand.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_yaml/version_wbg-rand.yaml b/tests/test_yaml/version_wbg-rand.yaml index 064dbb1ff..9814429be 100644 --- a/tests/test_yaml/version_wbg-rand.yaml +++ b/tests/test_yaml/version_wbg-rand.yaml @@ -34,4 +34,4 @@ about: extra: recipe-maintainers: - - mbhall88 \ No newline at end of file + - mbhall88