Skip to content

Commit e273ad9

Browse files
committed
Remove ct-python->inline-python-macros dependency.
1 parent 9692ac4 commit e273ad9

File tree

9 files changed

+345
-367
lines changed

9 files changed

+345
-367
lines changed

ct-python/Cargo.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,11 @@ edition = "2024"
77
repository = "https://github.com/m-ou-se/inline-python"
88
keywords = ["python", "macro", "generate", "compile-time"]
99

10+
[lib]
11+
proc-macro = true
12+
1013
[dependencies]
11-
inline-python-macros = { version = "0.14.1", path = "../macros" }
14+
pyo3 = { version = "0.24", default-features = false, features = ["auto-initialize"] }
15+
16+
[target.'cfg(unix)'.dependencies]
17+
libc = "0.2.71"

ct-python/src/lib.rs

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,71 @@
3838
//!
3939
//! [1]: https://docs.rs/inline-python/#syntax-issues
4040
41+
#![feature(proc_macro_span)]
42+
43+
use proc_macro::{Span, TokenStream};
44+
use pyo3::{PyObject, PyResult, Python, prelude::*};
45+
use std::{ffi::CString, ptr::null_mut, str::FromStr};
46+
47+
mod shared;
48+
use shared::*;
49+
4150
/// A block of compile-time executed Rust code generating Python code.
4251
///
4352
/// See [the crate's module level documentation](index.html) for examples.
44-
pub use inline_python_macros::ct_python;
53+
#[proc_macro]
54+
pub fn ct_python(input: TokenStream) -> TokenStream {
55+
ct_python_impl(input).unwrap_or_else(|e| e)
56+
}
57+
58+
fn ct_python_impl(input: TokenStream) -> Result<TokenStream, TokenStream> {
59+
let python = CString::new(python_from_macro(input.clone(), None)?).unwrap();
60+
let filename = CString::new(Span::call_site().file()).unwrap();
61+
62+
Python::with_gil(|py| {
63+
let code = compile_python(py, &python, &filename, input.clone())?;
64+
let output = run_and_capture(py, code).map_err(|err| python_error_to_compile_error(py, err, input))?;
65+
TokenStream::from_str(&output).map_err(|_| compile_error(None, "produced invalid Rust code"))
66+
})
67+
}
68+
69+
fn run_and_capture(py: Python, code: PyObject) -> PyResult<String> {
70+
#[cfg(unix)]
71+
let _ = ensure_libpython_symbols_loaded(py);
72+
73+
let globals = py.import("__main__")?.dict().copy()?;
74+
75+
let sys = py.import("sys")?;
76+
let stdout = py.import("io")?.getattr("StringIO")?.call0()?;
77+
let original_stdout = sys.dict().get_item("stdout")?;
78+
sys.dict().set_item("stdout", &stdout)?;
79+
80+
let result = unsafe {
81+
let ptr = pyo3::ffi::PyEval_EvalCode(code.as_ptr(), globals.as_ptr(), null_mut());
82+
PyObject::from_owned_ptr_or_err(py, ptr)
83+
};
84+
85+
sys.dict().set_item("stdout", original_stdout)?;
86+
87+
result?;
88+
89+
stdout.call_method0("getvalue")?.extract()
90+
}
91+
92+
#[cfg(unix)]
93+
fn ensure_libpython_symbols_loaded(py: Python) -> PyResult<()> {
94+
// On Unix, Rustc loads proc-macro crates with RTLD_LOCAL, which (at least
95+
// on Linux) means all their dependencies (in our case: libpython) don't
96+
// get their symbols made available globally either. This means that
97+
// loading modules (e.g. `import math`) will fail, as those modules refer
98+
// back to symbols of libpython.
99+
//
100+
// This function tries to (re)load the right version of libpython, but this
101+
// time with RTLD_GLOBAL enabled.
102+
let sysconfig = py.import("sysconfig")?;
103+
let libdir: String = sysconfig.getattr("get_config_var")?.call1(("LIBDIR",))?.extract()?;
104+
let so_name: String = sysconfig.getattr("get_config_var")?.call1(("INSTSONAME",))?.extract()?;
105+
let path = CString::new(format!("{libdir}/{so_name}")).unwrap();
106+
unsafe { libc::dlopen(path.as_ptr(), libc::RTLD_NOW | libc::RTLD_GLOBAL) };
107+
Ok(())
108+
}

ct-python/src/shared.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../macros/src/shared.rs

macros/Cargo.toml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,3 @@ proc-macro = true
1111

1212
[dependencies]
1313
pyo3 = { version = "0.24", default-features = false, features = ["auto-initialize"] }
14-
15-
[target.'cfg(unix)'.dependencies]
16-
libc = "0.2.71"

macros/src/embed_python.rs

Lines changed: 0 additions & 132 deletions
This file was deleted.

macros/src/error.rs

Lines changed: 0 additions & 68 deletions
This file was deleted.

0 commit comments

Comments
 (0)