From 98598794351aef9c9c19002b2180ce77378ae1df Mon Sep 17 00:00:00 2001 From: Antoine Lambert Date: Tue, 4 Aug 2026 14:42:35 +0200 Subject: [PATCH 1/2] Add new option to force rust debug profile with editable install By default rust release profile is used to compile the artifacts and it can be changed using the profile option in tool.hatch.build.hooks.hatch-rs or tool.hatch.build.hooks.hatch-rs.artifacts sections. When installing the Python project in development mode (aka editable installs) using the command "pip install --editable ", it can be preferred to use the rust debug profile so the compilation time is faster. Using rust debug profile in development mode can now be enforced by setting the debug-for-dev-mode option to true either in tool.hatch.build.hooks.hatch-rs or tool.hatch.build.hooks.hatch-rs.artifacts sections. --- README.md | 14 ++ hatch_rs/plugin.py | 2 +- hatch_rs/structs.py | 16 +- .../Cargo.lock | 180 ++++++++++++++++++ .../Cargo.toml | 17 ++ .../project/__init__.py | 0 .../pyproject.toml | 37 ++++ .../src/lib.rs | 13 ++ hatch_rs/tests/test_projects.py | 35 ++++ pyproject.toml | 2 + 10 files changed, 314 insertions(+), 2 deletions(-) create mode 100644 hatch_rs/tests/test_project_debug_for_dev_mode/Cargo.lock create mode 100644 hatch_rs/tests/test_project_debug_for_dev_mode/Cargo.toml create mode 100644 hatch_rs/tests/test_project_debug_for_dev_mode/project/__init__.py create mode 100644 hatch_rs/tests/test_project_debug_for_dev_mode/pyproject.toml create mode 100644 hatch_rs/tests/test_project_debug_for_dev_mode/src/lib.rs diff --git a/README.md b/README.md index 4ed41e3..1bc3d77 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,20 @@ destination = "project/lib/{shared_library}" Destination templates support `{module}`, `{target}`, `{profile}`, `{name}`, `{shared_library}`, `{import_library}`, and `{python_extension_name}`. +### Forcing rust debug profile in development mode + +By default rust release profile is used to compile the artifacts and it can +be changed using the `profile` option in `tool.hatch.build.hooks.hatch-rs` +or `tool.hatch.build.hooks.hatch-rs.artifacts` sections. + +When installing the Python project in development mode (aka editable installs) +using the command `pip install --editable `, it can be preferred +to use the rust debug profile so the compilation time is faster. + +Using rust debug profile in development mode can be enforced by setting the +`debug-for-dev-mode` option to `true` either in `tool.hatch.build.hooks.hatch-rs` +or `tool.hatch.build.hooks.hatch-rs.artifacts` sections. + ### Generated files and headers Artifacts with `command` run an argv-list command and then validate explicit diff --git a/hatch_rs/plugin.py b/hatch_rs/plugin.py index 052803a..0cd2609 100644 --- a/hatch_rs/plugin.py +++ b/hatch_rs/plugin.py @@ -50,7 +50,7 @@ def initialize(self, version: str, build_data: dict[str, Any]) -> None: build_plan = build_plan_class(**config.model_dump()) # Generate commands - build_plan.generate() + build_plan.generate(editable_install=(version == "editable")) # Log commands if in verbose mode if config.verbose: diff --git a/hatch_rs/structs.py b/hatch_rs/structs.py index 86ae165..49b1dc1 100644 --- a/hatch_rs/structs.py +++ b/hatch_rs/structs.py @@ -416,6 +416,11 @@ class RustArtifactConfig(BaseModel): manifest: Path | None = Field(default=None, description="Path to Cargo.toml, relative to the hook path unless absolute.") build_type: BuildType | None = Field(default=None, alias="build-type") profile: str | None = Field(default=None, description="Cargo profile for this artifact.") + debug_for_dev_mode: bool = Field( + default=False, + alias="debug-for-dev-mode", + description="Force rust debug profile when installing the Python project in development mode (aka editable installs)", + ) target: str | None = Field(default=None, description="Rust target triple for this artifact.") package: str | None = Field(default=None, description="Cargo package selector.") cargo_target_kind: CargoTargetKind | None = Field(default=None, alias="cargo-target-kind", description="Cargo target selector kind.") @@ -576,6 +581,11 @@ class HatchRustBuildConfig(BaseModel): manifest: Path | None = Field(default=None, description="Path to Cargo.toml, relative to path unless absolute.") build_type: BuildType = Field(default="release", alias="build-type") profile: str | None = Field(default=None, description="Cargo profile to build. Overrides build_type when set.") + debug_for_dev_mode: bool = Field( + default=False, + alias="debug-for-dev-mode", + description="Force rust debug profile when installing the Python project in development mode (aka editable installs)", + ) features: list[str] = Field(default_factory=list, description="Cargo features to enable.") all_features: bool = Field(default=False, alias="all-features", description="Enable all Cargo features.") no_default_features: bool = Field(default=False, alias="no-default-features", description="Disable Cargo default features.") @@ -657,6 +667,7 @@ class HatchRustBuildPlan(HatchRustBuildConfig): _target_dir: Path | None = PrivateAttr(default=None) _set_target_dir_env: bool = PrivateAttr(default=False) _temporary_target_dir: TemporaryDirectory[str] | None = PrivateAttr(default=None) + _editable_install: bool = PrivateAttr(default=False) @property def libraries(self) -> list[str]: @@ -722,6 +733,8 @@ def _artifact_manifest(self, artifact: RustArtifactConfig) -> Path | None: return artifact.manifest if artifact.manifest is not None else self.manifest def _artifact_profile(self, artifact: RustArtifactConfig) -> str: + if self._editable_install and (artifact.debug_for_dev_mode or self.debug_for_dev_mode): + return "debug" build_type = artifact.build_type or self.build_type return artifact.profile or self.profile or build_type @@ -897,7 +910,7 @@ def _build_command_artifact_plan(self, artifact: RustArtifactConfig, *, global_t set_target_dir_env=set_target_dir_env, ) - def generate(self): + def generate(self, editable_install=False): if self._temporary_target_dir is not None: self._temporary_target_dir.cleanup() self._temporary_target_dir = None @@ -910,6 +923,7 @@ def generate(self): self._shared_scripts = {} self._artifact_manifest_records = [] self._libraries = [] + self._editable_install = editable_install global_target = self.target for artifact in self._configured_artifacts(): diff --git a/hatch_rs/tests/test_project_debug_for_dev_mode/Cargo.lock b/hatch_rs/tests/test_project_debug_for_dev_mode/Cargo.lock new file mode 100644 index 0000000..175c2c2 --- /dev/null +++ b/hatch_rs/tests/test_project_debug_for_dev_mode/Cargo.lock @@ -0,0 +1,180 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "indoc" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" + +[[package]] +name = "inventory" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab08d7cd2c5897f2c949e5383ea7c7db03fb19130ffcfbf7eda795137ae3cb83" +dependencies = [ + "rustversion", +] + +[[package]] +name = "libc" +version = "0.2.174" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "project_py" +version = "0.1.0" +dependencies = [ + "pyo3", +] + +[[package]] +name = "pyo3" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8970a78afe0628a3e3430376fc5fd76b6b45c4d43360ffd6cdd40bdde72b682a" +dependencies = [ + "indoc", + "inventory", + "libc", + "memoffset", + "once_cell", + "portable-atomic", + "pyo3-build-config", + "pyo3-ffi", + "pyo3-macros", + "unindent", +] + +[[package]] +name = "pyo3-build-config" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "458eb0c55e7ece017adeba38f2248ff3ac615e53660d7c71a238d7d2a01c7598" +dependencies = [ + "once_cell", + "target-lexicon", +] + +[[package]] +name = "pyo3-ffi" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7114fe5457c61b276ab77c5055f206295b812608083644a5c5b2640c3102565c" +dependencies = [ + "libc", + "pyo3-build-config", +] + +[[package]] +name = "pyo3-macros" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8725c0a622b374d6cb051d11a0983786448f7785336139c3c94f5aa6bef7e50" +dependencies = [ + "proc-macro2", + "pyo3-macros-backend", + "quote", + "syn", +] + +[[package]] +name = "pyo3-macros-backend" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4109984c22491085343c05b0dbc54ddc405c3cf7b4374fc533f5c3313a572ccc" +dependencies = [ + "heck", + "proc-macro2", + "pyo3-build-config", + "quote", + "syn", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustversion" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" + +[[package]] +name = "syn" +version = "2.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "target-lexicon" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a" + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "unindent" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" diff --git a/hatch_rs/tests/test_project_debug_for_dev_mode/Cargo.toml b/hatch_rs/tests/test_project_debug_for_dev_mode/Cargo.toml new file mode 100644 index 0000000..8fb6b75 --- /dev/null +++ b/hatch_rs/tests/test_project_debug_for_dev_mode/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "project_py" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +name = "extension" +path = "src/lib.rs" +crate-type = ["cdylib"] + +[dependencies] +pyo3 = { version = "0.25", features = ["abi3-py39", "extension-module", "multiple-pymethods"] } + +[profile.release] +panic = 'abort' +lto = true diff --git a/hatch_rs/tests/test_project_debug_for_dev_mode/project/__init__.py b/hatch_rs/tests/test_project_debug_for_dev_mode/project/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/hatch_rs/tests/test_project_debug_for_dev_mode/pyproject.toml b/hatch_rs/tests/test_project_debug_for_dev_mode/pyproject.toml new file mode 100644 index 0000000..471aa94 --- /dev/null +++ b/hatch_rs/tests/test_project_debug_for_dev_mode/pyproject.toml @@ -0,0 +1,37 @@ +[build-system] +requires = ["hatchling>=1.20"] +build-backend = "hatchling.build" + +[project] +name = "hatch-cpp-test-project-debug-for-dev-mode" +description = "Basic test project for hatch-rs" +version = "0.1.0" +requires-python = ">=3.9" + +[tool.hatch.build] +artifacts = [ + "project/*.dll", + "project/*.dylib", + "project/*.so", +] + +[tool.hatch.build.sources] +src = "/" + +[tool.hatch.build.targets.sdist] +packages = ["project"] + +[tool.hatch.build.targets.wheel] +packages = ["project"] + +[tool.hatch.build.hooks.hatch-rs] +verbose = true +abi3 = true +module = "project" +target-dir = "target" + +[[tool.hatch.build.hooks.hatch-rs.artifacts]] +name = "extension" +manifest = "Cargo.toml" +destination = "project/{python_extension_name}" +debug-for-dev-mode = true diff --git a/hatch_rs/tests/test_project_debug_for_dev_mode/src/lib.rs b/hatch_rs/tests/test_project_debug_for_dev_mode/src/lib.rs new file mode 100644 index 0000000..66338f0 --- /dev/null +++ b/hatch_rs/tests/test_project_debug_for_dev_mode/src/lib.rs @@ -0,0 +1,13 @@ +use pyo3::prelude::*; + +#[pyfunction] +pub fn hello() -> &'static str { + "A string" +} + +#[pymodule] +fn extension(_py: Python, m: &Bound) -> PyResult<()> { + // Example + m.add_function(pyo3::wrap_pyfunction!(hello, m)?)?; + Ok(()) +} diff --git a/hatch_rs/tests/test_projects.py b/hatch_rs/tests/test_projects.py index 44ace4a..0401e78 100644 --- a/hatch_rs/tests/test_projects.py +++ b/hatch_rs/tests/test_projects.py @@ -306,3 +306,38 @@ def test_c_abi_symbol_validation_failure(self): assert completed.returncode != 0 assert "validation_failure_missing_symbol" in completed.stdout + + def test_debug_for_dev_mode(self): + project_folder = "test_project_debug_for_dev_mode" + # cleanup + rmtree(f"hatch_rs/tests/{project_folder}/target", ignore_errors=True) + rmtree(f"hatch_rs/tests/{project_folder}/project/extension.abi3.so", ignore_errors=True) + rmtree(f"hatch_rs/tests/{project_folder}/project/extension.abi3.pyd", ignore_errors=True) + modules.pop("project", None) + modules.pop("project.extension", None) + + # install project in development mode (editable install) + check_call( + [ + "pip", + "install", + "--verbose", + # ensure hatch-rs from this repository is used and not fetched from PyPI + "--no-build-isolation", + "--editable", + ".", + ], + cwd=f"hatch_rs/tests/{project_folder}", + env=_subprocess_env(), + ) + + # check debug-for-dev-mode option was honored + assert Path(f"hatch_rs/tests/{project_folder}/target/debug").exists() + assert not Path(f"hatch_rs/tests/{project_folder}/target/release").exists() + + # import + here = Path(__file__).parent / project_folder + path.insert(0, str(here)) + import project.extension + + assert project.extension.hello() == "A string" diff --git a/pyproject.toml b/pyproject.toml index fffb15b..c1745f6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,9 +45,11 @@ develop = [ "bump-my-version", "check-dist", "codespell", + "editables", "hatchling", "mdformat", "mdformat-tables>=1", + "pip", "pytest", "pytest-cov", "ruff", From 42f9a439d7ca1a1c0ab8d003b4f4525f598df22f Mon Sep 17 00:00:00 2001 From: Tim Paine <3105306+timkpaine@users.noreply.github.com> Date: Tue, 4 Aug 2026 10:39:47 -0400 Subject: [PATCH 2/2] Small tweaks and compatibility fixes Signed-off-by: Tim Paine <3105306+timkpaine@users.noreply.github.com> --- README.md | 6 +-- hatch_rs/plugin.py | 4 +- hatch_rs/structs.py | 21 +++++----- hatch_rs/tests/test_plugin.py | 40 +++++++++++++++++++ .../Cargo.lock | 0 .../Cargo.toml | 0 .../project/__init__.py | 0 .../pyproject.toml | 4 +- .../src/lib.rs | 0 hatch_rs/tests/test_projects.py | 6 +-- hatch_rs/tests/test_structs.py | 25 ++++++++++++ 11 files changed, 87 insertions(+), 19 deletions(-) create mode 100644 hatch_rs/tests/test_plugin.py rename hatch_rs/tests/{test_project_debug_for_dev_mode => test_project_editable_debug}/Cargo.lock (100%) rename hatch_rs/tests/{test_project_debug_for_dev_mode => test_project_editable_debug}/Cargo.toml (100%) rename hatch_rs/tests/{test_project_debug_for_dev_mode => test_project_editable_debug}/project/__init__.py (100%) rename hatch_rs/tests/{test_project_debug_for_dev_mode => test_project_editable_debug}/pyproject.toml (89%) rename hatch_rs/tests/{test_project_debug_for_dev_mode => test_project_editable_debug}/src/lib.rs (100%) diff --git a/README.md b/README.md index 1bc3d77..4ac2df8 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ destination = "project/lib/{shared_library}" Destination templates support `{module}`, `{target}`, `{profile}`, `{name}`, `{shared_library}`, `{import_library}`, and `{python_extension_name}`. -### Forcing rust debug profile in development mode +### Using the Rust debug profile for editable installs By default rust release profile is used to compile the artifacts and it can be changed using the `profile` option in `tool.hatch.build.hooks.hatch-rs` @@ -57,8 +57,8 @@ When installing the Python project in development mode (aka editable installs) using the command `pip install --editable `, it can be preferred to use the rust debug profile so the compilation time is faster. -Using rust debug profile in development mode can be enforced by setting the -`debug-for-dev-mode` option to `true` either in `tool.hatch.build.hooks.hatch-rs` +Using the Rust debug profile for editable installs can be enforced by setting the +`editable-debug` option to `true` either in `tool.hatch.build.hooks.hatch-rs` or `tool.hatch.build.hooks.hatch-rs.artifacts` sections. ### Generated files and headers diff --git a/hatch_rs/plugin.py b/hatch_rs/plugin.py index 0cd2609..4aa1e32 100644 --- a/hatch_rs/plugin.py +++ b/hatch_rs/plugin.py @@ -50,7 +50,9 @@ def initialize(self, version: str, build_data: dict[str, Any]) -> None: build_plan = build_plan_class(**config.model_dump()) # Generate commands - build_plan.generate(editable_install=(version == "editable")) + if isinstance(build_plan, HatchRustBuildPlan): + build_plan.set_editable_install(version == "editable") + build_plan.generate() # Log commands if in verbose mode if config.verbose: diff --git a/hatch_rs/structs.py b/hatch_rs/structs.py index 49b1dc1..6e2508a 100644 --- a/hatch_rs/structs.py +++ b/hatch_rs/structs.py @@ -416,10 +416,10 @@ class RustArtifactConfig(BaseModel): manifest: Path | None = Field(default=None, description="Path to Cargo.toml, relative to the hook path unless absolute.") build_type: BuildType | None = Field(default=None, alias="build-type") profile: str | None = Field(default=None, description="Cargo profile for this artifact.") - debug_for_dev_mode: bool = Field( + editable_debug: bool = Field( default=False, - alias="debug-for-dev-mode", - description="Force rust debug profile when installing the Python project in development mode (aka editable installs)", + alias="editable-debug", + description="Use the Rust debug profile for editable installs.", ) target: str | None = Field(default=None, description="Rust target triple for this artifact.") package: str | None = Field(default=None, description="Cargo package selector.") @@ -581,10 +581,10 @@ class HatchRustBuildConfig(BaseModel): manifest: Path | None = Field(default=None, description="Path to Cargo.toml, relative to path unless absolute.") build_type: BuildType = Field(default="release", alias="build-type") profile: str | None = Field(default=None, description="Cargo profile to build. Overrides build_type when set.") - debug_for_dev_mode: bool = Field( + editable_debug: bool = Field( default=False, - alias="debug-for-dev-mode", - description="Force rust debug profile when installing the Python project in development mode (aka editable installs)", + alias="editable-debug", + description="Use the Rust debug profile for editable installs.", ) features: list[str] = Field(default_factory=list, description="Cargo features to enable.") all_features: bool = Field(default=False, alias="all-features", description="Enable all Cargo features.") @@ -733,7 +733,7 @@ def _artifact_manifest(self, artifact: RustArtifactConfig) -> Path | None: return artifact.manifest if artifact.manifest is not None else self.manifest def _artifact_profile(self, artifact: RustArtifactConfig) -> str: - if self._editable_install and (artifact.debug_for_dev_mode or self.debug_for_dev_mode): + if self._editable_install and (artifact.editable_debug or self.editable_debug): return "debug" build_type = artifact.build_type or self.build_type return artifact.profile or self.profile or build_type @@ -910,7 +910,10 @@ def _build_command_artifact_plan(self, artifact: RustArtifactConfig, *, global_t set_target_dir_env=set_target_dir_env, ) - def generate(self, editable_install=False): + def set_editable_install(self, editable_install: bool) -> None: + self._editable_install = editable_install + + def generate(self): if self._temporary_target_dir is not None: self._temporary_target_dir.cleanup() self._temporary_target_dir = None @@ -923,8 +926,6 @@ def generate(self, editable_install=False): self._shared_scripts = {} self._artifact_manifest_records = [] self._libraries = [] - self._editable_install = editable_install - global_target = self.target for artifact in self._configured_artifacts(): if self._is_generated_artifact(artifact): diff --git a/hatch_rs/tests/test_plugin.py b/hatch_rs/tests/test_plugin.py new file mode 100644 index 0000000..acd9251 --- /dev/null +++ b/hatch_rs/tests/test_plugin.py @@ -0,0 +1,40 @@ +from hatch_rs.plugin import HatchRustBuildHook + + +def test_custom_build_plan_generate_keeps_no_argument_contract(monkeypatch, tmp_path): + generated = [] + + class CustomBuildPlan: + def __init__(self, **_config): + self.commands = [] + self.copied_artifacts = [] + self.shared_data = {"source": "destination"} + self.shared_scripts = {} + self.libraries = [] + + def generate(self): + generated.append(True) + + def execute(self): + pass + + def cleanup(self): + pass + + class Metadata: + def __init__(self): + self.config = {"project": {"name": "project"}} + + monkeypatch.setattr("hatch_rs.plugin.import_string", lambda path: CustomBuildPlan) + hook = HatchRustBuildHook( + root=str(tmp_path), + config={"module": "project", "path": str(tmp_path), "build-plan-class": "tests.CustomBuildPlan"}, + build_config=None, + metadata=Metadata(), + directory=str(tmp_path), + target_name="wheel", + ) + + hook.initialize("standard", {}) + + assert generated == [True] diff --git a/hatch_rs/tests/test_project_debug_for_dev_mode/Cargo.lock b/hatch_rs/tests/test_project_editable_debug/Cargo.lock similarity index 100% rename from hatch_rs/tests/test_project_debug_for_dev_mode/Cargo.lock rename to hatch_rs/tests/test_project_editable_debug/Cargo.lock diff --git a/hatch_rs/tests/test_project_debug_for_dev_mode/Cargo.toml b/hatch_rs/tests/test_project_editable_debug/Cargo.toml similarity index 100% rename from hatch_rs/tests/test_project_debug_for_dev_mode/Cargo.toml rename to hatch_rs/tests/test_project_editable_debug/Cargo.toml diff --git a/hatch_rs/tests/test_project_debug_for_dev_mode/project/__init__.py b/hatch_rs/tests/test_project_editable_debug/project/__init__.py similarity index 100% rename from hatch_rs/tests/test_project_debug_for_dev_mode/project/__init__.py rename to hatch_rs/tests/test_project_editable_debug/project/__init__.py diff --git a/hatch_rs/tests/test_project_debug_for_dev_mode/pyproject.toml b/hatch_rs/tests/test_project_editable_debug/pyproject.toml similarity index 89% rename from hatch_rs/tests/test_project_debug_for_dev_mode/pyproject.toml rename to hatch_rs/tests/test_project_editable_debug/pyproject.toml index 471aa94..f493531 100644 --- a/hatch_rs/tests/test_project_debug_for_dev_mode/pyproject.toml +++ b/hatch_rs/tests/test_project_editable_debug/pyproject.toml @@ -3,7 +3,7 @@ requires = ["hatchling>=1.20"] build-backend = "hatchling.build" [project] -name = "hatch-cpp-test-project-debug-for-dev-mode" +name = "hatch-rs-test-project-editable-debug" description = "Basic test project for hatch-rs" version = "0.1.0" requires-python = ">=3.9" @@ -34,4 +34,4 @@ target-dir = "target" name = "extension" manifest = "Cargo.toml" destination = "project/{python_extension_name}" -debug-for-dev-mode = true +editable-debug = true diff --git a/hatch_rs/tests/test_project_debug_for_dev_mode/src/lib.rs b/hatch_rs/tests/test_project_editable_debug/src/lib.rs similarity index 100% rename from hatch_rs/tests/test_project_debug_for_dev_mode/src/lib.rs rename to hatch_rs/tests/test_project_editable_debug/src/lib.rs diff --git a/hatch_rs/tests/test_projects.py b/hatch_rs/tests/test_projects.py index 0401e78..f9ddb42 100644 --- a/hatch_rs/tests/test_projects.py +++ b/hatch_rs/tests/test_projects.py @@ -307,8 +307,8 @@ def test_c_abi_symbol_validation_failure(self): assert completed.returncode != 0 assert "validation_failure_missing_symbol" in completed.stdout - def test_debug_for_dev_mode(self): - project_folder = "test_project_debug_for_dev_mode" + def test_editable_debug(self): + project_folder = "test_project_editable_debug" # cleanup rmtree(f"hatch_rs/tests/{project_folder}/target", ignore_errors=True) rmtree(f"hatch_rs/tests/{project_folder}/project/extension.abi3.so", ignore_errors=True) @@ -331,7 +331,7 @@ def test_debug_for_dev_mode(self): env=_subprocess_env(), ) - # check debug-for-dev-mode option was honored + # check editable-debug option was honored assert Path(f"hatch_rs/tests/{project_folder}/target/debug").exists() assert not Path(f"hatch_rs/tests/{project_folder}/target/release").exists() diff --git a/hatch_rs/tests/test_structs.py b/hatch_rs/tests/test_structs.py index 9e8e55d..7d34bc5 100644 --- a/hatch_rs/tests/test_structs.py +++ b/hatch_rs/tests/test_structs.py @@ -123,6 +123,31 @@ def test_build_plan_generates_cargo_invocation(tmp_path): ] +def test_build_plan_uses_debug_profile_for_editable_install(tmp_path): + plan = HatchRustBuildPlan( + module="project", + path=tmp_path, + target="x86_64-unknown-linux-gnu", + profile="optimized", + editable_debug=True, + ) + plan.set_editable_install(True) + + assert plan.generate() == ["cargo rustc --target x86_64-unknown-linux-gnu -- --crate-type cdylib"] + + +def test_build_plan_preserves_profile_for_standard_install(tmp_path): + plan = HatchRustBuildPlan( + module="project", + path=tmp_path, + target="x86_64-unknown-linux-gnu", + profile="optimized", + editable_debug=True, + ) + + assert plan.generate() == ["cargo rustc --profile optimized --target x86_64-unknown-linux-gnu -- --crate-type cdylib"] + + def test_build_plan_generates_manifest_and_cargo_options(tmp_path): plan = HatchRustBuildPlan( module="project",