Cleanup
This commit is contained in:
parent
7ebbbe41db
commit
b12b65cfae
|
@ -1,12 +1,8 @@
|
|||
sudo: required
|
||||
dist: trusty
|
||||
language: python
|
||||
|
||||
cache:
|
||||
pip: true
|
||||
directories:
|
||||
- $HOME/.cargo
|
||||
- $TRAVIS_BUILD_DIR/target
|
||||
cargo: true
|
||||
|
||||
matrix:
|
||||
include:
|
||||
|
|
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file.
|
|||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Changed
|
||||
|
||||
* PyTryFrom's error is always to `PyDowncastError`
|
||||
|
||||
### Removed
|
||||
|
||||
* The pyobject_downcast macro
|
||||
|
||||
## [0.4.0] - 2018-07-30
|
||||
|
||||
### Removed
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# PyO3
|
||||
|
||||
[![Build Status](https://travis-ci.org/PyO3/pyo3.svg?branch=master)](https://travis-ci.org/PyO3/pyo3)
|
||||
[![Build Status](https://ci.appveyor.com/api/projects/status/github/fafhrd91/pyo3?branch=master&svg=true)](https://ci.appveyor.com/project/fafhrd91/pyo3)
|
||||
[![Build Status](https://ci.appveyor.com/api/projects/status/github/PyO3/pyo3?branch=master&svg=true)](https://ci.appveyor.com/project/fafhrd91/pyo3)
|
||||
[![codecov](https://codecov.io/gh/PyO3/pyo3/branch/master/graph/badge.svg)](https://codecov.io/gh/PyO3/pyo3)
|
||||
[![crates.io](http://meritbadge.herokuapp.com/pyo3)](https://crates.io/crates/pyo3)
|
||||
[![Join the dev chat](https://img.shields.io/gitter/room/nwjs/nw.js.svg)](https://gitter.im/PyO3/Lobby)
|
||||
|
@ -64,7 +64,7 @@ fn rust_py(py: Python, m: &PyModule) -> PyResult<()> {
|
|||
}
|
||||
```
|
||||
|
||||
On windows and linux, you can build normally with `cargo build --release`. On Mac Os, you need to set additional linker arguments. One option is to compile with `cargo rustc --release -- -C link-arg=-undefined -C link-arg=dynamic_lookup`, the other is to create a `.cargo/config` with the following content:
|
||||
On windows and linux, you can build normally with `cargo build --release`. On Mac Os, you need to set additional linker arguments. One option is to compile with `cargo rustc --release -- -C link-arg=-undefined -C link-arg=dynamic_lookup`, the other is to create a `.cargo/config` with the following content:
|
||||
|
||||
```toml
|
||||
[target.x86_64-apple-darwin]
|
||||
|
@ -117,6 +117,7 @@ fn main() -> PyResult<()> {
|
|||
* [hyperjson](https://github.com/mre/hyperjson) _A hyper-fast Python module for reading/writing JSON data using Rust's serde-json_
|
||||
* [rust-numpy](https://github.com/rust-numpy/rust-numpy) _Rust binding of NumPy C-API_
|
||||
* [pyo3-built](https://github.com/PyO3/pyo3-built) _Simple macro to expose metadata obtained with the [`built`](https://crates.io/crates/built) crate as a [`PyDict`](https://pyo3.github.io/pyo3/pyo3/struct.PyDict.html)_
|
||||
* [point-process](https://github.com/ManifoldFR/point-process-rust/tree/master/pylib) _High level API for pointprocesses as a Python library_
|
||||
|
||||
## License
|
||||
|
||||
|
|
16
build.rs
16
build.rs
|
@ -200,8 +200,16 @@ fn get_rustc_link_lib(
|
|||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn get_macos_linkmodel() -> Result<String, String> {
|
||||
let script = "import sysconfig;\
|
||||
print('framework' if sysconfig.get_config_var('PYTHONFRAMEWORK') else ('shared' if sysconfig.get_config_var('Py_ENABLE_SHARED') else 'static'));";
|
||||
let script = r#"
|
||||
import sysconfig
|
||||
|
||||
if sysconfig.get_config_var("PYTHONFRAMEWORK"):
|
||||
print("framework")
|
||||
elif sysconfig.get_config_var("Py_ENABLE_SHARED"):
|
||||
print("shared")
|
||||
else:
|
||||
print("static")
|
||||
"#;
|
||||
let out = run_python_script("python", script).unwrap();
|
||||
Ok(out.trim_right().to_owned())
|
||||
}
|
||||
|
@ -520,6 +528,10 @@ fn main() {
|
|||
}
|
||||
);
|
||||
|
||||
if env::var_os("TARGET") == Some("x86_64-apple-darwin".into()) {
|
||||
// TODO: Find out how we can set -undefined dynamic_lookup here (if this is possible)
|
||||
}
|
||||
|
||||
let env_vars = ["LD_LIBRARY_PATH", "PATH", "PYTHON_SYS_EXECUTABLE"];
|
||||
|
||||
for var in env_vars.iter() {
|
||||
|
|
|
@ -1,23 +1,86 @@
|
|||
# PyO3
|
||||
|
||||
[Rust](http://www.rust-lang.org/) bindings for the [Python](https://www.python.org/) interpreter. This includes running and interacting with python code from a rust binaries as well as writing native python modules.
|
||||
[Rust](http://www.rust-lang.org/) bindings for [Python](https://www.python.org/). This includes running and interacting with python code from a rust binaries as well as writing native python modules.
|
||||
|
||||
## Usage
|
||||
|
||||
Pyo3 supports python 2.7 as well as python 3.5 and up. The minimum required rust version is 1.27.0-nightly 2018-05-01.
|
||||
Pyo3 supports python 2.7 as well as python 3.5 and up. The minimum required rust version is 1.29.0-nightly 2018-07-16.
|
||||
|
||||
### From a rust binary
|
||||
You can either write a native python module in rust or use python from a rust binary.
|
||||
|
||||
To use `pyo3`, add this to your `Cargo.toml`:
|
||||
### Using rust from python
|
||||
|
||||
Pyo3 can be used to generate a native python module.
|
||||
|
||||
**`Cargo.toml`:**
|
||||
|
||||
```toml
|
||||
[package]
|
||||
name = "rust-py"
|
||||
version = "0.1.0"
|
||||
|
||||
[lib]
|
||||
name = "rust_py"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies.pyo3]
|
||||
version = "0.3"
|
||||
features = ["extension-module"]
|
||||
```
|
||||
|
||||
**`src/lib.rs`**
|
||||
|
||||
```rust
|
||||
#![feature(use_extern_macros, specialization)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate pyo3;
|
||||
|
||||
use pyo3::prelude::*;
|
||||
|
||||
#[pyfunction]
|
||||
/// Formats the sum of two numbers as string
|
||||
fn sum_as_string(a: usize, b: usize) -> PyResult<String> {
|
||||
Ok((a + b).to_string())
|
||||
}
|
||||
|
||||
/// This module is a python moudle implemented in Rust.
|
||||
#[pymodinit]
|
||||
fn rust_py(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
m.add_function(wrap_function!(sum_as_string))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
On windows and linux, you can build normally with `cargo build --release`. On Mac Os, you need to set additional linker arguments. One option is to compile with `cargo rustc --release -- -C link-arg=-undefined -C link-arg=dynamic_lookup`, the other is to create a `.cargo/config` with the following content:
|
||||
|
||||
```toml
|
||||
[target.x86_64-apple-darwin]
|
||||
rustflags = [
|
||||
"-C", "link-arg=-undefined",
|
||||
"-C", "link-arg=dynamic_lookup",
|
||||
]
|
||||
```
|
||||
|
||||
Also on macOS, you will need to rename the output from \*.dylib to \*.so. On Windows, you will need to rename the output from \*.dll to \*.pyd.
|
||||
|
||||
[`setuptools-rust`](https://github.com/PyO3/setuptools-rust) can be used to generate a python package and includes the commands above by default. See [examples/word-count](examples/https://github.com/PyO3/pyo3/tree/master/examples/word-count) and the associated setup.py.
|
||||
|
||||
### Using python from rust
|
||||
|
||||
Add `pyo3` this to your `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
pyo3 = "0.2"
|
||||
pyo3 = "0.3"
|
||||
```
|
||||
|
||||
Example program displaying the value of `sys.version`:
|
||||
|
||||
```rust
|
||||
#![feature(use_extern_macros, specialization)]
|
||||
|
||||
extern crate pyo3;
|
||||
|
||||
use pyo3::prelude::*;
|
||||
|
@ -37,57 +100,10 @@ fn main() -> PyResult<()> {
|
|||
}
|
||||
```
|
||||
|
||||
### As native module
|
||||
## Examples and tooling
|
||||
|
||||
Pyo3 can be used to write native python module. The example will generate a python-compatible library.
|
||||
|
||||
For MacOS, "-C link-arg=-undefined -C link-arg=dynamic_lookup" is required to build the library.
|
||||
`setuptools-rust` includes this by default. See [examples/word-count](examples/word-count) and the associated setup.py. Also on macOS, you will need to rename the output from \*.dylib to \*.so. On Windows, you will need to rename the output from \*.dll to \*.pyd.
|
||||
|
||||
**`Cargo.toml`:**
|
||||
|
||||
```toml
|
||||
[lib]
|
||||
name = "rust2py"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies.pyo3]
|
||||
version = "0.2"
|
||||
features = ["extension-module"]
|
||||
```
|
||||
|
||||
**`src/lib.rs`**
|
||||
|
||||
```rust
|
||||
#![feature(use_extern_macros, specialization)]
|
||||
|
||||
extern crate pyo3;
|
||||
use pyo3::prelude::*;
|
||||
|
||||
|
||||
|
||||
// Add bindings to the generated python module
|
||||
// N.B: names: "librust2py" must be the name of the `.so` or `.pyd` file
|
||||
/// This module is implemented in Rust.
|
||||
#[pymodinit]
|
||||
fn rust2py(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
|
||||
#[pyfn(m, "sum_as_string")]
|
||||
// ``#[pyfn()]` converts the arguments from Python objects to Rust values
|
||||
// and the Rust return value back into a Python object.
|
||||
fn sum_as_string_py(a:i64, b:i64) -> PyResult<String> {
|
||||
let out = sum_as_string(a, b);
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// The logic can be implemented as a normal rust function
|
||||
fn sum_as_string(a:i64, b:i64) -> String {
|
||||
format!("{}", a + b).to_string()
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
For `setup.py` integration, see [setuptools-rust](https://github.com/PyO3/setuptools-rust)
|
||||
* [examples/word-count](https://github.com/PyO3/pyo3/tree/master/examples/word-count) _Counting the occurences of a word in a text file_
|
||||
* [hyperjson](https://github.com/mre/hyperjson) _A hyper-fast Python module for reading/writing JSON data using Rust's serde-json_
|
||||
* [rust-numpy](https://github.com/rust-numpy/rust-numpy) _Rust binding of NumPy C-API_
|
||||
* [pyo3-built](https://github.com/PyO3/pyo3-built) _Simple macro to expose metadata obtained with the [`built`](https://crates.io/crates/built) crate as a [`PyDict`](https://pyo3.github.io/pyo3/pyo3/struct.PyDict.html)_
|
||||
* [point-process](https://github.com/ManifoldFR/point-process-rust/tree/master/pylib) _High level API for pointprocesses as a Python library_
|
||||
|
|
|
@ -136,14 +136,14 @@ fn impl_class(
|
|||
}
|
||||
impl std::fmt::Debug for #cls {
|
||||
fn fmt(&self, f : &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||
use pyo3::ObjectProtocol;
|
||||
use ::pyo3::ObjectProtocol;
|
||||
let s = try!(self.repr().map_err(|_| std::fmt::Error));
|
||||
f.write_str(&s.to_string_lossy())
|
||||
}
|
||||
}
|
||||
impl std::fmt::Display for #cls {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||
use pyo3::ObjectProtocol;
|
||||
use ::pyo3::ObjectProtocol;
|
||||
let s = try!(self.str().map_err(|_| std::fmt::Error));
|
||||
f.write_str(&s.to_string_lossy())
|
||||
}
|
||||
|
|
|
@ -318,7 +318,7 @@ macro_rules! py_func_set {
|
|||
slf: *mut $crate::ffi::PyObject,
|
||||
name: *mut $crate::ffi::PyObject,
|
||||
value: *mut $crate::ffi::PyObject,
|
||||
) -> $crate::c_int
|
||||
) -> $crate::libc::c_int
|
||||
where
|
||||
T: for<'p> $trait<'p>,
|
||||
{
|
||||
|
@ -368,7 +368,7 @@ macro_rules! py_func_del {
|
|||
slf: *mut $crate::ffi::PyObject,
|
||||
name: *mut $crate::ffi::PyObject,
|
||||
value: *mut $crate::ffi::PyObject,
|
||||
) -> $crate::c_int
|
||||
) -> $crate::libc::c_int
|
||||
where
|
||||
T: for<'p> $trait<'p>,
|
||||
{
|
||||
|
@ -414,7 +414,7 @@ macro_rules! py_func_set_del {
|
|||
slf: *mut $crate::ffi::PyObject,
|
||||
name: *mut $crate::ffi::PyObject,
|
||||
value: *mut $crate::ffi::PyObject,
|
||||
) -> $crate::c_int
|
||||
) -> $crate::libc::c_int
|
||||
where
|
||||
T: for<'p> $trait<'p> + for<'p> $trait2<'p>,
|
||||
{
|
||||
|
|
|
@ -4,6 +4,7 @@ use std;
|
|||
use std::ffi::CString;
|
||||
|
||||
use ffi;
|
||||
use libc::c_int;
|
||||
|
||||
static NO_PY_METHODS: &'static [PyMethodDefType] = &[];
|
||||
|
||||
|
@ -42,7 +43,7 @@ pub enum PyMethodType {
|
|||
pub struct PyMethodDef {
|
||||
pub ml_name: &'static str,
|
||||
pub ml_meth: PyMethodType,
|
||||
pub ml_flags: ::c_int,
|
||||
pub ml_flags: c_int,
|
||||
pub ml_doc: &'static str,
|
||||
}
|
||||
|
||||
|
|
|
@ -155,18 +155,18 @@ where
|
|||
/// Extract reference to instance from `PyObject`
|
||||
impl<'a, T> FromPyObject<'a> for &'a T
|
||||
where
|
||||
T: PyTypeInfo,
|
||||
T: PyTryFrom,
|
||||
{
|
||||
#[inline]
|
||||
default fn extract(ob: &'a PyObjectRef) -> PyResult<&'a T> {
|
||||
Ok(<T as PyTryFrom>::try_from(ob)?)
|
||||
Ok(T::try_from(ob)?)
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract mutable reference to instance from `PyObject`
|
||||
impl<'a, T> FromPyObject<'a> for &'a mut T
|
||||
where
|
||||
T: PyTypeInfo,
|
||||
T: PyTryFrom,
|
||||
{
|
||||
#[inline]
|
||||
default fn extract(ob: &'a PyObjectRef) -> PyResult<&'a mut T> {
|
||||
|
@ -212,20 +212,17 @@ pub trait PyTryInto<T>: Sized {
|
|||
/// Trait implemented by Python object types that allow a checked downcast.
|
||||
/// This trait is similar to `std::convert::TryFrom`
|
||||
pub trait PyTryFrom: Sized {
|
||||
/// The type returned in the event of a conversion error.
|
||||
type Error;
|
||||
|
||||
/// Cast from a concrete Python object type to PyObject.
|
||||
fn try_from(value: &PyObjectRef) -> Result<&Self, Self::Error>;
|
||||
fn try_from(value: &PyObjectRef) -> Result<&Self, PyDowncastError>;
|
||||
|
||||
/// Cast from a concrete Python object type to PyObject. With exact type check.
|
||||
fn try_from_exact(value: &PyObjectRef) -> Result<&Self, Self::Error>;
|
||||
fn try_from_exact(value: &PyObjectRef) -> Result<&Self, PyDowncastError>;
|
||||
|
||||
/// Cast from a concrete Python object type to PyObject.
|
||||
fn try_from_mut(value: &PyObjectRef) -> Result<&mut Self, Self::Error>;
|
||||
fn try_from_mut(value: &PyObjectRef) -> Result<&mut Self, PyDowncastError>;
|
||||
|
||||
/// Cast from a concrete Python object type to PyObject. With exact type check.
|
||||
fn try_from_mut_exact(value: &PyObjectRef) -> Result<&mut Self, Self::Error>;
|
||||
fn try_from_mut_exact(value: &PyObjectRef) -> Result<&mut Self, PyDowncastError>;
|
||||
}
|
||||
|
||||
// TryFrom implies TryInto
|
||||
|
@ -233,18 +230,18 @@ impl<U> PyTryInto<U> for PyObjectRef
|
|||
where
|
||||
U: PyTryFrom,
|
||||
{
|
||||
type Error = U::Error;
|
||||
type Error = PyDowncastError;
|
||||
|
||||
fn try_into(&self) -> Result<&U, U::Error> {
|
||||
fn try_into(&self) -> Result<&U, PyDowncastError> {
|
||||
U::try_from(self)
|
||||
}
|
||||
fn try_into_exact(&self) -> Result<&U, U::Error> {
|
||||
fn try_into_exact(&self) -> Result<&U, PyDowncastError> {
|
||||
U::try_from_exact(self)
|
||||
}
|
||||
fn try_into_mut(&self) -> Result<&mut U, U::Error> {
|
||||
fn try_into_mut(&self) -> Result<&mut U, PyDowncastError> {
|
||||
U::try_from_mut(self)
|
||||
}
|
||||
fn try_into_mut_exact(&self) -> Result<&mut U, U::Error> {
|
||||
fn try_into_mut_exact(&self) -> Result<&mut U, PyDowncastError> {
|
||||
U::try_from_mut_exact(self)
|
||||
}
|
||||
}
|
||||
|
@ -253,9 +250,7 @@ impl<T> PyTryFrom for T
|
|||
where
|
||||
T: PyTypeInfo,
|
||||
{
|
||||
type Error = PyDowncastError;
|
||||
|
||||
fn try_from(value: &PyObjectRef) -> Result<&T, Self::Error> {
|
||||
fn try_from(value: &PyObjectRef) -> Result<&T, PyDowncastError> {
|
||||
unsafe {
|
||||
if T::is_instance(value.as_ptr()) {
|
||||
let ptr = if T::OFFSET == 0 {
|
||||
|
@ -270,7 +265,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn try_from_exact(value: &PyObjectRef) -> Result<&T, Self::Error> {
|
||||
fn try_from_exact(value: &PyObjectRef) -> Result<&T, PyDowncastError> {
|
||||
unsafe {
|
||||
if T::is_exact_instance(value.as_ptr()) {
|
||||
let ptr = if T::OFFSET == 0 {
|
||||
|
@ -285,7 +280,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn try_from_mut(value: &PyObjectRef) -> Result<&mut T, Self::Error> {
|
||||
fn try_from_mut(value: &PyObjectRef) -> Result<&mut T, PyDowncastError> {
|
||||
unsafe {
|
||||
if T::is_instance(value.as_ptr()) {
|
||||
let ptr = if T::OFFSET == 0 {
|
||||
|
@ -300,7 +295,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn try_from_mut_exact(value: &PyObjectRef) -> Result<&mut T, Self::Error> {
|
||||
fn try_from_mut_exact(value: &PyObjectRef) -> Result<&mut T, PyDowncastError> {
|
||||
unsafe {
|
||||
if T::is_exact_instance(value.as_ptr()) {
|
||||
let ptr = if T::OFFSET == 0 {
|
||||
|
|
|
@ -6,6 +6,7 @@ use std;
|
|||
use err::PyResult;
|
||||
use ffi;
|
||||
use python::Python;
|
||||
use std::os::raw::c_void;
|
||||
use typeob::{PyObjectAlloc, PyTypeInfo};
|
||||
|
||||
/// Implementing this trait for custom class adds free allocation list to class.
|
||||
|
@ -92,13 +93,13 @@ where
|
|||
|
||||
if let Some(obj) = <T as PyObjectWithFreeList>::get_free_list().insert(obj) {
|
||||
match (*T::type_object()).tp_free {
|
||||
Some(free) => free(obj as *mut ::c_void),
|
||||
Some(free) => free(obj as *mut c_void),
|
||||
None => {
|
||||
let ty = ffi::Py_TYPE(obj);
|
||||
if ffi::PyType_IS_GC(ty) != 0 {
|
||||
ffi::PyObject_GC_Del(obj as *mut ::c_void);
|
||||
ffi::PyObject_GC_Del(obj as *mut c_void);
|
||||
} else {
|
||||
ffi::PyObject_Free(obj as *mut ::c_void);
|
||||
ffi::PyObject_Free(obj as *mut c_void);
|
||||
}
|
||||
|
||||
// For heap types, PyType_GenericAlloc calls INCREF on the type objects,
|
||||
|
@ -117,13 +118,13 @@ where
|
|||
|
||||
if let Some(obj) = <T as PyObjectWithFreeList>::get_free_list().insert(obj) {
|
||||
match (*T::type_object()).tp_free {
|
||||
Some(free) => free(obj as *mut ::c_void),
|
||||
Some(free) => free(obj as *mut c_void),
|
||||
None => {
|
||||
let ty = ffi::Py_TYPE(obj);
|
||||
if ffi::PyType_IS_GC(ty) != 0 {
|
||||
ffi::PyObject_GC_Del(obj as *mut ::c_void);
|
||||
ffi::PyObject_GC_Del(obj as *mut c_void);
|
||||
} else {
|
||||
ffi::PyObject_Free(obj as *mut ::c_void);
|
||||
ffi::PyObject_Free(obj as *mut c_void);
|
||||
}
|
||||
|
||||
// For heap types, PyType_GenericAlloc calls INCREF on the type objects,
|
||||
|
|
|
@ -120,7 +120,9 @@
|
|||
//!
|
||||
//! [`setuptools-rust`](https://github.com/PyO3/setuptools-rust) can be used to generate a python package and includes the commands above by default. See [examples/word-count](examples/word-count) and the associated setup.py.
|
||||
|
||||
extern crate libc;
|
||||
// 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
|
||||
|
@ -214,7 +216,3 @@ pub mod prelude;
|
|||
pub mod python;
|
||||
mod pythonrun;
|
||||
pub mod typeob;
|
||||
|
||||
// re-export for simplicity
|
||||
#[doc(hidden)]
|
||||
pub use std::os::raw::*;
|
||||
|
|
|
@ -14,6 +14,7 @@ use pythonrun;
|
|||
|
||||
/// Safe wrapper around unsafe `*mut ffi::PyObject` pointer.
|
||||
#[derive(Debug)]
|
||||
#[repr(transparent)]
|
||||
pub struct PyObject(*mut ffi::PyObject);
|
||||
|
||||
// `PyObject` is thread-safe, any python related operations require a Python<'p> token.
|
||||
|
@ -136,9 +137,9 @@ impl PyObject {
|
|||
}
|
||||
|
||||
/// Casts the PyObject to a concrete Python object type.
|
||||
pub fn cast_as<D>(&self, py: Python) -> Result<&D, <D as PyTryFrom>::Error>
|
||||
pub fn cast_as<D>(&self, py: Python) -> Result<&D, PyDowncastError>
|
||||
where
|
||||
D: PyTryFrom<Error = PyDowncastError>,
|
||||
D: PyTryFrom,
|
||||
{
|
||||
D::try_from(self.as_ref(py))
|
||||
}
|
||||
|
|
|
@ -177,9 +177,9 @@ pub trait ObjectProtocol {
|
|||
Self: PyTypeInfo;
|
||||
|
||||
/// Casts the PyObject to a concrete Python object type.
|
||||
fn cast_as<'a, D>(&'a self) -> Result<&'a D, <D as PyTryFrom>::Error>
|
||||
fn cast_as<'a, D>(&'a self) -> Result<&'a D, PyDowncastError>
|
||||
where
|
||||
D: PyTryFrom<Error = PyDowncastError>,
|
||||
D: PyTryFrom,
|
||||
&'a PyObjectRef: std::convert::From<&'a Self>;
|
||||
|
||||
/// Extracts some type from the Python object.
|
||||
|
@ -500,9 +500,9 @@ where
|
|||
unsafe { self.py().mut_from_borrowed_ptr(self.as_ptr()) }
|
||||
}
|
||||
|
||||
fn cast_as<'a, D>(&'a self) -> Result<&'a D, <D as PyTryFrom>::Error>
|
||||
fn cast_as<'a, D>(&'a self) -> Result<&'a D, PyDowncastError>
|
||||
where
|
||||
D: PyTryFrom<Error = PyDowncastError>,
|
||||
D: PyTryFrom,
|
||||
&'a PyObjectRef: std::convert::From<&'a Self>,
|
||||
{
|
||||
D::try_from(self.into())
|
||||
|
|
|
@ -93,7 +93,6 @@ macro_rules! pyobject_native_type(
|
|||
($name: ty, $typeobject: expr, $checkfunction: path $(,$type_param: ident)*) => {
|
||||
pyobject_native_type_named!($name $(,$type_param)*);
|
||||
pyobject_native_type_convert!($name, $typeobject, $checkfunction $(,$type_param)*);
|
||||
pyobject_downcast!($name, $checkfunction $(,$type_param)*);
|
||||
|
||||
impl<'a, $($type_param,)*> ::std::convert::From<&'a $name> for &'a $crate::PyObjectRef {
|
||||
fn from(ob: &'a $name) -> Self {
|
||||
|
@ -210,7 +209,6 @@ use python::ToPyPointer;
|
|||
pub struct PyObjectRef(::PyObject);
|
||||
pyobject_native_type_named!(PyObjectRef);
|
||||
pyobject_native_type_convert!(PyObjectRef, ffi::PyBaseObject_Type, ffi::PyObject_Check);
|
||||
pyobject_downcast!(PyObjectRef, ffi::PyObject_Check);
|
||||
|
||||
mod boolobject;
|
||||
mod bytearray;
|
||||
|
|
|
@ -16,7 +16,6 @@ use python::ToPyPointer;
|
|||
#[repr(transparent)]
|
||||
pub struct PySequence(PyObject);
|
||||
pyobject_native_type_named!(PySequence);
|
||||
pyobject_downcast!(PySequence, ffi::PySequence_Check);
|
||||
|
||||
impl PySequence {
|
||||
/// Returns the number of objects in sequence. This is equivalent to Python `len()`.
|
||||
|
@ -279,9 +278,7 @@ where
|
|||
}
|
||||
|
||||
impl PyTryFrom for PySequence {
|
||||
type Error = PyDowncastError;
|
||||
|
||||
fn try_from(value: &PyObjectRef) -> Result<&PySequence, Self::Error> {
|
||||
fn try_from(value: &PyObjectRef) -> Result<&PySequence, PyDowncastError> {
|
||||
unsafe {
|
||||
if ffi::PySequence_Check(value.as_ptr()) != 0 {
|
||||
let ptr = value as *const _ as *mut u8 as *mut PySequence;
|
||||
|
@ -292,11 +289,11 @@ impl PyTryFrom for PySequence {
|
|||
}
|
||||
}
|
||||
|
||||
fn try_from_exact(value: &PyObjectRef) -> Result<&PySequence, Self::Error> {
|
||||
fn try_from_exact(value: &PyObjectRef) -> Result<&PySequence, PyDowncastError> {
|
||||
<PySequence as PyTryFrom>::try_from(value)
|
||||
}
|
||||
|
||||
fn try_from_mut(value: &PyObjectRef) -> Result<&mut PySequence, Self::Error> {
|
||||
fn try_from_mut(value: &PyObjectRef) -> Result<&mut PySequence, PyDowncastError> {
|
||||
unsafe {
|
||||
if ffi::PySequence_Check(value.as_ptr()) != 0 {
|
||||
let ptr = value as *const _ as *mut u8 as *mut PySequence;
|
||||
|
@ -307,7 +304,7 @@ impl PyTryFrom for PySequence {
|
|||
}
|
||||
}
|
||||
|
||||
fn try_from_mut_exact(value: &PyObjectRef) -> Result<&mut PySequence, Self::Error> {
|
||||
fn try_from_mut_exact(value: &PyObjectRef) -> Result<&mut PySequence, PyDowncastError> {
|
||||
PySequence::try_from_mut(value)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ use err::{PyErr, PyResult};
|
|||
use instance::{Py, PyObjectWithToken, PyToken};
|
||||
use objects::PyType;
|
||||
use python::{IntoPyPointer, Python};
|
||||
use std::os::raw::c_void;
|
||||
use {class, ffi, pythonrun};
|
||||
|
||||
/// Python type information.
|
||||
|
@ -65,10 +66,7 @@ pub const PY_TYPE_FLAG_BASETYPE: usize = 1 << 2;
|
|||
/// The instances of this type have a dictionary containing instance variables
|
||||
pub const PY_TYPE_FLAG_DICT: usize = 1 << 3;
|
||||
|
||||
impl<'a, T: ?Sized> PyTypeInfo for &'a T
|
||||
where
|
||||
T: PyTypeInfo,
|
||||
{
|
||||
impl<'a, T: PyTypeInfo + ?Sized> PyTypeInfo for &'a T {
|
||||
type Type = T::Type;
|
||||
type BaseType = T::BaseType;
|
||||
const NAME: &'static str = T::NAME;
|
||||
|
@ -262,13 +260,13 @@ where
|
|||
}
|
||||
|
||||
match (*T::type_object()).tp_free {
|
||||
Some(free) => free(obj as *mut ::c_void),
|
||||
Some(free) => free(obj as *mut c_void),
|
||||
None => {
|
||||
let ty = ffi::Py_TYPE(obj);
|
||||
if ffi::PyType_IS_GC(ty) != 0 {
|
||||
ffi::PyObject_GC_Del(obj as *mut ::c_void);
|
||||
ffi::PyObject_GC_Del(obj as *mut c_void);
|
||||
} else {
|
||||
ffi::PyObject_Free(obj as *mut ::c_void);
|
||||
ffi::PyObject_Free(obj as *mut c_void);
|
||||
}
|
||||
|
||||
// For heap types, PyType_GenericAlloc calls INCREF on the type objects,
|
||||
|
@ -285,13 +283,13 @@ where
|
|||
Self::drop(py, obj);
|
||||
|
||||
match (*T::type_object()).tp_free {
|
||||
Some(free) => free(obj as *mut ::c_void),
|
||||
Some(free) => free(obj as *mut c_void),
|
||||
None => {
|
||||
let ty = ffi::Py_TYPE(obj);
|
||||
if ffi::PyType_IS_GC(ty) != 0 {
|
||||
ffi::PyObject_GC_Del(obj as *mut ::c_void);
|
||||
ffi::PyObject_GC_Del(obj as *mut c_void);
|
||||
} else {
|
||||
ffi::PyObject_Free(obj as *mut ::c_void);
|
||||
ffi::PyObject_Free(obj as *mut c_void);
|
||||
}
|
||||
|
||||
// For heap types, PyType_GenericAlloc calls INCREF on the type objects,
|
||||
|
|
|
@ -90,13 +90,13 @@ impl<'p> PyObjectProtocol<'p> for StringMethods {
|
|||
Ok(format!("format({})", format_spec))
|
||||
}
|
||||
|
||||
fn __unicode__(&self) -> PyResult<PyObject> {
|
||||
Ok(PyString::new(self.py(), "unicode").into())
|
||||
}
|
||||
|
||||
fn __bytes__(&self) -> PyResult<PyObject> {
|
||||
Ok(PyBytes::new(self.py(), b"bytes").into())
|
||||
}
|
||||
|
||||
fn __unicode__(&self) -> PyResult<PyObject> {
|
||||
Ok(PyString::new(self.py(), "unicode").into())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(Py_3)]
|
||||
|
|
Loading…
Reference in New Issue