3 Commits

Author SHA1 Message Date
generatedunixname89002005307016
204fe5831b Remove unused type error suppressions (landing group 42)
Summary:
This Phabricator Diff was generated from Pyrefly type-checker output by the per-target upgrade tool. It was not generated by an AI coding system.

It changes only type-error suppression comments: it removes suppressions that are no longer needed and adds `# pyrefly: ignore[...]` comments for remaining errors. It does not change Python runtime behavior or application logic.

Landing group: `74a406ba3ec1f23501f4841695298046d3c8db50f864040e2c4b64506cdb66bd` (attempt 1, 20 batches, 391 files)
Merged patch SHA-256: `c3e986b54ae5248e9810275f66372a9b2047a8e0aa14b3d3301ff8783f4e7e0e`

#pyreupgrade

Differential Revision: D126124958

fbshipit-source-id: f89b7d78ab77074fd80a15de7cef6f1f9fdb4237
2026-10-19 15:24:05 -07:00
Raashish Aggarwal
8b3ba6ede4 Accept tab-separated lines in load_obj (#2061)
Summary:
`load_obj` recognizes vertex, texture, normal and face lines with `line.startswith("v ")`, `"vt "`, `"vn "` and `"f "`. The OBJ format separates fields with any whitespace, and some exporters write a tab after the keyword. Those lines are skipped without any error, so the mesh silently loses vertices and faces:

```python
from io import StringIO
from pytorch3d.io import load_obj

verts, faces, _ = load_obj(StringIO("v\t0 0 0\nv 1 0 0\nv 0 1 0\nf\t1 2 3\n"))
verts.shape, faces.verts_idx.shape
# before: (2, 3), (0, 3)   after: (3, 3), (1, 3)
```

This dispatches on the first token of the already split line (`tokens[:1] == ["v"]`), the same way the `usemtl` branch already does.

Pull Request resolved: https://github.com/facebookresearch/pytorch3d/pull/2061

Test Plan: added `test_load_obj_tab_separated` to `tests/test_io_obj.py`, using tabs in `v`, `vt`, `vn` and `f` lines. It fails on main and passes with the change. I ran `tests/test_io_obj.py` on Windows without the C++ extension: the same 19 tests fail before and after (they reopen a `NamedTemporaryFile` or need `_C`), and the rest pass. flake8 is clean on the changed lines.

Reviewed By: MichaelRamamonjisoa

Differential Revision: D124656223

Pulled By: bottler

fbshipit-source-id: ab0ef3dc0f3c998c44874e6a416e6a9649f29378
2026-10-19 14:36:14 -07:00
generatedunixname89002005307016
88e182f989 Suppress type errors for Pyre upgrade
Summary:
This diff was automatically generated by the Pyre per-target upgrade tool.

It adds `# pyrefly: ignore` comments for type errors that an upcoming Pyrefly version will report. These suppressions keep existing type-checking tests passing while the upgrade rolls out. This diff changes comments only; it does not change Python runtime behavior or application logic.

pyre-upgrade-september-29

#pyreupgrade

Differential Revision: D122460195

fbshipit-source-id: 2ca62cd61e77d222c5b42ac89e73fc570a9781ae
2026-09-29 23:00:50 -07:00
10 changed files with 42 additions and 15 deletions

View File

@@ -104,7 +104,6 @@ class _SymEig3x3(nn.Module):
)
p = torch.sqrt(p2 / 6.0)
# pyrefly: ignore [unsupported-operation]
B = (inputs - q[..., None, None] * self._identity) / p[..., None, None]
r = torch.det(B) / 2.0
@@ -189,10 +188,8 @@ class _SymEig3x3(nn.Module):
"""
# Find the eigenvector corresponding to alpha0, its eigenvalue is distinct
# pyrefly: ignore [unsupported-operation]
ev0 = self._get_ev0(inputs - alpha0[..., None, None] * self._identity)
u, v = self._get_uv(ev0)
# pyrefly: ignore [unsupported-operation]
ev1 = self._get_ev1(inputs - alpha1[..., None, None] * self._identity, u, v)
# Third eigenvector is computed as the cross-product of the other two
ev2 = torch.cross(ev0, ev1, dim=-1)
@@ -267,7 +264,6 @@ class _SymEig3x3(nn.Module):
"""
min_idx = w.abs().argmin(dim=-1)
# pyrefly: ignore [bad-index]
rotation_2d = self._rotations_3d[min_idx].to(w)
u = F.normalize((rotation_2d @ w[..., None])[..., 0], dim=-1)

View File

@@ -182,10 +182,12 @@ def generate_eval_video_cameras(
)
test_cameras = PerspectiveCameras(
# pyrefly: ignore [bad-argument-type]
focal_length=focal_length,
principal_point=principal_point,
R=R,
T=T,
# pyrefly: ignore [missing-attribute]
device=focal_length.device,
)

View File

@@ -472,26 +472,26 @@ def _parse_obj(f, data_dir: str):
materials_idx = len(material_names) - 1
else:
materials_idx = material_names.index(material_name)
elif line.startswith("v "): # Line is a vertex.
elif tokens[:1] == ["v"]: # Line is a vertex.
vert = [float(x) for x in tokens[1:4]]
if len(vert) != 3:
msg = "Vertex %s does not have 3 values. Line: %s"
raise ValueError(msg % (str(vert), str(line)))
verts.append(vert)
elif line.startswith("vt "): # Line is a texture.
elif tokens[:1] == ["vt"]: # Line is a texture.
tx = [float(x) for x in tokens[1:3]]
if len(tx) != 2:
raise ValueError(
"Texture %s does not have 2 values. Line: %s" % (str(tx), str(line))
)
verts_uvs.append(tx)
elif line.startswith("vn "): # Line is a normal.
elif tokens[:1] == ["vn"]: # Line is a normal.
norm = [float(x) for x in tokens[1:4]]
if len(norm) != 3:
msg = "Normal %s does not have 3 values. Line: %s"
raise ValueError(msg % (str(norm), str(line)))
normals.append(norm)
elif line.startswith("f "): # Line is a face.
elif tokens[:1] == ["f"]: # Line is a face.
# Update face properties info.
_parse_face(
line,
@@ -794,7 +794,7 @@ def save_obj(
mtl_path = str(mtl_path)
# Save texture map to output folder
# pyre-fixme[16] # undefined attribute cpu
# undefined attribute cpu
texture_map = texture_map.detach().cpu() * 255.0
image = Image.fromarray(texture_map.numpy().astype(np.uint8))
with _open_file(image_path, path_manager, "wb") as im_f:

View File

@@ -340,8 +340,11 @@ def corresponding_points_alignment(
total_weight = torch.clamp(num_points, 1)
# special handling for heterogeneous point clouds and/or input weights
if weights is not None:
# pyrefly: ignore [bad-index]
Xc *= weights[:, :, None]
# pyrefly: ignore [bad-index]
Yc *= weights[:, :, None]
# pyrefly: ignore [missing-attribute]
total_weight = torch.clamp(weights.sum(1), eps)
if (num_points < (dim + 1)).any():

View File

@@ -427,9 +427,11 @@ class CamerasBase(TensorProperties):
if isinstance(index, tensor_types["bool"]):
# LongTensor]` has no attribute `ndim`.
# LongTensor]` has no attribute `shape`.
# pyrefly: ignore [missing-attribute]
if index.ndim != 1 or index.shape[0] != len(self):
raise ValueError(
# LongTensor]` has no attribute `shape`.
# pyrefly: ignore [missing-attribute]
f"Boolean index of shape {index.shape} does not match cameras"
)
elif max(index) >= len(self):
@@ -1790,11 +1792,13 @@ def get_ndc_to_screen_transform(
image_size = torch.tensor(image_size, device=cameras.device)
# pyrefly: ignore [missing-attribute]
image_size = image_size.view(-1, 2) # of shape (1 or B)x2
# pyrefly: ignore [missing-attribute]
height, width = image_size.unbind(1)
# For non square images, we scale the points such that smallest side
# has range [-1, 1] and the largest side has range [-u, u], with u > 1.
# This convention is consistent with the PyTorch3D renderer
# pyrefly: ignore [missing-attribute]
scale = (image_size.min(dim=1).values - 0.0) / 2.0
K[:, 0, 0] = scale

View File

@@ -136,16 +136,13 @@ class HarmonicEmbedding(torch.nn.Module):
[..., (n_harmonic_functions * 2 + int(append_input)) * num_points_per_ray]
"""
# [..., dim, n_harmonic_functions]
# pyrefly: ignore [unsupported-operation]
embed = x[..., None] * self._frequencies
# [..., 1, dim, n_harmonic_functions] + [2, 1, 1] => [..., 2, dim, n_harmonic_functions]
# pyrefly: ignore [bad-index]
embed = embed[..., None, :, :] + self._zero_half_pi[..., None, None]
# Use the trig identity cos(x) = sin(x + pi/2)
# and do one vectorized call to sin([x, x+pi/2]) instead of (sin(x), cos(x)).
embed = embed.sin()
if diag_cov is not None:
# pyrefly: ignore [no-matching-overload]
x_var = diag_cov[..., None] * torch.pow(self._frequencies, 2)
exp_var = torch.exp(-0.5 * x_var)
# [..., 2, dim, n_harmonic_functions]
@@ -184,7 +181,6 @@ class HarmonicEmbedding(torch.nn.Module):
"""
return self.get_output_dim_static(
input_dims,
# pyrefly: ignore [bad-argument-type]
len(self._frequencies),
self.append_input,
)

View File

@@ -239,12 +239,10 @@ class MeshRasterizer(nn.Module):
if raster_settings.perspective_correct is not None:
perspective_correct = raster_settings.perspective_correct
else:
# pyrefly: ignore [missing-attribute]
perspective_correct = cameras.is_perspective()
if raster_settings.z_clip_value is not None:
z_clip = raster_settings.z_clip_value
else:
# pyrefly: ignore [missing-attribute]
znear = cameras.get_znear()
if isinstance(znear, torch.Tensor):
znear = znear.min().item()

View File

@@ -510,7 +510,9 @@ class Meshes:
index = index.squeeze(1) if index.numel() > 0 else index
# pyrefly: ignore [missing-attribute]
index = index.tolist()
# pyrefly: ignore [not-iterable]
verts = [self.verts_list()[i] for i in index]
# pyrefly: ignore [not-iterable]
faces = [self.faces_list()[i] for i in index]
else:
raise IndexError(index)

View File

@@ -411,10 +411,13 @@ class Pointclouds:
index = index.squeeze(1) if index.numel() > 0 else index
# pyrefly: ignore [missing-attribute]
index = index.tolist()
# pyrefly: ignore [not-iterable]
points = [self.points_list()[i] for i in index]
if normals_list is not None:
# pyrefly: ignore [not-iterable]
normals = [normals_list[i] for i in index]
if features_list is not None:
# pyrefly: ignore [not-iterable]
features = [features_list[i] for i in index]
else:
raise IndexError(index)

View File

@@ -319,6 +319,29 @@ class TestMeshObjIO(TestCaseMixin, unittest.TestCase):
self.assertTrue(materials is None)
self.assertTrue(tex_maps is None)
def test_load_obj_tab_separated(self):
# Tabs are whitespace too, including between the keyword and the values.
obj_file = "\n".join(
[
"v\t0.1\t0.2\t0.3",
"v 0.2 0.3 0.4",
"v\t0.3 0.4 0.5",
"vt\t0.5\t0.5",
"vn\t0.0\t0.0\t1.0",
"f\t1/1/1\t2/1/1\t3/1/1",
]
)
verts, faces, aux = load_obj(StringIO(obj_file))
expected_verts = torch.tensor(
[[0.1, 0.2, 0.3], [0.2, 0.3, 0.4], [0.3, 0.4, 0.5]], dtype=torch.float32
)
self.assertClose(verts, expected_verts)
self.assertClose(faces.verts_idx, torch.tensor([[0, 1, 2]]))
self.assertClose(faces.textures_idx, torch.tensor([[0, 0, 0]]))
self.assertClose(faces.normals_idx, torch.tensor([[0, 0, 0]]))
self.assertClose(aux.verts_uvs, torch.tensor([[0.5, 0.5]]))
self.assertClose(aux.normals, torch.tensor([[0.0, 0.0, 1.0]]))
def test_load_obj_error_textures(self):
obj_file = "\n".join(["vt 0.1"])
with NamedTemporaryFile(mode="w", suffix=".obj") as f: