diff --git a/Cargo.lock b/Cargo.lock index 174d436..98af8ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4391,6 +4391,7 @@ dependencies = [ name = "processing_pyo3" version = "0.1.0" dependencies = [ + "bevy", "glfw", "processing", "pyo3", diff --git a/crates/processing_pyo3/Cargo.toml b/crates/processing_pyo3/Cargo.toml index e9fca49..1f83db5 100644 --- a/crates/processing_pyo3/Cargo.toml +++ b/crates/processing_pyo3/Cargo.toml @@ -13,7 +13,11 @@ crate-type = ["cdylib"] [dependencies] pyo3 = "0.27.0" processing = { workspace = true } -glfw = "0.60.0" +bevy = { workspace = true } +glfw = { version = "0.60.0"} + +[target.'cfg(target_os = "macos")'.dependencies] +glfw = { version = "0.60.0", features = ["static-link"] } [target.'cfg(target_os = "linux")'.dependencies] glfw = { version = "0.60.0", features = ["wayland"] } diff --git a/crates/processing_pyo3/README.md b/crates/processing_pyo3/README.md index d66e7b2..3e28caa 100644 --- a/crates/processing_pyo3/README.md +++ b/crates/processing_pyo3/README.md @@ -7,6 +7,11 @@ Prototype for python bindings to libprocessing ### Install venv and maturin Follow these [installation instructions](https://pyo3.rs/v0.27.2/getting-started.html) +#### macOS +```bash +brew install glfw +``` + ### Running code ``` $ maturin develop diff --git a/crates/processing_pyo3/examples/rectangle.py b/crates/processing_pyo3/examples/rectangle.py new file mode 100644 index 0000000..cce3fe1 --- /dev/null +++ b/crates/processing_pyo3/examples/rectangle.py @@ -0,0 +1,15 @@ +from processing import * + +# TODO: this should be in a setup function +size(800, 600) + +def draw(): + background(220) + + fill(255, 0, 100) + stroke(0) + stroke_weight(2) + rect(100, 100, 200, 150) + +# TODO: this should happen implicitly on module load somehow +run(draw) diff --git a/crates/processing_pyo3/pyproject.toml b/crates/processing_pyo3/pyproject.toml index 773e032..24526db 100644 --- a/crates/processing_pyo3/pyproject.toml +++ b/crates/processing_pyo3/pyproject.toml @@ -12,5 +12,8 @@ classifiers = [ ] dynamic = ["version"] +[dependency-groups] +dev = ["maturin>=1.10,<2.0"] + [tool.maturin] manifest-path = "Cargo.toml" diff --git a/crates/processing_pyo3/src/graphics.rs b/crates/processing_pyo3/src/graphics.rs new file mode 100644 index 0000000..257ca4e --- /dev/null +++ b/crates/processing_pyo3/src/graphics.rs @@ -0,0 +1,132 @@ +use bevy::prelude::Entity; +use processing::prelude::*; +use pyo3::exceptions::PyRuntimeError; +use pyo3::prelude::*; +use pyo3::types::PyAny; + +use crate::glfw::GlfwContext; + +#[pyclass(unsendable)] +pub struct Graphics { + glfw_ctx: GlfwContext, + surface: Entity, +} + +#[pymethods] +impl Graphics { + #[new] + pub fn new(width: u32, height: u32) -> PyResult { + let glfw_ctx = GlfwContext::new(width, height) + .map_err(|e| PyRuntimeError::new_err(format!("{e}")))?; + + init().map_err(|e| PyRuntimeError::new_err(format!("{e}")))?; + + let window_handle = glfw_ctx.get_window(); + let display_handle = glfw_ctx.get_display(); + let surface = surface_create(window_handle, display_handle, width, height, 1.0) + .map_err(|e| PyRuntimeError::new_err(format!("{e}")))?; + + Ok(Self { glfw_ctx, surface }) + } + + pub fn background(&self, args: Vec) -> PyResult<()> { + let (r, g, b, a) = parse_color(&args)?; + let color = bevy::color::Color::srgba(r, g, b, a); + record_command(self.surface, DrawCommand::BackgroundColor(color)) + .map_err(|e| PyRuntimeError::new_err(format!("{e}"))) + } + + pub fn fill(&self, args: Vec) -> PyResult<()> { + let (r, g, b, a) = parse_color(&args)?; + let color = bevy::color::Color::srgba(r, g, b, a); + record_command(self.surface, DrawCommand::Fill(color)) + .map_err(|e| PyRuntimeError::new_err(format!("{e}"))) + } + + pub fn no_fill(&self) -> PyResult<()> { + record_command(self.surface, DrawCommand::NoFill) + .map_err(|e| PyRuntimeError::new_err(format!("{e}"))) + } + + pub fn stroke(&self, args: Vec) -> PyResult<()> { + let (r, g, b, a) = parse_color(&args)?; + let color = bevy::color::Color::srgba(r, g, b, a); + record_command(self.surface, DrawCommand::StrokeColor(color)) + .map_err(|e| PyRuntimeError::new_err(format!("{e}"))) + } + + pub fn no_stroke(&self) -> PyResult<()> { + record_command(self.surface, DrawCommand::NoStroke) + .map_err(|e| PyRuntimeError::new_err(format!("{e}"))) + } + + pub fn stroke_weight(&self, weight: f32) -> PyResult<()> { + record_command(self.surface, DrawCommand::StrokeWeight(weight)) + .map_err(|e| PyRuntimeError::new_err(format!("{e}"))) + } + + pub fn rect(&self, x: f32, y: f32, w: f32, h: f32, tl: f32, tr: f32, br: f32, bl: f32) -> PyResult<()> { + record_command( + self.surface, + DrawCommand::Rect { x, y, w, h, radii: [tl, tr, br, bl] }, + ) + .map_err(|e| PyRuntimeError::new_err(format!("{e}"))) + } + + pub fn run(&mut self, draw_fn: Option>) -> PyResult<()> { + loop { + if !self.glfw_ctx.poll_events() { + break; + } + + begin_draw(self.surface) + .map_err(|e| PyRuntimeError::new_err(format!("{e}")))?; + + if let Some(ref draw) = draw_fn { + Python::attach(|py| { + draw.call0(py).map_err(|e| PyRuntimeError::new_err(format!("{e}"))) + })?; + } + + end_draw(self.surface) + .map_err(|e| PyRuntimeError::new_err(format!("{e}")))?; + } + Ok(()) + } +} + +// TODO: a real color type. or color parser? idk. color is confusing. let's think +// about how to expose different color spaces in an idiomatic pythonic way +fn parse_color(args: &[f32]) -> PyResult<(f32, f32, f32, f32)> { + match args.len() { + 1 => { + let v = args[0] / 255.0; + Ok((v, v, v, 1.0)) + } + 2 => { + let v = args[0] / 255.0; + Ok((v, v, v, args[1] / 255.0)) + } + 3 => Ok((args[0] / 255.0, args[1] / 255.0, args[2] / 255.0, 1.0)), + 4 => Ok((args[0] / 255.0, args[1] / 255.0, args[2] / 255.0, args[3] / 255.0)), + _ => Err(PyRuntimeError::new_err("color requires 1-4 arguments")), + } +} + +pub fn get_graphics<'py>(module: &Bound<'py, PyModule>) -> PyResult> { + module + .getattr("_graphics")? + .cast_into::() + .map_err(|_| PyRuntimeError::new_err("no graphics context"))? + .try_borrow() + .map_err(|e| PyRuntimeError::new_err(format!("{e}"))) +} + +pub fn get_graphics_mut<'py>(module: &Bound<'py, PyModule>) -> PyResult> { + module + .getattr("_graphics")? + .cast_into::() + .map_err(|_| PyRuntimeError::new_err("no graphics context"))? + .try_borrow_mut() + .map_err(|e| PyRuntimeError::new_err(format!("{e}"))) +} diff --git a/crates/processing_pyo3/src/lib.rs b/crates/processing_pyo3/src/lib.rs index 9f1abef..6526e6a 100644 --- a/crates/processing_pyo3/src/lib.rs +++ b/crates/processing_pyo3/src/lib.rs @@ -1,40 +1,87 @@ +//! # processing_pyo3 +//! +//! A Python module that exposes libprocessing using pyo3. + +//! In processing4 Java, the sketch runs implicitly inside a class that extends PApplet and +//! executes main. This means that all PAplet methods can be called directly without an explicit +//! receiver. +//! +//! To allow Python users to create a similar experience, we provide module-level +//! functions that forward to a singleton Graphics object behind the scenes. mod glfw; +mod graphics; + +use graphics::{get_graphics, get_graphics_mut, Graphics}; use pyo3::prelude::*; +use pyo3::types::PyAny; #[pymodule] -mod processing { - use crate::glfw::GlfwContext; - use processing::prelude::*; - use pyo3::prelude::*; - - /// create surface - #[pyfunction] - fn size(width: u32, height: u32) -> PyResult { - let mut glfw_ctx = GlfwContext::new(400, 400).unwrap(); - init().unwrap(); - - let window_handle = glfw_ctx.get_window(); - let display_handle = glfw_ctx.get_display(); - let surface = surface_create(window_handle, display_handle, width, height, 1.0).unwrap(); - - while glfw_ctx.poll_events() { - begin_draw(surface).unwrap(); - - record_command( - surface, - DrawCommand::Rect { - x: 10.0, - y: 10.0, - w: 100.0, - h: 100.0, - radii: [0.0, 0.0, 0.0, 0.0], - }, - ) - .unwrap(); - - end_draw(surface).unwrap(); - } - - Ok("OK".to_string()) - } +fn processing(m: &Bound<'_, PyModule>) -> PyResult<()> { + m.add_class::()?; + m.add_function(wrap_pyfunction!(size, m)?)?; + m.add_function(wrap_pyfunction!(run, m)?)?; + m.add_function(wrap_pyfunction!(background, m)?)?; + m.add_function(wrap_pyfunction!(fill, m)?)?; + m.add_function(wrap_pyfunction!(no_fill, m)?)?; + m.add_function(wrap_pyfunction!(stroke, m)?)?; + m.add_function(wrap_pyfunction!(no_stroke, m)?)?; + m.add_function(wrap_pyfunction!(stroke_weight, m)?)?; + m.add_function(wrap_pyfunction!(rect, m)?)?; + Ok(()) +} + +#[pyfunction] +#[pyo3(pass_module)] +fn size(module: &Bound<'_, PyModule>, width: u32, height: u32) -> PyResult<()> { + let graphics = Graphics::new(width, height)?; + module.setattr("_graphics", graphics)?; + Ok(()) +} + +#[pyfunction] +#[pyo3(pass_module, signature = (draw_fn=None))] +fn run(module: &Bound<'_, PyModule>, draw_fn: Option>) -> PyResult<()> { + get_graphics_mut(module)?.run(draw_fn) +} + +#[pyfunction] +#[pyo3(pass_module, signature = (*args))] +fn background(module: &Bound<'_, PyModule>, args: Vec) -> PyResult<()> { + get_graphics(module)?.background(args) +} + +#[pyfunction] +#[pyo3(pass_module, signature = (*args))] +fn fill(module: &Bound<'_, PyModule>, args: Vec) -> PyResult<()> { + get_graphics(module)?.fill(args) +} + +#[pyfunction] +#[pyo3(pass_module)] +fn no_fill(module: &Bound<'_, PyModule>) -> PyResult<()> { + get_graphics(module)?.no_fill() +} + +#[pyfunction] +#[pyo3(pass_module, signature = (*args))] +fn stroke(module: &Bound<'_, PyModule>, args: Vec) -> PyResult<()> { + get_graphics(module)?.stroke(args) +} + +#[pyfunction] +#[pyo3(pass_module)] +fn no_stroke(module: &Bound<'_, PyModule>) -> PyResult<()> { + get_graphics(module)?.no_stroke() +} + +#[pyfunction] +#[pyo3(pass_module)] +fn stroke_weight(module: &Bound<'_, PyModule>, weight: f32) -> PyResult<()> { + get_graphics(module)?.stroke_weight(weight) +} + +#[pyfunction] +#[pyo3(pass_module, signature = (x, y, w, h, tl=0.0, tr=0.0, br=0.0, bl=0.0))] +fn rect(module: &Bound<'_, PyModule>, x: f32, y: f32, w: f32, h: f32, tl: f32, tr: f32, br: f32, bl: f32) -> PyResult<()> { + get_graphics(module)?.rect(x, y, w, h, tl, tr, br, bl) } diff --git a/crates/processing_pyo3/uv.lock b/crates/processing_pyo3/uv.lock new file mode 100644 index 0000000..bc6a9f3 --- /dev/null +++ b/crates/processing_pyo3/uv.lock @@ -0,0 +1,90 @@ +version = 1 +revision = 3 +requires-python = ">=3.8" + +[[package]] +name = "maturin" +version = "1.10.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/02/44/c593afce7d418ae6016b955c978055232359ad28c707a9ac6643fc60512d/maturin-1.10.2.tar.gz", hash = "sha256:259292563da89850bf8f7d37aa4ddba22905214c1e180b1c8f55505dfd8c0e81", size = 217835, upload-time = "2025-11-19T11:53:17.348Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/15/74/7f7e93019bb71aa072a7cdf951cbe4c9a8d5870dd86c66ec67002153487f/maturin-1.10.2-py3-none-linux_armv6l.whl", hash = "sha256:11c73815f21a755d2129c410e6cb19dbfacbc0155bfc46c706b69930c2eb794b", size = 8763201, upload-time = "2025-11-19T11:52:42.98Z" }, + { url = "https://files.pythonhosted.org/packages/4a/85/1d1b64dbb6518ee633bfde8787e251ae59428818fea7a6bdacb8008a09bd/maturin-1.10.2-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:7fbd997c5347649ee7987bd05a92bd5b8b07efa4ac3f8bcbf6196e07eb573d89", size = 17072583, upload-time = "2025-11-19T11:52:45.636Z" }, + { url = "https://files.pythonhosted.org/packages/7c/45/2418f0d6e1cbdf890205d1dc73ebea6778bb9ce80f92e866576c701ded72/maturin-1.10.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:e3ce9b2ad4fb9c341f450a6d32dc3edb409a2d582a81bc46ba55f6e3b6196b22", size = 8827021, upload-time = "2025-11-19T11:52:48.143Z" }, + { url = "https://files.pythonhosted.org/packages/7f/83/14c96ddc93b38745d8c3b85126f7d78a94f809a49dc9644bb22b0dc7b78c/maturin-1.10.2-py3-none-manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686.whl", hash = "sha256:f0d1b7b5f73c8d30a7e71cd2a2189a7f0126a3a3cd8b3d6843e7e1d4db50f759", size = 8751780, upload-time = "2025-11-19T11:52:51.613Z" }, + { url = "https://files.pythonhosted.org/packages/46/8d/753148c0d0472acd31a297f6d11c3263cd2668d38278ed29d523625f7290/maturin-1.10.2-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:efcd496a3202ffe0d0489df1f83d08b91399782fb2dd545d5a1e7bf6fd81af39", size = 9241884, upload-time = "2025-11-19T11:52:53.946Z" }, + { url = "https://files.pythonhosted.org/packages/b9/f9/f5ca9fe8cad70cac6f3b6008598cc708f8a74dd619baced99784a6253f23/maturin-1.10.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:a41ec70d99e27c05377be90f8e3c3def2a7bae4d0d9d5ea874aaf2d1da625d5c", size = 8671736, upload-time = "2025-11-19T11:52:57.133Z" }, + { url = "https://files.pythonhosted.org/packages/0a/76/f59cbcfcabef0259c3971f8b5754c85276a272028d8363386b03ec4e9947/maturin-1.10.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:07a82864352feeaf2167247c8206937ef6c6ae9533025d416b7004ade0ea601d", size = 8633475, upload-time = "2025-11-19T11:53:00.389Z" }, + { url = "https://files.pythonhosted.org/packages/53/40/96cd959ad1dda6c12301860a74afece200a3209d84b393beedd5d7d915c0/maturin-1.10.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le.whl", hash = "sha256:04df81ee295dcda37828bd025a4ac688ea856e3946e4cb300a8f44a448de0069", size = 11177118, upload-time = "2025-11-19T11:53:03.014Z" }, + { url = "https://files.pythonhosted.org/packages/e5/b6/144f180f36314be183f5237011528f0e39fe5fd2e74e65c3b44a5795971e/maturin-1.10.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96e1d391e4c1fa87edf2a37e4d53d5f2e5f39dd880b9d8306ac9f8eb212d23f8", size = 9320218, upload-time = "2025-11-19T11:53:05.39Z" }, + { url = "https://files.pythonhosted.org/packages/eb/2d/2c483c1b3118e2e10fd8219d5291843f5f7c12284113251bf506144a3ac1/maturin-1.10.2-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:a217aa7c42aa332fb8e8377eb07314e1f02cf0fe036f614aca4575121952addd", size = 8985266, upload-time = "2025-11-19T11:53:07.618Z" }, + { url = "https://files.pythonhosted.org/packages/1d/98/1d0222521e112cd058b56e8d96c72cf9615f799e3b557adb4b16004f42aa/maturin-1.10.2-py3-none-win32.whl", hash = "sha256:da031771d9fb6ddb1d373638ec2556feee29e4507365cd5749a2d354bcadd818", size = 7667897, upload-time = "2025-11-19T11:53:10.14Z" }, + { url = "https://files.pythonhosted.org/packages/a0/ec/c6c973b1def0d04533620b439d5d7aebb257657ba66710885394514c8045/maturin-1.10.2-py3-none-win_amd64.whl", hash = "sha256:da777766fd584440dc9fecd30059a94f85e4983f58b09e438ae38ee4b494024c", size = 8908416, upload-time = "2025-11-19T11:53:12.862Z" }, + { url = "https://files.pythonhosted.org/packages/1b/01/7da60c9f7d5dc92dfa5e8888239fd0fb2613ee19e44e6db5c2ed5595fab3/maturin-1.10.2-py3-none-win_arm64.whl", hash = "sha256:a4c29a770ea2c76082e0afc6d4efd8ee94405588bfae00d10828f72e206c739b", size = 7506680, upload-time = "2025-11-19T11:53:15.403Z" }, +] + +[[package]] +name = "processing" +source = { editable = "." } + +[package.dev-dependencies] +dev = [ + { name = "maturin" }, +] + +[package.metadata] + +[package.metadata.requires-dev] +dev = [{ name = "maturin", specifier = ">=1.10,<2.0" }] + +[[package]] +name = "tomli" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/52/ed/3f73f72945444548f33eba9a87fc7a6e969915e7b1acc8260b30e1f76a2f/tomli-2.3.0.tar.gz", hash = "sha256:64be704a875d2a59753d80ee8a533c3fe183e3f06807ff7dc2232938ccb01549", size = 17392, upload-time = "2025-10-08T22:01:47.119Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/2e/299f62b401438d5fe1624119c723f5d877acc86a4c2492da405626665f12/tomli-2.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:88bd15eb972f3664f5ed4b57c1634a97153b4bac4479dcb6a495f41921eb7f45", size = 153236, upload-time = "2025-10-08T22:01:00.137Z" }, + { url = "https://files.pythonhosted.org/packages/86/7f/d8fffe6a7aefdb61bced88fcb5e280cfd71e08939da5894161bd71bea022/tomli-2.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:883b1c0d6398a6a9d29b508c331fa56adbcdff647f6ace4dfca0f50e90dfd0ba", size = 148084, upload-time = "2025-10-08T22:01:01.63Z" }, + { url = "https://files.pythonhosted.org/packages/47/5c/24935fb6a2ee63e86d80e4d3b58b222dafaf438c416752c8b58537c8b89a/tomli-2.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d1381caf13ab9f300e30dd8feadb3de072aeb86f1d34a8569453ff32a7dea4bf", size = 234832, upload-time = "2025-10-08T22:01:02.543Z" }, + { url = "https://files.pythonhosted.org/packages/89/da/75dfd804fc11e6612846758a23f13271b76d577e299592b4371a4ca4cd09/tomli-2.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a0e285d2649b78c0d9027570d4da3425bdb49830a6156121360b3f8511ea3441", size = 242052, upload-time = "2025-10-08T22:01:03.836Z" }, + { url = "https://files.pythonhosted.org/packages/70/8c/f48ac899f7b3ca7eb13af73bacbc93aec37f9c954df3c08ad96991c8c373/tomli-2.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0a154a9ae14bfcf5d8917a59b51ffd5a3ac1fd149b71b47a3a104ca4edcfa845", size = 239555, upload-time = "2025-10-08T22:01:04.834Z" }, + { url = "https://files.pythonhosted.org/packages/ba/28/72f8afd73f1d0e7829bfc093f4cb98ce0a40ffc0cc997009ee1ed94ba705/tomli-2.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:74bf8464ff93e413514fefd2be591c3b0b23231a77f901db1eb30d6f712fc42c", size = 245128, upload-time = "2025-10-08T22:01:05.84Z" }, + { url = "https://files.pythonhosted.org/packages/b6/eb/a7679c8ac85208706d27436e8d421dfa39d4c914dcf5fa8083a9305f58d9/tomli-2.3.0-cp311-cp311-win32.whl", hash = "sha256:00b5f5d95bbfc7d12f91ad8c593a1659b6387b43f054104cda404be6bda62456", size = 96445, upload-time = "2025-10-08T22:01:06.896Z" }, + { url = "https://files.pythonhosted.org/packages/0a/fe/3d3420c4cb1ad9cb462fb52967080575f15898da97e21cb6f1361d505383/tomli-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:4dc4ce8483a5d429ab602f111a93a6ab1ed425eae3122032db7e9acf449451be", size = 107165, upload-time = "2025-10-08T22:01:08.107Z" }, + { url = "https://files.pythonhosted.org/packages/ff/b7/40f36368fcabc518bb11c8f06379a0fd631985046c038aca08c6d6a43c6e/tomli-2.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d7d86942e56ded512a594786a5ba0a5e521d02529b3826e7761a05138341a2ac", size = 154891, upload-time = "2025-10-08T22:01:09.082Z" }, + { url = "https://files.pythonhosted.org/packages/f9/3f/d9dd692199e3b3aab2e4e4dd948abd0f790d9ded8cd10cbaae276a898434/tomli-2.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:73ee0b47d4dad1c5e996e3cd33b8a76a50167ae5f96a2607cbe8cc773506ab22", size = 148796, upload-time = "2025-10-08T22:01:10.266Z" }, + { url = "https://files.pythonhosted.org/packages/60/83/59bff4996c2cf9f9387a0f5a3394629c7efa5ef16142076a23a90f1955fa/tomli-2.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:792262b94d5d0a466afb5bc63c7daa9d75520110971ee269152083270998316f", size = 242121, upload-time = "2025-10-08T22:01:11.332Z" }, + { url = "https://files.pythonhosted.org/packages/45/e5/7c5119ff39de8693d6baab6c0b6dcb556d192c165596e9fc231ea1052041/tomli-2.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f195fe57ecceac95a66a75ac24d9d5fbc98ef0962e09b2eddec5d39375aae52", size = 250070, upload-time = "2025-10-08T22:01:12.498Z" }, + { url = "https://files.pythonhosted.org/packages/45/12/ad5126d3a278f27e6701abde51d342aa78d06e27ce2bb596a01f7709a5a2/tomli-2.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e31d432427dcbf4d86958c184b9bfd1e96b5b71f8eb17e6d02531f434fd335b8", size = 245859, upload-time = "2025-10-08T22:01:13.551Z" }, + { url = "https://files.pythonhosted.org/packages/fb/a1/4d6865da6a71c603cfe6ad0e6556c73c76548557a8d658f9e3b142df245f/tomli-2.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b0882799624980785240ab732537fcfc372601015c00f7fc367c55308c186f6", size = 250296, upload-time = "2025-10-08T22:01:14.614Z" }, + { url = "https://files.pythonhosted.org/packages/a0/b7/a7a7042715d55c9ba6e8b196d65d2cb662578b4d8cd17d882d45322b0d78/tomli-2.3.0-cp312-cp312-win32.whl", hash = "sha256:ff72b71b5d10d22ecb084d345fc26f42b5143c5533db5e2eaba7d2d335358876", size = 97124, upload-time = "2025-10-08T22:01:15.629Z" }, + { url = "https://files.pythonhosted.org/packages/06/1e/f22f100db15a68b520664eb3328fb0ae4e90530887928558112c8d1f4515/tomli-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:1cb4ed918939151a03f33d4242ccd0aa5f11b3547d0cf30f7c74a408a5b99878", size = 107698, upload-time = "2025-10-08T22:01:16.51Z" }, + { url = "https://files.pythonhosted.org/packages/89/48/06ee6eabe4fdd9ecd48bf488f4ac783844fd777f547b8d1b61c11939974e/tomli-2.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5192f562738228945d7b13d4930baffda67b69425a7f0da96d360b0a3888136b", size = 154819, upload-time = "2025-10-08T22:01:17.964Z" }, + { url = "https://files.pythonhosted.org/packages/f1/01/88793757d54d8937015c75dcdfb673c65471945f6be98e6a0410fba167ed/tomli-2.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:be71c93a63d738597996be9528f4abe628d1adf5e6eb11607bc8fe1a510b5dae", size = 148766, upload-time = "2025-10-08T22:01:18.959Z" }, + { url = "https://files.pythonhosted.org/packages/42/17/5e2c956f0144b812e7e107f94f1cc54af734eb17b5191c0bbfb72de5e93e/tomli-2.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4665508bcbac83a31ff8ab08f424b665200c0e1e645d2bd9ab3d3e557b6185b", size = 240771, upload-time = "2025-10-08T22:01:20.106Z" }, + { url = "https://files.pythonhosted.org/packages/d5/f4/0fbd014909748706c01d16824eadb0307115f9562a15cbb012cd9b3512c5/tomli-2.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4021923f97266babc6ccab9f5068642a0095faa0a51a246a6a02fccbb3514eaf", size = 248586, upload-time = "2025-10-08T22:01:21.164Z" }, + { url = "https://files.pythonhosted.org/packages/30/77/fed85e114bde5e81ecf9bc5da0cc69f2914b38f4708c80ae67d0c10180c5/tomli-2.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4ea38c40145a357d513bffad0ed869f13c1773716cf71ccaa83b0fa0cc4e42f", size = 244792, upload-time = "2025-10-08T22:01:22.417Z" }, + { url = "https://files.pythonhosted.org/packages/55/92/afed3d497f7c186dc71e6ee6d4fcb0acfa5f7d0a1a2878f8beae379ae0cc/tomli-2.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ad805ea85eda330dbad64c7ea7a4556259665bdf9d2672f5dccc740eb9d3ca05", size = 248909, upload-time = "2025-10-08T22:01:23.859Z" }, + { url = "https://files.pythonhosted.org/packages/f8/84/ef50c51b5a9472e7265ce1ffc7f24cd4023d289e109f669bdb1553f6a7c2/tomli-2.3.0-cp313-cp313-win32.whl", hash = "sha256:97d5eec30149fd3294270e889b4234023f2c69747e555a27bd708828353ab606", size = 96946, upload-time = "2025-10-08T22:01:24.893Z" }, + { url = "https://files.pythonhosted.org/packages/b2/b7/718cd1da0884f281f95ccfa3a6cc572d30053cba64603f79d431d3c9b61b/tomli-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:0c95ca56fbe89e065c6ead5b593ee64b84a26fca063b5d71a1122bf26e533999", size = 107705, upload-time = "2025-10-08T22:01:26.153Z" }, + { url = "https://files.pythonhosted.org/packages/19/94/aeafa14a52e16163008060506fcb6aa1949d13548d13752171a755c65611/tomli-2.3.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:cebc6fe843e0733ee827a282aca4999b596241195f43b4cc371d64fc6639da9e", size = 154244, upload-time = "2025-10-08T22:01:27.06Z" }, + { url = "https://files.pythonhosted.org/packages/db/e4/1e58409aa78eefa47ccd19779fc6f36787edbe7d4cd330eeeedb33a4515b/tomli-2.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4c2ef0244c75aba9355561272009d934953817c49f47d768070c3c94355c2aa3", size = 148637, upload-time = "2025-10-08T22:01:28.059Z" }, + { url = "https://files.pythonhosted.org/packages/26/b6/d1eccb62f665e44359226811064596dd6a366ea1f985839c566cd61525ae/tomli-2.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c22a8bf253bacc0cf11f35ad9808b6cb75ada2631c2d97c971122583b129afbc", size = 241925, upload-time = "2025-10-08T22:01:29.066Z" }, + { url = "https://files.pythonhosted.org/packages/70/91/7cdab9a03e6d3d2bb11beae108da5bdc1c34bdeb06e21163482544ddcc90/tomli-2.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0eea8cc5c5e9f89c9b90c4896a8deefc74f518db5927d0e0e8d4a80953d774d0", size = 249045, upload-time = "2025-10-08T22:01:31.98Z" }, + { url = "https://files.pythonhosted.org/packages/15/1b/8c26874ed1f6e4f1fcfeb868db8a794cbe9f227299402db58cfcc858766c/tomli-2.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b74a0e59ec5d15127acdabd75ea17726ac4c5178ae51b85bfe39c4f8a278e879", size = 245835, upload-time = "2025-10-08T22:01:32.989Z" }, + { url = "https://files.pythonhosted.org/packages/fd/42/8e3c6a9a4b1a1360c1a2a39f0b972cef2cc9ebd56025168c4137192a9321/tomli-2.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b5870b50c9db823c595983571d1296a6ff3e1b88f734a4c8f6fc6188397de005", size = 253109, upload-time = "2025-10-08T22:01:34.052Z" }, + { url = "https://files.pythonhosted.org/packages/22/0c/b4da635000a71b5f80130937eeac12e686eefb376b8dee113b4a582bba42/tomli-2.3.0-cp314-cp314-win32.whl", hash = "sha256:feb0dacc61170ed7ab602d3d972a58f14ee3ee60494292d384649a3dc38ef463", size = 97930, upload-time = "2025-10-08T22:01:35.082Z" }, + { url = "https://files.pythonhosted.org/packages/b9/74/cb1abc870a418ae99cd5c9547d6bce30701a954e0e721821df483ef7223c/tomli-2.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:b273fcbd7fc64dc3600c098e39136522650c49bca95df2d11cf3b626422392c8", size = 107964, upload-time = "2025-10-08T22:01:36.057Z" }, + { url = "https://files.pythonhosted.org/packages/54/78/5c46fff6432a712af9f792944f4fcd7067d8823157949f4e40c56b8b3c83/tomli-2.3.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:940d56ee0410fa17ee1f12b817b37a4d4e4dc4d27340863cc67236c74f582e77", size = 163065, upload-time = "2025-10-08T22:01:37.27Z" }, + { url = "https://files.pythonhosted.org/packages/39/67/f85d9bd23182f45eca8939cd2bc7050e1f90c41f4a2ecbbd5963a1d1c486/tomli-2.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f85209946d1fe94416debbb88d00eb92ce9cd5266775424ff81bc959e001acaf", size = 159088, upload-time = "2025-10-08T22:01:38.235Z" }, + { url = "https://files.pythonhosted.org/packages/26/5a/4b546a0405b9cc0659b399f12b6adb750757baf04250b148d3c5059fc4eb/tomli-2.3.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a56212bdcce682e56b0aaf79e869ba5d15a6163f88d5451cbde388d48b13f530", size = 268193, upload-time = "2025-10-08T22:01:39.712Z" }, + { url = "https://files.pythonhosted.org/packages/42/4f/2c12a72ae22cf7b59a7fe75b3465b7aba40ea9145d026ba41cb382075b0e/tomli-2.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c5f3ffd1e098dfc032d4d3af5c0ac64f6d286d98bc148698356847b80fa4de1b", size = 275488, upload-time = "2025-10-08T22:01:40.773Z" }, + { url = "https://files.pythonhosted.org/packages/92/04/a038d65dbe160c3aa5a624e93ad98111090f6804027d474ba9c37c8ae186/tomli-2.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5e01decd096b1530d97d5d85cb4dff4af2d8347bd35686654a004f8dea20fc67", size = 272669, upload-time = "2025-10-08T22:01:41.824Z" }, + { url = "https://files.pythonhosted.org/packages/be/2f/8b7c60a9d1612a7cbc39ffcca4f21a73bf368a80fc25bccf8253e2563267/tomli-2.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8a35dd0e643bb2610f156cca8db95d213a90015c11fee76c946aa62b7ae7e02f", size = 279709, upload-time = "2025-10-08T22:01:43.177Z" }, + { url = "https://files.pythonhosted.org/packages/7e/46/cc36c679f09f27ded940281c38607716c86cf8ba4a518d524e349c8b4874/tomli-2.3.0-cp314-cp314t-win32.whl", hash = "sha256:a1f7f282fe248311650081faafa5f4732bdbfef5d45fe3f2e702fbc6f2d496e0", size = 107563, upload-time = "2025-10-08T22:01:44.233Z" }, + { url = "https://files.pythonhosted.org/packages/84/ff/426ca8683cf7b753614480484f6437f568fd2fda2edbdf57a2d3d8b27a0b/tomli-2.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:70a251f8d4ba2d9ac2542eecf008b3c8a9fc5c3f9f02c56a9d7952612be2fdba", size = 119756, upload-time = "2025-10-08T22:01:45.234Z" }, + { url = "https://files.pythonhosted.org/packages/77/b8/0135fadc89e73be292b473cb820b4f5a08197779206b33191e801feeae40/tomli-2.3.0-py3-none-any.whl", hash = "sha256:e95b1af3c5b07d9e643909b5abbec77cd9f1217e6d0bca72b0234736b9fb1f1b", size = 14408, upload-time = "2025-10-08T22:01:46.04Z" }, +] diff --git a/justfile b/justfile index 8a4dee8..dfbf0c4 100644 --- a/justfile +++ b/justfile @@ -1,6 +1,12 @@ default: @just --list +py-build: + cd crates/processing_pyo3 && uv run maturin develop + +py-run file: py-build + cd crates/processing_pyo3 && uv run python ../../{{file}} + wasm-build: wasm-pack build crates/processing_wasm --target web --out-dir ../../target/wasm