deprecate pyclass name without quotes
This commit is contained in:
parent
7dadf59fde
commit
5133f81e6d
|
@ -21,7 +21,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||||
- Add `PyAny::is_instance()` method. [#1276](https://github.com/PyO3/pyo3/pull/1276)
|
- Add `PyAny::is_instance()` method. [#1276](https://github.com/PyO3/pyo3/pull/1276)
|
||||||
- Add support for conversion between `char` and `PyString`. [#1282](https://github.com/PyO3/pyo3/pull/1282)
|
- Add support for conversion between `char` and `PyString`. [#1282](https://github.com/PyO3/pyo3/pull/1282)
|
||||||
- Add FFI definitions for `PyBuffer_SizeFromFormat`, `PyObject_LengthHint`, `PyObject_CallNoArgs`, `PyObject_CallOneArg`, `PyObject_CallMethodNoArgs`, `PyObject_CallMethodOneArg`, `PyObject_VectorcallDict`, and `PyObject_VectorcallMethod`. [#1287](https://github.com/PyO3/pyo3/pull/1287)
|
- Add FFI definitions for `PyBuffer_SizeFromFormat`, `PyObject_LengthHint`, `PyObject_CallNoArgs`, `PyObject_CallOneArg`, `PyObject_CallMethodNoArgs`, `PyObject_CallMethodOneArg`, `PyObject_VectorcallDict`, and `PyObject_VectorcallMethod`. [#1287](https://github.com/PyO3/pyo3/pull/1287)
|
||||||
- Allow the use of a string literal in `#[pyclass(name = "string literal")]`. [#1295](https://github.com/PyO3/pyo3/pull/1295)
|
|
||||||
- Add section about Python::check_signals to the FAQ page of the user guide. [#1301](https://github.com/PyO3/pyo3/pull/1301)
|
- Add section about Python::check_signals to the FAQ page of the user guide. [#1301](https://github.com/PyO3/pyo3/pull/1301)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
@ -34,6 +33,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||||
- Rename `PyTypeInfo::is_instance` and `PyTypeInfo::is_exact_instance` to `PyTypeInfo::is_type_of` and `PyTypeInfo::is_exact_type_of`. [#1278](https://github.com/PyO3/pyo3/pull/1278)
|
- Rename `PyTypeInfo::is_instance` and `PyTypeInfo::is_exact_instance` to `PyTypeInfo::is_type_of` and `PyTypeInfo::is_exact_type_of`. [#1278](https://github.com/PyO3/pyo3/pull/1278)
|
||||||
- Optimize `PyAny::call0`, `Py::call0` and `PyAny::call_method0` and `Py::call_method0` on Python 3.9 and up. [#1287](https://github.com/PyO3/pyo3/pull/1285)
|
- Optimize `PyAny::call0`, `Py::call0` and `PyAny::call_method0` and `Py::call_method0` on Python 3.9 and up. [#1287](https://github.com/PyO3/pyo3/pull/1285)
|
||||||
- Deprecate `Python::is_instance`, `Python::is_subclass`, `Python::release`, and `Python::xdecref`. [#1292](https://github.com/PyO3/pyo3/pull/1292)
|
- Deprecate `Python::is_instance`, `Python::is_subclass`, `Python::release`, and `Python::xdecref`. [#1292](https://github.com/PyO3/pyo3/pull/1292)
|
||||||
|
- Require double-quotes for pyclass name argument e.g `#[pyclass(name = "MyClass")]`. [#1303](https://github.com/PyO3/pyo3/pull/1303)
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
- Remove deprecated ffi definitions `PyUnicode_AsUnicodeCopy`, `PyUnicode_GetMax`, `_Py_CheckRecursionLimit`, `PyObject_AsCharBuffer`, `PyObject_AsReadBuffer`, `PyObject_CheckReadBuffer` and `PyObject_AsWriteBuffer`, which will be removed in Python 3.10. [#1217](https://github.com/PyO3/pyo3/pull/1217)
|
- Remove deprecated ffi definitions `PyUnicode_AsUnicodeCopy`, `PyUnicode_GetMax`, `_Py_CheckRecursionLimit`, `PyObject_AsCharBuffer`, `PyObject_AsReadBuffer`, `PyObject_CheckReadBuffer` and `PyObject_AsWriteBuffer`, which will be removed in Python 3.10. [#1217](https://github.com/PyO3/pyo3/pull/1217)
|
||||||
|
|
|
@ -15,7 +15,7 @@ use syn::{parse_quote, Expr, Token};
|
||||||
/// The parsed arguments of the pyclass macro
|
/// The parsed arguments of the pyclass macro
|
||||||
pub struct PyClassArgs {
|
pub struct PyClassArgs {
|
||||||
pub freelist: Option<syn::Expr>,
|
pub freelist: Option<syn::Expr>,
|
||||||
pub name: Option<syn::ExprPath>,
|
pub name: Option<syn::Ident>,
|
||||||
pub flags: Vec<syn::Expr>,
|
pub flags: Vec<syn::Expr>,
|
||||||
pub base: syn::TypePath,
|
pub base: syn::TypePath,
|
||||||
pub has_extends: bool,
|
pub has_extends: bool,
|
||||||
|
@ -96,15 +96,26 @@ impl PyClassArgs {
|
||||||
lit: syn::Lit::Str(lit),
|
lit: syn::Lit::Str(lit),
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
self.name = match lit.parse() {
|
self.name = Some(lit.parse().map_err(|_| {
|
||||||
Ok(name) => Some(name),
|
syn::Error::new_spanned(
|
||||||
Err(..) => expected!("type name (e.g., Name or \"Name\")"),
|
lit,
|
||||||
}
|
"expected a single identifier in double-quotes",
|
||||||
|
)
|
||||||
|
})?);
|
||||||
}
|
}
|
||||||
syn::Expr::Path(exp) if exp.path.segments.len() == 1 => {
|
syn::Expr::Path(exp) if exp.path.segments.len() == 1 => {
|
||||||
self.name = Some(exp.clone());
|
return Err(syn::Error::new_spanned(
|
||||||
|
exp,
|
||||||
|
format!(
|
||||||
|
concat!(
|
||||||
|
"since PyO3 0.13 a pyclass name should be in double-quotes, ",
|
||||||
|
"e.g. \"{}\""
|
||||||
|
),
|
||||||
|
exp.path.get_ident().expect("path has 1 segment")
|
||||||
|
),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
_ => expected!("type name (e.g., Name or \"Name\")"),
|
_ => expected!("type name (e.g. \"Name\")"),
|
||||||
},
|
},
|
||||||
"extends" => match &**right {
|
"extends" => match &**right {
|
||||||
syn::Expr::Path(exp) => {
|
syn::Expr::Path(exp) => {
|
||||||
|
@ -271,11 +282,8 @@ fn impl_proto_inventory(cls: &syn::Ident) -> TokenStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_class_python_name(cls: &syn::Ident, attr: &PyClassArgs) -> TokenStream {
|
fn get_class_python_name<'a>(cls: &'a syn::Ident, attr: &'a PyClassArgs) -> &'a syn::Ident {
|
||||||
match &attr.name {
|
attr.name.as_ref().unwrap_or(cls)
|
||||||
Some(name) => quote! { #name },
|
|
||||||
None => quote! { #cls },
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn impl_class(
|
fn impl_class(
|
||||||
|
|
|
@ -76,9 +76,9 @@ fn parse_text_signature_attr<T: Display + quote::ToTokens + ?Sized>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_text_signature_attrs<T: Display + quote::ToTokens + ?Sized>(
|
pub fn parse_text_signature_attrs(
|
||||||
attrs: &mut Vec<syn::Attribute>,
|
attrs: &mut Vec<syn::Attribute>,
|
||||||
python_name: &T,
|
python_name: &syn::Ident,
|
||||||
) -> syn::Result<Option<syn::LitStr>> {
|
) -> syn::Result<Option<syn::LitStr>> {
|
||||||
let mut text_signature = None;
|
let mut text_signature = None;
|
||||||
let mut attrs_out = Vec::with_capacity(attrs.len());
|
let mut attrs_out = Vec::with_capacity(attrs.len());
|
||||||
|
|
|
@ -66,7 +66,7 @@ fn class_with_docstr() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyclass(name=CustomName)]
|
#[pyclass(name = "CustomName")]
|
||||||
struct EmptyClass2 {}
|
struct EmptyClass2 {}
|
||||||
|
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
|
@ -79,17 +79,12 @@ impl EmptyClass2 {
|
||||||
fn bar_static() {}
|
fn bar_static() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyclass(name = "CustomName")]
|
|
||||||
struct EmptyClass3 {}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn custom_names() {
|
fn custom_names() {
|
||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
let typeobj = py.get_type::<EmptyClass2>();
|
let typeobj = py.get_type::<EmptyClass2>();
|
||||||
let typeobj2 = py.get_type::<EmptyClass3>();
|
|
||||||
py_assert!(py, typeobj, "typeobj.__name__ == 'CustomName'");
|
py_assert!(py, typeobj, "typeobj.__name__ == 'CustomName'");
|
||||||
py_assert!(py, typeobj2, "typeobj2.__name__ == 'CustomName'");
|
|
||||||
py_assert!(py, typeobj, "typeobj.custom_fn.__name__ == 'custom_fn'");
|
py_assert!(py, typeobj, "typeobj.custom_fn.__name__ == 'custom_fn'");
|
||||||
py_assert!(
|
py_assert!(
|
||||||
py,
|
py,
|
||||||
|
|
|
@ -9,6 +9,12 @@ struct InvalidExtends {}
|
||||||
#[pyclass(name = m::MyClass)]
|
#[pyclass(name = m::MyClass)]
|
||||||
struct InvalidName {}
|
struct InvalidName {}
|
||||||
|
|
||||||
|
#[pyclass(name = "Custom Name")]
|
||||||
|
struct InvalidName2 {}
|
||||||
|
|
||||||
|
#[pyclass(name = CustomName)]
|
||||||
|
struct DeprecatedName {}
|
||||||
|
|
||||||
#[pyclass(module = my_module)]
|
#[pyclass(module = my_module)]
|
||||||
struct InvalidModule {}
|
struct InvalidModule {}
|
||||||
|
|
||||||
|
|
|
@ -10,20 +10,32 @@ error: Expected type path (e.g., my_mod::BaseClass)
|
||||||
6 | #[pyclass(extends = "PyDict")]
|
6 | #[pyclass(extends = "PyDict")]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
||||||
error: Expected type name (e.g., Name or "Name")
|
error: Expected type name (e.g. "Name")
|
||||||
--> $DIR/invalid_pyclass_args.rs:9:18
|
--> $DIR/invalid_pyclass_args.rs:9:18
|
||||||
|
|
|
|
||||||
9 | #[pyclass(name = m::MyClass)]
|
9 | #[pyclass(name = m::MyClass)]
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: Expected string literal (e.g., "my_mod")
|
error: expected a single identifier in double-quotes
|
||||||
--> $DIR/invalid_pyclass_args.rs:12:20
|
--> $DIR/invalid_pyclass_args.rs:12:18
|
||||||
|
|
|
|
||||||
12 | #[pyclass(module = my_module)]
|
12 | #[pyclass(name = "Custom Name")]
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: since PyO3 0.13 a pyclass name should be in double-quotes, e.g. "CustomName"
|
||||||
|
--> $DIR/invalid_pyclass_args.rs:15:18
|
||||||
|
|
|
||||||
|
15 | #[pyclass(name = CustomName)]
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
|
error: Expected string literal (e.g., "my_mod")
|
||||||
|
--> $DIR/invalid_pyclass_args.rs:18:20
|
||||||
|
|
|
||||||
|
18 | #[pyclass(module = my_module)]
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: Expected one of gc/weakref/subclass/dict/unsendable
|
error: Expected one of gc/weakref/subclass/dict/unsendable
|
||||||
--> $DIR/invalid_pyclass_args.rs:15:11
|
--> $DIR/invalid_pyclass_args.rs:21:11
|
||||||
|
|
|
|
||||||
15 | #[pyclass(weakrev)]
|
21 | #[pyclass(weakrev)]
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
Loading…
Reference in New Issue