Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
From 7f1b2a37d5cb51aabbec6483588f6a58c91bcf31 Mon Sep 17 00:00:00 2001
From: OpenCentauri <dev@opencentauri.io>
Date: Mon, 20 Jul 2026 15:00:00 -0400
Subject: [PATCH] Lazy-load optional NumPy users

Upstream-Status: Pending

Importing NumPy 1.26 brings a substantial set of numerical modules into the
Klippy process. Do not make every configuration pay that cost merely for JSON
conversion or for temperature-fan control modes which do not use curves.

Recognize NumPy values by their type metadata in the JSON fallback, which is
only invoked for otherwise non-serializable objects. Import NumPy from the
curve controller itself so watermark and PID temperature fans remain free of
that dependency.
---
klippy/extras/temperature_fan.py | 13 +++++++------
klippy/webhooks.py | 15 ++++++++-------
2 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/klippy/extras/temperature_fan.py b/klippy/extras/temperature_fan.py
index 757b494..a358d2c 100644
--- a/klippy/extras/temperature_fan.py
+++ b/klippy/extras/temperature_fan.py
@@ -4,8 +4,6 @@
#
# This file may be distributed under the terms of the GNU GPLv3 license.

-import numpy as np
-
from . import fan

KELVIN_TO_CELSIUS = -273.15
@@ -250,7 +248,12 @@ class ControlPID:

class ControlCurve:
def __init__(self, temperature_fan, config):
+ # Curve control is the only temperature-fan mode which needs NumPy.
+ # Keep PID and watermark configurations from importing it at startup.
+ import numpy as np
+
self.temperature_fan = temperature_fan
+ self.numpy = np

points = list(
config.getlists("points", seps=(",", "\n"), parser=float, count=2)
@@ -316,19 +319,19 @@ class ControlCurve:

def temperature_callback(self, read_time, temp):
current_speed = self.temperature_fan.last_speed_value
- upper_temp = np.interp(
+ upper_temp = self.numpy.interp(
current_speed, self.curve_heating[1], self.curve_heating[0]
)
- lower_temp = np.interp(
+ lower_temp = self.numpy.interp(
current_speed, self.curve_cooling[1], self.curve_cooling[0]
)

if temp < lower_temp:
- next_speed = np.interp(
+ next_speed = self.numpy.interp(
temp, self.curve_cooling[0], self.curve_cooling[1]
)
elif temp > upper_temp:
- next_speed = np.interp(
+ next_speed = self.numpy.interp(
temp, self.curve_heating[0], self.curve_heating[1]
)
else:
diff --git a/klippy/webhooks.py b/klippy/webhooks.py
index f53cd1b..3037f25 100644
--- a/klippy/webhooks.py
+++ b/klippy/webhooks.py
@@ -13,8 +13,6 @@ import pwd
import socket
import sys

-import numpy
-
from . import APP_NAME, gcode
from .extras.danger_options import get_danger_options

@@ -322,13 +320,15 @@ class ClientConnection:
self.send(result)

def _json_convert(self, obj):
- # numpy bool/array objects aren't directly serializable;
- # convert to regular types in case they leak into state dicts
- # to avoid a shutdown
- if isinstance(obj, numpy.bool_):
- return bool(obj)
- elif isinstance(obj, numpy.ndarray):
+ # NumPy scalars and arrays are not directly serializable. This
+ # fallback is only called for otherwise unsupported values, so avoid
+ # importing all of NumPy just to recognize them. Both ndarray and
+ # NumPy scalar types provide one of these conversion methods.
+ obj_type = type(obj)
+ if obj_type.__module__.startswith("numpy") and hasattr(obj, "tolist"):
return obj.tolist()
+ if obj_type.__module__.startswith("numpy") and hasattr(obj, "item"):
+ return obj.item()
# anything else will fail
logging.warning(
f"_json_convert: can't serialize object of type {type(obj)}: '{str(obj)}'"
--
2.47.2
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

KLIPPY_EXEC="/usr/bin/python3"
KLIPPER_PRINTER_CONFIG="/etc/klipper/config/printer.cfg"
KLIPPY_ARGS="-O /usr/share/klipper/klippy/klippy.py $KLIPPER_PRINTER_CONFIG -l /board-resource/klippy.log -a /run/klippy.sock"
KLIPPY_ARGS="-O -X no_debug_ranges /usr/share/klipper/klippy/klippy.py $KLIPPER_PRINTER_CONFIG -l /board-resource/klippy.log -a /run/klippy.sock"
PIDFILE="/var/run/klipper.pid"
KLIPPER_VAR_CONFIG_BUILDER="/usr/bin/build-klipper-var-config"
KLIPPER_CONFIG_VERSION="0.0.8-2"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ FILESEXTRAPATHS:prepend := "${THISDIR}/files:"

SRC_URI += " \
file://klipper-init-d \
file://0001-Lazy-load-optional-NumPy-users.patch \
file://printer.cfg \
file://macros.cfg \
file://machine.cfg \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
### END INIT INFO

MOONRAKER_EXEC="/usr/bin/python3"
MOONRAKER_ARGS="-m moonraker.moonraker -d /etc/klipper -l /board-resource/moonraker.log -u /run/moonraker.sock"
MOONRAKER_ARGS="-X no_debug_ranges -m moonraker.moonraker -d /etc/klipper -l /board-resource/moonraker.log -u /run/moonraker.sock"
PIDFILE="/var/run/moonraker.pid"

export PYTHONPATH="/usr/share/moonraker"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
From a9f7ee07c78910755311648026226644a3250c4f Mon Sep 17 00:00:00 2001
From: OpenCentauri <dev@opencentauri.io>
Date: Mon, 20 Jul 2026 15:00:00 -0400
Subject: [PATCH] Lazy-load heavy public subpackages

Upstream-Status: Backport [https://github.com/numpy/numpy/commit/250e1479ce342d9d7ab8a592508f6ce892d4c98b]

NumPy 1.26 imports several independent numerical subpackages whenever the root
package is imported. Embedded users of core array operations consequently map
FFT, linear algebra, polynomial, random-number, ctypes, and masked-array code
which they may never call.

Retain the public NumPy 1.26 API by importing these modules on first attribute
access and caching them in the package globals. This follows the lazy public
submodule behavior used by newer NumPy releases while leaving core and lib
namespace initialization unchanged.
---
numpy/__init__.py | 27 ++++++++++++++++++++++-----
1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/numpy/__init__.py b/numpy/__init__.py
index 63a63bf..54d6a97 100644
--- a/numpy/__init__.py
+++ b/numpy/__init__.py
@@ -141,12 +141,7 @@ else:
# See gh-14454 and gh-15672 for discussion.
from .lib import *

- from . import linalg
- from . import fft
- from . import polynomial
- from . import random
- from . import ctypeslib
- from . import ma
+ # Heavy public subpackages are loaded on first access in __getattr__.
from . import matrixlib as _mat
from .matrixlib import *

@@ -289,6 +284,28 @@ else:
numarray = 'removed'

def __getattr__(attr):
+ # NumPy 1.26 historically imported these independent subpackages at
+ # root-package startup. Preserve np.<submodule> while avoiding their
+ # code and extension mappings for core-only embedded workloads.
+ if attr == 'linalg':
+ import numpy.linalg as linalg
+ return linalg
+ elif attr == 'fft':
+ import numpy.fft as fft
+ return fft
+ elif attr == 'random':
+ import numpy.random as random
+ return random
+ elif attr == 'polynomial':
+ import numpy.polynomial as polynomial
+ return polynomial
+ elif attr == 'ma':
+ import numpy.ma as ma
+ return ma
+ elif attr == 'ctypeslib':
+ import numpy.ctypeslib as ctypeslib
+ return ctypeslib
+
# Warn for expired attributes, and return a dummy function
# that always raises an exception.
import warnings
--
2.47.2
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FILESEXTRAPATHS:prepend := "${THISDIR}/python3-numpy:"

SRC_URI += "file://0001-Lazy-load-heavy-public-subpackages.patch"
Loading