Expand description
This library provides derive macros of Python spacial methods and a class attributes for PyO3.
The field attribute #[pyderive(..)]
helps to customize implementations,
like dataclasses.field()
of Python.
It requires to enable multiple-pymethods
feature of PyO3
because the derive macros that this library provides may implement multiple #[pymethods]
.
§Example
// Enable `multiple-pymethods` feature of PyO3
use pyo3::prelude::*;
use pyderive::*;
// Place #[derive(PyNew, ...)] before #[pyclass]
#[derive(PyNew, PyMatchArgs, PyRepr, PyEq)]
#[pyclass(get_all)]
#[derive(PartialEq, Hash)]
struct MyClass {
string: String,
integer: i64,
option: Option<i64>
}
# Python script
from rust_module import MyClass
# Derives __new__()
m = MyClass("a", 1, None)
# Derives __match_args__ (supports Pattern Matching by positional arguments)
match m:
case MyClass(a, b, c):
assert a == "a"
assert b == 1
assert c is None
case _:
raise AssertionError
# Derives __repr__(), calls Python repr() recursively
assert str(m) == "MyClass(string='a', integer=1, option=None)"
assert repr(m) == "MyClass(string='a', integer=1, option=None)"
# Derives __eq__() that depends on PartialEq trait
assert m == MyClass("a", 1, None)
§Detail
Some macros change implementations depend on #[pyclass(..)]
and #[pyo3(..)]
arguments,
hence it should place #[derive(PyNew)]
etc. before #[pyclass(..)]
and #[pyo3(..)]
.
We list the default implementations that the macros generate.
Derive Macro | Derives |
---|---|
PyNew | __new__() with all fields |
PyMatchArgs | __match_args__ class attr. with get fields |
PyRepr | __repr__() returns get and set fields |
PyStr | __str__() returns get and set fields |
PyIter | __iter__() returns an iterator of get fields |
PyReversed | __reversed__() returns an iterator of get fields |
PyLen | __len__() returns number of get fields |
PyDataclassFields | __dataclass_fields__ class attr. with all fields |
Notes, methods implemented by PyRepr
and PyStr
are recursively calls repr()
or str()
like a Python dataclass
.
We call the field is get
(or set
) field
if the field has a #[pyclass/pyo3(get)]
(or #[pyclass/pyo3(set)]
) attribute or
its struct has a #[pyclass/pyo3(get_all)]
(or #[pyclass/pyo3(set_all)]
) attribute.
The following derive macros depend on traits.
Derive Macro | Derives |
---|---|
PyEq | __eq__() and __ne__() , depends on PartialEq |
PyOrd | __lt__() , __le__() , __gt__() and __ge__() , depend on PartialOrd |
PyRichCmp | == , != , > , >= , < and <= by __richcmp__() , depend on PartialEq and PartialOrd |
PyNumeric | Numeric op traits (__add__() etc.) |
PyBitwise | Bitwise op traits (__and__() etc.) |
Notes, implementation of PyEq
and PyOrd
does not use __richcmp__()
.
Module pyderive::ops
and pyderive::convert
provides
derive macros that implement individual method that enumerating numeric type (__add__()
etc.) and
called by builtin functions (__int__()
etc.).
§Customize Implementation
The field attributes #[pyderive(..)]
is used to customize implementations
produced by pyderive’s derive.
use pyderive::*;
#[derive(PyNew, PyRepr)]
#[pyclass]
struct MyClass {
string: String,
#[pyderive(repr=false)]
#[pyo3(get)]
integer: i64,
#[pyderive(default=10)]
option: Option<i64>
}
It allows to omit the right-hand side,
and it evaluates to the right-hand as true
except default
, for example,
#[pyderive(repr)]
is equivalent to #[pyderive(repr=true)]
.
-
#[pyderive(repr=<bool>)]
If
repr=true
, the field is included in the string that the__repr__()
method returns; ifrepr=false
, it isn’t.The derive macro
PyDataclassFields
reads this attribute also, seePyDataclassFields
for detail. -
#[pyderive(str=<bool>)]
If
str=true
, the field is included in the string that the__str__()
method returns; ifstr=false
, it isn’t. -
#[pyderive(new=<bool>)]
If
new=false
, the field is excluded from the arguments of the__new__()
method. Notes,new=true
has no effect.The derive macro
PyDataclassFields
reads this attribute also, seePyDataclassFields
for detail. -
#[pyderive(default=<expr>)]
This is used to customize default value for the
__new__()
method. It supports any rust expression which PyO3 supports, e.g.,#[derive(PyNew)] #[pyclass] struct PyClass { #[pyderive(default = Some("str".to_string()))] field: Option<String>, }
We note that this internally produces
#[pyo3(signature = ..)]
attribute.-
No
#[pyderive(..)]
(for example, justfield: i64
)Pseudocode:
def __new__(cls, field): self = super().__new__(cls) self.field = field return self
-
#[pyderive(new=false)]
The field is excluded from the arguments, and initialized by
Default::default()
in the__new__()
method. We note that it is evaluated on every__new__()
call.Pseudocode:
def __new__(cls): self = super().__new__(cls) self.field = field::default() # call rust fn return self
-
#[pyderive(default=<expr>)]
The field is included to the arguments with default value
<expr>
. We note that<expr>
(rust code) is evaluated on every__new__()
call (PyO3 feature).Pseudocode:
def __new__(cls, field=<expr>): self = super().__new__(cls) self.field = field return self
-
#[pyderive(new=false, default=<expr>)]
The field is excluded from the arguments, and initialized with
<expr>
in the__new__()
method. We note that<expr>
(rust code) is evaluated on every__new__()
call.Pseudocode:
def __new__(cls): self = super().__new__(cls) self.field = <expr> return self
-
-
#[pyderive(default_factory=true)]
If
default_factory=true
, let thedefault_factory
attribute ofField
obj belambda: <expr>
, and let thedefault
attribute bedataclasses.MISSING
, where<expr>
is given by#[pyderive(default=<expr>)]
. Notes,default_factory=false
has no effect, If the field is not marked by#[pyderive(default=<expr>)]
, this ignores.See
PyDataclassFields
for detail. -
#[pyderive(kw_only=true)]
If
kw_only=true
, the following fields are keyword only arguments in the__new__()
method, like*
anddataclasses.KW_ONLY
. Note,kw_only=false
has no effect.The derive macro
PyDataclassFields
reads this attribute also, seePyDataclassFields
for detail. -
#[pyderive(match_args=<bool>)]
If
match_args=true
, the field is included in the__match_args__
class attribute; ifmatch_args=false
, it isn’t.We note that, as far as I know, the field must be accessible on the pattern matching. For example, pattern matching does not work with not
get
field without a getter (even ifmatch_args=true
), but it does work if the field has a getter. -
#[pyderive(iter=<bool>)]
If
iter=true
, the field is included in the iterator that__iter__()
and__reversed__()
return; ifiter=false
, it isn’t. -
#[pyderive(len=<bool>)]
If
len=true
, the field is counted by the__len__()
; iflen=false
, it isn’t. -
#[pyderive(dataclass_field=false)]
If
dataclass_field=false
, the field is excluded from the__dataclass_fields__
dict. Notes,dataclass_field=true
has no effect.See
PyDataclassFields
for detail. -
#[pyderive(annotation=<str>)]
The derive macro
PyDataclassFields
reads this attribute, seePyDataclassFields
for detail.
Modules§
- convert
- Provides derive macros that implements conversion by built-in functions.
- ops
- Provides derive macros that implements enumeration of numeric type.
Derive Macros§
- PyBitwise
- Derive macro generating an impl of bitwise op methods/fns base on std::ops traits.
- PyDataclass
Fields - Derive macro generating a
__dataclass_fields__
fn/Python class attribute. - PyEq
- Derive macro generating a
__eq__()
and__ne__()
fn/Python methods. - PyHash
- Derive macro generating a
__hash__()
fn/Python method. - PyIter
- Derive macro generating a
__iter__()
fn/Python method. - PyLen
- Derive macro generating a
__len__()
fn/Python method. - PyMatch
Args - Derive macro generating a
__match_args__
const/Python class attribute. - PyNew
- Derive macro generating a
__new__()
Python method. - PyNumeric
- Derive macro generating an impl of numeric op methods/fns base on std::ops traits.
- PyOrd
- Derive macro generating
__lt__()
,__le__()
,__gt__()
and__ge__()
fn/Python methods. - PyRepr
- Derive macro generating a
__repr__()
fn/Python method. - PyReversed
- Derive macro generating a
__reversed__()
fn/Python method. - PyRich
Cmp - Derive macro generating
__richcmp__
fn that provides Python comparison operations (==
,!=
,<
,<=
,>
, and>=
). - PyStr
- Derive macro generating a
__str__()
fn/Python method. - ToPy
Object - Derive macro generating an impl of the trait
ToPyObject
by traitIntoPy<PyObject>
.