diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 46ab54f14..b46f5d2fe 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: run: | pip install ruff - name: Check Formatting - run: ruff . + run: ruff check . tests: name: Run Unit Tests needs: formatting diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ddc3873ea..1defa397c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,11 +16,9 @@ jobs: with: python-version: "3.11" - name: Install - run: pip install ruff black + run: pip install ruff - name: Run Ruff - run: ruff . -# - name: Run Black -# run: black --check . + run: ruff check . tests: name: Run Unit Tests diff --git a/pyproject.toml b/pyproject.toml index ab8923c37..4d4bdc156 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ requires = ["setuptools >= 61.0", "wheel"] [project] name = "trimesh" requires-python = ">=3.7" -version = "4.2.2" +version = "4.2.3" authors = [{name = "Michael Dawson-Haggerty", email = "mikedh@kerfed.com"}] license = {file = "LICENSE.md"} description = "Import, export, process, analyze and view triangular meshes." @@ -129,7 +129,7 @@ select = [ "E", # style errors "F", # flakes "I", # import sorting - "RUF100", # meta + "RUF", # ruff specific rules "UP", # upgrade "W", # style warnings "YTT", # sys.version @@ -143,6 +143,7 @@ ignore = [ "E501", # Line too long ({width} > {limit} characters) "B904", # raise ... from err "B905", # zip() without an explicit strict= parameter + "RUF005", # recommends non-type-aware expansion ] # don't allow implicit string concatenation diff --git a/tests/test_align.py b/tests/test_align.py index cc237ea3f..2a36075ac 100644 --- a/tests/test_align.py +++ b/tests/test_align.py @@ -37,7 +37,7 @@ def test_align(self): unitized = g.trimesh.unitize(vectors) for unit_dest, dest in zip(unitized[-10:], vectors[-10:]): for unit, vector in zip(unitized, vectors): - T, a = align(vector, dest, return_angle=True) + T, _a = align(vector, dest, return_angle=True) assert is_rigid(T) assert g.np.isclose(g.np.linalg.det(T), 1.0) # rotate vector with transform @@ -97,7 +97,7 @@ def test_rigid(self): vector_1 = g.np.array([7.12106798e-07, -7.43194705e-08, 1.00000000e00]) vector_2 = g.np.array([0, 0, -1]) - T, angle = align(vector_1, vector_2, return_angle=True) + T, _angle = align(vector_1, vector_2, return_angle=True) assert g.np.isclose(g.np.linalg.det(T), 1.0) diff --git a/tests/test_creation.py b/tests/test_creation.py index bc06f9cb8..647e51fb0 100644 --- a/tests/test_creation.py +++ b/tests/test_creation.py @@ -267,7 +267,7 @@ def test_triangulate(self): ) except BaseException: g.log.error("failed to benchmark triangle", exc_info=True) - g.log.info(f"benchmarked triangulation on {len(bench)} polygons: {str(times)}") + g.log.info(f"benchmarked triangulation on {len(bench)} polygons: {times!s}") def test_triangulate_plumbing(self): """ diff --git a/tests/test_export.py b/tests/test_export.py index 1125b5bd7..380761d69 100644 --- a/tests/test_export.py +++ b/tests/test_export.py @@ -312,7 +312,7 @@ def test_parse_file_args(self): def test_buffered_random(self): """Test writing to non-standard file""" - mesh = list(g.get_meshes(1))[0] + mesh = next(iter(g.get_meshes(1))) with io.BufferedRandom(io.BytesIO()) as rw: mesh.export(rw, "STL") rw.seek(0) diff --git a/tests/test_gltf.py b/tests/test_gltf.py index a44aeb056..95aec4634 100644 --- a/tests/test_gltf.py +++ b/tests/test_gltf.py @@ -433,7 +433,7 @@ def to_integer(args): ) assert len(reloaded.geometry) == 1 # get meshes back - sphere_b = list(reloaded.geometry.values())[0] + sphere_b = next(iter(reloaded.geometry.values())) assert (sphere_b.visual.material.baseColorFactor == (255, 0, 0, 255)).all() def test_material_hash(self): @@ -1047,11 +1047,13 @@ def test_unitize_normals_null_values(self): # Export the mesh export = mesh.export(file_type="glb", unitize_normals=True) - reimported_mesh = list( - g.trimesh.load( - g.trimesh.util.wrap_as_stream(export), file_type="glb" - ).geometry.values() - )[0] + reimported_mesh = next( + iter( + g.trimesh.load( + g.trimesh.util.wrap_as_stream(export), file_type="glb" + ).geometry.values() + ) + ) # Check that the normals are still null assert g.np.allclose(reimported_mesh.vertex_normals[0], [0, 0, 0]) diff --git a/tests/test_obj.py b/tests/test_obj.py index 8000ff327..226781f09 100644 --- a/tests/test_obj.py +++ b/tests/test_obj.py @@ -110,7 +110,7 @@ def test_obj_simple_order(self): m = g.trimesh.load(file_name, process=False) # use trivial loading to compare with fancy performant one with open(file_name) as f: - f, v, vt = simple_load(f.read()) + f, v, _vt = simple_load(f.read()) # trimesh loader should return the same face order assert g.np.allclose(f, m.faces) assert g.np.allclose(v, m.vertices) @@ -123,7 +123,7 @@ def test_order_tex(self): m = g.trimesh.load(file_name, process=False, maintain_order=True) # use trivial loading to compare with fancy performant one with open(file_name) as f: - f, v, vt = simple_load(f.read()) + f, v, _vt = simple_load(f.read()) # trimesh loader should return the same face order assert g.np.allclose(f, m.faces) assert g.np.allclose(v, m.vertices) @@ -448,7 +448,7 @@ def test_export_normals(self): def test_export_mtl_args(self): mesh = g.trimesh.creation.box() # check for a crash with no materials defined - a, b = g.trimesh.exchange.obj.export_obj( + _a, _b = g.trimesh.exchange.obj.export_obj( mesh, return_texture=True, mtl_name="hi.mtl" ) diff --git a/tests/test_packing.py b/tests/test_packing.py index c56437232..6b500ee00 100644 --- a/tests/test_packing.py +++ b/tests/test_packing.py @@ -72,7 +72,7 @@ def test_obb(self): from trimesh.path import packing nestable = [g.Polygon(i) for i in g.data["nestable"]] - inserted, transforms = packing.polygons(nestable) + _inserted, _transforms = packing.polygons(nestable) def test_image(self): from trimesh.path import packing @@ -157,11 +157,11 @@ def test_3D(self): ) # try packing these 3D boxes - bounds, consume = packing.rectangles_single(e) + _bounds, consume = packing.rectangles_single(e) assert consume.all() # try packing these 3D boxes - bounds, consume = packing.rectangles_single(e, size=[14, 14, 1]) + _bounds, consume = packing.rectangles_single(e, size=[14, 14, 1]) assert not consume.all() def test_transform(self): diff --git a/tests/test_paths.py b/tests/test_paths.py index 1230e4cc1..61c2a44dd 100644 --- a/tests/test_paths.py +++ b/tests/test_paths.py @@ -282,7 +282,7 @@ def test_section(self): ) # Path3D -> Path2D - planar, T = section.to_planar() + planar, _T = section.to_planar() # tube should have one closed polygon assert len(planar.polygons_full) == 1 diff --git a/tests/test_permutate.py b/tests/test_permutate.py index 47debca74..96298c003 100644 --- a/tests/test_permutate.py +++ b/tests/test_permutate.py @@ -22,7 +22,7 @@ def make_assertions(mesh, test, rigid=False): close(test.face_adjacency, mesh.face_adjacency) and len(mesh.faces) > MIN_FACES ): - g.log.error(f"face_adjacency unchanged: {str(test.face_adjacency)}") + g.log.error(f"face_adjacency unchanged: {test.face_adjacency!s}") raise ValueError( "face adjacency of %s the same after permutation!", mesh.metadata["file_name"], @@ -33,7 +33,7 @@ def make_assertions(mesh, test, rigid=False): and len(mesh.faces) > MIN_FACES ): g.log.error( - f"face_adjacency_edges unchanged: {str(test.face_adjacency_edges)}" + f"face_adjacency_edges unchanged: {test.face_adjacency_edges!s}" ) raise ValueError( "face adjacency edges of %s the same after permutation!", diff --git a/tests/test_points.py b/tests/test_points.py index 4c28953ba..1b3724eaf 100644 --- a/tests/test_points.py +++ b/tests/test_points.py @@ -102,7 +102,7 @@ def test_plane(self): # so the true normal should be Z then rotated truth = g.trimesh.transform_points([[0, 0, 1]], matrix, translate=False)[0] # run the plane fit - C, N = g.trimesh.points.plane_fit(p) + _C, N = g.trimesh.points.plane_fit(p) # sign of normal is arbitrary on fit so check both assert g.np.allclose(truth, N) or g.np.allclose(truth, -N) # make sure plane fit works with multiple point sets at once @@ -130,7 +130,7 @@ def test_plane(self): [[0, 0, 1]], matrix, translate=False )[0] # run the plane fit - C, N = g.trimesh.points.plane_fit(p) + _C, N = g.trimesh.points.plane_fit(p) # sign of normal is arbitrary on fit so check both cosines = g.np.einsum("ij,ij->i", N, truths) diff --git a/tests/test_polygons.py b/tests/test_polygons.py index 9b204567e..005923da8 100644 --- a/tests/test_polygons.py +++ b/tests/test_polygons.py @@ -71,7 +71,7 @@ def test_sample(self): assert radius < (1.0 + 1e-8) # try getting OBB of samples - T, extents = g.trimesh.path.polygons.polygon_obb(s) + _T, extents = g.trimesh.path.polygons.polygon_obb(s) # OBB of samples should be less than diameter of circle diameter = g.np.reshape(p.bounds, (2, 2)).ptp(axis=0).max() assert (extents <= diameter).all() @@ -260,7 +260,7 @@ def test_native_centroid(self): for p, c in zip(polygons, coords): # area will be signed with respect to counter-clockwise - ccw, area, centroid = g.trimesh.util.is_ccw(c, return_all=True) + _ccw, area, centroid = g.trimesh.util.is_ccw(c, return_all=True) assert g.np.allclose(centroid, g.np.array(p.centroid.coords)[0]) assert g.np.isclose(abs(area), p.area) diff --git a/tests/test_poses.py b/tests/test_poses.py index 4b183c8c2..43dc4adda 100644 --- a/tests/test_poses.py +++ b/tests/test_poses.py @@ -29,7 +29,7 @@ def test_multiple(self): copied.apply_transform(matrix) # Compute the stable poses of the icosahedron - trans, probs = copied.compute_stable_poses() + _trans, probs = copied.compute_stable_poses() # we are only testing primitives with point symmetry # AKA 3 principal components of inertia are the same @@ -43,8 +43,8 @@ def test_multiple(self): def test_round(self): mesh = g.trimesh.primitives.Cylinder(radius=1.0, height=10.0) - transforms, probabilities = mesh.compute_stable_poses() - transforms, probabilities = mesh.compute_stable_poses(n_samples=10) + _transforms, _probabilities = mesh.compute_stable_poses() + _transforms, _probabilities = mesh.compute_stable_poses(n_samples=10) if __name__ == "__main__": diff --git a/tests/test_proximity.py b/tests/test_proximity.py index 93bd38dbe..83d6cdf44 100644 --- a/tests/test_proximity.py +++ b/tests/test_proximity.py @@ -20,7 +20,7 @@ def test_naive(self): triangles = sphere.triangles # NOQA # do the check - closest, distance, tid = g.trimesh.proximity.closest_point_naive(sphere, points) + closest, distance, _tid = g.trimesh.proximity.closest_point_naive(sphere, points) # the distance from a sphere of radius 1.0 to a sphere of radius 2.0 # should be pretty darn close to 1.0 @@ -98,7 +98,7 @@ def points_on_circle(count): # create a mesh with one triangle mesh = g.Trimesh(**g.trimesh.triangles.to_kwargs([triangle])) - result, result_distance, result_tid = fun(mesh, query) + result, result_distance, _result_tid = fun(mesh, query) polygon = g.Polygon(triangle[:, 0:2]) polygon_buffer = polygon.buffer(1e-5) diff --git a/tests/test_ray.py b/tests/test_ray.py index 46c4f1d6c..37493e955 100644 --- a/tests/test_ray.py +++ b/tests/test_ray.py @@ -102,7 +102,7 @@ def test_on_vertex(self): assert m.ray.intersects_any(ray_origins=origins, ray_directions=vectors).all() - (locations, index_ray, index_tri) = m.ray.intersects_location( + (_locations, index_ray, _index_tri) = m.ray.intersects_location( ray_origins=origins, ray_directions=vectors ) @@ -146,14 +146,14 @@ def test_multiple_hits(self): # Perform 256 * 256 raycasts, one for each pixel on the image # plane. We only want the 'first' hit. - index_triangles, index_ray = cube_mesh.ray.intersects_id( + index_triangles, _index_ray = cube_mesh.ray.intersects_id( ray_origins=ray_origins, ray_directions=ray_directions, multiple_hits=False, ) assert len(g.np.unique(index_triangles)) == 2 - index_triangles, index_ray = cube_mesh.ray.intersects_id( + index_triangles, _index_ray = cube_mesh.ray.intersects_id( ray_origins=ray_origins, ray_directions=ray_directions, multiple_hits=True ) assert len(g.np.unique(index_triangles)) > 2 @@ -192,7 +192,7 @@ def test_box(self): # (n,3) float intersection position in space # (n,) int, index of original ray # (m,) int, index of mesh.faces - pos, ray, tri = mesh.ray.intersects_location( + pos, ray, _tri = mesh.ray.intersects_location( ray_origins=origins, ray_directions=vectors ) @@ -218,7 +218,7 @@ def test_broken(self): for kwargs in [{"use_embree": True}, {"use_embree": False}]: mesh = g.get_mesh("broken.STL", **kwargs) - locations, index_ray, index_tri = mesh.ray.intersects_location( + locations, _index_ray, _index_tri = mesh.ray.intersects_location( ray_origins=ray_origins, ray_directions=ray_directions ) diff --git a/tests/test_registration.py b/tests/test_registration.py index a295a9c9a..44f422cfb 100644 --- a/tests/test_registration.py +++ b/tests/test_registration.py @@ -110,7 +110,7 @@ def test_icp_mesh(self): m = g.trimesh.creation.box() X = m.sample(10) X = X + [0.1, 0.1, 0.1] - matrix, transformed, cost = g.trimesh.registration.icp(X, m, scale=False) + _matrix, _transformed, cost = g.trimesh.registration.icp(X, m, scale=False) assert cost < 0.01 def test_icp_points(self): @@ -157,7 +157,7 @@ def test_mesh(self): truth = g.trimesh.creation.box(extents=extents) for a, b in [[truth, scan], [scan, truth]]: - a_to_b, cost = a.register(b) + a_to_b, _cost = a.register(b) a_check = a.copy() a_check.apply_transform(a_to_b) @@ -172,7 +172,7 @@ def test_mesh(self): points = g.trimesh.transform_points( scan.sample(100), matrix=g.trimesh.transformations.random_rotation_matrix() ) - truth_to_points, cost = truth.register(points) + truth_to_points, _cost = truth.register(points) truth.apply_transform(truth_to_points) distance = truth.nearest.on_surface(points)[1] diff --git a/tests/test_render.py b/tests/test_render.py index 052fd0128..8af7944c9 100644 --- a/tests/test_render.py +++ b/tests/test_render.py @@ -33,7 +33,7 @@ def test_args(self): assert len(args) == 6 assert len(args_auto) == len(args) - P20, T = P30.to_planar() + P20, _T = P30.to_planar() args = rendering.path_to_vertexlist(P20) args_auto = rendering.convert_to_vertexlist(P20) assert len(args) == 6 diff --git a/tests/test_sample.py b/tests/test_sample.py index f9f42f0e5..a34e2094d 100644 --- a/tests/test_sample.py +++ b/tests/test_sample.py @@ -14,7 +14,7 @@ def test_sample(self): distance = m.nearest.signed_distance(samples) assert g.np.abs(distance).max() < 1e-4 - even, index = g.trimesh.sample.sample_surface_even(m, 1000) + even, _index = g.trimesh.sample.sample_surface_even(m, 1000) # check to make sure all samples are on the mesh surface distance = m.nearest.signed_distance(even) assert g.np.abs(distance).max() < 1e-4 @@ -27,7 +27,7 @@ def test_weights(self): weights[0] = 1.0 # sample with passed weights - points, fid = m.sample(count=100, return_index=True, face_weight=weights) + _points, fid = m.sample(count=100, return_index=True, face_weight=weights) # all faces should be on single face assert (fid == 0).all() @@ -42,13 +42,13 @@ def test_color(self): # sample a textured mesh m = g.get_mesh("fuze.obj") - points, index, color = g.trimesh.sample.sample_surface(m, 100, sample_color=True) + points, _index, color = g.trimesh.sample.sample_surface(m, 100, sample_color=True) assert len(points) == len(color) # sample a color mesh m = g.get_mesh("machinist.XAML") assert m.visual.kind == "face" - points, index, color = g.trimesh.sample.sample_surface(m, 100, sample_color=True) + points, _index, color = g.trimesh.sample.sample_surface(m, 100, sample_color=True) assert len(points) == len(color) def test_sample_volume(self): diff --git a/tests/test_section.py b/tests/test_section.py index 2b8e91710..20c6cb040 100644 --- a/tests/test_section.py +++ b/tests/test_section.py @@ -57,7 +57,7 @@ def test_section(self): assert g.np.allclose(section.vertices[:, 2], z) assert len(section.centroid) == 3 - planar, to_3D = section.to_planar() + planar, _to_3D = section.to_planar() assert planar.is_closed assert len(planar.polygons_full) > 0 assert len(planar.centroid) == 2 @@ -72,7 +72,7 @@ def test_section(self): ) # call the multiplane method directly - lines, faces, T = g.trimesh.intersections.mesh_multiplane( + lines, _faces, _T = g.trimesh.intersections.mesh_multiplane( mesh=mesh, plane_origin=[0, 0, 0], plane_normal=plane_normal, diff --git a/tests/test_segments.py b/tests/test_segments.py index 7a023155c..86f44e596 100644 --- a/tests/test_segments.py +++ b/tests/test_segments.py @@ -107,7 +107,7 @@ def test_resample(self): assert g.np.isclose(length(res), length(seg)) # now try with indexes returned - res, index = resample(seg, maxlen=maxlen, return_index=True) + res, _index = resample(seg, maxlen=maxlen, return_index=True) # check lengths of the resampled result assert (length(res, summed=False) < maxlen).all() # make sure overall length hasn't changed diff --git a/tests/test_simplify.py b/tests/test_simplify.py index f9eacd69c..45e4529e9 100644 --- a/tests/test_simplify.py +++ b/tests/test_simplify.py @@ -64,7 +64,7 @@ def test_spline(self): m = scene.geometry["disc_cam_A"] path_3D = m.outline(m.facets[m.facets_area.argmax()]) - path_2D, to_3D = path_3D.to_planar() + path_2D, _to_3D = path_3D.to_planar() simple = g.trimesh.path.simplify.simplify_spline( path_2D, smooth=0.01, verbose=True diff --git a/tests/test_smooth.py b/tests/test_smooth.py index 2f81e1384..66e786b5a 100644 --- a/tests/test_smooth.py +++ b/tests/test_smooth.py @@ -13,7 +13,7 @@ def test_smooth(self): check = g.np.hstack((s.visual.uv, s.vertices)) tree = g.spatial.cKDTree(ori) - distances, index = tree.query(check, k=1) + distances, _index = tree.query(check, k=1) assert distances.max() < 1e-8 # g.texture_equal(m, s) diff --git a/tests/test_stl.py b/tests/test_stl.py index 5b9aa7a28..151e0c80f 100644 --- a/tests/test_stl.py +++ b/tests/test_stl.py @@ -72,6 +72,14 @@ def test_ascii_multibody(self): assert len(s.geometry) == 2 assert set(s.geometry.keys()) == {"bodyA", "bodyB"} + def test_ascii_solid_name(self): + mesh = g.trimesh.creation.icosphere(subdivisions=1, radius=1.0) + mesh.metadata = {"name": "solid_A"} + assert ( + g.trimesh.exchange.stl.export_stl_ascii(mesh).splitlines()[0] + == "solid solid_A" + ) + def test_empty(self): # demo files to check empty_files = ["stl_empty_ascii.stl", "stl_empty_bin.stl"] diff --git a/tests/test_visual.py b/tests/test_visual.py index af8da5b7f..01816a73e 100644 --- a/tests/test_visual.py +++ b/tests/test_visual.py @@ -15,7 +15,7 @@ def test_face_subset_texture_visuals(self): check = m.visual.face_subset(face_index).uv tree = g.spatial.cKDTree(ori) - distances, index = tree.query(check, k=1) + distances, _index = tree.query(check, k=1) assert distances.max() < 1e-8 def test_face_subset_color_visuals(self): @@ -33,7 +33,7 @@ def test_face_subset_color_visuals(self): check = m.visual.face_subset(face_index).vertex_colors tree = g.spatial.cKDTree(ori) - distances, index = tree.query(check, k=1) + distances, _index = tree.query(check, k=1) assert distances.max() < 1e-8 # def test_face_subset_vertex_color(self): diff --git a/trimesh/__init__.py b/trimesh/__init__.py index 829869223..7a0472089 100644 --- a/trimesh/__init__.py +++ b/trimesh/__init__.py @@ -39,8 +39,6 @@ units, util, ) - -# geometry objects from .base import Trimesh # general numeric tolerances @@ -48,6 +46,9 @@ # loader functions from .exchange.load import available_formats, load, load_mesh, load_path, load_remote + +# geometry objects +from .parent import Geometry from .points import PointCloud from .scene.scene import Scene from .transformations import transform_points @@ -73,9 +74,10 @@ __all__ = [ "PointCloud", + "Geometry", "Trimesh", "Scene", - "util", + "Trimesh", "__version__", "available_formats", "boolean", @@ -87,6 +89,7 @@ "creation", "curvature", "decomposition", + "exceptions", "geometry", "graph", "grouping", @@ -114,7 +117,7 @@ "triangles", "unitize", "units", + "util", "utilScene", "voxel", - "exceptions", ] diff --git a/trimesh/caching.py b/trimesh/caching.py index 2fbe4f85c..05aea98fc 100644 --- a/trimesh/caching.py +++ b/trimesh/caching.py @@ -654,7 +654,7 @@ def __setitem__(self, key, data): # will raise if this is not a hashable type hash(data) except BaseException: - raise ValueError("unhashable `{key}:{type(data)}`") + raise ValueError(f"unhashable `{key}:{type(data)}`") tracked = data # apply our mutability setting diff --git a/trimesh/exchange/binvox.py b/trimesh/exchange/binvox.py index bef8e9a8f..5480f37ad 100644 --- a/trimesh/exchange/binvox.py +++ b/trimesh/exchange/binvox.py @@ -426,7 +426,7 @@ def __init__( raise ValueError("Maximum dimension using exact is 1024, got %d" % dimension) if file_type not in Binvoxer.SUPPORTED_OUTPUT_TYPES: raise ValueError( - f"file_type {file_type} not in set of supported output types {str(Binvoxer.SUPPORTED_OUTPUT_TYPES)}" + f"file_type {file_type} not in set of supported output types {Binvoxer.SUPPORTED_OUTPUT_TYPES!s}" ) args = [encoder, "-d", str(dimension), "-t", file_type] if exact: @@ -513,7 +513,7 @@ def __call__(self, path, overwrite=False): ext = ext[1:].lower() if ext not in Binvoxer.SUPPORTED_INPUT_TYPES: raise ValueError( - f"file_type {ext} not in set of supported input types {str(Binvoxer.SUPPORTED_INPUT_TYPES)}" + f"file_type {ext} not in set of supported input types {Binvoxer.SUPPORTED_INPUT_TYPES!s}" ) out_path = f"{head}.{self._file_type}" if os.path.isfile(out_path) and not overwrite: diff --git a/trimesh/exchange/load.py b/trimesh/exchange/load.py index 8922bb058..34f71c0a9 100644 --- a/trimesh/exchange/load.py +++ b/trimesh/exchange/load.py @@ -214,9 +214,7 @@ def load_mesh( loaded = loaded[0] # show the repr for loaded, loader used, and time - log.debug( - f"loaded {str(loaded)} using `{loader.__name__}` in {now() - tic:0.4f}s" - ) + log.debug(f"loaded {loaded!s} using `{loader.__name__}` in {now() - tic:0.4f}s") finally: # if we failed to load close file if opened: diff --git a/trimesh/exchange/stl.py b/trimesh/exchange/stl.py index d5e5e47a7..a82a6d0de 100644 --- a/trimesh/exchange/stl.py +++ b/trimesh/exchange/stl.py @@ -309,7 +309,7 @@ def export_stl_ascii(mesh) -> str: name = "" # concatenate the header, data, and footer, and a new line - return "\n".join(["solid {name}", formatter.format(*blob.reshape(-1)), "endsolid\n"]) + return "\n".join([f"solid {name}", formatter.format(*blob.reshape(-1)), "endsolid\n"]) _stl_loaders = {"stl": load_stl, "stl_ascii": load_stl} diff --git a/trimesh/exchange/threemf.py b/trimesh/exchange/threemf.py index c6a254f19..f1c024496 100644 --- a/trimesh/exchange/threemf.py +++ b/trimesh/exchange/threemf.py @@ -29,7 +29,7 @@ def load_3MF(file_obj, postprocess=True, **kwargs): model = next(iter(v for k, v in archive.items() if "3d/3dmodel.model" in k.lower())) # read root attributes only from XML first - event, root = next(etree.iterparse(model, tag=("{*}model"), events=("start",))) + _event, root = next(etree.iterparse(model, tag=("{*}model"), events=("start",))) # collect unit information from the tree if "unit" in root.attrib: metadata = {"units": root.attrib["unit"]} diff --git a/trimesh/graph.py b/trimesh/graph.py index 22f77c1b1..f3f670df2 100644 --- a/trimesh/graph.py +++ b/trimesh/graph.py @@ -487,7 +487,7 @@ def connected_component_labels(edges, node_count=None): Component labels for each node """ matrix = edges_to_coo(edges, node_count) - body_count, labels = csgraph.connected_components(matrix, directed=False) + _body_count, labels = csgraph.connected_components(matrix, directed=False) if node_count is not None: assert len(labels) == node_count diff --git a/trimesh/nsphere.py b/trimesh/nsphere.py index 6475557f7..a23de86cc 100644 --- a/trimesh/nsphere.py +++ b/trimesh/nsphere.py @@ -187,6 +187,6 @@ def is_nsphere(points): check : bool True if input points are on an nsphere """ - center, radius, error = fit_nsphere(points) + _center, _radius, error = fit_nsphere(points) check = error < tol.merge return check diff --git a/trimesh/path/exchange/load.py b/trimesh/path/exchange/load.py index b7baaaab6..f3d012b2f 100644 --- a/trimesh/path/exchange/load.py +++ b/trimesh/path/exchange/load.py @@ -66,7 +66,7 @@ def load_path(file_obj, file_type=None, **kwargs): raise ValueError("Not a supported object type!") result = load_kwargs(kwargs) - util.log.debug(f"loaded {str(result)} in {util.now() - tic:0.4f}s") + util.log.debug(f"loaded {result!s} in {util.now() - tic:0.4f}s") return result diff --git a/trimesh/path/path.py b/trimesh/path/path.py index 7d615e18c..50ce9702f 100644 --- a/trimesh/path/path.py +++ b/trimesh/path/path.py @@ -403,7 +403,7 @@ def vertex_graph(self): graph : networkx.Graph Holds vertex indexes """ - graph, closed = traversal.vertex_graph(self.entities) + graph, _closed = traversal.vertex_graph(self.entities) return graph @caching.cache_decorator @@ -606,7 +606,7 @@ def remove_duplicate_entities(self): self.entities: length same or shorter """ entity_hashes = np.array([hash(i) for i in self.entities]) - unique, inverse = grouping.unique_rows(entity_hashes) + unique, _inverse = grouping.unique_rows(entity_hashes) if len(unique) != len(self.entities): self.entities = self.entities[unique] diff --git a/trimesh/path/segments.py b/trimesh/path/segments.py index b8a0fc2ef..840afb4bd 100644 --- a/trimesh/path/segments.py +++ b/trimesh/path/segments.py @@ -121,7 +121,7 @@ def colinear_pairs(segments, radius=0.01, angle=0.01, length=None): # convert segments to parameterized origins # which are the closest point on the line to # the actual zero- origin - origins, vectors, param = segments_to_parameters(segments) + origins, vectors, _param = segments_to_parameters(segments) # create a kdtree for origins tree = spatial.cKDTree(origins) diff --git a/trimesh/path/simplify.py b/trimesh/path/simplify.py index 13ca517d7..04c5b6091 100644 --- a/trimesh/path/simplify.py +++ b/trimesh/path/simplify.py @@ -283,7 +283,7 @@ def points_to_spline_entity(points, smooth=None, count=None): points = np.asanyarray(points, dtype=np.float64) closed = np.linalg.norm(points[0] - points[-1]) < tol.merge - knots, control, degree = splprep(points.T, s=smooth)[0] + knots, control, _degree = splprep(points.T, s=smooth)[0] control = np.transpose(control) index = np.arange(len(control)) diff --git a/trimesh/points.py b/trimesh/points.py index f5cf44f7a..7ff60ec25 100644 --- a/trimesh/points.py +++ b/trimesh/points.py @@ -59,7 +59,7 @@ def major_axis(points): axis : (dimension,) float Vector along approximate major axis """ - U, S, V = np.linalg.svd(points) + _U, S, V = np.linalg.svd(points) axis = util.unitize(np.dot(S, V)) return axis @@ -269,7 +269,7 @@ def k_means(points, k, **kwargs): points_std = points.std(axis=0) points_std[points_std < tol.zero] = 1 whitened = points / points_std - centroids_whitened, distortion = kmeans(whitened, k, **kwargs) + centroids_whitened, _distortion = kmeans(whitened, k, **kwargs) centroids = centroids_whitened * points_std # find which centroid each point is closest to diff --git a/trimesh/proximity.py b/trimesh/proximity.py index 2332bafce..e7a423162 100644 --- a/trimesh/proximity.py +++ b/trimesh/proximity.py @@ -400,7 +400,7 @@ def longest_ray(mesh, points, directions): if len(points) != len(directions): raise ValueError("number of points must equal number of directions!") - faces, rays, locations = mesh.ray.intersects_id( + _faces, rays, locations = mesh.ray.intersects_id( points, directions, return_locations=True, multiple_hits=True ) if len(rays) > 0: @@ -503,7 +503,7 @@ def max_tangent_sphere( n_iter = 0 while not_converged.sum() > 0 and n_iter < max_iter: n_iter += 1 - n_points, n_dists, n_faces = mesh.nearest.on_surface(centers[not_converged]) + n_points, n_dists, _n_faces = mesh.nearest.on_surface(centers[not_converged]) # If the distance to the nearest point is the same as the distance # to the start point then we are done. @@ -572,7 +572,7 @@ def thickness(mesh, points, exterior=False, normals=None, method="max_sphere"): normals = mesh.face_normals[closest_point(mesh, points)[2]] if method == "max_sphere": - centers, radius = max_tangent_sphere( + _centers, radius = max_tangent_sphere( mesh=mesh, points=points, inwards=not exterior, normals=normals ) thickness = radius * 2 diff --git a/trimesh/ray/__init__.py b/trimesh/ray/__init__.py index 373b4ef0e..fa8812a98 100644 --- a/trimesh/ray/__init__.py +++ b/trimesh/ray/__init__.py @@ -12,4 +12,4 @@ has_embree = False # add to __all__ as per pep8 -__all__ = ["ray_triangle", "ray_pyembree"] +__all__ = ["ray_pyembree", "ray_triangle"] diff --git a/trimesh/ray/ray_triangle.py b/trimesh/ray/ray_triangle.py index 805909eb8..48ad767e1 100644 --- a/trimesh/ray/ray_triangle.py +++ b/trimesh/ray/ray_triangle.py @@ -146,7 +146,7 @@ def intersects_any(self, ray_origins, ray_directions, **kwargs): hit : (m,) bool Whether any ray hit any triangle on the mesh """ - index_tri, index_ray = self.intersects_id(ray_origins, ray_directions) + _index_tri, index_ray = self.intersects_id(ray_origins, ray_directions) hit_any = np.zeros(len(ray_origins), dtype=bool) hit_idx = np.unique(index_ray) if len(hit_idx) > 0: diff --git a/trimesh/ray/ray_util.py b/trimesh/ray/ray_util.py index 292c7c1a9..57293eaec 100644 --- a/trimesh/ray/ray_util.py +++ b/trimesh/ray/ray_util.py @@ -51,7 +51,7 @@ def contains_points(intersector, points, check_direction=None): ) # cast a ray both forwards and backwards - location, index_ray, c = intersector.intersects_location( + _location, index_ray, _c = intersector.intersects_location( np.vstack((points[inside_aabb], points[inside_aabb])), np.vstack((ray_directions, -ray_directions)), ) diff --git a/trimesh/registration.py b/trimesh/registration.py index 21e476f7a..83600ed4e 100644 --- a/trimesh/registration.py +++ b/trimesh/registration.py @@ -147,7 +147,7 @@ def key_points(m, count): ) # run first pass ICP - matrix, junk, cost = icp( + matrix, _junk, cost = icp( a=points, b=search, initial=a_to_b, max_iterations=int(icp_first), scale=scale ) @@ -156,7 +156,7 @@ def key_points(m, count): costs[i] = cost # run a final ICP refinement step - matrix, junk, cost = icp( + matrix, _junk, cost = icp( a=points, b=search, initial=transforms[np.argmin(costs)], @@ -268,7 +268,7 @@ def procrustes( ((b - bcenter) / bscale).T, ((a - acenter) / ascale) * w.reshape((-1, 1)) ) - u, s, vh = np.linalg.svd(target) + u, _s, vh = np.linalg.svd(target) if reflection: R = np.dot(u, vh) @@ -349,9 +349,9 @@ def icp(a, b, initial=None, threshold=1e-5, max_iterations=20, **kwargs): for _ in range(max_iterations): # Closest point in b to each point in a if is_mesh: - closest, distance, faces = b.nearest.on_surface(a) + closest, _distance, _faces = b.nearest.on_surface(a) else: - distances, ix = btree.query(a, 1) + _distances, ix = btree.query(a, 1) closest = b[ix] # align a with closest points diff --git a/trimesh/typed.py b/trimesh/typed.py index e8e6bc180..a95611934 100644 --- a/trimesh/typed.py +++ b/trimesh/typed.py @@ -41,21 +41,21 @@ Number = Union[float, floating, Integer] __all__ = [ - "NDArray", - "ArrayLike", - "Optional", - "Sequence", - "Iterable", - "Loadable", "IO", + "Any", + "ArrayLike", "BinaryIO", - "List", "Dict", - "Any", + "Integer", + "Iterable", + "List", + "Loadable", + "NDArray", + "Number", + "Optional", + "Sequence", + "Stream", "Tuple", "float64", "int64", - "Number", - "Integer", - "Stream", ] diff --git a/trimesh/util.py b/trimesh/util.py index 1f3a5331a..aaf03d00c 100644 --- a/trimesh/util.py +++ b/trimesh/util.py @@ -237,10 +237,8 @@ def is_sequence(obj) -> bool: is_sequence : bool True if object is sequence """ - seq = ( - not hasattr(obj, "strip") - and hasattr(obj, "__getitem__") - or hasattr(obj, "__iter__") + seq = (not hasattr(obj, "strip") and hasattr(obj, "__getitem__")) or hasattr( + obj, "__iter__" ) # check to make sure it is not a set, string, or dictionary diff --git a/trimesh/viewer/__init__.py b/trimesh/viewer/__init__.py index 78ea03399..e92b649e4 100644 --- a/trimesh/viewer/__init__.py +++ b/trimesh/viewer/__init__.py @@ -30,10 +30,10 @@ # explicitly list imports in __all__ # as otherwise flake8 gets mad __all__ = [ - "SceneWidget", "SceneViewer", - "render_scene", + "SceneWidget", "in_notebook", - "scene_to_notebook", + "render_scene", "scene_to_html", + "scene_to_notebook", ] diff --git a/trimesh/voxel/creation.py b/trimesh/voxel/creation.py index c65b42352..7859a3de6 100644 --- a/trimesh/voxel/creation.py +++ b/trimesh/voxel/creation.py @@ -38,7 +38,7 @@ def voxelize_subdivide(mesh, pitch: float, max_iter: int = 10, edge_factor: floa # get the same mesh sudivided so every edge is shorter # than a factor of our pitch - v, f, idx = remesh.subdivide_to_size( + v, _f, _idx = remesh.subdivide_to_size( mesh.vertices, mesh.faces, max_edge=max_edge, max_iter=max_iter, return_index=True ) @@ -48,7 +48,7 @@ def voxelize_subdivide(mesh, pitch: float, max_iter: int = 10, edge_factor: floa hit = np.round(v / pitch).astype(int) # remove duplicates - unique, inverse = grouping.unique_rows(hit) + unique, _inverse = grouping.unique_rows(hit) # get the voxel centers in model space occupied_index = hit[unique] diff --git a/trimesh/voxel/ops.py b/trimesh/voxel/ops.py index c96552bf7..f29b45ac0 100644 --- a/trimesh/voxel/ops.py +++ b/trimesh/voxel/ops.py @@ -148,7 +148,7 @@ def matrix_to_marching_cubes(matrix, pitch=1.0): vertices, faces = meshed normals = None elif len(meshed) == 4: - vertices, faces, normals, vals = meshed + vertices, faces, normals, _vals = meshed # Return to the origin, add in the pad_width vertices = np.subtract(vertices, pad_width * pitch)