diff --git a/CHANGELOG.md b/CHANGELOG.md index ea82bffa..f69ddd6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,15 +9,20 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added * `#[pyclass]` objects can now be returned from rust functions + * `PyComplex` by kngwyu in [#226](https://github.com/PyO3/pyo3/pull/226) + +### Removed + * Removed most entries from the prelude. The new prelude is small and clear. + * Slowly removing specialization uses ### Changed - - * Slowly removing specialization uses + * Removes the types from the root module and the prelude. They now live in `pyo3::types` instead. * All exceptions are consturcted with `py_err` instead of `new`, as they return `PyErr` and not `Self`. * `as_mut` and friends take and `&mut self` instead of `&self` * `ObjectProtocol::call` now takes an `Option` for the kwargs instead of an `IntoPyDictPointer`. * `IntoPyDictPointer` was replace by `IntoPyDict` which doesn't convert `PyDict` itself anymore and returns a `PyDict` instead of `*mut PyObject`. * `PyTuple::new` now takes an `IntoIterator` instead of a slice + * Updated to syn 0.15 ### Fixed diff --git a/README.md b/README.md index 20689240..fef6f704 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,7 @@ Example program displaying the value of `sys.version`: extern crate pyo3; use pyo3::prelude::*; +use pyo3::types::PyDict; fn main() -> PyResult<()> { let gil = Python::acquire_gil(); diff --git a/examples/rustapi_module/src/lib.rs b/examples/rustapi_module/src/lib.rs index aadbb323..63af5fd2 100644 --- a/examples/rustapi_module/src/lib.rs +++ b/examples/rustapi_module/src/lib.rs @@ -3,15 +3,11 @@ #[macro_use] extern crate pyo3; -use pyo3::prelude::PyDeltaAccess; -use pyo3::prelude::PyModule; -use pyo3::prelude::PyObject; -use pyo3::prelude::{pyfunction, pymodinit}; -use pyo3::prelude::{PyDate, PyDateTime, PyDelta, PyTime, PyTzInfo}; -use pyo3::prelude::{PyDateAccess, PyTimeAccess}; -use pyo3::prelude::{PyDict, PyTuple}; -use pyo3::{ObjectProtocol, ToPyObject}; -use pyo3::{Py, PyResult, Python}; +use pyo3::prelude::*; +use pyo3::types::{ + PyDate, PyDateAccess, PyDateTime, PyDelta, PyDeltaAccess, PyDict, PyTime, PyTimeAccess, + PyTuple, PyTzInfo, +}; #[pyfunction] fn make_date(py: Python, year: i32, month: u8, day: u8) -> PyResult> { @@ -195,7 +191,7 @@ fn datetime_from_timestamp(py: Python, ts: f64, tz: Option<&PyTzInfo>) -> PyResu #[pyfunction] fn issue_219() -> PyResult<()> { let gil = Python::acquire_gil(); - let py = gil.python(); + let _py = gil.python(); Ok(()) } diff --git a/guide/src/class.md b/guide/src/class.md index 31e89203..e9cb3a3c 100644 --- a/guide/src/class.md +++ b/guide/src/class.md @@ -48,7 +48,7 @@ attribute. Only the python `__new__` method can be specified, `__init__` is not # # extern crate pyo3; # use pyo3::prelude::*; - +# use pyo3::PyRawObject; #[pyclass] struct MyClass { @@ -92,7 +92,7 @@ with value of custom class struct. Subclass must call parent's `__new__` method. # #![feature(specialization)] # extern crate pyo3; # use pyo3::prelude::*; -# +# use pyo3::PyRawObject; #[pyclass] struct BaseClass { val1: usize, diff --git a/guide/src/exception.md b/guide/src/exception.md index 440c6831..f9811e0d 100644 --- a/guide/src/exception.md +++ b/guide/src/exception.md @@ -7,7 +7,7 @@ You can use the `py_exception!` macro to define a new exception type: ```rust #[macro_use] extern crate pyo3; -py_exception!(module, MyError, pyo3::exc::Exception); +py_exception!(module, MyError, pyo3::exceptions::Exception); ``` * `module` is the name of the containing module. @@ -18,9 +18,10 @@ For example: ```rust #[macro_use] extern crate pyo3; -use pyo3::{Python, PyDict}; +use pyo3::Python; +use pyo3::types::PyDict; -py_exception!(mymodule, CustomError, pyo3::exc::Exception); +py_exception!(mymodule, CustomError, pyo3::exceptions::Exception); fn main() { let gil = Python::acquire_gil(); @@ -46,7 +47,7 @@ use pyo3::{Python, PyErr, exc}; fn main() { let gil = Python::acquire_gil(); let py = gil.python(); - PyErr::new::("Error").restore(py); + PyErr::new::("Error").restore(py); assert!(PyErr::occurred(py)); drop(PyErr::fetch(py)); } @@ -69,7 +70,7 @@ have rust type as well. # fn check_for_error() -> bool {false} fn my_func(arg: PyObject) -> PyResult<()> { if check_for_error() { - Err(exc::ValueError::py_err("argument is wrong")) + Err(exceptions::ValueError::py_err("argument is wrong")) } else { Ok(()) } @@ -106,8 +107,8 @@ To check the type of an exception, you can simply do: # fn main() { # let gil = Python::acquire_gil(); # let py = gil.python(); -# let err = exc::TypeError::py_err(NoArgs); -err.is_instance::(py); +# let err = exceptions::TypeError::py_err(NoArgs); +err.is_instance::(py); # } ``` @@ -139,7 +140,7 @@ use pyo3::{PyErr, PyResult, exc}; impl std::convert::From for PyErr { fn from(err: std::io::Error) -> PyErr { - exc::OSError.into() + exceptions::OSError.into() } } @@ -179,7 +180,7 @@ use pyo3::prelude::*; import_exception!(io, UnsupportedOperation); fn tell(file: PyObject) -> PyResult { - use pyo3::exc::*; + use pyo3::exceptions::*; let gil = Python::acquire_gil(); let py = gil.python(); diff --git a/guide/src/overview.md b/guide/src/overview.md index e4dcd67f..e369d6f7 100644 --- a/guide/src/overview.md +++ b/guide/src/overview.md @@ -84,6 +84,7 @@ Example program displaying the value of `sys.version`: extern crate pyo3; use pyo3::prelude::*; +use pyo3::types::PyDict; fn main() -> PyResult<()> { let gil = Python::acquire_gil(); diff --git a/guide/src/rust-cpython.md b/guide/src/rust-cpython.md index aef716ed..7bba1dc1 100644 --- a/guide/src/rust-cpython.md +++ b/guide/src/rust-cpython.md @@ -30,7 +30,7 @@ py_class!(class MyClass |py| { extern crate pyo3; use pyo3::prelude::*; - +use pyo3::PyRawObject; #[pyclass] struct MyClass { diff --git a/pyo3-derive-backend/src/module.rs b/pyo3-derive-backend/src/module.rs index c112859b..69758f87 100644 --- a/pyo3-derive-backend/src/module.rs +++ b/pyo3-derive-backend/src/module.rs @@ -20,7 +20,7 @@ pub fn py3_init(fnname: &syn::Ident, name: &syn::Ident, doc: syn::Lit) -> TokenS /// This autogenerated function is called by the python interpreter when importing /// the module. pub unsafe extern "C" fn #cb_name() -> *mut ::pyo3::ffi::PyObject { - ::pyo3::make_module(concat!(stringify!(#name), "\0"), #doc, #fnname) + ::pyo3::derive_utils::make_module(concat!(stringify!(#name), "\0"), #doc, #fnname) } } } @@ -32,7 +32,7 @@ pub fn py2_init(fnname: &syn::Ident, name: &syn::Ident, doc: syn::Lit) -> TokenS #[no_mangle] #[allow(non_snake_case)] pub unsafe extern "C" fn #cb_name() { - ::pyo3::make_module(concat!(stringify!(#name), "\0"), #doc, #fnname) + ::pyo3::derive_utils::make_module(concat!(stringify!(#name), "\0"), #doc, #fnname) } } } @@ -243,8 +243,8 @@ fn function_c_wrapper(name: &syn::Ident, spec: &method::FnSpec) -> TokenStream { let _pool = ::pyo3::GILPool::new(); let _py = ::pyo3::Python::assume_gil_acquired(); - let _args = _py.from_borrowed_ptr::<::pyo3::PyTuple>(_args); - let _kwargs: Option<&PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); + let _args = _py.from_borrowed_ptr::<::pyo3::types::PyTuple>(_args); + let _kwargs: Option<&::pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); #body_to_result ::pyo3::callback::cb_convert( diff --git a/pyo3-derive-backend/src/py_class.rs b/pyo3-derive-backend/src/py_class.rs index 27c510c6..1e6c86ea 100644 --- a/pyo3-derive-backend/src/py_class.rs +++ b/pyo3-derive-backend/src/py_class.rs @@ -236,6 +236,7 @@ fn impl_class( impl ::pyo3::ToPyObject for #cls { fn to_object(&self, py: ::pyo3::Python) -> ::pyo3::PyObject { + use ::pyo3::python::ToPyPointer; unsafe { ::pyo3::PyObject::from_borrowed_ptr(py, self.as_ptr()) } } } @@ -251,6 +252,7 @@ fn impl_class( impl<'a> ::pyo3::ToPyObject for &'a mut #cls { fn to_object(&self, py: ::pyo3::Python) -> ::pyo3::PyObject { + use ::pyo3::python::ToPyPointer; unsafe { ::pyo3::PyObject::from_borrowed_ptr(py, self.as_ptr()) } } } @@ -259,6 +261,7 @@ fn impl_class( fn with_borrowed_ptr(&self, _py: ::pyo3::Python, f: F) -> R where F: FnOnce(*mut ::pyo3::ffi::PyObject) -> R { + use ::pyo3::python::ToPyPointer; f(self.as_ptr()) } } @@ -267,6 +270,7 @@ fn impl_class( fn with_borrowed_ptr(&self, _py: ::pyo3::Python, f: F) -> R where F: FnOnce(*mut ::pyo3::ffi::PyObject) -> R { + use ::pyo3::python::ToPyPointer; f(self.as_ptr()) } } @@ -393,7 +397,7 @@ fn parse_attribute( // We need the 0 as value for the constant we're later building using quote for when there // are no other flags let mut flags = vec![parse_quote! {0}]; - let mut base: syn::TypePath = parse_quote! {::pyo3::PyObjectRef}; + let mut base: syn::TypePath = parse_quote! {::pyo3::types::PyObjectRef}; for expr in args.iter() { match expr { diff --git a/pyo3-derive-backend/src/py_method.rs b/pyo3-derive-backend/src/py_method.rs index a515e49a..22fc32b7 100644 --- a/pyo3-derive-backend/src/py_method.rs +++ b/pyo3-derive-backend/src/py_method.rs @@ -88,8 +88,8 @@ pub fn impl_wrap(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec, noargs: bool let _pool = ::pyo3::GILPool::new(); let _py = ::pyo3::Python::assume_gil_acquired(); let _slf = _py.mut_from_borrowed_ptr::<#cls>(_slf); - let _args = _py.from_borrowed_ptr::<::pyo3::PyTuple>(_args); - let _kwargs: Option<&PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); + let _args = _py.from_borrowed_ptr::<::pyo3::types::PyTuple>(_args); + let _kwargs: Option<&::pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); #body_to_result ::pyo3::callback::cb_convert( @@ -115,8 +115,8 @@ pub fn impl_proto_wrap(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec) -> Tok let _pool = ::pyo3::GILPool::new(); let _py = ::pyo3::Python::assume_gil_acquired(); let _slf = _py.mut_from_borrowed_ptr::<#cls>(_slf); - let _args = _py.from_borrowed_ptr::<::pyo3::PyTuple>(_args); - let _kwargs: Option<&PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); + let _args = _py.from_borrowed_ptr::<::pyo3::types::PyTuple>(_args); + let _kwargs: Option<&::pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); let _result = { #body @@ -161,13 +161,13 @@ pub fn impl_wrap_new(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec) -> Token let _py = ::pyo3::Python::assume_gil_acquired(); match ::pyo3::typeob::PyRawObject::new(_py, #cls::type_object(), _cls) { Ok(_obj) => { - let _args = _py.from_borrowed_ptr::<::pyo3::PyTuple>(_args); - let _kwargs: Option<&PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); + let _args = _py.from_borrowed_ptr::<::pyo3::types::PyTuple>(_args); + let _kwargs: Option<&::pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); #body_to_result match _result { - Ok(_) => _obj.into_ptr(), + Ok(_) => ::pyo3::IntoPyPointer::into_ptr(_obj), Err(e) => { e.restore(_py); ::std::ptr::null_mut() @@ -207,8 +207,8 @@ fn impl_wrap_init(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec) -> TokenStr let _pool = ::pyo3::GILPool::new(); let _py = ::pyo3::Python::assume_gil_acquired(); let _slf = _py.mut_from_borrowed_ptr::<#cls>(_slf); - let _args = _py.from_borrowed_ptr::<::pyo3::PyTuple>(_args); - let _kwargs: Option<&PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); + let _args = _py.from_borrowed_ptr::<::pyo3::types::PyTuple>(_args); + let _kwargs: Option<&::pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); #body_to_result match _result { @@ -252,9 +252,9 @@ pub fn impl_wrap_class(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec) -> Tok const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#name),"()"); let _pool = ::pyo3::GILPool::new(); let _py = ::pyo3::Python::assume_gil_acquired(); - let _cls = ::pyo3::PyType::from_type_ptr(_py, _cls as *mut ::pyo3::ffi::PyTypeObject); - let _args = _py.from_borrowed_ptr::<::pyo3::PyTuple>(_args); - let _kwargs: Option<&PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); + let _cls = ::pyo3::types::PyType::from_type_ptr(_py, _cls as *mut ::pyo3::ffi::PyTypeObject); + let _args = _py.from_borrowed_ptr::<::pyo3::types::PyTuple>(_args); + let _kwargs: Option<&::pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); #body_to_result ::pyo3::callback::cb_convert( @@ -293,8 +293,8 @@ pub fn impl_wrap_static(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec) -> To const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#name),"()"); let _pool = ::pyo3::GILPool::new(); let _py = ::pyo3::Python::assume_gil_acquired(); - let _args = _py.from_borrowed_ptr::<::pyo3::PyTuple>(_args); - let _kwargs: Option<&PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); + let _args = _py.from_borrowed_ptr::<::pyo3::types::PyTuple>(_args); + let _kwargs: Option<&::pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); #body_to_result ::pyo3::callback::cb_convert( @@ -317,7 +317,7 @@ pub(crate) fn impl_wrap_getter(cls: &syn::Type, name: &syn::Ident) -> TokenStrea match _slf.#name() { Ok(val) => { - val.into_object(_py).into_ptr() + ::pyo3::IntoPyPointer::into_ptr(val.into_object(_py)) } Err(e) => { e.restore(_py); @@ -413,7 +413,7 @@ pub fn impl_arg_params(spec: &FnSpec, body: TokenStream) -> TokenStream { }; params.push(quote! { - ::pyo3::argparse::ParamDescription{ + ::pyo3::derive_utils::ParamDescription{ name: stringify!(#name), is_optional: #opt, kw_only: #kwonly} }); } @@ -448,12 +448,12 @@ pub fn impl_arg_params(spec: &FnSpec, body: TokenStream) -> TokenStream { // create array of arguments, and then parse quote! { - const _PARAMS: &'static [::pyo3::argparse::ParamDescription<'static>] = &[ + const _PARAMS: &'static [::pyo3::derive_utils::ParamDescription<'static>] = &[ #(#params),* ]; let mut _output = [#(#placeholders),*]; - match ::pyo3::argparse::parse_args(Some(_LOCATION), _PARAMS, &_args, + match ::pyo3::derive_utils::parse_fn_args(Some(_LOCATION), _PARAMS, &_args, _kwargs, #accept_args, #accept_kwargs, &mut _output) { Ok(_) => { diff --git a/src/buffer.rs b/src/buffer.rs index 9d38fb08..3df4e494 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -23,10 +23,10 @@ use std::os::raw; use std::{cell, mem, slice}; use err::{self, PyResult}; -use exc; +use exceptions; use ffi; -use objects::PyObjectRef; use python::{Python, ToPyPointer}; +use types::PyObjectRef; /// Allows access to the underlying buffer used by a python object such as `bytes`, `bytearray` or `array.array`. #[repr(transparent)] @@ -460,7 +460,7 @@ impl PyBuffer { fort: u8, ) -> PyResult<()> { if mem::size_of_val(target) != self.len_bytes() { - return Err(exc::BufferError::py_err( + return Err(exceptions::BufferError::py_err( "Slice length does not match buffer length.", )); } @@ -563,7 +563,7 @@ impl PyBuffer { return buffer_readonly_error(); } if mem::size_of_val(source) != self.len_bytes() { - return Err(exc::BufferError::py_err( + return Err(exceptions::BufferError::py_err( "Slice length does not match buffer length.", )); } @@ -593,13 +593,13 @@ impl PyBuffer { } fn incompatible_format_error() -> PyResult<()> { - Err(exc::BufferError::py_err( + Err(exceptions::BufferError::py_err( "Slice type is incompatible with buffer format.", )) } fn buffer_readonly_error() -> PyResult<()> { - Err(exc::BufferError::py_err( + Err(exceptions::BufferError::py_err( "Cannot write to read-only buffer.", )) } diff --git a/src/callback.rs b/src/callback.rs index 6b1842e8..a400eafd 100644 --- a/src/callback.rs +++ b/src/callback.rs @@ -8,8 +8,8 @@ use std::{isize, ptr}; use conversion::IntoPyObject; use err::PyResult; use ffi::{self, Py_hash_t}; -use objects::exc::OverflowError; use python::{IntoPyPointer, Python}; +use types::exceptions::OverflowError; pub trait CallbackConverter { type R; diff --git a/src/class/basic.rs b/src/class/basic.rs index 73bea87a..0bc490a5 100644 --- a/src/class/basic.rs +++ b/src/class/basic.rs @@ -17,9 +17,9 @@ use conversion::{FromPyObject, IntoPyObject}; use err::{PyErr, PyResult}; use ffi; use objectprotocol::ObjectProtocol; -use objects::{exc, PyObjectRef}; use python::{IntoPyPointer, Python}; use typeob::PyTypeInfo; +use types::{exceptions, PyObjectRef}; use CompareOp; /// Basic python class customization @@ -458,7 +458,7 @@ fn extract_op(op: c_int) -> PyResult { ffi::Py_NE => Ok(CompareOp::Ne), ffi::Py_GT => Ok(CompareOp::Gt), ffi::Py_GE => Ok(CompareOp::Ge), - _ => Err(PyErr::new::( + _ => Err(PyErr::new::( "tp_richcompare called with invalid comparison operator", )), } diff --git a/src/class/descr.rs b/src/class/descr.rs index 724e2a57..3d3ac2b2 100644 --- a/src/class/descr.rs +++ b/src/class/descr.rs @@ -12,8 +12,8 @@ use class::methods::PyMethodDef; use conversion::{FromPyObject, IntoPyObject}; use err::PyResult; use ffi; -use objects::{PyObjectRef, PyType}; use typeob::PyTypeInfo; +use types::{PyObjectRef, PyType}; /// Descriptor interface #[allow(unused_variables)] diff --git a/src/class/macros.rs b/src/class/macros.rs index 73448e06..e625cf6e 100644 --- a/src/class/macros.rs +++ b/src/class/macros.rs @@ -87,7 +87,7 @@ macro_rules! py_binary_func { let _pool = $crate::GILPool::new(); let py = $crate::Python::assume_gil_acquired(); let slf = py.mut_from_borrowed_ptr::(slf); - let arg = py.from_borrowed_ptr::<$crate::PyObjectRef>(arg); + let arg = py.from_borrowed_ptr::<$crate::types::PyObjectRef>(arg); let result = match arg.extract() { Ok(arg) => slf.$f(arg).into(), @@ -114,8 +114,8 @@ macro_rules! py_binary_num_func { use $crate::ObjectProtocol; let _pool = $crate::GILPool::new(); let py = $crate::Python::assume_gil_acquired(); - let lhs = py.from_borrowed_ptr::<$crate::PyObjectRef>(lhs); - let rhs = py.from_borrowed_ptr::<$crate::PyObjectRef>(rhs); + let lhs = py.from_borrowed_ptr::<$crate::types::PyObjectRef>(lhs); + let rhs = py.from_borrowed_ptr::<$crate::types::PyObjectRef>(rhs); let result = match lhs.extract() { Ok(lhs) => match rhs.extract() { @@ -147,7 +147,7 @@ macro_rules! py_binary_self_func { let _pool = $crate::GILPool::new(); let py = $crate::Python::assume_gil_acquired(); let slf1 = py.mut_from_borrowed_ptr::(slf); - let arg = py.from_borrowed_ptr::<$crate::PyObjectRef>(arg); + let arg = py.from_borrowed_ptr::<$crate::types::PyObjectRef>(arg); let result = match arg.extract() { Ok(arg) => slf1.$f(arg).into(), @@ -216,8 +216,8 @@ macro_rules! py_ternary_func { let _pool = $crate::GILPool::new(); let py = $crate::Python::assume_gil_acquired(); let slf = py.mut_from_borrowed_ptr::(slf); - let arg1 = py.from_borrowed_ptr::<$crate::PyObjectRef>(arg1); - let arg2 = py.from_borrowed_ptr::<$crate::PyObjectRef>(arg2); + let arg1 = py.from_borrowed_ptr::<$crate::types::PyObjectRef>(arg1); + let arg2 = py.from_borrowed_ptr::<$crate::types::PyObjectRef>(arg2); let result = match arg1.extract() { Ok(arg1) => match arg2.extract() { @@ -249,9 +249,9 @@ macro_rules! py_ternary_num_func { let _pool = $crate::GILPool::new(); let py = $crate::Python::assume_gil_acquired(); - let arg1 = py.from_borrowed_ptr::<$crate::PyObjectRef>(arg1); - let arg2 = py.from_borrowed_ptr::<$crate::PyObjectRef>(arg2); - let arg3 = py.from_borrowed_ptr::<$crate::PyObjectRef>(arg3); + let arg1 = py.from_borrowed_ptr::<$crate::types::PyObjectRef>(arg1); + let arg2 = py.from_borrowed_ptr::<$crate::types::PyObjectRef>(arg2); + let arg3 = py.from_borrowed_ptr::<$crate::types::PyObjectRef>(arg3); let result = match arg1.extract() { Ok(arg1) => match arg2.extract() { @@ -287,8 +287,8 @@ macro_rules! py_ternary_self_func { let _pool = $crate::GILPool::new(); let py = $crate::Python::assume_gil_acquired(); let slf1 = py.mut_from_borrowed_ptr::(slf); - let arg1 = py.from_borrowed_ptr::<$crate::PyObjectRef>(arg1); - let arg2 = py.from_borrowed_ptr::<$crate::PyObjectRef>(arg2); + let arg1 = py.from_borrowed_ptr::<$crate::types::PyObjectRef>(arg1); + let arg2 = py.from_borrowed_ptr::<$crate::types::PyObjectRef>(arg2); let result = match arg1.extract() { Ok(arg1) => match arg2.extract() { @@ -328,13 +328,15 @@ macro_rules! py_func_set { let slf = py.mut_from_borrowed_ptr::<$generic>(slf); let result = if value.is_null() { - Err($crate::PyErr::new::(format!( - "Subscript deletion not supported by {:?}", - stringify!($generic) - ))) + Err($crate::PyErr::new::( + format!( + "Subscript deletion not supported by {:?}", + stringify!($generic) + ), + )) } else { - let name = py.mut_from_borrowed_ptr::<$crate::PyObjectRef>(name); - let value = py.from_borrowed_ptr::<$crate::PyObjectRef>(value); + let name = py.mut_from_borrowed_ptr::<$crate::types::PyObjectRef>(name); + let value = py.from_borrowed_ptr::<$crate::types::PyObjectRef>(value); match name.extract() { Ok(name) => match value.extract() { Ok(value) => slf.$fn_set(name, value).into(), @@ -374,14 +376,14 @@ macro_rules! py_func_del { let result = if value.is_null() { let slf = py.mut_from_borrowed_ptr::(slf); - let name = py.from_borrowed_ptr::<$crate::PyObjectRef>(name); + let name = py.from_borrowed_ptr::<$crate::types::PyObjectRef>(name); match name.extract() { Ok(name) => slf.$fn_del(name).into(), Err(e) => Err(e.into()), } } else { - Err(PyErr::new::( + Err(PyErr::new::( "Subscript assignment not supported", )) }; @@ -414,7 +416,7 @@ macro_rules! py_func_set_del { let _pool = $crate::GILPool::new(); let py = $crate::Python::assume_gil_acquired(); let slf = py.mut_from_borrowed_ptr::<$generic>(slf); - let name = py.from_borrowed_ptr::<$crate::PyObjectRef>(name); + let name = py.from_borrowed_ptr::<$crate::types::PyObjectRef>(name); let result = if value.is_null() { match name.extract() { @@ -422,7 +424,7 @@ macro_rules! py_func_set_del { Err(e) => Err(e.into()), } } else { - let value = py.from_borrowed_ptr::<$crate::PyObjectRef>(value); + let value = py.from_borrowed_ptr::<$crate::types::PyObjectRef>(value); match name.extract() { Ok(name) => match value.extract() { Ok(value) => slf.$fn_set(name, value).into(), diff --git a/src/class/mapping.rs b/src/class/mapping.rs index 5ce4dc2f..b711f7fc 100644 --- a/src/class/mapping.rs +++ b/src/class/mapping.rs @@ -8,9 +8,9 @@ use class::methods::PyMethodDef; use conversion::{FromPyObject, IntoPyObject}; use err::{PyErr, PyResult}; use ffi; -use objects::exc; use python::Python; use typeob::PyTypeInfo; +use types::exceptions; /// Mapping interface #[allow(unused_variables)] diff --git a/src/class/sequence.rs b/src/class/sequence.rs index 212dce08..32a73938 100644 --- a/src/class/sequence.rs +++ b/src/class/sequence.rs @@ -8,10 +8,10 @@ use conversion::{FromPyObject, IntoPyObject}; use err::{PyErr, PyResult}; use ffi; use objectprotocol::ObjectProtocol; -use objects::{exc, PyObjectRef}; use python::Python; use std::os::raw::c_int; use typeob::PyTypeInfo; +use types::{exceptions, PyObjectRef}; /// Sequece interface #[allow(unused_variables)] @@ -235,7 +235,7 @@ where let slf = py.mut_from_borrowed_ptr::(slf); let result = if value.is_null() { - Err(PyErr::new::(format!( + Err(PyErr::new::(format!( "Item deletion not supported by {:?}", stringify!(T) ))) @@ -311,7 +311,7 @@ mod sq_ass_item_impl { let result = if value.is_null() { slf.__delitem__(key as isize).into() } else { - Err(PyErr::new::(format!( + Err(PyErr::new::(format!( "Item assignment not supported by {:?}", stringify!(T) ))) diff --git a/src/conversion.rs b/src/conversion.rs index 7e0b7701..d1976343 100644 --- a/src/conversion.rs +++ b/src/conversion.rs @@ -6,9 +6,9 @@ use err::{PyDowncastError, PyResult}; use ffi; use instance::Py; use object::PyObject; -use objects::{PyObjectRef, PyTuple}; use python::{IntoPyPointer, Python, ToPyPointer}; use typeob::PyTypeInfo; +use types::{PyObjectRef, PyTuple}; /// Conversion trait that allows various objects to be converted into `PyObject` pub trait ToPyObject { diff --git a/src/argparse.rs b/src/derive_utils.rs similarity index 53% rename from src/argparse.rs rename to src/derive_utils.rs index de0dc436..448f4670 100644 --- a/src/argparse.rs +++ b/src/derive_utils.rs @@ -2,10 +2,18 @@ // // based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython -//! Python argument parsing +//! Functionality for the code generated by the derive backend + use conversion::PyTryFrom; use err::PyResult; -use objects::{exc, PyDict, PyObjectRef, PyString, PyTuple}; +use exceptions::TypeError; +use ffi; +use init_once; +use std::ptr; +use types::PyModule; +use types::{PyDict, PyObjectRef, PyString, PyTuple}; +use GILPool; +use Python; #[derive(Debug)] /// Description of a python parameter; used for `parse_args()`. @@ -26,7 +34,7 @@ pub struct ParamDescription<'a> { /// * kwargs: Keyword arguments /// * output: Output array that receives the arguments. /// Must have same length as `params` and must be initialized to `None`. -pub fn parse_args<'p>( +pub fn parse_fn_args<'p>( fname: Option<&str>, params: &[ParamDescription], args: &'p PyTuple, @@ -38,7 +46,7 @@ pub fn parse_args<'p>( let nargs = args.len(); let nkeywords = kwargs.map_or(0, |d| d.len()); if !accept_args && (nargs + nkeywords > params.len()) { - return Err(exc::TypeError::py_err(format!( + return Err(TypeError::py_err(format!( "{}{} takes at most {} argument{} ({} given)", fname.unwrap_or("function"), if fname.is_some() { "()" } else { "" }, @@ -55,7 +63,7 @@ pub fn parse_args<'p>( *out = Some(kwarg); used_keywords += 1; if i < nargs { - return Err(exc::TypeError::py_err(format!( + return Err(TypeError::py_err(format!( "Argument given by name ('{}') and position ({})", p.name, i + 1 @@ -65,7 +73,7 @@ pub fn parse_args<'p>( None => { if p.kw_only { if !p.is_optional { - return Err(exc::TypeError::py_err(format!( + return Err(TypeError::py_err(format!( "Required argument ('{}') is keyword only argument", p.name ))); @@ -76,7 +84,7 @@ pub fn parse_args<'p>( } else { *out = None; if !p.is_optional { - return Err(exc::TypeError::py_err(format!( + return Err(TypeError::py_err(format!( "Required argument ('{}') (pos {}) not found", p.name, i + 1 @@ -92,7 +100,7 @@ pub fn parse_args<'p>( let item = ::try_from(item)?; let key = ::try_from(item.get_item(0))?.to_string()?; if !params.iter().any(|p| p.name == key) { - return Err(exc::TypeError::py_err(format!( + return Err(TypeError::py_err(format!( "'{}' is an invalid keyword argument for this function", key ))); @@ -101,3 +109,90 @@ pub fn parse_args<'p>( } Ok(()) } + +#[cfg(Py_3)] +#[doc(hidden)] +/// Builds a module (or null) from a user given initializer. Used for `#[pymodinit]`. +pub unsafe fn make_module( + name: &str, + doc: &str, + initializer: impl Fn(Python, &PyModule) -> PyResult<()>, +) -> *mut ffi::PyObject { + use python::IntoPyPointer; + + init_once(); + + #[cfg(py_sys_config = "WITH_THREAD")] + // > Changed in version 3.7: This function is now called by Py_Initialize(), so you don’t have + // > to call it yourself anymore. + #[cfg(not(Py_3_7))] + ffi::PyEval_InitThreads(); + + static mut MODULE_DEF: ffi::PyModuleDef = ffi::PyModuleDef_INIT; + // We can't convert &'static str to *const c_char within a static initializer, + // so we'll do it here in the module initialization: + MODULE_DEF.m_name = name.as_ptr() as *const _; + + let module = ffi::PyModule_Create(&mut MODULE_DEF); + if module.is_null() { + return module; + } + + let _pool = GILPool::new(); + let py = Python::assume_gil_acquired(); + let module = match py.from_owned_ptr_or_err::(module) { + Ok(m) => m, + Err(e) => { + e.restore(py); + return ptr::null_mut(); + } + }; + + module + .add("__doc__", doc) + .expect("Failed to add doc for module"); + match initializer(py, module) { + Ok(_) => module.into_ptr(), + Err(e) => { + e.restore(py); + ptr::null_mut() + } + } +} + +#[cfg(not(Py_3))] +#[doc(hidden)] +/// Builds a module (or null) from a user given initializer. Used for `#[pymodinit]`. +pub unsafe fn make_module( + name: &str, + doc: &str, + initializer: impl Fn(Python, &PyModule) -> PyResult<()>, +) { + init_once(); + + #[cfg(py_sys_config = "WITH_THREAD")] + ffi::PyEval_InitThreads(); + + let _name = name.as_ptr() as *const _; + let _pool = GILPool::new(); + let py = Python::assume_gil_acquired(); + let _module = ffi::Py_InitModule(_name, ptr::null_mut()); + if _module.is_null() { + return; + } + + let _module = match py.from_borrowed_ptr_or_err::(_module) { + Ok(m) => m, + Err(e) => { + e.restore(py); + return; + } + }; + + _module + .add("__doc__", doc) + .expect("Failed to add doc for module"); + if let Err(e) = initializer(py, _module) { + e.restore(py) + } +} diff --git a/src/err.rs b/src/err.rs index 0f14f61b..f6fe0ec4 100644 --- a/src/err.rs +++ b/src/err.rs @@ -10,27 +10,28 @@ use conversion::{IntoPyObject, ToBorrowedObject, ToPyObject}; use ffi; use instance::Py; use object::PyObject; -use objects::{exc, PyObjectRef, PyType}; use python::{IntoPyPointer, Python, ToPyPointer}; use typeob::PyTypeObject; +use types::{exceptions, PyObjectRef, PyType}; /// Defines a new exception type. /// /// # Syntax -/// `py_exception!(module, MyError, pyo3::exc::Exception)` +/// `py_exception!(module, MyError, pyo3::exceptions::Exception)` /// /// * `module` is the name of the containing module. /// * `MyError` is the name of the new exception type. -/// * `pyo3::exc::Exception` is the name of the base type +/// * `pyo3::exceptions::Exception` is the name of the base type /// /// # Example /// ``` /// #[macro_use] /// extern crate pyo3; /// -/// use pyo3::{Python, PyDict}; +/// use pyo3::Python; +/// use pyo3::types::PyDict; /// -/// py_exception!(mymodule, CustomError, pyo3::exc::Exception); +/// py_exception!(mymodule, CustomError, pyo3::exceptions::Exception); /// /// fn main() { /// let gil = Python::acquire_gil(); @@ -97,7 +98,7 @@ macro_rules! py_exception { } #[inline] - fn type_object() -> $crate::Py<$crate::PyType> { + fn type_object() -> $crate::Py<$crate::types::PyType> { unsafe { $crate::Py::from_borrowed_ptr( $name::type_object() as *const _ as *mut $crate::ffi::PyObject @@ -156,7 +157,7 @@ impl PyErr { /// Panics if `T` is not a python class derived from `BaseException`. /// /// Example: - /// `return Err(PyErr::new::("Error message"));` + /// `return Err(PyErr::new::("Error message"));` pub fn new(value: V) -> PyErr where T: PyTypeObject, @@ -174,7 +175,7 @@ impl PyErr { /// Construct a new error, with the usual lazy initialization of Python exceptions. /// `exc` is the exception type; usually one of the standard exceptions - /// like `exc::RuntimeError`. + /// like `exceptions::RuntimeError`. /// `args` is the a tuple of arguments to pass to the exception constructor. pub fn from_type(exc: Py, args: A) -> PyErr where @@ -225,7 +226,7 @@ impl PyErr { } } else { PyErr { - ptype: exc::TypeError::type_object(), + ptype: exceptions::TypeError::type_object(), pvalue: PyErrValue::ToObject(Box::new("exceptions must derive from BaseException")), ptraceback: None, } @@ -297,7 +298,7 @@ impl PyErr { }; let ptype = if ptype.is_null() { - ::type_object() + ::type_object() } else { Py::from_owned_ptr(ptype) }; @@ -479,7 +480,7 @@ impl<'a> IntoPyObject for &'a PyErr { /// Converts `PyDowncastError` to Python `TypeError`. impl std::convert::From for PyErr { fn from(_err: PyDowncastError) -> PyErr { - exc::TypeError.into() + exceptions::TypeError.into() } } @@ -528,30 +529,32 @@ impl std::convert::From for PyErr { fn from(err: io::Error) -> PyErr { match err.kind() { io::ErrorKind::BrokenPipe => { - PyErr::from_value::(PyErrValue::ToArgs(Box::new(err))) - } - io::ErrorKind::ConnectionRefused => { - PyErr::from_value::(PyErrValue::ToArgs(Box::new(err))) - } - io::ErrorKind::ConnectionAborted => { - PyErr::from_value::(PyErrValue::ToArgs(Box::new(err))) + PyErr::from_value::(PyErrValue::ToArgs(Box::new(err))) } + io::ErrorKind::ConnectionRefused => PyErr::from_value::< + exceptions::ConnectionRefusedError, + >(PyErrValue::ToArgs(Box::new(err))), + io::ErrorKind::ConnectionAborted => PyErr::from_value::< + exceptions::ConnectionAbortedError, + >(PyErrValue::ToArgs(Box::new(err))), io::ErrorKind::ConnectionReset => { - PyErr::from_value::(PyErrValue::ToArgs(Box::new(err))) + PyErr::from_value::(PyErrValue::ToArgs(Box::new( + err, + ))) } io::ErrorKind::Interrupted => { - PyErr::from_value::(PyErrValue::ToArgs(Box::new(err))) - } - io::ErrorKind::NotFound => { - PyErr::from_value::(PyErrValue::ToArgs(Box::new(err))) + PyErr::from_value::(PyErrValue::ToArgs(Box::new(err))) } + io::ErrorKind::NotFound => PyErr::from_value::( + PyErrValue::ToArgs(Box::new(err)), + ), io::ErrorKind::WouldBlock => { - PyErr::from_value::(PyErrValue::ToArgs(Box::new(err))) + PyErr::from_value::(PyErrValue::ToArgs(Box::new(err))) } io::ErrorKind::TimedOut => { - PyErr::from_value::(PyErrValue::ToArgs(Box::new(err))) + PyErr::from_value::(PyErrValue::ToArgs(Box::new(err))) } - _ => PyErr::from_value::(PyErrValue::ToArgs(Box::new(err))), + _ => PyErr::from_value::(PyErrValue::ToArgs(Box::new(err))), } } } @@ -560,7 +563,7 @@ impl std::convert::From for PyErr { /// Create `OSError` from `io::Error` impl std::convert::From for PyErr { fn from(err: io::Error) -> PyErr { - PyErr::from_value::(PyErrValue::ToArgs(Box::new(err))) + PyErr::from_value::(PyErrValue::ToArgs(Box::new(err))) } } @@ -573,7 +576,7 @@ impl PyErrArguments for io::Error { impl std::convert::From> for PyErr { fn from(err: std::io::IntoInnerError) -> PyErr { - PyErr::from_value::(PyErrValue::ToArgs(Box::new(err))) + PyErr::from_value::(PyErrValue::ToArgs(Box::new(err))) } } @@ -583,17 +586,17 @@ impl PyErrArguments for std::io::IntoInnerError { } } -impl_to_pyerr!(std::num::ParseIntError, exc::ValueError); -impl_to_pyerr!(std::num::ParseFloatError, exc::ValueError); -impl_to_pyerr!(std::string::ParseError, exc::ValueError); -impl_to_pyerr!(std::str::ParseBoolError, exc::ValueError); -impl_to_pyerr!(std::ffi::IntoStringError, exc::UnicodeDecodeError); -impl_to_pyerr!(std::ffi::NulError, exc::ValueError); -impl_to_pyerr!(std::str::Utf8Error, exc::UnicodeDecodeError); -impl_to_pyerr!(std::string::FromUtf8Error, exc::UnicodeDecodeError); -impl_to_pyerr!(std::string::FromUtf16Error, exc::UnicodeDecodeError); -impl_to_pyerr!(std::char::DecodeUtf16Error, exc::UnicodeDecodeError); -impl_to_pyerr!(std::net::AddrParseError, exc::ValueError); +impl_to_pyerr!(std::num::ParseIntError, exceptions::ValueError); +impl_to_pyerr!(std::num::ParseFloatError, exceptions::ValueError); +impl_to_pyerr!(std::string::ParseError, exceptions::ValueError); +impl_to_pyerr!(std::str::ParseBoolError, exceptions::ValueError); +impl_to_pyerr!(std::ffi::IntoStringError, exceptions::UnicodeDecodeError); +impl_to_pyerr!(std::ffi::NulError, exceptions::ValueError); +impl_to_pyerr!(std::str::Utf8Error, exceptions::UnicodeDecodeError); +impl_to_pyerr!(std::string::FromUtf8Error, exceptions::UnicodeDecodeError); +impl_to_pyerr!(std::string::FromUtf16Error, exceptions::UnicodeDecodeError); +impl_to_pyerr!(std::char::DecodeUtf16Error, exceptions::UnicodeDecodeError); +impl_to_pyerr!(std::net::AddrParseError, exceptions::ValueError); pub fn panic_after_error() -> ! { unsafe { @@ -614,14 +617,14 @@ pub fn error_on_minusone(py: Python, result: libc::c_int) -> PyResult<()> { #[cfg(test)] mod tests { - use objects::exc; + use types::exceptions; use {PyErr, Python}; #[test] fn set_typeerror() { let gil = Python::acquire_gil(); let py = gil.python(); - let err: PyErr = exc::TypeError.into(); + let err: PyErr = exceptions::TypeError.into(); err.restore(py); assert!(PyErr::occurred(py)); drop(PyErr::fetch(py)); diff --git a/src/instance.rs b/src/instance.rs index bf41e238..2bd623b6 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -10,10 +10,10 @@ use ffi; use instance; use object::PyObject; use objectprotocol::ObjectProtocol; -use objects::PyObjectRef; use python::{IntoPyPointer, Python, ToPyPointer}; use pythonrun; use typeob::{PyTypeInfo, PyTypeObject}; +use types::PyObjectRef; pub struct PyToken(PhantomData>); diff --git a/src/lib.rs b/src/lib.rs index 271bf2a9..2af1a63f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,6 +34,7 @@ //! extern crate pyo3; //! //! use pyo3::prelude::*; +//! use pyo3::types::PyDict; //! //! fn main() -> PyResult<()> { //! let gil = Python::acquire_gil(); @@ -123,14 +124,29 @@ // We need those types in the macro exports #[doc(hidden)] pub extern crate libc; -extern crate pyo3cls; -extern crate spin; // We need that reexport for wrap_function #[doc(hidden)] pub extern crate mashup; #[cfg(test)] #[macro_use] extern crate assert_approx_eq; +extern crate pyo3cls; +extern crate spin; + +pub use class::*; +pub use conversion::{ + FromPyObject, IntoPyObject, IntoPyTuple, PyTryFrom, PyTryInto, ReturnTypeIntoPyResult, + ToBorrowedObject, ToPyObject, +}; +pub use err::{PyDowncastError, PyErr, PyErrArguments, PyErrValue, PyResult}; +pub use instance::{AsPyRef, Py, PyNativeType, PyObjectWithToken, PyToken}; +pub use noargs::NoArgs; +pub use object::PyObject; +pub use objectprotocol::ObjectProtocol; +pub use python::{IntoPyPointer, Python, ToPyPointer}; +pub use pythonrun::{init_once, prepare_freethreaded_python, GILGuard, GILPool}; +pub use typeob::{PyObjectAlloc, PyRawObject, PyTypeInfo}; +pub use types::exceptions; /// Rust FFI declarations for Python pub mod ffi; @@ -141,32 +157,7 @@ mod ffi2; #[cfg(Py_3)] mod ffi3; -pub use conversion::{ - FromPyObject, IntoPyObject, IntoPyTuple, PyTryFrom, PyTryInto, ReturnTypeIntoPyResult, - ToBorrowedObject, ToPyObject, -}; -pub use err::{PyDowncastError, PyErr, PyErrArguments, PyErrValue, PyResult}; -pub use instance::{AsPyRef, Py, PyNativeType, PyObjectWithToken, PyToken}; -pub use noargs::NoArgs; -pub use object::PyObject; -pub use objectprotocol::ObjectProtocol; -pub use objects::*; -pub use python::{IntoPyPointer, Python, ToPyPointer}; -pub use pythonrun::{init_once, prepare_freethreaded_python, GILGuard, GILPool}; -pub use typeob::{PyObjectAlloc, PyRawObject, PyTypeInfo}; pub mod class; -pub use class::*; - -/// The proc macro attributes -pub mod proc_macro { - pub use pyo3cls::{pyclass, pyfunction, pymethods, pyproto}; - - #[cfg(Py_3)] - pub use pyo3cls::mod3init as pymodinit; - - #[cfg(not(Py_3))] - pub use pyo3cls::mod2init as pymodinit; -} /// Constructs a `&'static CStr` literal. macro_rules! cstr { @@ -176,9 +167,37 @@ macro_rules! cstr { }; } +pub mod buffer; +#[doc(hidden)] +pub mod callback; +mod conversion; +#[doc(hidden)] +pub mod derive_utils; +mod err; +pub mod freelist; +mod instance; +mod noargs; +mod object; +mod objectprotocol; +pub mod prelude; +pub mod python; +mod pythonrun; +pub mod typeob; +pub mod types; + +/// The proc macros, which are also part of the prelude +pub mod proc_macro { + #[cfg(not(Py_3))] + pub use pyo3cls::mod2init as pymodinit; + #[cfg(Py_3)] + pub use pyo3cls::mod3init as pymodinit; + /// The proc macro attributes + pub use pyo3cls::{pyclass, pyfunction, pymethods, pyproto}; +} + /// Returns a function that takes a [Python] instance and returns a python function. /// -/// Use this together with `#[function]` and [PyModule::add_function]. +/// Use this together with `#[function]` and [types::PyModule::add_function]. #[macro_export] macro_rules! wrap_function { ($function_name:ident) => {{ @@ -195,21 +214,3 @@ macro_rules! wrap_function { } }}; } - -#[doc(hidden)] -pub mod argparse; -pub mod buffer; -#[doc(hidden)] -pub mod callback; -mod conversion; -mod err; -pub mod freelist; -mod instance; -mod noargs; -mod object; -mod objectprotocol; -mod objects; -pub mod prelude; -pub mod python; -mod pythonrun; -pub mod typeob; diff --git a/src/noargs.rs b/src/noargs.rs index 8ce5af8a..174fbf3a 100644 --- a/src/noargs.rs +++ b/src/noargs.rs @@ -3,8 +3,8 @@ use conversion::{IntoPyObject, IntoPyTuple, ToPyObject}; use instance::Py; use object::PyObject; -use objects::PyTuple; use python::Python; +use types::PyTuple; /// An empty struct that represents the empty argument list. /// Corresponds to the empty tuple `()` in Python. diff --git a/src/object.rs b/src/object.rs index 6b89ba7b..6c48293c 100644 --- a/src/object.rs +++ b/src/object.rs @@ -8,10 +8,9 @@ use conversion::{ use err::{PyDowncastError, PyErr, PyResult}; use ffi; use instance::{AsPyRef, PyObjectWithToken}; -use objects::PyDict; -use objects::{PyObjectRef, PyTuple}; use python::{IntoPyPointer, Python, ToPyPointer}; use pythonrun; +use types::{PyDict, PyObjectRef, PyTuple}; /// Safe wrapper around unsafe `*mut ffi::PyObject` pointer. #[derive(Debug)] diff --git a/src/objectprotocol.rs b/src/objectprotocol.rs index 96e27690..ea411939 100644 --- a/src/objectprotocol.rs +++ b/src/objectprotocol.rs @@ -5,13 +5,12 @@ use err::{self, PyDowncastError, PyErr, PyResult}; use ffi; use instance::PyObjectWithToken; use object::PyObject; -use objects::PyDict; -use objects::{PyIterator, PyObjectRef, PyString, PyTuple, PyType}; use python::{IntoPyPointer, Python, ToPyPointer}; use std; use std::cmp::Ordering; use std::os::raw::c_int; use typeob::PyTypeInfo; +use types::{PyDict, PyIterator, PyObjectRef, PyString, PyTuple, PyType}; /// Python object model helper methods pub trait ObjectProtocol { @@ -269,7 +268,7 @@ where } else if result < 0 { return Err(PyErr::fetch(py)); } - Err(::exc::TypeError::py_err( + Err(::exceptions::TypeError::py_err( "ObjectProtocol::compare(): All comparisons returned false", )) } @@ -482,8 +481,8 @@ mod test { use super::*; use conversion::{PyTryFrom, ToPyObject}; use instance::AsPyRef; - use objects::PyString; use python::Python; + use types::PyString; #[test] fn test_debug_string() { diff --git a/src/objects/exc_impl.rs b/src/objects/exc_impl.rs deleted file mode 100644 index a62a6535..00000000 --- a/src/objects/exc_impl.rs +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright (c) 2017-present PyO3 Project and Contributors - -/// Stringify a dotted path. -#[macro_export] -macro_rules! dot_stringify { - ($e:ident) => ( - stringify!($e) - ); - ($e:ident. $($es:ident).+) => ( - concat!(stringify!($e), ".", dot_stringify!($($es).*)) - ); -} - -/// Defines rust type for exception defined in Python code. -/// -/// # Syntax -/// `import_exception!(module, MyError)` -/// -/// * `module` is the name of the containing module. -/// * `MyError` is the name of the new exception type. -/// -/// # Example -/// ``` -/// #[macro_use] extern crate pyo3; -/// -/// use pyo3::{Python, PyDict}; -/// -/// import_exception!(socket, gaierror); -/// -/// fn main() { -/// let gil = Python::acquire_gil(); -/// let py = gil.python(); -/// let ctx = PyDict::new(py); -/// -/// ctx.set_item("gaierror", py.get_type::()).unwrap(); -/// py.run("import socket; assert gaierror is socket.gaierror", None, Some(ctx)).unwrap(); -/// } -/// ``` -#[macro_export] -macro_rules! import_exception { - ($($module:ident).+ , $name: ident) => { - #[allow(non_camel_case_types)] - pub struct $name; - - impl ::std::convert::From<$name> for $crate::PyErr { - fn from(_err: $name) -> $crate::PyErr { - $crate::PyErr::new::<$name, _>(()) - } - } - - impl ::std::convert::Into<$crate::PyResult> for $name { - fn into(self) -> $crate::PyResult { - $crate::PyErr::new::<$name, _>(()).into() - } - } - - impl $name { - pub fn py_err(args: T) -> $crate::PyErr - where Self: $crate::typeob::PyTypeObject + Sized - { - $crate::PyErr::new::(args) - } - pub fn into(args: T) -> $crate::PyResult - where Self: $crate::typeob::PyTypeObject + Sized - { - $crate::PyErr::new::(args).into() - } - } - - impl $crate::typeob::PyTypeObject for $name { - #[inline] - fn init_type() {} - - #[inline] - fn type_object() -> $crate::Py<$crate::PyType> { - use $crate::IntoPyPointer; - static mut TYPE_OBJECT: *mut $crate::ffi::PyTypeObject = ::std::ptr::null_mut(); - - unsafe { - if TYPE_OBJECT.is_null() { - let gil = $crate::Python::acquire_gil(); - let py = gil.python(); - - let imp = py.import(dot_stringify!($($module).*)) - .expect(concat!( - "Can not import module: ", dot_stringify!($($module).*))); - let cls = imp.get(stringify!($name)) - .expect(concat!( - "Can not load exception class: {}.{}", dot_stringify!($($module).*), - ".", stringify!($name))); - TYPE_OBJECT = cls.into_ptr() as *mut $crate::ffi::PyTypeObject; - } - - $crate::Py::from_borrowed_ptr( - TYPE_OBJECT as *const _ as *mut $crate::ffi::PyObject) - } - } - } - }; -} - -#[cfg(test)] -mod test { - use objects::PyDict; - use {PyErr, Python}; - - import_exception!(socket, gaierror); - import_exception!(email.errors, MessageError); - - #[test] - fn test_check_exception() { - let gil = Python::acquire_gil(); - let py = gil.python(); - - let err: PyErr = gaierror.into(); - let socket = py - .import("socket") - .map_err(|e| e.print(py)) - .expect("could not import socket"); - - let d = PyDict::new(py); - d.set_item("socket", socket) - .map_err(|e| e.print(py)) - .expect("could not setitem"); - d.set_item("exc", err) - .map_err(|e| e.print(py)) - .expect("could not setitem"); - - py.run("assert isinstance(exc, socket.gaierror)", None, Some(d)) - .map_err(|e| e.print(py)) - .expect("assertion failed"); - } - - #[test] - fn test_check_exception_nested() { - let gil = Python::acquire_gil(); - let py = gil.python(); - - let err: PyErr = MessageError.into(); - let email = py - .import("email") - .map_err(|e| e.print(py)) - .expect("could not import email"); - - let d = PyDict::new(py); - d.set_item("email", email) - .map_err(|e| e.print(py)) - .expect("could not setitem"); - d.set_item("exc", err) - .map_err(|e| e.print(py)) - .expect("could not setitem"); - - py.run( - "assert isinstance(exc, email.errors.MessageError)", - None, - Some(d), - ).map_err(|e| e.print(py)) - .expect("assertion failed"); - } -} diff --git a/src/prelude.rs b/src/prelude.rs index 4e0122aa..28a23653 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -10,19 +10,18 @@ //! use pyo3::prelude::*; //! ``` -pub use class::*; -pub use conversion::{ - FromPyObject, IntoPyObject, IntoPyTuple, PyTryFrom, PyTryInto, ToBorrowedObject, ToPyObject, -}; -pub use err::{PyDowncastError, PyErr, PyErrArguments, PyErrValue, PyResult}; -pub use instance::{AsPyRef, Py, PyNativeType, PyObjectWithToken, PyToken}; +pub use conversion::{FromPyObject, IntoPyObject, PyTryFrom, PyTryInto, ToPyObject}; +pub use err::{PyErr, PyResult}; +pub use instance::{AsPyRef, Py, PyToken}; pub use noargs::NoArgs; pub use object::PyObject; pub use objectprotocol::ObjectProtocol; -pub use objects::*; -pub use python::{IntoPyPointer, Python, ToPyPointer}; +pub use python::Python; pub use pythonrun::GILGuard; -pub use typeob::PyRawObject; +// This is only part of the prelude because we need it for the pymodinit function +pub use types::PyModule; +// This is required for the constructor +pub use PyRawObject; pub use pyo3cls::{pyclass, pyfunction, pymethods, pyproto}; diff --git a/src/python.rs b/src/python.rs index bc80a0bc..9e58a32c 100644 --- a/src/python.rs +++ b/src/python.rs @@ -7,13 +7,13 @@ use err::{PyDowncastError, PyErr, PyResult}; use ffi; use instance::{AsPyRef, Py, PyToken}; use object::PyObject; -use objects::{PyDict, PyModule, PyObjectRef, PyType}; use pythonrun::{self, GILGuard}; use std; use std::ffi::CString; use std::marker::PhantomData; use std::os::raw::c_int; use typeob::{PyObjectAlloc, PyTypeInfo, PyTypeObject}; +use types::{PyDict, PyModule, PyObjectRef, PyType}; /// Marker type that indicates that the GIL is currently held. /// @@ -482,7 +482,7 @@ impl<'p> Python<'p> { #[cfg(test)] mod test { use objectprotocol::ObjectProtocol; - use objects::{PyBool, PyDict, PyInt, PyList, PyObjectRef}; + use types::{PyBool, PyDict, PyInt, PyList, PyObjectRef}; use Python; #[test] diff --git a/src/pythonrun.rs b/src/pythonrun.rs index 20a84189..7dca0522 100644 --- a/src/pythonrun.rs +++ b/src/pythonrun.rs @@ -1,9 +1,9 @@ // Copyright (c) 2017-present PyO3 Project and Contributors use ffi; -use objects::PyObjectRef; use python::Python; use spin; use std::{any, marker, rc, sync}; +use types::PyObjectRef; static START: sync::Once = sync::ONCE_INIT; static START_PYO3: sync::Once = sync::ONCE_INIT; diff --git a/src/typeob.rs b/src/typeob.rs index da70d16d..514b0025 100644 --- a/src/typeob.rs +++ b/src/typeob.rs @@ -5,8 +5,6 @@ use class::methods::PyMethodDefType; use err::{PyErr, PyResult}; use instance::{Py, PyObjectWithToken, PyToken}; -use objects::PyObjectRef; -use objects::PyType; use python::ToPyPointer; use python::{IntoPyPointer, Python}; use std; @@ -14,6 +12,8 @@ use std::collections::HashMap; use std::ffi::CString; use std::mem; use std::os::raw::c_void; +use types::PyObjectRef; +use types::PyType; use {class, ffi, pythonrun}; /// Python type information. diff --git a/src/objects/boolobject.rs b/src/types/boolobject.rs similarity index 97% rename from src/objects/boolobject.rs rename to src/types/boolobject.rs index 8cab7c2c..67454e53 100644 --- a/src/objects/boolobject.rs +++ b/src/types/boolobject.rs @@ -2,8 +2,8 @@ use conversion::{IntoPyObject, PyTryFrom, ToBorrowedObject, ToPyObject}; use ffi; use object::PyObject; -use objects::PyObjectRef; use python::{Python, ToPyPointer}; +use types::PyObjectRef; use FromPyObject; use PyResult; @@ -81,8 +81,8 @@ impl<'source> FromPyObject<'source> for bool { mod test { use conversion::ToPyObject; use objectprotocol::ObjectProtocol; - use objects::{PyBool, PyObjectRef}; use python::Python; + use types::{PyBool, PyObjectRef}; #[test] fn test_true() { diff --git a/src/objects/bytearray.rs b/src/types/bytearray.rs similarity index 96% rename from src/objects/bytearray.rs rename to src/types/bytearray.rs index c10940e4..b5114679 100644 --- a/src/objects/bytearray.rs +++ b/src/types/bytearray.rs @@ -70,10 +70,10 @@ impl PyByteArray { #[cfg(test)] mod test { - use exc; + use exceptions; use object::PyObject; - use objects::PyByteArray; use python::Python; + use types::PyByteArray; #[test] fn test_bytearray() { @@ -96,7 +96,7 @@ mod test { let none = py.None(); if let Err(err) = PyByteArray::from(py, &none) { - assert!(err.is_instance::(py)); + assert!(err.is_instance::(py)); } else { panic!("error"); } diff --git a/src/objects/complex.rs b/src/types/complex.rs similarity index 100% rename from src/objects/complex.rs rename to src/types/complex.rs diff --git a/src/objects/datetime.rs b/src/types/datetime.rs similarity index 100% rename from src/objects/datetime.rs rename to src/types/datetime.rs diff --git a/src/objects/dict.rs b/src/types/dict.rs similarity index 99% rename from src/objects/dict.rs rename to src/types/dict.rs index 8c1b88f0..8588a00f 100644 --- a/src/objects/dict.rs +++ b/src/types/dict.rs @@ -5,10 +5,10 @@ use err::{self, PyErr, PyResult}; use ffi; use instance::PyObjectWithToken; use object::PyObject; -use objects::{PyList, PyObjectRef}; use python::{Python, ToPyPointer}; use std; use std::{cmp, collections, hash, mem}; +use types::{PyList, PyObjectRef}; /// Represents a Python `dict`. #[repr(transparent)] @@ -256,10 +256,10 @@ where mod test { use conversion::{IntoPyObject, PyTryFrom, ToPyObject}; use instance::AsPyRef; - use objects::dict::IntoPyDict; - use objects::{PyDict, PyTuple}; use python::Python; use std::collections::{BTreeMap, HashMap}; + use types::dict::IntoPyDict; + use types::{PyDict, PyTuple}; use ObjectProtocol; #[test] diff --git a/src/objects/exc.rs b/src/types/exceptions.rs similarity index 54% rename from src/objects/exc.rs rename to src/types/exceptions.rs index bc81ff5b..4eec4b90 100644 --- a/src/objects/exc.rs +++ b/src/types/exceptions.rs @@ -6,12 +6,115 @@ use conversion::ToPyObject; use err::{PyErr, PyResult}; use ffi; use instance::Py; -use objects::{PyObjectRef, PyTuple, PyType}; use python::{Python, ToPyPointer}; use std::ffi::CStr; use std::os::raw::c_char; use std::{self, ops}; use typeob::PyTypeObject; +use types::{PyObjectRef, PyTuple, PyType}; + +// Copyright (c) 2017-present PyO3 Project and Contributors + +/// Stringify a dotted path. +#[doc(hidden)] +#[macro_export] +macro_rules! dot_stringify { + ($e:ident) => ( + stringify!($e) + ); + ($e:ident. $($es:ident).+) => ( + concat!(stringify!($e), ".", dot_stringify!($($es).*)) + ); +} + +/// Defines rust type for exception defined in Python code. +/// +/// # Syntax +/// `import_exception!(module, MyError)` +/// +/// * `module` is the name of the containing module. +/// * `MyError` is the name of the new exception type. +/// +/// # Example +/// ``` +/// #[macro_use] extern crate pyo3; +/// +/// use pyo3::Python; +/// use pyo3::types::PyDict; +/// +/// import_exception!(socket, gaierror); +/// +/// fn main() { +/// let gil = Python::acquire_gil(); +/// let py = gil.python(); +/// let ctx = PyDict::new(py); +/// +/// ctx.set_item("gaierror", py.get_type::()).unwrap(); +/// py.run("import socket; assert gaierror is socket.gaierror", None, Some(ctx)).unwrap(); +/// } +/// ``` +#[macro_export] +macro_rules! import_exception { + ($($module:ident).+ , $name: ident) => { + #[allow(non_camel_case_types)] + pub struct $name; + + impl ::std::convert::From<$name> for $crate::PyErr { + fn from(_err: $name) -> $crate::PyErr { + $crate::PyErr::new::<$name, _>(()) + } + } + + impl ::std::convert::Into<$crate::PyResult> for $name { + fn into(self) -> $crate::PyResult { + $crate::PyErr::new::<$name, _>(()).into() + } + } + + impl $name { + pub fn py_err(args: T) -> $crate::PyErr + where Self: $crate::typeob::PyTypeObject + Sized + { + $crate::PyErr::new::(args) + } + pub fn into(args: T) -> $crate::PyResult + where Self: $crate::typeob::PyTypeObject + Sized + { + $crate::PyErr::new::(args).into() + } + } + + impl $crate::typeob::PyTypeObject for $name { + #[inline] + fn init_type() {} + + #[inline] + fn type_object() -> $crate::Py<$crate::types::PyType> { + use $crate::IntoPyPointer; + static mut TYPE_OBJECT: *mut $crate::ffi::PyTypeObject = ::std::ptr::null_mut(); + + unsafe { + if TYPE_OBJECT.is_null() { + let gil = $crate::Python::acquire_gil(); + let py = gil.python(); + + let imp = py.import(dot_stringify!($($module).*)) + .expect(concat!( + "Can not import module: ", dot_stringify!($($module).*))); + let cls = imp.get(stringify!($name)) + .expect(concat!( + "Can not load exception class: {}.{}", dot_stringify!($($module).*), + ".", stringify!($name))); + TYPE_OBJECT = cls.into_ptr() as *mut $crate::ffi::PyTypeObject; + } + + $crate::Py::from_borrowed_ptr( + TYPE_OBJECT as *const _ as *mut $crate::ffi::PyObject) + } + } + } + }; +} macro_rules! exc_type ( ($name:ident, $exc_name:ident) => ( @@ -193,3 +296,63 @@ pub mod socket { import_exception!(socket, gaierror); import_exception!(socket, timeout); } + +#[cfg(test)] +mod test { + use types::PyDict; + use {PyErr, Python}; + + import_exception!(socket, gaierror); + import_exception!(email.errors, MessageError); + + #[test] + fn test_check_exception() { + let gil = Python::acquire_gil(); + let py = gil.python(); + + let err: PyErr = gaierror.into(); + let socket = py + .import("socket") + .map_err(|e| e.print(py)) + .expect("could not import socket"); + + let d = PyDict::new(py); + d.set_item("socket", socket) + .map_err(|e| e.print(py)) + .expect("could not setitem"); + d.set_item("exc", err) + .map_err(|e| e.print(py)) + .expect("could not setitem"); + + py.run("assert isinstance(exc, socket.gaierror)", None, Some(d)) + .map_err(|e| e.print(py)) + .expect("assertion failed"); + } + + #[test] + fn test_check_exception_nested() { + let gil = Python::acquire_gil(); + let py = gil.python(); + + let err: PyErr = MessageError.into(); + let email = py + .import("email") + .map_err(|e| e.print(py)) + .expect("could not import email"); + + let d = PyDict::new(py); + d.set_item("email", email) + .map_err(|e| e.print(py)) + .expect("could not setitem"); + d.set_item("exc", err) + .map_err(|e| e.print(py)) + .expect("could not setitem"); + + py.run( + "assert isinstance(exc, email.errors.MessageError)", + None, + Some(d), + ).map_err(|e| e.print(py)) + .expect("assertion failed"); + } +} diff --git a/src/objects/floatob.rs b/src/types/floatob.rs similarity index 99% rename from src/objects/floatob.rs rename to src/types/floatob.rs index 9e035c03..5e3e188f 100644 --- a/src/objects/floatob.rs +++ b/src/types/floatob.rs @@ -8,9 +8,9 @@ use ffi; use instance::{Py, PyObjectWithToken}; use object::PyObject; use objectprotocol::ObjectProtocol; -use objects::PyObjectRef; use python::{Python, ToPyPointer}; use std::os::raw::c_double; +use types::PyObjectRef; use FromPyObject; use PyResult; diff --git a/src/objects/iterator.rs b/src/types/iterator.rs similarity index 98% rename from src/objects/iterator.rs rename to src/types/iterator.rs index e18d4937..72f45c61 100644 --- a/src/objects/iterator.rs +++ b/src/types/iterator.rs @@ -5,8 +5,8 @@ use err::{PyDowncastError, PyErr, PyResult}; use ffi; use instance::PyObjectWithToken; -use objects::PyObjectRef; use python::{Python, ToPyPointer}; +use types::PyObjectRef; /// A python iterator object. /// @@ -69,9 +69,9 @@ mod tests { use conversion::{PyTryFrom, ToPyObject}; use instance::AsPyRef; use objectprotocol::ObjectProtocol; - use objects::{PyList, PyObjectRef}; use python::Python; use pythonrun::GILPool; + use types::{PyList, PyObjectRef}; #[test] fn vec_iter() { diff --git a/src/objects/list.rs b/src/types/list.rs similarity index 99% rename from src/objects/list.rs rename to src/types/list.rs index 19fc4059..fc8b3ba8 100644 --- a/src/objects/list.rs +++ b/src/types/list.rs @@ -9,8 +9,8 @@ use err::{self, PyResult}; use ffi::{self, Py_ssize_t}; use instance::PyObjectWithToken; use object::PyObject; -use objects::PyObjectRef; use python::{IntoPyPointer, Python, ToPyPointer}; +use types::PyObjectRef; /// Represents a Python `list`. #[repr(transparent)] @@ -191,8 +191,8 @@ mod test { use conversion::{PyTryFrom, ToPyObject}; use instance::AsPyRef; use objectprotocol::ObjectProtocol; - use objects::PyList; use python::Python; + use types::PyList; #[test] fn test_new() { diff --git a/src/objects/mod.rs b/src/types/mod.rs similarity index 87% rename from src/objects/mod.rs rename to src/types/mod.rs index 8c4c9685..c39af460 100644 --- a/src/objects/mod.rs +++ b/src/types/mod.rs @@ -1,5 +1,7 @@ // Copyright (c) 2017-present PyO3 Project and Contributors +//! Various types defined by the python interpreter such as `int`, `str` and `tuple` + pub use self::boolobject::PyBool; pub use self::bytearray::PyByteArray; pub use self::complex::PyComplex; @@ -11,7 +13,7 @@ pub use self::dict::PyDict; pub use self::floatob::PyFloat; pub use self::iterator::PyIterator; pub use self::list::PyList; -pub use self::module::{make_module, PyModule}; +pub use self::module::PyModule; #[cfg(not(Py_3))] pub use self::num2::{PyInt, PyLong}; #[cfg(Py_3)] @@ -31,9 +33,6 @@ pub use self::typeobject::PyType; use ffi; use python::ToPyPointer; -#[macro_use] -mod exc_impl; - /// Implements a typesafe conversions throught [FromPyObject], given a typecheck function as second /// parameter #[macro_export] @@ -42,11 +41,11 @@ macro_rules! pyobject_downcast ( impl<'a, $($type_param,)*> $crate::FromPyObject<'a> for &'a $name { /// Extracts `Self` from the source `PyObject`. - fn extract(ob: &'a $crate::PyObjectRef) -> $crate::PyResult + fn extract(ob: &'a $crate::types::PyObjectRef) -> $crate::PyResult { unsafe { if $checkfunction(ob.as_ptr()) != 0 { - Ok(&*(ob as *const $crate::PyObjectRef as *const $name)) + Ok(&*(ob as *const $crate::types::PyObjectRef as *const $name)) } else { Err($crate::PyDowncastError.into()) } @@ -61,9 +60,9 @@ macro_rules! pyobject_native_type_named ( ($name: ty $(,$type_param: ident)*) => { impl<$($type_param,)*> $crate::PyNativeType for $name {} - impl<$($type_param,)*> ::std::convert::AsRef<$crate::PyObjectRef> for $name { - fn as_ref(&self) -> &$crate::PyObjectRef { - unsafe{&*(self as *const $name as *const $crate::PyObjectRef)} + impl<$($type_param,)*> ::std::convert::AsRef<$crate::types::PyObjectRef> for $name { + fn as_ref(&self) -> &$crate::types::PyObjectRef { + unsafe{&*(self as *const $name as *const $crate::types::PyObjectRef)} } } @@ -97,9 +96,9 @@ macro_rules! pyobject_native_type ( pyobject_native_type_named!($name $(,$type_param)*); pyobject_native_type_convert!($name, $typeobject, $checkfunction $(,$type_param)*); - impl<'a, $($type_param,)*> ::std::convert::From<&'a $name> for &'a $crate::PyObjectRef { + impl<'a, $($type_param,)*> ::std::convert::From<&'a $name> for &'a $crate::types::PyObjectRef { fn from(ob: &'a $name) -> Self { - unsafe{&*(ob as *const $name as *const $crate::PyObjectRef)} + unsafe{&*(ob as *const $name as *const $crate::types::PyObjectRef)} } } }; @@ -110,7 +109,7 @@ macro_rules! pyobject_native_type_convert( ($name: ty, $typeobject: expr, $checkfunction: path $(,$type_param: ident)*) => { impl<$($type_param,)*> $crate::typeob::PyTypeInfo for $name { type Type = (); - type BaseType = $crate::PyObjectRef; + type BaseType = $crate::types::PyObjectRef; const NAME: &'static str = stringify!($name); const SIZE: usize = ::std::mem::size_of::<$crate::ffi::PyObject>(); @@ -121,7 +120,7 @@ macro_rules! pyobject_native_type_convert( &mut $typeobject } - fn is_instance(ptr: &$crate::objects::PyObjectRef) -> bool { + fn is_instance(ptr: &$crate::types::PyObjectRef) -> bool { #[allow(unused_unsafe)] unsafe { $checkfunction(ptr.as_ptr()) > 0 } } @@ -132,8 +131,8 @@ macro_rules! pyobject_native_type_convert( fn init_type() {} #[inline] - fn type_object() -> $crate::Py<$crate::PyType> { - $crate::PyType::new::<$name>() + fn type_object() -> $crate::Py<$crate::types::PyType> { + $crate::types::PyType::new::<$name>() } } @@ -188,7 +187,7 @@ mod bytearray; mod complex; mod datetime; mod dict; -pub mod exc; +pub mod exceptions; mod floatob; mod iterator; mod list; diff --git a/src/objects/module.rs b/src/types/module.rs similarity index 70% rename from src/objects/module.rs rename to src/types/module.rs index 140b0348..da0ae1ea 100644 --- a/src/objects/module.rs +++ b/src/types/module.rs @@ -5,18 +5,15 @@ use conversion::{IntoPyTuple, ToPyObject}; use err::{PyErr, PyResult}; use ffi; -use init_once; use instance::PyObjectWithToken; use object::PyObject; use objectprotocol::ObjectProtocol; -use objects::{exc, PyDict, PyObjectRef, PyType}; use python::{Python, ToPyPointer}; use std::ffi::{CStr, CString}; use std::os::raw::c_char; -use std::ptr; use std::str; use typeob::{initialize_type, PyTypeInfo}; -use GILPool; +use types::{exceptions, PyDict, PyObjectRef, PyType}; /// Represents a Python `module` object. #[repr(transparent)] @@ -84,11 +81,9 @@ impl PyModule { let slice = CStr::from_ptr(ptr).to_bytes(); match str::from_utf8(slice) { Ok(s) => Ok(s), - Err(e) => Err(PyErr::from_instance(exc::UnicodeDecodeError::new_utf8( - self.py(), - slice, - e, - )?)), + Err(e) => Err(PyErr::from_instance( + exceptions::UnicodeDecodeError::new_utf8(self.py(), slice, e)?, + )), } } } @@ -194,90 +189,3 @@ impl PyModule { self.add(name.extract(self.py()).unwrap(), function) } } - -#[cfg(Py_3)] -#[doc(hidden)] -/// Builds a module (or null) from a user given initializer. Used for `#[pymodinit]`. -pub unsafe fn make_module( - name: &str, - doc: &str, - initializer: impl Fn(Python, &PyModule) -> PyResult<()>, -) -> *mut ffi::PyObject { - use python::IntoPyPointer; - - init_once(); - - #[cfg(py_sys_config = "WITH_THREAD")] - // > Changed in version 3.7: This function is now called by Py_Initialize(), so you don’t have - // > to call it yourself anymore. - #[cfg(not(Py_3_7))] - ffi::PyEval_InitThreads(); - - static mut MODULE_DEF: ffi::PyModuleDef = ffi::PyModuleDef_INIT; - // We can't convert &'static str to *const c_char within a static initializer, - // so we'll do it here in the module initialization: - MODULE_DEF.m_name = name.as_ptr() as *const _; - - let module = ffi::PyModule_Create(&mut MODULE_DEF); - if module.is_null() { - return module; - } - - let _pool = GILPool::new(); - let py = Python::assume_gil_acquired(); - let module = match py.from_owned_ptr_or_err::(module) { - Ok(m) => m, - Err(e) => { - e.restore(py); - return ptr::null_mut(); - } - }; - - module - .add("__doc__", doc) - .expect("Failed to add doc for module"); - match initializer(py, module) { - Ok(_) => module.into_ptr(), - Err(e) => { - e.restore(py); - ptr::null_mut() - } - } -} - -#[cfg(not(Py_3))] -#[doc(hidden)] -/// Builds a module (or null) from a user given initializer. Used for `#[pymodinit]`. -pub unsafe fn make_module( - name: &str, - doc: &str, - initializer: impl Fn(Python, &PyModule) -> PyResult<()>, -) { - init_once(); - - #[cfg(py_sys_config = "WITH_THREAD")] - ffi::PyEval_InitThreads(); - - let _name = name.as_ptr() as *const _; - let _pool = GILPool::new(); - let py = Python::assume_gil_acquired(); - let _module = ffi::Py_InitModule(_name, ptr::null_mut()); - if _module.is_null() { - return; - } - - let _module = match py.from_borrowed_ptr_or_err::(_module) { - Ok(m) => m, - Err(e) => { - e.restore(py); - return; - } - }; - - _module - .add("__doc__", doc) - .expect("Failed to add doc for module"); - if let Err(e) = initializer(py, _module) { - e.restore(py) - } -} diff --git a/src/objects/num2.rs b/src/types/num2.rs similarity index 97% rename from src/objects/num2.rs rename to src/types/num2.rs index ddb9c2c1..4e4bc280 100644 --- a/src/objects/num2.rs +++ b/src/types/num2.rs @@ -13,8 +13,8 @@ use err::{PyErr, PyResult}; use ffi; use instance::{Py, PyObjectWithToken}; use object::PyObject; -use objects::{exc, PyObjectRef}; use python::{IntoPyPointer, Python, ToPyPointer}; +use types::{exceptions, PyObjectRef}; /// Represents a Python `int` object. /// @@ -86,7 +86,7 @@ macro_rules! int_fits_c_long( } match cast::(val) { Some(v) => Ok(v), - None => Err(exc::OverflowError.into()) + None => Err(exceptions::OverflowError.into()) } } } @@ -128,7 +128,7 @@ macro_rules! int_convert_u64_or_i64 ( } else if ffi::PyInt_Check(ptr) != 0 { match cast::(ffi::PyInt_AS_LONG(ptr)) { Some(v) => Ok(v), - None => Err(exc::OverflowError.into()) + None => Err(exceptions::OverflowError.into()) } } else { let num = PyObject::from_owned_ptr_or_err( diff --git a/src/objects/num3.rs b/src/types/num3.rs similarity index 95% rename from src/objects/num3.rs rename to src/types/num3.rs index 743d5493..9a466a92 100644 --- a/src/objects/num3.rs +++ b/src/types/num3.rs @@ -11,10 +11,10 @@ use err::{PyErr, PyResult}; use ffi; use instance::PyObjectWithToken; use object::PyObject; -use objects::{exc, PyObjectRef}; use python::{Python, ToPyPointer}; use std::i64; use std::os::raw::{c_long, c_uchar}; +use types::{exceptions, PyObjectRef}; /// Represents a Python `int` object. /// @@ -61,7 +61,7 @@ macro_rules! int_fits_c_long ( }?; match cast::(val) { Some(v) => Ok(v), - None => Err(exc::OverflowError.into()) + None => Err(exceptions::OverflowError.into()) } } } @@ -148,7 +148,7 @@ mod test { macro_rules! test_common ( ($test_mod_name:ident, $t:ty) => ( mod $test_mod_name { - use objects::exc; + use types::exceptions; use conversion::ToPyObject; use python::Python; @@ -159,7 +159,7 @@ mod test { let obj = ("123").to_object(py); let err = obj.extract::<$t>(py).unwrap_err(); - assert!(err.is_instance::(py)); + assert!(err.is_instance::(py)); } #[test] @@ -169,7 +169,7 @@ mod test { let obj = (12.3).to_object(py); let err = obj.extract::<$t>(py).unwrap_err(); - assert!(err.is_instance::(py)); + assert!(err.is_instance::(py)); } #[test] diff --git a/src/objects/num_common.rs b/src/types/num_common.rs similarity index 97% rename from src/objects/num_common.rs rename to src/types/num_common.rs index 7f8baf5d..7971e870 100644 --- a/src/objects/num_common.rs +++ b/src/types/num_common.rs @@ -36,7 +36,7 @@ macro_rules! int_fits_larger_int( let val = try!($crate::objectprotocol::ObjectProtocol::extract::<$larger_type>(obj)); match cast::<$larger_type, $rust_type>(val) { Some(v) => Ok(v), - None => Err(exc::OverflowError.into()) + None => Err(exceptions::OverflowError.into()) } } } @@ -188,8 +188,8 @@ mod test { fn test_u128_overflow() { use ffi; use object::PyObject; - use objects::exc; use std::os::raw::c_uchar; + use types::exceptions; let gil = Python::acquire_gil(); let py = gil.python(); let overflow_bytes: [c_uchar; 20] = [255; 20]; @@ -202,7 +202,7 @@ mod test { ); let obj = PyObject::from_owned_ptr_or_panic(py, obj); let err = obj.extract::(py).unwrap_err(); - assert!(err.is_instance::(py)); + assert!(err.is_instance::(py)); } } } diff --git a/src/objects/sequence.rs b/src/types/sequence.rs similarity index 99% rename from src/objects/sequence.rs rename to src/types/sequence.rs index 36171825..72d729f7 100644 --- a/src/objects/sequence.rs +++ b/src/types/sequence.rs @@ -7,8 +7,8 @@ use ffi::{self, Py_ssize_t}; use instance::PyObjectWithToken; use object::PyObject; use objectprotocol::ObjectProtocol; -use objects::{PyList, PyObjectRef, PyTuple}; use python::ToPyPointer; +use types::{PyList, PyObjectRef, PyTuple}; /// Represents a reference to a python object supporting the sequence protocol. #[repr(transparent)] @@ -313,8 +313,8 @@ mod test { use instance::AsPyRef; use object::PyObject; use objectprotocol::ObjectProtocol; - use objects::PySequence; use python::{Python, ToPyPointer}; + use types::PySequence; fn get_object() -> PyObject { // Convenience function for getting a single unique object diff --git a/src/objects/set.rs b/src/types/set.rs similarity index 100% rename from src/objects/set.rs rename to src/types/set.rs diff --git a/src/objects/slice.rs b/src/types/slice.rs similarity index 100% rename from src/objects/slice.rs rename to src/types/slice.rs diff --git a/src/objects/string.rs b/src/types/string.rs similarity index 98% rename from src/objects/string.rs rename to src/types/string.rs index 780149b4..24dc93c1 100644 --- a/src/objects/string.rs +++ b/src/types/string.rs @@ -10,8 +10,8 @@ use err::{PyErr, PyResult}; use ffi; use instance::{Py, PyObjectWithToken}; use object::PyObject; -use objects::PyObjectRef; use python::{Python, ToPyPointer}; +use types::PyObjectRef; /// Represents a Python `string`. #[repr(transparent)] @@ -21,7 +21,9 @@ pyobject_native_type!(PyString, ffi::PyUnicode_Type, ffi::PyUnicode_Check); /// Represents a Python `unicode string`. /// Corresponds to `unicode` in Python 2, and `str` in Python 3. -pub use PyString as PyUnicode; +//pub use PyString as PyUnicode; + +pub struct PyUnicode(); /// Represents a Python `byte` string. #[repr(transparent)] diff --git a/src/objects/string2.rs b/src/types/string2.rs similarity index 100% rename from src/objects/string2.rs rename to src/types/string2.rs diff --git a/src/objects/stringdata.rs b/src/types/stringdata.rs similarity index 78% rename from src/objects/stringdata.rs rename to src/types/stringdata.rs index bbfd756a..fa8015c1 100644 --- a/src/objects/stringdata.rs +++ b/src/types/stringdata.rs @@ -6,8 +6,8 @@ use std::borrow::Cow; use std::{char, str}; use err::{PyErr, PyResult}; -use objects::exc; use python::Python; +use types::exceptions; /// Enum of possible Python string representations. #[derive(Clone, Copy, Debug)] @@ -50,9 +50,9 @@ impl<'a> PyStringData<'a> { match self { PyStringData::Utf8(data) => match str::from_utf8(data) { Ok(s) => Ok(Cow::Borrowed(s)), - Err(e) => Err(PyErr::from_instance(exc::UnicodeDecodeError::new_utf8( - py, data, e, - )?)), + Err(e) => Err(PyErr::from_instance( + exceptions::UnicodeDecodeError::new_utf8(py, data, e)?, + )), }, PyStringData::Latin1(data) => { if data.iter().all(|&b| b.is_ascii()) { @@ -67,13 +67,15 @@ impl<'a> PyStringData<'a> { } match String::from_utf16(data) { Ok(s) => Ok(Cow::Owned(s)), - Err(_) => Err(PyErr::from_instance(exc::UnicodeDecodeError::new_err( - py, - cstr!("utf-16"), - utf16_bytes(data), - 0..2 * data.len(), - cstr!("invalid utf-16"), - )?)), + Err(_) => Err(PyErr::from_instance( + exceptions::UnicodeDecodeError::new_err( + py, + cstr!("utf-16"), + utf16_bytes(data), + 0..2 * data.len(), + cstr!("invalid utf-16"), + )?, + )), } } PyStringData::Utf32(data) => { @@ -82,13 +84,15 @@ impl<'a> PyStringData<'a> { } match data.iter().map(|&u| char::from_u32(u)).collect() { Some(s) => Ok(Cow::Owned(s)), - None => Err(PyErr::from_instance(exc::UnicodeDecodeError::new_err( - py, - cstr!("utf-32"), - utf32_bytes(data), - 0..4 * data.len(), - cstr!("invalid utf-32"), - )?)), + None => Err(PyErr::from_instance( + exceptions::UnicodeDecodeError::new_err( + py, + cstr!("utf-32"), + utf32_bytes(data), + 0..4 * data.len(), + cstr!("invalid utf-32"), + )?, + )), } } } diff --git a/src/objects/stringutils.rs b/src/types/stringutils.rs similarity index 98% rename from src/objects/stringutils.rs rename to src/types/stringutils.rs index e248ecad..cc2c03fa 100644 --- a/src/objects/stringutils.rs +++ b/src/types/stringutils.rs @@ -2,9 +2,9 @@ use conversion::{IntoPyObject, PyTryFrom, ToPyObject}; use err::PyResult; use instance::PyObjectWithToken; use object::PyObject; -use objects::{PyObjectRef, PyString}; use python::Python; use std::borrow::Cow; +use types::{PyObjectRef, PyString}; use FromPyObject; /// Converts Rust `str` to Python object. diff --git a/src/objects/tuple.rs b/src/types/tuple.rs similarity index 98% rename from src/objects/tuple.rs rename to src/types/tuple.rs index 1ab9ec9f..aa4ce6d6 100644 --- a/src/objects/tuple.rs +++ b/src/types/tuple.rs @@ -1,14 +1,14 @@ // Copyright (c) 2017-present PyO3 Project and Contributors -use super::exc; +use super::exceptions; use conversion::{FromPyObject, IntoPyObject, IntoPyTuple, PyTryFrom, ToPyObject}; use err::{PyErr, PyResult}; use ffi::{self, Py_ssize_t}; use instance::{AsPyRef, Py, PyObjectWithToken}; use object::PyObject; -use objects::PyObjectRef; use python::{IntoPyPointer, Python, ToPyPointer}; use std::slice; +use types::PyObjectRef; /// Represents a Python `tuple` object. #[repr(transparent)] @@ -159,7 +159,7 @@ fn wrong_tuple_length(t: &PyTuple, expected_length: usize) -> PyErr { expected_length, t.len() ); - exc::ValueError::py_err(msg) + exceptions::ValueError::py_err(msg) } macro_rules! tuple_conversion ({$length:expr,$(($refN:ident, $n:tt, $T:ident)),+} => { @@ -268,10 +268,10 @@ mod test { use conversion::{PyTryFrom, ToPyObject}; use instance::AsPyRef; use objectprotocol::ObjectProtocol; - use objects::PyObjectRef; use python::Python; use std::collections::HashSet; - use PyTuple; + use types::PyObjectRef; + use types::PyTuple; #[test] fn test_new() { diff --git a/src/objects/typeobject.rs b/src/types/typeobject.rs similarity index 100% rename from src/objects/typeobject.rs rename to src/types/typeobject.rs diff --git a/tests/common.rs b/tests/common.rs index 20edc1ad..cb274148 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -24,7 +24,7 @@ pub fn indoc(commands: &str) -> String { #[macro_export] macro_rules! py_run { ($py:expr, $val:expr, $code:expr) => {{ - let d = PyDict::new($py); + let d = pyo3::types::PyDict::new($py); d.set_item(stringify!($val), &$val).unwrap(); $py.run(&common::indoc($code), None, Some(d)) .map_err(|e| { @@ -48,11 +48,11 @@ macro_rules! py_assert { #[macro_export] macro_rules! py_expect_exception { ($py:expr, $val:ident, $code:expr, $err:ident) => {{ - let d = PyDict::new($py); + let d = pyo3::types::PyDict::new($py); d.set_item(stringify!($val), &$val).unwrap(); let res = $py.run($code, None, Some(d)); let err = res.unwrap_err(); - if !err.matches($py, $py.get_type::()) { + if !err.matches($py, $py.get_type::()) { panic!(format!("Expected {} but got {:?}", stringify!($err), err)) } }}; diff --git a/tests/test_arithmetics.rs b/tests/test_arithmetics.rs index 9a60ea1a..c59f5f7c 100644 --- a/tests/test_arithmetics.rs +++ b/tests/test_arithmetics.rs @@ -2,7 +2,10 @@ extern crate pyo3; +use pyo3::class::*; use pyo3::prelude::*; +use pyo3::types::PyObjectRef; +use pyo3::PyObjectWithToken; #[macro_use] mod common; diff --git a/tests/test_buffer_protocol.rs b/tests/test_buffer_protocol.rs index d1f015b6..54bba395 100644 --- a/tests/test_buffer_protocol.rs +++ b/tests/test_buffer_protocol.rs @@ -5,9 +5,11 @@ extern crate pyo3; use std::os::raw::{c_int, c_void}; use std::ptr; -use pyo3::exc::BufferError; +use pyo3::class::PyBufferProtocol; +use pyo3::exceptions::BufferError; use pyo3::ffi; use pyo3::prelude::*; +use pyo3::types::PyDict; #[pyclass] struct TestClass { diff --git a/tests/test_class_new.rs b/tests/test_class_new.rs index 981d6692..6386b293 100644 --- a/tests/test_class_new.rs +++ b/tests/test_class_new.rs @@ -3,6 +3,7 @@ extern crate pyo3; use pyo3::prelude::*; +use pyo3::PyRawObject; #[pyclass] struct EmptyClassWithNew {} diff --git a/tests/test_datetime.rs b/tests/test_datetime.rs index 61eb7b5f..c4a10cca 100644 --- a/tests/test_datetime.rs +++ b/tests/test_datetime.rs @@ -2,10 +2,10 @@ extern crate pyo3; -use std::iter; - use pyo3::ffi::*; use pyo3::prelude::*; +use pyo3::types::{PyDate, PyDateTime, PyDict, PyObjectRef, PyTime}; +use std::iter; fn _get_subclasses<'p>( py: &'p Python, @@ -40,6 +40,7 @@ fn _get_subclasses<'p>( macro_rules! assert_check_exact { ($check_func:ident, $obj: expr) => { unsafe { + use pyo3::ToPyPointer; assert!($check_func(($obj).as_ptr()) != 0); assert!(concat_idents!($check_func, Exact)(($obj).as_ptr()) != 0); } @@ -49,6 +50,7 @@ macro_rules! assert_check_exact { macro_rules! assert_check_only { ($check_func:ident, $obj: expr) => { unsafe { + use pyo3::ToPyPointer; assert!($check_func(($obj).as_ptr()) != 0); assert!(concat_idents!($check_func, Exact)(($obj).as_ptr()) == 0); } diff --git a/tests/test_dunder.rs b/tests/test_dunder.rs index 9591e35c..01b47a76 100644 --- a/tests/test_dunder.rs +++ b/tests/test_dunder.rs @@ -2,8 +2,15 @@ extern crate pyo3; +use pyo3::class::{ + PyContextProtocol, PyIterProtocol, PyMappingProtocol, PyObjectProtocol, PySequenceProtocol, +}; +use pyo3::exceptions::{IndexError, ValueError}; use pyo3::ffi; use pyo3::prelude::*; +use pyo3::python::ToPyPointer; +use pyo3::types::{PyBytes, PyDict, PyObjectRef, PySlice, PyString, PyType}; +use pyo3::PyObjectWithToken; use std::{isize, iter}; #[macro_use] @@ -171,7 +178,7 @@ impl PySequenceProtocol for Sequence { fn __getitem__(&self, key: isize) -> PyResult { if key == 5 { - return Err(PyErr::new::(NoArgs)); + return Err(PyErr::new::(NoArgs)); } Ok(key) } @@ -369,7 +376,7 @@ impl<'p> PyContextProtocol<'p> for ContextManager { _traceback: Option<&'p PyObjectRef>, ) -> PyResult { self.exit_called = true; - if ty == Some(self.py().get_type::()) { + if ty == Some(self.py().get_type::()) { Ok(true) } else { Ok(false) @@ -435,7 +442,7 @@ impl<'p> PyMappingProtocol<'p> for Test { return Ok("int".into_object(self.py())); } } - Err(PyErr::new::("error")) + Err(PyErr::new::("error")) } } diff --git a/tests/test_gc.rs b/tests/test_gc.rs index dd656070..5ff88668 100644 --- a/tests/test_gc.rs +++ b/tests/test_gc.rs @@ -2,8 +2,16 @@ extern crate pyo3; +use pyo3::class::PyGCProtocol; +use pyo3::class::PyTraverseError; +use pyo3::class::PyVisit; use pyo3::ffi; use pyo3::prelude::*; +use pyo3::python::ToPyPointer; +use pyo3::types::PyObjectRef; +use pyo3::types::PyTuple; +use pyo3::PyObjectWithToken; +use pyo3::PyRawObject; use std::cell::RefCell; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; diff --git a/tests/test_inheritance.rs b/tests/test_inheritance.rs index 89dec4eb..f813fabe 100644 --- a/tests/test_inheritance.rs +++ b/tests/test_inheritance.rs @@ -3,6 +3,7 @@ extern crate pyo3; use pyo3::prelude::*; +use pyo3::types::PyDict; use std::isize; #[macro_use] diff --git a/tests/test_methods.rs b/tests/test_methods.rs index af57ca0f..a8ccaa93 100644 --- a/tests/test_methods.rs +++ b/tests/test_methods.rs @@ -3,6 +3,9 @@ extern crate pyo3; use pyo3::prelude::*; +use pyo3::types::{PyDict, PyString, PyTuple, PyType}; +use pyo3::PyObjectWithToken; +use pyo3::PyRawObject; #[macro_use] mod common; diff --git a/tests/test_module.rs b/tests/test_module.rs index 292a6a1d..b3a94d7b 100644 --- a/tests/test_module.rs +++ b/tests/test_module.rs @@ -4,6 +4,7 @@ extern crate pyo3; use pyo3::prelude::*; +use pyo3::types::PyDict; #[macro_use] mod common; diff --git a/tests/test_various.rs b/tests/test_various.rs index c1a1c058..b599da2d 100644 --- a/tests/test_various.rs +++ b/tests/test_various.rs @@ -4,6 +4,7 @@ extern crate pyo3; use pyo3::prelude::*; +use pyo3::types::PyDict; use std::isize; #[macro_use]