Skip to content

Commit b8dc8d9

Browse files
authored
Merge pull request #60 from Point72/tkp/libskip
Add skip-if-env gating for individual Rust artifacts
2 parents 51d3012 + 68cbc94 commit b8dc8d9

3 files changed

Lines changed: 58 additions & 1 deletion

File tree

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,3 +155,7 @@ ROADMAP.md
155155
AGENTS.md
156156
.github/hooks/sdlc.json
157157
.superpowers
158+
159+
# Generated by test_project_generated_files fixture during the test suite
160+
hatch_rs/tests/test_project_generated_files/generated_files_project/generated/
161+
hatch_rs/tests/test_project_generated_files/generated_files_project/include/

hatch_rs/structs.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,13 @@ class CopiedArtifact:
114114
}
115115

116116

117+
def _env_truthy(value: Optional[str]) -> bool:
118+
"""Return True when an environment variable value reads as enabled/truthy."""
119+
if value is None:
120+
return False
121+
return value.strip().lower() not in ("", "0", "false", "no", "off")
122+
123+
117124
def _normalize_machine(machine: str) -> str:
118125
normalized = machine.lower().replace("-", "_")
119126
aliases = {
@@ -392,6 +399,11 @@ class RustArtifactConfig(BaseModel):
392399
model_config = ConfigDict(extra="ignore", populate_by_name=True)
393400

394401
name: Optional[str] = Field(default=None, description="Cargo artifact name used for exact artifact discovery and errors.")
402+
skip_if_env: Optional[str] = Field(
403+
default=None,
404+
alias="skip-if-env",
405+
description="Skip building and packaging this artifact when the named environment variable is set to a truthy value.",
406+
)
395407
manifest: Optional[Path] = Field(default=None, description="Path to Cargo.toml, relative to the hook path unless absolute.")
396408
build_type: Optional[BuildType] = Field(default=None, alias="build-type")
397409
profile: Optional[str] = Field(default=None, description="Cargo profile for this artifact.")
@@ -651,9 +663,12 @@ def shared_data(self) -> dict[str, str]:
651663
def resolved_target(self) -> Optional[ResolvedTarget]:
652664
return self._resolved_target
653665

666+
def _artifact_skipped(self, artifact: RustArtifactConfig) -> bool:
667+
return artifact.skip_if_env is not None and _env_truthy(environ.get(artifact.skip_if_env))
668+
654669
def _configured_artifacts(self) -> list[RustArtifactConfig]:
655670
if self.artifacts:
656-
return list(self.artifacts)
671+
return [artifact for artifact in self.artifacts if not self._artifact_skipped(artifact)]
657672
return [RustArtifactConfig(destination=f"{self.module}/{{python_extension_name}}")]
658673

659674
def _artifact_label(self, artifact: RustArtifactConfig) -> str:

hatch_rs/tests/test_structs.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,44 @@ def test_build_plan_generates_explicit_artifacts(tmp_path):
206206
plan.cleanup()
207207

208208

209+
def test_build_plan_skips_artifact_when_skip_if_env_is_truthy(tmp_path, monkeypatch):
210+
plan = HatchRustBuildPlan(
211+
module="project",
212+
path=tmp_path,
213+
target="x86_64-unknown-linux-gnu",
214+
target_dir="isolated",
215+
artifacts=[
216+
{
217+
"name": "project",
218+
"manifest": "Cargo.toml",
219+
"destination": "{module}/{python_extension_name}",
220+
},
221+
{
222+
"name": "project_ffi",
223+
"manifest": "rust/Cargo.toml",
224+
"destination": "{module}/lib/{shared_library}",
225+
"skip-if-env": "PROJECT_SKIP_SHARED_LIBRARY",
226+
},
227+
],
228+
)
229+
230+
monkeypatch.delenv("PROJECT_SKIP_SHARED_LIBRARY", raising=False)
231+
assert plan.generate() == [
232+
"cargo rustc --manifest-path Cargo.toml --release --target x86_64-unknown-linux-gnu -- --crate-type cdylib",
233+
"cargo rustc --manifest-path rust/Cargo.toml --release --target x86_64-unknown-linux-gnu -- --crate-type cdylib",
234+
]
235+
236+
monkeypatch.setenv("PROJECT_SKIP_SHARED_LIBRARY", "1")
237+
assert plan.generate() == [
238+
"cargo rustc --manifest-path Cargo.toml --release --target x86_64-unknown-linux-gnu -- --crate-type cdylib",
239+
]
240+
241+
monkeypatch.setenv("PROJECT_SKIP_SHARED_LIBRARY", "0")
242+
assert len(plan.generate()) == 2
243+
244+
plan.cleanup()
245+
246+
209247
def test_build_plan_copies_shared_library_to_tokenized_destination(tmp_path):
210248
plan = HatchRustBuildPlan(
211249
module="project",

0 commit comments

Comments
 (0)