Cleanup
This commit is contained in:
parent
7ebbbe41db
commit
b12b65cfae
|
@ -1,12 +1,8 @@
|
||||||
sudo: required
|
|
||||||
dist: trusty
|
|
||||||
language: python
|
language: python
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
pip: true
|
pip: true
|
||||||
directories:
|
cargo: true
|
||||||
- $HOME/.cargo
|
|
||||||
- $TRAVIS_BUILD_DIR/target
|
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
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/)
|
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).
|
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
|
## [0.4.0] - 2018-07-30
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# PyO3
|
# PyO3
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/PyO3/pyo3.svg?branch=master)](https://travis-ci.org/PyO3/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)
|
[![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)
|
[![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)
|
[![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
|
```toml
|
||||||
[target.x86_64-apple-darwin]
|
[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_
|
* [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_
|
* [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)_
|
* [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
|
## License
|
||||||
|
|
||||||
|
|
16
build.rs
16
build.rs
|
@ -200,8 +200,16 @@ fn get_rustc_link_lib(
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
fn get_macos_linkmodel() -> Result<String, String> {
|
fn get_macos_linkmodel() -> Result<String, String> {
|
||||||
let script = "import sysconfig;\
|
let script = r#"
|
||||||
print('framework' if sysconfig.get_config_var('PYTHONFRAMEWORK') else ('shared' if sysconfig.get_config_var('Py_ENABLE_SHARED') else 'static'));";
|
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();
|
let out = run_python_script("python", script).unwrap();
|
||||||
Ok(out.trim_right().to_owned())
|
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"];
|
let env_vars = ["LD_LIBRARY_PATH", "PATH", "PYTHON_SYS_EXECUTABLE"];
|
||||||
|
|
||||||
for var in env_vars.iter() {
|
for var in env_vars.iter() {
|
||||||
|
|
|
@ -1,23 +1,86 @@
|
||||||
# PyO3
|
# 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
|
## 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
|
```toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
pyo3 = "0.2"
|
pyo3 = "0.3"
|
||||||
```
|
```
|
||||||
|
|
||||||
Example program displaying the value of `sys.version`:
|
Example program displaying the value of `sys.version`:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
#![feature(use_extern_macros, specialization)]
|
||||||
|
|
||||||
extern crate pyo3;
|
extern crate pyo3;
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
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.
|
* [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_
|
||||||
For MacOS, "-C link-arg=-undefined -C link-arg=dynamic_lookup" is required to build the library.
|
* [rust-numpy](https://github.com/rust-numpy/rust-numpy) _Rust binding of NumPy C-API_
|
||||||
`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.
|
* [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_
|
||||||
**`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)
|
|
||||||
|
|
|
@ -136,14 +136,14 @@ fn impl_class(
|
||||||
}
|
}
|
||||||
impl std::fmt::Debug for #cls {
|
impl std::fmt::Debug for #cls {
|
||||||
fn fmt(&self, f : &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
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));
|
let s = try!(self.repr().map_err(|_| std::fmt::Error));
|
||||||
f.write_str(&s.to_string_lossy())
|
f.write_str(&s.to_string_lossy())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl std::fmt::Display for #cls {
|
impl std::fmt::Display for #cls {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
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));
|
let s = try!(self.str().map_err(|_| std::fmt::Error));
|
||||||
f.write_str(&s.to_string_lossy())
|
f.write_str(&s.to_string_lossy())
|
||||||
}
|
}
|
||||||
|
|
|
@ -318,7 +318,7 @@ macro_rules! py_func_set {
|
||||||
slf: *mut $crate::ffi::PyObject,
|
slf: *mut $crate::ffi::PyObject,
|
||||||
name: *mut $crate::ffi::PyObject,
|
name: *mut $crate::ffi::PyObject,
|
||||||
value: *mut $crate::ffi::PyObject,
|
value: *mut $crate::ffi::PyObject,
|
||||||
) -> $crate::c_int
|
) -> $crate::libc::c_int
|
||||||
where
|
where
|
||||||
T: for<'p> $trait<'p>,
|
T: for<'p> $trait<'p>,
|
||||||
{
|
{
|
||||||
|
@ -368,7 +368,7 @@ macro_rules! py_func_del {
|
||||||
slf: *mut $crate::ffi::PyObject,
|
slf: *mut $crate::ffi::PyObject,
|
||||||
name: *mut $crate::ffi::PyObject,
|
name: *mut $crate::ffi::PyObject,
|
||||||
value: *mut $crate::ffi::PyObject,
|
value: *mut $crate::ffi::PyObject,
|
||||||
) -> $crate::c_int
|
) -> $crate::libc::c_int
|
||||||
where
|
where
|
||||||
T: for<'p> $trait<'p>,
|
T: for<'p> $trait<'p>,
|
||||||
{
|
{
|
||||||
|
@ -414,7 +414,7 @@ macro_rules! py_func_set_del {
|
||||||
slf: *mut $crate::ffi::PyObject,
|
slf: *mut $crate::ffi::PyObject,
|
||||||
name: *mut $crate::ffi::PyObject,
|
name: *mut $crate::ffi::PyObject,
|
||||||
value: *mut $crate::ffi::PyObject,
|
value: *mut $crate::ffi::PyObject,
|
||||||
) -> $crate::c_int
|
) -> $crate::libc::c_int
|
||||||
where
|
where
|
||||||
T: for<'p> $trait<'p> + for<'p> $trait2<'p>,
|
T: for<'p> $trait<'p> + for<'p> $trait2<'p>,
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,6 +4,7 @@ use std;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
|
|
||||||
use ffi;
|
use ffi;
|
||||||
|
use libc::c_int;
|
||||||
|
|
||||||
static NO_PY_METHODS: &'static [PyMethodDefType] = &[];
|
static NO_PY_METHODS: &'static [PyMethodDefType] = &[];
|
||||||
|
|
||||||
|
@ -42,7 +43,7 @@ pub enum PyMethodType {
|
||||||
pub struct PyMethodDef {
|
pub struct PyMethodDef {
|
||||||
pub ml_name: &'static str,
|
pub ml_name: &'static str,
|
||||||
pub ml_meth: PyMethodType,
|
pub ml_meth: PyMethodType,
|
||||||
pub ml_flags: ::c_int,
|
pub ml_flags: c_int,
|
||||||
pub ml_doc: &'static str,
|
pub ml_doc: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -155,18 +155,18 @@ where
|
||||||
/// Extract reference to instance from `PyObject`
|
/// Extract reference to instance from `PyObject`
|
||||||
impl<'a, T> FromPyObject<'a> for &'a T
|
impl<'a, T> FromPyObject<'a> for &'a T
|
||||||
where
|
where
|
||||||
T: PyTypeInfo,
|
T: PyTryFrom,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
default fn extract(ob: &'a PyObjectRef) -> PyResult<&'a T> {
|
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`
|
/// Extract mutable reference to instance from `PyObject`
|
||||||
impl<'a, T> FromPyObject<'a> for &'a mut T
|
impl<'a, T> FromPyObject<'a> for &'a mut T
|
||||||
where
|
where
|
||||||
T: PyTypeInfo,
|
T: PyTryFrom,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
default fn extract(ob: &'a PyObjectRef) -> PyResult<&'a mut T> {
|
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.
|
/// Trait implemented by Python object types that allow a checked downcast.
|
||||||
/// This trait is similar to `std::convert::TryFrom`
|
/// This trait is similar to `std::convert::TryFrom`
|
||||||
pub trait PyTryFrom: Sized {
|
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.
|
/// 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.
|
/// 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.
|
/// 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.
|
/// 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
|
// TryFrom implies TryInto
|
||||||
|
@ -233,18 +230,18 @@ impl<U> PyTryInto<U> for PyObjectRef
|
||||||
where
|
where
|
||||||
U: PyTryFrom,
|
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)
|
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)
|
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)
|
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)
|
U::try_from_mut_exact(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -253,9 +250,7 @@ impl<T> PyTryFrom for T
|
||||||
where
|
where
|
||||||
T: PyTypeInfo,
|
T: PyTypeInfo,
|
||||||
{
|
{
|
||||||
type Error = PyDowncastError;
|
fn try_from(value: &PyObjectRef) -> Result<&T, PyDowncastError> {
|
||||||
|
|
||||||
fn try_from(value: &PyObjectRef) -> Result<&T, Self::Error> {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
if T::is_instance(value.as_ptr()) {
|
if T::is_instance(value.as_ptr()) {
|
||||||
let ptr = if T::OFFSET == 0 {
|
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 {
|
unsafe {
|
||||||
if T::is_exact_instance(value.as_ptr()) {
|
if T::is_exact_instance(value.as_ptr()) {
|
||||||
let ptr = if T::OFFSET == 0 {
|
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 {
|
unsafe {
|
||||||
if T::is_instance(value.as_ptr()) {
|
if T::is_instance(value.as_ptr()) {
|
||||||
let ptr = if T::OFFSET == 0 {
|
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 {
|
unsafe {
|
||||||
if T::is_exact_instance(value.as_ptr()) {
|
if T::is_exact_instance(value.as_ptr()) {
|
||||||
let ptr = if T::OFFSET == 0 {
|
let ptr = if T::OFFSET == 0 {
|
||||||
|
|
|
@ -6,6 +6,7 @@ use std;
|
||||||
use err::PyResult;
|
use err::PyResult;
|
||||||
use ffi;
|
use ffi;
|
||||||
use python::Python;
|
use python::Python;
|
||||||
|
use std::os::raw::c_void;
|
||||||
use typeob::{PyObjectAlloc, PyTypeInfo};
|
use typeob::{PyObjectAlloc, PyTypeInfo};
|
||||||
|
|
||||||
/// Implementing this trait for custom class adds free allocation list to class.
|
/// 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) {
|
if let Some(obj) = <T as PyObjectWithFreeList>::get_free_list().insert(obj) {
|
||||||
match (*T::type_object()).tp_free {
|
match (*T::type_object()).tp_free {
|
||||||
Some(free) => free(obj as *mut ::c_void),
|
Some(free) => free(obj as *mut c_void),
|
||||||
None => {
|
None => {
|
||||||
let ty = ffi::Py_TYPE(obj);
|
let ty = ffi::Py_TYPE(obj);
|
||||||
if ffi::PyType_IS_GC(ty) != 0 {
|
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 {
|
} 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,
|
// 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) {
|
if let Some(obj) = <T as PyObjectWithFreeList>::get_free_list().insert(obj) {
|
||||||
match (*T::type_object()).tp_free {
|
match (*T::type_object()).tp_free {
|
||||||
Some(free) => free(obj as *mut ::c_void),
|
Some(free) => free(obj as *mut c_void),
|
||||||
None => {
|
None => {
|
||||||
let ty = ffi::Py_TYPE(obj);
|
let ty = ffi::Py_TYPE(obj);
|
||||||
if ffi::PyType_IS_GC(ty) != 0 {
|
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 {
|
} 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,
|
// 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.
|
//! [`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 pyo3cls;
|
||||||
extern crate spin;
|
extern crate spin;
|
||||||
// We need that reexport for wrap_function
|
// We need that reexport for wrap_function
|
||||||
|
@ -214,7 +216,3 @@ pub mod prelude;
|
||||||
pub mod python;
|
pub mod python;
|
||||||
mod pythonrun;
|
mod pythonrun;
|
||||||
pub mod typeob;
|
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.
|
/// Safe wrapper around unsafe `*mut ffi::PyObject` pointer.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[repr(transparent)]
|
||||||
pub struct PyObject(*mut ffi::PyObject);
|
pub struct PyObject(*mut ffi::PyObject);
|
||||||
|
|
||||||
// `PyObject` is thread-safe, any python related operations require a Python<'p> token.
|
// `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.
|
/// 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
|
where
|
||||||
D: PyTryFrom<Error = PyDowncastError>,
|
D: PyTryFrom,
|
||||||
{
|
{
|
||||||
D::try_from(self.as_ref(py))
|
D::try_from(self.as_ref(py))
|
||||||
}
|
}
|
||||||
|
|
|
@ -177,9 +177,9 @@ pub trait ObjectProtocol {
|
||||||
Self: PyTypeInfo;
|
Self: PyTypeInfo;
|
||||||
|
|
||||||
/// Casts the PyObject to a concrete Python object type.
|
/// 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
|
where
|
||||||
D: PyTryFrom<Error = PyDowncastError>,
|
D: PyTryFrom,
|
||||||
&'a PyObjectRef: std::convert::From<&'a Self>;
|
&'a PyObjectRef: std::convert::From<&'a Self>;
|
||||||
|
|
||||||
/// Extracts some type from the Python object.
|
/// Extracts some type from the Python object.
|
||||||
|
@ -500,9 +500,9 @@ where
|
||||||
unsafe { self.py().mut_from_borrowed_ptr(self.as_ptr()) }
|
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
|
where
|
||||||
D: PyTryFrom<Error = PyDowncastError>,
|
D: PyTryFrom,
|
||||||
&'a PyObjectRef: std::convert::From<&'a Self>,
|
&'a PyObjectRef: std::convert::From<&'a Self>,
|
||||||
{
|
{
|
||||||
D::try_from(self.into())
|
D::try_from(self.into())
|
||||||
|
|
|
@ -93,7 +93,6 @@ macro_rules! pyobject_native_type(
|
||||||
($name: ty, $typeobject: expr, $checkfunction: path $(,$type_param: ident)*) => {
|
($name: ty, $typeobject: expr, $checkfunction: path $(,$type_param: ident)*) => {
|
||||||
pyobject_native_type_named!($name $(,$type_param)*);
|
pyobject_native_type_named!($name $(,$type_param)*);
|
||||||
pyobject_native_type_convert!($name, $typeobject, $checkfunction $(,$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 {
|
impl<'a, $($type_param,)*> ::std::convert::From<&'a $name> for &'a $crate::PyObjectRef {
|
||||||
fn from(ob: &'a $name) -> Self {
|
fn from(ob: &'a $name) -> Self {
|
||||||
|
@ -210,7 +209,6 @@ use python::ToPyPointer;
|
||||||
pub struct PyObjectRef(::PyObject);
|
pub struct PyObjectRef(::PyObject);
|
||||||
pyobject_native_type_named!(PyObjectRef);
|
pyobject_native_type_named!(PyObjectRef);
|
||||||
pyobject_native_type_convert!(PyObjectRef, ffi::PyBaseObject_Type, ffi::PyObject_Check);
|
pyobject_native_type_convert!(PyObjectRef, ffi::PyBaseObject_Type, ffi::PyObject_Check);
|
||||||
pyobject_downcast!(PyObjectRef, ffi::PyObject_Check);
|
|
||||||
|
|
||||||
mod boolobject;
|
mod boolobject;
|
||||||
mod bytearray;
|
mod bytearray;
|
||||||
|
|
|
@ -16,7 +16,6 @@ use python::ToPyPointer;
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct PySequence(PyObject);
|
pub struct PySequence(PyObject);
|
||||||
pyobject_native_type_named!(PySequence);
|
pyobject_native_type_named!(PySequence);
|
||||||
pyobject_downcast!(PySequence, ffi::PySequence_Check);
|
|
||||||
|
|
||||||
impl PySequence {
|
impl PySequence {
|
||||||
/// Returns the number of objects in sequence. This is equivalent to Python `len()`.
|
/// Returns the number of objects in sequence. This is equivalent to Python `len()`.
|
||||||
|
@ -279,9 +278,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PyTryFrom for PySequence {
|
impl PyTryFrom for PySequence {
|
||||||
type Error = PyDowncastError;
|
fn try_from(value: &PyObjectRef) -> Result<&PySequence, PyDowncastError> {
|
||||||
|
|
||||||
fn try_from(value: &PyObjectRef) -> Result<&PySequence, Self::Error> {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::PySequence_Check(value.as_ptr()) != 0 {
|
if ffi::PySequence_Check(value.as_ptr()) != 0 {
|
||||||
let ptr = value as *const _ as *mut u8 as *mut PySequence;
|
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)
|
<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 {
|
unsafe {
|
||||||
if ffi::PySequence_Check(value.as_ptr()) != 0 {
|
if ffi::PySequence_Check(value.as_ptr()) != 0 {
|
||||||
let ptr = value as *const _ as *mut u8 as *mut PySequence;
|
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)
|
PySequence::try_from_mut(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ use err::{PyErr, PyResult};
|
||||||
use instance::{Py, PyObjectWithToken, PyToken};
|
use instance::{Py, PyObjectWithToken, PyToken};
|
||||||
use objects::PyType;
|
use objects::PyType;
|
||||||
use python::{IntoPyPointer, Python};
|
use python::{IntoPyPointer, Python};
|
||||||
|
use std::os::raw::c_void;
|
||||||
use {class, ffi, pythonrun};
|
use {class, ffi, pythonrun};
|
||||||
|
|
||||||
/// Python type information.
|
/// 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
|
/// The instances of this type have a dictionary containing instance variables
|
||||||
pub const PY_TYPE_FLAG_DICT: usize = 1 << 3;
|
pub const PY_TYPE_FLAG_DICT: usize = 1 << 3;
|
||||||
|
|
||||||
impl<'a, T: ?Sized> PyTypeInfo for &'a T
|
impl<'a, T: PyTypeInfo + ?Sized> PyTypeInfo for &'a T {
|
||||||
where
|
|
||||||
T: PyTypeInfo,
|
|
||||||
{
|
|
||||||
type Type = T::Type;
|
type Type = T::Type;
|
||||||
type BaseType = T::BaseType;
|
type BaseType = T::BaseType;
|
||||||
const NAME: &'static str = T::NAME;
|
const NAME: &'static str = T::NAME;
|
||||||
|
@ -262,13 +260,13 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
match (*T::type_object()).tp_free {
|
match (*T::type_object()).tp_free {
|
||||||
Some(free) => free(obj as *mut ::c_void),
|
Some(free) => free(obj as *mut c_void),
|
||||||
None => {
|
None => {
|
||||||
let ty = ffi::Py_TYPE(obj);
|
let ty = ffi::Py_TYPE(obj);
|
||||||
if ffi::PyType_IS_GC(ty) != 0 {
|
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 {
|
} 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,
|
// For heap types, PyType_GenericAlloc calls INCREF on the type objects,
|
||||||
|
@ -285,13 +283,13 @@ where
|
||||||
Self::drop(py, obj);
|
Self::drop(py, obj);
|
||||||
|
|
||||||
match (*T::type_object()).tp_free {
|
match (*T::type_object()).tp_free {
|
||||||
Some(free) => free(obj as *mut ::c_void),
|
Some(free) => free(obj as *mut c_void),
|
||||||
None => {
|
None => {
|
||||||
let ty = ffi::Py_TYPE(obj);
|
let ty = ffi::Py_TYPE(obj);
|
||||||
if ffi::PyType_IS_GC(ty) != 0 {
|
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 {
|
} 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,
|
// 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))
|
Ok(format!("format({})", format_spec))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __unicode__(&self) -> PyResult<PyObject> {
|
|
||||||
Ok(PyString::new(self.py(), "unicode").into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn __bytes__(&self) -> PyResult<PyObject> {
|
fn __bytes__(&self) -> PyResult<PyObject> {
|
||||||
Ok(PyBytes::new(self.py(), b"bytes").into())
|
Ok(PyBytes::new(self.py(), b"bytes").into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn __unicode__(&self) -> PyResult<PyObject> {
|
||||||
|
Ok(PyString::new(self.py(), "unicode").into())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(Py_3)]
|
#[cfg(Py_3)]
|
||||||
|
|
Loading…
Reference in New Issue