Skip to content

Commit

Permalink
Add PEP 660 support
Browse files Browse the repository at this point in the history
  • Loading branch information
messense committed Oct 13, 2021
1 parent 0220fd9 commit df6c586
Show file tree
Hide file tree
Showing 10 changed files with 98 additions and 22 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 support for PEP 660 editable installs in [#648](https://github.com/PyO3/maturin/pull/648)

## [0.11.5] - 2021-10-13

* Fixed module documentation missing bug of pyo3 bindings in [#639](https://github.com/PyO3/maturin/pull/639)
Expand Down
26 changes: 25 additions & 1 deletion maturin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,14 @@ def get_config() -> Dict[str, str]:


# noinspection PyUnusedLocal
def build_wheel(wheel_directory, config_settings=None, metadata_directory=None):
def _build_wheel(
wheel_directory, config_settings=None, metadata_directory=None, editable=False
):
# PEP 517 specifies that only `sys.executable` points to the correct
# python interpreter
command = ["maturin", "pep517", "build-wheel", "-i", sys.executable]
if editable:
command.append("--editable")

print("Running `{}`".format(" ".join(command)))
sys.stdout.flush()
Expand All @@ -48,6 +52,11 @@ def build_wheel(wheel_directory, config_settings=None, metadata_directory=None):
return filename


# noinspection PyUnusedLocal
def build_wheel(wheel_directory, config_settings=None, metadata_directory=None):
return _build_wheel(wheel_directory, config_settings, metadata_directory)


# noinspection PyUnusedLocal
def build_sdist(sdist_directory, config_settings=None):
command = ["maturin", "pep517", "write-sdist", "--sdist-directory", sdist_directory]
Expand All @@ -74,6 +83,17 @@ def get_requires_for_build_wheel(config_settings=None):
return []


# noinspection PyUnusedLocal
def build_editable(wheel_directory, config_settings=None, metadata_directory=None):
return _build_wheel(
wheel_directory, config_settings, metadata_directory, editable=True
)


# Requirements to build an editable are the same as for a wheel
get_requires_for_build_editable = get_requires_for_build_wheel


# noinspection PyUnusedLocal
def get_requires_for_build_sdist(config_settings=None):
return []
Expand Down Expand Up @@ -122,3 +142,7 @@ def prepare_metadata_for_build_wheel(metadata_directory, config_settings=None):
sys.stdout.flush()
output = output.decode(errors="replace")
return output.strip().splitlines()[-1]


# Metadata for editable are the same as for a wheel
prepare_metadata_for_build_editable = prepare_metadata_for_build_wheel
31 changes: 24 additions & 7 deletions src/build_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ pub struct BuildContext {
pub cargo_metadata: Metadata,
/// Whether to use universal2 or use the native macOS tag (off)
pub universal2: bool,
/// Build editable wheels
pub editable: bool,
}

/// The wheel file location and its Python version tag (e.g. `py3`).
Expand Down Expand Up @@ -244,6 +246,13 @@ impl BuildContext {
Ok(policy)
}

fn add_pth(&self, writer: &mut WheelWriter) -> Result<()> {
if self.editable {
writer.add_pth(&self.project_layout, &self.metadata21)?;
}
Ok(())
}

fn write_binding_wheel_abi3(
&self,
artifact: &Path,
Expand All @@ -267,6 +276,8 @@ impl BuildContext {
)
.context("Failed to add the files to the wheel")?;

self.add_pth(&mut writer)?;

let wheel_path = writer.finish()?;
Ok((wheel_path, format!("cp{}{}", major, min_minor)))
}
Expand Down Expand Up @@ -322,6 +333,8 @@ impl BuildContext {
)
.context("Failed to add the files to the wheel")?;

self.add_pth(&mut writer)?;

let wheel_path = writer.finish()?;
Ok((
wheel_path,
Expand Down Expand Up @@ -398,10 +411,10 @@ impl BuildContext {
.target
.get_universal_tags(platform_tag, self.universal2);

let mut builder = WheelWriter::new(&tag, &self.out, &self.metadata21, &tags)?;
let mut writer = WheelWriter::new(&tag, &self.out, &self.metadata21, &tags)?;

write_cffi_module(
&mut builder,
&mut writer,
&self.project_layout,
self.manifest_path.parent().unwrap(),
&self.module_name,
Expand All @@ -410,7 +423,9 @@ impl BuildContext {
false,
)?;

let wheel_path = builder.finish()?;
self.add_pth(&mut writer)?;

let wheel_path = writer.finish()?;
Ok((wheel_path, "py3".to_string()))
}

Expand Down Expand Up @@ -440,15 +455,15 @@ impl BuildContext {
bail!("Defining entrypoints and working with a binary doesn't mix well");
}

let mut builder = WheelWriter::new(&tag, &self.out, &self.metadata21, &tags)?;
let mut writer = WheelWriter::new(&tag, &self.out, &self.metadata21, &tags)?;

match self.project_layout {
ProjectLayout::Mixed {
ref python_module,
ref extension_name,
..
} => {
write_python_part(&mut builder, python_module, extension_name)
write_python_part(&mut writer, python_module, extension_name)
.context("Failed to add the python module to the package")?;
}
ProjectLayout::PureRust { .. } => {}
Expand All @@ -459,9 +474,11 @@ impl BuildContext {
let bin_name = artifact
.file_name()
.expect("Couldn't get the filename from the binary produced by cargo");
write_bin(&mut builder, artifact, &self.metadata21, bin_name)?;
write_bin(&mut writer, artifact, &self.metadata21, bin_name)?;

let wheel_path = builder.finish()?;
self.add_pth(&mut writer)?;

let wheel_path = writer.finish()?;
Ok((wheel_path, "py3".to_string()))
}

Expand Down
10 changes: 8 additions & 2 deletions src/build_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,12 @@ impl Default for BuildOptions {

impl BuildOptions {
/// Tries to fill the missing metadata for a BuildContext by querying cargo and python
pub fn into_build_context(self, release: bool, strip: bool) -> Result<BuildContext> {
pub fn into_build_context(
self,
release: bool,
strip: bool,
editable: bool,
) -> Result<BuildContext> {
let manifest_file = &self.manifest_path;
if !manifest_file.exists() {
let current_dir =
Expand Down Expand Up @@ -303,6 +308,7 @@ impl BuildOptions {
interpreter,
cargo_metadata,
universal2,
editable,
})
}
}
Expand Down Expand Up @@ -789,7 +795,7 @@ mod test {
let mut options = BuildOptions::default();
options.cargo_extra_args.push("--features log".to_string());
options.bindings = Some("bin".to_string());
let context = options.into_build_context(false, false).unwrap();
let context = options.into_build_context(false, false, false).unwrap();
assert_eq!(context.cargo_extra_args, vec!["--features", "log"])
}

Expand Down
2 changes: 1 addition & 1 deletion src/develop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ pub fn develop(
universal2: false,
};

let build_context = build_options.into_build_context(release, strip)?;
let build_context = build_options.into_build_context(release, strip, false)?;

let interpreter = PythonInterpreter::check_executable(python, &target, &build_context.bridge)?
.ok_or_else(|| {
Expand Down
12 changes: 8 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,9 @@ enum Pep517Command {
/// Strip the library for minimum file size
#[structopt(long)]
strip: bool,
/// Build editable wheels
#[structopt(long)]
editable: bool,
},
/// The implementation of build_sdist
#[structopt(name = "write-sdist")]
Expand Down Expand Up @@ -356,7 +359,7 @@ fn pep517(subcommand: Pep517Command) -> Result<()> {
build_options.interpreter.as_ref(),
Some(version) if version.len() == 1
));
let context = build_options.into_build_context(true, strip)?;
let context = build_options.into_build_context(true, strip, false)?;

// Since afaik all other PEP 517 backends also return linux tagged wheels, we do so too
let tags = match context.bridge {
Expand Down Expand Up @@ -384,8 +387,9 @@ fn pep517(subcommand: Pep517Command) -> Result<()> {
Pep517Command::BuildWheel {
build_options,
strip,
editable,
} => {
let build_context = build_options.into_build_context(true, strip)?;
let build_context = build_options.into_build_context(true, strip, editable)?;
let wheels = build_context.build_wheels()?;
assert_eq!(wheels.len(), 1);
println!("{}", wheels[0].0.to_str().unwrap());
Expand Down Expand Up @@ -507,7 +511,7 @@ fn run() -> Result<()> {
strip,
no_sdist,
} => {
let build_context = build.into_build_context(release, strip)?;
let build_context = build.into_build_context(release, strip, false)?;
if !no_sdist {
build_context.build_source_distribution()?;
}
Expand All @@ -521,7 +525,7 @@ fn run() -> Result<()> {
no_strip,
no_sdist,
} => {
let build_context = build.into_build_context(!debug, !no_strip)?;
let build_context = build.into_build_context(!debug, !no_strip, false)?;

if !build_context.release {
eprintln!("⚠️ Warning: You're publishing debug wheels");
Expand Down
23 changes: 23 additions & 0 deletions src/module_writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,29 @@ impl WheelWriter {
Ok(builder)
}

/// Add a pth file to wheel root for editable installs
pub fn add_pth(
&mut self,
project_layout: &ProjectLayout,
metadata21: &Metadata21,
) -> Result<()> {
match project_layout {
ProjectLayout::Mixed {
ref python_module, ..
} => {
let absolute_path = python_module.canonicalize()?;
if let Some(python_path) = absolute_path.parent().and_then(|p| p.to_str()) {
let name = metadata21.get_distribution_escaped();
self.add_bytes(format!("{}.pth", name), python_path.as_bytes())?;
} else {
println!("⚠ source code path contains non-Unicode sequences, editable installs may not work.");
}
}
ProjectLayout::PureRust { .. } => {}
}
Ok(())
}

/// Creates the record file and finishes the zip
pub fn finish(mut self) -> Result<PathBuf, io::Error> {
let compression_method = if cfg!(feature = "faster-tests") {
Expand Down
6 changes: 3 additions & 3 deletions tests/common/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub fn abi3_without_version() -> Result<()> {
];

let options = BuildOptions::from_iter_safe(cli)?;
let result = options.into_build_context(false, cfg!(feature = "faster-tests"));
let result = options.into_build_context(false, cfg!(feature = "faster-tests"), false);
if let Err(err) = result {
assert_eq!(err.to_string(),
"You have selected the `abi3` feature but not a minimum version (e.g. the `abi3-py36` feature). \
Expand All @@ -40,7 +40,7 @@ pub fn pyo3_no_extension_module() -> Result<()> {

let options = BuildOptions::from_iter_safe(cli)?;
let result = options
.into_build_context(false, cfg!(feature = "faster-tests"))?
.into_build_context(false, cfg!(feature = "faster-tests"), false)?
.build_wheels();
if let Err(err) = result {
if !(err
Expand Down Expand Up @@ -71,7 +71,7 @@ pub fn locked_doesnt_build_without_cargo_lock() -> Result<()> {
"-i=python",
];
let options = BuildOptions::from_iter_safe(cli)?;
let result = options.into_build_context(false, cfg!(feature = "faster-tests"));
let result = options.into_build_context(false, cfg!(feature = "faster-tests"), false);
if let Err(err) = result {
let err_string = err
.source()
Expand Down
4 changes: 2 additions & 2 deletions tests/common/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub fn test_integration(package: impl AsRef<Path>, bindings: Option<String>) ->

let options: BuildOptions = BuildOptions::from_iter_safe(cli)?;

let build_context = options.into_build_context(false, cfg!(feature = "faster-tests"))?;
let build_context = options.into_build_context(false, cfg!(feature = "faster-tests"), false)?;
let wheels = build_context.build_wheels()?;

let test_name = package
Expand Down Expand Up @@ -184,7 +184,7 @@ pub fn test_integration_conda(package: impl AsRef<Path>, bindings: Option<String

let options = BuildOptions::from_iter_safe(cli)?;

let build_context = options.into_build_context(false, cfg!(feature = "faster-tests"))?;
let build_context = options.into_build_context(false, cfg!(feature = "faster-tests"), false)?;
let wheels = build_context.build_wheels()?;

let mut conda_wheels: Vec<(PathBuf, PathBuf)> = vec![];
Expand Down
4 changes: 2 additions & 2 deletions tests/common/other.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ pub fn test_musl() -> Result<bool> {
"linux",
])?;

let build_context = options.into_build_context(false, cfg!(feature = "faster-tests"))?;
let build_context = options.into_build_context(false, cfg!(feature = "faster-tests"), false)?;
let built_lib = build_context
.manifest_path
.parent()
Expand Down Expand Up @@ -91,7 +91,7 @@ pub fn test_workspace_cargo_lock() -> Result<()> {
"linux",
])?;

let build_context = options.into_build_context(false, cfg!(feature = "faster-tests"))?;
let build_context = options.into_build_context(false, cfg!(feature = "faster-tests"), false)?;
let source_distribution = build_context.build_source_distribution()?;
assert!(source_distribution.is_some());

Expand Down

0 comments on commit df6c586

Please sign in to comment.