Merge #3208
3208: bump msrv to 1.56 r=davidhewitt a=davidhewitt The MSRV changes from #3204, plus a commit which should hopefully make CI pass. With luck this is mergeable and resolves CI pain while we decide what to do about the Python version. Co-authored-by: Adam Reichold <adam.reichold@t-online.de> Co-authored-by: David Hewitt <1939362+davidhewitt@users.noreply.github.com>
This commit is contained in:
commit
3332f31339
|
@ -3,10 +3,6 @@ xtask = "run --package xtask --"
|
|||
|
||||
[target.'cfg(feature = "cargo-clippy")']
|
||||
rustflags = [
|
||||
# TODO: remove these allows once msrv increased from 1.48
|
||||
"-Aclippy::iter_kv_map",
|
||||
"-Aclippy::needless_borrow",
|
||||
"-Aclippy::uninlined_format_args",
|
||||
# Lints to enforce in CI
|
||||
"-Dclippy::checked_conversions",
|
||||
"-Dclippy::dbg_macro",
|
||||
|
@ -15,7 +11,6 @@ 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",
|
||||
|
|
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
|
@ -201,7 +201,3 @@ jobs:
|
|||
# TODO: this is a hack to workaround compile_error! warnings about auto-initialize on PyPy
|
||||
# Once cargo's `resolver = "2"` is stable (~ MSRV Rust 1.52), remove this.
|
||||
PYO3_CI: 1
|
||||
# This is a hack to make CARGO_PRIMARY_PACKAGE always set even for the
|
||||
# msrv job. MSRV is currently 1.48, but CARGO_PRIMARY_PACKAGE only came in
|
||||
# 1.49.
|
||||
CARGO_PRIMARY_PACKAGE: 1
|
||||
|
|
42
.github/workflows/ci.yml
vendored
42
.github/workflows/ci.yml
vendored
|
@ -34,6 +34,32 @@ jobs:
|
|||
- name: Check rust formatting (rustfmt)
|
||||
run: nox -s fmt-rust
|
||||
|
||||
check-msrv:
|
||||
needs: [fmt]
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref != 'refs/heads/main'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
toolchain: 1.56.0
|
||||
targets: x86_64-unknown-linux-gnu
|
||||
components: clippy,rust-src
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
architecture: "x64"
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
key: check-msrv-1.56.0
|
||||
continue-on-error: true
|
||||
- run: python -m pip install --upgrade pip && pip install nox
|
||||
- name: Prepare minimal package versions
|
||||
run: nox -s set-minimal-package-versions
|
||||
- run: nox -s check-all
|
||||
|
||||
env:
|
||||
CARGO_BUILD_TARGET: x86_64-unknown-linux-gnu
|
||||
|
||||
clippy:
|
||||
needs: [fmt]
|
||||
runs-on: ${{ matrix.platform.os }}
|
||||
|
@ -80,16 +106,6 @@ jobs:
|
|||
rust-target: "i686-pc-windows-msvc",
|
||||
},
|
||||
]
|
||||
include:
|
||||
- rust: 1.48.0
|
||||
python-version: "3.11"
|
||||
platform:
|
||||
{
|
||||
os: "ubuntu-latest",
|
||||
python-architecture: "x64",
|
||||
rust-target: "x86_64-unknown-linux-gnu",
|
||||
}
|
||||
msrv: "MSRV"
|
||||
name: clippy/${{ matrix.platform.rust-target }}/${{ matrix.rust }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
@ -106,9 +122,6 @@ jobs:
|
|||
key: clippy-${{ matrix.platform.rust-target }}-${{ matrix.platform.os }}-${{ matrix.rust }}
|
||||
continue-on-error: true
|
||||
- run: python -m pip install --upgrade pip && pip install nox
|
||||
- if: matrix.msrv == 'MSRV'
|
||||
name: Prepare minimal package versions (MSRV only)
|
||||
run: nox -s set-minimal-package-versions
|
||||
- run: nox -s clippy-all
|
||||
env:
|
||||
CARGO_BUILD_TARGET: ${{ matrix.platform.rust-target }}
|
||||
|
@ -207,7 +220,7 @@ jobs:
|
|||
]
|
||||
include:
|
||||
# Test minimal supported Rust version
|
||||
- rust: 1.48.0
|
||||
- rust: 1.56.0
|
||||
python-version: "3.11"
|
||||
platform:
|
||||
{
|
||||
|
@ -353,6 +366,7 @@ jobs:
|
|||
conclusion:
|
||||
needs:
|
||||
- fmt
|
||||
- check-msrv
|
||||
- clippy
|
||||
- build-pr
|
||||
- build-full
|
||||
|
|
|
@ -12,6 +12,7 @@ categories = ["api-bindings", "development-tools::ffi"]
|
|||
license = "Apache-2.0"
|
||||
exclude = ["/.gitignore", ".cargo/config", "/codecov.yml", "/Makefile", "/pyproject.toml", "/noxfile.py", "/.github", "/tests/test_compile_error.rs", "/tests/ui"]
|
||||
edition = "2018"
|
||||
rust-version = "1.56"
|
||||
|
||||
[dependencies]
|
||||
cfg-if = "1.0"
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
[![benchmark](https://github.com/PyO3/pyo3/actions/workflows/bench.yml/badge.svg)](https://pyo3.rs/dev/bench/)
|
||||
[![codecov](https://codecov.io/gh/PyO3/pyo3/branch/main/graph/badge.svg)](https://codecov.io/gh/PyO3/pyo3)
|
||||
[![crates.io](https://img.shields.io/crates/v/pyo3)](https://crates.io/crates/pyo3)
|
||||
[![minimum rustc 1.48](https://img.shields.io/badge/rustc-1.48+-blue.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html)
|
||||
[![minimum rustc 1.56](https://img.shields.io/badge/rustc-1.56+-blue.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html)
|
||||
[![dev chat](https://img.shields.io/gitter/room/nwjs/nw.js.svg)](https://gitter.im/PyO3/Lobby)
|
||||
[![contributing notes](https://img.shields.io/badge/contribute-on%20github-Green)](https://github.com/PyO3/pyo3/blob/main/Contributing.md)
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
|||
|
||||
PyO3 supports the following software versions:
|
||||
- Python 3.7 and up (CPython and PyPy)
|
||||
- Rust 1.48 and up
|
||||
- Rust 1.56 and up
|
||||
|
||||
You can use PyO3 to write a native Python module in Rust, or to embed Python in a Rust binary. The following sections explain each of these in turn.
|
||||
|
||||
|
|
|
@ -10,5 +10,3 @@ classifiers = [
|
|||
"Programming Language :: Python :: Implementation :: CPython",
|
||||
"Programming Language :: Python :: Implementation :: PyPy",
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ To get started using PyO3 you will need three things: a Rust toolchain, a Python
|
|||
|
||||
## Rust
|
||||
|
||||
First, make sure you have Rust installed on your system. If you haven't already done so, try following the instructions [here](https://www.rust-lang.org/tools/install). PyO3 runs on both the `stable` and `nightly` versions so you can choose whichever one fits you best. The minimum required Rust version is 1.48.
|
||||
First, make sure you have Rust installed on your system. If you haven't already done so, try following the instructions [here](https://www.rust-lang.org/tools/install). PyO3 runs on both the `stable` and `nightly` versions so you can choose whichever one fits you best. The minimum required Rust version is 1.56.
|
||||
|
||||
If you can run `rustc --version` and the version is new enough you're good to go!
|
||||
|
||||
|
|
|
@ -3,6 +3,12 @@
|
|||
This guide can help you upgrade code through breaking changes from one PyO3 version to the next.
|
||||
For a detailed list of all changes, see the [CHANGELOG](changelog.md).
|
||||
|
||||
## from 0.19.* to 0.20
|
||||
|
||||
### Drop support for older technologies
|
||||
|
||||
PyO3 0.20 has increased minimum Rust version to 1.56. This enables use of newer language features and simplifies maintenance of the project.
|
||||
|
||||
## from 0.18.* to 0.19
|
||||
|
||||
### Access to `Python` inside `__traverse__` implementations are now forbidden
|
||||
|
|
1
newsfragments/3208.packaging.md
Normal file
1
newsfragments/3208.packaging.md
Normal file
|
@ -0,0 +1 @@
|
|||
Update MSRV to Rust 1.56.
|
139
noxfile.py
139
noxfile.py
|
@ -8,7 +8,7 @@ import time
|
|||
from functools import lru_cache
|
||||
from glob import glob
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
from typing import Any, Callable, Dict, List, Optional, Tuple
|
||||
|
||||
import nox
|
||||
|
||||
|
@ -96,25 +96,19 @@ def _clippy(session: nox.Session, *, env: Dict[str, str] = None) -> bool:
|
|||
success = True
|
||||
env = env or os.environ
|
||||
for feature_set in _get_feature_sets():
|
||||
command = "clippy"
|
||||
extra = ("--", "--deny=warnings")
|
||||
if _get_rust_version()[:2] == (1, 48):
|
||||
# 1.48 crashes during clippy because of lints requested
|
||||
# in .cargo/config
|
||||
command = "check"
|
||||
extra = ()
|
||||
try:
|
||||
_run(
|
||||
session,
|
||||
"cargo",
|
||||
command,
|
||||
"clippy",
|
||||
*feature_set,
|
||||
"--all-targets",
|
||||
"--workspace",
|
||||
# linting pyo3-ffi-check requires docs to have been built or
|
||||
# the macros will error; doesn't seem worth it on CI
|
||||
"--exclude=pyo3-ffi-check",
|
||||
*extra,
|
||||
"--",
|
||||
"--deny=warnings",
|
||||
external=True,
|
||||
env=env,
|
||||
)
|
||||
|
@ -126,31 +120,43 @@ def _clippy(session: nox.Session, *, env: Dict[str, str] = None) -> bool:
|
|||
@nox.session(name="clippy-all", venv_backend="none")
|
||||
def clippy_all(session: nox.Session) -> None:
|
||||
success = True
|
||||
with tempfile.NamedTemporaryFile("r+") as config:
|
||||
env = os.environ.copy()
|
||||
env["PYO3_CONFIG_FILE"] = config.name
|
||||
env["PYO3_CI"] = "1"
|
||||
|
||||
def _clippy_with_config(implementation, version) -> bool:
|
||||
config.seek(0)
|
||||
config.truncate(0)
|
||||
config.write(
|
||||
f"""\
|
||||
implementation={implementation}
|
||||
version={version}
|
||||
suppress_build_script_link_lines=true
|
||||
"""
|
||||
)
|
||||
config.flush()
|
||||
def _clippy_with_config(env: Dict[str, str]) -> None:
|
||||
nonlocal success
|
||||
success &= _clippy(session, env=env)
|
||||
|
||||
session.log(f"{implementation} {version}")
|
||||
return _clippy(session, env=env)
|
||||
_for_all_version_configs(session, _clippy_with_config)
|
||||
|
||||
for version in PY_VERSIONS:
|
||||
success &= _clippy_with_config("CPython", version)
|
||||
if not success:
|
||||
session.error("one or more jobs failed")
|
||||
|
||||
for version in PYPY_VERSIONS:
|
||||
success &= _clippy_with_config("PyPy", version)
|
||||
|
||||
@nox.session(name="check-all", venv_backend="none")
|
||||
def check_all(session: nox.Session) -> None:
|
||||
success = True
|
||||
|
||||
def _check(env: Dict[str, str]) -> None:
|
||||
nonlocal success
|
||||
env = env or os.environ
|
||||
for feature_set in _get_feature_sets():
|
||||
try:
|
||||
_run(
|
||||
session,
|
||||
"cargo",
|
||||
"check",
|
||||
*feature_set,
|
||||
"--all-targets",
|
||||
"--workspace",
|
||||
# linting pyo3-ffi-check requires docs to have been built or
|
||||
# the macros will error; doesn't seem worth it on CI
|
||||
"--exclude=pyo3-ffi-check",
|
||||
external=True,
|
||||
env=env,
|
||||
)
|
||||
except Exception:
|
||||
success = False
|
||||
|
||||
_for_all_version_configs(session, _check)
|
||||
|
||||
if not success:
|
||||
session.error("one or more jobs failed")
|
||||
|
@ -422,42 +428,13 @@ def set_minimal_package_versions(session: nox.Session):
|
|||
"examples/word-count",
|
||||
)
|
||||
min_pkg_versions = {
|
||||
# newer versions of rust_decimal want newer arrayvec
|
||||
"rust_decimal": "1.18.0",
|
||||
# newer versions of arrayvec use const generics (Rust 1.51+)
|
||||
"arrayvec": "0.5.2",
|
||||
"rust_decimal": "1.26.1",
|
||||
"csv": "1.1.6",
|
||||
# newer versions of chrono use i32::rem_euclid as a const fn
|
||||
"chrono": "0.4.24",
|
||||
"indexmap": "1.6.2",
|
||||
"inventory": "0.3.4",
|
||||
"hashbrown": "0.9.1",
|
||||
"plotters": "0.3.1",
|
||||
"plotters-svg": "0.3.1",
|
||||
"plotters-backend": "0.3.2",
|
||||
"bumpalo": "3.10.0",
|
||||
"once_cell": "1.14.0",
|
||||
"rayon": "1.5.3",
|
||||
"rayon-core": "1.9.3",
|
||||
"hashbrown": "0.12.3",
|
||||
"once_cell": "1.17.2",
|
||||
"rayon": "1.6.1",
|
||||
"rayon-core": "1.10.2",
|
||||
"regex": "1.7.3",
|
||||
# string_cache 0.8.4 depends on parking_lot 0.12
|
||||
"string_cache": "0.8.3",
|
||||
# 1.15.0 depends on hermit-abi 0.2.6 which has edition 2021 and breaks 1.48.0
|
||||
"num_cpus": "1.14.0",
|
||||
"parking_lot": "0.11.0",
|
||||
# 1.0.77 needs basic-toml which has edition 2021
|
||||
"trybuild": "1.0.76",
|
||||
# pins to avoid syn 2.0 (which requires Rust 1.56)
|
||||
"ghost": "0.1.8",
|
||||
"serde": "1.0.156",
|
||||
"serde_derive": "1.0.156",
|
||||
"cxx": "1.0.92",
|
||||
"cxxbridge-macro": "1.0.92",
|
||||
"cxx-build": "1.0.92",
|
||||
"web-sys": "0.3.61",
|
||||
"js-sys": "0.3.61",
|
||||
"wasm-bindgen": "0.2.84",
|
||||
"syn": "1.0.109",
|
||||
}
|
||||
|
||||
# run cargo update first to ensure that everything is at highest
|
||||
|
@ -634,7 +611,7 @@ def _run_cargo_set_package_version(
|
|||
*,
|
||||
project: Optional[str] = None,
|
||||
) -> None:
|
||||
command = ["cargo", "update", "-p", pkg_id, "--precise", version]
|
||||
command = ["cargo", "update", "-p", pkg_id, "--precise", version, "--workspace"]
|
||||
if project:
|
||||
command.append(f"--manifest-path={project}/Cargo.toml")
|
||||
_run(session, *command, external=True)
|
||||
|
@ -642,3 +619,33 @@ def _run_cargo_set_package_version(
|
|||
|
||||
def _get_output(*args: str) -> str:
|
||||
return subprocess.run(args, capture_output=True, text=True, check=True).stdout
|
||||
|
||||
|
||||
def _for_all_version_configs(
|
||||
session: nox.Session, job: Callable[[Dict[str, str]], None]
|
||||
) -> None:
|
||||
with tempfile.NamedTemporaryFile("r+") as config:
|
||||
env = os.environ.copy()
|
||||
env["PYO3_CONFIG_FILE"] = config.name
|
||||
env["PYO3_CI"] = "1"
|
||||
|
||||
def _job_with_config(implementation, version) -> bool:
|
||||
config.seek(0)
|
||||
config.truncate(0)
|
||||
config.write(
|
||||
f"""\
|
||||
implementation={implementation}
|
||||
version={version}
|
||||
suppress_build_script_link_lines=true
|
||||
"""
|
||||
)
|
||||
config.flush()
|
||||
|
||||
session.log(f"{implementation} {version}")
|
||||
return job(env)
|
||||
|
||||
for version in PY_VERSIONS:
|
||||
_job_with_config("CPython", version)
|
||||
|
||||
for version in PYPY_VERSIONS:
|
||||
_job_with_config("PyPy", version)
|
||||
|
|
|
@ -161,6 +161,11 @@ pub fn print_feature_cfgs() {
|
|||
if rustc_minor_version >= 59 {
|
||||
println!("cargo:rustc-cfg=thread_local_const_init");
|
||||
}
|
||||
|
||||
// Enable use of `#[cfg(panic = "...")]` on Rust 1.60 and greater
|
||||
if rustc_minor_version >= 60 {
|
||||
println!("cargo:rustc-cfg=panic_unwind");
|
||||
}
|
||||
}
|
||||
|
||||
/// Private exports used in PyO3's build.rs
|
||||
|
|
|
@ -14,7 +14,7 @@ Manual][capi] for up-to-date documentation.
|
|||
|
||||
PyO3 supports the following software versions:
|
||||
- Python 3.7 and up (CPython and PyPy)
|
||||
- Rust 1.48 and up
|
||||
- Rust 1.56 and up
|
||||
|
||||
# Example: Building Python Native modules
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
//!
|
||||
//! PyO3 supports the following software versions:
|
||||
//! - Python 3.7 and up (CPython and PyPy)
|
||||
//! - Rust 1.48 and up
|
||||
//! - Rust 1.56 and up
|
||||
//!
|
||||
//! # Example: Building Python Native modules
|
||||
//!
|
||||
|
|
|
@ -27,10 +27,11 @@ pub struct Signature {
|
|||
impl Parse for Signature {
|
||||
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
||||
let content;
|
||||
Ok(Signature {
|
||||
paren_token: syn::parenthesized!(content in input),
|
||||
items: content.parse_terminated(SignatureItem::parse)?,
|
||||
})
|
||||
let paren_token = syn::parenthesized!(content in input);
|
||||
|
||||
let items = content.parse_terminated(SignatureItem::parse)?;
|
||||
|
||||
Ok(Signature { paren_token, items })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,10 +13,7 @@ fn make_date(py: Python<'_>, year: i32, month: u8, day: u8) -> PyResult<&PyDate>
|
|||
|
||||
#[pyfunction]
|
||||
fn get_date_tuple<'p>(py: Python<'p>, d: &PyDate) -> &'p PyTuple {
|
||||
PyTuple::new(
|
||||
py,
|
||||
&[d.get_year(), d.get_month() as i32, d.get_day() as i32],
|
||||
)
|
||||
PyTuple::new(py, [d.get_year(), d.get_month() as i32, d.get_day() as i32])
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
|
@ -54,7 +51,7 @@ fn time_with_fold<'p>(
|
|||
fn get_time_tuple<'p>(py: Python<'p>, dt: &PyTime) -> &'p PyTuple {
|
||||
PyTuple::new(
|
||||
py,
|
||||
&[
|
||||
[
|
||||
dt.get_hour() as u32,
|
||||
dt.get_minute() as u32,
|
||||
dt.get_second() as u32,
|
||||
|
@ -67,7 +64,7 @@ fn get_time_tuple<'p>(py: Python<'p>, dt: &PyTime) -> &'p PyTuple {
|
|||
fn get_time_tuple_fold<'p>(py: Python<'p>, dt: &PyTime) -> &'p PyTuple {
|
||||
PyTuple::new(
|
||||
py,
|
||||
&[
|
||||
[
|
||||
dt.get_hour() as u32,
|
||||
dt.get_minute() as u32,
|
||||
dt.get_second() as u32,
|
||||
|
@ -86,7 +83,7 @@ fn make_delta(py: Python<'_>, days: i32, seconds: i32, microseconds: i32) -> PyR
|
|||
fn get_delta_tuple<'p>(py: Python<'p>, delta: &PyDelta) -> &'p PyTuple {
|
||||
PyTuple::new(
|
||||
py,
|
||||
&[
|
||||
[
|
||||
delta.get_days(),
|
||||
delta.get_seconds(),
|
||||
delta.get_microseconds(),
|
||||
|
@ -124,7 +121,7 @@ fn make_datetime<'p>(
|
|||
fn get_datetime_tuple<'p>(py: Python<'p>, dt: &PyDateTime) -> &'p PyTuple {
|
||||
PyTuple::new(
|
||||
py,
|
||||
&[
|
||||
[
|
||||
dt.get_year(),
|
||||
dt.get_month() as i32,
|
||||
dt.get_day() as i32,
|
||||
|
@ -140,7 +137,7 @@ fn get_datetime_tuple<'p>(py: Python<'p>, dt: &PyDateTime) -> &'p PyTuple {
|
|||
fn get_datetime_tuple_fold<'p>(py: Python<'p>, dt: &PyDateTime) -> &'p PyTuple {
|
||||
PyTuple::new(
|
||||
py,
|
||||
&[
|
||||
[
|
||||
dt.get_year(),
|
||||
dt.get_month() as i32,
|
||||
dt.get_day() as i32,
|
||||
|
|
|
@ -667,7 +667,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_try_from_unchecked() {
|
||||
Python::with_gil(|py| {
|
||||
let list = PyList::new(py, &[1, 2, 3]);
|
||||
let list = PyList::new(py, [1, 2, 3]);
|
||||
let val = unsafe { <PyList as PyTryFrom>::try_from_unchecked(list.as_ref()) };
|
||||
assert!(list.is(val));
|
||||
});
|
||||
|
|
|
@ -63,7 +63,7 @@ impl ModuleDef {
|
|||
.import("sys")?
|
||||
.getattr("implementation")?
|
||||
.getattr("version")?;
|
||||
if version.lt(crate::types::PyTuple::new(py, &PYPY_GOOD_VERSION))? {
|
||||
if version.lt(crate::types::PyTuple::new(py, PYPY_GOOD_VERSION))? {
|
||||
let warn = py.import("warnings")?.getattr("warn")?;
|
||||
warn.call1((
|
||||
"PyPy 3.7 versions older than 7.3.8 are known to have binary \
|
||||
|
|
|
@ -122,7 +122,7 @@
|
|||
//!
|
||||
//! PyO3 supports the following software versions:
|
||||
//! - Python 3.7 and up (CPython and PyPy)
|
||||
//! - Rust 1.48 and up
|
||||
//! - Rust 1.56 and up
|
||||
//!
|
||||
//! # Example: Building a native Python module
|
||||
//!
|
||||
|
|
|
@ -1049,7 +1049,7 @@ mod tests {
|
|||
|
||||
// If allow_threads is implemented correctly, this thread still owns the GIL here
|
||||
// so the following Python calls should not cause crashes.
|
||||
let list = PyList::new(py, &[1, 2, 3, 4]);
|
||||
let list = PyList::new(py, [1, 2, 3, 4]);
|
||||
assert_eq!(list.extract::<Vec<i32>>().unwrap(), vec![1, 2, 3, 4]);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -196,7 +196,7 @@ impl PyDate {
|
|||
///
|
||||
/// This is equivalent to `datetime.date.fromtimestamp`
|
||||
pub fn from_timestamp(py: Python<'_>, timestamp: i64) -> PyResult<&PyDate> {
|
||||
let time_tuple = PyTuple::new(py, &[timestamp]);
|
||||
let time_tuple = PyTuple::new(py, [timestamp]);
|
||||
|
||||
// safety ensure that the API is loaded
|
||||
let _api = ensure_datetime_api(py);
|
||||
|
|
|
@ -119,7 +119,7 @@ impl PyList {
|
|||
/// ```
|
||||
/// use pyo3::{prelude::*, types::PyList};
|
||||
/// Python::with_gil(|py| {
|
||||
/// let list = PyList::new(py, &[2, 3, 5, 7]);
|
||||
/// let list = PyList::new(py, [2, 3, 5, 7]);
|
||||
/// let obj = list.get_item(0);
|
||||
/// assert_eq!(obj.unwrap().extract::<i32>().unwrap(), 2);
|
||||
/// });
|
||||
|
@ -351,7 +351,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_new() {
|
||||
Python::with_gil(|py| {
|
||||
let list = PyList::new(py, &[2, 3, 5, 7]);
|
||||
let list = PyList::new(py, [2, 3, 5, 7]);
|
||||
assert_eq!(2, list[0].extract::<i32>().unwrap());
|
||||
assert_eq!(3, list[1].extract::<i32>().unwrap());
|
||||
assert_eq!(5, list[2].extract::<i32>().unwrap());
|
||||
|
@ -362,7 +362,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_len() {
|
||||
Python::with_gil(|py| {
|
||||
let list = PyList::new(py, &[1, 2, 3, 4]);
|
||||
let list = PyList::new(py, [1, 2, 3, 4]);
|
||||
assert_eq!(4, list.len());
|
||||
});
|
||||
}
|
||||
|
@ -370,7 +370,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_get_item() {
|
||||
Python::with_gil(|py| {
|
||||
let list = PyList::new(py, &[2, 3, 5, 7]);
|
||||
let list = PyList::new(py, [2, 3, 5, 7]);
|
||||
assert_eq!(2, list.get_item(0).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(3, list.get_item(1).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(5, list.get_item(2).unwrap().extract::<i32>().unwrap());
|
||||
|
@ -381,7 +381,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_get_slice() {
|
||||
Python::with_gil(|py| {
|
||||
let list = PyList::new(py, &[2, 3, 5, 7]);
|
||||
let list = PyList::new(py, [2, 3, 5, 7]);
|
||||
let slice = list.get_slice(1, 3);
|
||||
assert_eq!(2, slice.len());
|
||||
let slice = list.get_slice(1, 7);
|
||||
|
@ -392,7 +392,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_set_item() {
|
||||
Python::with_gil(|py| {
|
||||
let list = PyList::new(py, &[2, 3, 5, 7]);
|
||||
let list = PyList::new(py, [2, 3, 5, 7]);
|
||||
let val = 42i32.to_object(py);
|
||||
let val2 = 42i32.to_object(py);
|
||||
assert_eq!(2, list[0].extract::<i32>().unwrap());
|
||||
|
@ -423,7 +423,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_insert() {
|
||||
Python::with_gil(|py| {
|
||||
let list = PyList::new(py, &[2, 3, 5, 7]);
|
||||
let list = PyList::new(py, [2, 3, 5, 7]);
|
||||
let val = 42i32.to_object(py);
|
||||
let val2 = 43i32.to_object(py);
|
||||
assert_eq!(4, list.len());
|
||||
|
@ -456,7 +456,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_append() {
|
||||
Python::with_gil(|py| {
|
||||
let list = PyList::new(py, &[2]);
|
||||
let list = PyList::new(py, [2]);
|
||||
list.append(3).unwrap();
|
||||
assert_eq!(2, list[0].extract::<i32>().unwrap());
|
||||
assert_eq!(3, list[1].extract::<i32>().unwrap());
|
||||
|
@ -514,7 +514,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_into_iter() {
|
||||
Python::with_gil(|py| {
|
||||
let list = PyList::new(py, &[1, 2, 3, 4]);
|
||||
let list = PyList::new(py, [1, 2, 3, 4]);
|
||||
for (i, item) in list.iter().enumerate() {
|
||||
assert_eq!((i + 1) as i32, item.extract::<i32>().unwrap());
|
||||
}
|
||||
|
@ -578,7 +578,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_list_get_item_invalid_index() {
|
||||
Python::with_gil(|py| {
|
||||
let list = PyList::new(py, &[2, 3, 5, 7]);
|
||||
let list = PyList::new(py, [2, 3, 5, 7]);
|
||||
let obj = list.get_item(5);
|
||||
assert!(obj.is_err());
|
||||
assert_eq!(
|
||||
|
@ -591,7 +591,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_list_get_item_sanity() {
|
||||
Python::with_gil(|py| {
|
||||
let list = PyList::new(py, &[2, 3, 5, 7]);
|
||||
let list = PyList::new(py, [2, 3, 5, 7]);
|
||||
let obj = list.get_item(0);
|
||||
assert_eq!(obj.unwrap().extract::<i32>().unwrap(), 2);
|
||||
});
|
||||
|
@ -601,7 +601,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_list_get_item_unchecked_sanity() {
|
||||
Python::with_gil(|py| {
|
||||
let list = PyList::new(py, &[2, 3, 5, 7]);
|
||||
let list = PyList::new(py, [2, 3, 5, 7]);
|
||||
let obj = unsafe { list.get_item_unchecked(0) };
|
||||
assert_eq!(obj.extract::<i32>().unwrap(), 2);
|
||||
});
|
||||
|
@ -610,7 +610,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_list_index_trait() {
|
||||
Python::with_gil(|py| {
|
||||
let list = PyList::new(py, &[2, 3, 5]);
|
||||
let list = PyList::new(py, [2, 3, 5]);
|
||||
assert_eq!(2, list[0].extract::<i32>().unwrap());
|
||||
assert_eq!(3, list[1].extract::<i32>().unwrap());
|
||||
assert_eq!(5, list[2].extract::<i32>().unwrap());
|
||||
|
@ -621,7 +621,7 @@ mod tests {
|
|||
#[should_panic]
|
||||
fn test_list_index_trait_panic() {
|
||||
Python::with_gil(|py| {
|
||||
let list = PyList::new(py, &[2, 3, 5]);
|
||||
let list = PyList::new(py, [2, 3, 5]);
|
||||
let _ = &list[7];
|
||||
});
|
||||
}
|
||||
|
@ -629,7 +629,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_list_index_trait_ranges() {
|
||||
Python::with_gil(|py| {
|
||||
let list = PyList::new(py, &[2, 3, 5]);
|
||||
let list = PyList::new(py, [2, 3, 5]);
|
||||
assert_eq!(vec![3, 5], list[1..3].extract::<Vec<i32>>().unwrap());
|
||||
assert_eq!(Vec::<i32>::new(), list[3..3].extract::<Vec<i32>>().unwrap());
|
||||
assert_eq!(vec![3, 5], list[1..].extract::<Vec<i32>>().unwrap());
|
||||
|
@ -645,7 +645,7 @@ mod tests {
|
|||
#[should_panic = "range start index 5 out of range for list of length 3"]
|
||||
fn test_list_index_trait_range_panic_start() {
|
||||
Python::with_gil(|py| {
|
||||
let list = PyList::new(py, &[2, 3, 5]);
|
||||
let list = PyList::new(py, [2, 3, 5]);
|
||||
list[5..10].extract::<Vec<i32>>().unwrap();
|
||||
})
|
||||
}
|
||||
|
@ -654,7 +654,7 @@ mod tests {
|
|||
#[should_panic = "range end index 10 out of range for list of length 3"]
|
||||
fn test_list_index_trait_range_panic_end() {
|
||||
Python::with_gil(|py| {
|
||||
let list = PyList::new(py, &[2, 3, 5]);
|
||||
let list = PyList::new(py, [2, 3, 5]);
|
||||
list[1..10].extract::<Vec<i32>>().unwrap();
|
||||
})
|
||||
}
|
||||
|
@ -663,7 +663,7 @@ mod tests {
|
|||
#[should_panic = "slice index starts at 2 but ends at 1"]
|
||||
fn test_list_index_trait_range_panic_wrong_order() {
|
||||
Python::with_gil(|py| {
|
||||
let list = PyList::new(py, &[2, 3, 5]);
|
||||
let list = PyList::new(py, [2, 3, 5]);
|
||||
#[allow(clippy::reversed_empty_ranges)]
|
||||
list[2..1].extract::<Vec<i32>>().unwrap();
|
||||
})
|
||||
|
@ -673,7 +673,7 @@ mod tests {
|
|||
#[should_panic = "range start index 8 out of range for list of length 3"]
|
||||
fn test_list_index_trait_range_from_panic() {
|
||||
Python::with_gil(|py| {
|
||||
let list = PyList::new(py, &[2, 3, 5]);
|
||||
let list = PyList::new(py, [2, 3, 5]);
|
||||
list[8..].extract::<Vec<i32>>().unwrap();
|
||||
})
|
||||
}
|
||||
|
@ -681,7 +681,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_list_del_item() {
|
||||
Python::with_gil(|py| {
|
||||
let list = PyList::new(py, &[1, 1, 2, 3, 5, 8]);
|
||||
let list = PyList::new(py, [1, 1, 2, 3, 5, 8]);
|
||||
assert!(list.del_item(10).is_err());
|
||||
assert_eq!(1, list[0].extract::<i32>().unwrap());
|
||||
assert!(list.del_item(0).is_ok());
|
||||
|
@ -703,8 +703,8 @@ mod tests {
|
|||
#[test]
|
||||
fn test_list_set_slice() {
|
||||
Python::with_gil(|py| {
|
||||
let list = PyList::new(py, &[1, 1, 2, 3, 5, 8]);
|
||||
let ins = PyList::new(py, &[7, 4]);
|
||||
let list = PyList::new(py, [1, 1, 2, 3, 5, 8]);
|
||||
let ins = PyList::new(py, [7, 4]);
|
||||
list.set_slice(1, 4, ins).unwrap();
|
||||
assert_eq!([1, 7, 4, 5, 8], list.extract::<[i32; 5]>().unwrap());
|
||||
list.set_slice(3, 100, PyList::empty(py)).unwrap();
|
||||
|
@ -715,7 +715,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_list_del_slice() {
|
||||
Python::with_gil(|py| {
|
||||
let list = PyList::new(py, &[1, 1, 2, 3, 5, 8]);
|
||||
let list = PyList::new(py, [1, 1, 2, 3, 5, 8]);
|
||||
list.del_slice(1, 4).unwrap();
|
||||
assert_eq!([1, 5, 8], list.extract::<[i32; 3]>().unwrap());
|
||||
list.del_slice(1, 100).unwrap();
|
||||
|
@ -726,7 +726,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_list_contains() {
|
||||
Python::with_gil(|py| {
|
||||
let list = PyList::new(py, &[1, 1, 2, 3, 5, 8]);
|
||||
let list = PyList::new(py, [1, 1, 2, 3, 5, 8]);
|
||||
assert_eq!(6, list.len());
|
||||
|
||||
let bad_needle = 7i32.to_object(py);
|
||||
|
@ -743,7 +743,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_list_index() {
|
||||
Python::with_gil(|py| {
|
||||
let list = PyList::new(py, &[1, 1, 2, 3, 5, 8]);
|
||||
let list = PyList::new(py, [1, 1, 2, 3, 5, 8]);
|
||||
assert_eq!(0, list.index(1i32).unwrap());
|
||||
assert_eq!(2, list.index(2i32).unwrap());
|
||||
assert_eq!(3, list.index(3i32).unwrap());
|
||||
|
|
|
@ -832,7 +832,7 @@ mod tests {
|
|||
assert!(seq
|
||||
.to_list()
|
||||
.unwrap()
|
||||
.eq(PyList::new(py, &["f", "o", "o"]))
|
||||
.eq(PyList::new(py, ["f", "o", "o"]))
|
||||
.unwrap());
|
||||
#[allow(deprecated)]
|
||||
{
|
||||
|
@ -850,7 +850,7 @@ mod tests {
|
|||
assert!(seq
|
||||
.to_tuple()
|
||||
.unwrap()
|
||||
.eq(PyTuple::new(py, &["foo", "bar"]))
|
||||
.eq(PyTuple::new(py, ["foo", "bar"]))
|
||||
.unwrap());
|
||||
#[allow(deprecated)]
|
||||
{
|
||||
|
|
|
@ -459,7 +459,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_new() {
|
||||
Python::with_gil(|py| {
|
||||
let ob = PyTuple::new(py, &[1, 2, 3]);
|
||||
let ob = PyTuple::new(py, [1, 2, 3]);
|
||||
assert_eq!(3, ob.len());
|
||||
let ob: &PyAny = ob.into();
|
||||
assert_eq!((1, 2, 3), ob.extract().unwrap());
|
||||
|
@ -467,7 +467,7 @@ mod tests {
|
|||
let mut map = HashSet::new();
|
||||
map.insert(1);
|
||||
map.insert(2);
|
||||
PyTuple::new(py, &map);
|
||||
PyTuple::new(py, map);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -485,7 +485,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_slice() {
|
||||
Python::with_gil(|py| {
|
||||
let tup = PyTuple::new(py, &[2, 3, 5, 7]);
|
||||
let tup = PyTuple::new(py, [2, 3, 5, 7]);
|
||||
let slice = tup.get_slice(1, 3);
|
||||
assert_eq!(2, slice.len());
|
||||
let slice = tup.get_slice(1, 7);
|
||||
|
|
|
@ -96,7 +96,7 @@ fn recursive_class_attributes() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(panic = "unwind")]
|
||||
#[cfg_attr(cfg_panic, cfg(panic = "unwind"))]
|
||||
fn test_fallible_class_attribute() {
|
||||
use pyo3::{exceptions::PyValueError, types::PyString};
|
||||
|
||||
|
|
|
@ -562,7 +562,7 @@ pub struct TransparentFromPyWith {
|
|||
#[test]
|
||||
fn test_transparent_from_py_with() {
|
||||
Python::with_gil(|py| {
|
||||
let result = TransparentFromPyWith::extract(PyList::new(py, &[1, 2, 3])).unwrap();
|
||||
let result = TransparentFromPyWith::extract(PyList::new(py, [1, 2, 3])).unwrap();
|
||||
let expected = TransparentFromPyWith { len: 3 };
|
||||
|
||||
assert_eq!(result, expected);
|
||||
|
|
|
@ -42,7 +42,7 @@ impl ClassWithProperties {
|
|||
|
||||
#[getter]
|
||||
fn get_data_list<'py>(&self, py: Python<'py>) -> &'py PyList {
|
||||
PyList::new(py, &[self.num])
|
||||
PyList::new(py, [self.num])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ fn test_basic() {
|
|||
let module = pyo3::wrap_pymodule!(basic_module)(py);
|
||||
let cls = py.get_type::<BasicClass>();
|
||||
let d = pyo3::types::IntoPyDict::into_py_dict(
|
||||
&[
|
||||
[
|
||||
("mod", module.as_ref(py).as_ref()),
|
||||
("cls", cls.as_ref()),
|
||||
("a", cls.call1((8,)).unwrap()),
|
||||
|
|
|
@ -849,7 +849,7 @@ struct DefaultedContains;
|
|||
#[pymethods]
|
||||
impl DefaultedContains {
|
||||
fn __iter__(&self, py: Python<'_>) -> PyObject {
|
||||
PyList::new(py, &["a", "b", "c"])
|
||||
PyList::new(py, ["a", "b", "c"])
|
||||
.as_ref()
|
||||
.iter()
|
||||
.unwrap()
|
||||
|
@ -863,7 +863,7 @@ struct NoContains;
|
|||
#[pymethods]
|
||||
impl NoContains {
|
||||
fn __iter__(&self, py: Python<'_>) -> PyObject {
|
||||
PyList::new(py, &["a", "b", "c"])
|
||||
PyList::new(py, ["a", "b", "c"])
|
||||
.as_ref()
|
||||
.iter()
|
||||
.unwrap()
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::process::{Command, Output};
|
|||
use std::time::Instant;
|
||||
use structopt::StructOpt;
|
||||
|
||||
pub const MSRV: &str = "1.48";
|
||||
pub const MSRV: &str = "1.56";
|
||||
|
||||
#[derive(StructOpt)]
|
||||
pub enum Subcommand {
|
||||
|
|
Loading…
Reference in a new issue