diff --git a/guide/src/project_layout.md b/guide/src/project_layout.md index e6969c838..3d185105c 100644 --- a/guide/src/project_layout.md +++ b/guide/src/project_layout.md @@ -127,10 +127,12 @@ my-rust-and-python-project ``` #### Import Rust as a submodule of your project -If the Python module created by Rust has the same name as the Python package in a mixed Rust/Python project, IDEs might get confused. You might also want to discourage end users from using the Rust functions directly by giving it a different name, say '\_my_project'. This can be done by adding `name = .` to the `[package.metadata.maturin]` in your `Cargo.toml`. For example: +If the Python module created by Rust has the same name as the Python package in a mixed Rust/Python project, IDEs might get confused. +You might also want to discourage end users from using the Rust functions directly by giving it a different name, say '\_my_project'. +This can be done by adding `name = .` to the `[tool.maturin]` in your `pyproject.toml`. For example: ```toml -[package.metadata.maturin] +[tool.maturin] name = "my_project._my_project" ``` diff --git a/src/build_options.rs b/src/build_options.rs index 725b78a30..64c656927 100644 --- a/src/build_options.rs +++ b/src/build_options.rs @@ -516,7 +516,7 @@ impl BuildOptions { bail!( "The module name must not contain a minus `-` \ (Make sure you have set an appropriate [lib] name or \ - [package.metadata.maturin] name in your Cargo.toml)" + [tool.maturin] name in your pyproject.toml)" ); } @@ -1497,18 +1497,14 @@ mod test { #[test] fn test_get_min_python_minor() { - use crate::CargoToml; - // Nothing specified let manifest_path = "test-crates/pyo3-pure/Cargo.toml"; - let cargo_toml = CargoToml::from_path(manifest_path).unwrap(); let cargo_metadata = MetadataCommand::new() .manifest_path(manifest_path) .exec() .unwrap(); let metadata21 = - Metadata21::from_cargo_toml(&cargo_toml, "test-crates/pyo3-pure", &cargo_metadata) - .unwrap(); + Metadata21::from_cargo_toml("test-crates/pyo3-pure", &cargo_metadata).unwrap(); assert_eq!(get_min_python_minor(&metadata21), None); } } diff --git a/src/cargo_toml.rs b/src/cargo_toml.rs index 49a4165df..b31e9a936 100644 --- a/src/cargo_toml.rs +++ b/src/cargo_toml.rs @@ -102,7 +102,6 @@ struct CargoTomlMetadata { #[derive(Serialize, Deserialize, Debug, Clone, Default)] #[serde(rename_all = "kebab-case")] pub struct RemainingCoreMetadata { - pub name: Option, /// Cargo compile targets pub targets: Option>, #[serde(flatten)] diff --git a/src/metadata.rs b/src/metadata.rs index 97aff6be8..2d9afb098 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -1,4 +1,4 @@ -use crate::{CargoToml, PyProjectToml}; +use crate::PyProjectToml; use anyhow::{bail, Context, Result}; use fs_err as fs; use regex::Regex; @@ -281,7 +281,6 @@ impl Metadata21 { /// /// manifest_path must be the directory, not the file pub fn from_cargo_toml( - cargo_toml: &CargoToml, manifest_path: impl AsRef, cargo_metadata: &cargo_metadata::Metadata, ) -> Result { @@ -295,8 +294,6 @@ impl Metadata21 { None }; - let extra_metadata = cargo_toml.remaining_core_metadata(); - let mut description: Option = None; let mut description_content_type: Option = None; // See https://packaging.python.org/specifications/core-metadata/#description @@ -329,16 +326,7 @@ impl Metadata21 { } } }; - let name = extra_metadata - .name - .map(|name| { - if let Some(pos) = name.find('.') { - name.split_at(pos).0.to_string() - } else { - name.clone() - } - }) - .unwrap_or_else(|| package.name.clone()); + let name = package.name.clone(); let mut project_url = HashMap::new(); if let Some(repository) = package.repository.as_ref() { project_url.insert("Source Code".to_string(), repository.clone()); @@ -564,14 +552,12 @@ mod test { let toml_with_path = cargo_toml.replace("REPLACE_README_PATH", &readme_path); fs::write(&manifest_path, &toml_with_path).unwrap(); - let cargo_toml_struct: CargoToml = toml::from_str(&toml_with_path).unwrap(); let cargo_metadata = MetadataCommand::new() .manifest_path(manifest_path) .exec() .unwrap(); - let metadata = - Metadata21::from_cargo_toml(&cargo_toml_struct, crate_path, &cargo_metadata).unwrap(); + let metadata = Metadata21::from_cargo_toml(crate_path, &cargo_metadata).unwrap(); let actual = metadata.to_file_contents().unwrap(); @@ -590,13 +576,6 @@ mod test { "cargo_toml name and version string do not match hardcoded values, test will fail", ); - if cargo_toml_struct.remaining_core_metadata().name.is_none() { - assert_eq!( - metadata.get_dist_info_dir(), - PathBuf::from("info_project-0.1.0.dist-info"), - "Dist info dir differed from expected" - ); - } metadata } @@ -726,14 +705,11 @@ mod test { #[test] fn test_merge_metadata_from_pyproject_toml() { let manifest_dir = PathBuf::from("test-crates").join("pyo3-pure"); - let cargo_toml_str = fs_err::read_to_string(manifest_dir.join("Cargo.toml")).unwrap(); - let cargo_toml: CargoToml = toml::from_str(&cargo_toml_str).unwrap(); let cargo_metadata = MetadataCommand::new() .manifest_path(manifest_dir.join("Cargo.toml")) .exec() .unwrap(); - let mut metadata = - Metadata21::from_cargo_toml(&cargo_toml, &manifest_dir, &cargo_metadata).unwrap(); + let mut metadata = Metadata21::from_cargo_toml(&manifest_dir, &cargo_metadata).unwrap(); let pyproject_toml = PyProjectToml::new(manifest_dir.join("pyproject.toml")).unwrap(); metadata .merge_pyproject_toml(&manifest_dir, &pyproject_toml) @@ -777,14 +753,11 @@ mod test { #[test] fn test_merge_metadata_from_pyproject_toml_with_customized_python_source_dir() { let manifest_dir = PathBuf::from("test-crates").join("pyo3-mixed-py-subdir"); - let cargo_toml_str = fs_err::read_to_string(manifest_dir.join("Cargo.toml")).unwrap(); - let cargo_toml: CargoToml = toml::from_str(&cargo_toml_str).unwrap(); let cargo_metadata = MetadataCommand::new() .manifest_path(manifest_dir.join("Cargo.toml")) .exec() .unwrap(); - let mut metadata = - Metadata21::from_cargo_toml(&cargo_toml, &manifest_dir, &cargo_metadata).unwrap(); + let mut metadata = Metadata21::from_cargo_toml(&manifest_dir, &cargo_metadata).unwrap(); let pyproject_toml = PyProjectToml::new(manifest_dir.join("pyproject.toml")).unwrap(); metadata .merge_pyproject_toml(&manifest_dir, &pyproject_toml) @@ -801,14 +774,11 @@ mod test { #[test] fn test_implicit_readme() { let manifest_dir = PathBuf::from("test-crates").join("pyo3-mixed"); - let cargo_toml_str = fs_err::read_to_string(manifest_dir.join("Cargo.toml")).unwrap(); - let cargo_toml = toml::from_str(&cargo_toml_str).unwrap(); let cargo_metadata = MetadataCommand::new() .manifest_path(manifest_dir.join("Cargo.toml")) .exec() .unwrap(); - let metadata = - Metadata21::from_cargo_toml(&cargo_toml, &manifest_dir, &cargo_metadata).unwrap(); + let metadata = Metadata21::from_cargo_toml(&manifest_dir, &cargo_metadata).unwrap(); assert!(metadata.description.unwrap().starts_with("# pyo3-mixed")); assert_eq!( metadata.description_content_type.unwrap(), @@ -819,14 +789,11 @@ mod test { #[test] fn test_merge_metadata_from_pyproject_dynamic_license_test() { let manifest_dir = PathBuf::from("test-crates").join("license-test"); - let cargo_toml_str = fs_err::read_to_string(manifest_dir.join("Cargo.toml")).unwrap(); - let cargo_toml: CargoToml = toml::from_str(&cargo_toml_str).unwrap(); let cargo_metadata = MetadataCommand::new() .manifest_path(manifest_dir.join("Cargo.toml")) .exec() .unwrap(); - let mut metadata = - Metadata21::from_cargo_toml(&cargo_toml, &manifest_dir, &cargo_metadata).unwrap(); + let mut metadata = Metadata21::from_cargo_toml(&manifest_dir, &cargo_metadata).unwrap(); let pyproject_toml = PyProjectToml::new(manifest_dir.join("pyproject.toml")).unwrap(); metadata .merge_pyproject_toml(&manifest_dir, &pyproject_toml) diff --git a/src/project_layout.rs b/src/project_layout.rs index 9679a709b..4300b7d04 100644 --- a/src/project_layout.rs +++ b/src/project_layout.rs @@ -108,14 +108,12 @@ impl ProjectResolver { let cargo_metadata = Self::resolve_cargo_metadata(&manifest_file, &cargo_options)?; - let mut metadata21 = - Metadata21::from_cargo_toml(&cargo_toml, manifest_dir, &cargo_metadata) - .context("Failed to parse Cargo.toml into python metadata")?; + let mut metadata21 = Metadata21::from_cargo_toml(manifest_dir, &cargo_metadata) + .context("Failed to parse Cargo.toml into python metadata")?; if let Some(pyproject) = pyproject { let pyproject_dir = pyproject_file.parent().unwrap(); metadata21.merge_pyproject_toml(pyproject_dir, pyproject)?; } - let extra_metadata = cargo_toml.remaining_core_metadata(); let crate_name = &cargo_toml.package.name; @@ -128,7 +126,7 @@ impl ProjectResolver { .unwrap_or(crate_name) .to_owned(); - let extension_name = extra_metadata.name.as_ref().unwrap_or(&module_name); + let extension_name = pyproject.and_then(|x| x.name()).unwrap_or(&module_name); let project_root = if pyproject_file.is_file() { pyproject_file.parent().unwrap_or(manifest_dir) diff --git a/src/pyproject_toml.rs b/src/pyproject_toml.rs index d3e0ac8e5..d506e40c2 100644 --- a/src/pyproject_toml.rs +++ b/src/pyproject_toml.rs @@ -86,6 +86,8 @@ impl GlobPattern { #[serde(rename_all = "kebab-case")] pub struct ToolMaturin { // maturin specific options + // extension module name, accepts setuptools style import name like `foo.bar` + name: Option, include: Option>, exclude: Option>, bindings: Option, @@ -170,6 +172,11 @@ impl PyProjectToml { self.tool.as_ref()?.maturin.as_ref() } + /// Returns the value of `[tool.maturin.name]` in pyproject.toml + pub fn name(&self) -> Option<&str> { + self.maturin()?.name.as_deref() + } + /// Returns the value of `[tool.maturin.include]` in pyproject.toml pub fn include(&self) -> Option<&[GlobPattern]> { self.maturin()?.include.as_ref().map(AsRef::as_ref) diff --git a/test-crates/pyo3-mixed-py-subdir/Cargo.toml b/test-crates/pyo3-mixed-py-subdir/Cargo.toml index 4620a49ba..e6fe21af5 100644 --- a/test-crates/pyo3-mixed-py-subdir/Cargo.toml +++ b/test-crates/pyo3-mixed-py-subdir/Cargo.toml @@ -12,6 +12,3 @@ pyo3 = { version = "0.18.0", features = ["extension-module"] } [lib] name = "pyo3_mixed_py_subdir" crate-type = ["cdylib"] - -[package.metadata.maturin] -name = "pyo3_mixed_py_subdir._pyo3_mixed" diff --git a/test-crates/pyo3-mixed-py-subdir/pyproject.toml b/test-crates/pyo3-mixed-py-subdir/pyproject.toml index d4dec533b..85a06217a 100644 --- a/test-crates/pyo3-mixed-py-subdir/pyproject.toml +++ b/test-crates/pyo3-mixed-py-subdir/pyproject.toml @@ -14,4 +14,5 @@ requires-python = ">=3.6" get_42 = "pyo3_mixed_py_subdir:get_42" [tool.maturin] +name = "pyo3_mixed_py_subdir._pyo3_mixed" python-source = "python" diff --git a/test-crates/pyo3-mixed-submodule/Cargo.toml b/test-crates/pyo3-mixed-submodule/Cargo.toml index a7bb42a48..5bf924c67 100644 --- a/test-crates/pyo3-mixed-submodule/Cargo.toml +++ b/test-crates/pyo3-mixed-submodule/Cargo.toml @@ -6,9 +6,6 @@ description = "Implements a dummy function combining rust and python" readme = "README.md" edition = "2021" -[package.metadata.maturin] -name = "pyo3_mixed_submodule.rust_module.rust" - [dependencies] pyo3 = { version = "0.18.0", features = ["extension-module"] } diff --git a/test-crates/pyo3-mixed-submodule/pyproject.toml b/test-crates/pyo3-mixed-submodule/pyproject.toml index 14719144a..ccc2f8599 100644 --- a/test-crates/pyo3-mixed-submodule/pyproject.toml +++ b/test-crates/pyo3-mixed-submodule/pyproject.toml @@ -8,3 +8,6 @@ classifiers = [ "Programming Language :: Python", "Programming Language :: Rust" ] + +[tool.maturin] +name = "pyo3_mixed_submodule.rust_module.rust"