badgerp_get_crates_version 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,15 @@
1
+ /target
2
+ /dist
3
+ /.venv
4
+ __pycache__/
5
+ *.pyc
6
+ plugins/**/.packages/
7
+ test.svg
8
+ badges/
9
+ /plugins/repology-badge/.site-packages
10
+ plugins/**/dist/
11
+ plugins/**/*.egg-info/
12
+ .pytest_cache/
13
+ mutants.out*
14
+ /mutants.out*
15
+ /xz2-0.1.7
@@ -0,0 +1,21 @@
1
+ Metadata-Version: 2.5
2
+ Name: badgerp_get_crates_version
3
+ Version: 0.1.0
4
+ Summary: Show the latest published version of a crate from crates.io
5
+ Author-email: 𝑷𝒉𝒊𝒍𝒐𝒄𝒂𝒍𝒚𝒔𝒕 <regime_skylark.0y@icloud.com>
6
+ License-Expression: MIT
7
+ Requires-Python: >=3.11
8
+ Description-Content-Type: text/markdown
9
+
10
+ # get-crates-version
11
+
12
+ A [badger](https://github.com/) plugin that looks up the latest published
13
+ version of a crate from crates.io.
14
+
15
+ By default it resolves the crate name from a `Cargo.toml` in the current
16
+ directory (with basic support for workspaces), then queries the crates.io
17
+ API and returns a `crates.io: <version>` badge entry. You can also pass an
18
+ explicit `crate` name to skip the `Cargo.toml` lookup.
19
+
20
+ This package is not meant to be used as a standalone library — badger loads
21
+ `plugin.py`'s `run()` function directly as its entrypoint.
@@ -0,0 +1,12 @@
1
+ # get-crates-version
2
+
3
+ A [badger](https://github.com/) plugin that looks up the latest published
4
+ version of a crate from crates.io.
5
+
6
+ By default it resolves the crate name from a `Cargo.toml` in the current
7
+ directory (with basic support for workspaces), then queries the crates.io
8
+ API and returns a `crates.io: <version>` badge entry. You can also pass an
9
+ explicit `crate` name to skip the `Cargo.toml` lookup.
10
+
11
+ This package is not meant to be used as a standalone library — badger loads
12
+ `plugin.py`'s `run()` function directly as its entrypoint.
@@ -0,0 +1,62 @@
1
+ # This badge does the really simple thing of getting the CURRENTLY PUBLISHED crates version
2
+ # This is subtly different from the version of the crate in question in your repo because it's not FOR SURE
3
+ # on crates.io yet (just is the expectation).
4
+
5
+ import json
6
+ import tomllib
7
+ import urllib.request
8
+ from badger import entry
9
+
10
+
11
+ def _crate_name_from_toml(cargo_toml: str) -> str:
12
+ """Resolve the crate name from a Cargo.toml, with workspace support.
13
+
14
+ Handles three shapes:
15
+ - ``[package]`` only — a normal single-crate project.
16
+ - ``[package]`` + ``[workspace]`` — a workspace root that is also a
17
+ publishable crate (e.g. ``badger`` itself).
18
+ - ``[workspace]`` only (virtual workspace) — no ``[package]`` at the root.
19
+ Falls back to ``workspace.package.name`` if the workspace defines
20
+ inherited package metadata; otherwise raises with a helpful message.
21
+ """
22
+ with open(cargo_toml, "rb") as f:
23
+ data = tomllib.load(f)
24
+
25
+ if "package" in data:
26
+ return data["package"]["name"]
27
+
28
+ # Virtual workspace: try workspace-level inherited package metadata.
29
+ workspace = data.get("workspace", {})
30
+ workspace_pkg_name = workspace.get("package", {}).get("name")
31
+ if workspace_pkg_name:
32
+ return workspace_pkg_name
33
+
34
+ members = workspace.get("members", [])
35
+ raise ValueError(
36
+ f"{cargo_toml!r} is a virtual workspace root (no [package] section). "
37
+ f"Workspace members: {members}. "
38
+ "Pass crate='<name>' explicitly to get-crates-version, or point "
39
+ "cargo_toml at a specific member's Cargo.toml."
40
+ )
41
+
42
+
43
+ def run(crate: str = "", cargo_toml: str = "Cargo.toml") -> entry:
44
+ """Fetch the newest crates.io release for a crate.
45
+
46
+ When no crate name is supplied, the package name is resolved from the
47
+ given Cargo manifest, including workspace metadata where available.
48
+
49
+ Args:
50
+ crate: crates.io package name; empty uses the manifest's package name.
51
+ cargo_toml: manifest used when `crate` is empty.
52
+ """
53
+ if not crate:
54
+ crate = _crate_name_from_toml(cargo_toml)
55
+
56
+ req = urllib.request.Request(
57
+ f"https://crates.io/api/v1/crates/{crate}",
58
+ headers={"User-Agent": "badger-badge-generator/0.1"},
59
+ )
60
+ with urllib.request.urlopen(req, timeout=10) as resp:
61
+ version = json.loads(resp.read().decode())["crate"]["newest_version"]
62
+ return entry(label="crates.io", status=version)
@@ -0,0 +1,16 @@
1
+ [project]
2
+ name = "badgerp_get_crates_version"
3
+ version = "0.1.0"
4
+ description = "Show the latest published version of a crate from crates.io"
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ authors = [{ name = "𝑷𝒉𝒊𝒍𝒐𝒄𝒂𝒍𝒚𝒔𝒕", email = "regime_skylark.0y@icloud.com" }]
8
+ dependencies = []
9
+ requires-python = ">=3.11"
10
+
11
+ [build-system]
12
+ requires = ["hatchling"]
13
+ build-backend = "hatchling.build"
14
+
15
+ [tool.hatch.build.targets.wheel]
16
+ include = ["plugin.py"]
@@ -0,0 +1,117 @@
1
+ import textwrap
2
+
3
+ import pytest
4
+
5
+
6
+ @pytest.mark.network
7
+ def test_label(plugin):
8
+ assert plugin.run(crate="serde").label == "crates.io"
9
+
10
+
11
+ @pytest.mark.network
12
+ def test_version_is_semver(plugin):
13
+ parts = plugin.run(crate="serde").status.split(".")
14
+ assert len(parts) >= 2
15
+ assert parts[0].isdigit()
16
+
17
+
18
+ @pytest.mark.network
19
+ def test_unknown_crate_raises(plugin):
20
+ with pytest.raises(Exception):
21
+ plugin.run(crate="this-crate-does-not-exist-xyzzy-99999")
22
+
23
+
24
+ @pytest.mark.network
25
+ def test_infers_crate_from_cargo_toml(plugin, monkeypatch, project_root):
26
+ monkeypatch.chdir(project_root)
27
+ result = plugin.run()
28
+ assert result.label == "crates.io"
29
+ assert result.status
30
+
31
+
32
+ @pytest.fixture
33
+ def tmp_toml(tmp_path):
34
+ """Write a Cargo.toml in a temp dir and return its absolute path."""
35
+ def _write(content: str) -> str:
36
+ path = tmp_path / "Cargo.toml"
37
+ path.write_text(textwrap.dedent(content))
38
+ return str(path)
39
+ return _write
40
+
41
+
42
+ def test_crate_name_from_package_only_toml(plugin, tmp_toml):
43
+ path = tmp_toml("""\
44
+ [package]
45
+ name = "my-crate"
46
+ version = "0.1.0"
47
+ edition = "2021"
48
+ """)
49
+ assert plugin._crate_name_from_toml(path) == "my-crate"
50
+
51
+
52
+ def test_crate_name_from_package_plus_workspace_toml(plugin, tmp_toml):
53
+ """A crate that is also the workspace root (e.g. badger itself)."""
54
+ path = tmp_toml("""\
55
+ [package]
56
+ name = "root-crate"
57
+ version = "0.1.0"
58
+ edition = "2021"
59
+
60
+ [workspace]
61
+ members = ["sub-a", "sub-b"]
62
+ """)
63
+ assert plugin._crate_name_from_toml(path) == "root-crate"
64
+
65
+
66
+ def test_crate_name_from_virtual_workspace_with_inherited_package(plugin, tmp_toml):
67
+ """Virtual workspace that declares workspace.package.name."""
68
+ path = tmp_toml("""\
69
+ [workspace]
70
+ members = ["crate-a", "crate-b"]
71
+
72
+ [workspace.package]
73
+ name = "my-workspace"
74
+ version = "1.0.0"
75
+ edition = "2021"
76
+ """)
77
+ assert plugin._crate_name_from_toml(path) == "my-workspace"
78
+
79
+
80
+ def test_crate_name_from_virtual_workspace_without_package_raises(plugin, tmp_toml):
81
+ path = tmp_toml("""\
82
+ [workspace]
83
+ members = ["crate-a", "crate-b"]
84
+ """)
85
+ with pytest.raises(ValueError, match="virtual workspace root"):
86
+ plugin._crate_name_from_toml(path)
87
+
88
+
89
+ def test_virtual_workspace_error_mentions_members(plugin, tmp_toml):
90
+ path = tmp_toml("""\
91
+ [workspace]
92
+ members = ["alpha", "beta"]
93
+ """)
94
+ with pytest.raises(ValueError, match="alpha"):
95
+ plugin._crate_name_from_toml(path)
96
+
97
+
98
+ def test_explicit_crate_kwarg_skips_toml_read(plugin, tmp_toml, monkeypatch):
99
+ """When crate= is provided the Cargo.toml is never opened."""
100
+ path = tmp_toml("""\
101
+ [workspace]
102
+ members = ["a"]
103
+ """)
104
+
105
+ original_open = open
106
+
107
+ def _guarded(name, *args, **kwargs):
108
+ if str(name) == path:
109
+ raise AssertionError(f"Cargo.toml should not be read when crate= is explicit: {name}")
110
+ return original_open(name, *args, **kwargs)
111
+
112
+ monkeypatch.setattr("builtins.open", _guarded)
113
+
114
+ # We expect a network/URL error, NOT a ValueError about virtual workspaces.
115
+ with pytest.raises(Exception) as exc_info:
116
+ plugin.run(crate="some-crate-name", cargo_toml=path)
117
+ assert "virtual workspace root" not in str(exc_info.value)
@@ -0,0 +1,8 @@
1
+ version = 1
2
+ revision = 3
3
+ requires-python = ">=3.11"
4
+
5
+ [[package]]
6
+ name = "badgerp-get-crates-version"
7
+ version = "0.1.0"
8
+ source = { editable = "." }