Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --src option to generate src layout for mixed Python/Rust projects #1189

Merged
merged 1 commit into from
Oct 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

* Initial support for shipping bin targets as wasm32-wasi binaries that are run through wasmtime in [#1107](https://github.com/PyO3/maturin/pull/1107).
Note that wasmtime currently only support the five most popular platforms and that wasi binaries have restrictions when interacting with the host.
Usage is by setting `--target wasm32-wasi`.
* Add support for python first [`src` project layout](https://py-pkgs.org/04-package-structure.html#the-source-layout) in [#1185](https://github.com/PyO3/maturin/pull/1185)
* Initial support for shipping bin targets as wasm32-wasi binaries that are run through wasmtime in [#1107](https://github.com/PyO3/maturin/pull/1107).
Note that wasmtime currently only support the five most popular platforms and that wasi binaries have restrictions when interacting with the host.
Usage is by setting `--target wasm32-wasi`.
* Add support for python first [`src` project layout](https://py-pkgs.org/04-package-structure.html#the-source-layout) in [#1185](https://github.com/PyO3/maturin/pull/1185)
* Add `--src` option to generate src layout for mixed Python/Rust projects in [#1189](https://github.com/PyO3/maturin/pull/1189)

## [0.13.6] - 2022-10-08

Expand Down
74 changes: 54 additions & 20 deletions src/new_project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,29 @@ use fs_err as fs;
use minijinja::{context, Environment};
use std::path::Path;

/// Mixed Rust/Python project layout
#[derive(Debug, Clone, Copy)]
enum ProjectLayout {
Mixed { src: bool },
PureRust,
}

struct ProjectGenerator<'a> {
env: Environment<'a>,
project_name: String,
crate_name: String,
bindings: String,
mixed: bool,
layout: ProjectLayout,
overwrite: bool,
}

impl<'a> ProjectGenerator<'a> {
fn new(project_name: String, mixed: bool, bindings: String, overwrite: bool) -> Result<Self> {
fn new(
project_name: String,
layout: ProjectLayout,
bindings: String,
overwrite: bool,
) -> Result<Self> {
let crate_name = project_name.replace('-', "_");
let mut env = Environment::new();
env.add_template(".gitignore", include_str!("templates/.gitignore.j2"))?;
Expand All @@ -33,34 +45,48 @@ impl<'a> ProjectGenerator<'a> {
project_name,
crate_name,
bindings,
mixed,
layout,
overwrite,
})
}

fn generate(&self, project_path: &Path) -> Result<()> {
let src_path = project_path.join("src");
fs::create_dir_all(&src_path)?;

fs::create_dir_all(project_path)?;
self.write_project_file(project_path, ".gitignore")?;
self.write_project_file(project_path, "Cargo.toml")?;
self.write_project_file(project_path, "pyproject.toml")?;

if self.bindings == "bin" {
self.write_project_file(&src_path, "main.rs")?;
} else {
self.write_project_file(&src_path, "lib.rs")?;
}

// CI configuration
let gh_action_path = project_path.join(".github").join("workflows");
fs::create_dir_all(&gh_action_path)?;
self.write_project_file(&gh_action_path, "CI.yml")?;

if self.mixed {
let python_dir = project_path.join("python");
let py_path = python_dir.join(&self.crate_name);
fs::create_dir_all(&py_path)?;
self.write_project_file(&py_path, "__init__.py")?;
let rust_project = match self.layout {
ProjectLayout::Mixed { src } => {
let python_dir = if src {
project_path.join("src")
} else {
project_path.join("python")
};
let python_project = python_dir.join(&self.crate_name);
fs::create_dir_all(&python_project)?;
self.write_project_file(&python_project, "__init__.py")?;

if src {
project_path.join("rust")
} else {
project_path.to_path_buf()
}
}
ProjectLayout::PureRust => project_path.to_path_buf(),
};

let rust_src = rust_project.join("src");
fs::create_dir_all(&rust_src)?;
self.write_project_file(&rust_project, "Cargo.toml")?;
if self.bindings == "bin" {
self.write_project_file(&rust_src, "main.rs")?;
} else {
self.write_project_file(&rust_src, "lib.rs")?;
}

Ok(())
Expand All @@ -74,7 +100,7 @@ impl<'a> ProjectGenerator<'a> {
name => self.project_name,
crate_name => self.crate_name,
bindings => self.bindings,
mixed => self.mixed,
mixed_non_src => matches!(self.layout, ProjectLayout::Mixed { src: false }),
version_major => version_major,
version_minor => version_minor
))?;
Expand All @@ -99,6 +125,9 @@ pub struct GenerateProjectOptions {
/// Use mixed Rust/Python project layout
#[clap(long)]
mixed: bool,
/// Use Python first src layout for mixed Rust/Python project
#[clap(long)]
src: bool,
/// Which kind of bindings to use
#[clap(short, long, value_parser = ["pyo3", "rust-cpython", "cffi", "bin"])]
bindings: Option<String>,
Expand Down Expand Up @@ -173,6 +202,11 @@ fn generate_project(
bindings_items[selection].to_string()
};

let generator = ProjectGenerator::new(name, options.mixed, bindings, overwrite)?;
let layout = if options.mixed {
ProjectLayout::Mixed { src: options.src }
} else {
ProjectLayout::PureRust
};
let generator = ProjectGenerator::new(name, layout, bindings, overwrite)?;
generator.generate(project_path)
}
4 changes: 2 additions & 2 deletions src/templates/pyproject.toml.j2
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ classifiers = [
dependencies = ["cffi"]
{%- endif %}

{% if bindings == "cffi" or bindings == "bin" or mixed -%}
{% if bindings == "cffi" or bindings == "bin" or mixed_non_src -%}
[tool.maturin]
{% if bindings == "cffi" or bindings == "bin" -%}
bindings = "{{ bindings }}"
{% endif -%}
{% if mixed -%}
{% if mixed_non_src -%}
python-source = "python"
{% endif -%}
{% endif -%}
1 change: 1 addition & 0 deletions tests/cmd/init.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ ARGS:
OPTIONS:
--name <NAME> Set the resulting package name, defaults to the directory name
--mixed Use mixed Rust/Python project layout
--src Use Python first src layout for mixed Rust/Python project
-b, --bindings <BINDINGS> Which kind of bindings to use [possible values: pyo3, rust-cpython,
cffi, bin]
-h, --help Print help information
1 change: 1 addition & 0 deletions tests/cmd/new.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ ARGS:
OPTIONS:
--name <NAME> Set the resulting package name, defaults to the directory name
--mixed Use mixed Rust/Python project layout
--src Use Python first src layout for mixed Rust/Python project
-b, --bindings <BINDINGS> Which kind of bindings to use [possible values: pyo3, rust-cpython,
cffi, bin]
-h, --help Print help information