Grotti 2.2.6: Wand-Vorschau, dichterer 3D-Pfad, ASCII-Dateinamen.

Kacheln zeigen Moonraker-Thumbnails; Toolpath-Thinning behält ganze Schichten; Nicht-ASCII-Namen vermeiden 10115 beim Senden.
This commit is contained in:
Dominic Gundel committed 2026-10-17 11:22:43 +02:00
1 parent 7da895bbcd
commit b277ca48aa
16 files changed
+302 -50

No files matched your search

+25
View File
@@ -0,0 +1,25 @@
"""ASCII-Dateinamen für Moonraker-Upload."""
from grotti.moonraker import multipart, safe_upload_name
def test_safe_upload_strips_cjk():
name = "1015-2159-虎钳式强力夹子_plate(01)_PLA_0.2_53m57s.gcode"
safe = safe_upload_name(name)
assert safe.isascii()
assert safe.endswith(".gcode")
assert "plate(01)" in safe
assert "虎" not in safe
def test_multipart_single_ascii_filename():
name = "模型_test.gcode"
_boundary, body = multipart(name, b"G28\n")
head = body.split(b"G28\n", 1)[0].decode("ascii")
assert "filename*=UTF-8" not in head
assert 'filename="test.gcode"' in head
assert all(ord(ch) < 128 for ch in head)
def test_safe_upload_preserves_path():
assert safe_upload_name("subdir/foo.gcode") == "subdir/foo.gcode"
+55
View File
@@ -0,0 +1,55 @@
"""Toolpath-Thinning: ganze Schichten dicht, keine gesprenkelten Stichproben."""
from grotti.toolpath import TOOLPATH_VERSION, _thin_points, build_toolpath
def _fake_points(layers=40, per_layer=800):
points = []
breaks = []
seq = 0
for layer in range(layers):
z = 0.2 + layer * 0.2
breaks.append(len(points))
for i in range(per_layer):
extrude = 1 if i > 0 else 0
points.append([float(i), float(layer), z, extrude, seq])
seq += 1
return points, breaks
def test_thin_keeps_consecutive_extrude_pairs():
points, breaks = _fake_points()
kept, new_breaks = _thin_points(points, breaks, max_points=8_000)
assert len(kept) <= 8_000
assert new_breaks
consec = 0
for i in range(1, len(kept)):
if kept[i][3] and kept[i][4] == kept[i - 1][4] + 1:
consec += 1
assert consec > 500, "Thinning darf keine zeichnbaren Segmente übrig lassen"
def test_thin_keeps_solid_layers():
points, breaks = _fake_points(layers=50, per_layer=600)
kept, _ = _thin_points(points, breaks, max_points=10_000)
# Pro behaltener Z-Höhe: hoher Anteil aufeinanderfolgender Extrusionen
by_z = {}
for i in range(1, len(kept)):
if not (kept[i][3] and kept[i][4] == kept[i - 1][4] + 1):
continue
z = round(kept[i][2], 2)
by_z[z] = by_z.get(z, 0) + 1
assert by_z, "keine Extrusionssegmente"
assert max(by_z.values()) >= 40, "behaltene Schichten sollen dicht sein"
def test_toolpath_version():
assert TOOLPATH_VERSION >= 8
def test_build_empty(tmp_path):
path = tmp_path / "empty.gcode"
path.write_text("; nix\n", encoding="utf-8")
data = build_toolpath(path)
assert data["points"] == []
assert data["version"] == TOOLPATH_VERSION