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

msrv: bump to 1.45 #1272

Merged
merged 1 commit into from
Nov 12, 2020
Merged
Show file tree
Hide file tree
Changes from all 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/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ jobs:
platform: { os: "windows-latest" }
include:
# Test minimal supported Rust version
- rust: 1.39.0
- rust: 1.45.0
python-version: 3.9
platform: { os: "ubuntu-latest", python-architecture: "x64", rust-target: "x86_64-unknown-linux-gnu" }
msrv: "MSRV"
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [Unreleased]
### Packaging
- Drop support for Python 3.5 (as it is now end-of-life). [#1250](https://github.com/PyO3/pyo3/pull/1250)
- Bump minimum supported Rust version to 1.45. [#1272](https://github.com/PyO3/pyo3/pull/1272)
- Bump indoc dependency to 1.0. [#1272](https://github.com/PyO3/pyo3/pull/1272)
- Bump paste dependency to 1.0. [#1272](https://github.com/PyO3/pyo3/pull/1272)

### Added
- Add support for building for CPython limited API. This required a few minor changes to runtime behaviour of of pyo3 `#[pyclass]` types. See the migration guide for full details. [#1152](https://github.com/PyO3/pyo3/pull/1152)
Expand Down
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ edition = "2018"

[dependencies]
ctor = { version = "0.1", optional = true }
indoc = { version = "0.3.4", optional = true }
indoc = { version = "1.0.3", optional = true }
inventory = { version = "0.1.4", optional = true }
libc = "0.2.62"
parking_lot = "0.11.0"
num-bigint = { version = "0.3", optional = true }
num-complex = { version = "0.3", optional = true }
paste = { version = "0.1.6", optional = true }
paste = { version = "1.0.3", optional = true }
pyo3cls = { path = "pyo3cls", version = "=0.12.3", optional = true }
unindent = { version = "0.1.4", optional = true }
hashbrown = { version = "0.9", optional = true }
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,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)
[![minimum rustc 1.45](https://img.shields.io/badge/rustc-1.45+-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.
Expand All @@ -18,7 +18,7 @@ A comparison with rust-cpython can be found [in the guide](https://pyo3.rs/maste

## Usage

PyO3 supports Python 3.6 and up. The minimum required Rust version is 1.39.0.
PyO3 supports Python 3.6 and up. The minimum required Rust version is 1.45.0.

Building with PyPy is also possible (via cpyext) for Python 3.6, targeted PyPy version is 7.3+.
Please refer to the [pypy section in the guide](https://pyo3.rs/master/pypy.html).
Expand Down
14 changes: 7 additions & 7 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,16 +341,16 @@ fn find_sysconfigdata(cross: &CrossCompileConfig) -> Result<PathBuf> {
/// recursive search for _sysconfigdata, returns all possibilities of sysconfigdata paths
fn search_lib_dir(path: impl AsRef<Path>, cross: &CrossCompileConfig) -> Vec<PathBuf> {
let mut sysconfig_paths = vec![];
let version_pat = if let Some(ref v) = cross.version {
let version_pat = if let Some(v) = &cross.version {
format!("python{}", v)
} else {
"python3.".into()
};
for f in fs::read_dir(path).expect("Path does not exist") {
let sysc = match f {
Ok(ref f) if starts_with(f, "_sysconfigdata") && ends_with(f, "py") => vec![f.path()],
Ok(ref f) if starts_with(f, "build") => search_lib_dir(f.path(), cross),
Ok(ref f) if starts_with(f, "lib.") => {
let sysc = match &f {
Ok(f) if starts_with(f, "_sysconfigdata") && ends_with(f, "py") => vec![f.path()],
Ok(f) if starts_with(f, "build") => search_lib_dir(f.path(), cross),
Ok(f) if starts_with(f, "lib.") => {
let name = f.file_name();
// check if right target os
if !name.to_string_lossy().contains(if cross.os == "android" {
Expand All @@ -366,7 +366,7 @@ fn search_lib_dir(path: impl AsRef<Path>, cross: &CrossCompileConfig) -> Vec<Pat
}
search_lib_dir(f.path(), cross)
}
Ok(ref f) if starts_with(f, &version_pat) => search_lib_dir(f.path(), cross),
Ok(f) if starts_with(f, &version_pat) => search_lib_dir(f.path(), cross),
_ => continue,
};
sysconfig_paths.extend(sysc);
Expand Down Expand Up @@ -569,7 +569,7 @@ fn run_python_script(interpreter: &Path, script: &str) -> Result<String> {
);
}
}
Ok(ref ok) if !ok.status.success() => bail!("Python script failed: {}"),
Ok(ok) if !ok.status.success() => bail!("Python script failed: {}"),
Ok(ok) => Ok(String::from_utf8(ok.stdout)?),
}
}
Expand Down
2 changes: 1 addition & 1 deletion guide/src/class/protocols.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ struct ClassWithGCSupport {
#[pyproto]
impl PyGCProtocol for ClassWithGCSupport {
fn __traverse__(&self, visit: PyVisit) -> Result<(), PyTraverseError> {
if let Some(ref obj) = self.obj {
if let Some(obj) = &self.obj {
visit.call(obj)?
}
Ok(())
Expand Down
18 changes: 8 additions & 10 deletions pyo3-derive-backend/src/from_pyobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,10 @@ impl<'a> Container<'a> {
}
let style = match (fields, transparent) {
(Fields::Unnamed(_), true) => ContainerType::TupleNewtype,
(Fields::Unnamed(unnamed), false) => {
if unnamed.unnamed.len() == 1 {
ContainerType::TupleNewtype
} else {
ContainerType::Tuple(unnamed.unnamed.len())
}
}
(Fields::Unnamed(unnamed), false) => match unnamed.unnamed.len() {
1 => ContainerType::TupleNewtype,
len => ContainerType::Tuple(len),
},
(Fields::Named(named), true) => {
let field = named
.named
Expand Down Expand Up @@ -457,14 +454,15 @@ fn get_pyo3_meta_list(attrs: &[Attribute]) -> Result<MetaList> {
}

fn verify_and_get_lifetime(generics: &syn::Generics) -> Result<Option<&syn::LifetimeDef>> {
let lifetimes = generics.lifetimes().collect::<Vec<_>>();
if lifetimes.len() > 1 {
let mut lifetimes = generics.lifetimes();
let lifetime = lifetimes.next();
if lifetimes.next().is_some() {
return Err(spanned_err(
&generics,
"FromPyObject can be derived with at most one lifetime parameter.",
));
}
Ok(lifetimes.into_iter().next())
Ok(lifetime)
}

/// Derive FromPyObject for enums and structs.
Expand Down
44 changes: 19 additions & 25 deletions pyo3-derive-backend/src/method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ pub struct FnSpec<'a> {
pub fn get_return_info(output: &syn::ReturnType) -> syn::Type {
match output {
syn::ReturnType::Default => syn::Type::Infer(syn::parse_quote! {_}),
syn::ReturnType::Type(_, ref ty) => *ty.clone(),
syn::ReturnType::Type(_, ty) => *ty.clone(),
}
}

Expand All @@ -109,7 +109,7 @@ pub fn parse_method_receiver(arg: &syn::FnArg) -> syn::Result<SelfType> {
syn::FnArg::Receiver(recv) => Ok(SelfType::Receiver {
mutable: recv.mutability.is_some(),
}),
syn::FnArg::Typed(syn::PatType { ref ty, .. }) => Ok(SelfType::TryFromPyCell(ty.span())),
syn::FnArg::Typed(syn::PatType { ty, .. }) => Ok(SelfType::TryFromPyCell(ty.span())),
}
}

Expand Down Expand Up @@ -198,14 +198,12 @@ impl<'a> FnSpec<'a> {
"Unexpected receiver for method",
));
}
syn::FnArg::Typed(syn::PatType {
ref pat, ref ty, ..
}) => {
let (ident, by_ref, mutability) = match **pat {
syn::FnArg::Typed(syn::PatType { pat, ty, .. }) => {
let (ident, by_ref, mutability) = match &**pat {
syn::Pat::Ident(syn::PatIdent {
ref ident,
ref by_ref,
ref mutability,
ident,
by_ref,
mutability,
..
}) => (ident, by_ref, mutability),
_ => {
Expand Down Expand Up @@ -267,7 +265,7 @@ impl<'a> FnSpec<'a> {

pub fn is_args(&self, name: &syn::Ident) -> bool {
for s in self.attrs.iter() {
if let Argument::VarArgs(ref path) = s {
if let Argument::VarArgs(path) = s {
return path.is_ident(name);
}
}
Expand All @@ -276,7 +274,7 @@ impl<'a> FnSpec<'a> {

pub fn is_kwargs(&self, name: &syn::Ident) -> bool {
for s in self.attrs.iter() {
if let Argument::KeywordArgs(ref path) = s {
if let Argument::KeywordArgs(path) = s {
return path.is_ident(name);
}
}
Expand All @@ -285,10 +283,10 @@ impl<'a> FnSpec<'a> {

pub fn default_value(&self, name: &syn::Ident) -> Option<TokenStream> {
for s in self.attrs.iter() {
match *s {
Argument::Arg(ref path, ref opt) | Argument::Kwarg(ref path, ref opt) => {
match s {
Argument::Arg(path, opt) | Argument::Kwarg(path, opt) => {
if path.is_ident(name) {
if let Some(ref val) = opt {
if let Some(val) = opt {
let i: syn::Expr = syn::parse_str(&val).unwrap();
return Some(i.into_token_stream());
}
Expand All @@ -302,7 +300,7 @@ impl<'a> FnSpec<'a> {

pub fn is_kw_only(&self, name: &syn::Ident) -> bool {
for s in self.attrs.iter() {
if let Argument::Kwarg(ref path, _) = s {
if let Argument::Kwarg(path, _) = s {
if path.is_ident(name) {
return true;
}
Expand Down Expand Up @@ -341,7 +339,7 @@ fn parse_method_attributes(

for attr in attrs.iter() {
match attr.parse_meta()? {
syn::Meta::Path(ref name) => {
syn::Meta::Path(name) => {
if name.is_ident("new") || name.is_ident("__new__") {
set_ty!(MethodTypeAttribute::New, name);
} else if name.is_ident("init") || name.is_ident("__init__") {
Expand Down Expand Up @@ -373,11 +371,7 @@ fn parse_method_attributes(
new_attrs.push(attr.clone())
}
}
syn::Meta::List(syn::MetaList {
ref path,
ref nested,
..
}) => {
syn::Meta::List(syn::MetaList { path, nested, .. }) => {
if path.is_ident("new") {
set_ty!(MethodTypeAttribute::New, path);
} else if path.is_ident("init") {
Expand Down Expand Up @@ -408,11 +402,11 @@ fn parse_method_attributes(
};

property_name = match nested.first().unwrap() {
syn::NestedMeta::Meta(syn::Meta::Path(ref w)) if w.segments.len() == 1 => {
syn::NestedMeta::Meta(syn::Meta::Path(w)) if w.segments.len() == 1 => {
Some(w.segments[0].ident.clone())
}
syn::NestedMeta::Lit(ref lit) => match *lit {
syn::Lit::Str(ref s) => Some(s.parse()?),
syn::NestedMeta::Lit(lit) => match lit {
syn::Lit::Str(s) => Some(s.parse()?),
_ => {
return Err(syn::Error::new_spanned(
lit,
Expand All @@ -428,7 +422,7 @@ fn parse_method_attributes(
}
};
} else if path.is_ident("args") {
let attrs = PyFunctionAttr::from_meta(nested)?;
let attrs = PyFunctionAttr::from_meta(&nested)?;
args.extend(attrs.arguments)
} else {
new_attrs.push(attr.clone())
Expand Down
18 changes: 9 additions & 9 deletions pyo3-derive-backend/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub fn process_functions_in_module(func: &mut syn::ItemFn) -> syn::Result<()> {
let mut stmts: Vec<syn::Stmt> = Vec::new();

for stmt in func.block.stmts.iter_mut() {
if let syn::Stmt::Item(syn::Item::Fn(ref mut func)) = stmt {
if let syn::Stmt::Item(syn::Item::Fn(func)) = stmt {
if let Some((module_name, python_name, pyfn_attrs)) =
extract_pyfn_attrs(&mut func.attrs)?
{
Expand All @@ -59,8 +59,8 @@ pub fn process_functions_in_module(func: &mut syn::ItemFn) -> syn::Result<()> {

/// Transforms a rust fn arg parsed with syn into a method::FnArg
fn wrap_fn_argument<'a>(cap: &'a syn::PatType) -> syn::Result<method::FnArg<'a>> {
let (mutability, by_ref, ident) = match *cap.pat {
syn::Pat::Ident(ref patid) => (&patid.mutability, &patid.by_ref, &patid.ident),
let (mutability, by_ref, ident) = match &*cap.pat {
syn::Pat::Ident(patid) => (&patid.mutability, &patid.by_ref, &patid.ident),
_ => return Err(syn::Error::new_spanned(&cap.pat, "Unsupported argument")),
};

Expand All @@ -85,12 +85,12 @@ fn extract_pyfn_attrs(

for attr in attrs.iter() {
match attr.parse_meta() {
Ok(syn::Meta::List(ref list)) if list.path.is_ident("pyfn") => {
Ok(syn::Meta::List(list)) if list.path.is_ident("pyfn") => {
let meta: Vec<_> = list.nested.iter().cloned().collect();
if meta.len() >= 2 {
// read module name
match meta[0] {
syn::NestedMeta::Meta(syn::Meta::Path(ref path)) => {
match &meta[0] {
syn::NestedMeta::Meta(syn::Meta::Path(path)) => {
modname = Some(path.clone())
}
_ => {
Expand All @@ -101,8 +101,8 @@ fn extract_pyfn_attrs(
}
}
// read Python function name
match meta[1] {
syn::NestedMeta::Lit(syn::Lit::Str(ref lits)) => {
match &meta[1] {
syn::NestedMeta::Lit(syn::Lit::Str(lits)) => {
fnname = Some(syn::Ident::new(&lits.value(), lits.span()));
}
_ => {
Expand Down Expand Up @@ -157,7 +157,7 @@ pub fn add_fn_to_module(
"Unexpected receiver for #[pyfn]",
))
}
syn::FnArg::Typed(ref cap) => {
syn::FnArg::Typed(cap) => {
if pyfn_attrs.pass_module && i == 0 {
if let syn::Type::Reference(tyref) = cap.ty.as_ref() {
if let syn::Type::Path(typath) = tyref.elem.as_ref() {
Expand Down
14 changes: 7 additions & 7 deletions pyo3-derive-backend/src/pyclass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ impl PyClassArgs {
/// either a single word or an assignment expression
fn add_expr(&mut self, expr: &Expr) -> syn::parse::Result<()> {
match expr {
syn::Expr::Path(ref exp) if exp.path.segments.len() == 1 => self.add_path(exp),
syn::Expr::Assign(ref assign) => self.add_assign(assign),
syn::Expr::Path(exp) if exp.path.segments.len() == 1 => self.add_path(exp),
syn::Expr::Assign(assign) => self.add_assign(assign),
_ => Err(syn::Error::new_spanned(expr, "Failed to parse arguments")),
}
}
Expand Down Expand Up @@ -156,7 +156,7 @@ pub fn build_py_class(class: &mut syn::ItemStruct, attr: &PyClassArgs) -> syn::R
let mut descriptors = Vec::new();

check_generics(class)?;
if let syn::Fields::Named(ref mut fields) = class.fields {
if let syn::Fields::Named(fields) = &mut class.fields {
for field in fields.named.iter_mut() {
let field_descs = parse_descriptors(field)?;
if !field_descs.is_empty() {
Expand All @@ -178,10 +178,10 @@ fn parse_descriptors(item: &mut syn::Field) -> syn::Result<Vec<FnType>> {
let mut descs = Vec::new();
let mut new_attrs = Vec::new();
for attr in item.attrs.iter() {
if let Ok(syn::Meta::List(ref list)) = attr.parse_meta() {
if let Ok(syn::Meta::List(list)) = attr.parse_meta() {
if list.path.is_ident("pyo3") {
for meta in list.nested.iter() {
if let syn::NestedMeta::Meta(ref metaitem) = meta {
if let syn::NestedMeta::Meta(metaitem) = meta {
if metaitem.path().is_ident("get") {
descs.push(FnType::Getter(SelfType::Receiver { mutable: false }));
} else if metaitem.path().is_ident("set") {
Expand Down Expand Up @@ -318,7 +318,7 @@ fn impl_class(
let mut has_dict = false;
let mut has_gc = false;
for f in attr.flags.iter() {
if let syn::Expr::Path(ref epath) = f {
if let syn::Expr::Path(epath) = f {
if epath.path == parse_quote! { pyo3::type_flags::WEAKREF } {
has_weakref = true;
} else if epath.path == parse_quote! { pyo3::type_flags::DICT } {
Expand Down Expand Up @@ -469,7 +469,7 @@ fn impl_descriptors(
) -> syn::Result<TokenStream> {
let py_methods: Vec<TokenStream> = descriptors
.iter()
.flat_map(|&(ref field, ref fns)| {
.flat_map(|(field, fns)| {
fns.iter()
.map(|desc| {
let name = field.ident.as_ref().unwrap().unraw();
Expand Down
Loading