Refactoring

This is actually a failed bugfix attempt, but still useful
This commit is contained in:
konstin 2018-06-13 18:02:45 +02:00
parent 60d1565a8f
commit 76510bdd0e
7 changed files with 66 additions and 42 deletions

View File

@ -45,3 +45,10 @@ python3 = []
# It tells the linker to keep the python symbols unresolved,
# so that the module can also be used with statically linked python interpreters.
extension-module = []
[workspace]
members = [
"pyo3cls",
"pyo3-derive-backend",
"examples/*",
]

View File

@ -1,7 +1,6 @@
// Source adopted from
// https://github.com/tildeio/helix-website/blob/master/crates/word_count/src/lib.rs
#![feature(proc_macro, specialization)]
#![feature(const_fn, const_align_of, const_size_of, const_ptr_null, const_ptr_null_mut)]
extern crate pyo3;
extern crate rayon;
@ -16,7 +15,7 @@ use pyo3::py::methods as pymethods;
use pyo3::py::class as pyclass;
use pyo3::py::modinit as pymodinit;
#[pyclass]
#[pyclass(dict)]
struct WordCounter {
path: String,
token: PyToken,
@ -27,7 +26,7 @@ impl WordCounter {
#[new]
fn __new__(obj: &PyRawObject, path: String) -> PyResult<()> {
obj.init(|t| WordCounter {path: path, token: t})
obj.init(|t| WordCounter {path, token: t})
}
fn search(&self, py: Python, search: String) -> PyResult<i32> {

View File

@ -47,7 +47,7 @@ are generated only if struct contains `PyToken` attribute.
TODO - continue
## class macro
## The `#[class]` macro
Python class generation is powered by [Procedural Macros](https://doc.rust-lang.org/book/first-edition/procedural-macros.html).
To define python custom class, rust struct needs to be annotated with `#[class]` attribute.
@ -65,7 +65,7 @@ python object that can be collector `PyGCProtocol` trait has to be implemented.
* `base=BaseType` - use custom base class. BaseType is type which is
implements `PyTypeInfo` trait.
* `subclass` - adds subclass support so that Python classes can inherit from this class
* `dict` - adds `__dict__` support, the instances of this type have a dictionary containing instance variables
* `dict` - adds `__dict__` support, the instances of this type have a dictionary containing instance variables.
## Constructor

View File

@ -420,11 +420,6 @@ fn parse_attribute(
let mut flags = vec![syn::Expr::Lit(parse_quote!{0})];
let mut base: syn::TypePath = parse_quote!{_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
for expr in args.iter() {
match expr {

View File

@ -1,9 +1,23 @@
/// Removes indentation from multiline strings in pyrun commands
pub fn indoc(commands: &str) -> String {
let indent;
if let Some(second) = commands.lines().nth(1) {
indent = second.chars().take_while(char::is_ascii_whitespace).collect::<String>();
} else {
indent = "".to_string();
}
commands.trim_right().replace(&("\n".to_string() + &indent), "\n") + "\n"
}
#[macro_export]
macro_rules! py_run {
($py:expr, $val:ident, $code:expr) => {{
let d = PyDict::new($py);
d.set_item(stringify!($val), &$val).unwrap();
$py.run($code, None, Some(d)).map_err(|e| e.print($py)).expect($code);
$py.run(&common::indoc($code), None, Some(d))
.map_err(|e| e.print($py))
.expect(&common::indoc($code));
}}
}

View File

@ -371,16 +371,16 @@ fn context_manager() {
let py = gil.python();
let c = py.init_mut(|t| ContextManager{exit_called: false, token: t}).unwrap();
py_run!(py, c, "with c as x:\n assert x == 42");
py_run!(py, c, "with c as x: assert x == 42");
assert!(c.exit_called);
c.exit_called = false;
py_run!(py, c, "with c as x:\n raise ValueError");
py_run!(py, c, "with c as x: raise ValueError");
assert!(c.exit_called);
c.exit_called = false;
py_expect_exception!(
py, c, "with c as x:\n raise NotImplementedError", NotImplementedError);
py, c, "with c as x: raise NotImplementedError", NotImplementedError);
assert!(c.exit_called);
}
@ -434,3 +434,40 @@ fn test_cls_impl() {
py.run("assert ob[1] == 'int'", None, Some(d)).unwrap();
py.run("assert ob[100:200:1] == 'slice'", None, Some(d)).unwrap();
}
#[pyclass(dict)]
struct DunderDictSupport {
token: PyToken,
}
#[test]
fn dunder_dict_support() {
let gil = Python::acquire_gil();
let py = gil.python();
let inst = Py::new_ref(py, |t| DunderDictSupport{token: t}).unwrap();
py_run!(py, inst, r#"
inst.a = 1
assert inst.a == 1
"#);
py_run!(py, inst, r#"
import copy
inst2 = copy.deepcopy(inst)
inst2.a = 2
assert inst.a == 1
"#);
}
#[pyclass(weakref, dict)]
struct WeakRefDunderDictSupport {
token: PyToken,
}
#[test]
fn weakref_dunder_dict_support() {
let gil = Python::acquire_gil();
let py = gil.python();
let inst = Py::new_ref(py, |t| WeakRefDunderDictSupport{token: t}).unwrap();
py_run!(py, inst, "import weakref; assert weakref.ref(inst)() is inst; inst.a = 1; assert inst.a == 1");
}

View File

@ -11,34 +11,6 @@ use pyo3::py::methods as pymethods;
#[macro_use]
mod common;
#[pyclass(dict)]
struct DunderDictSupport {
token: PyToken,
}
#[test]
fn dunder_dict_support() {
let gil = Python::acquire_gil();
let py = gil.python();
let inst = Py::new_ref(py, |t| DunderDictSupport{token: t}).unwrap();
py_run!(py, inst, "inst.a = 1; assert inst.a == 1");
}
#[pyclass(weakref, dict)]
struct WeakRefDunderDictSupport {
token: PyToken,
}
#[test]
fn weakref_dunder_dict_support() {
let gil = Python::acquire_gil();
let py = gil.python();
let inst = Py::new_ref(py, |t| WeakRefDunderDictSupport{token: t}).unwrap();
py_run!(py, inst, "import weakref; assert weakref.ref(inst)() is inst; inst.a = 1; assert inst.a == 1");
}
#[pyclass]
struct MutRefArg {
n: i32,