Refactoring
This is actually a failed bugfix attempt, but still useful
This commit is contained in:
parent
60d1565a8f
commit
76510bdd0e
|
@ -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/*",
|
||||
]
|
|
@ -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> {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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));
|
||||
}}
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue