Skip to content

Commit

Permalink
Add path option for Python source
Browse files Browse the repository at this point in the history
Co-authored-by: David Hewitt <1939362+davidhewitt@users.noreply.github.com>
  • Loading branch information
messense and davidhewitt committed Aug 6, 2021
1 parent 24d0ee1 commit 411900f
Show file tree
Hide file tree
Showing 18 changed files with 448 additions and 6 deletions.
2 changes: 2 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

* Add path option for Python source in [#584](https://github.com/PyO3/maturin/pull/584)

## [0.11.2] - 2021-07-20

* Use UTF-8 encoding when reading `pyproject.toml` by domdfcoding in [#588](https://github.com/PyO3/maturin/pull/588)
Expand Down
24 changes: 24 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,30 @@ my-project
├── my_project
│   ├── __init__.py
│   └── bar.py
├── pyproject.toml
├── Readme.md
└── src
   └── lib.rs
```

You can specify a different python source directory in `Cargo.toml` by setting `package.metadata.maturin.python-source`, for example

```toml
[package.metadata.maturin]
python-source = "python"
```

then the project structure would look like this:

```
my-project
├── Cargo.toml
├── python
│   ├── my_project
│  │ ├── __init__.py
│   │ ├── __init__.py
│   │ └── bar.py
│   └── pyproject.toml
├── Readme.md
└── src
   └── lib.rs
Expand Down
16 changes: 12 additions & 4 deletions src/build_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::Target;
use anyhow::{anyhow, bail, Context, Result};
use cargo_metadata::Metadata;
use fs_err as fs;
use std::borrow::Cow;
use std::path::{Path, PathBuf};

/// The way the rust code is used in the wheel
Expand Down Expand Up @@ -73,22 +74,29 @@ pub enum ProjectLayout {

impl ProjectLayout {
/// Checks whether a python module exists besides Cargo.toml with the right name
pub fn determine(project_root: impl AsRef<Path>, module_name: &str) -> Result<ProjectLayout> {
pub fn determine(
project_root: impl AsRef<Path>,
module_name: &str,
py_src: Option<impl AsRef<Path>>,
) -> Result<ProjectLayout> {
// A dot in the module name means the extension module goes into the module folder specified by the path
let parts: Vec<&str> = module_name.split('.').collect();
let project_root = project_root.as_ref();
let python_root = py_src.map_or(Cow::Borrowed(project_root), |py_src| {
Cow::Owned(project_root.join(py_src))
});
let (python_module, rust_module, extension_name) = if parts.len() > 1 {
let mut rust_module = project_root.to_path_buf();
rust_module.extend(&parts[0..parts.len() - 1]);
(
project_root.join(parts[0]),
python_root.join(parts[0]),
rust_module,
parts[parts.len() - 1].to_string(),
)
} else {
(
project_root.join(module_name),
project_root.join(module_name),
python_root.join(module_name),
python_root.join(module_name),
module_name.to_string(),
)
};
Expand Down
6 changes: 5 additions & 1 deletion src/build_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,11 @@ impl BuildOptions {
.filter(|name| name.contains('.'))
.unwrap_or(&module_name);

let project_layout = ProjectLayout::determine(manifest_dir, extension_name)?;
let project_layout = ProjectLayout::determine(
manifest_dir,
extension_name,
extra_metadata.python_source.as_deref(),
)?;

let mut cargo_extra_args = split_extra_args(&self.cargo_extra_args)?;
if let Some(ref target) = self.target {
Expand Down
1 change: 1 addition & 0 deletions src/cargo_toml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ pub struct RemainingCoreMetadata {
pub project_url: Option<HashMap<String, String>>,
pub provides_extra: Option<Vec<String>>,
pub description_content_type: Option<String>,
pub python_source: Option<String>,
}

#[cfg(test)]
Expand Down
26 changes: 25 additions & 1 deletion src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use anyhow::{bail, Context, Result};
use fs_err as fs;
use regex::Regex;
use serde::{Deserialize, Serialize};
use std::borrow::Cow;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::str;
Expand Down Expand Up @@ -356,7 +357,14 @@ impl Metadata21 {
gui_scripts: HashMap::new(),
entry_points: HashMap::new(),
};
metadata.merge_pyproject_toml(manifest_path)?;

let manifest_path = manifest_path.as_ref();
let py_src = extra_metadata
.python_source
.map_or(Cow::Borrowed(manifest_path), |src| {
Cow::Owned(manifest_path.join(src))
});
metadata.merge_pyproject_toml(&*py_src)?;
Ok(metadata)
}

Expand Down Expand Up @@ -776,4 +784,20 @@ mod test {
let pkginfo: Result<python_pkginfo::Metadata, _> = content.parse();
assert!(pkginfo.is_ok());
}

#[test]
fn test_merge_metadata_from_pyproject_toml_with_customized_python_source_dir() {
let cargo_toml_str =
fs_err::read_to_string("test-crates/pyo3-mixed-py-subdir/Cargo.toml").unwrap();
let cargo_toml: CargoToml = toml::from_str(&cargo_toml_str).unwrap();
let metadata =
Metadata21::from_cargo_toml(&cargo_toml, "test-crates/pyo3-mixed-py-subdir").unwrap();
// defined in Cargo.toml
assert_eq!(
metadata.summary,
Some("Implements a dummy function combining rust and python".to_string())
);
// defined in pyproject.toml
assert_eq!(metadata.scripts["get_42"], "pyo3_mixed_py_subdir:get_42");
}
}
Loading

0 comments on commit 411900f

Please sign in to comment.