Merge master
This commit is contained in:
parent
6113428746
commit
0880ac166c
|
@ -5,6 +5,8 @@ Cargo.lock
|
|||
build/
|
||||
__pycache__/
|
||||
.cache
|
||||
.pytest_cache/
|
||||
dist/
|
||||
|
||||
*.so
|
||||
*.out
|
||||
|
|
|
@ -23,7 +23,7 @@ log = "0.4"
|
|||
libc = "0.2"
|
||||
spin = "0.4.6"
|
||||
num-traits = "0.2"
|
||||
pyo3cls = { path = "pyo3cls" }
|
||||
pyo3cls = { path = "pyo3cls", version = "^0.2.1" }
|
||||
|
||||
[build-dependencies]
|
||||
regex = "0.2"
|
||||
|
|
|
@ -83,10 +83,12 @@ features = ["extension-module"]
|
|||
extern crate pyo3;
|
||||
use pyo3::prelude::*;
|
||||
|
||||
use pyo3::py::modinit as pymodinit;
|
||||
|
||||
// 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.
|
||||
#[py::modinit(rust2py)]
|
||||
#[pymodinit(rust2py)]
|
||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
|
||||
#[pyfn(m, "sum_as_string")]
|
||||
|
|
|
@ -12,13 +12,17 @@ use std::io::prelude::*;
|
|||
use rayon::prelude::*;
|
||||
use pyo3::prelude::*;
|
||||
|
||||
#[py::class]
|
||||
use pyo3::py::methods as pymethods;
|
||||
use pyo3::py::class as pyclass;
|
||||
use pyo3::py::modinit as pymodinit;
|
||||
|
||||
#[pyclass]
|
||||
struct WordCounter {
|
||||
path: String,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[py::methods]
|
||||
#[pymethods]
|
||||
impl WordCounter {
|
||||
|
||||
#[new]
|
||||
|
@ -81,9 +85,7 @@ fn wc_parallel(lines: &str, search: &str) -> i32 {
|
|||
.sum()
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[py::modinit(_word_count)]
|
||||
#[pymodinit(_word_count)]
|
||||
fn init_mod(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||
m.add_class::<WordCounter>()?;
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ use std::io::prelude::*;
|
|||
use rayon::prelude::*;
|
||||
use pyo3::prelude::*;
|
||||
|
||||
use pyo3::py::modinit as pymodinit;
|
||||
|
||||
fn matches(word: &str, search: &str) -> bool {
|
||||
let mut search = search.chars();
|
||||
for ch in word.chars().skip_while(|ch| !ch.is_alphabetic()) {
|
||||
|
@ -47,7 +49,7 @@ fn wc_parallel(lines: &str, search: &str) -> i32 {
|
|||
.sum()
|
||||
}
|
||||
|
||||
#[py::modinit(_word_count)]
|
||||
#[pymodinit(_word_count)]
|
||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
|
||||
#[pyfn(m, "search")]
|
||||
|
|
|
@ -28,10 +28,12 @@ Now you can write your module, for example
|
|||
extern crate pyo3;
|
||||
use pyo3::{py, PyResult, Python, PyModule};
|
||||
|
||||
use pyo3::py::modinit as pymodinit;
|
||||
|
||||
// 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.
|
||||
#[py::modinit(rust2py)]
|
||||
#[pymodinit(rust2py)]
|
||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
|
||||
// pyo3 aware function. All of our python interface could be declared in a separate module.
|
||||
|
|
|
@ -78,10 +78,12 @@ features = ["extension-module"]
|
|||
extern crate pyo3;
|
||||
use pyo3::{py, PyResult, Python, PyModule};
|
||||
|
||||
use pyo3::py::modinit as pymodinit;
|
||||
|
||||
// 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.
|
||||
#[py::modinit(rust2py)]
|
||||
#[pymodinit(rust2py)]
|
||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
|
||||
#[pyfn(m, "sum_as_string")]
|
||||
|
|
|
@ -28,7 +28,7 @@ Then in the Python bridge, we have a function `search` exposed to Python runtime
|
|||
`Python::allow_threads` method to enable true parallelism:
|
||||
|
||||
```rust,ignore
|
||||
#[py::modinit(_word_count)]
|
||||
#[pymodinit(_word_count)]
|
||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
|
||||
#[pyfn(m, "search")]
|
||||
|
|
|
@ -7,6 +7,7 @@ extern crate log;
|
|||
#[macro_use]
|
||||
extern crate quote;
|
||||
extern crate syn;
|
||||
extern crate proc_macro;
|
||||
|
||||
pub mod py_class;
|
||||
pub mod py_impl;
|
||||
|
|
|
@ -393,20 +393,29 @@ fn is_python_token(field: &syn::Field) -> bool {
|
|||
return false
|
||||
}
|
||||
|
||||
fn parse_attribute(attr: String) -> (HashMap<&'static str, syn::Ident>,
|
||||
Vec<syn::Ident>, syn::Ident) {
|
||||
fn parse_attribute(mut attr: String) -> (HashMap<&'static str, syn::Ident>,
|
||||
Vec<syn::Ident>, syn::Ident) {
|
||||
let mut params = HashMap::new();
|
||||
let mut flags = vec![syn::Ident::from("0")];
|
||||
let mut base = syn::Ident::from("_pyo3::PyObjectRef");
|
||||
|
||||
// https://github.com/rust-lang/rust/pull/50120 removed the parantheses from
|
||||
// the attr TokenStream, so we need to re-add them manually
|
||||
// Old nightly (like 2018-04-05): ( name=CustomName )
|
||||
// New nightly (like 2018-04-28): name=CustomName
|
||||
|
||||
if attr.len() > 0 && !attr.starts_with("(") {
|
||||
attr = format!("({})", attr);
|
||||
}
|
||||
|
||||
if let Ok(tts) = syn::parse_token_trees(&attr) {
|
||||
let mut elem = Vec::new();
|
||||
let mut elems = Vec::new();
|
||||
|
||||
for tt in tts.iter() {
|
||||
match tt {
|
||||
&syn::TokenTree::Token(_) => {
|
||||
println!("Wrong format: {:?}", attr.to_string());
|
||||
&syn::TokenTree::Token(ref token) => {
|
||||
println!("Wrong format: Expected delimited, found token: {:?} {:?}", attr.to_string(), token);
|
||||
}
|
||||
&syn::TokenTree::Delimited(ref delimited) => {
|
||||
for tt in delimited.tts.iter() {
|
||||
|
@ -431,7 +440,7 @@ fn parse_attribute(attr: String) -> (HashMap<&'static str, syn::Ident>,
|
|||
ident.as_ref().to_owned().to_lowercase()
|
||||
},
|
||||
_ => {
|
||||
println!("Wrong format: {:?}", attr.to_string());
|
||||
println!("Wrong format: Expected Token: {:?}", attr.to_string());
|
||||
continue
|
||||
}
|
||||
};
|
||||
|
@ -461,14 +470,14 @@ fn parse_attribute(attr: String) -> (HashMap<&'static str, syn::Ident>,
|
|||
}
|
||||
|
||||
if elem.len() < 3 {
|
||||
println!("Wrong format: {:?}", elem);
|
||||
println!("Wrong format: Less than three elements{:?}", elem);
|
||||
continue
|
||||
}
|
||||
|
||||
match elem[1] {
|
||||
syn::TokenTree::Token(syn::Token::Eq) => (),
|
||||
_ => {
|
||||
println!("Wrong format: {:?}", attr.to_string());
|
||||
println!("Wrong format: Expected a Token as fist element: {:?}", attr.to_string());
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,23 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
use syn;
|
||||
use quote::{Tokens, ToTokens};
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
|
||||
/// https://github.com/rust-lang/rust/pull/50120 removed the parantheses from
|
||||
/// the attr TokenStream, so we need to re-add them manually.
|
||||
///
|
||||
/// nightly-2018-04-05: ( name=CustomName )
|
||||
/// nightly-2018-04-28: name=CustomName
|
||||
pub fn attr_with_parentheses(attr: TokenStream) -> String {
|
||||
let attr = attr.to_string();
|
||||
if attr.len() > 0 && !attr.starts_with("(") {
|
||||
return format!("({})", attr);
|
||||
} else {
|
||||
return attr;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_err(msg: String, t: Tokens) {
|
||||
println!("Error: {} in '{}'", msg, t.to_string());
|
||||
}
|
||||
|
|
|
@ -24,7 +24,9 @@ pub fn mod2init(attr: TokenStream, input: TokenStream) -> TokenStream {
|
|||
// Build the output
|
||||
module::process_functions_in_module(&mut ast);
|
||||
|
||||
let modname = &attr.to_string()[1..attr.to_string().len() - 1].to_string();
|
||||
let attr = utils::attr_with_parentheses(attr);
|
||||
|
||||
let modname = &attr[1..attr.len() - 1].to_string();
|
||||
|
||||
let init = module::py2_init(&ast.ident, &modname, utils::get_doc(&ast.attrs, false));
|
||||
|
||||
|
@ -47,7 +49,9 @@ pub fn mod3init(attr: TokenStream, input: TokenStream) -> TokenStream {
|
|||
// Build the output
|
||||
module::process_functions_in_module(&mut ast);
|
||||
|
||||
let modname = &attr.to_string()[1..attr.to_string().len() - 1].to_string();
|
||||
let attr = utils::attr_with_parentheses(attr);
|
||||
|
||||
let modname = &attr[1..attr.len() - 1].to_string();
|
||||
|
||||
let init = module::py3_init(&ast.ident, &modname, utils::get_doc(&ast.attrs, false));
|
||||
|
||||
|
@ -87,7 +91,7 @@ pub fn class(attr: TokenStream, input: TokenStream) -> TokenStream {
|
|||
let mut ast = syn::parse_derive_input(&source).unwrap();
|
||||
|
||||
// Build the output
|
||||
let expanded = py_class::build_py_class(&mut ast, attr.to_string());
|
||||
let expanded = py_class::build_py_class(&mut ast, utils::attr_with_parentheses(attr));
|
||||
|
||||
// Return the generated impl as a TokenStream
|
||||
let mut tokens = Tokens::new();
|
||||
|
|
10
src/lib.rs
10
src/lib.rs
|
@ -54,10 +54,10 @@
|
|||
//! # Python extension
|
||||
//!
|
||||
//! To allow Python to load the rust code as a Python extension
|
||||
//! module, you need provide initialization function and annotate it with `#[py::modinit(name)]`.
|
||||
//! `py::modinit` expands to an `extern "C"` function.
|
||||
//! module, you need provide initialization function and annotate it with `#[pymodinit(name)]`.
|
||||
//! `pymodinit` expands to an `extern "C"` function.
|
||||
//!
|
||||
//! Macro syntax: `#[py::modinit(name)]`
|
||||
//! Macro syntax: `#[pymodinit(name)]`
|
||||
//!
|
||||
//! 1. `name`: The module name as a Rust identifier
|
||||
//! 2. Decorate init function `Fn(Python, &PyModule) -> PyResult<()>`.
|
||||
|
@ -80,11 +80,13 @@
|
|||
//! extern crate pyo3;
|
||||
//! use pyo3::{py, Python, PyResult, PyModule, PyString};
|
||||
//!
|
||||
//! use pyo3::py::modinit as pymodinit;
|
||||
//!
|
||||
//! // add bindings to the generated python module
|
||||
//! // N.B: names: "libhello" must be the name of the `.so` or `.pyd` file
|
||||
//!
|
||||
//! /// Module documentation string
|
||||
//! #[py::modinit(hello)]
|
||||
//! #[pymodinit(hello)]
|
||||
//! fn init_module(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
//!
|
||||
//! // pyo3 aware function. All of our python interface could be declared
|
||||
|
|
|
@ -27,7 +27,7 @@ static START_PYO3: sync::Once = sync::ONCE_INIT;
|
|||
/// thread (the thread which originally initialized Python) also initializes
|
||||
/// threading.
|
||||
///
|
||||
/// When writing an extension module, the `#[py::modinit(..)]` macro
|
||||
/// When writing an extension module, the `#[pymodinit(..)]` macro
|
||||
/// will ensure that Python threading is initialized.
|
||||
///
|
||||
pub fn prepare_freethreaded_python() {
|
||||
|
|
|
@ -8,14 +8,17 @@ use std::os::raw::{c_int, c_void};
|
|||
|
||||
use pyo3::*;
|
||||
|
||||
use pyo3::py::class as pyclass;
|
||||
use pyo3::py::proto as pyproto;
|
||||
|
||||
#[py::class]
|
||||
|
||||
#[pyclass]
|
||||
struct TestClass {
|
||||
vec: Vec<u8>,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[py::proto]
|
||||
#[pyproto]
|
||||
impl class::PyBufferProtocol for TestClass {
|
||||
|
||||
fn bf_getbuffer(&self, view: *mut ffi::Py_buffer, flags: c_int) -> PyResult<()> {
|
||||
|
|
|
@ -10,6 +10,9 @@ use std::sync::Arc;
|
|||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use pyo3::ffi;
|
||||
|
||||
use pyo3::py::class as pyclass;
|
||||
use pyo3::py::methods as pymethods;
|
||||
use pyo3::py::proto as pyproto;
|
||||
|
||||
macro_rules! py_run {
|
||||
($py:expr, $val:ident, $code:expr) => {{
|
||||
|
@ -35,7 +38,7 @@ macro_rules! py_expect_exception {
|
|||
}}
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct EmptyClass { }
|
||||
|
||||
#[test]
|
||||
|
@ -53,7 +56,7 @@ fn empty_class() {
|
|||
///Line2
|
||||
/// Line3
|
||||
// this is not doc string
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct ClassWithDocs { }
|
||||
|
||||
#[test]
|
||||
|
@ -66,7 +69,7 @@ fn class_with_docstr() {
|
|||
}
|
||||
}
|
||||
|
||||
#[py::class(name=CustomName)]
|
||||
#[pyclass(name=CustomName)]
|
||||
struct EmptyClass2 { }
|
||||
|
||||
#[test]
|
||||
|
@ -77,7 +80,7 @@ fn custom_class_name() {
|
|||
py_assert!(py, typeobj, "typeobj.__name__ == 'CustomName'");
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct EmptyClassInModule { }
|
||||
|
||||
#[test]
|
||||
|
@ -92,12 +95,12 @@ fn empty_class_in_module() {
|
|||
assert_eq!(ty.getattr("__module__").unwrap().extract::<String>().unwrap(), "test_module.nested");
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct EmptyClassWithNew {
|
||||
token: PyToken
|
||||
}
|
||||
|
||||
#[py::methods]
|
||||
#[pymethods]
|
||||
impl EmptyClassWithNew {
|
||||
#[__new__]
|
||||
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||
|
@ -113,13 +116,13 @@ fn empty_class_with_new() {
|
|||
assert!(typeobj.call(NoArgs, NoArgs).unwrap().cast_as::<EmptyClassWithNew>().is_ok());
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct NewWithOneArg {
|
||||
_data: i32,
|
||||
token: PyToken
|
||||
}
|
||||
|
||||
#[py::methods]
|
||||
#[pymethods]
|
||||
impl NewWithOneArg {
|
||||
#[new]
|
||||
fn __new__(obj: &PyRawObject, arg: i32) -> PyResult<()> {
|
||||
|
@ -137,7 +140,7 @@ fn new_with_one_arg() {
|
|||
assert_eq!(obj._data, 42);
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct NewWithTwoArgs {
|
||||
_data1: i32,
|
||||
_data2: i32,
|
||||
|
@ -145,7 +148,7 @@ struct NewWithTwoArgs {
|
|||
token: PyToken
|
||||
}
|
||||
|
||||
#[py::methods]
|
||||
#[pymethods]
|
||||
impl NewWithTwoArgs {
|
||||
#[new]
|
||||
fn __new__(obj: &PyRawObject, arg1: i32, arg2: i32) -> PyResult<()>
|
||||
|
@ -165,7 +168,7 @@ fn new_with_two_args() {
|
|||
assert_eq!(obj._data2, 20);
|
||||
}
|
||||
|
||||
#[py::class(freelist=2)]
|
||||
#[pyclass(freelist=2)]
|
||||
struct ClassWithFreelist{token: PyToken}
|
||||
|
||||
#[test]
|
||||
|
@ -202,7 +205,7 @@ impl Drop for TestDropCall {
|
|||
}
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct DataIsDropped {
|
||||
member1: TestDropCall,
|
||||
member2: TestDropCall,
|
||||
|
@ -231,7 +234,7 @@ fn data_is_dropped() {
|
|||
assert!(drop_called2.load(Ordering::Relaxed));
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct ClassWithDrop {
|
||||
token: PyToken,
|
||||
}
|
||||
|
@ -277,13 +280,13 @@ fn create_pointers_in_drop() {
|
|||
}
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct InstanceMethod {
|
||||
member: i32,
|
||||
token: PyToken
|
||||
}
|
||||
|
||||
#[py::methods]
|
||||
#[pymethods]
|
||||
impl InstanceMethod {
|
||||
/// Test method
|
||||
fn method(&self) -> PyResult<i32> {
|
||||
|
@ -304,13 +307,13 @@ fn instance_method() {
|
|||
py.run("assert obj.method.__doc__ == 'Test method'", None, Some(d)).unwrap();
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct InstanceMethodWithArgs {
|
||||
member: i32,
|
||||
token: PyToken
|
||||
}
|
||||
|
||||
#[py::methods]
|
||||
#[pymethods]
|
||||
impl InstanceMethodWithArgs {
|
||||
fn method(&self, multiplier: i32) -> PyResult<i32> {
|
||||
Ok(self.member * multiplier)
|
||||
|
@ -331,10 +334,10 @@ fn instance_method_with_args() {
|
|||
}
|
||||
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct ClassMethod {token: PyToken}
|
||||
|
||||
#[py::methods]
|
||||
#[pymethods]
|
||||
impl ClassMethod {
|
||||
#[new]
|
||||
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||
|
@ -359,10 +362,10 @@ fn class_method() {
|
|||
}
|
||||
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct ClassMethodWithArgs{token: PyToken}
|
||||
|
||||
#[py::methods]
|
||||
#[pymethods]
|
||||
impl ClassMethodWithArgs {
|
||||
#[classmethod]
|
||||
fn method(cls: &PyType, input: &PyString) -> PyResult<String> {
|
||||
|
@ -380,12 +383,12 @@ fn class_method_with_args() {
|
|||
py.run("assert C.method('abc') == 'ClassMethodWithArgs.method(abc)'", None, Some(d)).unwrap();
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct StaticMethod {
|
||||
token: PyToken
|
||||
}
|
||||
|
||||
#[py::methods]
|
||||
#[pymethods]
|
||||
impl StaticMethod {
|
||||
#[new]
|
||||
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||
|
@ -416,10 +419,10 @@ fn static_method() {
|
|||
py.run("assert C.no_parameters() == 'StaticMethod.no_parameters()!'", None, Some(d)).unwrap();
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct StaticMethodWithArgs{token: PyToken}
|
||||
|
||||
#[py::methods]
|
||||
#[pymethods]
|
||||
impl StaticMethodWithArgs {
|
||||
|
||||
#[staticmethod]
|
||||
|
@ -440,14 +443,14 @@ fn static_method_with_args() {
|
|||
py.run("assert C.method(1337) == '0x539'", None, Some(d)).unwrap();
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct GCIntegration {
|
||||
self_ref: RefCell<PyObject>,
|
||||
dropped: TestDropCall,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[py::proto]
|
||||
#[pyproto]
|
||||
impl PyGCProtocol for GCIntegration {
|
||||
fn __traverse__(&self, visit: PyVisit) -> Result<(), PyTraverseError> {
|
||||
visit.call(&*self.self_ref.borrow())
|
||||
|
@ -479,7 +482,7 @@ fn gc_integration() {
|
|||
assert!(drop_called.load(Ordering::Relaxed));
|
||||
}
|
||||
|
||||
#[py::class(gc)]
|
||||
#[pyclass(gc)]
|
||||
struct GCIntegration2 {
|
||||
token: PyToken,
|
||||
}
|
||||
|
@ -491,7 +494,7 @@ fn gc_integration2() {
|
|||
py_run!(py, inst, "import gc; assert inst in gc.get_objects()");
|
||||
}
|
||||
|
||||
#[py::class(weakref)]
|
||||
#[pyclass(weakref)]
|
||||
struct WeakRefSupport {
|
||||
token: PyToken,
|
||||
}
|
||||
|
@ -503,13 +506,13 @@ fn weakref_support() {
|
|||
py_run!(py, inst, "import weakref; assert weakref.ref(inst)() is inst");
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
pub struct Len {
|
||||
l: usize,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[py::proto]
|
||||
#[pyproto]
|
||||
impl PyMappingProtocol for Len {
|
||||
fn __len__(&self) -> PyResult<usize> {
|
||||
Ok(self.l)
|
||||
|
@ -532,13 +535,13 @@ fn len() {
|
|||
py_expect_exception!(py, inst, "len(inst)", OverflowError);
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct Iterator{
|
||||
iter: Box<iter::Iterator<Item=i32> + Send>,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[py::proto]
|
||||
#[pyproto]
|
||||
impl PyIterProtocol for Iterator {
|
||||
fn __iter__(&mut self) -> PyResult<Py<Iterator>> {
|
||||
Ok(self.into())
|
||||
|
@ -559,10 +562,10 @@ fn iterator() {
|
|||
py_assert!(py, inst, "list(inst) == [5, 6, 7]");
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct StringMethods {token: PyToken}
|
||||
|
||||
#[py::proto]
|
||||
#[pyproto]
|
||||
impl<'p> PyObjectProtocol<'p> for StringMethods {
|
||||
fn __str__(&self) -> PyResult<&'static str> {
|
||||
Ok("str")
|
||||
|
@ -612,13 +615,13 @@ fn string_methods() {
|
|||
}
|
||||
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct Comparisons {
|
||||
val: i32,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[py::proto]
|
||||
#[pyproto]
|
||||
impl PyObjectProtocol for Comparisons {
|
||||
fn __hash__(&self) -> PyResult<isize> {
|
||||
Ok(self.val as isize)
|
||||
|
@ -647,12 +650,12 @@ fn comparisons() {
|
|||
}
|
||||
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct Sequence {
|
||||
token: PyToken
|
||||
}
|
||||
|
||||
#[py::proto]
|
||||
#[pyproto]
|
||||
impl PySequenceProtocol for Sequence {
|
||||
fn __len__(&self) -> PyResult<usize> {
|
||||
Ok(5)
|
||||
|
@ -677,10 +680,10 @@ fn sequence() {
|
|||
}
|
||||
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct Callable {token: PyToken}
|
||||
|
||||
#[py::methods]
|
||||
#[pymethods]
|
||||
impl Callable {
|
||||
|
||||
#[__call__]
|
||||
|
@ -702,14 +705,14 @@ fn callable() {
|
|||
py_assert!(py, nc, "not callable(nc)");
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct SetItem {
|
||||
key: i32,
|
||||
val: i32,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[py::proto]
|
||||
#[pyproto]
|
||||
impl PyMappingProtocol<'a> for SetItem {
|
||||
fn __setitem__(&mut self, key: i32, val: i32) -> PyResult<()> {
|
||||
self.key = key;
|
||||
|
@ -730,13 +733,13 @@ fn setitem() {
|
|||
py_expect_exception!(py, c, "del c[1]", NotImplementedError);
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct DelItem {
|
||||
key: i32,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[py::proto]
|
||||
#[pyproto]
|
||||
impl PyMappingProtocol<'a> for DelItem {
|
||||
fn __delitem__(&mut self, key: i32) -> PyResult<()> {
|
||||
self.key = key;
|
||||
|
@ -755,13 +758,13 @@ fn delitem() {
|
|||
py_expect_exception!(py, c, "c[1] = 2", NotImplementedError);
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct SetDelItem {
|
||||
val: Option<i32>,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[py::proto]
|
||||
#[pyproto]
|
||||
impl PyMappingProtocol for SetDelItem {
|
||||
fn __setitem__(&mut self, key: i32, val: i32) -> PyResult<()> {
|
||||
self.val = Some(val);
|
||||
|
@ -786,10 +789,10 @@ fn setdelitem() {
|
|||
assert_eq!(c.val, None);
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct Reversed {token: PyToken}
|
||||
|
||||
#[py::proto]
|
||||
#[pyproto]
|
||||
impl PyMappingProtocol for Reversed{
|
||||
fn __reversed__(&self) -> PyResult<&'static str> {
|
||||
Ok("I am reversed")
|
||||
|
@ -805,10 +808,10 @@ fn reversed() {
|
|||
py_run!(py, c, "assert reversed(c) == 'I am reversed'");
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct Contains {token: PyToken}
|
||||
|
||||
#[py::proto]
|
||||
#[pyproto]
|
||||
impl PySequenceProtocol for Contains {
|
||||
fn __contains__(&self, item: i32) -> PyResult<bool> {
|
||||
Ok(item >= 0)
|
||||
|
@ -828,10 +831,10 @@ fn contains() {
|
|||
|
||||
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct UnaryArithmetic {token: PyToken}
|
||||
|
||||
#[py::proto]
|
||||
#[pyproto]
|
||||
impl PyNumberProtocol for UnaryArithmetic {
|
||||
|
||||
fn __neg__(&self) -> PyResult<&'static str> {
|
||||
|
@ -864,19 +867,19 @@ fn unary_arithmetic() {
|
|||
}
|
||||
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct BinaryArithmetic {
|
||||
token: PyToken
|
||||
}
|
||||
|
||||
#[py::proto]
|
||||
#[pyproto]
|
||||
impl PyObjectProtocol for BinaryArithmetic {
|
||||
fn __repr__(&self) -> PyResult<&'static str> {
|
||||
Ok("BA")
|
||||
}
|
||||
}
|
||||
|
||||
#[py::proto]
|
||||
#[pyproto]
|
||||
impl PyNumberProtocol for BinaryArithmetic {
|
||||
fn __add__(lhs: &PyObjectRef, rhs: &PyObjectRef) -> PyResult<String> {
|
||||
Ok(format!("{:?} + {:?}", lhs, rhs))
|
||||
|
@ -938,12 +941,12 @@ fn binary_arithmetic() {
|
|||
}
|
||||
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct RichComparisons {
|
||||
token: PyToken
|
||||
}
|
||||
|
||||
#[py::proto]
|
||||
#[pyproto]
|
||||
impl PyObjectProtocol for RichComparisons {
|
||||
fn __repr__(&self) -> PyResult<&'static str> {
|
||||
Ok("RC")
|
||||
|
@ -961,12 +964,12 @@ impl PyObjectProtocol for RichComparisons {
|
|||
}
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct RichComparisons2 {
|
||||
py: PyToken
|
||||
}
|
||||
|
||||
#[py::proto]
|
||||
#[pyproto]
|
||||
impl PyObjectProtocol for RichComparisons2 {
|
||||
fn __repr__(&self) -> PyResult<&'static str> {
|
||||
Ok("RC2")
|
||||
|
@ -1034,20 +1037,20 @@ fn rich_comparisons_python_3_type_error() {
|
|||
py_expect_exception!(py, c2, "1 >= c2", TypeError);
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct InPlaceOperations {
|
||||
value: u32,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[py::proto]
|
||||
#[pyproto]
|
||||
impl PyObjectProtocol for InPlaceOperations {
|
||||
fn __repr__(&self) -> PyResult<String> {
|
||||
Ok(format!("IPO({:?})", self.value))
|
||||
}
|
||||
}
|
||||
|
||||
#[py::proto]
|
||||
#[pyproto]
|
||||
impl PyNumberProtocol for InPlaceOperations {
|
||||
fn __iadd__(&mut self, other: u32) -> PyResult<()> {
|
||||
self.value += other;
|
||||
|
@ -1120,13 +1123,13 @@ fn inplace_operations() {
|
|||
py_run!(py, c, "d = c; c ^= 5; assert repr(c) == repr(d) == 'IPO(9)'");
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct ContextManager {
|
||||
exit_called: bool,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[py::proto]
|
||||
#[pyproto]
|
||||
impl<'p> PyContextProtocol<'p> for ContextManager {
|
||||
|
||||
fn __enter__(&mut self) -> PyResult<i32> {
|
||||
|
@ -1165,13 +1168,13 @@ fn context_manager() {
|
|||
assert!(c.exit_called);
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct ClassWithProperties {
|
||||
num: i32,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[py::methods]
|
||||
#[pymethods]
|
||||
impl ClassWithProperties {
|
||||
|
||||
fn get_num(&self) -> PyResult<i32> {
|
||||
|
@ -1203,12 +1206,12 @@ fn class_with_properties() {
|
|||
py_run!(py, inst, "assert inst.get_num() == inst.DATA");
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct MethArgs {
|
||||
token: PyToken
|
||||
}
|
||||
|
||||
#[py::methods]
|
||||
#[pymethods]
|
||||
impl MethArgs {
|
||||
|
||||
#[args(test="10")]
|
||||
|
@ -1243,7 +1246,7 @@ fn meth_args() {
|
|||
// py_expect_exception!(py, inst, "inst.get_kwarg(100)", TypeError);
|
||||
}
|
||||
|
||||
#[py::class(subclass)]
|
||||
#[pyclass(subclass)]
|
||||
struct SubclassAble {}
|
||||
|
||||
#[test]
|
||||
|
@ -1258,7 +1261,7 @@ fn subclass() {
|
|||
.unwrap();
|
||||
}
|
||||
|
||||
#[py::class(dict)]
|
||||
#[pyclass(dict)]
|
||||
struct DunderDictSupport {
|
||||
token: PyToken,
|
||||
}
|
||||
|
@ -1271,7 +1274,7 @@ fn dunder_dict_support() {
|
|||
py_run!(py, inst, "inst.a = 1; assert inst.a == 1");
|
||||
}
|
||||
|
||||
#[py::class(weakref, dict)]
|
||||
#[pyclass(weakref, dict)]
|
||||
struct WeakRefDunderDictSupport {
|
||||
token: PyToken,
|
||||
}
|
||||
|
@ -1284,14 +1287,14 @@ fn weakref_dunder_dict_support() {
|
|||
py_run!(py, inst, "import weakref; assert weakref.ref(inst)() is inst; inst.a = 1; assert inst.a == 1");
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct GetterSetter {
|
||||
#[prop(get, set)]
|
||||
num: i32,
|
||||
token: PyToken
|
||||
}
|
||||
|
||||
#[py::methods]
|
||||
#[pymethods]
|
||||
impl GetterSetter {
|
||||
|
||||
fn get_num2(&self) -> PyResult<i32> {
|
||||
|
@ -1310,13 +1313,13 @@ fn getter_setter_autogen() {
|
|||
py_run!(py, inst, "inst.num = 20; assert inst.num == 20");
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct BaseClass {
|
||||
#[prop(get)]
|
||||
val1: usize,
|
||||
}
|
||||
|
||||
#[py::methods]
|
||||
#[pymethods]
|
||||
impl BaseClass {
|
||||
#[new]
|
||||
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||
|
@ -1324,13 +1327,13 @@ impl BaseClass {
|
|||
}
|
||||
}
|
||||
|
||||
#[py::class(base=BaseClass)]
|
||||
#[pyclass(base=BaseClass)]
|
||||
struct SubClass {
|
||||
#[prop(get)]
|
||||
val2: usize,
|
||||
}
|
||||
|
||||
#[py::methods]
|
||||
#[pymethods]
|
||||
impl SubClass {
|
||||
#[new]
|
||||
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||
|
@ -1350,13 +1353,13 @@ fn inheritance_with_new_methods() {
|
|||
}
|
||||
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct BaseClassWithDrop {
|
||||
token: PyToken,
|
||||
data: Option<Arc<AtomicBool>>,
|
||||
}
|
||||
|
||||
#[py::methods]
|
||||
#[pymethods]
|
||||
impl BaseClassWithDrop {
|
||||
#[new]
|
||||
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||
|
@ -1372,13 +1375,13 @@ impl Drop for BaseClassWithDrop {
|
|||
}
|
||||
}
|
||||
|
||||
#[py::class(base=BaseClassWithDrop)]
|
||||
#[pyclass(base=BaseClassWithDrop)]
|
||||
struct SubClassWithDrop {
|
||||
token: PyToken,
|
||||
data: Option<Arc<AtomicBool>>,
|
||||
}
|
||||
|
||||
#[py::methods]
|
||||
#[pymethods]
|
||||
impl SubClassWithDrop {
|
||||
#[new]
|
||||
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||
|
@ -1419,13 +1422,13 @@ fn inheritance_with_new_methods_with_drop() {
|
|||
}
|
||||
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct MutRefArg {
|
||||
n: i32,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[py::methods]
|
||||
#[pymethods]
|
||||
impl MutRefArg {
|
||||
|
||||
fn get(&self) -> PyResult<i32> {
|
||||
|
|
|
@ -43,6 +43,7 @@ fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(Py_3)]
|
||||
fn test_module_with_functions() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
|
|
@ -5,6 +5,9 @@ extern crate pyo3;
|
|||
|
||||
use pyo3::*;
|
||||
|
||||
use pyo3::py::class as pyclass;
|
||||
use pyo3::py::proto as pyproto;
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_basics() {
|
||||
|
@ -20,12 +23,12 @@ fn test_basics() {
|
|||
}
|
||||
|
||||
|
||||
#[py::class]
|
||||
#[pyclass]
|
||||
struct Test {
|
||||
token: PyToken
|
||||
}
|
||||
|
||||
#[py::proto]
|
||||
#[pyproto]
|
||||
impl<'p> PyMappingProtocol<'p> for Test
|
||||
{
|
||||
fn __getitem__(&self, idx: &PyObjectRef) -> PyResult<PyObject> {
|
||||
|
|
Loading…
Reference in New Issue