Skip to content

Commit

Permalink
add report logic
Browse files Browse the repository at this point in the history
  • Loading branch information
mikedh committed Jan 17, 2025
1 parent eaa6004 commit ffdc7eb
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 16 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:

pypi:
name: Release To PyPi
needs: [tests, containers]
needs: [tests, containers, corpus]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -118,13 +118,13 @@ jobs:
- name: Install Trimesh
run: pip install .[easy,test]
- name: Run Corpus Check
run: python tests/corpus.py
run: python tests/corpus.py -run

release:
permissions:
contents: write # for actions/create-release
name: Create GitHub Release
needs: [tests, containers]
needs: [tests, containers, corpus]
runs-on: ubuntu-latest
steps:
- name: Checkout code
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,5 @@ jobs:
- name: Install Trimesh
run: pip install .[easy,test]
- name: Run Corpus Check
run: python tests/corpus.py
run: python tests/corpus.py -run

64 changes: 59 additions & 5 deletions tests/corpus.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"""

import json
import sys
import time
from dataclasses import asdict, dataclass

Expand Down Expand Up @@ -52,6 +53,34 @@ class Report:
# a pyinstrument.renderers.JSONRenderer output
profile: str

def compare(self, other: "Report"):
"""
Compare this load report to another.
"""
# what files were loaded by both versions
ot = {o.file_name: o.type_load for o in self.load}
nt = {n.file_name: n.type_load for n in other.load}

both = set(ot.keys()).intersection(nt.keys())
matches = np.array([ot[k] == nt[k] for k in both])
percent = matches.sum() / len(matches)

print(f"Comparing `{self.version}` against `{other.version}`")
print(f"Return types matched {percent * 100.0:0.3f}% of the time")
print(f"Loaded {len(self.load)} vs Loaded {len(other.load)}")


def from_dict(data: dict) -> Report:
"""
Parse a `Report` which has been exported using `dataclasses.asdict`
into a Report object.
"""
return Report(
load=[LoadReport(**r) for r in data.get("load", [])],
version=data.get("version"),
profile=data.get("profile"),
)


def on_repo(
repo: str, commit: str, available: set, root: Optional[str] = None
Expand Down Expand Up @@ -207,9 +236,15 @@ def equal(a, b):
return a == b


if __name__ == "__main__":
trimesh.util.attach_to_log()
def run(save: bool = False):
"""
Try to load and export every mesh we can get our hands on.
Parameters
-----------
save
If passed, save a JSON dump of the load report.
"""
# get a set with available extension
available = trimesh.available_formats()

Expand All @@ -223,7 +258,7 @@ def equal(a, b):
)

# TODO : waiting on a release containing pycollada/pycollada/147
available.difference_update({"dae"})
# available.difference_update({"dae"})

with Profiler() as P:
# check against the small trimesh corpus
Expand Down Expand Up @@ -269,5 +304,24 @@ def equal(a, b):
# compose the overall report
report = Report(load=loads, version=trimesh.__version__, profile=profile)

with open(f"trimesh.{trimesh.__version__}.{int(time.time())}.json", "w") as F:
json.dump(asdict(report), F)
if save:
with open(f"trimesh.{trimesh.__version__}.{int(time.time())}.json", "w") as F:
json.dump(asdict(report), F)

return report


if __name__ == "__main__":
trimesh.util.attach_to_log()

if "-run" in " ".join(sys.argv):
run()

if "-compare" in " ".join(sys.argv):
with open("trimesh.4.5.3.1737061410.json") as f:
old = from_dict(json.load(f))

with open("trimesh.4.6.0.1737060030.json") as f:
new = from_dict(json.load(f))

new.compare(old)
12 changes: 7 additions & 5 deletions trimesh/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2184,7 +2184,8 @@ def section(
Curve of intersection or None if it was not hit by plane.
"""
# turn line segments into Path2D/Path3D objects
from .exchange.load import load_path
from .path.exchange.misc import lines_to_path
from .path.path import Path3D

# return a single cross section in 3D
lines, face_index = intersections.mesh_plane(
Expand All @@ -2199,13 +2200,14 @@ def section(
if len(lines) == 0:
return None

# otherwise load the line segments into a Path3D object
path = load_path(lines)
# otherwise load the line segments into the keyword arguments
# for a Path3D object.
path = lines_to_path(lines)

# add the face index info into metadata
path.metadata["face_index"] = face_index
# path.metadata["face_index"] = face_index

return path
return Path3D(**path)

def section_multiplane(
self,
Expand Down
9 changes: 7 additions & 2 deletions trimesh/path/exchange/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from ... import graph, grouping, util
from ...constants import tol_path
from ...typed import ArrayLike, Dict
from ...typed import ArrayLike, Dict, NDArray, Optional
from ..entities import Arc, Line


Expand Down Expand Up @@ -37,14 +37,16 @@ def dict_to_path(as_dict):
return result


def lines_to_path(lines):
def lines_to_path(lines: ArrayLike, index: Optional[NDArray[np.int64]] = None) -> Dict:
"""
Turn line segments into a Path2D or Path3D object.
Parameters
------------
lines : (n, 2, dimension) or (n, dimension) float
Line segments or connected polyline curve in 2D or 3D
index : (n,) int64
If passed save an index for each line segment.
Returns
-----------
Expand All @@ -53,6 +55,9 @@ def lines_to_path(lines):
"""
lines = np.asanyarray(lines, dtype=np.float64)

if index is not None:
index = np.asanyarray(index, dtype=np.int64)

if util.is_shape(lines, (-1, (2, 3))):
# the case where we have a list of points
# we are going to assume they are connected
Expand Down

0 comments on commit ffdc7eb

Please sign in to comment.