Skip to content
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

pymodule: remove call_function etc. #1492

Merged
merged 1 commit into from Mar 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Expand Up @@ -23,7 +23,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Deprecate FFI definitions `PyModule_GetFilename`. [#1425](https://github.com/PyO3/pyo3/pull/1425)
- The `auto-initialize` feature is no longer enabled by default. [#1443](https://github.com/PyO3/pyo3/pull/1443)
- Change `PyCFunction::new()` and `PyCFunction::new_with_keywords()` to take `&'static str` arguments rather than implicitly copying (and leaking) them. [#1450](https://github.com/PyO3/pyo3/pull/1450)
- The `call/call0/call1` methods of `PyModule` have been renamed to `call_function` etc. for consistency with `call` and `call_method` on `PyAny`. The old names are still present, but deprecated. [#1467](https://github.com/PyO3/pyo3/pull/1467)
- Deprecate `PyModule` methods `call`, `call0`, `call1` and `get`. [#1492](https://github.com/PyO3/pyo3/pull/1492)

### Removed
- Remove deprecated exception names `BaseException` etc. [#1426](https://github.com/PyO3/pyo3/pull/1426)
Expand Down
17 changes: 9 additions & 8 deletions guide/src/python_from_rust.md
Expand Up @@ -115,7 +115,7 @@ use pyo3::prelude::*;
fn main() -> PyResult<()> {
Python::with_gil(|py| {
let builtins = PyModule::import(py, "builtins")?;
let total: i32 = builtins.call_function1("sum", (vec![1, 2, 3],))?.extract()?;
let total: i32 = builtins.getattr("sum")?.call1((vec![1, 2, 3],))?.extract()?;
assert_eq!(total, 6);
Ok(())
})
Expand Down Expand Up @@ -215,12 +215,12 @@ def leaky_relu(x, slope=0.01):
return x if x >= 0 else x * slope
"#, "activators.py", "activators")?;

let relu_result: f64 = activators.call_function1("relu", (-1.0,))?.extract()?;
let relu_result: f64 = activators.getattr("relu")?.call1((-1.0,))?.extract()?;
assert_eq!(relu_result, 0.0);

let kwargs = [("slope", 0.2)].into_py_dict(py);
let lrelu_result: f64 = activators
.call_function("leaky_relu", (-1.0,), Some(kwargs))?
.getattr("leaky_relu")?.call((-1.0,), Some(kwargs))?
.extract()?;
assert_eq!(lrelu_result, -0.2);
# Ok(())
Expand All @@ -239,7 +239,7 @@ Use context managers by directly invoking `__enter__` and `__exit__`.
use pyo3::prelude::*;
use pyo3::types::PyModule;

fn main() {
fn main() {
Python::with_gil(|py| {
let custom_manager = PyModule::from_code(py, r#"
class House(object):
Expand All @@ -254,14 +254,15 @@ class House(object):
print(f"Thank you for visiting {self.address}, come again soon!")

"#, "house.py", "house").unwrap();

let house = custom_manager.call_function1("House", ("123 Main Street",)).unwrap();

let house_class = custom_manager.getattr("House").unwrap();
let house = house_class.call1(("123 Main Street",)).unwrap();

house.call_method0("__enter__").unwrap();

let result = py.eval("undefined_variable + 1", None, None);
// If the eval threw an exception we'll pass it through to the context manager.

// If the eval threw an exception we'll pass it through to the context manager.
// Otherwise, __exit__ is called with empty arguments (Python "None").
match result {
Ok(_) => {
Expand Down
2 changes: 1 addition & 1 deletion src/exceptions.rs
Expand Up @@ -101,7 +101,7 @@ macro_rules! import_exception {
let imp = py
.import(stringify!($module))
.expect(concat!("Can not import module: ", stringify!($module)));
let cls = imp.get(stringify!($name)).expect(concat!(
let cls = imp.getattr(stringify!($name)).expect(concat!(
"Can not load exception class: {}.{}",
stringify!($module),
".",
Expand Down
99 changes: 40 additions & 59 deletions src/types/module.rs
Expand Up @@ -129,65 +129,6 @@ impl PyModule {
}
}

/// Calls a function in the module.
///
/// This is equivalent to the Python expression `module.name(*args, **kwargs)`.
pub fn call_function(
&self,
name: &str,
args: impl IntoPy<Py<PyTuple>>,
kwargs: Option<&PyDict>,
) -> PyResult<&PyAny> {
self.getattr(name)?.call(args, kwargs)
}

/// Calls a function in the module with only positional arguments.
///
/// This is equivalent to the Python expression `module.name(*args)`.
pub fn call_function1(&self, name: &str, args: impl IntoPy<Py<PyTuple>>) -> PyResult<&PyAny> {
self.getattr(name)?.call1(args)
}

/// Calls a function in the module without arguments.
///
/// This is equivalent to the Python expression `module.name()`.
pub fn call_function0(&self, name: &str) -> PyResult<&PyAny> {
self.getattr(name)?.call0()
}

#[deprecated(since = "0.14.0", note = "Renamed to call_function() for consistency.")]
pub fn call(
&self,
name: &str,
args: impl IntoPy<Py<PyTuple>>,
kwargs: Option<&PyDict>,
) -> PyResult<&PyAny> {
self.call_function(name, args, kwargs)
}

#[deprecated(
since = "0.14.0",
note = "Renamed to call_function1() for consistency."
)]
pub fn call1(&self, name: &str, args: impl IntoPy<Py<PyTuple>>) -> PyResult<&PyAny> {
self.call_function1(name, args)
}

#[deprecated(
since = "0.14.0",
note = "Renamed to call_function0() for consistency."
)]
pub fn call0(&self, name: &str) -> PyResult<&PyAny> {
self.call_function0(name)
}

/// Gets a member from the module.
///
/// This is equivalent to the Python expression `module.name`.
pub fn get(&self, name: &str) -> PyResult<&PyAny> {
self.getattr(name)
}

/// Adds a member to the module.
///
/// This is a convenience function which can be used from the module's initialization function.
Expand Down Expand Up @@ -310,4 +251,44 @@ impl PyModule {
let name = fun.getattr("__name__")?.extract()?;
self.add(name, fun)
}

/// Calls a function in the module.
///
/// This is equivalent to the Python expression `module.name(*args, **kwargs)`.
#[deprecated(
since = "0.14.0",
note = "use getattr(name)?.call(args, kwargs) instead"
)]
pub fn call(
&self,
name: &str,
args: impl IntoPy<Py<PyTuple>>,
kwargs: Option<&PyDict>,
) -> PyResult<&PyAny> {
self.getattr(name)?.call(args, kwargs)
}

/// Calls a function in the module with only positional arguments.
///
/// This is equivalent to the Python expression `module.name(*args)`.
#[deprecated(since = "0.14.0", note = "use getattr(name)?.call1(args) instead")]
pub fn call1(&self, name: &str, args: impl IntoPy<Py<PyTuple>>) -> PyResult<&PyAny> {
self.getattr(name)?.call1(args)
}

/// Calls a function in the module without arguments.
///
/// This is equivalent to the Python expression `module.name()`.
#[deprecated(since = "0.14.0", note = "use getattr(name)?.call0() instead")]
pub fn call0(&self, name: &str) -> PyResult<&PyAny> {
self.getattr(name)?.call0()
}

/// Gets a member from the module.
///
/// This is equivalent to the Python expression `module.name`.
#[deprecated(since = "0.14.0", note = "use getattr(name) instead")]
pub fn get(&self, name: &str) -> PyResult<&PyAny> {
self.getattr(name)
}
}
12 changes: 7 additions & 5 deletions src/types/num.rs
Expand Up @@ -489,12 +489,12 @@ mod bigint_conversion {
.unwrap();
// Checks if Python Long -> Rust BigUint conversion is correct if N is small
let py_result: BigUint =
FromPyObject::extract(fib.call_function1("fib", (400,)).unwrap()).unwrap();
FromPyObject::extract(fib.getattr("fib").unwrap().call1((400,)).unwrap()).unwrap();
assert_eq!(rs_result, py_result);
// Checks if Python Long -> Rust BigUint conversion is correct if N is large
let rs_result: BigUint = rust_fib(2000);
let py_result: BigUint =
FromPyObject::extract(fib.call_function1("fib", (2000,)).unwrap()).unwrap();
FromPyObject::extract(fib.getattr("fib").unwrap().call1((2000,)).unwrap()).unwrap();
assert_eq!(rs_result, py_result);
}

Expand All @@ -512,12 +512,14 @@ mod bigint_conversion {
.unwrap();
// Checks if Python Long -> Rust BigInt conversion is correct if N is small
let py_result: BigInt =
FromPyObject::extract(fib.call_function1("fib_neg", (400,)).unwrap()).unwrap();
FromPyObject::extract(fib.getattr("fib_neg").unwrap().call1((400,)).unwrap())
.unwrap();
assert_eq!(rs_result, py_result);
// Checks if Python Long -> Rust BigInt conversion is correct if N is large
let rs_result = rust_fib::<BigInt>(2000) * -1;
let py_result: BigInt =
FromPyObject::extract(fib.call_function1("fib_neg", (2000,)).unwrap()).unwrap();
FromPyObject::extract(fib.getattr("fib_neg").unwrap().call1((2000,)).unwrap())
.unwrap();
assert_eq!(rs_result, py_result);
}

Expand Down Expand Up @@ -551,7 +553,7 @@ mod bigint_conversion {
let py = gil.python();
let fib = python_fib(py);
let zero: BigInt =
FromPyObject::extract(fib.call_function1("fib", (0,)).unwrap()).unwrap();
FromPyObject::extract(fib.getattr("fib").unwrap().call1((0,)).unwrap()).unwrap();
assert_eq!(zero, BigInt::from(0));
}

Expand Down
4 changes: 2 additions & 2 deletions tests/test_datetime.rs
Expand Up @@ -12,7 +12,7 @@ fn _get_subclasses<'p>(
// Import the class from Python and create some subclasses
let datetime = py.import("datetime")?;

let locals = [(py_type, datetime.get(py_type)?)].into_py_dict(*py);
let locals = [(py_type, datetime.getattr(py_type)?)].into_py_dict(*py);

let make_subclass_py = format!("class Subklass({}):\n pass", py_type);

Expand Down Expand Up @@ -108,7 +108,7 @@ fn test_datetime_utc() {
let gil = Python::acquire_gil();
let py = gil.python();
let datetime = py.import("datetime").map_err(|e| e.print(py)).unwrap();
let timezone = datetime.get("timezone").unwrap();
let timezone = datetime.getattr("timezone").unwrap();
let utc = timezone.getattr("utc").unwrap().to_object(py);

let dt = PyDateTime::new(py, 2018, 1, 1, 0, 0, 0, 0, Some(&utc)).unwrap();
Expand Down
2 changes: 1 addition & 1 deletion tests/test_module.rs
Expand Up @@ -141,7 +141,7 @@ fn test_module_from_code() {
.expect("Module code should be loaded");

let add_func = adder_mod
.get("add")
.getattr("add")
.expect("Add function should be in the module")
.to_object(py);

Expand Down