Doc fixes, changelog and rename.
This commit is contained in:
parent
9137855e81
commit
e65b849ab6
|
@ -15,6 +15,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||||
- Add optional implementations of `ToPyObject`, `IntoPy`, and `FromPyObject` for [hashbrown](https://crates.io/crates/hashbrown)'s `HashMap` and `HashSet` types. The `hashbrown` feature must be enabled for these implementations to be built. [#1114](https://github.com/PyO3/pyo3/pull/1114/)
|
- Add optional implementations of `ToPyObject`, `IntoPy`, and `FromPyObject` for [hashbrown](https://crates.io/crates/hashbrown)'s `HashMap` and `HashSet` types. The `hashbrown` feature must be enabled for these implementations to be built. [#1114](https://github.com/PyO3/pyo3/pull/1114/)
|
||||||
- Allow other `Result` types when using `#[pyfunction]`. [#1106](https://github.com/PyO3/pyo3/issues/1106).
|
- Allow other `Result` types when using `#[pyfunction]`. [#1106](https://github.com/PyO3/pyo3/issues/1106).
|
||||||
- Add `#[derive(FromPyObject)]` macro for enums and structs. [#1065](https://github.com/PyO3/pyo3/pull/1065)
|
- Add `#[derive(FromPyObject)]` macro for enums and structs. [#1065](https://github.com/PyO3/pyo3/pull/1065)
|
||||||
|
- Add macro attribute to `#[pyfn]` and `#[pyfunction]` to pass the module of a Python function to the function
|
||||||
|
body. [#1143](https://github.com/PyO3/pyo3/pull/1143)
|
||||||
|
- Add `add_function()` and `add_submodule()` functions to `PyModule` [#1143](https://github.com/PyO3/pyo3/pull/1143)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Exception types have been renamed from e.g. `RuntimeError` to `PyRuntimeError`, and are now only accessible by `&T` or `Py<T>` similar to other Python-native types. The old names continue to exist but are deprecated. [#1024](https://github.com/PyO3/pyo3/pull/1024)
|
- Exception types have been renamed from e.g. `RuntimeError` to `PyRuntimeError`, and are now only accessible by `&T` or `Py<T>` similar to other Python-native types. The old names continue to exist but are deprecated. [#1024](https://github.com/PyO3/pyo3/pull/1024)
|
||||||
|
@ -50,6 +53,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||||
- Link against libpython on android with `extension-module` set. [#1095](https://github.com/PyO3/pyo3/pull/1095)
|
- Link against libpython on android with `extension-module` set. [#1095](https://github.com/PyO3/pyo3/pull/1095)
|
||||||
- Fix support for both `__add__` and `__radd__` in the `+` operator when both are defined in `PyNumberProtocol`
|
- Fix support for both `__add__` and `__radd__` in the `+` operator when both are defined in `PyNumberProtocol`
|
||||||
(and similar for all other reversible operators). [#1107](https://github.com/PyO3/pyo3/pull/1107)
|
(and similar for all other reversible operators). [#1107](https://github.com/PyO3/pyo3/pull/1107)
|
||||||
|
- Associate Python functions with their module by passing the Module and Module name [#1143](https://github.com/PyO3/pyo3/pull/1143)
|
||||||
|
|
||||||
## [0.11.1] - 2020-06-30
|
## [0.11.1] - 2020-06-30
|
||||||
### Added
|
### Added
|
||||||
|
|
|
@ -192,15 +192,14 @@ If you have a static function, you can expose it with `#[pyfunction]` and use [`
|
||||||
|
|
||||||
### Accessing the module of a function
|
### Accessing the module of a function
|
||||||
|
|
||||||
Functions are usually associated with modules, in the C-API, the self parameter in a function call corresponds
|
It is possible to access the module of a `#[pyfunction]` and `#[pyfn]` in the
|
||||||
to the module of the function. It is possible to access the module of a `#[pyfunction]` and `#[pyfn]` in the
|
function body by passing the `pass_module` argument to the attribute:
|
||||||
function body by passing the `need_module` argument to the attribute:
|
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use pyo3::wrap_pyfunction;
|
use pyo3::wrap_pyfunction;
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
#[pyfunction(need_module)]
|
#[pyfunction(pass_module)]
|
||||||
fn pyfunction_with_module(
|
fn pyfunction_with_module(
|
||||||
module: &PyModule
|
module: &PyModule
|
||||||
) -> PyResult<&str> {
|
) -> PyResult<&str> {
|
||||||
|
@ -215,8 +214,8 @@ fn module_with_fn(py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
# fn main() {}
|
# fn main() {}
|
||||||
```
|
```
|
||||||
|
|
||||||
If `need_module` is set, the first argument **must** be the `&PyModule`. It is then possible to interact with
|
If `pass_module` is set, the first argument **must** be the `&PyModule`. It is then possible to use the module
|
||||||
the module.
|
in the function body.
|
||||||
|
|
||||||
The same works for `#[pyfn]`:
|
The same works for `#[pyfn]`:
|
||||||
|
|
||||||
|
@ -227,7 +226,7 @@ use pyo3::prelude::*;
|
||||||
#[pymodule]
|
#[pymodule]
|
||||||
fn module_with_fn(py: Python, m: &PyModule) -> PyResult<()> {
|
fn module_with_fn(py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
|
|
||||||
#[pyfn(m, "module_name", need_module)]
|
#[pyfn(m, "module_name", pass_module)]
|
||||||
fn module_name(module: &PyModule) -> PyResult<&str> {
|
fn module_name(module: &PyModule) -> PyResult<&str> {
|
||||||
module.name()
|
module.name()
|
||||||
}
|
}
|
||||||
|
@ -236,6 +235,3 @@ fn module_with_fn(py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
|
|
||||||
# fn main() {}
|
# fn main() {}
|
||||||
```
|
```
|
||||||
|
|
||||||
Within Python, the name of the module that a function belongs to can be accessed through the `__module__`
|
|
||||||
attribute.
|
|
|
@ -158,7 +158,7 @@ pub fn add_fn_to_module(
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
syn::FnArg::Typed(ref cap) => {
|
syn::FnArg::Typed(ref cap) => {
|
||||||
if pyfn_attrs.need_module && i == 0 {
|
if pyfn_attrs.pass_module && i == 0 {
|
||||||
if let syn::Type::Reference(tyref) = cap.ty.as_ref() {
|
if let syn::Type::Reference(tyref) = cap.ty.as_ref() {
|
||||||
if let syn::Type::Path(typath) = tyref.elem.as_ref() {
|
if let syn::Type::Path(typath) = tyref.elem.as_ref() {
|
||||||
if typath
|
if typath
|
||||||
|
@ -174,7 +174,7 @@ pub fn add_fn_to_module(
|
||||||
}
|
}
|
||||||
return Err(syn::Error::new_spanned(
|
return Err(syn::Error::new_spanned(
|
||||||
cap,
|
cap,
|
||||||
"Expected &PyModule as first argument with `need_module`.",
|
"Expected &PyModule as first argument with `pass_module`.",
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
arguments.push(wrap_fn_argument(cap)?);
|
arguments.push(wrap_fn_argument(cap)?);
|
||||||
|
@ -204,7 +204,7 @@ pub fn add_fn_to_module(
|
||||||
|
|
||||||
let python_name = &spec.python_name;
|
let python_name = &spec.python_name;
|
||||||
|
|
||||||
let wrapper = function_c_wrapper(&func.sig.ident, &spec, pyfn_attrs.need_module);
|
let wrapper = function_c_wrapper(&func.sig.ident, &spec, pyfn_attrs.pass_module);
|
||||||
|
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
fn #function_wrapper_ident<'a>(
|
fn #function_wrapper_ident<'a>(
|
||||||
|
@ -247,11 +247,11 @@ pub fn add_fn_to_module(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate static function wrapper (PyCFunction, PyCFunctionWithKeywords)
|
/// Generate static function wrapper (PyCFunction, PyCFunctionWithKeywords)
|
||||||
fn function_c_wrapper(name: &Ident, spec: &method::FnSpec<'_>, need_module: bool) -> TokenStream {
|
fn function_c_wrapper(name: &Ident, spec: &method::FnSpec<'_>, pass_module: bool) -> TokenStream {
|
||||||
let names: Vec<Ident> = get_arg_names(&spec);
|
let names: Vec<Ident> = get_arg_names(&spec);
|
||||||
let cb;
|
let cb;
|
||||||
let slf_module;
|
let slf_module;
|
||||||
if need_module {
|
if pass_module {
|
||||||
cb = quote! {
|
cb = quote! {
|
||||||
#name(_slf, #(#names),*)
|
#name(_slf, #(#names),*)
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,7 +24,7 @@ pub struct PyFunctionAttr {
|
||||||
has_kw: bool,
|
has_kw: bool,
|
||||||
has_varargs: bool,
|
has_varargs: bool,
|
||||||
has_kwargs: bool,
|
has_kwargs: bool,
|
||||||
pub need_module: bool,
|
pub pass_module: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl syn::parse::Parse for PyFunctionAttr {
|
impl syn::parse::Parse for PyFunctionAttr {
|
||||||
|
@ -46,8 +46,8 @@ impl PyFunctionAttr {
|
||||||
|
|
||||||
pub fn add_item(&mut self, item: &NestedMeta) -> syn::Result<()> {
|
pub fn add_item(&mut self, item: &NestedMeta) -> syn::Result<()> {
|
||||||
match item {
|
match item {
|
||||||
NestedMeta::Meta(syn::Meta::Path(ref ident)) if ident.is_ident("need_module") => {
|
NestedMeta::Meta(syn::Meta::Path(ref ident)) if ident.is_ident("pass_module") => {
|
||||||
self.need_module = true;
|
self.pass_module = true;
|
||||||
}
|
}
|
||||||
NestedMeta::Meta(syn::Meta::Path(ref ident)) => self.add_work(item, ident)?,
|
NestedMeta::Meta(syn::Meta::Path(ref ident)) => self.add_work(item, ident)?,
|
||||||
NestedMeta::Meta(syn::Meta::NameValue(ref nv)) => {
|
NestedMeta::Meta(syn::Meta::NameValue(ref nv)) => {
|
||||||
|
|
|
@ -49,7 +49,7 @@ fn module_with_functions(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
Ok(42)
|
Ok(42)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyfn(m, "with_module", need_module)]
|
#[pyfn(m, "with_module", pass_module)]
|
||||||
fn with_module(module: &PyModule) -> PyResult<&str> {
|
fn with_module(module: &PyModule) -> PyResult<&str> {
|
||||||
module.name()
|
module.name()
|
||||||
}
|
}
|
||||||
|
@ -312,12 +312,12 @@ fn test_module_with_constant() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyfunction(need_module)]
|
#[pyfunction(pass_module)]
|
||||||
fn pyfunction_with_module(module: &PyModule) -> PyResult<&str> {
|
fn pyfunction_with_module(module: &PyModule) -> PyResult<&str> {
|
||||||
module.name()
|
module.name()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyfunction(need_module)]
|
#[pyfunction(pass_module)]
|
||||||
fn pyfunction_with_module_and_py<'a>(
|
fn pyfunction_with_module_and_py<'a>(
|
||||||
module: &'a PyModule,
|
module: &'a PyModule,
|
||||||
_python: Python<'a>,
|
_python: Python<'a>,
|
||||||
|
@ -325,12 +325,12 @@ fn pyfunction_with_module_and_py<'a>(
|
||||||
module.name()
|
module.name()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyfunction(need_module)]
|
#[pyfunction(pass_module)]
|
||||||
fn pyfunction_with_module_and_arg(module: &PyModule, string: String) -> PyResult<(&str, String)> {
|
fn pyfunction_with_module_and_arg(module: &PyModule, string: String) -> PyResult<(&str, String)> {
|
||||||
module.name().map(|s| (s, string))
|
module.name().map(|s| (s, string))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyfunction(need_module, string = "\"foo\"")]
|
#[pyfunction(pass_module, string = "\"foo\"")]
|
||||||
fn pyfunction_with_module_and_default_arg<'a>(
|
fn pyfunction_with_module_and_default_arg<'a>(
|
||||||
module: &'a PyModule,
|
module: &'a PyModule,
|
||||||
string: &str,
|
string: &str,
|
||||||
|
@ -338,7 +338,7 @@ fn pyfunction_with_module_and_default_arg<'a>(
|
||||||
module.name().map(|s| (s, string.into()))
|
module.name().map(|s| (s, string.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyfunction(need_module, args = "*", kwargs = "**")]
|
#[pyfunction(pass_module, args = "*", kwargs = "**")]
|
||||||
fn pyfunction_with_module_and_args_kwargs<'a>(
|
fn pyfunction_with_module_and_args_kwargs<'a>(
|
||||||
module: &'a PyModule,
|
module: &'a PyModule,
|
||||||
args: &PyTuple,
|
args: &PyTuple,
|
||||||
|
|
|
@ -2,7 +2,7 @@ use pyo3::prelude::*;
|
||||||
|
|
||||||
#[pymodule]
|
#[pymodule]
|
||||||
fn module(_py: Python, m: &PyModule) -> PyResult<()> {
|
fn module(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
#[pyfn(m, "with_module", need_module)]
|
#[pyfn(m, "with_module", pass_module)]
|
||||||
fn fail(string: &str, module: &PyModule) -> PyResult<&str> {
|
fn fail(string: &str, module: &PyModule) -> PyResult<&str> {
|
||||||
module.name()
|
module.name()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: Expected &PyModule as first argument with `need_module`.
|
error: Expected &PyModule as first argument with `pass_module`.
|
||||||
--> $DIR/invalid_need_module_arg_position.rs:6:13
|
--> $DIR/invalid_need_module_arg_position.rs:6:13
|
||||||
|
|
|
|
||||||
6 | fn fail(string: &str, module: &PyModule) -> PyResult<&str> {
|
6 | fn fail(string: &str, module: &PyModule) -> PyResult<&str> {
|
||||||
|
|
Loading…
Reference in a new issue