diff options
Diffstat (limited to 'generat3d')
| -rw-r--r-- | generat3d/config.py | 5 | ||||
| -rw-r--r-- | generat3d/library.py | 3 | ||||
| -rw-r--r-- | generat3d/scene.py | 22 |
3 files changed, 24 insertions, 6 deletions
diff --git a/generat3d/config.py b/generat3d/config.py index 804723f..fbb9f4d 100644 --- a/generat3d/config.py +++ b/generat3d/config.py @@ -53,7 +53,10 @@ def library_roots(cli_roots, path=None): for r in roots: if not r.strip(): raise Error("empty library root") - p = Path(r).expanduser() + try: + p = Path(r).expanduser() + except RuntimeError: + raise Error(f"cannot expand library root: {r}") from None if not p.is_dir(): raise Error(f"library root not found: {p}") out.append(p) diff --git a/generat3d/library.py b/generat3d/library.py index ea12794..39ad6fb 100644 --- a/generat3d/library.py +++ b/generat3d/library.py @@ -18,6 +18,7 @@ import gzip import json import os +import zlib from pathlib import Path from urllib.parse import unquote @@ -41,7 +42,7 @@ def read_dson(path): if data[:2] == b"\x1f\x8b": data = gzip.decompress(data) return json.loads(data) - except (OSError, EOFError, ValueError) as e: + except (OSError, EOFError, ValueError, zlib.error, RecursionError) as e: raise Error(f"{path}: {e}") from None diff --git a/generat3d/scene.py b/generat3d/scene.py index 25e4b61..28dc00c 100644 --- a/generat3d/scene.py +++ b/generat3d/scene.py @@ -62,9 +62,17 @@ class Scene: graph: Graph +def _finite(v): + return (not isinstance(v, bool) and isinstance(v, (int, float)) + and math.isfinite(v)) + + def _channel(node, name): comps = {c["id"]: c.get("current_value", c.get("value", 0.0)) for c in node.get(name, [])} - return [comps.get(a, 0.0) for a in AXES] + out = [comps.get(a, 0.0) for a in AXES] + if not all(_finite(v) for v in out): + raise Error(f"{node['id']}: {name} is not a finite number") + return out def _lookup(library, doc, url, section): @@ -147,9 +155,12 @@ class _Loader: self.graph.add_prop(key(n["id"], n["id"], f"{ch}/{a}"), v) for f in n.get("formulas", []): self.pending.append((f, fpath)) + verts = np.array(geom["vertices"]["values"], dtype=float) + if verts.ndim != 2 or verts.shape[1] != 3 or not np.isfinite(verts).all(): + raise Error(f"{fpath}: bad vertices") return Figure(asset["id"], inst.get("name", asset.get("name", asset["id"])), inst.get("label", asset.get("label", asset["id"])), - np.array(geom["vertices"]["values"], dtype=float), + verts, list(geom.get("polygon_material_groups", {}).get("values", [])), nodes) @@ -179,6 +190,9 @@ class _Loader: if parent and parent != self.figure.id: continue ch = mod.get("channel", {}) + for name in ("value", "min", "max"): + if name in ch and not _finite(ch[name]): + raise Error(f"{path}#{mod['id']}: {name} is not a finite number") k = key(self.figure.id, mod["id"], "value") self.graph.add_prop(k, ch.get("value", 0.0), ch.get("min", -math.inf), ch.get("max", math.inf), ch.get("clamped", False)) @@ -206,7 +220,7 @@ class _Loader: doc = self.library.load(path) try: self._modifiers(path, doc) - except (KeyError, TypeError, ValueError, IndexError, AttributeError) as e: + except (KeyError, TypeError, ValueError, IndexError, AttributeError, OverflowError) as e: raise Error(f"{path}: malformed morph data: {e!r}") from None def _morphs(self, fpath): @@ -263,5 +277,5 @@ def load(path, library): """Load a .duf scene and everything its figure needs.""" try: return _Loader(path, library).run() - except (KeyError, TypeError, IndexError, ValueError, AttributeError) as e: + except (KeyError, TypeError, IndexError, ValueError, AttributeError, OverflowError) as e: raise Error(f"{path}: malformed scene data: {e!r}") from None |
