diff --git a/.cargo/config b/.cargo/config index f54d6312..e8b36b75 100644 --- a/.cargo/config +++ b/.cargo/config @@ -1,6 +1,3 @@ -[alias] -xtask = "run --package xtask --" - [target.'cfg(feature = "cargo-clippy")'] rustflags = [ # Lints to enforce in CI @@ -11,6 +8,7 @@ rustflags = [ "-Dclippy::filter_map_next", "-Dclippy::flat_map_option", "-Dclippy::let_unit_value", + "-Dclippy::manual_assert", "-Dclippy::manual_ok_or", "-Dclippy::todo", "-Dclippy::unnecessary_wraps", diff --git a/.netlify/build.sh b/.netlify/build.sh index 74c8bca1..215ee8c8 100755 --- a/.netlify/build.sh +++ b/.netlify/build.sh @@ -53,7 +53,7 @@ mv target/guide netlify_build/main/ ## Build public docs -cargo xtask doc +nox -s docs mv target/doc netlify_build/main/doc/ echo "" > netlify_build/main/doc/index.html @@ -61,7 +61,7 @@ echo "" > netlify_build/main/doc/in ## Build internal docs echo "
⚠️ Internal Docs ⚠️ Not Public API 👉 Official Docs Here
" > netlify_build/banner.html -RUSTDOCFLAGS="--html-before-content netlify_build/banner.html" cargo xtask doc --internal +RUSTDOCFLAGS="--html-before-content netlify_build/banner.html" nox -s docs -- nightly internal rm netlify_build/banner.html mkdir -p netlify_build/internal diff --git a/Cargo.toml b/Cargo.toml index 651d4157..57002434 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -186,7 +186,6 @@ members = [ "pyo3-macros-backend", "pytests", "examples", - "xtask" ] [package.metadata.docs.rs] diff --git a/Contributing.md b/Contributing.md index a1fd31a3..c6d29e2d 100644 --- a/Contributing.md +++ b/Contributing.md @@ -51,7 +51,7 @@ There are some specific areas of focus where help is currently needed for the do You can build the docs (including all features) with ```shell -cargo xtask doc --open +nox -s docs -- open ``` #### Doctests @@ -95,8 +95,10 @@ Tests run with all supported Python versions with the latest stable Rust compile If you are adding a new feature, you should add it to the `full` feature in our *Cargo.toml** so that it is tested in CI. You can run these tests yourself with -```cargo xtask ci``` -See [its documentation](https://github.com/PyO3/pyo3/tree/main/xtask#readme) for more commands you can run. +```nox``` +and +```nox -l``` +lists further commands you can run. ### Documenting changes @@ -145,7 +147,7 @@ You can view what code is and isn't covered by PyO3's tests. We aim to have 100% - First, generate a `lcov.info` file with ```shell -cargo xtask coverage +nox -s coverage ``` You can install an IDE plugin to view the coverage. For example, if you use VSCode: - Add the [coverage-gutters](https://marketplace.visualstudio.com/items?itemName=ryanluker.vscode-coverage-gutters) plugin. diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml deleted file mode 100644 index bdd52175..00000000 --- a/xtask/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "xtask" -version = "0.1.0" -edition = "2018" -publish = false - -[[bin]] -name = "xtask" - -[dependencies] -anyhow = "1.0.51" - -# Clap 3 requires MSRV 1.54 -structopt = { version = "0.3", default-features = false } -clap = { version = "2" } diff --git a/xtask/README.md b/xtask/README.md deleted file mode 100644 index 68d078e5..00000000 --- a/xtask/README.md +++ /dev/null @@ -1,23 +0,0 @@ -## Commands to test PyO3. - -To run these commands, you should be in PyO3's root directory, and run (for example) `cargo xtask ci`. - -``` -USAGE: - xtask.exe - -FLAGS: - -h, --help Prints help information - -V, --version Prints version information - -SUBCOMMANDS: - ci Runs everything - clippy Runs `clippy`, denying all warnings - coverage Runs `cargo llvm-cov` for the PyO3 codebase - default Only runs the fast things (this is used if no command is specified) - doc Attempts to render the documentation - fmt Checks Rust and Python code formatting with `rustfmt` and `black` - help Prints this message or the help of the given subcommand(s) - test Runs various variations on `cargo test` - test-py Runs the tests in examples/ and pytests/ -``` \ No newline at end of file diff --git a/xtask/src/cli.rs b/xtask/src/cli.rs deleted file mode 100644 index ec674ec6..00000000 --- a/xtask/src/cli.rs +++ /dev/null @@ -1,216 +0,0 @@ -use crate::utils::*; -use anyhow::{ensure, Result}; -use std::io; -use std::process::{Command, Output}; -use std::time::Instant; -use structopt::StructOpt; - -pub const MSRV: &str = "1.56"; - -#[derive(StructOpt)] -pub enum Subcommand { - /// Only runs the fast things (this is used if no command is specified) - Default, - /// Runs everything - Ci, - /// Checks Rust and Python code formatting with `rustfmt` and `black` - Fmt, - /// Runs `clippy`, denying all warnings. - Clippy, - /// Attempts to render the documentation. - Doc(DocOpts), - /// Runs various variations on `cargo test` - Test, - /// Runs the tests in examples/ and pytests/ - TestPy, -} - -impl Default for Subcommand { - fn default() -> Self { - Self::Default - } -} - -#[derive(StructOpt)] -pub struct DocOpts { - /// Whether to run the docs using nightly rustdoc - #[structopt(long)] - pub stable: bool, - /// Whether to open the docs after rendering. - #[structopt(long)] - pub open: bool, - /// Whether to show the private and hidden API. - #[structopt(long)] - pub internal: bool, -} - -impl Default for DocOpts { - fn default() -> Self { - Self { - stable: true, - open: false, - internal: false, - } - } -} - -impl Subcommand { - pub fn execute(self) -> Result<()> { - print_metadata()?; - - let start = Instant::now(); - - match self { - Subcommand::Default => { - crate::fmt::rust::run()?; - crate::clippy::run()?; - crate::test::run()?; - crate::doc::run(DocOpts::default())?; - } - Subcommand::Ci => { - let installed = Installed::new()?; - crate::fmt::rust::run()?; - if installed.black { - crate::fmt::python::run()?; - } else { - Installed::warn_black() - }; - crate::clippy::run()?; - crate::test::run()?; - crate::doc::run(DocOpts::default())?; - if installed.nox { - crate::pytests::run(None)?; - } else { - Installed::warn_nox() - }; - installed.assert()? - } - - Subcommand::Doc(opts) => crate::doc::run(opts)?, - Subcommand::Fmt => { - crate::fmt::rust::run()?; - crate::fmt::python::run()?; - } - Subcommand::Clippy => crate::clippy::run()?, - Subcommand::TestPy => crate::pytests::run(None)?, - Subcommand::Test => crate::test::run()?, - }; - - let dt = start.elapsed().as_secs(); - let minutes = dt / 60; - let seconds = dt % 60; - println!("\nxtask finished in {}m {}s.", minutes, seconds); - - Ok(()) - } -} - -/// Run a command as a child process, inheriting stdin, stdout and stderr. -pub fn run(command: &mut Command) -> Result<()> { - let command_str = format!("{:?}", command); - let github_actions = std::env::var_os("GITHUB_ACTIONS").is_some(); - if github_actions { - println!("::group::Running: {}", command_str); - } else { - println!("Running: {}", command_str); - } - - let status = command.spawn()?.wait()?; - - ensure! { - status.success(), - "process did not run successfully ({exit}): {command}", - exit = match status.code() { - Some(code) => format!("exit code {}", code), - None => "terminated by signal".into(), - }, - command = command_str, - }; - - if github_actions { - println!("::endgroup::") - } - Ok(()) -} - -/// Like `run`, but does not inherit stdin, stdout and stderr. -pub fn run_with_output(command: &mut Command) -> Result { - let command_str = format!("{:?}", command); - - println!("Running: {}", command_str); - - let output = command.output()?; - - ensure! { - output.status.success(), - "process did not run successfully ({exit}): {command}:\n{stderr}", - exit = match output.status.code() { - Some(code) => format!("exit code {}", code), - None => "terminated by signal".into(), - }, - command = command_str, - stderr = String::from_utf8_lossy(&output.stderr) - }; - - Ok(output) -} - -#[derive(Copy, Clone, Debug)] -pub struct Installed { - pub nox: bool, - pub black: bool, -} - -impl Installed { - pub fn new() -> anyhow::Result { - Ok(Self { - nox: Self::nox()?, - black: Self::black()?, - }) - } - - pub fn nox() -> anyhow::Result { - let output = std::process::Command::new("nox").arg("--version").output(); - match output { - Ok(_) => Ok(true), - Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(false), - Err(other) => Err(other.into()), - } - } - - pub fn warn_nox() { - eprintln!("Skipping: formatting Python code, because `nox` was not found"); - } - - pub fn black() -> anyhow::Result { - let output = std::process::Command::new("black") - .arg("--version") - .output(); - match output { - Ok(_) => Ok(true), - Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(false), - Err(other) => Err(other.into()), - } - } - - pub fn warn_black() { - eprintln!("Skipping: Python code formatting, because `black` was not found."); - } - - pub fn assert(&self) -> anyhow::Result<()> { - if self.nox && self.black { - Ok(()) - } else { - let mut err = - String::from("\n\nxtask was unable to run all tests due to some missing programs:"); - if !self.black { - err.push_str("\n`black` was not installed. (`pip install black`)"); - } - if !self.nox { - err.push_str("\n`nox` was not installed. (`pip install nox`)"); - } - - Err(anyhow::anyhow!(err)) - } - } -} diff --git a/xtask/src/clippy.rs b/xtask/src/clippy.rs deleted file mode 100644 index eec5f5fd..00000000 --- a/xtask/src/clippy.rs +++ /dev/null @@ -1,25 +0,0 @@ -use crate::cli; -use std::process::Command; - -pub fn run() -> anyhow::Result<()> { - cli::run( - Command::new("cargo") - .arg("clippy") - .arg("--features=full") - .arg("--all-targets") - .arg("--workspace") - .arg("--") - .arg("-Dwarnings"), - )?; - cli::run( - Command::new("cargo") - .arg("clippy") - .arg("--all-targets") - .arg("--workspace") - .arg("--features=abi3,full") - .arg("--") - .arg("-Dwarnings"), - )?; - - Ok(()) -} diff --git a/xtask/src/doc.rs b/xtask/src/doc.rs deleted file mode 100644 index cde2c882..00000000 --- a/xtask/src/doc.rs +++ /dev/null @@ -1,42 +0,0 @@ -use crate::cli; -use crate::cli::DocOpts; -use std::process::Command; -//--cfg docsrs --Z unstable-options --document-hidden-items - -pub fn run(opts: DocOpts) -> anyhow::Result<()> { - let mut flags = Vec::new(); - - if !opts.stable { - flags.push("--cfg docsrs"); - } - if opts.internal { - flags.push("--Z unstable-options"); - flags.push("--document-hidden-items"); - } - flags.push("-Dwarnings"); - - std::env::set_var("RUSTDOCFLAGS", flags.join(" ")); - cli::run( - Command::new(concat!(env!("CARGO_HOME"), "/bin/cargo")) - .args(if opts.stable { None } else { Some("+nightly") }) - .arg("doc") - .arg("--lib") - .arg("--no-default-features") - .arg("--features=full") - .arg("--no-deps") - .arg("--workspace") - .args(if opts.internal { - &["--document-private-items"][..] - } else { - &["--exclude=pyo3-macros", "--exclude=pyo3-macros-backend"][..] - }) - .args(if opts.stable { - &[][..] - } else { - &["-Z", "unstable-options", "-Z", "rustdoc-scrape-examples"][..] - }) - .args(if opts.open { Some("--open") } else { None }), - )?; - - Ok(()) -} diff --git a/xtask/src/fmt.rs b/xtask/src/fmt.rs deleted file mode 100644 index 8bc74524..00000000 --- a/xtask/src/fmt.rs +++ /dev/null @@ -1,23 +0,0 @@ -pub mod rust { - use crate::cli; - use std::process::Command; - pub fn run() -> anyhow::Result<()> { - cli::run( - Command::new("cargo") - .arg("fmt") - .arg("--all") - .arg("--") - .arg("--check"), - )?; - Ok(()) - } -} - -pub mod python { - use crate::cli; - use std::process::Command; - pub fn run() -> anyhow::Result<()> { - cli::run(Command::new("black").arg(".").arg("--check"))?; - Ok(()) - } -} diff --git a/xtask/src/main.rs b/xtask/src/main.rs deleted file mode 100644 index 42174268..00000000 --- a/xtask/src/main.rs +++ /dev/null @@ -1,23 +0,0 @@ -use clap::ErrorKind::MissingArgumentOrSubcommand; -use structopt::StructOpt; - -pub mod cli; -pub mod clippy; -pub mod doc; -pub mod fmt; -pub mod pytests; -pub mod test; -pub mod utils; - -fn main() -> anyhow::Result<()> { - // Avoid spewing backtraces all over the command line - // For some reason this is automatically enabled on nightly compilers... - std::env::set_var("RUST_LIB_BACKTRACE", "0"); - - match cli::Subcommand::from_args_safe() { - Ok(c) => c.execute()?, - Err(e) if e.kind == MissingArgumentOrSubcommand => cli::Subcommand::default().execute()?, - Err(e) => return Err(e.into()), - } - Ok(()) -} diff --git a/xtask/src/pytests.rs b/xtask/src/pytests.rs deleted file mode 100644 index 78744c69..00000000 --- a/xtask/src/pytests.rs +++ /dev/null @@ -1,27 +0,0 @@ -use crate::cli; -use anyhow::Result; -use std::{path::Path, process::Command}; - -pub fn run<'a>(env: impl IntoIterator + Copy) -> Result<()> { - cli::run( - Command::new("nox") - .arg("--non-interactive") - .arg("-f") - .arg(Path::new("pytests").join("noxfile.py")) - .envs(env), - )?; - - for entry in std::fs::read_dir("examples")? { - let path = entry?.path(); - if path.is_dir() && path.join("noxfile.py").exists() { - cli::run( - Command::new("nox") - .arg("--non-interactive") - .arg("-f") - .arg(path.join("noxfile.py")) - .envs(env), - )?; - } - } - Ok(()) -} diff --git a/xtask/src/test.rs b/xtask/src/test.rs deleted file mode 100644 index b85f3e4a..00000000 --- a/xtask/src/test.rs +++ /dev/null @@ -1,81 +0,0 @@ -use crate::cli::{self, MSRV}; -use std::process::Command; - -pub fn run() -> anyhow::Result<()> { - cli::run( - Command::new("cargo") - .arg("test") - .arg("--lib") - .arg("--no-default-features") - .arg("--tests") - .arg("--quiet"), - )?; - - cli::run( - Command::new("cargo") - .arg("test") - .arg("--no-default-features") - .arg("--features=full") - .arg("--quiet"), - )?; - - cli::run( - Command::new("cargo") - .arg("test") - .arg("--no-default-features") - .arg("--features=abi3,full") - .arg("--quiet"), - )?; - - // If the MSRV toolchain is not installed, this will install it - cli::run( - Command::new("rustup") - .arg("toolchain") - .arg("install") - .arg(MSRV), - )?; - - // Test MSRV - cli::run( - Command::new(concat!(env!("CARGO_HOME"), "/bin/cargo")) - .arg(format!("+{}", MSRV)) - .arg("test") - .arg("--no-default-features") - .arg("--features=full,auto-initialize") - .arg("--quiet"), - )?; - - // If the nightly toolchain is not installed, this will install it - cli::run( - Command::new("rustup") - .arg("toolchain") - .arg("install") - .arg("nightly"), - )?; - - cli::run( - Command::new(concat!(env!("CARGO_HOME"), "/bin/cargo")) - .arg("+nightly") - .arg("test") - .arg("--no-default-features") - .arg("--features=full,nightly") - .arg("--quiet"), - )?; - - cli::run( - Command::new("cargo") - .arg("test") - .arg("--manifest-path=pyo3-ffi/Cargo.toml") - .arg("--quiet"), - )?; - - cli::run( - Command::new("cargo") - .arg("test") - .arg("--no-default-features") - .arg("--manifest-path=pyo3-build-config/Cargo.toml") - .arg("--quiet"), - )?; - - Ok(()) -} diff --git a/xtask/src/utils.rs b/xtask/src/utils.rs deleted file mode 100644 index b6941263..00000000 --- a/xtask/src/utils.rs +++ /dev/null @@ -1,34 +0,0 @@ -use anyhow::ensure; -use std::process::Command; - -pub fn get_output(command: &mut Command) -> anyhow::Result { - let output = command.output()?; - ensure! { - output.status.success(), - "process did not run successfully ({exit}): {command:?}", - exit = match output.status.code() { - Some(code) => format!("exit code {}", code), - None => "terminated by signal".into(), - }, - command = command, - }; - Ok(output) -} - -pub fn print_metadata() -> anyhow::Result<()> { - let rustc_output = std::process::Command::new("rustc") - .arg("--version") - .arg("--verbose") - .output()?; - let rustc_version = core::str::from_utf8(&rustc_output.stdout).unwrap(); - println!("Metadata: \n\n{}", rustc_version); - - let py_output = std::process::Command::new("python") - .arg("--version") - .arg("-V") - .output()?; - let py_version = core::str::from_utf8(&py_output.stdout).unwrap(); - println!("{}", py_version); - - Ok(()) -}