commit
7075827a03
|
@ -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
|
||||
|
|
15
.travis.yml
15
.travis.yml
|
@ -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
|
||||
|
|
|
@ -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 `GILOnceCell` to use in situations where `lazy_static` or `once_cell` can deadlock. [#975](https://github.com/PyO3/pyo3/pull/975)
|
||||
- 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)
|
||||
|
|
|
@ -33,13 +33,13 @@ 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"]
|
||||
# Optimizes PyObject to Vec conversion and so on.
|
||||
nightly = []
|
||||
|
||||
# this is no longer needed internally, but setuptools-rust assumes this feature
|
||||
python3 = []
|
||||
|
|
2
Makefile
2
Makefile
|
@ -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="default num-bigint num-complex" --tests -- \
|
||||
$(addprefix -D ,${CLIPPY_LINTS_TO_DENY})
|
||||
for example in examples/*; do (cd $$example/; cargo clippy) || exit 1; done
|
||||
|
||||
|
|
|
@ -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)
|
||||
[![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.
|
||||
|
@ -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).
|
||||
|
|
40
build.rs
40
build.rs
|
@ -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";
|
||||
|
@ -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()),
|
||||
}
|
||||
}
|
||||
|
@ -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)?),
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
|
|
@ -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="default num-bigint num-complex" --no-deps
|
||||
echo "<meta http-equiv=refresh content=0;url=pyo3/index.html>" > target/doc/index.html
|
||||
|
||||
# Get the lastest tag across all branches
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -28,3 +28,9 @@ version = "0.8.1"
|
|||
extension-module = ["pyo3/extension-module"]
|
||||
default = ["extension-module"]
|
||||
```
|
||||
|
||||
## The `nightly` feature
|
||||
|
||||
The `pyo3/nightly` feature needs the nightly Rust compiler. This allows PyO3 to use Rust's unstable specialization feature to apply the following optimizations:
|
||||
- `FromPyObject` for `Vec` and `[T;N]` can perform a `memcpy` when the object is a `PyBuffer`
|
||||
- `ToBorrowedObject` can skip a reference count increase when the provided object is a Python native type.
|
||||
|
|
|
@ -893,12 +893,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 using the [ctor](https://github.com/mmastrac/rust-ctor) crate.
|
||||
|
||||
Specifically, the following implementation is generated:
|
||||
|
||||
|
|
|
@ -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_rules!` 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.
|
||||
|
||||
**rust-cpython**
|
||||
|
||||
|
|
|
@ -153,6 +153,7 @@ Now we add the PyO3 annotations to the trait implementation:
|
|||
impl Model for UserModel {
|
||||
// the previous trait implementation
|
||||
}
|
||||
```
|
||||
|
||||
However, the previous code will not compile. The compilation error is the following one:
|
||||
`error: #[pymethods] cannot be used on trait impl blocks`
|
||||
|
|
|
@ -46,7 +46,7 @@ references is done at runtime using `PyCell`, a scheme very similar to
|
|||
|
||||
## Object types
|
||||
|
||||
### [`PyAny`]
|
||||
### [`PyAny`][PyAny]
|
||||
|
||||
**Represents:** a Python object of unspecified type, restricted to a GIL
|
||||
lifetime. Currently, `PyAny` can only ever occur as a reference, `&PyAny`.
|
||||
|
@ -95,7 +95,7 @@ These types all implement `Deref<Target = PyAny>`, so they all expose the same
|
|||
methods which can be found on `PyAny`.
|
||||
|
||||
To see all Python types exposed by `PyO3` you should consult the
|
||||
[`pyo3::types`] module.
|
||||
[`pyo3::types`][pyo3::types] module.
|
||||
|
||||
**Conversions:**
|
||||
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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! {
|
||||
|
@ -525,7 +526,7 @@ fn impl_arg_param(
|
|||
},
|
||||
None => #default,
|
||||
};
|
||||
let #arg_name = _tmp.#as_deref();
|
||||
let #arg_name = #tmp_as_deref;
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
use crate::buffer;
|
||||
use crate::err::{self, PyDowncastError, PyErr, PyResult};
|
||||
use crate::exceptions;
|
||||
|
@ -261,6 +262,7 @@ impl PySequence {
|
|||
macro_rules! array_impls {
|
||||
($($N:expr),+) => {
|
||||
$(
|
||||
#[cfg(feature = "nightly")]
|
||||
impl<'a, T> FromPyObject<'a> for [T; $N]
|
||||
where
|
||||
T: Copy + Default + FromPyObject<'a>,
|
||||
|
@ -272,6 +274,19 @@ macro_rules! array_impls {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "nightly"))]
|
||||
impl<'a, T> FromPyObject<'a> for [T; $N]
|
||||
where
|
||||
T: Copy + Default + FromPyObject<'a>,
|
||||
{
|
||||
fn extract(obj: &'a PyAny) -> PyResult<Self> {
|
||||
let mut array = [T::default(); $N];
|
||||
extract_sequence_into_slice(obj, &mut array)?;
|
||||
Ok(array)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
impl<'source, T> FromPyObject<'source> for [T; $N]
|
||||
where
|
||||
for<'a> T: Copy + Default + FromPyObject<'a> + buffer::Element,
|
||||
|
@ -300,6 +315,17 @@ array_impls!(
|
|||
26, 27, 28, 29, 30, 31, 32
|
||||
);
|
||||
|
||||
#[cfg(not(feature = "nightly"))]
|
||||
impl<'a, T> FromPyObject<'a> for Vec<T>
|
||||
where
|
||||
T: FromPyObject<'a>,
|
||||
{
|
||||
fn extract(obj: &'a PyAny) -> PyResult<Self> {
|
||||
extract_sequence(obj)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
impl<'a, T> FromPyObject<'a> for Vec<T>
|
||||
where
|
||||
T: FromPyObject<'a>,
|
||||
|
@ -309,6 +335,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
impl<'source, T> FromPyObject<'source> for Vec<T>
|
||||
where
|
||||
for<'a> T: FromPyObject<'a> + buffer::Element + Copy,
|
||||
|
|
|
@ -1,17 +1,22 @@
|
|||
#[test]
|
||||
fn test_compile_errors() {
|
||||
let t = trybuild::TestCases::new();
|
||||
t.compile_fail("tests/ui/invalid_macro_args.rs");
|
||||
t.compile_fail("tests/ui/invalid_property_args.rs");
|
||||
t.compile_fail("tests/ui/invalid_pyclass_args.rs");
|
||||
t.compile_fail("tests/ui/invalid_pymethod_names.rs");
|
||||
t.compile_fail("tests/ui/missing_clone.rs");
|
||||
t.compile_fail("tests/ui/reject_generics.rs");
|
||||
t.compile_fail("tests/ui/wrong_aspyref_lifetimes.rs");
|
||||
// Since the current minimum nightly(2020-01-20) has a different error message,
|
||||
// we skip this test.
|
||||
// TODO(kngwyu): Remove this `if` when we update minimum nightly.
|
||||
if option_env!("TRAVIS_JOB_NAME") != Some("Minimum nightly") {
|
||||
testcase_common(&t);
|
||||
testcase_latest_stable(&t);
|
||||
|
||||
fn testcase_common(t: &trybuild::TestCases) {
|
||||
t.compile_fail("tests/ui/invalid_macro_args.rs");
|
||||
t.compile_fail("tests/ui/invalid_property_args.rs");
|
||||
t.compile_fail("tests/ui/invalid_pyclass_args.rs");
|
||||
t.compile_fail("tests/ui/missing_clone.rs");
|
||||
t.compile_fail("tests/ui/reject_generics.rs");
|
||||
t.compile_fail("tests/ui/wrong_aspyref_lifetimes.rs");
|
||||
t.compile_fail("tests/ui/invalid_pymethod_names.rs");
|
||||
}
|
||||
#[rustversion::since(1.43)]
|
||||
fn testcase_latest_stable(t: &trybuild::TestCases) {
|
||||
t.compile_fail("tests/ui/static_ref.rs");
|
||||
}
|
||||
#[rustversion::before(1.43)]
|
||||
fn testcase_latest_stable(_t: &trybuild::TestCases) {}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
#![feature(concat_idents)]
|
||||
|
||||
use pyo3::ffi::*;
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::types::IntoPyDict;
|
||||
|
||||
|
@ -37,9 +34,9 @@ fn _get_subclasses<'p>(
|
|||
macro_rules! assert_check_exact {
|
||||
($check_func:ident, $obj: expr) => {
|
||||
unsafe {
|
||||
use pyo3::AsPyPointer;
|
||||
use pyo3::{AsPyPointer, ffi::*};
|
||||
assert!($check_func(($obj).as_ptr()) != 0);
|
||||
assert!(concat_idents!($check_func, Exact)(($obj).as_ptr()) != 0);
|
||||
assert!(pyo3::paste::expr!([<$check_func Exact>])(($obj).as_ptr()) != 0);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -47,9 +44,9 @@ macro_rules! assert_check_exact {
|
|||
macro_rules! assert_check_only {
|
||||
($check_func:ident, $obj: expr) => {
|
||||
unsafe {
|
||||
use pyo3::AsPyPointer;
|
||||
use pyo3::{AsPyPointer, ffi::*};
|
||||
assert!($check_func(($obj).as_ptr()) != 0);
|
||||
assert!(concat_idents!($check_func, Exact)(($obj).as_ptr()) == 0);
|
||||
assert!(pyo3::paste::expr!([<$check_func Exact>])(($obj).as_ptr()) == 0);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -2,16 +2,16 @@ error: name not allowed with this attribute
|
|||
--> $DIR/invalid_pymethod_names.rs:10:5
|
||||
|
|
||||
10 | #[name = "num"]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
| ^
|
||||
|
||||
error: #[name] can not be specified multiple times
|
||||
--> $DIR/invalid_pymethod_names.rs:17:5
|
||||
|
|
||||
17 | #[name = "foo"]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
| ^
|
||||
|
||||
error: name not allowed with this attribute
|
||||
--> $DIR/invalid_pymethod_names.rs:24:5
|
||||
|
|
||||
24 | #[name = "makenew"]
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
| ^
|
||||
|
|
Loading…
Reference in New Issue