From fcf9d9d695508c6f3b3f08614410e6cd3f3c7830 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?charlotte=20=F0=9F=8C=B8?= Date: Mon, 27 Apr 2026 17:21:15 -0700 Subject: [PATCH 1/2] Switch-up strategy for ensuring dynamic vars end up in LSP. --- crates/processing_pyo3/mewnala/__init__.py | 79 ++++++++++++++++------ crates/processing_pyo3/src/lib.rs | 43 ++---------- tools/generate_stubs/src/main.rs | 27 +++++++- 3 files changed, 90 insertions(+), 59 deletions(-) diff --git a/crates/processing_pyo3/mewnala/__init__.py b/crates/processing_pyo3/mewnala/__init__.py index ef4dae0..13b1b81 100644 --- a/crates/processing_pyo3/mewnala/__init__.py +++ b/crates/processing_pyo3/mewnala/__init__.py @@ -17,33 +17,54 @@ "width", "height", "focused", + "pixel_density", "pixel_width", "pixel_height", -) -_DYNAMIC_FUNCTIONS = ( "mouse_x", "mouse_y", "pmouse_x", "pmouse_y", + "mouse_is_pressed", + "mouse_button", + "mouse_wheel", + "moved_x", + "moved_y", + "key", + "key_code", + "key_is_pressed", +) + +_DYNAMIC_TIME_ATTRS = ( "frame_count", "delta_time", "elapsed_time", ) + +_DEFAULT_GRAPHICS_VALUES = { + "width": 100, + "height": 100, + "focused": False, + "pixel_density": 1.0, + "pixel_width": 100, + "pixel_height": 100, + "mouse_x": 0.0, + "mouse_y": 0.0, + "pmouse_x": 0.0, + "pmouse_y": 0.0, + "mouse_is_pressed": False, + "mouse_button": None, + "mouse_wheel": 0.0, + "moved_x": 0.0, + "moved_y": 0.0, + "key": None, + "key_code": None, + "key_is_pressed": False, +} + _DYNAMIC = ( - _DYNAMIC_GRAPHICS_ATTRS + _DYNAMIC_FUNCTIONS + ( - "mouse_is_pressed", - "mouse_button", - "moved_x", - "moved_y", - "mouse_wheel", - "key", - "key_code", - "key_is_pressed", - "display_width", - "display_height", - "window_x", - "window_y", - ) + _DYNAMIC_GRAPHICS_ATTRS + + _DYNAMIC_TIME_ATTRS + + ("display_width", "display_height", "window_x", "window_y") ) @@ -56,15 +77,29 @@ def __getattr__(name): g = _get_graphics() if g is not None: return getattr(g, name) - if name in _DYNAMIC_FUNCTIONS: - fn = getattr(_native, name, None) - if callable(fn): + return _DEFAULT_GRAPHICS_VALUES[name] + if name in _DYNAMIC_TIME_ATTRS: + fn = getattr(_native, f"_dyn_{name}", None) + if not callable(fn): + return 0 + try: return fn() + except RuntimeError: + return 0 if name == "frame_count" else 0.0 if name in ("display_width", "display_height"): - mon = getattr(_native, "primary_monitor", lambda: None)() + try: + mon = getattr(_native, "primary_monitor", lambda: None)() + except RuntimeError: + return 0 if mon is None: return 0 return mon.width if name == "display_width" else mon.height + if name in ("window_x", "window_y"): + g = _get_graphics() + if g is None: + return 0 + x, y = g.surface.position + return x if name == "window_x" else y raise AttributeError(f"module {__name__!r} has no attribute {name!r}") @@ -72,4 +107,8 @@ def __dir__(): return sorted(set(list(globals().keys()) + list(_DYNAMIC))) +__all__ = sorted( + {n for n in dir(_native) if not n.startswith("_")} | set(_DYNAMIC) +) + del _sys, _name, _sub diff --git a/crates/processing_pyo3/src/lib.rs b/crates/processing_pyo3/src/lib.rs index 012b7ea..7902979 100644 --- a/crates/processing_pyo3/src/lib.rs +++ b/crates/processing_pyo3/src/lib.rs @@ -603,9 +603,6 @@ mod mewnala { fn init(module: &Bound<'_, PyModule>) -> PyResult<()> { use processing::prelude::BlendMode; - module.add("width", super::DEFAULT_WIDTH)?; - module.add("height", super::DEFAULT_HEIGHT)?; - module.add("BLEND", PyBlendMode::from_preset(BlendMode::Blend))?; module.add("ADD", PyBlendMode::from_preset(BlendMode::Add))?; module.add("SUBTRACT", PyBlendMode::from_preset(BlendMode::Subtract))?; @@ -1762,38 +1759,6 @@ mod mewnala { midi::play_notes(note, duration) } - #[pyfunction] - #[pyo3(pass_module)] - fn mouse_x(module: &Bound<'_, PyModule>) -> PyResult { - let graphics = - get_graphics(module)?.ok_or_else(|| PyRuntimeError::new_err("call size() first"))?; - input::mouse_x(graphics.surface.entity, graphics.width) - } - - #[pyfunction] - #[pyo3(pass_module)] - fn mouse_y(module: &Bound<'_, PyModule>) -> PyResult { - let graphics = - get_graphics(module)?.ok_or_else(|| PyRuntimeError::new_err("call size() first"))?; - input::mouse_y(graphics.surface.entity, graphics.height) - } - - #[pyfunction] - #[pyo3(pass_module)] - fn pmouse_x(module: &Bound<'_, PyModule>) -> PyResult { - let graphics = - get_graphics(module)?.ok_or_else(|| PyRuntimeError::new_err("call size() first"))?; - input::pmouse_x(graphics.surface.entity, graphics.width) - } - - #[pyfunction] - #[pyo3(pass_module)] - fn pmouse_y(module: &Bound<'_, PyModule>) -> PyResult { - let graphics = - get_graphics(module)?.ok_or_else(|| PyRuntimeError::new_err("call size() first"))?; - input::pmouse_y(graphics.surface.entity, graphics.height) - } - #[pyfunction] fn key_is_down(key_code: u32) -> PyResult { input::key_is_down(key_code) @@ -1833,18 +1798,20 @@ mod mewnala { graphics.surface.display_density() } + // private stuff + #[pyfunction] - fn frame_count() -> PyResult { + fn _dyn_frame_count() -> PyResult { time::frame_count() } #[pyfunction] - fn delta_time() -> PyResult { + fn _dyn_delta_time() -> PyResult { time::delta_time() } #[pyfunction] - fn elapsed_time() -> PyResult { + fn _dyn_elapsed_time() -> PyResult { time::elapsed_time() } diff --git a/tools/generate_stubs/src/main.rs b/tools/generate_stubs/src/main.rs index b80cbed..bdd83c9 100644 --- a/tools/generate_stubs/src/main.rs +++ b/tools/generate_stubs/src/main.rs @@ -46,7 +46,32 @@ fn main() { module.incomplete = false; - let stubs = module_stub_files(&module); + let mut stubs = module_stub_files(&module); + + // join in extras + + let extras_dir = workspace_root() + .join("crates") + .join("processing_pyo3") + .join("stubs"); + if extras_dir.is_dir() { + for entry in fs::read_dir(&extras_dir).unwrap() { + let entry = entry.unwrap(); + let path = entry.path(); + if path.extension().and_then(|s| s.to_str()) != Some("pyi") { + continue; + } + let filename = path.file_name().unwrap().to_owned(); + let extra = fs::read_to_string(&path).unwrap(); + let target = stubs.entry(PathBuf::from(&filename)).or_default(); + if !target.is_empty() && !target.ends_with('\n') { + target.push('\n'); + } + target.push('\n'); + target.push_str(&extra); + eprintln!("Appended extras: {}", path.display()); + } + } let output_dir = workspace_root() .join("crates") From 86b3382f216e42d315bd9442370f542644113466 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?charlotte=20=F0=9F=8C=B8?= Date: Mon, 27 Apr 2026 18:22:03 -0700 Subject: [PATCH 2/2] Fmt. --- tools/generate_stubs/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/generate_stubs/src/main.rs b/tools/generate_stubs/src/main.rs index bdd83c9..235f948 100644 --- a/tools/generate_stubs/src/main.rs +++ b/tools/generate_stubs/src/main.rs @@ -49,7 +49,7 @@ fn main() { let mut stubs = module_stub_files(&module); // join in extras - + let extras_dir = workspace_root() .join("crates") .join("processing_pyo3")