-
Notifications
You must be signed in to change notification settings - Fork 763
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add context manager example to user guide #1476
Conversation
A simple illustrative example on how to use context managers. I required this to use pymc3, which relies heavily on the context stack for modelling.
CI failure looks unrelated:
|
Thanks, will read later! Yes, the coverage failure is a regression in upstream Rust nightly that'll be fixed in good time ;) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks very much for writing this. You're right that the __exit__
part probably needs some expansion - I've added a comment below.
Thanks for your suggestion! I ran with it, and did a little eval with an undefined variable which will always throw an exception. Here's the output I get:
Your use of py.None() there results in a moved value, so I passed it by reference (even though that branch of the match will never execute, but it should be helpful as an example of what to do). However, I'm not certain that it's okay to pass py.None() by reference here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, just two final nits!
guide/src/python_from_rust.md
Outdated
|
||
"#, "objects.py", "objects").unwrap(); | ||
|
||
let house = custom_manager.call1("House", ("123 Main Street",)).unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be call_function1
, because we actually just deprecated call1
on master.
@birkenfeld strictly speaking this isn't a function, so maybe call_attribute
is better? Although I wonder if actually we should plan to remove module::call{_function}
etc. completely and instead just ask users to do .getattr("...")?.call1("...")?
etc? It's not much longer and doesn't suffer with naming ambiguity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you must mean call_method1
, so I've changed it to that!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See e065f9b - call_function1
is very hot off the press :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, you updated the documentation in that commit. Ignore earlier message if you saw it! I'll make the change!
Changes made, though I'm having trouble using that code in a little test bed I made. My cargo.toml has
[dependencies]
pyo3 = {git = "https://github.com/PyO3/pyo3.git", features=["auto-initialize"]}
That change is in master, so I figure it should be active. Did a cargo clean for fun.
cargo run
gives
Compiling proc-macro2 v1.0.24
Compiling unicode-xid v0.2.1
Compiling syn v1.0.62
Compiling proc-macro-hack v0.5.19
Compiling winapi v0.3.9
Compiling cfg-if v1.0.0
Compiling libc v0.2.88
Compiling unindent v0.1.7
Compiling smallvec v1.6.1
Compiling scopeguard v1.1.0
Compiling pyo3 v0.13.2 (https://github.com/PyO3/pyo3.git#b75a8f6e)
Compiling instant v0.1.9
Compiling lock_api v0.4.2
Compiling quote v1.0.9
Compiling paste-impl v0.1.18
Compiling paste v0.1.18
Compiling parking_lot_core v0.8.3
Compiling parking_lot v0.11.1
Compiling pyo3-macros-backend v0.13.2 (https://github.com/PyO3/pyo3.git#b75a8f6e)
Compiling indoc-impl v0.3.6
Compiling indoc v0.3.6
Compiling pyo3-macros v0.13.2 (https://github.com/PyO3/pyo3.git#b75a8f6e)
Compiling pyo3-context-example v0.1.0 (C:\Users\Matt\Documents\Development\Rust\pyo3-context-example)
error[E0599]: no method named `call_function0` found for reference `&PyAny` in the current scope
--> src\main.rs:22:15
|
22 | house.call_function0("__enter__").unwrap();
| ^^^^^^^^^^^^^^ method not found in `&PyAny`
error[E0599]: no method named `call_function1` found for reference `&PyAny` in the current scope
--> src\main.rs:30:23
|
30 | house.call_function1("__exit__", (&none, &none, &none)).unwrap();
| ^^^^^^^^^^^^^^ method not found in `&PyAny`
error[E0599]: no method named `call_function1` found for reference `&PyAny` in the current scope
--> src\main.rs:33:23
|
33 | house.call_function1(
| ^^^^^^^^^^^^^^ method not found in `&PyAny`
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0599`.
error: could not compile `pyo3-context-example`
To learn more, run the command again with --verbose.
I'm probably missing something?
// If the eval threw an exception we'll pass it through to the context manager. | ||
// Otherwise, __exit__ is called with empty arguments (Python "None"). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Simple and illustrative example 👍🏼 , thank you!
guide/src/python_from_rust.md
Outdated
else: | ||
print(f"Thank you for visiting {self.address}, come again soon!") | ||
|
||
"#, "objects.py", "objects").unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a nit, but is house.py
better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, changed!
As for In the end I wish we could implement some |
I have been abstractly dreaming recently about a macro to solve all this, spread args and kwargs and also use the Vectorcall optimization. E.g.: py_call!(module.attr(a, b, *args, **kwargs)); but that's probably a pipe dream 😄 |
Co-authored-by: David Hewitt <1939362+davidhewitt@users.noreply.github.com>
Co-authored-by: David Hewitt <1939362+davidhewitt@users.noreply.github.com>
👍 Thanks very much for this example; sorry for the complications caused by our API changes. |
A simple illustrative example on how to use context managers. I required this to use pymc3, which relies heavily on the context stack for modelling.
My example has a gap in that it calls
__exit__
with blank arguments. I don't honestly know how to use it without them, or if I even need to call it at all. If anyone wants to add some detail there, I'd appreciate it!