From d61a9db0f35cb5d11c65e5409ac55265a2e04171 Mon Sep 17 00:00:00 2001 From: Martin Larralde Date: Thu, 30 May 2019 20:44:09 -0700 Subject: [PATCH 01/10] Add `MODULE` const value to `PyTypeInfo` trait --- src/type_object.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/type_object.rs b/src/type_object.rs index 15b525fd60c..d1e3242cd95 100644 --- a/src/type_object.rs +++ b/src/type_object.rs @@ -25,6 +25,9 @@ pub trait PyTypeInfo { /// Class name const NAME: &'static str; + /// Module name, if any + const MODULE: Option<&'static str>; + /// Class doc string const DESCRIPTION: &'static str = "\0"; @@ -256,7 +259,7 @@ where let gil = Python::acquire_gil(); let py = gil.python(); - initialize_type::(py, None).unwrap_or_else(|_| { + initialize_type::(py, ::MODULE).unwrap_or_else(|_| { panic!("An error occurred while initializing class {}", Self::NAME) }); } From 80c34d3073d2d792361d7980b81bbbfde95b39b6 Mon Sep 17 00:00:00 2001 From: Martin Larralde Date: Thu, 30 May 2019 20:44:42 -0700 Subject: [PATCH 02/10] Allow setting module name in `pyclass` macro arguments --- pyo3-derive-backend/src/pyclass.rs | 31 ++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/pyo3-derive-backend/src/pyclass.rs b/pyo3-derive-backend/src/pyclass.rs index 5332f49c7df..837f1bfda65 100644 --- a/pyo3-derive-backend/src/pyclass.rs +++ b/pyo3-derive-backend/src/pyclass.rs @@ -15,6 +15,7 @@ pub struct PyClassArgs { pub name: Option, pub flags: Vec, pub base: syn::TypePath, + pub module: Option, } impl Parse for PyClassArgs { @@ -34,6 +35,7 @@ impl Default for PyClassArgs { PyClassArgs { freelist: None, name: None, + module: None, // We need the 0 as value for the constant we're later building using quote for when there // are no other flags flags: vec![parse_quote! {0}], @@ -94,6 +96,29 @@ impl PyClassArgs { )); } }, + + "module" => match *assign.right { + syn::Expr::Lit(ref exp) => { + match exp.lit { + syn::Lit::Str(ref lit) => { + self.module = Some(lit.clone()); + } + _ => { + return Err(syn::Error::new_spanned( + *assign.right.clone(), + "Wrong format for module", + )); + } + } + }, + _ => { + return Err(syn::Error::new_spanned( + *assign.right.clone(), + "Wrong format for module", + )); + } + } + _ => { return Err(syn::Error::new_spanned( *assign.left.clone(), @@ -298,6 +323,11 @@ fn impl_class( } else { quote! {0} }; + let module = if let Some(m) = &attr.module { + quote! { Some(#m) } + } else { + quote! { None } + }; let inventory_impl = impl_inventory(&cls); @@ -310,6 +340,7 @@ fn impl_class( type BaseType = #base; const NAME: &'static str = #cls_name; + const MODULE: Option<&'static str> = #module; const DESCRIPTION: &'static str = #doc; const FLAGS: usize = #(#flags)|*; From a79af1b6806510e1dad846e2e8e6b4e1c9066007 Mon Sep 17 00:00:00 2001 From: Martin Larralde Date: Thu, 30 May 2019 21:39:30 -0700 Subject: [PATCH 03/10] Add `$module` argument to `pyobject_native_type` macro in `pyo3::types` --- src/types/mod.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/types/mod.rs b/src/types/mod.rs index fb92102682b..8a88160be78 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -79,9 +79,9 @@ macro_rules! pyobject_native_type_named ( #[macro_export] macro_rules! pyobject_native_type ( - ($name: ty, $typeobject: expr, $checkfunction: path $(,$type_param: ident)*) => { + ($name: ty, $typeobject: expr, $module: expr, $checkfunction: path $(,$type_param: ident)*) => { pyobject_native_type_named!($name $(,$type_param)*); - pyobject_native_type_convert!($name, $typeobject, $checkfunction $(,$type_param)*); + pyobject_native_type_convert!($name, $typeobject, $module, $checkfunction $(,$type_param)*); impl<'a, $($type_param,)*> ::std::convert::From<&'a $name> for &'a $crate::types::PyAny { fn from(ob: &'a $name) -> Self { @@ -93,12 +93,13 @@ macro_rules! pyobject_native_type ( #[macro_export] macro_rules! pyobject_native_type_convert( - ($name: ty, $typeobject: expr, $checkfunction: path $(,$type_param: ident)*) => { + ($name: ty, $typeobject: expr, $module: expr, $checkfunction: path $(,$type_param: ident)*) => { impl<$($type_param,)*> $crate::type_object::PyTypeInfo for $name { type Type = (); type BaseType = $crate::types::PyAny; const NAME: &'static str = stringify!($name); + const MODULE: Option<&'static str> = $module; const SIZE: usize = ::std::mem::size_of::<$crate::ffi::PyObject>(); const OFFSET: isize = 0; From f711c99991df94ff7ccb58342c9ed18724bc768c Mon Sep 17 00:00:00 2001 From: Martin Larralde Date: Thu, 30 May 2019 21:39:56 -0700 Subject: [PATCH 04/10] Set the right module for builtin types in `pyo3::types` --- src/types/any.rs | 2 +- src/types/boolobject.rs | 2 +- src/types/bytearray.rs | 2 +- src/types/complex.rs | 2 +- src/types/datetime.rs | 10 +++++----- src/types/dict.rs | 2 +- src/types/floatob.rs | 2 +- src/types/list.rs | 2 +- src/types/module.rs | 2 +- src/types/num.rs | 2 +- src/types/set.rs | 4 ++-- src/types/slice.rs | 2 +- src/types/string.rs | 4 ++-- src/types/tuple.rs | 2 +- src/types/typeobject.rs | 2 +- 15 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/types/any.rs b/src/types/any.rs index 58d35c4cd2f..90e6e7aa6ce 100644 --- a/src/types/any.rs +++ b/src/types/any.rs @@ -23,7 +23,7 @@ use crate::{ffi, PyObject, PyRef, PyRefMut, PyTryFrom, PyTypeInfo}; #[repr(transparent)] pub struct PyAny(PyObject); pyobject_native_type_named!(PyAny); -pyobject_native_type_convert!(PyAny, ffi::PyBaseObject_Type, ffi::PyObject_Check); +pyobject_native_type_convert!(PyAny, ffi::PyBaseObject_Type, Some("builtins"), ffi::PyObject_Check); impl PyAny { pub fn downcast_ref(&self) -> Result<&T, PyDowncastError> diff --git a/src/types/boolobject.rs b/src/types/boolobject.rs index 79e4626873a..a9d46468a0b 100644 --- a/src/types/boolobject.rs +++ b/src/types/boolobject.rs @@ -12,7 +12,7 @@ use crate::{IntoPyObject, PyTryFrom, ToPyObject}; #[repr(transparent)] pub struct PyBool(PyObject); -pyobject_native_type!(PyBool, ffi::PyBool_Type, ffi::PyBool_Check); +pyobject_native_type!(PyBool, ffi::PyBool_Type, Some("builtins"), ffi::PyBool_Check); impl PyBool { /// Depending on `val`, returns `py.True()` or `py.False()`. diff --git a/src/types/bytearray.rs b/src/types/bytearray.rs index 690f0f9d7b2..1ac5d2f8388 100644 --- a/src/types/bytearray.rs +++ b/src/types/bytearray.rs @@ -13,7 +13,7 @@ use std::slice; #[repr(transparent)] pub struct PyByteArray(PyObject); -pyobject_native_type!(PyByteArray, ffi::PyByteArray_Type, ffi::PyByteArray_Check); +pyobject_native_type!(PyByteArray, ffi::PyByteArray_Type, Some("builtins"), ffi::PyByteArray_Check); impl PyByteArray { /// Creates a new Python bytearray object. diff --git a/src/types/complex.rs b/src/types/complex.rs index adee578dbab..00c1ae9b94f 100644 --- a/src/types/complex.rs +++ b/src/types/complex.rs @@ -12,7 +12,7 @@ use std::os::raw::c_double; #[repr(transparent)] pub struct PyComplex(PyObject); -pyobject_native_type!(PyComplex, ffi::PyComplex_Type, ffi::PyComplex_Check); +pyobject_native_type!(PyComplex, ffi::PyComplex_Type, Some("builtins"), ffi::PyComplex_Check); impl PyComplex { /// Creates a new Python `PyComplex` object, from its real and imaginary values. diff --git a/src/types/datetime.rs b/src/types/datetime.rs index 127aa1eeb36..af1776c49e8 100644 --- a/src/types/datetime.rs +++ b/src/types/datetime.rs @@ -66,7 +66,7 @@ pub trait PyTimeAccess { /// Bindings around `datetime.date` pub struct PyDate(PyObject); -pyobject_native_type!(PyDate, *PyDateTimeAPI.DateType, PyDate_Check); +pyobject_native_type!(PyDate, *PyDateTimeAPI.DateType, Some("datetime"), PyDate_Check); impl PyDate { pub fn new<'p>(py: Python<'p>, year: i32, month: u8, day: u8) -> PyResult<&'p PyDate> { @@ -116,7 +116,7 @@ impl PyDateAccess for PyDate { /// Bindings for `datetime.datetime` pub struct PyDateTime(PyObject); -pyobject_native_type!(PyDateTime, *PyDateTimeAPI.DateTimeType, PyDateTime_Check); +pyobject_native_type!(PyDateTime, *PyDateTimeAPI.DateTimeType, Some("datetime"), PyDateTime_Check); impl PyDateTime { pub fn new<'p>( @@ -220,7 +220,7 @@ impl PyTimeAccess for PyDateTime { /// Bindings for `datetime.time` pub struct PyTime(PyObject); -pyobject_native_type!(PyTime, *PyDateTimeAPI.TimeType, PyTime_Check); +pyobject_native_type!(PyTime, *PyDateTimeAPI.TimeType, Some("datetime"), PyTime_Check); impl PyTime { pub fn new<'p>( @@ -299,11 +299,11 @@ impl PyTimeAccess for PyTime { /// /// This is an abstract base class and should not be constructed directly. pub struct PyTzInfo(PyObject); -pyobject_native_type!(PyTzInfo, *PyDateTimeAPI.TZInfoType, PyTZInfo_Check); +pyobject_native_type!(PyTzInfo, *PyDateTimeAPI.TZInfoType, Some("datetime"), PyTZInfo_Check); /// Bindings for `datetime.timedelta` pub struct PyDelta(PyObject); -pyobject_native_type!(PyDelta, *PyDateTimeAPI.DeltaType, PyDelta_Check); +pyobject_native_type!(PyDelta, *PyDateTimeAPI.DeltaType, Some("datetime"), PyDelta_Check); impl PyDelta { pub fn new<'p>( diff --git a/src/types/dict.rs b/src/types/dict.rs index 429729a0608..4ccbb6a9183 100644 --- a/src/types/dict.rs +++ b/src/types/dict.rs @@ -16,7 +16,7 @@ use std::{cmp, collections, hash, mem}; #[repr(transparent)] pub struct PyDict(PyObject); -pyobject_native_type!(PyDict, ffi::PyDict_Type, ffi::PyDict_Check); +pyobject_native_type!(PyDict, ffi::PyDict_Type, Some("builtins"), ffi::PyDict_Check); impl PyDict { /// Creates a new empty dictionary. diff --git a/src/types/floatob.rs b/src/types/floatob.rs index 87fa44831ba..ac16568278c 100644 --- a/src/types/floatob.rs +++ b/src/types/floatob.rs @@ -24,7 +24,7 @@ use std::os::raw::c_double; #[repr(transparent)] pub struct PyFloat(PyObject); -pyobject_native_type!(PyFloat, ffi::PyFloat_Type, ffi::PyFloat_Check); +pyobject_native_type!(PyFloat, ffi::PyFloat_Type, Some("builtins"), ffi::PyFloat_Check); impl PyFloat { /// Creates a new Python `float` object. diff --git a/src/types/list.rs b/src/types/list.rs index 0f5f081cd6b..d17e8e44457 100644 --- a/src/types/list.rs +++ b/src/types/list.rs @@ -16,7 +16,7 @@ use crate::{IntoPyObject, ToBorrowedObject, ToPyObject}; #[repr(transparent)] pub struct PyList(PyObject); -pyobject_native_type!(PyList, ffi::PyList_Type, ffi::PyList_Check); +pyobject_native_type!(PyList, ffi::PyList_Type, Some("builtins"), ffi::PyList_Check); impl PyList { /// Construct a new list with the given elements. diff --git a/src/types/module.rs b/src/types/module.rs index 10672cf6f4b..53c4861145a 100644 --- a/src/types/module.rs +++ b/src/types/module.rs @@ -25,7 +25,7 @@ use std::str; #[repr(transparent)] pub struct PyModule(PyObject); -pyobject_native_type!(PyModule, ffi::PyModule_Type, ffi::PyModule_Check); +pyobject_native_type!(PyModule, ffi::PyModule_Type, Some("builtins"), ffi::PyModule_Check); impl PyModule { /// Create a new module object with the `__name__` attribute set to name. diff --git a/src/types/num.rs b/src/types/num.rs index 164a8b1005e..a3b6d12ea2d 100644 --- a/src/types/num.rs +++ b/src/types/num.rs @@ -123,7 +123,7 @@ pub(super) const IS_LITTLE_ENDIAN: c_int = 0; #[repr(transparent)] pub struct PyLong(PyObject); -pyobject_native_type!(PyLong, ffi::PyLong_Type, ffi::PyLong_Check); +pyobject_native_type!(PyLong, ffi::PyLong_Type, Some("builtins"), ffi::PyLong_Check); macro_rules! int_fits_c_long ( ($rust_type:ty) => ( diff --git a/src/types/set.rs b/src/types/set.rs index 1232290858e..a789282609b 100644 --- a/src/types/set.rs +++ b/src/types/set.rs @@ -18,8 +18,8 @@ pub struct PySet(PyObject); #[repr(transparent)] pub struct PyFrozenSet(PyObject); -pyobject_native_type!(PySet, ffi::PySet_Type, ffi::PySet_Check); -pyobject_native_type!(PyFrozenSet, ffi::PyFrozenSet_Type, ffi::PyFrozenSet_Check); +pyobject_native_type!(PySet, ffi::PySet_Type, Some("builtins"), ffi::PySet_Check); +pyobject_native_type!(PyFrozenSet, ffi::PyFrozenSet_Type, Some("builtins"), ffi::PyFrozenSet_Check); impl PySet { /// Creates a new set. diff --git a/src/types/slice.rs b/src/types/slice.rs index 41f0b104714..339ee3ec6b2 100644 --- a/src/types/slice.rs +++ b/src/types/slice.rs @@ -14,7 +14,7 @@ use std::os::raw::c_long; #[repr(transparent)] pub struct PySlice(PyObject); -pyobject_native_type!(PySlice, ffi::PySlice_Type, ffi::PySlice_Check); +pyobject_native_type!(PySlice, ffi::PySlice_Type, Some("builtins"), ffi::PySlice_Check); /// Represents a Python `slice` indices pub struct PySliceIndices { diff --git a/src/types/string.rs b/src/types/string.rs index 8e542c030ac..58d9a86d420 100644 --- a/src/types/string.rs +++ b/src/types/string.rs @@ -18,13 +18,13 @@ use std::{mem, str}; #[repr(transparent)] pub struct PyString(PyObject); -pyobject_native_type!(PyString, ffi::PyUnicode_Type, ffi::PyUnicode_Check); +pyobject_native_type!(PyString, ffi::PyUnicode_Type, Some("builtins"), ffi::PyUnicode_Check); /// Represents a Python `byte` string. #[repr(transparent)] pub struct PyBytes(PyObject); -pyobject_native_type!(PyBytes, ffi::PyBytes_Type, ffi::PyBytes_Check); +pyobject_native_type!(PyBytes, ffi::PyBytes_Type, Some("builtins"), ffi::PyBytes_Check); impl PyString { /// Creates a new Python string object. diff --git a/src/types/tuple.rs b/src/types/tuple.rs index 9e259d1a9d6..31dd19a720e 100644 --- a/src/types/tuple.rs +++ b/src/types/tuple.rs @@ -17,7 +17,7 @@ use std::slice; #[repr(transparent)] pub struct PyTuple(PyObject); -pyobject_native_type!(PyTuple, ffi::PyTuple_Type, ffi::PyTuple_Check); +pyobject_native_type!(PyTuple, ffi::PyTuple_Type, Some("builtins"), ffi::PyTuple_Check); impl PyTuple { /// Construct a new tuple with the given elements. diff --git a/src/types/typeobject.rs b/src/types/typeobject.rs index bfb68714a5c..b7e5faf0540 100644 --- a/src/types/typeobject.rs +++ b/src/types/typeobject.rs @@ -16,7 +16,7 @@ use std::ffi::CStr; #[repr(transparent)] pub struct PyType(PyObject); -pyobject_native_type!(PyType, ffi::PyType_Type, ffi::PyType_Check); +pyobject_native_type!(PyType, ffi::PyType_Type, Some("builtins"), ffi::PyType_Check); impl PyType { #[inline] From 86cc21184195312491af36bffa25b0326caf384c Mon Sep 17 00:00:00 2001 From: Martin Larralde Date: Thu, 30 May 2019 21:42:29 -0700 Subject: [PATCH 05/10] Add `module` argument to example `word_count.WordCounter` class --- examples/word-count/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/word-count/src/lib.rs b/examples/word-count/src/lib.rs index aa98108c6be..55fa738805a 100644 --- a/examples/word-count/src/lib.rs +++ b/examples/word-count/src/lib.rs @@ -8,7 +8,7 @@ use std::fs; use std::path::PathBuf; /// Represents a file that can be searched -#[pyclass] +#[pyclass(module="word_count")] struct WordCounter { path: PathBuf, } From b37a1395b7b742a5f0503cebd66e517ff7a9923f Mon Sep 17 00:00:00 2001 From: Martin Larralde Date: Thu, 30 May 2019 21:48:00 -0700 Subject: [PATCH 06/10] Add `module` argument of `pyclass` macro to guide --- guide/src/class.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/guide/src/class.md b/guide/src/class.md index a7aa0943ecf..69de02b57ce 100644 --- a/guide/src/class.md +++ b/guide/src/class.md @@ -104,6 +104,8 @@ If a custom class contains references to other Python objects that can be collec * `extends=BaseType` - Use a custom base class. The base `BaseType` must implement `PyTypeInfo`. * `subclass` - Allows Python classes to inherit from this class. * `dict` - Adds `__dict__` support, so that the instances of this type have a dictionary containing arbitrary instance variables. +* `module="XXX"` - Set the name of the module the class will be shown as defined in. If not given, the class + will be a virtual member of the `builtins` module. ## Constructor From 25a235aea21e18dee7da62111f98ef7930ee245a Mon Sep 17 00:00:00 2001 From: Martin Larralde Date: Thu, 30 May 2019 22:51:13 -0700 Subject: [PATCH 07/10] Reformat code using `rustfmt` --- examples/word-count/src/lib.rs | 2 +- pyo3-derive-backend/src/pyclass.rs | 21 ++++++------------ src/types/any.rs | 7 +++++- src/types/boolobject.rs | 7 +++++- src/types/bytearray.rs | 7 +++++- src/types/complex.rs | 7 +++++- src/types/datetime.rs | 35 +++++++++++++++++++++++++----- src/types/dict.rs | 7 +++++- src/types/floatob.rs | 7 +++++- src/types/list.rs | 7 +++++- src/types/module.rs | 7 +++++- src/types/num.rs | 7 +++++- src/types/set.rs | 7 +++++- src/types/slice.rs | 7 +++++- src/types/string.rs | 14 ++++++++++-- src/types/tuple.rs | 7 +++++- src/types/typeobject.rs | 7 +++++- 17 files changed, 128 insertions(+), 35 deletions(-) diff --git a/examples/word-count/src/lib.rs b/examples/word-count/src/lib.rs index 55fa738805a..29f97808c0f 100644 --- a/examples/word-count/src/lib.rs +++ b/examples/word-count/src/lib.rs @@ -8,7 +8,7 @@ use std::fs; use std::path::PathBuf; /// Represents a file that can be searched -#[pyclass(module="word_count")] +#[pyclass(module = "word_count")] struct WordCounter { path: PathBuf, } diff --git a/pyo3-derive-backend/src/pyclass.rs b/pyo3-derive-backend/src/pyclass.rs index 837f1bfda65..7100e52704c 100644 --- a/pyo3-derive-backend/src/pyclass.rs +++ b/pyo3-derive-backend/src/pyclass.rs @@ -98,26 +98,19 @@ impl PyClassArgs { }, "module" => match *assign.right { - syn::Expr::Lit(ref exp) => { - match exp.lit { - syn::Lit::Str(ref lit) => { - self.module = Some(lit.clone()); - } - _ => { - return Err(syn::Error::new_spanned( - *assign.right.clone(), - "Wrong format for module", - )); - } - } - }, + syn::Expr::Lit(syn::ExprLit { + lit: syn::Lit::Str(ref lit), + .. + }) => { + self.module = Some(lit.clone()); + } _ => { return Err(syn::Error::new_spanned( *assign.right.clone(), "Wrong format for module", )); } - } + }, _ => { return Err(syn::Error::new_spanned( diff --git a/src/types/any.rs b/src/types/any.rs index 90e6e7aa6ce..39becb255e1 100644 --- a/src/types/any.rs +++ b/src/types/any.rs @@ -23,7 +23,12 @@ use crate::{ffi, PyObject, PyRef, PyRefMut, PyTryFrom, PyTypeInfo}; #[repr(transparent)] pub struct PyAny(PyObject); pyobject_native_type_named!(PyAny); -pyobject_native_type_convert!(PyAny, ffi::PyBaseObject_Type, Some("builtins"), ffi::PyObject_Check); +pyobject_native_type_convert!( + PyAny, + ffi::PyBaseObject_Type, + Some("builtins"), + ffi::PyObject_Check +); impl PyAny { pub fn downcast_ref(&self) -> Result<&T, PyDowncastError> diff --git a/src/types/boolobject.rs b/src/types/boolobject.rs index a9d46468a0b..246ca82cdfd 100644 --- a/src/types/boolobject.rs +++ b/src/types/boolobject.rs @@ -12,7 +12,12 @@ use crate::{IntoPyObject, PyTryFrom, ToPyObject}; #[repr(transparent)] pub struct PyBool(PyObject); -pyobject_native_type!(PyBool, ffi::PyBool_Type, Some("builtins"), ffi::PyBool_Check); +pyobject_native_type!( + PyBool, + ffi::PyBool_Type, + Some("builtins"), + ffi::PyBool_Check +); impl PyBool { /// Depending on `val`, returns `py.True()` or `py.False()`. diff --git a/src/types/bytearray.rs b/src/types/bytearray.rs index 1ac5d2f8388..cca6ee4a114 100644 --- a/src/types/bytearray.rs +++ b/src/types/bytearray.rs @@ -13,7 +13,12 @@ use std::slice; #[repr(transparent)] pub struct PyByteArray(PyObject); -pyobject_native_type!(PyByteArray, ffi::PyByteArray_Type, Some("builtins"), ffi::PyByteArray_Check); +pyobject_native_type!( + PyByteArray, + ffi::PyByteArray_Type, + Some("builtins"), + ffi::PyByteArray_Check +); impl PyByteArray { /// Creates a new Python bytearray object. diff --git a/src/types/complex.rs b/src/types/complex.rs index 00c1ae9b94f..4d4f2f8fe54 100644 --- a/src/types/complex.rs +++ b/src/types/complex.rs @@ -12,7 +12,12 @@ use std::os::raw::c_double; #[repr(transparent)] pub struct PyComplex(PyObject); -pyobject_native_type!(PyComplex, ffi::PyComplex_Type, Some("builtins"), ffi::PyComplex_Check); +pyobject_native_type!( + PyComplex, + ffi::PyComplex_Type, + Some("builtins"), + ffi::PyComplex_Check +); impl PyComplex { /// Creates a new Python `PyComplex` object, from its real and imaginary values. diff --git a/src/types/datetime.rs b/src/types/datetime.rs index af1776c49e8..077be5fb3a0 100644 --- a/src/types/datetime.rs +++ b/src/types/datetime.rs @@ -66,7 +66,12 @@ pub trait PyTimeAccess { /// Bindings around `datetime.date` pub struct PyDate(PyObject); -pyobject_native_type!(PyDate, *PyDateTimeAPI.DateType, Some("datetime"), PyDate_Check); +pyobject_native_type!( + PyDate, + *PyDateTimeAPI.DateType, + Some("datetime"), + PyDate_Check +); impl PyDate { pub fn new<'p>(py: Python<'p>, year: i32, month: u8, day: u8) -> PyResult<&'p PyDate> { @@ -116,7 +121,12 @@ impl PyDateAccess for PyDate { /// Bindings for `datetime.datetime` pub struct PyDateTime(PyObject); -pyobject_native_type!(PyDateTime, *PyDateTimeAPI.DateTimeType, Some("datetime"), PyDateTime_Check); +pyobject_native_type!( + PyDateTime, + *PyDateTimeAPI.DateTimeType, + Some("datetime"), + PyDateTime_Check +); impl PyDateTime { pub fn new<'p>( @@ -220,7 +230,12 @@ impl PyTimeAccess for PyDateTime { /// Bindings for `datetime.time` pub struct PyTime(PyObject); -pyobject_native_type!(PyTime, *PyDateTimeAPI.TimeType, Some("datetime"), PyTime_Check); +pyobject_native_type!( + PyTime, + *PyDateTimeAPI.TimeType, + Some("datetime"), + PyTime_Check +); impl PyTime { pub fn new<'p>( @@ -299,11 +314,21 @@ impl PyTimeAccess for PyTime { /// /// This is an abstract base class and should not be constructed directly. pub struct PyTzInfo(PyObject); -pyobject_native_type!(PyTzInfo, *PyDateTimeAPI.TZInfoType, Some("datetime"), PyTZInfo_Check); +pyobject_native_type!( + PyTzInfo, + *PyDateTimeAPI.TZInfoType, + Some("datetime"), + PyTZInfo_Check +); /// Bindings for `datetime.timedelta` pub struct PyDelta(PyObject); -pyobject_native_type!(PyDelta, *PyDateTimeAPI.DeltaType, Some("datetime"), PyDelta_Check); +pyobject_native_type!( + PyDelta, + *PyDateTimeAPI.DeltaType, + Some("datetime"), + PyDelta_Check +); impl PyDelta { pub fn new<'p>( diff --git a/src/types/dict.rs b/src/types/dict.rs index 4ccbb6a9183..2e08f1d3b20 100644 --- a/src/types/dict.rs +++ b/src/types/dict.rs @@ -16,7 +16,12 @@ use std::{cmp, collections, hash, mem}; #[repr(transparent)] pub struct PyDict(PyObject); -pyobject_native_type!(PyDict, ffi::PyDict_Type, Some("builtins"), ffi::PyDict_Check); +pyobject_native_type!( + PyDict, + ffi::PyDict_Type, + Some("builtins"), + ffi::PyDict_Check +); impl PyDict { /// Creates a new empty dictionary. diff --git a/src/types/floatob.rs b/src/types/floatob.rs index ac16568278c..6169973f0aa 100644 --- a/src/types/floatob.rs +++ b/src/types/floatob.rs @@ -24,7 +24,12 @@ use std::os::raw::c_double; #[repr(transparent)] pub struct PyFloat(PyObject); -pyobject_native_type!(PyFloat, ffi::PyFloat_Type, Some("builtins"), ffi::PyFloat_Check); +pyobject_native_type!( + PyFloat, + ffi::PyFloat_Type, + Some("builtins"), + ffi::PyFloat_Check +); impl PyFloat { /// Creates a new Python `float` object. diff --git a/src/types/list.rs b/src/types/list.rs index d17e8e44457..18e01621bcf 100644 --- a/src/types/list.rs +++ b/src/types/list.rs @@ -16,7 +16,12 @@ use crate::{IntoPyObject, ToBorrowedObject, ToPyObject}; #[repr(transparent)] pub struct PyList(PyObject); -pyobject_native_type!(PyList, ffi::PyList_Type, Some("builtins"), ffi::PyList_Check); +pyobject_native_type!( + PyList, + ffi::PyList_Type, + Some("builtins"), + ffi::PyList_Check +); impl PyList { /// Construct a new list with the given elements. diff --git a/src/types/module.rs b/src/types/module.rs index 53c4861145a..31d2c24fc8c 100644 --- a/src/types/module.rs +++ b/src/types/module.rs @@ -25,7 +25,12 @@ use std::str; #[repr(transparent)] pub struct PyModule(PyObject); -pyobject_native_type!(PyModule, ffi::PyModule_Type, Some("builtins"), ffi::PyModule_Check); +pyobject_native_type!( + PyModule, + ffi::PyModule_Type, + Some("builtins"), + ffi::PyModule_Check +); impl PyModule { /// Create a new module object with the `__name__` attribute set to name. diff --git a/src/types/num.rs b/src/types/num.rs index a3b6d12ea2d..5fccb07e468 100644 --- a/src/types/num.rs +++ b/src/types/num.rs @@ -123,7 +123,12 @@ pub(super) const IS_LITTLE_ENDIAN: c_int = 0; #[repr(transparent)] pub struct PyLong(PyObject); -pyobject_native_type!(PyLong, ffi::PyLong_Type, Some("builtins"), ffi::PyLong_Check); +pyobject_native_type!( + PyLong, + ffi::PyLong_Type, + Some("builtins"), + ffi::PyLong_Check +); macro_rules! int_fits_c_long ( ($rust_type:ty) => ( diff --git a/src/types/set.rs b/src/types/set.rs index a789282609b..39c8a00c471 100644 --- a/src/types/set.rs +++ b/src/types/set.rs @@ -19,7 +19,12 @@ pub struct PySet(PyObject); pub struct PyFrozenSet(PyObject); pyobject_native_type!(PySet, ffi::PySet_Type, Some("builtins"), ffi::PySet_Check); -pyobject_native_type!(PyFrozenSet, ffi::PyFrozenSet_Type, Some("builtins"), ffi::PyFrozenSet_Check); +pyobject_native_type!( + PyFrozenSet, + ffi::PyFrozenSet_Type, + Some("builtins"), + ffi::PyFrozenSet_Check +); impl PySet { /// Creates a new set. diff --git a/src/types/slice.rs b/src/types/slice.rs index 339ee3ec6b2..4f8db4920d7 100644 --- a/src/types/slice.rs +++ b/src/types/slice.rs @@ -14,7 +14,12 @@ use std::os::raw::c_long; #[repr(transparent)] pub struct PySlice(PyObject); -pyobject_native_type!(PySlice, ffi::PySlice_Type, Some("builtins"), ffi::PySlice_Check); +pyobject_native_type!( + PySlice, + ffi::PySlice_Type, + Some("builtins"), + ffi::PySlice_Check +); /// Represents a Python `slice` indices pub struct PySliceIndices { diff --git a/src/types/string.rs b/src/types/string.rs index 58d9a86d420..9d315f943f4 100644 --- a/src/types/string.rs +++ b/src/types/string.rs @@ -18,13 +18,23 @@ use std::{mem, str}; #[repr(transparent)] pub struct PyString(PyObject); -pyobject_native_type!(PyString, ffi::PyUnicode_Type, Some("builtins"), ffi::PyUnicode_Check); +pyobject_native_type!( + PyString, + ffi::PyUnicode_Type, + Some("builtins"), + ffi::PyUnicode_Check +); /// Represents a Python `byte` string. #[repr(transparent)] pub struct PyBytes(PyObject); -pyobject_native_type!(PyBytes, ffi::PyBytes_Type, Some("builtins"), ffi::PyBytes_Check); +pyobject_native_type!( + PyBytes, + ffi::PyBytes_Type, + Some("builtins"), + ffi::PyBytes_Check +); impl PyString { /// Creates a new Python string object. diff --git a/src/types/tuple.rs b/src/types/tuple.rs index 31dd19a720e..65d28f39c89 100644 --- a/src/types/tuple.rs +++ b/src/types/tuple.rs @@ -17,7 +17,12 @@ use std::slice; #[repr(transparent)] pub struct PyTuple(PyObject); -pyobject_native_type!(PyTuple, ffi::PyTuple_Type, Some("builtins"), ffi::PyTuple_Check); +pyobject_native_type!( + PyTuple, + ffi::PyTuple_Type, + Some("builtins"), + ffi::PyTuple_Check +); impl PyTuple { /// Construct a new tuple with the given elements. diff --git a/src/types/typeobject.rs b/src/types/typeobject.rs index b7e5faf0540..5a515c92ae3 100644 --- a/src/types/typeobject.rs +++ b/src/types/typeobject.rs @@ -16,7 +16,12 @@ use std::ffi::CStr; #[repr(transparent)] pub struct PyType(PyObject); -pyobject_native_type!(PyType, ffi::PyType_Type, Some("builtins"), ffi::PyType_Check); +pyobject_native_type!( + PyType, + ffi::PyType_Type, + Some("builtins"), + ffi::PyType_Check +); impl PyType { #[inline] From a8e6a02f586d7c37348ba28a30e79cfcee07b15f Mon Sep 17 00:00:00 2001 From: Martin Larralde Date: Fri, 31 May 2019 00:47:51 -0700 Subject: [PATCH 08/10] Add tests and entry in CHANGELOG.md for `module` argument in `pyclass` --- CHANGELOG.md | 5 +++++ pyo3-derive-backend/src/pyclass.rs | 2 -- tests/test_module.rs | 12 +++++++++--- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e8819e8bbc..beb3e35d02d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Added + + * `module` argument to `pyclass` macro. [#499](https://github.com/PyO3/pyo3/pull/499) + + ## [0.7.0] - 2018-05-26 ### Added diff --git a/pyo3-derive-backend/src/pyclass.rs b/pyo3-derive-backend/src/pyclass.rs index 7100e52704c..04f378682a1 100644 --- a/pyo3-derive-backend/src/pyclass.rs +++ b/pyo3-derive-backend/src/pyclass.rs @@ -96,7 +96,6 @@ impl PyClassArgs { )); } }, - "module" => match *assign.right { syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Str(ref lit), @@ -111,7 +110,6 @@ impl PyClassArgs { )); } }, - _ => { return Err(syn::Error::new_spanned( *assign.left.clone(), diff --git a/tests/test_module.rs b/tests/test_module.rs index 61b31907694..4daa5266f87 100644 --- a/tests/test_module.rs +++ b/tests/test_module.rs @@ -6,7 +6,10 @@ use pyo3::types::IntoPyDict; mod common; #[pyclass] -struct EmptyClass {} +struct AnonClass {} + +#[pyclass(module = "module")] +struct LocatedClass {} fn sum_as_string(a: i64, b: i64) -> String { format!("{}", a + b).to_string() @@ -34,7 +37,8 @@ fn module_with_functions(py: Python, m: &PyModule) -> PyResult<()> { Ok(42) } - m.add_class::().unwrap(); + m.add_class::().unwrap(); + m.add_class::().unwrap(); m.add("foo", "bar").unwrap(); @@ -63,7 +67,9 @@ fn test_module_with_functions() { run("assert module_with_functions.sum_as_string(1, 2) == '3'"); run("assert module_with_functions.no_parameters() == 42"); run("assert module_with_functions.foo == 'bar'"); - run("assert module_with_functions.EmptyClass != None"); + run("assert module_with_functions.AnonClass != None"); + run("assert module_with_functions.LocatedClass != None"); + run("assert module_with_functions.LocatedClass.__module__ == 'module'"); run("assert module_with_functions.double(3) == 6"); run("assert module_with_functions.double.__doc__ == 'Doubles the given value'"); run("assert module_with_functions.also_double(3) == 6"); From 491805c78adc86512cdb2274c8f44029678db081 Mon Sep 17 00:00:00 2001 From: Martin Larralde Date: Sat, 1 Jun 2019 19:26:07 -0700 Subject: [PATCH 09/10] Make `$module` parameter in `pyobject_native_type` optional --- src/types/mod.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/types/mod.rs b/src/types/mod.rs index 8a88160be78..7546b153647 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -89,6 +89,9 @@ macro_rules! pyobject_native_type ( } } }; + ($name: ty, $typeobject: expr, $checkfunction: path $(,$type_param: ident)*) => { + pyobject_native_type!($name, $typeobject, None, $checkfunction, $(,$type_param)*); + } ); #[macro_export] @@ -155,6 +158,9 @@ macro_rules! pyobject_native_type_convert( } } }; + ($name: ty, $typeobject: expr, $checkfunction: path $(,$type_param: ident)*) => { + pyobject_native_type_convert!($name, $typeobject, $checkfunction $(,$type_param)*); + }; ); mod any; From 91af634644b4ae5c8c685794768958d284523223 Mon Sep 17 00:00:00 2001 From: Martin Larralde Date: Sun, 2 Jun 2019 18:07:08 -0700 Subject: [PATCH 10/10] Make `pyobject_native_type` declare module as `Some("builtins")` by default --- src/types/any.rs | 7 +------ src/types/boolobject.rs | 7 +------ src/types/bytearray.rs | 7 +------ src/types/complex.rs | 7 +------ src/types/dict.rs | 7 +------ src/types/floatob.rs | 7 +------ src/types/list.rs | 7 +------ src/types/mod.rs | 6 +++--- src/types/module.rs | 7 +------ src/types/set.rs | 7 +------ src/types/slice.rs | 7 +------ src/types/string.rs | 7 +------ src/types/tuple.rs | 7 +------ src/types/typeobject.rs | 7 +------ 14 files changed, 16 insertions(+), 81 deletions(-) diff --git a/src/types/any.rs b/src/types/any.rs index 39becb255e1..58d35c4cd2f 100644 --- a/src/types/any.rs +++ b/src/types/any.rs @@ -23,12 +23,7 @@ use crate::{ffi, PyObject, PyRef, PyRefMut, PyTryFrom, PyTypeInfo}; #[repr(transparent)] pub struct PyAny(PyObject); pyobject_native_type_named!(PyAny); -pyobject_native_type_convert!( - PyAny, - ffi::PyBaseObject_Type, - Some("builtins"), - ffi::PyObject_Check -); +pyobject_native_type_convert!(PyAny, ffi::PyBaseObject_Type, ffi::PyObject_Check); impl PyAny { pub fn downcast_ref(&self) -> Result<&T, PyDowncastError> diff --git a/src/types/boolobject.rs b/src/types/boolobject.rs index 246ca82cdfd..79e4626873a 100644 --- a/src/types/boolobject.rs +++ b/src/types/boolobject.rs @@ -12,12 +12,7 @@ use crate::{IntoPyObject, PyTryFrom, ToPyObject}; #[repr(transparent)] pub struct PyBool(PyObject); -pyobject_native_type!( - PyBool, - ffi::PyBool_Type, - Some("builtins"), - ffi::PyBool_Check -); +pyobject_native_type!(PyBool, ffi::PyBool_Type, ffi::PyBool_Check); impl PyBool { /// Depending on `val`, returns `py.True()` or `py.False()`. diff --git a/src/types/bytearray.rs b/src/types/bytearray.rs index cca6ee4a114..690f0f9d7b2 100644 --- a/src/types/bytearray.rs +++ b/src/types/bytearray.rs @@ -13,12 +13,7 @@ use std::slice; #[repr(transparent)] pub struct PyByteArray(PyObject); -pyobject_native_type!( - PyByteArray, - ffi::PyByteArray_Type, - Some("builtins"), - ffi::PyByteArray_Check -); +pyobject_native_type!(PyByteArray, ffi::PyByteArray_Type, ffi::PyByteArray_Check); impl PyByteArray { /// Creates a new Python bytearray object. diff --git a/src/types/complex.rs b/src/types/complex.rs index 4d4f2f8fe54..adee578dbab 100644 --- a/src/types/complex.rs +++ b/src/types/complex.rs @@ -12,12 +12,7 @@ use std::os::raw::c_double; #[repr(transparent)] pub struct PyComplex(PyObject); -pyobject_native_type!( - PyComplex, - ffi::PyComplex_Type, - Some("builtins"), - ffi::PyComplex_Check -); +pyobject_native_type!(PyComplex, ffi::PyComplex_Type, ffi::PyComplex_Check); impl PyComplex { /// Creates a new Python `PyComplex` object, from its real and imaginary values. diff --git a/src/types/dict.rs b/src/types/dict.rs index 2e08f1d3b20..429729a0608 100644 --- a/src/types/dict.rs +++ b/src/types/dict.rs @@ -16,12 +16,7 @@ use std::{cmp, collections, hash, mem}; #[repr(transparent)] pub struct PyDict(PyObject); -pyobject_native_type!( - PyDict, - ffi::PyDict_Type, - Some("builtins"), - ffi::PyDict_Check -); +pyobject_native_type!(PyDict, ffi::PyDict_Type, ffi::PyDict_Check); impl PyDict { /// Creates a new empty dictionary. diff --git a/src/types/floatob.rs b/src/types/floatob.rs index 6169973f0aa..87fa44831ba 100644 --- a/src/types/floatob.rs +++ b/src/types/floatob.rs @@ -24,12 +24,7 @@ use std::os::raw::c_double; #[repr(transparent)] pub struct PyFloat(PyObject); -pyobject_native_type!( - PyFloat, - ffi::PyFloat_Type, - Some("builtins"), - ffi::PyFloat_Check -); +pyobject_native_type!(PyFloat, ffi::PyFloat_Type, ffi::PyFloat_Check); impl PyFloat { /// Creates a new Python `float` object. diff --git a/src/types/list.rs b/src/types/list.rs index 18e01621bcf..0f5f081cd6b 100644 --- a/src/types/list.rs +++ b/src/types/list.rs @@ -16,12 +16,7 @@ use crate::{IntoPyObject, ToBorrowedObject, ToPyObject}; #[repr(transparent)] pub struct PyList(PyObject); -pyobject_native_type!( - PyList, - ffi::PyList_Type, - Some("builtins"), - ffi::PyList_Check -); +pyobject_native_type!(PyList, ffi::PyList_Type, ffi::PyList_Check); impl PyList { /// Construct a new list with the given elements. diff --git a/src/types/mod.rs b/src/types/mod.rs index 7546b153647..e1dea39954a 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -90,8 +90,8 @@ macro_rules! pyobject_native_type ( } }; ($name: ty, $typeobject: expr, $checkfunction: path $(,$type_param: ident)*) => { - pyobject_native_type!($name, $typeobject, None, $checkfunction, $(,$type_param)*); - } + pyobject_native_type!{$name, $typeobject, Some("builtins"), $checkfunction $(,$type_param)*} + }; ); #[macro_export] @@ -159,7 +159,7 @@ macro_rules! pyobject_native_type_convert( } }; ($name: ty, $typeobject: expr, $checkfunction: path $(,$type_param: ident)*) => { - pyobject_native_type_convert!($name, $typeobject, $checkfunction $(,$type_param)*); + pyobject_native_type_convert!{$name, $typeobject, Some("builtins"), $checkfunction $(,$type_param)*} }; ); diff --git a/src/types/module.rs b/src/types/module.rs index 31d2c24fc8c..10672cf6f4b 100644 --- a/src/types/module.rs +++ b/src/types/module.rs @@ -25,12 +25,7 @@ use std::str; #[repr(transparent)] pub struct PyModule(PyObject); -pyobject_native_type!( - PyModule, - ffi::PyModule_Type, - Some("builtins"), - ffi::PyModule_Check -); +pyobject_native_type!(PyModule, ffi::PyModule_Type, ffi::PyModule_Check); impl PyModule { /// Create a new module object with the `__name__` attribute set to name. diff --git a/src/types/set.rs b/src/types/set.rs index 39c8a00c471..43d9b39d51a 100644 --- a/src/types/set.rs +++ b/src/types/set.rs @@ -19,12 +19,7 @@ pub struct PySet(PyObject); pub struct PyFrozenSet(PyObject); pyobject_native_type!(PySet, ffi::PySet_Type, Some("builtins"), ffi::PySet_Check); -pyobject_native_type!( - PyFrozenSet, - ffi::PyFrozenSet_Type, - Some("builtins"), - ffi::PyFrozenSet_Check -); +pyobject_native_type!(PyFrozenSet, ffi::PyFrozenSet_Type, ffi::PyFrozenSet_Check); impl PySet { /// Creates a new set. diff --git a/src/types/slice.rs b/src/types/slice.rs index 4f8db4920d7..41f0b104714 100644 --- a/src/types/slice.rs +++ b/src/types/slice.rs @@ -14,12 +14,7 @@ use std::os::raw::c_long; #[repr(transparent)] pub struct PySlice(PyObject); -pyobject_native_type!( - PySlice, - ffi::PySlice_Type, - Some("builtins"), - ffi::PySlice_Check -); +pyobject_native_type!(PySlice, ffi::PySlice_Type, ffi::PySlice_Check); /// Represents a Python `slice` indices pub struct PySliceIndices { diff --git a/src/types/string.rs b/src/types/string.rs index 9d315f943f4..ad3aaa40735 100644 --- a/src/types/string.rs +++ b/src/types/string.rs @@ -18,12 +18,7 @@ use std::{mem, str}; #[repr(transparent)] pub struct PyString(PyObject); -pyobject_native_type!( - PyString, - ffi::PyUnicode_Type, - Some("builtins"), - ffi::PyUnicode_Check -); +pyobject_native_type!(PyString, ffi::PyUnicode_Type, ffi::PyUnicode_Check); /// Represents a Python `byte` string. #[repr(transparent)] diff --git a/src/types/tuple.rs b/src/types/tuple.rs index 65d28f39c89..9e259d1a9d6 100644 --- a/src/types/tuple.rs +++ b/src/types/tuple.rs @@ -17,12 +17,7 @@ use std::slice; #[repr(transparent)] pub struct PyTuple(PyObject); -pyobject_native_type!( - PyTuple, - ffi::PyTuple_Type, - Some("builtins"), - ffi::PyTuple_Check -); +pyobject_native_type!(PyTuple, ffi::PyTuple_Type, ffi::PyTuple_Check); impl PyTuple { /// Construct a new tuple with the given elements. diff --git a/src/types/typeobject.rs b/src/types/typeobject.rs index 5a515c92ae3..bfb68714a5c 100644 --- a/src/types/typeobject.rs +++ b/src/types/typeobject.rs @@ -16,12 +16,7 @@ use std::ffi::CStr; #[repr(transparent)] pub struct PyType(PyObject); -pyobject_native_type!( - PyType, - ffi::PyType_Type, - Some("builtins"), - ffi::PyType_Check -); +pyobject_native_type!(PyType, ffi::PyType_Type, ffi::PyType_Check); impl PyType { #[inline]