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

Stable Rust #969

Merged
merged 10 commits into from
Jun 21, 2020
Merged
Show file tree
Hide file tree
Changes from 9 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
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: nightly
toolchain: stable
default: true
- run: rustup set default-host ${{ matrix.platform.rust-target }}
- name: Build without default features
Expand Down
15 changes: 10 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,28 @@ jobs:
python: "3.7"
- name: Python 3.8
python: "3.8"
# Run clippy and rustfmt
env: RUN_LINT=1
- name: Python 3.9-dev
python: "3.9-dev"
- name: Minimum nightly
- name: Nightly
python: "3.7"
# Keep this synced up with build.rs and ensure that the nightly version does have clippy available
# https://static.rust-lang.org/dist/YYYY-MM-DD/clippy-nightly-x86_64-unknown-linux-gnu.tar.gz exists
env: TRAVIS_RUST_VERSION=nightly-2020-01-21
env: TRAVIS_RUST_VERSION=nightly FEATURES="nightly"
- name: Minimum Stable
python: "3.7"
env: TRAVIS_RUST_VERSION=1.39.0
- name: PyPy3.5 7.0 # Tested via anaconda PyPy (since travis's PyPy version is too old)
python: "3.7"
env: FEATURES="pypy" PATH="$PATH:/opt/anaconda/envs/pypy3/bin"
allow_failures:
- name: Nightly
- python: 3.9-dev

env:
global:
- TRAVIS_RUST_VERSION=nightly
- TRAVIS_RUST_VERSION=stable
- RUST_BACKTRACE=1
- RUN_LINT=0

before_install:
- source ./ci/travis/setup.sh
Expand Down
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]
### Added
- Add FFI definition `PyObject_AsFileDescriptor` [#938](https://github.com/PyO3/pyo3/pull/938)
- Support stable versions of Rust (>=1.39). [#969](https://github.com/PyO3/pyo3/pull/969)
- Add FFI definition `PyObject_AsFileDescriptor`. [#938](https://github.com/PyO3/pyo3/pull/938)
- Add `PyByteArray::data`, `PyByteArray::as_bytes`, and `PyByteArray::as_bytes_mut`. [#967](https://github.com/PyO3/pyo3/pull/967)
- Add `Py::borrow`, `Py::borrow_mut`, `Py::try_borrow`, and `Py::try_borrow_mut` for accessing `#[pyclass]` values. [#976](https://github.com/PyO3/pyo3/pull/976)

Expand Down
8 changes: 5 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@ unindent = { version = "0.1.4", optional = true }
[dev-dependencies]
assert_approx_eq = "1.1.0"
trybuild = "1.0.23"

[build-dependencies]
version_check = "0.9.1"
rustversion = "1.0"

[features]
default = ["macros"]
macros = ["ctor", "indoc", "inventory", "paste", "pyo3cls", "unindent"]
# For CI
all-stable = ["default", "num-bigint", "num-complex"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this feature is just for convenience in CI scripts, maybe it's better to code it into the CI scripts instead of making this user-facing feature?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

# Optimizes PyObject to Vec conversion and so on.
nightly = []

# this is no longer needed internally, but setuptools-rust assumes this feature
python3 = []
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ fmt:

clippy:
@touch src/lib.rs # Touching file to ensure that cargo clippy will re-check the project
cargo clippy --all-features --all-targets -- \
cargo clippy --features=all-stable --tests -- \
$(addprefix -D ,${CLIPPY_LINTS_TO_DENY})
for example in examples/*; do (cd $$example/; cargo clippy) || exit 1; done

Expand Down
7 changes: 2 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
[![Actions Status](https://github.com/PyO3/pyo3/workflows/Test/badge.svg)](https://github.com/PyO3/pyo3/actions)
[![codecov](https://codecov.io/gh/PyO3/pyo3/branch/master/graph/badge.svg)](https://codecov.io/gh/PyO3/pyo3)
[![crates.io](http://meritbadge.herokuapp.com/pyo3)](https://crates.io/crates/pyo3)
[![minimum rustc 1.39](https://img.shields.io/badge/rustc-1.39+-blue.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

[![Join the dev chat](https://img.shields.io/gitter/room/nwjs/nw.js.svg)](https://gitter.im/PyO3/Lobby)

[Rust](http://www.rust-lang.org/) bindings for [Python](https://www.python.org/). This includes running and interacting with Python code from a Rust binary, as well as writing native Python modules.
Expand All @@ -16,11 +17,7 @@ A comparison with rust-cpython can be found [in the guide](https://pyo3.rs/maste

## Usage

PyO3 supports Python 3.5 and up. The minimum required Rust version is 1.42.0-nightly 2020-01-21.

If you have never used nightly Rust, the official guide has
[a great section](https://doc.rust-lang.org/book/appendix-07-nightly-rust.html#rustup-and-the-role-of-rust-nightly)
about installing it.
PyO3 supports Python 3.5 and up. The minimum required Rust version is 1.39.0.

PyPy is also supported (via cpyext) for Python 3.5 only, targeted PyPy version is 7.0.0.
Please refer to the [pypy section in the guide](https://pyo3.rs/master/pypy.html).
Expand Down
40 changes: 3 additions & 37 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,6 @@ use std::{
process::{Command, Stdio},
str::FromStr,
};
use version_check::{Channel, Date, Version};

/// Specifies the minimum nightly version needed to compile pyo3.
/// Keep this synced up with the travis ci config,
/// But note that this is the rustc version which can be lower than the nightly version
const MIN_DATE: &str = "2020-01-20";
const MIN_VERSION: &str = "1.42.0-nightly";

const PY3_MIN_MINOR: u8 = 5;
const CFG_KEY: &str = "py_sys_config";
Expand Down Expand Up @@ -76,8 +69,8 @@ impl FromStr for PythonInterpreterKind {
type Err = Box<dyn std::error::Error>;
fn from_str(s: &str) -> Result<Self> {
match s {
"CPython" => Ok(Self::CPython),
"PyPy" => Ok(Self::PyPy),
"CPython" => Ok(PythonInterpreterKind::CPython),
"PyPy" => Ok(PythonInterpreterKind::PyPy),
_ => Err(format!("Invalid interpreter: {}", s).into()),
}
}
Expand Down Expand Up @@ -302,7 +295,7 @@ fn run_python_script(interpreter: &Path, script: &str) -> Result<String> {
);
}
}
Ok(ok) if !ok.status.success() => bail!("Python script failed: {}"),
Ok(ref ok) if !ok.status.success() => bail!("Python script failed: {}"),
Ok(ok) => Ok(String::from_utf8(ok.stdout)?),
}
}
Expand Down Expand Up @@ -567,34 +560,7 @@ fn check_target_architecture(interpreter_config: &InterpreterConfig) -> Result<(
Ok(())
}

fn check_rustc_version() -> Result<()> {
let channel = Channel::read().ok_or("Failed to determine rustc channel")?;
if !channel.supports_features() {
bail!("PyO3 requires a nightly or dev version of Rust.");
}

let actual_version = Version::read().ok_or("Failed to determine the rustc version")?;
if !actual_version.at_least(MIN_VERSION) {
bail!(
"PyO3 requires at least rustc {}, while the current version is {}",
MIN_VERSION,
actual_version
)
}

let actual_date = Date::read().ok_or("Failed to determine the rustc date")?;
if !actual_date.at_least(MIN_DATE) {
bail!(
"PyO3 requires at least rustc {}, while the current rustc date is {}",
MIN_DATE,
actual_date
)
}
Ok(())
}

fn main() -> Result<()> {
check_rustc_version()?;
// 1. Setup cfg variables so we can do conditional compilation in this library based on the
// python interpeter's compilation flags. This is necessary for e.g. matching the right unicode
// and threading interfaces. First check if we're cross compiling, if so, we cannot run the
Expand Down
2 changes: 1 addition & 1 deletion ci/travis/guide.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ mdbook build -d ../target/guide guide

# Build the doc
# This builds the book in target/doc
cargo doc --all-features --no-deps
cargo doc --features=all-stable --no-deps
echo "<meta http-equiv=refresh content=0;url=pyo3/index.html>" > target/doc/index.html

# Get the lastest tag across all branches
Expand Down
2 changes: 1 addition & 1 deletion ci/travis/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ set -e
# Use profile=minimal here to skip installing clippy
curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain=$TRAVIS_RUST_VERSION --profile=minimal -y
export PATH=$PATH:$HOME/.cargo/bin
if [ "$TRAVIS_JOB_NAME" = "Minimum nightly" ]; then
if [[ $RUN_LINT == 1 ]]; then
rustup component add clippy
rustup component add rustfmt
fi
Expand Down
2 changes: 1 addition & 1 deletion ci/travis/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ else
PYTHON_SYS_EXECUTABLE="/opt/anaconda/envs/pypy3/bin/pypy3" cargo build;
fi

if [ "$TRAVIS_JOB_NAME" = "Minimum nightly" ]; then
if [[ $RUN_LINT == 1 ]]; then
pip install --pre black==19.3b0
make lint
fi
Expand Down
6 changes: 6 additions & 0 deletions guide/src/advanced.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,9 @@ version = "0.8.1"
extension-module = ["pyo3/extension-module"]
default = ["extension-module"]
```

## `nightly` flag
kngwyu marked this conversation as resolved.
Show resolved Hide resolved

`pyo3/nightly` feature needs nightly compiler, but enables some optimizations as follows:
kngwyu marked this conversation as resolved.
Show resolved Hide resolved
- `FromPyObject` for `Vec` and array is optimized when the object can be `PyBuffer`
kngwyu marked this conversation as resolved.
Show resolved Hide resolved
- `ToBorrowedObject`, used by `PyDict::set_item` or so, is optimized when the taken object is a Python native type.
kngwyu marked this conversation as resolved.
Show resolved Hide resolved
8 changes: 4 additions & 4 deletions guide/src/class.md
Original file line number Diff line number Diff line change
Expand Up @@ -888,12 +888,12 @@ documentation](https://docs.python.org/3/library/stdtypes.html#iterator-types).
Users should be able to define a `#[pyclass]` with or without `#[pymethods]`, while PyO3 needs a
trait with a function that returns all methods. Since it's impossible to make the code generation in
pyclass dependent on whether there is an impl block, we'd need to implement the trait on
`#[pyclass]` and override the implementation in `#[pymethods]`, which is to the best of my knowledge
only possible with the specialization feature, which can't be used on stable.

To escape this we use [inventory](https://github.com/dtolnay/inventory),
`#[pyclass]` and override the implementation in `#[pymethods]`.
To enable this, we use a static registry type provided by [inventory](https://github.com/dtolnay/inventory),
which allows us to collect `impl`s from arbitrary source code by exploiting some binary trick.
See [inventory: how it works](https://github.com/dtolnay/inventory#how-it-works) and `pyo3_derive_backend::py_class` for more details.
Also for `#[pyproto]`, we use a similar, but more task-specific registry and
initialize it by [ctor](https://github.com/mmastrac/rust-ctor) crate.
kngwyu marked this conversation as resolved.
Show resolved Hide resolved

Specifically, the following implementation is generated:

Expand Down
2 changes: 1 addition & 1 deletion guide/src/rust_cpython.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ This chapter is based on the discussion in [PyO3/pyo3#55](https://github.com/PyO

## Macros

While rust-cpython has a macro based dsl for declaring modules and classes, PyO3 uses proc macros and specialization. PyO3 also doesn't change your struct and functions so you can still use them as normal Rust functions. The disadvantage is that specialization currently only works on nightly.
While rust-cpython has a macro based dsl for declaring modules and classes, PyO3 uses proc macros. PyO3 also doesn't change your struct and functions so you can still use them as normal Rust functions.
kngwyu marked this conversation as resolved.
Show resolved Hide resolved

**rust-cpython**

Expand Down
19 changes: 11 additions & 8 deletions pyo3-derive-backend/src/pyfunction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,22 +179,25 @@ pub fn parse_name_attribute(attrs: &mut Vec<syn::Attribute>) -> syn::Result<Opti
_ => true,
});

match &*name_attrs {
[] => Ok(None),
[(syn::Lit::Str(s), span)] => {
if 1 < name_attrs.len() {
return Err(syn::Error::new(
name_attrs[0].1,
"#[name] can not be specified multiple times",
));
}

match name_attrs.get(0) {
Some((syn::Lit::Str(s), span)) => {
let mut ident: syn::Ident = s.parse()?;
// This span is the whole attribute span, which is nicer for reporting errors.
ident.set_span(*span);
Ok(Some(ident))
}
[(_, span)] => Err(syn::Error::new(
Some((_, span)) => Err(syn::Error::new(
*span,
"Expected string literal for #[name] argument",
)),
[(_, span), ..] => Err(syn::Error::new(
*span,
"#[name] can not be specified multiple times",
)),
None => Ok(None),
}
}

Expand Down
16 changes: 9 additions & 7 deletions pyo3-derive-backend/src/pymethod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -512,10 +512,11 @@ fn impl_arg_param(
};
if let syn::Type::Reference(tref) = ty {
let (tref, mut_) = tref_preprocess(tref);
let as_deref = if mut_.is_some() {
quote! { as_deref_mut }
// To support Rustc 1.39.0, we don't use as_deref here...
let tmp_as_deref = if mut_.is_some() {
quote! { _tmp.as_mut().map(std::ops::DerefMut::deref_mut) }
} else {
quote! { as_deref }
quote! { _tmp.as_ref().map(std::ops::Deref::deref) }
};
// Get Option<&T> from Option<PyRef<T>>
quote! {
Expand All @@ -525,7 +526,7 @@ fn impl_arg_param(
},
None => #default,
};
let #arg_name = _tmp.#as_deref();
let #arg_name = #tmp_as_deref;
}
} else {
quote! {
Expand Down Expand Up @@ -731,8 +732,9 @@ pub(crate) fn impl_py_getter_def(

/// Split an argument of pyo3::Python from the front of the arg list, if present
fn split_off_python_arg<'a>(args: &'a [FnArg<'a>]) -> (Option<&FnArg>, &[FnArg]) {
match args {
[py, rest @ ..] if utils::if_type_is_python(&py.ty) => (Some(py), rest),
rest => (None, rest),
if args.get(0).map(|py| utils::if_type_is_python(&py.ty)) == Some(true) {
(Some(&args[0]), &args[1..])
} else {
(None, args)
}
}
20 changes: 20 additions & 0 deletions src/conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ pub trait ToBorrowedObject: ToPyObject {
F: FnOnce(*mut ffi::PyObject) -> R;
}

#[cfg(feature = "nightly")]
impl<T> ToBorrowedObject for T
where
T: ToPyObject,
Expand All @@ -115,6 +116,25 @@ where
}
}

#[cfg(not(feature = "nightly"))]
impl<T> ToBorrowedObject for T
where
T: ToPyObject,
{
fn with_borrowed_ptr<F, R>(&self, py: Python, f: F) -> R
where
F: FnOnce(*mut ffi::PyObject) -> R,
{
let ptr = self.to_object(py).into_ptr();
let result = f(ptr);
unsafe {
ffi::Py_XDECREF(ptr);
}
result
}
}

#[cfg(feature = "nightly")]
impl<T> ToBorrowedObject for T
where
T: ToPyObject + AsPyPointer,
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![feature(specialization)]
#![cfg_attr(feature = "nightly", feature(specialization))]
#![allow(clippy::missing_safety_doc)] // FIXME (#698)

//! Rust bindings to the Python interpreter.
Expand Down
Loading