commit
527f3c286b
|
@ -0,0 +1 @@
|
|||
Switched from syn 1.x to syn 2.x
|
|
@ -18,7 +18,7 @@ quote = { version = "1", default-features = false }
|
|||
proc-macro2 = { version = "1", default-features = false }
|
||||
|
||||
[dependencies.syn]
|
||||
version = "1.0.85"
|
||||
version = "2"
|
||||
default-features = false
|
||||
features = ["derive", "parsing", "printing", "clone-impls", "full", "extra-traits"]
|
||||
|
||||
|
|
|
@ -146,21 +146,13 @@ pub type FromPyWithAttribute = KeywordAttribute<kw::from_py_with, LitStrValue<Ex
|
|||
pub type CrateAttribute = KeywordAttribute<Token![crate], LitStrValue<Path>>;
|
||||
|
||||
pub fn get_pyo3_options<T: Parse>(attr: &syn::Attribute) -> Result<Option<Punctuated<T, Comma>>> {
|
||||
if is_attribute_ident(attr, "pyo3") {
|
||||
if attr.path().is_ident("pyo3") {
|
||||
attr.parse_args_with(Punctuated::parse_terminated).map(Some)
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_attribute_ident(attr: &syn::Attribute, name: &str) -> bool {
|
||||
if let Some(path_segment) = attr.path.segments.last() {
|
||||
attr.path.segments.len() == 1 && path_segment.ident == name
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Takes attributes from an attribute vector.
|
||||
///
|
||||
/// For each attribute in `attrs`, `extractor` is called. If `extractor` returns `Ok(true)`, then
|
||||
|
|
|
@ -544,7 +544,7 @@ impl FieldPyO3Attributes {
|
|||
}
|
||||
}
|
||||
|
||||
fn verify_and_get_lifetime(generics: &syn::Generics) -> Result<Option<&syn::LifetimeDef>> {
|
||||
fn verify_and_get_lifetime(generics: &syn::Generics) -> Result<Option<&syn::LifetimeParam>> {
|
||||
let mut lifetimes = generics.lifetimes();
|
||||
let lifetime = lifetimes.next();
|
||||
ensure_spanned!(
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use crate::{
|
||||
attributes::{self, get_pyo3_options, is_attribute_ident, take_attributes, NameAttribute},
|
||||
attributes::{self, get_pyo3_options, take_attributes, NameAttribute},
|
||||
deprecations::Deprecations,
|
||||
};
|
||||
use proc_macro2::{Ident, TokenStream};
|
||||
|
@ -64,9 +64,9 @@ impl ConstAttributes {
|
|||
};
|
||||
|
||||
take_attributes(attrs, |attr| {
|
||||
if is_attribute_ident(attr, "classattr") {
|
||||
if attr.path().is_ident("classattr") {
|
||||
ensure_spanned!(
|
||||
attr.tokens.is_empty(),
|
||||
matches!(attr.meta, syn::Meta::Path(..)),
|
||||
attr.span() => "`#[classattr]` does not take any arguments"
|
||||
);
|
||||
attributes.is_class_attr = true;
|
||||
|
|
|
@ -651,8 +651,8 @@ fn parse_method_attributes(
|
|||
}
|
||||
|
||||
for attr in attrs.drain(..) {
|
||||
match attr.parse_meta() {
|
||||
Ok(syn::Meta::Path(name)) => {
|
||||
match attr.meta {
|
||||
syn::Meta::Path(ref name) => {
|
||||
if name.is_ident("new") || name.is_ident("__new__") {
|
||||
set_compound_ty!(MethodTypeAttribute::New, name);
|
||||
} else if name.is_ident("init") || name.is_ident("__init__") {
|
||||
|
@ -680,9 +680,7 @@ fn parse_method_attributes(
|
|||
new_attrs.push(attr)
|
||||
}
|
||||
}
|
||||
Ok(syn::Meta::List(syn::MetaList {
|
||||
path, mut nested, ..
|
||||
})) => {
|
||||
syn::Meta::List(ref ml @ syn::MetaList { ref path, .. }) => {
|
||||
if path.is_ident("new") {
|
||||
set_ty!(MethodTypeAttribute::New, path);
|
||||
} else if path.is_ident("init") {
|
||||
|
@ -699,10 +697,6 @@ fn parse_method_attributes(
|
|||
attr.span() => "inner attribute is not supported for setter and getter"
|
||||
);
|
||||
}
|
||||
ensure_spanned!(
|
||||
nested.len() == 1,
|
||||
attr.span() => "setter/getter requires one value"
|
||||
);
|
||||
|
||||
if path.is_ident("setter") {
|
||||
set_ty!(MethodTypeAttribute::Setter, path);
|
||||
|
@ -715,31 +709,21 @@ fn parse_method_attributes(
|
|||
python_name.span() => "`name` may only be specified once"
|
||||
);
|
||||
|
||||
python_name = match nested.pop().unwrap().into_value() {
|
||||
syn::NestedMeta::Meta(syn::Meta::Path(w)) if w.segments.len() == 1 => {
|
||||
Some(w.segments[0].ident.clone())
|
||||
}
|
||||
syn::NestedMeta::Lit(lit) => match lit {
|
||||
syn::Lit::Str(s) => Some(s.parse()?),
|
||||
_ => {
|
||||
return Err(syn::Error::new_spanned(
|
||||
lit,
|
||||
"setter/getter attribute requires str value",
|
||||
))
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
return Err(syn::Error::new_spanned(
|
||||
nested.first().unwrap(),
|
||||
"expected ident or string literal for property name",
|
||||
))
|
||||
}
|
||||
};
|
||||
if let Ok(ident) = ml.parse_args::<syn::Ident>() {
|
||||
python_name = Some(ident);
|
||||
} else if let Ok(syn::Lit::Str(s)) = ml.parse_args::<syn::Lit>() {
|
||||
python_name = Some(s.parse()?);
|
||||
} else {
|
||||
return Err(syn::Error::new_spanned(
|
||||
ml,
|
||||
"expected ident or string literal for property name",
|
||||
));
|
||||
}
|
||||
} else {
|
||||
new_attrs.push(attr)
|
||||
}
|
||||
}
|
||||
Ok(syn::Meta::NameValue(_)) | Err(_) => new_attrs.push(attr),
|
||||
syn::Meta::NameValue(_) => new_attrs.push(attr),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
//! Code generation for the function that initializes a python module and adds classes and function.
|
||||
|
||||
use crate::{
|
||||
attributes::{
|
||||
self, is_attribute_ident, take_attributes, take_pyo3_options, CrateAttribute, NameAttribute,
|
||||
},
|
||||
attributes::{self, take_attributes, take_pyo3_options, CrateAttribute, NameAttribute},
|
||||
pyfunction::{impl_wrap_pyfunction, PyFunctionOptions},
|
||||
utils::{get_pyo3_crate, PythonDoc},
|
||||
};
|
||||
|
@ -165,7 +163,7 @@ fn get_pyfn_attr(attrs: &mut Vec<syn::Attribute>) -> syn::Result<Option<PyFnArgs
|
|||
let mut pyfn_args: Option<PyFnArgs> = None;
|
||||
|
||||
take_attributes(attrs, |attr| {
|
||||
if is_attribute_ident(attr, "pyfn") {
|
||||
if attr.path().is_ident("pyfn") {
|
||||
ensure_spanned!(
|
||||
pyfn_args.is_none(),
|
||||
attr.span() => "`#[pyfn] may only be specified once"
|
||||
|
|
|
@ -264,7 +264,7 @@ enum Annotated<X, Y> {
|
|||
Struct(Y),
|
||||
}
|
||||
|
||||
impl<X: Spanned, Y: Spanned> Spanned for Annotated<X, Y> {
|
||||
impl<X: Spanned, Y: Spanned> Annotated<X, Y> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::Field(x) => x.span(),
|
||||
|
@ -410,7 +410,7 @@ impl<'a> PyClassEnum<'a> {
|
|||
// "Under the default representation, the specified discriminant is interpreted as an isize
|
||||
// value", so `isize` should be enough by default.
|
||||
let mut repr_type = syn::Ident::new("isize", proc_macro2::Span::call_site());
|
||||
if let Some(attr) = enum_.attrs.iter().find(|attr| attr.path.is_ident("repr")) {
|
||||
if let Some(attr) = enum_.attrs.iter().find(|attr| attr.path().is_ident("repr")) {
|
||||
let args =
|
||||
attr.parse_args_with(Punctuated::<TokenStream, Token![!]>::parse_terminated)?;
|
||||
if let Some(ident) = args
|
||||
|
@ -447,7 +447,7 @@ pub fn build_py_enum(
|
|||
} else if let Some(subclass) = &args.options.subclass {
|
||||
bail_spanned!(subclass.span() => "enums can't be inherited by other classes");
|
||||
} else if enum_.variants.is_empty() {
|
||||
bail_spanned!(enum_.brace_token.span => "#[pyclass] can't be used on enums without any variants");
|
||||
bail_spanned!(enum_.brace_token.span.join() => "#[pyclass] can't be used on enums without any variants");
|
||||
}
|
||||
|
||||
let doc = utils::get_doc(&enum_.attrs, None);
|
||||
|
@ -518,7 +518,7 @@ fn impl_enum(
|
|||
);
|
||||
quote! { #cls::#variant_name => #repr, }
|
||||
});
|
||||
let mut repr_impl: syn::ImplItemMethod = syn::parse_quote! {
|
||||
let mut repr_impl: syn::ImplItemFn = syn::parse_quote! {
|
||||
fn __pyo3__repr__(&self) -> &'static str {
|
||||
match self {
|
||||
#(#variants_repr)*
|
||||
|
@ -537,7 +537,7 @@ fn impl_enum(
|
|||
let variant_name = variant.ident;
|
||||
quote! { #cls::#variant_name => #cls::#variant_name as #repr_type, }
|
||||
});
|
||||
let mut int_impl: syn::ImplItemMethod = syn::parse_quote! {
|
||||
let mut int_impl: syn::ImplItemFn = syn::parse_quote! {
|
||||
fn __pyo3__int__(&self) -> #repr_type {
|
||||
match self {
|
||||
#(#variants_to_int)*
|
||||
|
@ -549,7 +549,7 @@ fn impl_enum(
|
|||
};
|
||||
|
||||
let (default_richcmp, default_richcmp_slot) = {
|
||||
let mut richcmp_impl: syn::ImplItemMethod = syn::parse_quote! {
|
||||
let mut richcmp_impl: syn::ImplItemFn = syn::parse_quote! {
|
||||
fn __pyo3__richcmp__(
|
||||
&self,
|
||||
py: _pyo3::Python,
|
||||
|
@ -623,7 +623,7 @@ fn impl_enum(
|
|||
|
||||
fn generate_default_protocol_slot(
|
||||
cls: &syn::Type,
|
||||
method: &mut syn::ImplItemMethod,
|
||||
method: &mut syn::ImplItemFn,
|
||||
slot: &SlotDef,
|
||||
) -> syn::Result<MethodAndSlotDef> {
|
||||
let spec = FnSpec::parse(
|
||||
|
|
|
@ -23,7 +23,7 @@ impl Parse for Signature {
|
|||
let content;
|
||||
let paren_token = syn::parenthesized!(content in input);
|
||||
|
||||
let items = content.parse_terminated(SignatureItem::parse)?;
|
||||
let items = content.parse_terminated(SignatureItem::parse, Token![,])?;
|
||||
|
||||
Ok(Signature { paren_token, items })
|
||||
}
|
||||
|
|
|
@ -99,7 +99,7 @@ pub fn impl_methods(
|
|||
|
||||
for iimpl in impls.iter_mut() {
|
||||
match iimpl {
|
||||
syn::ImplItem::Method(meth) => {
|
||||
syn::ImplItem::Fn(meth) => {
|
||||
let mut fun_options = PyFunctionOptions::from_attrs(&mut meth.attrs)?;
|
||||
fun_options.krate = fun_options.krate.or_else(|| options.krate.clone());
|
||||
match pymethod::gen_py_method(ty, &mut meth.sig, &mut meth.attrs, fun_options)? {
|
||||
|
@ -299,6 +299,6 @@ fn submit_methods_inventory(
|
|||
fn get_cfg_attributes(attrs: &[syn::Attribute]) -> Vec<&syn::Attribute> {
|
||||
attrs
|
||||
.iter()
|
||||
.filter(|attr| attr.path.is_ident("cfg"))
|
||||
.filter(|attr| attr.path().is_ident("cfg"))
|
||||
.collect()
|
||||
}
|
||||
|
|
|
@ -541,7 +541,11 @@ pub fn impl_py_setter_def(
|
|||
|
||||
let mut cfg_attrs = TokenStream::new();
|
||||
if let PropertyType::Descriptor { field, .. } = &property_type {
|
||||
for attr in field.attrs.iter().filter(|attr| attr.path.is_ident("cfg")) {
|
||||
for attr in field
|
||||
.attrs
|
||||
.iter()
|
||||
.filter(|attr| attr.path().is_ident("cfg"))
|
||||
{
|
||||
attr.to_tokens(&mut cfg_attrs);
|
||||
}
|
||||
}
|
||||
|
@ -667,7 +671,11 @@ pub fn impl_py_getter_def(
|
|||
|
||||
let mut cfg_attrs = TokenStream::new();
|
||||
if let PropertyType::Descriptor { field, .. } = &property_type {
|
||||
for attr in field.attrs.iter().filter(|attr| attr.path.is_ident("cfg")) {
|
||||
for attr in field
|
||||
.attrs
|
||||
.iter()
|
||||
.filter(|attr| attr.path().is_ident("cfg"))
|
||||
{
|
||||
attr.to_tokens(&mut cfg_attrs);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,18 +80,18 @@ pub fn get_doc(attrs: &[syn::Attribute], mut text_signature: Option<String>) ->
|
|||
let mut current_part = text_signature.unwrap_or_default();
|
||||
|
||||
for attr in attrs.iter() {
|
||||
if attr.path.is_ident("doc") {
|
||||
if let Ok(DocArgs {
|
||||
_eq_token,
|
||||
token_stream,
|
||||
}) = syn::parse2(attr.tokens.clone())
|
||||
{
|
||||
if attr.path().is_ident("doc") {
|
||||
if let Ok(nv) = attr.meta.require_name_value() {
|
||||
if !first {
|
||||
current_part.push('\n');
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
if let Ok(syn::Lit::Str(lit_str)) = syn::parse2(token_stream.clone()) {
|
||||
if let syn::Expr::Lit(syn::ExprLit {
|
||||
lit: syn::Lit::Str(lit_str),
|
||||
..
|
||||
}) = &nv.value
|
||||
{
|
||||
// Strip single left space from literal strings, if needed.
|
||||
// e.g. `/// Hello world` expands to #[doc = " Hello world"]
|
||||
let doc_line = lit_str.value();
|
||||
|
@ -101,7 +101,7 @@ pub fn get_doc(attrs: &[syn::Attribute], mut text_signature: Option<String>) ->
|
|||
// Reset the string buffer, write that part, and then push this macro part too.
|
||||
parts.push(current_part.to_token_stream());
|
||||
current_part.clear();
|
||||
parts.push(token_stream);
|
||||
parts.push(nv.value.to_token_stream());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ pub fn get_doc(attrs: &[syn::Attribute], mut text_signature: Option<String>) ->
|
|||
let mut tokens = TokenStream::new();
|
||||
|
||||
syn::Ident::new("concat", Span::call_site()).to_tokens(&mut tokens);
|
||||
syn::token::Bang(Span::call_site()).to_tokens(&mut tokens);
|
||||
syn::token::Not(Span::call_site()).to_tokens(&mut tokens);
|
||||
syn::token::Bracket(Span::call_site()).surround(&mut tokens, |tokens| {
|
||||
parts.to_tokens(tokens);
|
||||
syn::token::Comma(Span::call_site()).to_tokens(tokens);
|
||||
|
@ -137,22 +137,6 @@ impl quote::ToTokens for PythonDoc {
|
|||
}
|
||||
}
|
||||
|
||||
struct DocArgs {
|
||||
_eq_token: syn::Token![=],
|
||||
token_stream: TokenStream,
|
||||
}
|
||||
|
||||
impl syn::parse::Parse for DocArgs {
|
||||
fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
|
||||
let this = Self {
|
||||
_eq_token: input.parse()?,
|
||||
token_stream: input.parse()?,
|
||||
};
|
||||
ensure_spanned!(input.is_empty(), input.span() => "expected end of doc attribute");
|
||||
Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ensure_not_async_fn(sig: &syn::Signature) -> syn::Result<()> {
|
||||
if let Some(asyncness) = &sig.asyncness {
|
||||
bail_spanned!(
|
||||
|
|
|
@ -21,5 +21,5 @@ abi3 = ["pyo3-macros-backend/abi3"]
|
|||
[dependencies]
|
||||
proc-macro2 = { version = "1", default-features = false }
|
||||
quote = "1"
|
||||
syn = { version = "1.0.85", features = ["full", "extra-traits"] }
|
||||
syn = { version = "2", features = ["full", "extra-traits"] }
|
||||
pyo3-macros-backend = { path = "../pyo3-macros-backend", version = "=0.19.0" }
|
||||
|
|
Loading…
Reference in New Issue