Skip to content

Commit

Permalink
module::from_code takes CStr instead str
Browse files Browse the repository at this point in the history
  • Loading branch information
bschoenmaeckers committed Aug 13, 2024
1 parent ec245a9 commit 4d34e37
Show file tree
Hide file tree
Showing 11 changed files with 165 additions and 114 deletions.
35 changes: 19 additions & 16 deletions guide/src/conversions/traits.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ the Python object, i.e. `obj.getattr("my_string")`, and call `extract()` on the

```rust
use pyo3::prelude::*;
use pyo3_ffi::c_str;

#[derive(FromPyObject)]
struct RustyStruct {
Expand All @@ -56,11 +57,11 @@ struct RustyStruct {
# Python::with_gil(|py| -> PyResult<()> {
# let module = PyModule::from_code(
# py,
# "class Foo:
# c_str!("class Foo:
# def __init__(self):
# self.my_string = 'test'",
# "",
# "",
# self.my_string = 'test'"),
# c_str!(""),
# c_str!(""),
# )?;
#
# let class = module.getattr("Foo")?;
Expand Down Expand Up @@ -100,6 +101,7 @@ The argument passed to `getattr` and `get_item` can also be configured:

```rust
use pyo3::prelude::*;
use pyo3_ffi::c_str;

#[derive(FromPyObject)]
struct RustyStruct {
Expand All @@ -113,12 +115,12 @@ struct RustyStruct {
# Python::with_gil(|py| -> PyResult<()> {
# let module = PyModule::from_code(
# py,
# "class Foo(dict):
# c_str!("class Foo(dict):
# def __init__(self):
# self.name = 'test'
# self['key'] = 'test2'",
# "",
# "",
# self['key'] = 'test2'"),
# c_str!(""),
# c_str!(""),
# )?;
#
# let class = module.getattr("Foo")?;
Expand Down Expand Up @@ -262,6 +264,7 @@ attribute can be applied to single-field-variants.

```rust
use pyo3::prelude::*;
use pyo3_ffi::c_str;

#[derive(FromPyObject)]
# #[derive(Debug)]
Expand Down Expand Up @@ -341,13 +344,13 @@ enum RustyEnum<'py> {
# {
# let module = PyModule::from_code(
# py,
# "class Foo(dict):
# c_str!("class Foo(dict):
# def __init__(self):
# self.x = 0
# self.y = 1
# self.z = 2",
# "",
# "",
# self.z = 2"),
# c_str!(""),
# c_str!(""),
# )?;
#
# let class = module.getattr("Foo")?;
Expand All @@ -366,12 +369,12 @@ enum RustyEnum<'py> {
# {
# let module = PyModule::from_code(
# py,
# "class Foo(dict):
# c_str!("class Foo(dict):
# def __init__(self):
# self.x = 3
# self.y = 4",
# "",
# "",
# self.y = 4"),
# c_str!(""),
# c_str!(""),
# )?;
#
# let class = module.getattr("Foo")?;
Expand Down
35 changes: 20 additions & 15 deletions guide/src/python-from-rust/calling-existing-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,21 +106,22 @@ to this function!

```rust
use pyo3::{prelude::*, types::IntoPyDict};
use pyo3_ffi::c_str;

# fn main() -> PyResult<()> {
Python::with_gil(|py| {
let activators = PyModule::from_code(
py,
r#"
c_str!(r#"
def relu(x):
"""see https://en.wikipedia.org/wiki/Rectifier_(neural_networks)"""
return max(0.0, x)
def leaky_relu(x, slope=0.01):
return x if x >= 0 else x * slope
"#,
"activators.py",
"activators",
"#),
c_str!("activators.py"),
c_str!("activators"),
)?;

let relu_result: f64 = activators.getattr("relu")?.call1((-1.0,))?.extract()?;
Expand Down Expand Up @@ -249,16 +250,17 @@ The example below shows:
`src/main.rs`:
```rust,ignore
use pyo3::prelude::*;
use pyo3_ffi::c_str;
fn main() -> PyResult<()> {
let py_foo = include_str!(concat!(
let py_foo = c_str!(include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/python_app/utils/foo.py"
));
let py_app = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/python_app/app.py"));
)));
let py_app = c_str!(include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/python_app/app.py")));
let from_python = Python::with_gil(|py| -> PyResult<Py<PyAny>> {
PyModule::from_code(py, py_foo, "utils.foo", "utils.foo")?;
let app: Py<PyAny> = PyModule::from_code(py, py_app, "", "")?
PyModule::from_code(py, py_foo, c_str!("utils.foo"), c_str!("utils.foo"))?;
let app: Py<PyAny> = PyModule::from_code(py, py_app, c_str!(""), c_str!(""))?
.getattr("run")?
.into();
app.call0(py)
Expand All @@ -283,19 +285,21 @@ that directory is `/usr/share/python_app`).
```rust,no_run
use pyo3::prelude::*;
use pyo3::types::PyList;
use pyo3_ffi::c_str;
use std::fs;
use std::path::Path;
use std::ffi::CString;
fn main() -> PyResult<()> {
let path = Path::new("/usr/share/python_app");
let py_app = fs::read_to_string(path.join("app.py"))?;
let py_app = CString::new(fs::read_to_string(path.join("app.py"))?)?;
let from_python = Python::with_gil(|py| -> PyResult<Py<PyAny>> {
let syspath = py
.import("sys")?
.getattr("path")?
.downcast_into::<PyList>()?;
syspath.insert(0, &path)?;
let app: Py<PyAny> = PyModule::from_code(py, &py_app, "", "")?
let app: Py<PyAny> = PyModule::from_code(py, py_app.as_c_str(), c_str!(""), c_str!(""))?
.getattr("run")?
.into();
app.call0(py)
Expand All @@ -316,12 +320,13 @@ Use context managers by directly invoking `__enter__` and `__exit__`.

```rust
use pyo3::prelude::*;
use pyo3_ffi::c_str;

fn main() {
Python::with_gil(|py| {
let custom_manager = PyModule::from_code(
py,
r#"
c_str!(r#"
class House(object):
def __init__(self, address):
self.address = address
Expand All @@ -333,9 +338,9 @@ class House(object):
else:
print(f"Thank you for visiting {self.address}, come again soon!")
"#,
"house.py",
"house",
"#),
c_str!("house.py"),
c_str!("house"),
)
.unwrap();

Expand Down
18 changes: 10 additions & 8 deletions guide/src/python-from-rust/function-calls.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ The example below calls a Python function behind a `PyObject` (aka `Py<PyAny>`)
```rust
use pyo3::prelude::*;
use pyo3::types::PyTuple;
use pyo3_ffi::c_str;

fn main() -> PyResult<()> {
let arg1 = "arg1";
Expand All @@ -28,15 +29,15 @@ fn main() -> PyResult<()> {
Python::with_gil(|py| {
let fun: Py<PyAny> = PyModule::from_code(
py,
"def example(*args, **kwargs):
c_str!("def example(*args, **kwargs):
if args != ():
print('called with args', args)
if kwargs != {}:
print('called with kwargs', kwargs)
if args == () and kwargs == {}:
print('called with no arguments')",
"",
"",
print('called with no arguments')"),
c_str!(""),
c_str!(""),
)?
.getattr("example")?
.into();
Expand Down Expand Up @@ -64,6 +65,7 @@ For the `call` and `call_method` APIs, `kwargs` are `Option<&Bound<'py, PyDict>>
use pyo3::prelude::*;
use pyo3::types::IntoPyDict;
use std::collections::HashMap;
use pyo3_ffi::c_str;

fn main() -> PyResult<()> {
let key1 = "key1";
Expand All @@ -74,15 +76,15 @@ fn main() -> PyResult<()> {
Python::with_gil(|py| {
let fun: Py<PyAny> = PyModule::from_code(
py,
"def example(*args, **kwargs):
c_str!("def example(*args, **kwargs):
if args != ():
print('called with args', args)
if kwargs != {}:
print('called with kwargs', kwargs)
if args == () and kwargs == {}:
print('called with no arguments')",
"",
"",
print('called with no arguments')"),
c_str!(""),
c_str!(""),
)?
.getattr("example")?
.into();
Expand Down
3 changes: 2 additions & 1 deletion pyo3-benches/benches/bench_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ use std::hint::black_box;
use codspeed_criterion_compat::{criterion_group, criterion_main, Bencher, Criterion};

use pyo3::prelude::*;
use pyo3_ffi::c_str;

macro_rules! test_module {
($py:ident, $code:literal) => {
PyModule::from_code($py, $code, file!(), "test_module")
PyModule::from_code($py, c_str!($code), c_str!(file!()), c_str!("test_module"))
.expect("module creation failed")
};
}
Expand Down
7 changes: 4 additions & 3 deletions src/conversions/num_bigint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ mod tests {
use super::*;
use crate::types::{PyDict, PyModule};
use indoc::indoc;
use pyo3_ffi::c_str;

fn rust_fib<T>() -> impl Iterator<Item = T>
where
Expand Down Expand Up @@ -441,16 +442,16 @@ mod tests {
}

fn python_index_class(py: Python<'_>) -> Bound<'_, PyModule> {
let index_code = indoc!(
let index_code = c_str!(indoc!(
r#"
class C:
def __init__(self, x):
self.x = x
def __index__(self):
return self.x
"#
);
PyModule::from_code(py, index_code, "index.py", "index").unwrap()
));
PyModule::from_code(py, index_code, c_str!("index.py"), c_str!("index")).unwrap()
}

#[test]
Expand Down
41 changes: 25 additions & 16 deletions src/conversions/num_complex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ complex_conversion!(f64);
mod tests {
use super::*;
use crate::types::{complex::PyComplexMethods, PyModule};
use pyo3_ffi::c_str;

#[test]
fn from_complex() {
Expand Down Expand Up @@ -235,16 +236,18 @@ mod tests {
Python::with_gil(|py| {
let module = PyModule::from_code(
py,
r#"
c_str!(
r#"
class A:
def __complex__(self): return 3.0+1.2j
class B:
def __float__(self): return 3.0
class C:
def __index__(self): return 3
"#,
"test.py",
"test",
"#
),
c_str!("test.py"),
c_str!("test"),
)
.unwrap();
let from_complex = module.getattr("A").unwrap().call0().unwrap();
Expand Down Expand Up @@ -273,7 +276,8 @@ class C:
Python::with_gil(|py| {
let module = PyModule::from_code(
py,
r#"
c_str!(
r#"
class First: pass
class ComplexMixin:
def __complex__(self): return 3.0+1.2j
Expand All @@ -284,9 +288,10 @@ class IndexMixin:
class A(First, ComplexMixin): pass
class B(First, FloatMixin): pass
class C(First, IndexMixin): pass
"#,
"test.py",
"test",
"#
),
c_str!("test.py"),
c_str!("test"),
)
.unwrap();
let from_complex = module.getattr("A").unwrap().call0().unwrap();
Expand Down Expand Up @@ -317,14 +322,16 @@ class C(First, IndexMixin): pass
Python::with_gil(|py| {
let module = PyModule::from_code(
py,
r#"
c_str!(
r#"
class A:
@property
def __complex__(self):
return lambda: 3.0+1.2j
"#,
"test.py",
"test",
"#
),
c_str!("test.py"),
c_str!("test"),
)
.unwrap();
let obj = module.getattr("A").unwrap().call0().unwrap();
Expand All @@ -340,14 +347,16 @@ class A:
Python::with_gil(|py| {
let module = PyModule::from_code(
py,
r#"
c_str!(
r#"
class MyComplex:
def __call__(self): return 3.0+1.2j
class A:
__complex__ = MyComplex()
"#,
"test.py",
"test",
"#
),
c_str!("test.py"),
c_str!("test"),
)
.unwrap();
let obj = module.getattr("A").unwrap().call0().unwrap();
Expand Down
Loading

0 comments on commit 4d34e37

Please sign in to comment.