Skip to content

Commit 8bad439

Browse files
committed
refactor(cargo_provider): improve readability and maintainability
1 parent f795e46 commit 8bad439

File tree

1 file changed

+89
-34
lines changed

1 file changed

+89
-34
lines changed

commitizen/providers/cargo_provider.py

Lines changed: 89 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -45,68 +45,111 @@ def set_version(self, version: str) -> None:
4545
self.set_lock_version(version)
4646

4747
def set_lock_version(self, version: str) -> None:
48-
cargo_toml = parse(self.file.read_text())
49-
cargo_lock = parse(self.lock_file.read_text())
50-
packages = cargo_lock["package"]
48+
cargo_toml_content = parse(self.file.read_text())
49+
cargo_lock_content = parse(self.lock_file.read_text())
50+
packages = cargo_lock_content["package"]
51+
5152
if TYPE_CHECKING:
5253
assert isinstance(packages, AoT)
5354

54-
root_pkg = _table_get(cargo_toml, "package")
55+
root_pkg = _table_get(cargo_toml_content, "package")
5556
if root_pkg is not None:
5657
name = root_pkg.get("name")
5758
if isinstance(name, str):
5859
_lock_set_versions(packages, {name}, version)
59-
self.lock_file.write_text(dumps(cargo_lock))
60+
self.lock_file.write_text(dumps(cargo_lock_content))
6061
return
6162

62-
ws = _table_get(cargo_toml, "workspace") or {}
63-
members = cast("list[str]", ws.get("members", []) or [])
64-
excludes = cast("list[str]", ws.get("exclude", []) or [])
65-
inheriting = _workspace_inheriting_member_names(members, excludes)
63+
ws = _table_get(cargo_toml_content, "workspace") or {}
64+
member_globs = cast("list[str]", ws.get("members", []) or [])
65+
exclude_globs = cast("list[str]", ws.get("exclude", []) or [])
66+
inheriting = _workspace_inheriting_member_names(member_globs, exclude_globs)
6667
_lock_set_versions(packages, inheriting, version)
67-
self.lock_file.write_text(dumps(cargo_lock))
68+
self.lock_file.write_text(dumps(cargo_lock_content))
6869

6970

7071
def _table_get(doc: TOMLDocument, key: str) -> DictLike | None:
71-
"""Return a dict-like table for `key` if present, else None (type-safe for Pylance)."""
72+
"""Get a TOML table by key as a dict-like object.
73+
74+
Returns:
75+
The value at `doc[key]` cast to a dict-like table (supports `.get`) if it
76+
exists and is table/container-like; otherwise returns None.
77+
78+
Rationale:
79+
tomlkit returns loosely-typed Container/Table objects; using a small
80+
helper keeps call sites readable and makes type-checkers happier.
81+
"""
7282
try:
73-
v = doc[key] # tomlkit returns Container/Table-like; typing is loose
83+
value = doc[key]
7484
except NonExistentKey:
7585
return None
76-
return cast("DictLike", v) if hasattr(v, "get") else None
86+
return cast("DictLike", value) if hasattr(value, "get") else None
7787

7888

7989
def _root_version_table(doc: TOMLDocument) -> DictLike:
80-
"""Prefer [workspace.package]; fallback to [package]."""
81-
ws = _table_get(doc, "workspace")
82-
if ws is not None:
83-
pkg = ws.get("package")
84-
if hasattr(pkg, "get"):
85-
return cast("DictLike", pkg)
86-
pkg = _table_get(doc, "package")
87-
if pkg is None:
90+
"""Return the table that owns the "root" version field.
91+
92+
This provider supports two layouts:
93+
94+
1) Workspace virtual manifests:
95+
[workspace.package]
96+
version = "x.y.z"
97+
98+
2) Regular crate(non-workspace root manifest):
99+
[package]
100+
version = "x.y.z"
101+
102+
The selected table is where `get()` reads from and `set()` writes to.
103+
"""
104+
workspace_table = _table_get(doc, "workspace")
105+
if workspace_table is not None:
106+
workspace_package_table = workspace_table.get("package")
107+
if hasattr(workspace_package_table, "get"):
108+
return cast("DictLike", workspace_package_table)
109+
110+
package_table = _table_get(doc, "package")
111+
if package_table is None:
88112
raise NonExistentKey("expected either [workspace.package] or [package]")
89-
return pkg
113+
return package_table
90114

91115

92116
def _is_workspace_inherited_version(v: Any) -> bool:
93117
return hasattr(v, "get") and cast("DictLike", v).get("workspace") is True
94118

95119

96120
def _iter_member_dirs(
97-
members: Iterable[str], excludes: Iterable[str]
121+
member_globs: Iterable[str], exclude_globs: Iterable[str]
98122
) -> Iterable[Path]:
99-
for pat in members:
100-
for p in glob.glob(pat, recursive=True):
101-
if any(fnmatch.fnmatch(p, ex) for ex in excludes):
123+
"""Yield workspace member directories matched by `member_globs`, excluding `exclude_globs`.
124+
125+
Cargo workspaces define members/exclude as glob patterns (e.g. "crates/*").
126+
This helper expands those patterns and yields the corresponding directories
127+
as `Path` objects, skipping any matches that satisfy an exclude glob.
128+
129+
Kept as a helper to make call sites read as domain logic ("iterate member dirs")
130+
rather than glob/filter plumbing.
131+
"""
132+
for member_glob in member_globs:
133+
for match in glob.glob(member_glob, recursive=True):
134+
if any(fnmatch.fnmatch(match, ex) for ex in exclude_globs):
102135
continue
103-
yield Path(p)
136+
yield Path(match)
104137

105138

106139
def _workspace_inheriting_member_names(
107140
members: Iterable[str], excludes: Iterable[str]
108141
) -> set[str]:
109-
out: set[str] = set()
142+
"""Return workspace member crate names that inherit the workspace version.
143+
144+
A member is considered "inheriting" when its Cargo.toml has:
145+
[package]
146+
version.workspace = true
147+
148+
This scans `members` globs (respecting `excludes`) and returns the set of
149+
`[package].name` values for matching crates. Missing/invalid Cargo.toml files
150+
are ignored.
151+
"""
152+
inheriting_member_names: set[str] = set()
110153
for d in _iter_member_dirs(members, excludes):
111154
cargo_file = d / "Cargo.toml"
112155
if not cargo_file.exists():
@@ -118,13 +161,25 @@ def _workspace_inheriting_member_names(
118161
if _is_workspace_inherited_version(pkgd.get("version")):
119162
name = pkgd.get("name")
120163
if isinstance(name, str):
121-
out.add(name)
122-
return out
164+
inheriting_member_names.add(name)
165+
return inheriting_member_names
166+
167+
168+
def _lock_set_versions(packages: Any, package_names: set[str], version: str) -> None:
169+
"""Update Cargo.lock package entries in-place.
123170
171+
Args:
172+
packages: `Cargo.lock` parsed TOML "package" array (AoT-like). Mutated in-place.
173+
package_names: Set of package names whose `version` field should be updated.
174+
version: New version string to write.
124175
125-
def _lock_set_versions(packages: Any, names: set[str], version: str) -> None:
126-
if not names:
176+
Notes:
177+
We use `enumerate` + index assignment because tomlkit AoT entries may be
178+
Container-like and direct mutation patterns vary; indexed assignment is
179+
reliable for updating the underlying document.
180+
"""
181+
if not package_names:
127182
return
128-
for i, p in enumerate(packages):
129-
if getattr(p, "get", None) and p.get("name") in names:
183+
for i, pkg_entry in enumerate(packages):
184+
if getattr(pkg_entry, "get", None) and pkg_entry.get("name") in package_names:
130185
packages[i]["version"] = version

0 commit comments

Comments
 (0)