Skip to content

Commit 519fd61

Browse files
authored
Merge pull request #1272 from davidhewitt/bump-msrv
msrv: bump to 1.45
2 parents 470716e + 9617edf commit 519fd61

25 files changed

+121
-148
lines changed

.github/workflows/ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ jobs:
5858
platform: { os: "windows-latest" }
5959
include:
6060
# Test minimal supported Rust version
61-
- rust: 1.39.0
61+
- rust: 1.45.0
6262
python-version: 3.9
6363
platform: { os: "ubuntu-latest", python-architecture: "x64", rust-target: "x86_64-unknown-linux-gnu" }
6464
msrv: "MSRV"

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
88
## [Unreleased]
99
### Packaging
1010
- Drop support for Python 3.5 (as it is now end-of-life). [#1250](https://github.com/PyO3/pyo3/pull/1250)
11+
- Bump minimum supported Rust version to 1.45. [#1272](https://github.com/PyO3/pyo3/pull/1272)
12+
- Bump indoc dependency to 1.0. [#1272](https://github.com/PyO3/pyo3/pull/1272)
13+
- Bump paste dependency to 1.0. [#1272](https://github.com/PyO3/pyo3/pull/1272)
1114

1215
### Added
1316
- 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)

Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@ edition = "2018"
1616

1717
[dependencies]
1818
ctor = { version = "0.1", optional = true }
19-
indoc = { version = "0.3.4", optional = true }
19+
indoc = { version = "1.0.3", optional = true }
2020
inventory = { version = "0.1.4", optional = true }
2121
libc = "0.2.62"
2222
parking_lot = "0.11.0"
2323
num-bigint = { version = "0.3", optional = true }
2424
num-complex = { version = "0.3", optional = true }
25-
paste = { version = "0.1.6", optional = true }
25+
paste = { version = "1.0.3", optional = true }
2626
pyo3cls = { path = "pyo3cls", version = "=0.12.3", optional = true }
2727
unindent = { version = "0.1.4", optional = true }
2828
hashbrown = { version = "0.9", optional = true }

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
[![Actions Status](https://github.com/PyO3/pyo3/workflows/Test/badge.svg)](https://github.com/PyO3/pyo3/actions)
44
[![codecov](https://codecov.io/gh/PyO3/pyo3/branch/master/graph/badge.svg)](https://codecov.io/gh/PyO3/pyo3)
55
[![crates.io](http://meritbadge.herokuapp.com/pyo3)](https://crates.io/crates/pyo3)
6-
[![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)
6+
[![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)
77
[![Join the dev chat](https://img.shields.io/gitter/room/nwjs/nw.js.svg)](https://gitter.im/PyO3/Lobby)
88

99
[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.
@@ -18,7 +18,7 @@ A comparison with rust-cpython can be found [in the guide](https://pyo3.rs/maste
1818

1919
## Usage
2020

21-
PyO3 supports Python 3.6 and up. The minimum required Rust version is 1.39.0.
21+
PyO3 supports Python 3.6 and up. The minimum required Rust version is 1.45.0.
2222

2323
Building with PyPy is also possible (via cpyext) for Python 3.6, targeted PyPy version is 7.3+.
2424
Please refer to the [pypy section in the guide](https://pyo3.rs/master/pypy.html).

build.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -341,16 +341,16 @@ fn find_sysconfigdata(cross: &CrossCompileConfig) -> Result<PathBuf> {
341341
/// recursive search for _sysconfigdata, returns all possibilities of sysconfigdata paths
342342
fn search_lib_dir(path: impl AsRef<Path>, cross: &CrossCompileConfig) -> Vec<PathBuf> {
343343
let mut sysconfig_paths = vec![];
344-
let version_pat = if let Some(ref v) = cross.version {
344+
let version_pat = if let Some(v) = &cross.version {
345345
format!("python{}", v)
346346
} else {
347347
"python3.".into()
348348
};
349349
for f in fs::read_dir(path).expect("Path does not exist") {
350-
let sysc = match f {
351-
Ok(ref f) if starts_with(f, "_sysconfigdata") && ends_with(f, "py") => vec![f.path()],
352-
Ok(ref f) if starts_with(f, "build") => search_lib_dir(f.path(), cross),
353-
Ok(ref f) if starts_with(f, "lib.") => {
350+
let sysc = match &f {
351+
Ok(f) if starts_with(f, "_sysconfigdata") && ends_with(f, "py") => vec![f.path()],
352+
Ok(f) if starts_with(f, "build") => search_lib_dir(f.path(), cross),
353+
Ok(f) if starts_with(f, "lib.") => {
354354
let name = f.file_name();
355355
// check if right target os
356356
if !name.to_string_lossy().contains(if cross.os == "android" {
@@ -366,7 +366,7 @@ fn search_lib_dir(path: impl AsRef<Path>, cross: &CrossCompileConfig) -> Vec<Pat
366366
}
367367
search_lib_dir(f.path(), cross)
368368
}
369-
Ok(ref f) if starts_with(f, &version_pat) => search_lib_dir(f.path(), cross),
369+
Ok(f) if starts_with(f, &version_pat) => search_lib_dir(f.path(), cross),
370370
_ => continue,
371371
};
372372
sysconfig_paths.extend(sysc);
@@ -569,7 +569,7 @@ fn run_python_script(interpreter: &Path, script: &str) -> Result<String> {
569569
);
570570
}
571571
}
572-
Ok(ref ok) if !ok.status.success() => bail!("Python script failed: {}"),
572+
Ok(ok) if !ok.status.success() => bail!("Python script failed: {}"),
573573
Ok(ok) => Ok(String::from_utf8(ok.stdout)?),
574574
}
575575
}

guide/src/class/protocols.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ struct ClassWithGCSupport {
175175
#[pyproto]
176176
impl PyGCProtocol for ClassWithGCSupport {
177177
fn __traverse__(&self, visit: PyVisit) -> Result<(), PyTraverseError> {
178-
if let Some(ref obj) = self.obj {
178+
if let Some(obj) = &self.obj {
179179
visit.call(obj)?
180180
}
181181
Ok(())

pyo3-derive-backend/src/from_pyobject.rs

+8-10
Original file line numberDiff line numberDiff line change
@@ -137,13 +137,10 @@ impl<'a> Container<'a> {
137137
}
138138
let style = match (fields, transparent) {
139139
(Fields::Unnamed(_), true) => ContainerType::TupleNewtype,
140-
(Fields::Unnamed(unnamed), false) => {
141-
if unnamed.unnamed.len() == 1 {
142-
ContainerType::TupleNewtype
143-
} else {
144-
ContainerType::Tuple(unnamed.unnamed.len())
145-
}
146-
}
140+
(Fields::Unnamed(unnamed), false) => match unnamed.unnamed.len() {
141+
1 => ContainerType::TupleNewtype,
142+
len => ContainerType::Tuple(len),
143+
},
147144
(Fields::Named(named), true) => {
148145
let field = named
149146
.named
@@ -457,14 +454,15 @@ fn get_pyo3_meta_list(attrs: &[Attribute]) -> Result<MetaList> {
457454
}
458455

459456
fn verify_and_get_lifetime(generics: &syn::Generics) -> Result<Option<&syn::LifetimeDef>> {
460-
let lifetimes = generics.lifetimes().collect::<Vec<_>>();
461-
if lifetimes.len() > 1 {
457+
let mut lifetimes = generics.lifetimes();
458+
let lifetime = lifetimes.next();
459+
if lifetimes.next().is_some() {
462460
return Err(spanned_err(
463461
&generics,
464462
"FromPyObject can be derived with at most one lifetime parameter.",
465463
));
466464
}
467-
Ok(lifetimes.into_iter().next())
465+
Ok(lifetime)
468466
}
469467

470468
/// Derive FromPyObject for enums and structs.

pyo3-derive-backend/src/method.rs

+19-25
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ pub struct FnSpec<'a> {
100100
pub fn get_return_info(output: &syn::ReturnType) -> syn::Type {
101101
match output {
102102
syn::ReturnType::Default => syn::Type::Infer(syn::parse_quote! {_}),
103-
syn::ReturnType::Type(_, ref ty) => *ty.clone(),
103+
syn::ReturnType::Type(_, ty) => *ty.clone(),
104104
}
105105
}
106106

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

@@ -198,14 +198,12 @@ impl<'a> FnSpec<'a> {
198198
"Unexpected receiver for method",
199199
));
200200
}
201-
syn::FnArg::Typed(syn::PatType {
202-
ref pat, ref ty, ..
203-
}) => {
204-
let (ident, by_ref, mutability) = match **pat {
201+
syn::FnArg::Typed(syn::PatType { pat, ty, .. }) => {
202+
let (ident, by_ref, mutability) = match &**pat {
205203
syn::Pat::Ident(syn::PatIdent {
206-
ref ident,
207-
ref by_ref,
208-
ref mutability,
204+
ident,
205+
by_ref,
206+
mutability,
209207
..
210208
}) => (ident, by_ref, mutability),
211209
_ => {
@@ -267,7 +265,7 @@ impl<'a> FnSpec<'a> {
267265

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

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

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

303301
pub fn is_kw_only(&self, name: &syn::Ident) -> bool {
304302
for s in self.attrs.iter() {
305-
if let Argument::Kwarg(ref path, _) = s {
303+
if let Argument::Kwarg(path, _) = s {
306304
if path.is_ident(name) {
307305
return true;
308306
}
@@ -341,7 +339,7 @@ fn parse_method_attributes(
341339

342340
for attr in attrs.iter() {
343341
match attr.parse_meta()? {
344-
syn::Meta::Path(ref name) => {
342+
syn::Meta::Path(name) => {
345343
if name.is_ident("new") || name.is_ident("__new__") {
346344
set_ty!(MethodTypeAttribute::New, name);
347345
} else if name.is_ident("init") || name.is_ident("__init__") {
@@ -373,11 +371,7 @@ fn parse_method_attributes(
373371
new_attrs.push(attr.clone())
374372
}
375373
}
376-
syn::Meta::List(syn::MetaList {
377-
ref path,
378-
ref nested,
379-
..
380-
}) => {
374+
syn::Meta::List(syn::MetaList { path, nested, .. }) => {
381375
if path.is_ident("new") {
382376
set_ty!(MethodTypeAttribute::New, path);
383377
} else if path.is_ident("init") {
@@ -408,11 +402,11 @@ fn parse_method_attributes(
408402
};
409403

410404
property_name = match nested.first().unwrap() {
411-
syn::NestedMeta::Meta(syn::Meta::Path(ref w)) if w.segments.len() == 1 => {
405+
syn::NestedMeta::Meta(syn::Meta::Path(w)) if w.segments.len() == 1 => {
412406
Some(w.segments[0].ident.clone())
413407
}
414-
syn::NestedMeta::Lit(ref lit) => match *lit {
415-
syn::Lit::Str(ref s) => Some(s.parse()?),
408+
syn::NestedMeta::Lit(lit) => match lit {
409+
syn::Lit::Str(s) => Some(s.parse()?),
416410
_ => {
417411
return Err(syn::Error::new_spanned(
418412
lit,
@@ -428,7 +422,7 @@ fn parse_method_attributes(
428422
}
429423
};
430424
} else if path.is_ident("args") {
431-
let attrs = PyFunctionAttr::from_meta(nested)?;
425+
let attrs = PyFunctionAttr::from_meta(&nested)?;
432426
args.extend(attrs.arguments)
433427
} else {
434428
new_attrs.push(attr.clone())

pyo3-derive-backend/src/module.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ pub fn process_functions_in_module(func: &mut syn::ItemFn) -> syn::Result<()> {
3535
let mut stmts: Vec<syn::Stmt> = Vec::new();
3636

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

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

@@ -85,12 +85,12 @@ fn extract_pyfn_attrs(
8585

8686
for attr in attrs.iter() {
8787
match attr.parse_meta() {
88-
Ok(syn::Meta::List(ref list)) if list.path.is_ident("pyfn") => {
88+
Ok(syn::Meta::List(list)) if list.path.is_ident("pyfn") => {
8989
let meta: Vec<_> = list.nested.iter().cloned().collect();
9090
if meta.len() >= 2 {
9191
// read module name
92-
match meta[0] {
93-
syn::NestedMeta::Meta(syn::Meta::Path(ref path)) => {
92+
match &meta[0] {
93+
syn::NestedMeta::Meta(syn::Meta::Path(path)) => {
9494
modname = Some(path.clone())
9595
}
9696
_ => {
@@ -101,8 +101,8 @@ fn extract_pyfn_attrs(
101101
}
102102
}
103103
// read Python function name
104-
match meta[1] {
105-
syn::NestedMeta::Lit(syn::Lit::Str(ref lits)) => {
104+
match &meta[1] {
105+
syn::NestedMeta::Lit(syn::Lit::Str(lits)) => {
106106
fnname = Some(syn::Ident::new(&lits.value(), lits.span()));
107107
}
108108
_ => {
@@ -157,7 +157,7 @@ pub fn add_fn_to_module(
157157
"Unexpected receiver for #[pyfn]",
158158
))
159159
}
160-
syn::FnArg::Typed(ref cap) => {
160+
syn::FnArg::Typed(cap) => {
161161
if pyfn_attrs.pass_module && i == 0 {
162162
if let syn::Type::Reference(tyref) = cap.ty.as_ref() {
163163
if let syn::Type::Path(typath) = tyref.elem.as_ref() {

pyo3-derive-backend/src/pyclass.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ impl PyClassArgs {
5656
/// either a single word or an assignment expression
5757
fn add_expr(&mut self, expr: &Expr) -> syn::parse::Result<()> {
5858
match expr {
59-
syn::Expr::Path(ref exp) if exp.path.segments.len() == 1 => self.add_path(exp),
60-
syn::Expr::Assign(ref assign) => self.add_assign(assign),
59+
syn::Expr::Path(exp) if exp.path.segments.len() == 1 => self.add_path(exp),
60+
syn::Expr::Assign(assign) => self.add_assign(assign),
6161
_ => Err(syn::Error::new_spanned(expr, "Failed to parse arguments")),
6262
}
6363
}
@@ -156,7 +156,7 @@ pub fn build_py_class(class: &mut syn::ItemStruct, attr: &PyClassArgs) -> syn::R
156156
let mut descriptors = Vec::new();
157157

158158
check_generics(class)?;
159-
if let syn::Fields::Named(ref mut fields) = class.fields {
159+
if let syn::Fields::Named(fields) = &mut class.fields {
160160
for field in fields.named.iter_mut() {
161161
let field_descs = parse_descriptors(field)?;
162162
if !field_descs.is_empty() {
@@ -178,10 +178,10 @@ fn parse_descriptors(item: &mut syn::Field) -> syn::Result<Vec<FnType>> {
178178
let mut descs = Vec::new();
179179
let mut new_attrs = Vec::new();
180180
for attr in item.attrs.iter() {
181-
if let Ok(syn::Meta::List(ref list)) = attr.parse_meta() {
181+
if let Ok(syn::Meta::List(list)) = attr.parse_meta() {
182182
if list.path.is_ident("pyo3") {
183183
for meta in list.nested.iter() {
184-
if let syn::NestedMeta::Meta(ref metaitem) = meta {
184+
if let syn::NestedMeta::Meta(metaitem) = meta {
185185
if metaitem.path().is_ident("get") {
186186
descs.push(FnType::Getter(SelfType::Receiver { mutable: false }));
187187
} else if metaitem.path().is_ident("set") {
@@ -318,7 +318,7 @@ fn impl_class(
318318
let mut has_dict = false;
319319
let mut has_gc = false;
320320
for f in attr.flags.iter() {
321-
if let syn::Expr::Path(ref epath) = f {
321+
if let syn::Expr::Path(epath) = f {
322322
if epath.path == parse_quote! { pyo3::type_flags::WEAKREF } {
323323
has_weakref = true;
324324
} else if epath.path == parse_quote! { pyo3::type_flags::DICT } {
@@ -469,7 +469,7 @@ fn impl_descriptors(
469469
) -> syn::Result<TokenStream> {
470470
let py_methods: Vec<TokenStream> = descriptors
471471
.iter()
472-
.flat_map(|&(ref field, ref fns)| {
472+
.flat_map(|(field, fns)| {
473473
fns.iter()
474474
.map(|desc| {
475475
let name = field.ident.as_ref().unwrap().unraw();

0 commit comments

Comments
 (0)