diff --git a/.github/workflows/core_code_checks.yml b/.github/workflows/core_code_checks.yml index 3e30fba7d..179b4cd9d 100644 --- a/.github/workflows/core_code_checks.yml +++ b/.github/workflows/core_code_checks.yml @@ -32,13 +32,10 @@ jobs: - name: Check notebook cell metadata run: | python ./nerfstudio/scripts/docs/add_nb_tags.py --check - - name: Run isort - run: isort docs/ nerfstudio/ tests/ --profile black --check + - name: Run Ruff + run: ruff docs/ nerfstudio/ tests/ - name: Run Black run: black docs/ nerfstudio/ tests/ --check - - name: Python Pylint - run: | - pylint nerfstudio tests - name: Test with pytest run: | pytest diff --git a/.gitignore b/.gitignore index 7f1688d59..873fe16d9 100644 --- a/.gitignore +++ b/.gitignore @@ -169,9 +169,7 @@ renders/ events.out.* # Data -data -!*/data -!docs/reference/api/data/ +/data # Misc old/ diff --git a/.vscode/settings.json b/.vscode/settings.json index 90f5ae01c..b21aa5301 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -33,7 +33,7 @@ "python.envFile": "${workspaceFolder}/.env", "python.formatting.provider": "black", "python.formatting.blackArgs": ["--line-length=120"], - "python.linting.pylintEnabled": true, + "python.linting.pylintEnabled": false, "python.linting.flake8Enabled": false, "python.linting.enabled": true, "python.sortImports.args": ["--src=${workspaceFolder}", "--profile", "black"], @@ -122,5 +122,6 @@ }, "python.analysis.typeCheckingMode": "basic", "python.analysis.diagnosticMode": "workspace", - "eslint.packageManager": "yarn" + "eslint.packageManager": "yarn", + "ruff.fixAll": true } diff --git a/docs/conf.py b/docs/conf.py index 6c5028b9b..be838235d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,4 +1,3 @@ -# pylint: skip-file # Configuration file for the Sphinx documentation builder. # # This file only contains a selection of the most common options. For a full diff --git a/docs/reference/contributing.md b/docs/reference/contributing.md index 84db92093..5b2a82ad0 100644 --- a/docs/reference/contributing.md +++ b/docs/reference/contributing.md @@ -17,8 +17,8 @@ Below are the various tooling features our team uses to maintain this codebase. | Tooling | Support | | --------------- | ---------------------------------------------------------- | | Formatting | [Black](https://black.readthedocs.io/en/stable/) | -| Linter | [Pylint](https://readthedocs.org/projects/pylint/) | -| Testing | [PyTest](https://docs.pytest.org/en/7.1.x/) | +| Linter | [Ruff](https://beta.ruff.rs/docs/) | +| Testing | [pytest](https://docs.pytest.org/en/7.1.x/) | | Docs | [Sphinx](https://www.sphinx-doc.org/en/master/) | | Docstring style | [Google](https://google.github.io/styleguide/pyguide.html) | | JS Linting | [eslint](https://eslint.org/) | diff --git a/nerfstudio/cameras/camera_optimizers.py b/nerfstudio/cameras/camera_optimizers.py index 44971683e..899833f83 100644 --- a/nerfstudio/cameras/camera_optimizers.py +++ b/nerfstudio/cameras/camera_optimizers.py @@ -74,7 +74,7 @@ class CameraOptimizer(nn.Module): config: CameraOptimizerConfig, num_cameras: int, device: Union[torch.device, str], - **kwargs, # pylint: disable=unused-argument + **kwargs, ) -> None: super().__init__() self.config = config diff --git a/nerfstudio/cameras/cameras.py b/nerfstudio/cameras/cameras.py index 6fdf8e1b5..2bff5575c 100644 --- a/nerfstudio/cameras/cameras.py +++ b/nerfstudio/cameras/cameras.py @@ -35,7 +35,7 @@ from nerfstudio.cameras.rays import RayBundle from nerfstudio.data.scene_box import SceneBox from nerfstudio.utils.tensor_dataclass import TensorDataclass -TORCH_DEVICE = Union[torch.device, str] # pylint: disable=invalid-name +TORCH_DEVICE = Union[torch.device, str] class CameraType(Enum): @@ -306,7 +306,7 @@ class Cameras(TensorDataclass): image_coords = torch.stack(image_coords, dim=-1) + pixel_offset # stored as (y, x) coordinates return image_coords - def generate_rays( # pylint: disable=too-many-statements + def generate_rays( self, camera_indices: Union[Int[Tensor, "*num_rays num_cameras_batch_dims"], int], coords: Optional[Float[Tensor, "*num_rays 2"]] = None, @@ -448,7 +448,7 @@ class Cameras(TensorDataclass): # This will do the actual work of generating the rays now that we have standardized the inputs # raybundle.shape == (num_rays) when done - # pylint: disable=protected-access + raybundle = cameras._generate_rays_from_coords( camera_indices, coords, camera_opt_to_camera, distortion_params_delta, disable_distortion=disable_distortion ) @@ -483,7 +483,6 @@ class Cameras(TensorDataclass): # that we haven't caught yet with tests return raybundle - # pylint: disable=too-many-statements def _generate_rays_from_coords( self, camera_indices: Int[Tensor, "*num_rays num_cameras_batch_dims"], diff --git a/nerfstudio/cameras/lie_groups.py b/nerfstudio/cameras/lie_groups.py index c0fdfbef0..bba85d4de 100644 --- a/nerfstudio/cameras/lie_groups.py +++ b/nerfstudio/cameras/lie_groups.py @@ -21,7 +21,7 @@ from torch import Tensor # We make an exception on snake case conventions because SO3 != so3. -def exp_map_SO3xR3(tangent_vector: Float[Tensor, "b 6"]) -> Float[Tensor, "b 3 4"]: # pylint: disable=invalid-name +def exp_map_SO3xR3(tangent_vector: Float[Tensor, "b 6"]) -> Float[Tensor, "b 3 4"]: """Compute the exponential map of the direct product group `SO(3) x R^3`. This can be used for learning pose deltas on SE(3), and is generally faster than `exp_map_SE3`. @@ -59,7 +59,7 @@ def exp_map_SO3xR3(tangent_vector: Float[Tensor, "b 6"]) -> Float[Tensor, "b 3 4 return ret -def exp_map_SE3(tangent_vector: Float[Tensor, "b 6"]) -> Float[Tensor, "b 3 4"]: # pylint: disable=invalid-name +def exp_map_SE3(tangent_vector: Float[Tensor, "b 6"]) -> Float[Tensor, "b 3 4"]: """Compute the exponential map `se(3) -> SE(3)`. This can be used for learning pose deltas on `SE(3)`. diff --git a/nerfstudio/cameras/rays.py b/nerfstudio/cameras/rays.py index 113622d53..30a3057ba 100644 --- a/nerfstudio/cameras/rays.py +++ b/nerfstudio/cameras/rays.py @@ -26,7 +26,7 @@ from torch import Tensor from nerfstudio.utils.math import Gaussians, conical_frustum_to_gaussian from nerfstudio.utils.tensor_dataclass import TensorDataclass -TORCH_DEVICE = Union[str, torch.device] # pylint: disable=invalid-name +TORCH_DEVICE = Union[str, torch.device] @dataclass diff --git a/nerfstudio/configs/base_config.py b/nerfstudio/configs/base_config.py index 5f8e23e4d..e167ce567 100644 --- a/nerfstudio/configs/base_config.py +++ b/nerfstudio/configs/base_config.py @@ -14,7 +14,6 @@ """Base Configs""" -# pylint: disable=wrong-import-position from __future__ import annotations @@ -30,7 +29,7 @@ warnings.filterwarnings("ignore", module="torchvision") # Pretty printing class -class PrintableConfig: # pylint: disable=too-few-public-methods +class PrintableConfig: """Printable Config defining str function""" def __str__(self): @@ -48,7 +47,7 @@ class PrintableConfig: # pylint: disable=too-few-public-methods # Base instantiate configs @dataclass -class InstantiateConfig(PrintableConfig): # pylint: disable=too-few-public-methods +class InstantiateConfig(PrintableConfig): """Config class for instantiating an the class specified in the _target attribute.""" _target: Type diff --git a/nerfstudio/configs/external_methods.py b/nerfstudio/configs/external_methods.py index b15632cab..11d4541c6 100644 --- a/nerfstudio/configs/external_methods.py +++ b/nerfstudio/configs/external_methods.py @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# pylint: disable=invalid-name """This file contains the configuration for external methods which are not included in this repository.""" import subprocess diff --git a/nerfstudio/data/datamanagers/base_datamanager.py b/nerfstudio/data/datamanagers/base_datamanager.py index 4c2db5843..9cfafc263 100644 --- a/nerfstudio/data/datamanagers/base_datamanager.py +++ b/nerfstudio/data/datamanagers/base_datamanager.py @@ -278,18 +278,18 @@ class DataManager(nn.Module): """Returns the number of rays per batch for evaluation.""" raise NotImplementedError - def get_datapath(self) -> Optional[Path]: # pylint:disable=no-self-use + def get_datapath(self) -> Optional[Path]: """Returns the path to the data. This is used to determine where to save camera paths.""" return None - def get_training_callbacks( # pylint:disable=no-self-use - self, training_callback_attributes: TrainingCallbackAttributes # pylint: disable=unused-argument + def get_training_callbacks( + self, training_callback_attributes: TrainingCallbackAttributes ) -> List[TrainingCallback]: """Returns a list of callbacks to be used during training.""" return [] @abstractmethod - def get_param_groups(self) -> Dict[str, List[Parameter]]: # pylint: disable=no-self-use + def get_param_groups(self) -> Dict[str, List[Parameter]]: """Get the param groups for the data manager. Returns: @@ -338,7 +338,7 @@ class VanillaDataManagerConfig(DataManagerConfig): TDataset = TypeVar("TDataset", bound=InputDataset, default=InputDataset) -class VanillaDataManager(DataManager, Generic[TDataset]): # pylint: disable=abstract-method +class VanillaDataManager(DataManager, Generic[TDataset]): """Basic stored data manager implementation. This is pretty much a port over from our old dataloading utilities, and is a little jank @@ -365,7 +365,7 @@ class VanillaDataManager(DataManager, Generic[TDataset]): # pylint: disable=abs test_mode: Literal["test", "val", "inference"] = "val", world_size: int = 1, local_rank: int = 0, - **kwargs, # pylint: disable=unused-argument + **kwargs, ): self.dataset_type: Type[TDataset] = kwargs.get("_dataset_type", getattr(TDataset, "__default__")) self.config = config @@ -419,9 +419,7 @@ class VanillaDataManager(DataManager, Generic[TDataset]): # pylint: disable=abs scale_factor=self.config.camera_res_scale_factor, ) - def _get_pixel_sampler( # pylint: disable=no-self-use - self, dataset: TDataset, *args: Any, **kwargs: Any - ) -> PixelSampler: + def _get_pixel_sampler(self, dataset: TDataset, *args: Any, **kwargs: Any) -> PixelSampler: """Infer pixel sampler to use.""" if self.config.patch_size > 1: return PatchPixelSampler(*args, **kwargs, patch_size=self.config.patch_size) @@ -530,7 +528,7 @@ class VanillaDataManager(DataManager, Generic[TDataset]): # pylint: disable=abs def get_datapath(self) -> Path: return self.config.dataparser.data - def get_param_groups(self) -> Dict[str, List[Parameter]]: # pylint: disable=no-self-use + def get_param_groups(self) -> Dict[str, List[Parameter]]: """Get the param groups for the data manager. Returns: A list of dictionaries containing the data manager's param groups. diff --git a/nerfstudio/data/dataparsers/nerfstudio_dataparser.py b/nerfstudio/data/dataparsers/nerfstudio_dataparser.py index 1bbf0b455..ea5012179 100644 --- a/nerfstudio/data/dataparsers/nerfstudio_dataparser.py +++ b/nerfstudio/data/dataparsers/nerfstudio_dataparser.py @@ -72,8 +72,6 @@ class Nerfstudio(DataParser): downscale_factor: Optional[int] = None def _generate_dataparser_outputs(self, split="train"): - # pylint: disable=too-many-statements - assert self.config.data.exists(), f"Data directory {self.config.data} does not exist." if self.config.data.suffix == ".json": diff --git a/nerfstudio/data/dataparsers/nuscenes_dataparser.py b/nerfstudio/data/dataparsers/nuscenes_dataparser.py index 056e11ec5..317717e86 100644 --- a/nerfstudio/data/dataparsers/nuscenes_dataparser.py +++ b/nerfstudio/data/dataparsers/nuscenes_dataparser.py @@ -85,8 +85,6 @@ class NuScenes(DataParser): config: NuScenesDataParserConfig def _generate_dataparser_outputs(self, split="train"): - # pylint: disable=too-many-statements - nusc = NuScenesDatabase( version=self.config.version, dataroot=str(self.config.data_dir.absolute()), diff --git a/nerfstudio/data/dataparsers/phototourism_dataparser.py b/nerfstudio/data/dataparsers/phototourism_dataparser.py index ff2a41578..9249ae42a 100644 --- a/nerfstudio/data/dataparsers/phototourism_dataparser.py +++ b/nerfstudio/data/dataparsers/phototourism_dataparser.py @@ -77,7 +77,6 @@ class Phototourism(DataParser): super().__init__(config=config) self.data: Path = config.data - # pylint: disable=too-many-statements def _generate_dataparser_outputs(self, split="train"): image_filenames = [] poses = [] diff --git a/nerfstudio/data/dataparsers/sdfstudio_dataparser.py b/nerfstudio/data/dataparsers/sdfstudio_dataparser.py index 1f6c5c90d..85684aeb8 100644 --- a/nerfstudio/data/dataparsers/sdfstudio_dataparser.py +++ b/nerfstudio/data/dataparsers/sdfstudio_dataparser.py @@ -61,7 +61,7 @@ class SDFStudio(DataParser): config: SDFStudioDataParserConfig - def _generate_dataparser_outputs(self, split="train"): # pylint: disable=unused-argument,too-many-statements + def _generate_dataparser_outputs(self, split="train"): # load meta data meta = load_from_json(self.config.data / "meta_data.json") diff --git a/nerfstudio/data/dataparsers/sitcoms3d_dataparser.py b/nerfstudio/data/dataparsers/sitcoms3d_dataparser.py index 1d90a49d9..1d4bc73c3 100644 --- a/nerfstudio/data/dataparsers/sitcoms3d_dataparser.py +++ b/nerfstudio/data/dataparsers/sitcoms3d_dataparser.py @@ -61,7 +61,7 @@ class Sitcoms3D(DataParser): config: Sitcoms3DDataParserConfig - def _generate_dataparser_outputs(self, split="train"): # pylint: disable=unused-argument,too-many-statements + def _generate_dataparser_outputs(self, split="train"): cameras_json = load_from_json(self.config.data / "cameras.json") frames = cameras_json["frames"] bbox = torch.tensor(cameras_json["bbox"]) diff --git a/nerfstudio/data/datasets/base_dataset.py b/nerfstudio/data/datasets/base_dataset.py index 9cc94c941..8ab110688 100644 --- a/nerfstudio/data/datasets/base_dataset.py +++ b/nerfstudio/data/datasets/base_dataset.py @@ -105,7 +105,6 @@ class InputDataset(Dataset): data.update(metadata) return data - # pylint: disable=no-self-use def get_metadata(self, data: Dict) -> Dict: """Method that can be used to process any additional metadata that may be part of the model inputs. diff --git a/nerfstudio/data/pixel_samplers.py b/nerfstudio/data/pixel_samplers.py index 59a7d18fe..0451e1fe9 100644 --- a/nerfstudio/data/pixel_samplers.py +++ b/nerfstudio/data/pixel_samplers.py @@ -24,7 +24,7 @@ from jaxtyping import Int from torch import Tensor -class PixelSampler: # pylint: disable=too-few-public-methods +class PixelSampler: """Samples 'pixel_batch's from 'image_batch's. Args: @@ -45,7 +45,7 @@ class PixelSampler: # pylint: disable=too-few-public-methods """ self.num_rays_per_batch = num_rays_per_batch - def sample_method( # pylint: disable=no-self-use + def sample_method( self, batch_size: int, num_images: int, @@ -203,7 +203,7 @@ class PixelSampler: # pylint: disable=too-few-public-methods return pixel_batch -class EquirectangularPixelSampler(PixelSampler): # pylint: disable=too-few-public-methods +class EquirectangularPixelSampler(PixelSampler): """Samples 'pixel_batch's from 'image_batch's. Assumes images are equirectangular and the sampling is done uniformly on the sphere. @@ -213,7 +213,7 @@ class EquirectangularPixelSampler(PixelSampler): # pylint: disable=too-few-publ """ # overrides base method - def sample_method( # pylint: disable=no-self-use + def sample_method( self, batch_size: int, num_images: int, @@ -244,7 +244,7 @@ class EquirectangularPixelSampler(PixelSampler): # pylint: disable=too-few-publ return indices -class PatchPixelSampler(PixelSampler): # pylint: disable=too-few-public-methods +class PatchPixelSampler(PixelSampler): """Samples 'pixel_batch's from 'image_batch's. Samples square patches from the images randomly. Useful for patch-based losses. @@ -269,7 +269,7 @@ class PatchPixelSampler(PixelSampler): # pylint: disable=too-few-public-methods self.num_rays_per_batch = (num_rays_per_batch // (self.patch_size**2)) * (self.patch_size**2) # overrides base method - def sample_method( # pylint: disable=no-self-use + def sample_method( self, batch_size: int, num_images: int, diff --git a/nerfstudio/data/utils/colmap_parsing_utils.py b/nerfstudio/data/utils/colmap_parsing_utils.py index aea19e144..818798ec8 100644 --- a/nerfstudio/data/utils/colmap_parsing_utils.py +++ b/nerfstudio/data/utils/colmap_parsing_utils.py @@ -6,8 +6,6 @@ TODO(1480) Delete this file when moving to pycolmap. """ -# pylint: disable-all -# Disabling all pylinting since this file is copy-pasted over from COLMAP # Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. diff --git a/nerfstudio/data/utils/nerfstudio_collate.py b/nerfstudio/data/utils/nerfstudio_collate.py index 5dfcee15f..922b025c0 100644 --- a/nerfstudio/data/utils/nerfstudio_collate.py +++ b/nerfstudio/data/utils/nerfstudio_collate.py @@ -26,16 +26,13 @@ import torch.utils.data from nerfstudio.cameras.cameras import Cameras -# pylint: disable=implicit-str-concat NERFSTUDIO_COLLATE_ERR_MSG_FORMAT = ( "default_collate: batch must contain tensors, numpy arrays, numbers, " "dicts, lists or anything in {}; found {}" ) np_str_obj_array_pattern = re.compile(r"[SaUO]") -def nerfstudio_collate( # pylint: disable=too-many-return-statements - batch: Any, extra_mappings: Union[Dict[type, Callable], None] = None -) -> Any: +def nerfstudio_collate(batch: Any, extra_mappings: Union[Dict[type, Callable], None] = None) -> Any: r""" This is the default pytorch collate function, but with support for nerfstudio types. All documentation below is copied straight over from pytorch's default_collate function, python version 3.8.13, @@ -95,17 +92,16 @@ def nerfstudio_collate( # pylint: disable=too-many-return-statements extra_mappings = {} elem = batch[0] elem_type = type(elem) - if isinstance(elem, torch.Tensor): # pylint: disable=no-else-return + if isinstance(elem, torch.Tensor): out = None if torch.utils.data.get_worker_info() is not None: # If we're in a background process, concatenate directly into a # shared memory tensor to avoid an extra copy numel = sum(x.numel() for x in batch) - storage = elem.storage()._new_shared(numel, device=elem.device) # pylint: disable=protected-access + storage = elem.storage()._new_shared(numel, device=elem.device) out = elem.new(storage).resize_(len(batch), *list(elem.size())) return torch.stack(batch, 0, out=out) elif elem_type.__module__ == "numpy" and elem_type.__name__ != "str_" and elem_type.__name__ != "string_": - # pylint: disable=no-else-return, consider-using-in if elem_type.__name__ == "ndarray" or elem_type.__name__ == "memmap": # array of string classes and object if np_str_obj_array_pattern.search(elem.dtype.str) is not None: diff --git a/nerfstudio/engine/schedulers.py b/nerfstudio/engine/schedulers.py index 2352e92a3..dd9a26699 100644 --- a/nerfstudio/engine/schedulers.py +++ b/nerfstudio/engine/schedulers.py @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# pylint: disable=too-few-public-methods """Scheduler Classes""" diff --git a/nerfstudio/engine/trainer.py b/nerfstudio/engine/trainer.py index 1bceb60ea..dc1dfb586 100644 --- a/nerfstudio/engine/trainer.py +++ b/nerfstudio/engine/trainer.py @@ -51,10 +51,8 @@ from nerfstudio.utils.rich_utils import CONSOLE from nerfstudio.utils.writer import EventName, TimeWriter from nerfstudio.viewer.server.viewer_state import ViewerState -TRAIN_INTERATION_OUTPUT = Tuple[ # pylint: disable=invalid-name - torch.Tensor, Dict[str, torch.Tensor], Dict[str, torch.Tensor] -] -TORCH_DEVICE = str # pylint: disable=invalid-name +TRAIN_INTERATION_OUTPUT = Tuple[torch.Tensor, Dict[str, torch.Tensor], Dict[str, torch.Tensor]] +TORCH_DEVICE = str @dataclass diff --git a/nerfstudio/exporter/exporter_utils.py b/nerfstudio/exporter/exporter_utils.py index a234f8490..68211b5c3 100644 --- a/nerfstudio/exporter/exporter_utils.py +++ b/nerfstudio/exporter/exporter_utils.py @@ -16,7 +16,6 @@ Export utils such as structs, point cloud generation, and rendering code. """ -# pylint: disable=no-member from __future__ import annotations @@ -113,8 +112,6 @@ def generate_point_cloud( Point cloud. """ - # pylint: disable=too-many-statements - progress = Progress( TextColumn(":cloud: Computing Point Cloud :cloud:"), BarColumn(), diff --git a/nerfstudio/exporter/texture_utils.py b/nerfstudio/exporter/texture_utils.py index 72aaf5655..415f658c1 100644 --- a/nerfstudio/exporter/texture_utils.py +++ b/nerfstudio/exporter/texture_utils.py @@ -16,7 +16,6 @@ Texture utils. """ -# pylint: disable=no-member from __future__ import annotations @@ -36,7 +35,7 @@ from nerfstudio.exporter.exporter_utils import Mesh from nerfstudio.pipelines.base_pipeline import Pipeline from nerfstudio.utils.rich_utils import CONSOLE, get_progress -TORCH_DEVICE = Union[torch.device, str] # pylint: disable=invalid-name +TORCH_DEVICE = Union[torch.device, str] def get_parallelogram_area( @@ -97,8 +96,6 @@ def unwrap_mesh_per_uv_triangle( px_per_uv_triangle: The number of pixels per UV triangle. """ - # pylint: disable=too-many-statements - assert len(vertices) == len(vertex_normals), "Number of vertices and vertex normals must be equal" device = vertices.device @@ -241,18 +238,13 @@ def unwrap_mesh_with_xatlas( directions: Tensor of directions for every pixel. """ - # pylint: disable=unused-variable - # pylint: disable=too-many-statements - device = vertices.device # unwrap the mesh vertices_np = vertices.cpu().numpy() faces_np = faces.cpu().numpy() vertex_normals_np = vertex_normals.cpu().cpu().numpy() - vmapping, indices, uvs = xatlas.parametrize( # pylint: disable=c-extension-no-member - vertices_np, faces_np, vertex_normals_np - ) + vmapping, indices, uvs = xatlas.parametrize(vertices_np, faces_np, vertex_normals_np) # vertices texture coordinates vertices_tc = torch.from_numpy(uvs.astype(np.float32)).to(device) @@ -352,8 +344,6 @@ def export_textured_mesh( num_pixels_per_side: The number of pixels per side of the texture image. """ - # pylint: disable=too-many-statements - device = pipeline.device vertices = mesh.vertices.to(device) @@ -431,14 +421,14 @@ def export_textured_mesh( "map_Kd material_0.png", ] lines_mtl = [line + "\n" for line in lines_mtl] - file_mtl = open(output_dir / "material_0.mtl", "w", encoding="utf-8") # pylint: disable=consider-using-with + file_mtl = open(output_dir / "material_0.mtl", "w", encoding="utf-8") file_mtl.writelines(lines_mtl) file_mtl.close() # create the .obj file lines_obj = ["# Generated with nerfstudio", "mtllib material_0.mtl", "usemtl material_0"] lines_obj = [line + "\n" for line in lines_obj] - file_obj = open(output_dir / "mesh.obj", "w", encoding="utf-8") # pylint: disable=consider-using-with + file_obj = open(output_dir / "mesh.obj", "w", encoding="utf-8") file_obj.writelines(lines_obj) # write the geometric vertices diff --git a/nerfstudio/exporter/tsdf_utils.py b/nerfstudio/exporter/tsdf_utils.py index 884751073..70f05caed 100644 --- a/nerfstudio/exporter/tsdf_utils.py +++ b/nerfstudio/exporter/tsdf_utils.py @@ -16,7 +16,6 @@ TSDF utils. """ -# pylint: disable=no-member from __future__ import annotations @@ -36,7 +35,7 @@ from nerfstudio.exporter.exporter_utils import Mesh, render_trajectory from nerfstudio.pipelines.base_pipeline import Pipeline from nerfstudio.utils.rich_utils import CONSOLE -TORCH_DEVICE = Union[torch.device, str] # pylint: disable=invalid-name +TORCH_DEVICE = Union[torch.device, str] @dataclass @@ -305,7 +304,7 @@ def export_tsdf_mesh( device = pipeline.device - dataparser_outputs = pipeline.datamanager.train_dataset._dataparser_outputs # pylint: disable=protected-access + dataparser_outputs = pipeline.datamanager.train_dataset._dataparser_outputs # initialize the TSDF volume if not use_bounding_box: diff --git a/nerfstudio/field_components/__init__.py b/nerfstudio/field_components/__init__.py index 2bd039624..d509df222 100644 --- a/nerfstudio/field_components/__init__.py +++ b/nerfstudio/field_components/__init__.py @@ -12,8 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# pylint:disable=useless-import-alias - """init field modules""" from .base_field_component import FieldComponent as FieldComponent from .encodings import Encoding as Encoding diff --git a/nerfstudio/field_components/activations.py b/nerfstudio/field_components/activations.py index 0f0387012..bc4cc58d0 100644 --- a/nerfstudio/field_components/activations.py +++ b/nerfstudio/field_components/activations.py @@ -21,18 +21,18 @@ from torch.autograd import Function from torch.cuda.amp import custom_bwd, custom_fwd -class _TruncExp(Function): # pylint: disable=abstract-method +class _TruncExp(Function): # Implementation from torch-ngp: # https://github.com/ashawkey/torch-ngp/blob/93b08a0d4ec1cc6e69d85df7f0acdfb99603b628/activation.py @staticmethod @custom_fwd(cast_inputs=torch.float32) - def forward(ctx, x): # pylint: disable=arguments-differ + def forward(ctx, x): ctx.save_for_backward(x) return torch.exp(x) @staticmethod @custom_bwd - def backward(ctx, g): # pylint: disable=arguments-differ + def backward(ctx, g): x = ctx.saved_tensors[0] return g * torch.exp(x.clamp(-15, 15)) diff --git a/nerfstudio/field_components/cuda/__init__.py b/nerfstudio/field_components/cuda/__init__.py index 6c08f9cd3..8b160d066 100644 --- a/nerfstudio/field_components/cuda/__init__.py +++ b/nerfstudio/field_components/cuda/__init__.py @@ -20,7 +20,6 @@ def _make_lazy_cuda_func(name: str) -> Callable: """_make_lazy_cuda_func from nerfacc.cuda""" def call_cuda(*args, **kwargs): - # pylint: disable=import-outside-toplevel from ._backend import _C return getattr(_C, name)(*args, **kwargs) diff --git a/nerfstudio/field_components/temporal_grid.py b/nerfstudio/field_components/temporal_grid.py index 9d9bccc70..71880b375 100644 --- a/nerfstudio/field_components/temporal_grid.py +++ b/nerfstudio/field_components/temporal_grid.py @@ -29,7 +29,6 @@ from torch.cuda.amp import custom_bwd, custom_fwd import nerfstudio.field_components.cuda as _C -# pylint: disable=abstract-method, arguments-differ class TemporalGridEncodeFunc(Function): """Class for autograd in pytorch.""" diff --git a/nerfstudio/fields/nerfplayer_nerfacto_field.py b/nerfstudio/fields/nerfplayer_nerfacto_field.py index 06b3df1b4..0d8ecde48 100644 --- a/nerfstudio/fields/nerfplayer_nerfacto_field.py +++ b/nerfstudio/fields/nerfplayer_nerfacto_field.py @@ -104,7 +104,6 @@ class TemporalHashMLPDensityField(Field): }, ) - # pylint: disable=arguments-differ def density_fn(self, positions: Float[Tensor, "*bs 3"], times: Float[Tensor, "bs 1"]) -> Float[Tensor, "*bs 1"]: """Returns only the density. Used primarily with the density grid. diff --git a/nerfstudio/fields/nerfplayer_ngp_field.py b/nerfstudio/fields/nerfplayer_ngp_field.py index 19b0ba3af..229d5f6dc 100644 --- a/nerfstudio/fields/nerfplayer_ngp_field.py +++ b/nerfstudio/fields/nerfplayer_ngp_field.py @@ -201,7 +201,6 @@ class NerfplayerNGPField(Field): rgb = self.mlp_head(h).view(*ray_samples.frustums.directions.shape[:-1], -1).to(directions) return {FieldHeadNames.RGB: rgb} - # pylint: disable=arguments-differ def density_fn(self, positions: Float[Tensor, "*bs 3"], times: Float[Tensor, "*bs 1"]) -> Float[Tensor, "*bs 1"]: """Returns only the density. Used primarily with the density grid. Overwrite this function since density is time dependent now. diff --git a/nerfstudio/fields/sdf_field.py b/nerfstudio/fields/sdf_field.py index 775dac5ad..358b2d7e5 100644 --- a/nerfstudio/fields/sdf_field.py +++ b/nerfstudio/fields/sdf_field.py @@ -191,13 +191,13 @@ class SDFField(Field): dims = [in_dim] + dims + [3] self.num_layers_color = len(dims) - for l in range(0, self.num_layers_color - 1): - out_dim = dims[l + 1] - lin = nn.Linear(dims[l], out_dim) + for layer in range(0, self.num_layers_color - 1): + out_dim = dims[layer + 1] + lin = nn.Linear(dims[layer], out_dim) if self.config.weight_norm: lin = nn.utils.weight_norm(lin) - setattr(self, "clin" + str(l), lin) + setattr(self, "clin" + str(layer), lin) self.softplus = nn.Softplus(beta=100) self.relu = nn.ReLU() @@ -216,27 +216,27 @@ class SDFField(Field): self.num_layers = len(dims) self.skip_in = [4] - for l in range(0, self.num_layers - 1): - if l + 1 in self.skip_in: - out_dim = dims[l + 1] - dims[0] + for layer in range(0, self.num_layers - 1): + if layer + 1 in self.skip_in: + out_dim = dims[layer + 1] - dims[0] else: - out_dim = dims[l + 1] + out_dim = dims[layer + 1] - lin = nn.Linear(dims[l], out_dim) + lin = nn.Linear(dims[layer], out_dim) if self.config.geometric_init: - if l == self.num_layers - 2: + if layer == self.num_layers - 2: if not self.config.inside_outside: - torch.nn.init.normal_(lin.weight, mean=np.sqrt(np.pi) / np.sqrt(dims[l]), std=0.0001) + torch.nn.init.normal_(lin.weight, mean=np.sqrt(np.pi) / np.sqrt(dims[layer]), std=0.0001) torch.nn.init.constant_(lin.bias, -self.config.bias) else: - torch.nn.init.normal_(lin.weight, mean=-np.sqrt(np.pi) / np.sqrt(dims[l]), std=0.0001) + torch.nn.init.normal_(lin.weight, mean=-np.sqrt(np.pi) / np.sqrt(dims[layer]), std=0.0001) torch.nn.init.constant_(lin.bias, self.config.bias) - elif l == 0: + elif layer == 0: torch.nn.init.constant_(lin.bias, 0.0) torch.nn.init.constant_(lin.weight[:, 3:], 0.0) torch.nn.init.normal_(lin.weight[:, :3], 0.0, np.sqrt(2) / np.sqrt(out_dim)) - elif l in self.skip_in: + elif layer in self.skip_in: torch.nn.init.constant_(lin.bias, 0.0) torch.nn.init.normal_(lin.weight, 0.0, np.sqrt(2) / np.sqrt(out_dim)) torch.nn.init.constant_(lin.weight[:, -(dims[0] - 3) :], 0.0) @@ -246,7 +246,7 @@ class SDFField(Field): if self.config.weight_norm: lin = nn.utils.weight_norm(lin) - setattr(self, "glin" + str(l), lin) + setattr(self, "glin" + str(layer), lin) def set_cos_anneal_ratio(self, anneal: float) -> None: """Set the anneal value for the proposal network.""" @@ -269,15 +269,15 @@ class SDFField(Field): # Pass through layers outputs = inputs - for l in range(0, self.num_layers - 1): - lin = getattr(self, "glin" + str(l)) + for layer in range(0, self.num_layers - 1): + lin = getattr(self, "glin" + str(layer)) - if l in self.skip_in: + if layer in self.skip_in: outputs = torch.cat([outputs, inputs], 1) / np.sqrt(2) outputs = lin(outputs) - if l < self.num_layers - 2: + if layer < self.num_layers - 2: outputs = self.softplus(outputs) return outputs diff --git a/nerfstudio/generative/stable_diffusion.py b/nerfstudio/generative/stable_diffusion.py index 178c5ae46..26a804b1e 100644 --- a/nerfstudio/generative/stable_diffusion.py +++ b/nerfstudio/generative/stable_diffusion.py @@ -61,12 +61,12 @@ class UNet2DConditionOutput: sample: torch.FloatTensor -class _SDSGradient(torch.autograd.Function): # pylint: disable=abstract-method +class _SDSGradient(torch.autograd.Function): """Custom gradient function for SDS loss. Since it is already computed, we can just return it.""" @staticmethod @custom_fwd - def forward(ctx, input_tensor, gt_grad): # pylint: disable=arguments-differ + def forward(ctx, input_tensor, gt_grad): del input_tensor ctx.save_for_backward(gt_grad) # Return magniture of gradient, not the actual loss. @@ -74,7 +74,7 @@ class _SDSGradient(torch.autograd.Function): # pylint: disable=abstract-method @staticmethod @custom_bwd - def backward(ctx, grad): # pylint: disable=arguments-differ + def backward(ctx, grad): del grad (gt_grad,) = ctx.saved_tensors batch_size = len(gt_grad) @@ -127,7 +127,7 @@ class StableDiffusion(nn.Module): self.in_channels = pipe.unet.in_channels self.device = pipe.unet.device - def forward(self, latent_model_input, t, encoder_hidden_states): # pylint: disable=no-self-use + def forward(self, latent_model_input, t, encoder_hidden_states): """Forward pass""" sample = unet_traced(latent_model_input, t, encoder_hidden_states)[0] return UNet2DConditionOutput(sample=sample) diff --git a/nerfstudio/model_components/losses.py b/nerfstudio/model_components/losses.py index b2d492f68..ed766c10d 100644 --- a/nerfstudio/model_components/losses.py +++ b/nerfstudio/model_components/losses.py @@ -518,18 +518,18 @@ def tv_loss(grids: Float[Tensor, "grids feature_dim row column"]) -> Float[Tenso return 2 * (h_tv / h_tv_count + w_tv / w_tv_count) / number_of_grids -class _GradientScaler(torch.autograd.Function): # typing: ignore, pylint: disable=abstract-method +class _GradientScaler(torch.autograd.Function): # typing: ignore """ Scale gradients by a constant factor. """ @staticmethod - def forward(ctx, value, scaling): # pylint: disable=arguments-differ + def forward(ctx, value, scaling): ctx.save_for_backward(scaling) return value, scaling @staticmethod - def backward(ctx, output_grad, grad_scaling): # pylint: disable=arguments-differ + def backward(ctx, output_grad, grad_scaling): (scaling,) = ctx.saved_tensors return output_grad * scaling, grad_scaling diff --git a/nerfstudio/model_components/ray_samplers.py b/nerfstudio/model_components/ray_samplers.py index 388ddae5a..fa97905a3 100644 --- a/nerfstudio/model_components/ray_samplers.py +++ b/nerfstudio/model_components/ray_samplers.py @@ -423,7 +423,6 @@ class VolumetricSampler(Sampler): "The VolumetricSampler fuses sample generation and density check together. Please call forward() directly." ) - # pylint: disable=arguments-differ def forward( self, ray_bundle: RayBundle, diff --git a/nerfstudio/model_components/renderers.py b/nerfstudio/model_components/renderers.py index 88440f4f6..da3277908 100644 --- a/nerfstudio/model_components/renderers.py +++ b/nerfstudio/model_components/renderers.py @@ -46,7 +46,7 @@ BACKGROUND_COLOR_OVERRIDE: Optional[Float[Tensor, "3"]] = None @contextlib.contextmanager def background_color_override_context(mode: Float[Tensor, "3"]) -> Generator[None, None, None]: """Context manager for setting background mode.""" - global BACKGROUND_COLOR_OVERRIDE # pylint: disable=global-statement + global BACKGROUND_COLOR_OVERRIDE old_background_color = BACKGROUND_COLOR_OVERRIDE try: BACKGROUND_COLOR_OVERRIDE = mode diff --git a/nerfstudio/models/base_model.py b/nerfstudio/models/base_model.py index 71d795945..046167f72 100644 --- a/nerfstudio/models/base_model.py +++ b/nerfstudio/models/base_model.py @@ -89,8 +89,8 @@ class Model(nn.Module): """Returns the device that the model is on.""" return self.device_indicator_param.device - def get_training_callbacks( # pylint:disable=no-self-use - self, training_callback_attributes: TrainingCallbackAttributes # pylint: disable=unused-argument + def get_training_callbacks( + self, training_callback_attributes: TrainingCallbackAttributes ) -> List[TrainingCallback]: """Returns a list of callbacks that run functions at the specified training iterations.""" return [] @@ -146,8 +146,7 @@ class Model(nn.Module): outputs: the output to compute loss dict to batch: ground truth batch corresponding to outputs """ - # pylint: disable=unused-argument - # pylint: disable=no-self-use + return {} @abstractmethod diff --git a/nerfstudio/models/depth_nerfacto.py b/nerfstudio/models/depth_nerfacto.py index 0dd1476a9..0bbde5cde 100644 --- a/nerfstudio/models/depth_nerfacto.py +++ b/nerfstudio/models/depth_nerfacto.py @@ -129,7 +129,7 @@ class DepthNerfactoModel(NerfactoModel): if not self.config.should_decay_sigma: return self.depth_sigma - self.depth_sigma = torch.maximum( # pylint: disable=attribute-defined-outside-init + self.depth_sigma = torch.maximum( self.config.sigma_decay_rate * self.depth_sigma, torch.tensor([self.config.depth_sigma]) ) return self.depth_sigma diff --git a/nerfstudio/models/nerfplayer_nerfacto.py b/nerfstudio/models/nerfplayer_nerfacto.py index 9facfe580..38150905b 100644 --- a/nerfstudio/models/nerfplayer_nerfacto.py +++ b/nerfstudio/models/nerfplayer_nerfacto.py @@ -249,12 +249,12 @@ class NerfplayerNerfactoModel(NerfactoModel): mask = (batch["depth_image"] != 0).view([-1]) loss_dict["depth_loss"] = 0 - def l(x): + def compute_depth_loss(x): return self.config.depth_weight * (x - batch["depth_image"][mask]).pow(2).mean() - loss_dict["depth_loss"] = l(outputs["depth"][mask]) + loss_dict["depth_loss"] = compute_depth_loss(outputs["depth"][mask]) for i in range(self.config.num_proposal_iterations): - loss_dict["depth_loss"] += l(outputs[f"prop_depth_{i}"][mask]) + loss_dict["depth_loss"] += compute_depth_loss(outputs[f"prop_depth_{i}"][mask]) if self.config.temporal_tv_weight > 0: loss_dict["temporal_tv_loss"] = self.field.mlp_base.get_temporal_tv_loss() for net in self.proposal_networks: diff --git a/nerfstudio/models/tensorf.py b/nerfstudio/models/tensorf.py index df12c7bc9..5cbb906b6 100644 --- a/nerfstudio/models/tensorf.py +++ b/nerfstudio/models/tensorf.py @@ -129,9 +129,7 @@ class TensoRFModel(Model): self, training_callback_attributes: TrainingCallbackAttributes ) -> List[TrainingCallback]: # the callback that we want to run every X iterations after the training iteration - def reinitialize_optimizer( - self, training_callback_attributes: TrainingCallbackAttributes, step: int # pylint: disable=unused-argument - ): + def reinitialize_optimizer(self, training_callback_attributes: TrainingCallbackAttributes, step: int): index = self.upsampling_iters.index(step) resolution = self.upsampling_steps[index] diff --git a/nerfstudio/pipelines/base_pipeline.py b/nerfstudio/pipelines/base_pipeline.py index b51d31370..9e80425cb 100644 --- a/nerfstudio/pipelines/base_pipeline.py +++ b/nerfstudio/pipelines/base_pipeline.py @@ -90,8 +90,6 @@ class Pipeline(nn.Module): model: The model that will be used """ - # pylint: disable=abstract-method - datamanager: DataManager _model: Model world_size: int diff --git a/nerfstudio/pipelines/dynamic_batch.py b/nerfstudio/pipelines/dynamic_batch.py index 57e7afa72..fda064c07 100644 --- a/nerfstudio/pipelines/dynamic_batch.py +++ b/nerfstudio/pipelines/dynamic_batch.py @@ -39,8 +39,6 @@ class DynamicBatchPipelineConfig(VanillaPipelineConfig): class DynamicBatchPipeline(VanillaPipeline): """Pipeline with logic for changing the number of rays per batch.""" - # pylint: disable=abstract-method - config: DynamicBatchPipelineConfig datamanager: VanillaDataManager dynamic_num_rays_per_batch: int diff --git a/nerfstudio/plugins/registry.py b/nerfstudio/plugins/registry.py index 2e4b00cde..808772678 100644 --- a/nerfstudio/plugins/registry.py +++ b/nerfstudio/plugins/registry.py @@ -63,7 +63,7 @@ def discover_methods() -> t.Tuple[t.Dict[str, TrainerConfig], t.Dict[str, str]]: assert isinstance(method_config, MethodSpecification) methods[name] = method_config.config descriptions[name] = method_config.description - except Exception: # pylint: disable=broad-except + except Exception: CONSOLE.print_exception() CONSOLE.print("[bold red]Error: Could not load methods from environment variable NERFSTUDIO_METHOD_CONFIGS") diff --git a/nerfstudio/process_data/base_converter_to_nerfstudio_dataset.py b/nerfstudio/process_data/base_converter_to_nerfstudio_dataset.py index 66b34864d..e46601479 100644 --- a/nerfstudio/process_data/base_converter_to_nerfstudio_dataset.py +++ b/nerfstudio/process_data/base_converter_to_nerfstudio_dataset.py @@ -37,7 +37,7 @@ class BaseConverterToNerfstudioDataset(ABC): self.image_dir.mkdir(parents=True, exist_ok=True) @property - def image_dir(self) -> Path: # pylint: disable=missing-function-docstring + def image_dir(self) -> Path: return self.output_dir / "images" @abstractmethod diff --git a/nerfstudio/process_data/colmap_converter_to_nerfstudio_dataset.py b/nerfstudio/process_data/colmap_converter_to_nerfstudio_dataset.py index 41cad1326..3203b16b0 100644 --- a/nerfstudio/process_data/colmap_converter_to_nerfstudio_dataset.py +++ b/nerfstudio/process_data/colmap_converter_to_nerfstudio_dataset.py @@ -98,15 +98,15 @@ class ColmapConverterToNerfstudioDataset(BaseConverterToNerfstudioDataset): """If --use-sfm-depth and this flag is True, also export debug images showing Sf overlaid upon input images.""" @staticmethod - def default_colmap_path() -> Path: # pylint: disable=missing-function-docstring + def default_colmap_path() -> Path: return Path("colmap/sparse/0") @property - def absolute_colmap_model_path(self) -> Path: # pylint: disable=missing-function-docstring + def absolute_colmap_model_path(self) -> Path: return self.output_dir / self.colmap_model_path @property - def absolute_colmap_path(self) -> Path: # pylint: disable=missing-function-docstring + def absolute_colmap_path(self) -> Path: return self.output_dir / "colmap" def _save_transforms( diff --git a/nerfstudio/process_data/colmap_utils.py b/nerfstudio/process_data/colmap_utils.py index abe17fa41..b94f530cc 100644 --- a/nerfstudio/process_data/colmap_utils.py +++ b/nerfstudio/process_data/colmap_utils.py @@ -176,7 +176,7 @@ def run_colmap( CONSOLE.log("[bold green]:tada: Done refining intrinsics.") -def parse_colmap_camera_params(camera) -> Dict[str, Any]: # pylint: disable=too-many-statements +def parse_colmap_camera_params(camera) -> Dict[str, Any]: """ Parses all currently supported COLMAP cameras into the transforms.json metadata @@ -514,7 +514,7 @@ def create_sfm_depth( im_id_to_image = read_images_binary(recon_dir / "images.bin") # Only support first camera - CAMERA_ID = 1 # pylint: disable=invalid-name + CAMERA_ID = 1 W = cam_id_to_camera[CAMERA_ID].width H = cam_id_to_camera[CAMERA_ID].height diff --git a/nerfstudio/process_data/hloc_utils.py b/nerfstudio/process_data/hloc_utils.py index 44bed7afe..2dbf58788 100644 --- a/nerfstudio/process_data/hloc_utils.py +++ b/nerfstudio/process_data/hloc_utils.py @@ -110,9 +110,7 @@ def run_hloc( pairs_from_retrieval.main(retrieval_path, sfm_pairs, num_matched=num_matched) match_features.main(matcher_conf, sfm_pairs, features=features, matches=matches) - image_options = pycolmap.ImageReaderOptions( # pylint: disable=c-extension-no-member - camera_model=camera_model.value - ) + image_options = pycolmap.ImageReaderOptions(camera_model=camera_model.value) if refine_pixsfm: sfm = PixSfM( conf={ @@ -128,7 +126,7 @@ def run_hloc( features, matches, image_list=references, - camera_mode=pycolmap.CameraMode.SINGLE, # pylint: disable=c-extension-no-member + camera_mode=pycolmap.CameraMode.SINGLE, image_options=image_options, verbose=verbose, ) @@ -141,7 +139,7 @@ def run_hloc( sfm_pairs, features, matches, - camera_mode=pycolmap.CameraMode.SINGLE, # pylint: disable=c-extension-no-member + camera_mode=pycolmap.CameraMode.SINGLE, image_options=image_options, verbose=verbose, ) diff --git a/nerfstudio/process_data/images_to_nerfstudio_dataset.py b/nerfstudio/process_data/images_to_nerfstudio_dataset.py index 0ac505013..4c0a5bf03 100644 --- a/nerfstudio/process_data/images_to_nerfstudio_dataset.py +++ b/nerfstudio/process_data/images_to_nerfstudio_dataset.py @@ -32,10 +32,9 @@ class ImagesToNerfstudioDataset(ColmapConverterToNerfstudioDataset): 2. Calculates the camera poses for each image using `COLMAP `_. """ - def main(self) -> None: # pylint: disable=R0915 + def main(self) -> None: """Process images into a nerfstudio dataset.""" - # pylint: disable=too-many-statements require_cameras_exist = False if self.colmap_model_path != ColmapConverterToNerfstudioDataset.default_colmap_path(): if not self.skip_colmap: diff --git a/nerfstudio/process_data/metashape_utils.py b/nerfstudio/process_data/metashape_utils.py index c1c2d5093..3acfdcde6 100644 --- a/nerfstudio/process_data/metashape_utils.py +++ b/nerfstudio/process_data/metashape_utils.py @@ -32,7 +32,7 @@ def _find_param(calib_xml: ET.Element, param_name: str): return 0.0 -def metashape_to_json( # pylint: disable=too-many-statements +def metashape_to_json( image_filename_map: Dict[str, Path], xml_filename: Path, output_dir: Path, diff --git a/nerfstudio/process_data/video_to_nerfstudio_dataset.py b/nerfstudio/process_data/video_to_nerfstudio_dataset.py index a570e6d44..13e4b6bc4 100644 --- a/nerfstudio/process_data/video_to_nerfstudio_dataset.py +++ b/nerfstudio/process_data/video_to_nerfstudio_dataset.py @@ -40,7 +40,7 @@ class VideoToNerfstudioDataset(ColmapConverterToNerfstudioDataset): percent_radius_crop: float = 1.0 """Create circle crop mask. The radius is the percent of the image diagonal.""" - def main(self) -> None: # pylint: disable=R0915 + def main(self) -> None: """Process video into a nerfstudio dataset.""" summary_log = [] diff --git a/nerfstudio/scripts/blender/nerfstudio_blender.py b/nerfstudio/scripts/blender/nerfstudio_blender.py index 0da0fc2da..8a2fa9908 100644 --- a/nerfstudio/scripts/blender/nerfstudio_blender.py +++ b/nerfstudio/scripts/blender/nerfstudio_blender.py @@ -29,13 +29,12 @@ bl_info = { "category": "Nerfstudio", } -# pylint: disable=wrong-import-position -import json -from math import atan, degrees, radians, tan -# pylint: disable=import-error -import bpy -from mathutils import Matrix +import json # noqa: E402 +from math import atan, degrees, radians, tan # noqa: E402 + +import bpy # noqa: E402 +from mathutils import Matrix # noqa: E402 class CreateJSONCameraPath(bpy.types.Operator): @@ -100,12 +99,12 @@ class CreateJSONCameraPath(bpy.types.Operator): for i, org_cam_path_mat_val in enumerate(org_camera_path_mat): self.transformed_camera_path_mat += [nerf_mesh_mat_list[i].inverted() @ org_cam_path_mat_val] - def get_list_from_matrix_path(self, input_mat): # pylint: disable=no-self-use + def get_list_from_matrix_path(self, input_mat): """Flatten matrix to list for camera path.""" full_arr = list(input_mat.row[0]) + list(input_mat.row[1]) + list(input_mat.row[2]) + list(input_mat.row[3]) return full_arr - def get_list_from_matrix_keyframe(self, input_mat): # pylint: disable=no-self-use + def get_list_from_matrix_keyframe(self, input_mat): """Flatten matrix to list for keyframes.""" full_arr = list(input_mat.col[0]) + list(input_mat.col[1]) + list(input_mat.col[2]) + list(input_mat.col[3]) return full_arr @@ -343,7 +342,7 @@ class ReadJSONinputCameraPath(bpy.types.Operator): # --- Blender UI Panel --- # -class NerfstudioMainPanel(bpy.types.Panel): # pylint: disable=too-few-public-methods +class NerfstudioMainPanel(bpy.types.Panel): """Blender UI main panel for the add-on.""" bl_idname = "NERFSTUDIO_PT_NerfstudioMainPanel" @@ -360,7 +359,7 @@ class NerfstudioMainPanel(bpy.types.Panel): # pylint: disable=too-few-public-me _ = self.layout.column() -class NerfstudioBgPanel(bpy.types.Panel): # pylint: disable=too-few-public-methods +class NerfstudioBgPanel(bpy.types.Panel): """Blender UI sub-panel for the camera path creation.""" bl_idname = "NERFSTUDIO_PT_NerfstudioBgPanel" @@ -383,7 +382,7 @@ class NerfstudioBgPanel(bpy.types.Panel): # pylint: disable=too-few-public-meth col.operator("opr.create_json_camera_path", text="Generate JSON File") -class NerfstudioInputPanel(bpy.types.Panel): # pylint: disable=too-few-public-methods +class NerfstudioInputPanel(bpy.types.Panel): """Blender UI sub-panel for the Blender camera creation.""" bl_idname = "NERFSTUDIO_PT_NerfstudioInputPanel" diff --git a/nerfstudio/scripts/docs/build_docs.py b/nerfstudio/scripts/docs/build_docs.py index 38534ed8f..3d060670b 100644 --- a/nerfstudio/scripts/docs/build_docs.py +++ b/nerfstudio/scripts/docs/build_docs.py @@ -22,8 +22,6 @@ from rich.style import Style from nerfstudio.utils.rich_utils import CONSOLE -LOCAL_TESTS = ["Run license checks", "Run Black", "Python Pylint", "Test with pytest"] - def run_command(command: str) -> None: """Run a command kill actions if it fails diff --git a/nerfstudio/scripts/downloads/download_data.py b/nerfstudio/scripts/downloads/download_data.py index e725bbca6..0bf9039d1 100644 --- a/nerfstudio/scripts/downloads/download_data.py +++ b/nerfstudio/scripts/downloads/download_data.py @@ -248,7 +248,6 @@ class DNerfDownload(DatasetDownload): download_path.unlink() -# pylint: disable=line-too-long phototourism_downloads = { "brandenburg-gate": "https://www.cs.ubc.ca/research/kmyi_data/imw2020/TrainingData/brandenburg_gate.tar.gz", "buckingham-palace": "https://www.cs.ubc.ca/research/kmyi_data/imw2020/TrainingData/buckingham_palace.tar.gz", @@ -311,7 +310,7 @@ class PhototourismDownload(DatasetDownload): # credit to https://autonomousvision.github.io/sdfstudio/ -# pylint: disable=line-too-long + sdfstudio_downloads = { "sdfstudio-demo-data": "https://s3.eu-central-1.amazonaws.com/avg-projects/monosdf/data/sdfstudio-demo-data.tar", "dtu": "https://s3.eu-central-1.amazonaws.com/avg-projects/monosdf/data/DTU.tar", @@ -382,7 +381,6 @@ class SDFstudioDemoDownload(DatasetDownload): os.remove(download_path) -# pylint: disable=line-too-long nerfosr_downloads = { "europa": "https://nextcloud.mpi-klsb.mpg.de/index.php/s/mGXYKpD8raQ8nMk/download?path=%2FData&files=europa&downloadStartSecret=0k2r95c1fdej", "lk2": "https://nextcloud.mpi-klsb.mpg.de/index.php/s/mGXYKpD8raQ8nMk/download?path=%2FData&files=lk2&downloadStartSecret=w8kuvjzmchc", diff --git a/nerfstudio/scripts/exporter.py b/nerfstudio/scripts/exporter.py index 8a4101115..aee9723a9 100644 --- a/nerfstudio/scripts/exporter.py +++ b/nerfstudio/scripts/exporter.py @@ -16,7 +16,6 @@ Script for exporting NeRF into other formats. """ -# pylint: disable=no-member from __future__ import annotations diff --git a/nerfstudio/scripts/github/run_actions.py b/nerfstudio/scripts/github/run_actions.py index 70a2fbbe3..0f8618921 100644 --- a/nerfstudio/scripts/github/run_actions.py +++ b/nerfstudio/scripts/github/run_actions.py @@ -23,7 +23,7 @@ from rich.style import Style from nerfstudio.utils.rich_utils import CONSOLE -LOCAL_TESTS = ["Run license checks", "Run isort", "Run Black", "Python Pylint", "Test with pytest"] +LOCAL_TESTS = ["Run license checks", "Run Ruff", "Run Black", "Test with pytest"] def run_command(command: str, continue_on_fail: bool = False) -> bool: @@ -57,8 +57,10 @@ def run_github_actions_file(filename: str, continue_on_fail: bool = False): for step in steps: if "name" in step and step["name"] in LOCAL_TESTS: compressed = step["run"].replace("\n", ";").replace("\\", "") - compressed = compressed.replace("--check", "") - curr_command = f"{compressed}" + if "ruff" in compressed: + curr_command = f"{compressed} --fix" + else: + curr_command = compressed.replace("--check", "") CONSOLE.line() CONSOLE.rule(f"[bold green]Running: {curr_command}") diff --git a/nerfstudio/scripts/texture.py b/nerfstudio/scripts/texture.py index 0a95d0e5d..c1dbcd0f6 100644 --- a/nerfstudio/scripts/texture.py +++ b/nerfstudio/scripts/texture.py @@ -52,7 +52,6 @@ class TextureMesh: def main(self) -> None: """Export textured mesh""" - # pylint: disable=too-many-statements if not self.output_dir.exists(): self.output_dir.mkdir(parents=True) diff --git a/nerfstudio/utils/misc.py b/nerfstudio/utils/misc.py index 655427978..48bd8f29c 100644 --- a/nerfstudio/utils/misc.py +++ b/nerfstudio/utils/misc.py @@ -71,7 +71,7 @@ def get_masked_dict(d, mask): return masked_dict -class IterableWrapper: # pylint: disable=too-few-public-methods +class IterableWrapper: """A helper that will allow an instance of a class to return multiple kinds of iterables bound to different functions of that class. diff --git a/nerfstudio/utils/poses.py b/nerfstudio/utils/poses.py index e0f495747..d0c7c15cc 100644 --- a/nerfstudio/utils/poses.py +++ b/nerfstudio/utils/poses.py @@ -46,7 +46,7 @@ def inverse(pose: Float[Tensor, "*batch 3 4"]) -> Float[Tensor, "*batch 3 4"]: """ R = pose[..., :3, :3] t = pose[..., :3, 3:] - R_inverse = R.transpose(-2, -1) # pylint: disable=invalid-name + R_inverse = R.transpose(-2, -1) t_inverse = -R_inverse.matmul(t) return torch.cat([R_inverse, t_inverse], dim=-1) diff --git a/nerfstudio/utils/profiler.py b/nerfstudio/utils/profiler.py index a119f923c..4bfac28f0 100644 --- a/nerfstudio/utils/profiler.py +++ b/nerfstudio/utils/profiler.py @@ -77,7 +77,7 @@ def time_function(name_or_func: Union[CallableT, str]) -> Union[CallableT, Conte return _TimeFunction(name_or_func) -class _TimeFunction(ContextDecorator): # pylint: disable=invalid-name +class _TimeFunction(ContextDecorator): """Decorator/Context manager: time a function call or a block of code""" def __init__(self, name: Union[str, Callable]): @@ -105,7 +105,7 @@ class _TimeFunction(ContextDecorator): # pylint: disable=invalid-name if self._function_call_args is not None: args, kwargs = self._function_call_args ctx = PYTORCH_PROFILER.record_function(self.name, *args, **kwargs) - ctx.__enter__() # pylint: disable=no-member + ctx.__enter__() self._profiler_contexts.append(ctx) if self._function_call_args is None: ctx = record_function(self.name) @@ -139,14 +139,14 @@ def flush_profiler(config: cfg.LoggingConfig): def setup_profiler(config: cfg.LoggingConfig, log_dir: Path): """Initialization of profilers""" - global PYTORCH_PROFILER # pylint: disable=global-statement + global PYTORCH_PROFILER if comms.is_main_process(): PROFILER.append(Profiler(config)) if config.profiler == "pytorch": PYTORCH_PROFILER = PytorchProfiler(log_dir) -class PytorchProfiler: # pylint: disable=too-few-public-methods +class PytorchProfiler: """ Wrapper for Pytorch Profiler """ diff --git a/nerfstudio/utils/tensor_dataclass.py b/nerfstudio/utils/tensor_dataclass.py index cbf7d5533..f64414fad 100644 --- a/nerfstudio/utils/tensor_dataclass.py +++ b/nerfstudio/utils/tensor_dataclass.py @@ -107,7 +107,6 @@ class TensorDataclass: for k, v in dict_.items(): if isinstance(v, torch.Tensor): if isinstance(self._field_custom_dimensions, dict) and k in self._field_custom_dimensions: - # pylint: disable=unsubscriptable-object batch_shapes.append(v.shape[: -self._field_custom_dimensions[k]]) else: batch_shapes.append(v.shape[:-1]) @@ -131,7 +130,6 @@ class TensorDataclass: if isinstance(v, torch.Tensor): # If custom dimension key, then we need to if isinstance(self._field_custom_dimensions, dict) and k in self._field_custom_dimensions: - # pylint: disable=unsubscriptable-object new_dict[k] = v.broadcast_to( ( *batch_shape, @@ -160,7 +158,7 @@ class TensorDataclass: return x[indices] def custom_tensor_dims_fn(k, v): - custom_dims = self._field_custom_dimensions[k] # pylint: disable=unsubscriptable-object + custom_dims = self._field_custom_dimensions[k] return v[indices + ((slice(None),) * custom_dims)] return self._apply_fn_to_fields(tensor_fn, dataclass_fn, custom_tensor_dims_fn=custom_tensor_dims_fn) @@ -219,7 +217,7 @@ class TensorDataclass: return x.reshape(shape) def custom_tensor_dims_fn(k, v): - custom_dims = self._field_custom_dimensions[k] # pylint: disable=unsubscriptable-object + custom_dims = self._field_custom_dimensions[k] return v.reshape((*shape, *v.shape[-custom_dims:])) return self._apply_fn_to_fields(tensor_fn, dataclass_fn, custom_tensor_dims_fn=custom_tensor_dims_fn) @@ -246,7 +244,7 @@ class TensorDataclass: """ def custom_tensor_dims_fn(k, v): - custom_dims = self._field_custom_dimensions[k] # pylint: disable=unsubscriptable-object + custom_dims = self._field_custom_dimensions[k] return v.broadcast_to((*shape, *v.shape[-custom_dims:])) return self._apply_fn_to_fields( diff --git a/nerfstudio/utils/writer.py b/nerfstudio/utils/writer.py index d6fcef3cc..cc12c9efc 100644 --- a/nerfstudio/utils/writer.py +++ b/nerfstudio/utils/writer.py @@ -315,8 +315,6 @@ class WandbWriter(Writer): wandb.log({name: scalar}, step=step) def write_config(self, name: str, config_dict: Dict[str, Any], step: int): - # pylint: disable=unused-argument - # pylint: disable=no-self-use """Function that writes out the config to wandb Args: @@ -339,7 +337,7 @@ class TensorboardWriter(Writer): def write_scalar(self, name: str, scalar: Union[float, torch.Tensor], step: int) -> None: self.tb_writer.add_scalar(name, scalar, step) - def write_config(self, name: str, config_dict: Dict[str, Any], step: int): # pylint: disable=unused-argument + def write_config(self, name: str, config_dict: Dict[str, Any], step: int): """Function that writes out the config to tensorboard Args: diff --git a/nerfstudio/viewer/server/render_state_machine.py b/nerfstudio/viewer/server/render_state_machine.py index 979c1fbdb..f49cba2b6 100644 --- a/nerfstudio/viewer/server/render_state_machine.py +++ b/nerfstudio/viewer/server/render_state_machine.py @@ -212,7 +212,7 @@ class RenderStateMachine(threading.Thread): if self.state == "low_static": self.action(RenderAction("static", action.cam_msg)) - def check_interrupt(self, frame, event, arg): # pylint: disable=unused-argument + def check_interrupt(self, frame, event, arg): """Raises interrupt when flag has been set and not already on lowest resolution. Used in conjunction with SetTrace. """ diff --git a/nerfstudio/viewer/server/viewer_elements.py b/nerfstudio/viewer/server/viewer_elements.py index be5120aa2..425cf3737 100644 --- a/nerfstudio/viewer/server/viewer_elements.py +++ b/nerfstudio/viewer/server/viewer_elements.py @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# pylint: disable=too-few-public-methods,access-member-before-definition,attribute-defined-outside-init """ Viewer GUI elements for the nerfstudio viewer """ diff --git a/nerfstudio/viewer/server/viewer_utils.py b/nerfstudio/viewer/server/viewer_utils.py index 9193d4811..3a2c01608 100644 --- a/nerfstudio/viewer/server/viewer_utils.py +++ b/nerfstudio/viewer/server/viewer_utils.py @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# pylint: disable=too-many-lines """Code to interface with the `vis/` (the JS viewer).""" from __future__ import annotations diff --git a/nerfstudio/viewer/viser/__init__.py b/nerfstudio/viewer/viser/__init__.py index 68d521275..915465d94 100644 --- a/nerfstudio/viewer/viser/__init__.py +++ b/nerfstudio/viewer/viser/__init__.py @@ -13,7 +13,7 @@ # limitations under the License. """ Viser is used for the nerfstudio viewr backend """ -# pylint: disable=useless-import-alias + from .message_api import GuiHandle as GuiHandle from .message_api import GuiSelectHandle as GuiSelectHandle diff --git a/nerfstudio/viewer/viser/gui.py b/nerfstudio/viewer/viser/gui.py index 187dd2eab..4b5ef0a73 100644 --- a/nerfstudio/viewer/viser/gui.py +++ b/nerfstudio/viewer/viser/gui.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -# pylint: disable=protected-access + """ Manages GUI communication. Should be almost identical to: https://github.com/brentyi/viser/blob/main/viser/_gui.py diff --git a/nerfstudio/viewer/viser/message_api.py b/nerfstudio/viewer/viser/message_api.py index c0ccce9f3..49df4e292 100644 --- a/nerfstudio/viewer/viser/message_api.py +++ b/nerfstudio/viewer/viser/message_api.py @@ -13,8 +13,7 @@ # limitations under the License. """ This module contains the MessageApi class, which is the interface for sending messages to the Viewer""" -# pylint: disable=protected-access -# pylint: disable=too-many-public-methods + from __future__ import annotations diff --git a/nerfstudio/viewer/viser/server.py b/nerfstudio/viewer/viser/server.py index e1959883f..31b1a78a5 100644 --- a/nerfstudio/viewer/viser/server.py +++ b/nerfstudio/viewer/viser/server.py @@ -13,8 +13,6 @@ # limitations under the License. """ Core Viser Server """ -# pylint: disable=protected-access -# pylint: disable=too-many-statements from __future__ import annotations diff --git a/pyproject.toml b/pyproject.toml index 9b43c5ea3..cd433faf3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -75,10 +75,10 @@ gen = [ # Development packages dev = [ "black[jupyter]==23.3.0", - "pylint==2.13.4", "pytest==7.1.2", "pytest-xdist==2.5.0", "typeguard==2.13.3", + "ruff==0.0.267", "sshconf==0.2.5", ] @@ -124,38 +124,15 @@ include = ["nerfstudio*"] [tool.setuptools.package-data] "*" = ["*.cu", "*.json", "py.typed", "setup.bash", "setup.zsh"] -# black [tool.black] line-length = 120 -# pylint -[tool.pylint.messages_control] -max-line-length = 120 -generated-members = ["numpy.*", "torch.*", "cv2.*", "cv.*"] -good-names-rgxs = "^[_a-zA-Z][_a-z0-9]?$" -jobs = 0 -ignored-classes = ["TensorDataclass"] - -disable = [ - "duplicate-code", - "fixme", - "logging-fstring-interpolation", - "too-many-arguments", - "too-many-branches", - "too-many-instance-attributes", - "too-many-locals", - "too-many-statements", - "unnecessary-ellipsis", -] - -#pytest [tool.pytest.ini_options] addopts = "-n=4 --typeguard-packages=nerfstudio --disable-warnings" testpaths = [ "tests", ] -# pyright [tool.pyright] include = ["nerfstudio"] exclude = ["**/node_modules", @@ -169,3 +146,28 @@ reportPrivateImportUsage = false pythonVersion = "3.8" pythonPlatform = "Linux" + +[tool.ruff] +select = [ + "E", # pycodestyle errors. + "F", # Pyflakes rules. + "PLC", # Pylint convention warnings. + "PLE", # Pylint errors. + "PLR", # Pylint refactor recommendations. + "PLW", # Pylint warnings. +] +ignore = [ + "E501", # Line too long. + "F722", # Forward annotation false positive from jaxtyping. Should be caught by pyright. + "F821", # Forward annotation false positive from jaxtyping. Should be caught by pyright. + "PLR2004", # Magic value used in comparison. + "PLR0915", # Too many statements. + "PLR0913", # Too many arguments. + "PLC0414", # Import alias does not rename variable. (this is used for exporting names) + "PLC1901", # Use falsey strings. + "PLR5501", # Use `elif` instead of `else if`. + "PLR0911", # Too many return statements. + "PLR0912", # Too many branches. + "PLW0603", # Globa statement updates are discouraged. + "PLW2901", # For loop variable overwritten. +] diff --git a/tests/cameras/test_cameras.py b/tests/cameras/test_cameras.py index 4f1b469cc..fd2bdcacb 100644 --- a/tests/cameras/test_cameras.py +++ b/tests/cameras/test_cameras.py @@ -13,7 +13,6 @@ BATCH_SIZE = 2 H_W = 800 FX_Y = 10.0 CX_Y = H_W / 2.0 -# pylint: disable=unnecessary-comprehension C2W_FLAT = torch.eye(4)[:3, :] CAMERA_TO_WORLDS = [ C2W_FLAT, diff --git a/tests/data/test_datamanager.py b/tests/data/test_datamanager.py index e80330183..568e6de8f 100644 --- a/tests/data/test_datamanager.py +++ b/tests/data/test_datamanager.py @@ -1,5 +1,3 @@ -# pylint: disable=all -from copy import copy from typing import Any import pytest @@ -9,7 +7,6 @@ import yaml from nerfstudio.cameras.cameras import Cameras from nerfstudio.configs.base_config import InstantiateConfig from nerfstudio.data.datamanagers.base_datamanager import ( - DataManager, DataparserOutputs, VanillaDataManager, VanillaDataManagerConfig, diff --git a/tests/dataparsers/test_nerfstudio_dataparser.py b/tests/dataparsers/test_nerfstudio_dataparser.py index f3f6f1223..b5581d5f8 100644 --- a/tests/dataparsers/test_nerfstudio_dataparser.py +++ b/tests/dataparsers/test_nerfstudio_dataparser.py @@ -1,7 +1,7 @@ """ Nerfstudio dataparser """ -# pylint: disable=all + import json from pathlib import Path diff --git a/tests/field_components/test_fields.py b/tests/field_components/test_fields.py index 81437645a..4714ed4d9 100644 --- a/tests/field_components/test_fields.py +++ b/tests/field_components/test_fields.py @@ -10,7 +10,7 @@ from nerfstudio.fields.instant_ngp_field import TCNNInstantNGPField def test_tcnn_instant_ngp_field(): """Test the tiny-cuda-nn field""" try: - import tinycudann as tcnn # pylint:disable=import-outside-toplevel, unused-import + import tinycudann as tcnn # noqa: F401 except ImportError as e: # tinycudann module doesn't exist print(e) diff --git a/tests/field_components/test_temporal_distortions.py b/tests/field_components/test_temporal_distortions.py index 61c240fd0..548a5fdcf 100644 --- a/tests/field_components/test_temporal_distortions.py +++ b/tests/field_components/test_temporal_distortions.py @@ -8,8 +8,7 @@ from nerfstudio.field_components.temporal_distortions import DNeRFDistortion def test_dnerf_distortion(): """Test dnerf distortion""" - # pylint: disable=import-outside-toplevel - # pylint: disable=unused-import + device = torch.device("cuda" if torch.cuda.is_available() else "cpu") distortion = DNeRFDistortion().to(device) diff --git a/tests/pipelines/test_vanilla_pipeline.py b/tests/pipelines/test_vanilla_pipeline.py index c51038135..2f6f6e4a9 100644 --- a/tests/pipelines/test_vanilla_pipeline.py +++ b/tests/pipelines/test_vanilla_pipeline.py @@ -3,11 +3,6 @@ Test pipeline """ from pathlib import Path -# pylint: disable=too-few-public-methods -# pylint: disable=no-self-use -# pylint: disable=missing-class-docstring -# pylint: disable=unused-argument -# pylint: disable=abstract-method import torch from torch import nn @@ -77,13 +72,13 @@ def test_load_state_dict(): ) pipeline = VanillaPipeline(config, "cpu") state_dict = pipeline.state_dict() - state_dict["_model.param"].mul_(2) # pylint: disable=unsubscriptable-object + state_dict["_model.param"].mul_(2) pipeline.load_pipeline(state_dict, 0) assert was_called assert pipeline.model.param[0].item() == 2 # preparation for another test - state_dict["_model.param"].mul_(2) # pylint: disable=unsubscriptable-object + state_dict["_model.param"].mul_(2) was_called = False # pretends to be a DDP checkpoint ddp_state_dict = {} diff --git a/tests/process_data/test_misc.py b/tests/process_data/test_misc.py index a300687ee..1b2404b51 100644 --- a/tests/process_data/test_misc.py +++ b/tests/process_data/test_misc.py @@ -39,7 +39,7 @@ def test_scalar_first_scalar_last_quaternions(): # Expected Rotation matrix # fmt: off - R_expected = np.array( # pylint: disable=invalid-name + R_expected = np.array( [ [ 0.81379768, -0.44096961, 0.37852231], [ 0.46984631, 0.88256412, 0.01802831], diff --git a/tests/test_train.py b/tests/test_train.py index 37b0ac41e..e1b977fd3 100644 --- a/tests/test_train.py +++ b/tests/test_train.py @@ -1,4 +1,3 @@ -# pylint: disable=protected-access """ Default test to make sure train runs """ diff --git a/tests/utils/test_tensor_dataclass.py b/tests/utils/test_tensor_dataclass.py index 1ade936a4..05c2eb43a 100644 --- a/tests/utils/test_tensor_dataclass.py +++ b/tests/utils/test_tensor_dataclass.py @@ -61,7 +61,7 @@ def test_broadcasting(): tensor_dataclass = DummyTensorDataclass(a=a, b=b) -def test_tensor_ops(): # pylint: disable=(too-many-statements) +def test_tensor_ops(): """Test tensor operations""" a = torch.ones((4, 6, 3))