From 249395bfe0e159e503296d16a49e7f36c2821fae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20W=C3=A4lchli?= Date: Wed, 3 May 2023 05:36:07 +0200 Subject: [PATCH 01/11] DDP Parity tests as standalone task (#17503) --- .azure/gpu-tests-fabric.yml | 7 ++++ tests/tests_fabric/parity/test_parity_ddp.py | 19 ++++----- tests/tests_fabric/run_standalone_tasks.sh | 43 ++++++++++++++++++++ 3 files changed, 57 insertions(+), 12 deletions(-) create mode 100644 tests/tests_fabric/run_standalone_tasks.sh diff --git a/.azure/gpu-tests-fabric.yml b/.azure/gpu-tests-fabric.yml index c4efcf3383520..96193347dff52 100644 --- a/.azure/gpu-tests-fabric.yml +++ b/.azure/gpu-tests-fabric.yml @@ -138,6 +138,13 @@ jobs: displayName: 'Testing: fabric standalone tests' timeoutInMinutes: "10" + - bash: bash run_standalone_tasks.sh + workingDirectory: tests/tests_fabric + env: + PL_RUN_CUDA_TESTS: "1" + displayName: 'Testing: fabric standalone tasks' + timeoutInMinutes: "10" + - bash: | python -m coverage report python -m coverage xml diff --git a/tests/tests_fabric/parity/test_parity_ddp.py b/tests/tests_fabric/parity/test_parity_ddp.py index 50cc603d16a1f..e3aa7c476b052 100644 --- a/tests/tests_fabric/parity/test_parity_ddp.py +++ b/tests/tests_fabric/parity/test_parity_ddp.py @@ -15,7 +15,6 @@ import time from copy import deepcopy -import pytest import torch import torch.distributed import torch.nn.functional @@ -24,7 +23,6 @@ from torch.utils.data.distributed import DistributedSampler from lightning.fabric.fabric import Fabric -from tests_fabric.helpers.runif import RunIf from tests_fabric.parity.models import ConvNet from tests_fabric.parity.utils import ( cuda_reset, @@ -125,16 +123,7 @@ def train_fabric_ddp(fabric): return model.state_dict(), torch.tensor(iteration_timings), memory_stats -@RunIf(standalone=True) -@pytest.mark.usefixtures("reset_deterministic_algorithm", "reset_cudnn_benchmark") -@pytest.mark.parametrize( - "accelerator, devices, tolerance", - [ - ("cpu", 2, 0.02), - pytest.param("cuda", 2, 0.01, marks=RunIf(min_cuda_gpus=2)), - ], -) -def test_parity_ddp(accelerator, devices, tolerance): +def run_parity_test(accelerator: str = "cpu", devices: int = 2, tolerance: float = 0.02): cuda_reset() # Launch processes with Fabric and re-use them for the PyTorch training for convenience @@ -169,3 +158,9 @@ def test_parity_ddp(accelerator, devices, tolerance): if accelerator == "cuda": assert all(fabric.all_gather(is_cuda_memory_close(memory_torch["start"], memory_fabric["start"]))) assert all(fabric.all_gather(is_cuda_memory_close(memory_torch["end"], memory_fabric["end"]))) + + +if __name__ == "__main__": + from jsonargparse.cli import CLI + + CLI(run_parity_test) diff --git a/tests/tests_fabric/run_standalone_tasks.sh b/tests/tests_fabric/run_standalone_tasks.sh new file mode 100644 index 0000000000000..d7c715390dee8 --- /dev/null +++ b/tests/tests_fabric/run_standalone_tasks.sh @@ -0,0 +1,43 @@ +#!/bin/bash +# Copyright The Lightning AI team. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# THIS FILE ASSUMES IT IS RUN INSIDE THE tests/tests_fabric DIRECTORY +export PYTHONPATH="${PYTHONPATH}:$(pwd)" +export PYTHONPATH="${PYTHONPATH}:$(pwd)/.." + +MAX_RETRIES=3 + +retry_command() { + local command="$@" + local exit_code=1 + for ((i=1; i<=$MAX_RETRIES; i++)) + do + echo "Run attempt: $i" + eval $command + exit_code=$? + if [ $exit_code -eq 0 ]; then + echo "Successfully ran: $command" + break + fi + echo "Attempt $i failed." + done + if [ $exit_code -ne 0 ]; then + echo "Failed after $MAX_RETRIES attempts: $command" + fi + return $exit_code +} + +retry_command "python -m parity.test_parity_ddp --accelerator="cpu" --devices=2 --tolerance=0.02" +retry_command "python -m parity.test_parity_ddp --accelerator="cuda" --devices=2 --tolerance=0.01" From a533f68693649513a337b350f77792593cee9c19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20W=C3=A4lchli?= Date: Wed, 3 May 2023 09:00:11 +0200 Subject: [PATCH 02/11] Support compiling a module after it was set up by Fabric (#17529) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Carlos Mocholí Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- src/lightning/fabric/fabric.py | 12 +++++-- src/lightning/fabric/wrappers.py | 28 ++++++++++++++-- tests/tests_fabric/test_wrappers.py | 51 +++++++++++++++++++++++++++-- 3 files changed, 84 insertions(+), 7 deletions(-) diff --git a/src/lightning/fabric/fabric.py b/src/lightning/fabric/fabric.py index 6e76a92f7cd13..5ed0fceb3ba1c 100644 --- a/src/lightning/fabric/fabric.py +++ b/src/lightning/fabric/fabric.py @@ -48,7 +48,13 @@ from lightning.fabric.utilities.seed import seed_everything from lightning.fabric.utilities.types import ReduceOp from lightning.fabric.utilities.warnings import PossibleUserWarning -from lightning.fabric.wrappers import _FabricDataLoader, _FabricModule, _FabricOptimizer, _unwrap_objects +from lightning.fabric.wrappers import ( + _FabricDataLoader, + _FabricModule, + _FabricOptimizer, + _unwrap_compiled, + _unwrap_objects, +) def _do_nothing(*_: Any) -> None: @@ -547,6 +553,7 @@ def no_backward_sync(self, module: _FabricModule, enabled: bool = True) -> Gener enabled: Whether the context manager is enabled or not. ``True`` means skip the sync, ``False`` means do not skip. """ + module = _unwrap_compiled(module) if not isinstance(module, _FabricModule): raise TypeError( "You need to set up the model first before you can call `self.no_backward_sync()`:" @@ -638,7 +645,8 @@ def load( # We need to unwrap objects (see above) but this creates a new dictionary. In-place updates # (for user metadata) wouldn't show up in the original dict, so we need to copy the data back. for k in list(unwrapped_state.keys()): - if isinstance(state[k], (_FabricModule, _FabricOptimizer, _FabricDataLoader)): + obj = _unwrap_compiled(state[k]) + if isinstance(obj, (_FabricModule, _FabricOptimizer, _FabricDataLoader)): continue state[k] = unwrapped_state[k] return remainder diff --git a/src/lightning/fabric/wrappers.py b/src/lightning/fabric/wrappers.py index 96ee7aedea205..947510244d0df 100644 --- a/src/lightning/fabric/wrappers.py +++ b/src/lightning/fabric/wrappers.py @@ -28,6 +28,7 @@ from lightning.fabric.utilities import move_data_to_device from lightning.fabric.utilities.data import _set_sampler_epoch from lightning.fabric.utilities.device_dtype_mixin import _DeviceDtypeModuleMixin +from lightning.fabric.utilities.imports import _TORCH_GREATER_EQUAL_2_0 from lightning.fabric.utilities.types import Optimizable from lightning.fabric.utilities.warnings import PossibleUserWarning @@ -218,15 +219,35 @@ def _unwrap_objects(collection: Any) -> Any: def _unwrap( obj: Union[_FabricModule, _FabricOptimizer, _FabricDataLoader] ) -> Union[nn.Module, Optimizer, DataLoader]: - if isinstance(obj, _FabricModule): - return obj._forward_module + if isinstance(unwrapped := _unwrap_compiled(obj), _FabricModule): + return unwrapped._forward_module if isinstance(obj, _FabricOptimizer): return obj.optimizer if isinstance(obj, _FabricDataLoader): return obj._dataloader return obj - return apply_to_collection(collection, dtype=(_FabricModule, _FabricOptimizer, _FabricDataLoader), function=_unwrap) + types = [_FabricModule, _FabricOptimizer, _FabricDataLoader] + if _TORCH_GREATER_EQUAL_2_0: + from torch._dynamo import OptimizedModule + + types.append(OptimizedModule) + + return apply_to_collection(collection, dtype=tuple(types), function=_unwrap) + + +def _unwrap_compiled(obj: Any) -> Any: + """Removes the :class:`torch._dynamo.OptimizedModule` around the object if it is wrapped. + + Use this function before instance checks against e.g. :class:`_FabricModule`. + """ + if not _TORCH_GREATER_EQUAL_2_0: + return obj + from torch._dynamo import OptimizedModule + + if isinstance(obj, OptimizedModule): + return obj._orig_mod + return obj def is_wrapped(obj: object) -> bool: @@ -239,4 +260,5 @@ def is_wrapped(obj: object) -> bool: Args: obj: The object to test. """ + obj = _unwrap_compiled(obj) return isinstance(obj, (_FabricModule, _FabricOptimizer, _FabricDataLoader)) diff --git a/tests/tests_fabric/test_wrappers.py b/tests/tests_fabric/test_wrappers.py index 0996627e57a15..72ce305506304 100644 --- a/tests/tests_fabric/test_wrappers.py +++ b/tests/tests_fabric/test_wrappers.py @@ -23,7 +23,7 @@ from lightning.fabric.fabric import Fabric from lightning.fabric.plugins import Precision from lightning.fabric.utilities.device_dtype_mixin import _DeviceDtypeModuleMixin -from lightning.fabric.wrappers import _FabricDataLoader, _FabricModule, _FabricOptimizer, is_wrapped +from lightning.fabric.wrappers import _FabricDataLoader, _FabricModule, _FabricOptimizer, _unwrap_objects, is_wrapped from tests_fabric.helpers.runif import RunIf @@ -358,7 +358,8 @@ def zero_grad(self, set_grads_to_None=False): custom_zero_grad.assert_called_with(set_grads_to_None=False) -def test_is_wrapped(): +@pytest.mark.parametrize("compile", [False, pytest.param(True, marks=RunIf(dynamo=True))]) +def test_is_wrapped(compile): """Test that the `is_wrapped` utility recognizes when an object was wrapped by Fabric.""" assert not is_wrapped(None) @@ -368,6 +369,15 @@ def test_is_wrapped(): wrapped = _FabricModule(module, Mock()) assert is_wrapped(wrapped) + # _FabricModule inside an OptimizedModule + if compile: + from torch._dynamo import OptimizedModule + + module = torch.nn.Linear(2, 2) + wrapped = torch.compile(_FabricModule(module, Mock())) + assert isinstance(wrapped, OptimizedModule) + assert is_wrapped(wrapped) + # _FabricOptimizer optimizer = torch.optim.Adam(module.parameters()) assert not is_wrapped(optimizer) @@ -381,6 +391,43 @@ def test_is_wrapped(): assert is_wrapped(wrapped) +@pytest.mark.parametrize("compile", [False, pytest.param(True, marks=RunIf(dynamo=True))]) +def test_unwrap_objects(compile): + # empty container + assert _unwrap_objects({}) == {} + + # container with pure objects and wrapped objects + module = torch.nn.Linear(1, 1) + wrapped_module = _FabricModule(module, Mock()) + if compile: + wrapped_module = torch.compile(wrapped_module) + optimizer = torch.optim.Adam(module.parameters()) + wrapped_optimizer = _FabricOptimizer(optimizer, Mock()) + dataloader = DataLoader([1, 2, 3]) + wrapped_dataloader = _FabricDataLoader(dataloader) + container = { + "int": 1, + "module": module, + "wrapped_module": wrapped_module, + "optimizer": optimizer, + "wrapped_optimizer": wrapped_optimizer, + "dataloader": dataloader, + "wrapped_dataloader": wrapped_dataloader, + "nested": [module, wrapped_module, optimizer, wrapped_optimizer, dataloader, wrapped_dataloader], + } + expected = { + "int": 1, + "module": module, + "wrapped_module": wrapped_module._forward_module, + "optimizer": optimizer, + "wrapped_optimizer": optimizer, + "dataloader": dataloader, + "wrapped_dataloader": dataloader, + "nested": [module, wrapped_module._forward_module, optimizer, optimizer, dataloader, dataloader], + } + assert _unwrap_objects(container) == expected + + def test_step_method_redirection(): """Test that the FabricModule redirects the special `LightningModule.*_step` methods through the forward- module.""" From 04a86f95d7b21bae1ac4f96759694c063dde582e Mon Sep 17 00:00:00 2001 From: Solomiia Date: Wed, 3 May 2023 20:00:54 +0300 Subject: [PATCH 03/11] Add an option to overwrite the existing checkpoint file (#17320) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Carlos Mocholí --- src/lightning/pytorch/CHANGELOG.md | 3 ++ .../pytorch/callbacks/model_checkpoint.py | 25 +++++++++----- .../checkpointing/test_model_checkpoint.py | 34 +++++++++++++++++++ 3 files changed, 53 insertions(+), 9 deletions(-) diff --git a/src/lightning/pytorch/CHANGELOG.md b/src/lightning/pytorch/CHANGELOG.md index d660f6aaadba4..4ec75ef5159e8 100644 --- a/src/lightning/pytorch/CHANGELOG.md +++ b/src/lightning/pytorch/CHANGELOG.md @@ -36,6 +36,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). - Run the DDP wrapper in a CUDA stream ([#17334](https://github.com/Lightning-AI/lightning/pull/17334)) +- Enabled optional file versioning of model checkpoints ([#17320](hhttps://github.com/Lightning-AI/lightning/pull/17320)) + + - Added the process group timeout argument `FSDPStrategy(timeout=...)` for the FSDP strategy ([#17274](https://github.com/Lightning-AI/lightning/pull/17274)) diff --git a/src/lightning/pytorch/callbacks/model_checkpoint.py b/src/lightning/pytorch/callbacks/model_checkpoint.py index 240ba13a1c1fc..24cb0f1723427 100644 --- a/src/lightning/pytorch/callbacks/model_checkpoint.py +++ b/src/lightning/pytorch/callbacks/model_checkpoint.py @@ -91,7 +91,8 @@ class ModelCheckpoint(Checkpoint): Please note that the monitors are checked every ``every_n_epochs`` epochs. if ``save_top_k >= 2`` and the callback is called multiple times inside an epoch, the name of the saved file will be - appended with a version count starting with ``v1``. + appended with a version count starting with ``v1`` + unless ``enable_version_counter`` is set to False. mode: one of {min, max}. If ``save_top_k != 0``, the decision to overwrite the current save file is made based on either the maximization or the minimization of the monitored quantity. @@ -129,6 +130,8 @@ class ModelCheckpoint(Checkpoint): where both values for ``every_n_epochs`` and ``check_val_every_n_epoch`` evenly divide E. save_on_train_epoch_end: Whether to run checkpointing at the end of the training epoch. If this is ``False``, then the check runs at the end of the validation. + enable_version_counter: Whether to append a version to the existing file name. + If this is ``False``, then the checkpoint files will be overwritten. Note: For extra customization, ModelCheckpoint includes the following attributes: @@ -217,6 +220,7 @@ def __init__( train_time_interval: Optional[timedelta] = None, every_n_epochs: Optional[int] = None, save_on_train_epoch_end: Optional[bool] = None, + enable_version_counter: bool = True, ): super().__init__() self.monitor = monitor @@ -226,6 +230,7 @@ def __init__( self.save_weights_only = save_weights_only self.auto_insert_metric_name = auto_insert_metric_name self._save_on_train_epoch_end = save_on_train_epoch_end + self._enable_version_counter = enable_version_counter self._last_global_step_saved = 0 # no need to save when no steps were taken self._last_time_checked: Optional[float] = None self.current_score: Optional[Tensor] = None @@ -617,10 +622,11 @@ def _get_metric_interpolated_filepath_name( ) -> str: filepath = self.format_checkpoint_name(monitor_candidates) - version_cnt = self.STARTING_VERSION - while self.file_exists(filepath, trainer) and filepath != del_filepath: - filepath = self.format_checkpoint_name(monitor_candidates, ver=version_cnt) - version_cnt += 1 + if self._enable_version_counter: + version_cnt = self.STARTING_VERSION + while self.file_exists(filepath, trainer) and filepath != del_filepath: + filepath = self.format_checkpoint_name(monitor_candidates, ver=version_cnt) + version_cnt += 1 return filepath @@ -640,10 +646,11 @@ def _save_last_checkpoint(self, trainer: "pl.Trainer", monitor_candidates: Dict[ filepath = self.format_checkpoint_name(monitor_candidates, self.CHECKPOINT_NAME_LAST) - version_cnt = self.STARTING_VERSION - while self.file_exists(filepath, trainer) and filepath != self.last_model_path: - filepath = self.format_checkpoint_name(monitor_candidates, self.CHECKPOINT_NAME_LAST, ver=version_cnt) - version_cnt += 1 + if self._enable_version_counter: + version_cnt = self.STARTING_VERSION + while self.file_exists(filepath, trainer) and filepath != self.last_model_path: + filepath = self.format_checkpoint_name(monitor_candidates, self.CHECKPOINT_NAME_LAST, ver=version_cnt) + version_cnt += 1 # set the last model path before saving because it will be part of the state. previous, self.last_model_path = self.last_model_path, filepath diff --git a/tests/tests_pytorch/checkpointing/test_model_checkpoint.py b/tests/tests_pytorch/checkpointing/test_model_checkpoint.py index 173a5578cde58..dac78e0477cd0 100644 --- a/tests/tests_pytorch/checkpointing/test_model_checkpoint.py +++ b/tests/tests_pytorch/checkpointing/test_model_checkpoint.py @@ -1171,6 +1171,40 @@ def test_ckpt_version_after_rerun_same_trainer(tmpdir): assert set(os.listdir(tmpdir)) == expected +def test_ckpt_version_counter_disabled_after_rerun_new_trainer(tmpdir): + """Check that previous checkpoints get overwritten and no suffixes are generated when new trainer instances are + used.""" + epochs = 2 + for i in range(epochs): + mc = ModelCheckpoint( + dirpath=tmpdir, + save_top_k=-1, + save_last=True, + monitor="epoch", + filename="{epoch}", + enable_version_counter=False, + ) + trainer = Trainer( + max_epochs=epochs, + limit_train_batches=1, + limit_val_batches=1, + default_root_dir=tmpdir, + callbacks=[mc], + logger=False, + enable_progress_bar=False, + enable_model_summary=False, + ) + trainer.fit(BoringModel()) + + # check best_k_models and last state + assert {Path(f).name for f in mc.best_k_models} == {"epoch=0.ckpt", "epoch=1.ckpt"} + assert Path(mc.last_model_path).name == "last.ckpt" + + # check created ckpts + actual = {f.basename for f in tmpdir.listdir()} + assert actual == {"epoch=0.ckpt", "epoch=1.ckpt", "last.ckpt"} + + def test_model_checkpoint_mode_options(): with pytest.raises(MisconfigurationException, match="`mode` can be .* but got unknown_option"): ModelCheckpoint(mode="unknown_option") From 7df627b43746a85aa87671bec3e6dada0d98b556 Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Thu, 4 May 2023 09:12:33 +0100 Subject: [PATCH 04/11] App: change cache location (#17491) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Adrian Wälchli Co-authored-by: thomas Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com> --- pyproject.toml | 1 + src/lightning/app/CHANGELOG.md | 2 +- src/lightning/app/runners/cloud.py | 5 +++- src/lightning/app/source_code/local.py | 8 ++++-- .../public/test_boring_app.py | 1 + tests/tests_app/source_code/test_local.py | 26 +++++++++++++++---- 6 files changed, 34 insertions(+), 9 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e0d7aad0db954..e9d33961f3f89 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -63,6 +63,7 @@ extend-select = [ ] ignore = [ "E731", # Do not assign a lambda expression, use a def + "S108", ] # Exclude a variety of commonly ignored directories. exclude = [ diff --git a/src/lightning/app/CHANGELOG.md b/src/lightning/app/CHANGELOG.md index 4ea16d1b3bcd0..3a2c47d97d3f2 100644 --- a/src/lightning/app/CHANGELOG.md +++ b/src/lightning/app/CHANGELOG.md @@ -14,7 +14,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). ### Changed -- +- Changed `LocalSourceCodeDir` cache_location to not use home in some certain cases ([#17491](https://github.com/Lightning-AI/lightning/pull/17491)) ### Deprecated diff --git a/src/lightning/app/runners/cloud.py b/src/lightning/app/runners/cloud.py index 89eb17b756d19..92ce499e128a1 100644 --- a/src/lightning/app/runners/cloud.py +++ b/src/lightning/app/runners/cloud.py @@ -493,9 +493,12 @@ def _resolve_cluster_id( self, cluster_id: Optional[str], project_id: str, existing_cloudspaces: List[V1CloudSpace] ) -> Optional[str]: """If cloudspaces exist and cluster is None, mimic cluster selection logic to choose a default.""" + # 1. Use the environement variables if cluster_id is None: - cluster_id = os.getenv("CLUSTER_ID", None) + cluster_id = os.getenv("LIGHTNING_CLUSTER_ID", None) + # 2. Use the project bindings + # TODO: Use the user prefered cluster. if cluster_id is None and len(existing_cloudspaces) > 0: # Determine the cluster ID cluster_id = _get_default_cluster(self.backend.client, project_id) diff --git a/src/lightning/app/source_code/local.py b/src/lightning/app/source_code/local.py index f145c5d6e7550..c383740aa6c80 100644 --- a/src/lightning/app/source_code/local.py +++ b/src/lightning/app/source_code/local.py @@ -28,9 +28,13 @@ class LocalSourceCodeDir: """Represents the source code directory and provide the utilities to manage it.""" - cache_location: Path = Path.home() / ".lightning" / "cache" / "repositories" - def __init__(self, path: Path, ignore_functions: Optional[List[_IGNORE_FUNCTION]] = None) -> None: + if "LIGHTNING_VSCODE_WORKSPACE" in os.environ: + # Don't use home to store the tar ball. This won't play nice with symlinks + self.cache_location: Path = Path("/tmp", ".lightning", "cache", "repositories") + else: + self.cache_location: Path = Path.home() / ".lightning" / "cache" / "repositories" + self.path = path self.ignore_functions = ignore_functions diff --git a/tests/integrations_app/public/test_boring_app.py b/tests/integrations_app/public/test_boring_app.py index bbe6468b5f28d..40893bb4b5728 100644 --- a/tests/integrations_app/public/test_boring_app.py +++ b/tests/integrations_app/public/test_boring_app.py @@ -29,6 +29,7 @@ def check_hello_there(*_, **__): assert result.exit_code == 0 assert result.exception is None + # TODO: Resolve # lines = result.output.splitlines() # assert any("Received from root.dict.dst_w" in line for line in lines) print("Succeeded App!") diff --git a/tests/tests_app/source_code/test_local.py b/tests/tests_app/source_code/test_local.py index c638bc32fd88a..868d8138091da 100644 --- a/tests/tests_app/source_code/test_local.py +++ b/tests/tests_app/source_code/test_local.py @@ -1,6 +1,11 @@ +import os +import sys import tarfile import uuid from pathlib import Path +from unittest import mock + +import pytest from lightning.app.source_code import LocalSourceCodeDir @@ -28,6 +33,20 @@ def test_repository_checksum(tmp_path): assert checksum_a != checksum_c +@pytest.mark.skipif(sys.platform == "win32", reason="this runs only on linux") +@mock.patch.dict(os.environ, {"LIGHTNING_VSCODE_WORKSPACE": "something"}) +def test_local_cache_path_tmp(tmp_path): + """LocalRepository.cache_location is under tmp.""" + repository = LocalSourceCodeDir(path=Path(tmp_path)) + assert str(repository.cache_location).startswith("/tmp") + + +def test_local_cache_path_home(tmp_path): + """LocalRepository.cache_location is under home.""" + repository = LocalSourceCodeDir(path=Path(tmp_path)) + assert str(repository.cache_location).startswith(str(Path.home())) + + def test_repository_package(tmp_path, monkeypatch): """LocalRepository.package() ceates package from local dir.""" cache_path = Path(tmp_path) @@ -35,10 +54,8 @@ def test_repository_package(tmp_path, monkeypatch): source_path.mkdir(parents=True, exist_ok=True) (source_path / "test.txt").write_text("test") - # set cache location to temp dir - monkeypatch.setattr(LocalSourceCodeDir, "cache_location", cache_path) - repository = LocalSourceCodeDir(path=source_path) + repository.cache_location = cache_path repository.package() # test that package is created @@ -276,8 +293,6 @@ def test_repository_lightningignore_unpackage(tmp_path, monkeypatch): lorem_ipsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit." cache_path = tmp_path / "cache" - monkeypatch.setattr(LocalSourceCodeDir, "cache_location", cache_path) - source_path = tmp_path / "source" source_path.mkdir() @@ -345,6 +360,7 @@ def test_repository_lightningignore_unpackage(tmp_path, monkeypatch): # create repo object repository = LocalSourceCodeDir(path=source_path) + repository.cache_location = cache_path repository.package() unpackage_path = tmp_path / "unpackage" From e0f335809d1f90a7a93c5482c056a929139ce6d2 Mon Sep 17 00:00:00 2001 From: Jirka Borovec <6035284+Borda@users.noreply.github.com> Date: Thu, 4 May 2023 12:33:46 +0200 Subject: [PATCH 05/11] Adding tests for legacy checkpoints - 1.8.x (#17374) * Adding tests for legacy checkpoints * 2.0 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix simple * utils * import * pl * num_features=24 * num_features=24 * length=6000 * other * rm * dru run * rm * prune * import --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .github/workflows/_legacy-checkpoints.yml | 37 +++++++------------- docs/source-pytorch/past_versions.rst | 3 +- tests/legacy/back-compatible-versions.txt | 6 ++++ tests/legacy/generate_checkpoints.sh | 4 ++- tests/legacy/simple_classif_training.py | 6 ++-- tests/tests_pytorch/helpers/simple_models.py | 7 +++- 6 files changed, 33 insertions(+), 30 deletions(-) diff --git a/.github/workflows/_legacy-checkpoints.yml b/.github/workflows/_legacy-checkpoints.yml index 380866b42580c..649c3f590a208 100644 --- a/.github/workflows/_legacy-checkpoints.yml +++ b/.github/workflows/_legacy-checkpoints.yml @@ -67,16 +67,11 @@ jobs: env: PACKAGE_NAME: pytorch FREEZE_REQUIREMENTS: 1 - run: | - pip install . -f https://download.pytorch.org/whl/cpu/torch_stable.html - pip list + run: pip install . -f https://download.pytorch.org/whl/cpu/torch_stable.html if: inputs.pl_version == '' - name: Install PL version - run: | - pip install "pytorch-lightning==${{ inputs.pl_version }}" \ - -f https://download.pytorch.org/whl/cpu/torch_stable.html - pip list + run: pip install "pytorch-lightning==${{ inputs.pl_version }}" -f https://download.pytorch.org/whl/cpu/torch_stable.html if: inputs.pl_version != '' - name: Adjust tests -> PL @@ -92,39 +87,31 @@ jobs: - name: Decide PL version to create a PR with id: decide-version - run: | - python -c "import pytorch_lightning as pl; print(f'pl-version={pl.__version__}')" >> $GITHUB_OUTPUT || echo pl-version='' >> $GITHUB_OUTPUT + run: python -c "import pytorch_lightning as pl; print(f'pl-version={pl.__version__}')" >> $GITHUB_OUTPUT || echo pl-version='' >> $GITHUB_OUTPUT - name: Generate checkpoints working-directory: ${{ env.legacy_dir }} - run: | - bash generate_checkpoints.sh ${{ inputs.pl_version }} + run: bash generate_checkpoints.sh ${{ inputs.pl_version }} - - name: Keep artifact - id: keep-artifact - run: python -c "print('DAYS=' + str(30 if '${{ github.event_name }}'.startswith('pull_request') else 0))" >> $GITHUB_OUTPUT + - name: Keep artifact & DryRun + run: | + python -c "print('KEEP_DAYS=' + str(30 if '${{ github.event_name }}'.startswith('pull_request') else 0))" >> $GITHUB_ENV + python -c "print('AWS_RUN=' + str('' if '${{inputs.push_to_s3}}' == 'true' else '--dryrun'))" >> $GITHUB_ENV - name: Upload checkpoints to GitHub Actions artifact uses: actions/upload-artifact@v3 with: name: checkpoints-${{ github.sha }} path: ${{ env.legacy_dir }}/checkpoints/ - retention-days: ${{ steps.keep-artifact.outputs.DAYS }} - - - name: Upload checkpoints to S3 (dryrun) - working-directory: ${{ env.legacy_dir }} - run: | - aws s3 sync --dryrun checkpoints/ s3://pl-public-data/legacy/checkpoints/ - zip -r checkpoints.zip checkpoints - aws s3 cp --dryrun checkpoints.zip s3://pl-public-data/legacy/ --acl public-read + retention-days: ${{ env.KEEP_DAYS }} - name: Upload checkpoints to S3 working-directory: ${{ env.legacy_dir }} run: | - aws s3 sync checkpoints/ s3://pl-public-data/legacy/checkpoints/ + aws s3 sync $AWS_RUN checkpoints/ s3://pl-public-data/legacy/checkpoints/ zip -r checkpoints.zip checkpoints - aws s3 cp checkpoints.zip s3://pl-public-data/legacy/ --acl public-read - if: inputs.push_to_s3 + aws s3 cp $AWS_RUN checkpoints.zip s3://pl-public-data/legacy/ --acl public-read + add-ckpt-test: runs-on: ubuntu-20.04 diff --git a/docs/source-pytorch/past_versions.rst b/docs/source-pytorch/past_versions.rst index 86c1c39a5e597..597e2c19d388a 100644 --- a/docs/source-pytorch/past_versions.rst +++ b/docs/source-pytorch/past_versions.rst @@ -20,7 +20,8 @@ To help you with keeping up to spead, check :doc:`Migration guide `_, `1.9.2 `_, `1.9.3 `_, - `1.9.4 `_ + `1.9.4 `_, + `1.9.5 `_ - :doc:`from 1.9 to 2.0 ` * - `1.8 `_ diff --git a/tests/legacy/back-compatible-versions.txt b/tests/legacy/back-compatible-versions.txt index b6c18738712ce..c2bc418eecd93 100644 --- a/tests/legacy/back-compatible-versions.txt +++ b/tests/legacy/back-compatible-versions.txt @@ -71,3 +71,9 @@ 1.7.6 1.7.7 1.8.0 +1.8.1 +1.8.2 +1.8.3 +1.8.4 +1.8.5 +1.8.6 diff --git a/tests/legacy/generate_checkpoints.sh b/tests/legacy/generate_checkpoints.sh index 9f597161acfc9..7873daf3fe56f 100644 --- a/tests/legacy/generate_checkpoints.sh +++ b/tests/legacy/generate_checkpoints.sh @@ -32,11 +32,13 @@ do # Don't install/update anything before activating venv # to avoid breaking any existing environment. + rm -rf $ENV_PATH python -m venv $ENV_PATH source $ENV_PATH/bin/activate - python -m pip install pytorch_lightning==$pl_ver -r $LEGACY_PATH/requirements.txt -f https://download.pytorch.org/whl/cpu/torch_stable.html + python -m pip install "pytorch_lightning==$pl_ver" -r $LEGACY_PATH/requirements.txt -f https://download.pytorch.org/whl/cpu/torch_stable.html + rm -rf $LEGACY_PATH/checkpoints/$pl_ver create_and_save_checkpoint deactivate diff --git a/tests/legacy/simple_classif_training.py b/tests/legacy/simple_classif_training.py index fd62bc0963c0f..00e51627efad9 100644 --- a/tests/legacy/simple_classif_training.py +++ b/tests/legacy/simple_classif_training.py @@ -38,8 +38,10 @@ def main_train(dir_path, max_epochs: int = 20): deterministic=True, ) - dm = ClassifDataModule() - model = ClassificationModel() + dm = ClassifDataModule( + num_features=24, length=6000, num_classes=3, batch_size=128, n_clusters_per_class=2, n_informative=int(24 / 3) + ) + model = ClassificationModel(num_features=24, num_classes=3, lr=0.01) trainer.fit(model, datamodule=dm) res = trainer.test(model, datamodule=dm) assert res[0]["test_loss"] <= 0.85, str(res[0]["test_loss"]) diff --git a/tests/tests_pytorch/helpers/simple_models.py b/tests/tests_pytorch/helpers/simple_models.py index 9e89fad7736e3..6873d642294ee 100644 --- a/tests/tests_pytorch/helpers/simple_models.py +++ b/tests/tests_pytorch/helpers/simple_models.py @@ -11,13 +11,18 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +import operator + import torch import torch.nn.functional as F +from lightning_utilities.core.imports import compare_version from torch import nn from torchmetrics import Accuracy, MeanSquaredError from lightning.pytorch import LightningModule -from lightning.pytorch.utilities.imports import _TORCHMETRICS_GREATER_EQUAL_0_11 as _TM_GE_0_11 + +# using new API with task +_TM_GE_0_11 = compare_version("torchmetrics", operator.ge, "0.11.0") class ClassificationModel(LightningModule): From ebbd1169d838b44e98cef5cc4d0f1f0860fc140f Mon Sep 17 00:00:00 2001 From: Jakub Kaczmarzyk Date: Thu, 4 May 2023 07:35:05 -0400 Subject: [PATCH 06/11] add note in LightningCLI docs that `--optimizer` must be given for `--lr_scheduler` to work (#17552) --- docs/source-pytorch/cli/lightning_cli_intermediate_2.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/source-pytorch/cli/lightning_cli_intermediate_2.rst b/docs/source-pytorch/cli/lightning_cli_intermediate_2.rst index 166f21ebd8f92..db06f85c359bd 100644 --- a/docs/source-pytorch/cli/lightning_cli_intermediate_2.rst +++ b/docs/source-pytorch/cli/lightning_cli_intermediate_2.rst @@ -193,13 +193,15 @@ Standard learning rate schedulers from ``torch.optim.lr_scheduler`` work out of .. code:: bash - python main.py fit --lr_scheduler CosineAnnealingLR + python main.py fit --optimizer=Adam --lr_scheduler CosineAnnealingLR + +Please note that ``--optimizer`` must be added for ``--lr_scheduler`` to have an effect. If the scheduler you want needs other arguments, add them via the CLI (no need to change your code)! .. code:: bash - python main.py fit --lr_scheduler=ReduceLROnPlateau --lr_scheduler.monitor=epoch + python main.py fit --optimizer=Adam --lr_scheduler=ReduceLROnPlateau --lr_scheduler.monitor=epoch Furthermore, any custom subclass of ``torch.optim.lr_scheduler.LRScheduler`` can be used as learning rate scheduler: @@ -224,7 +226,7 @@ Now you can choose between any learning rate scheduler at runtime: .. code:: bash # LitLRScheduler - python main.py fit --lr_scheduler LitLRScheduler + python main.py fit --optimizer=Adam --lr_scheduler LitLRScheduler ---- From 989ddeaa329bbae5fc642a8f51c983e5976b6a9d Mon Sep 17 00:00:00 2001 From: Eric Lam Date: Thu, 4 May 2023 19:35:44 +0800 Subject: [PATCH 07/11] feat: add LargeFileManager configuration to Jupyter in Dockerfile (#17553) --- dockers/nvidia/Dockerfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dockers/nvidia/Dockerfile b/dockers/nvidia/Dockerfile index cb76595f3eac7..9bebcf282adef 100644 --- a/dockers/nvidia/Dockerfile +++ b/dockers/nvidia/Dockerfile @@ -49,6 +49,10 @@ RUN \ RUN pip install jupyterlab[all] -U +# create jupyter_notebook_config.py +RUN mkdir -p /root/.jupyter && \ + echo "c.NotebookApp.contents_manager_class = 'notebook.services.contents.largefilemanager.LargeFileManager'" > /root/.jupyter/jupyter_notebook_config.py + ENV PYTHONPATH="/workspace" RUN \ From 2b05e2f113fc530553b2996cc040c15ac874d995 Mon Sep 17 00:00:00 2001 From: Nicki Skafte Detlefsen Date: Thu, 4 May 2023 16:18:30 +0200 Subject: [PATCH 08/11] Fix problems in trainer docs (#17561) --- docs/source-pytorch/common/trainer.rst | 9 ++++---- src/lightning/pytorch/trainer/trainer.py | 27 ++++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/source-pytorch/common/trainer.rst b/docs/source-pytorch/common/trainer.rst index a1d0de11193ff..041b1c5c09987 100644 --- a/docs/source-pytorch/common/trainer.rst +++ b/docs/source-pytorch/common/trainer.rst @@ -1181,11 +1181,12 @@ The metrics available to callbacks. This includes metrics logged via :meth:`~lightning.pytorch.core.module.LightningModule.log`. -..code-block:: python +.. code-block:: python def training_step(self, batch, batch_idx): self.log("a_val", 2.0) + callback_metrics = trainer.callback_metrics assert callback_metrics["a_val"] == 2.0 @@ -1239,9 +1240,9 @@ The first :class:`~lightning.pytorch.loggers.logger.Logger` being used. loggers ******** -The list of class:`~lightning.pytorch.loggers.logger.Logger` used. +The list of :class:`~lightning.pytorch.loggers.logger.Logger` used. -..code-block:: python +.. code-block:: python for logger in trainer.loggers: logger.log_metrics({"foo": 1.0}) @@ -1276,7 +1277,7 @@ The estimated number of batches that will ``optimizer.step()`` during training. This accounts for gradient accumulation and the current trainer configuration. This might sets up your training dataloader if hadn't been set up already. -..code-block:: python +.. code-block:: python def configure_optimizers(self): optimizer = ... diff --git a/src/lightning/pytorch/trainer/trainer.py b/src/lightning/pytorch/trainer/trainer.py index 0875f2e229e18..6a74434661365 100644 --- a/src/lightning/pytorch/trainer/trainer.py +++ b/src/lightning/pytorch/trainer/trainer.py @@ -513,7 +513,7 @@ def fit( train_dataloaders: An iterable or collection of iterables specifying training samples. Alternatively, a :class:`~lightning.pytorch.core.datamodule.LightningDataModule` that defines - the `:class:`~lightning.pytorch.core.hooks.DataHooks.train_dataloader` hook. + the :class:`~lightning.pytorch.core.hooks.DataHooks.train_dataloader` hook. val_dataloaders: An iterable or collection of iterables specifying validation samples. @@ -523,7 +523,7 @@ def fit( datamodule: An instance of :class:`~lightning.pytorch.core.datamodule.LightningDataModule`. datamodule: A :class:`~lightning.pytorch.core.datamodule.LightningDataModule` that defines - the `:class:`~lightning.pytorch.core.hooks.DataHooks.train_dataloader` hook. + the :class:`~lightning.pytorch.core.hooks.DataHooks.train_dataloader` hook. Raises: TypeError: @@ -595,7 +595,7 @@ def validate( dataloaders: An iterable or collection of iterables specifying validation samples. Alternatively, a :class:`~lightning.pytorch.core.datamodule.LightningDataModule` that defines - the `:class:`~lightning.pytorch.core.hooks.DataHooks.val_dataloader` hook. + the :class:`~lightning.pytorch.core.hooks.DataHooks.val_dataloader` hook. ckpt_path: Either ``"best"``, ``"last"``, ``"hpc"`` or path to the checkpoint you wish to validate. If ``None`` and the model instance was passed, use the current weights. @@ -605,7 +605,7 @@ def validate( verbose: If True, prints the validation results. datamodule: A :class:`~lightning.pytorch.core.datamodule.LightningDataModule` that defines - the `:class:`~lightning.pytorch.core.hooks.DataHooks.val_dataloader` hook. + the :class:`~lightning.pytorch.core.hooks.DataHooks.val_dataloader` hook. For more information about multiple dataloaders, see this :ref:`section `. @@ -702,7 +702,7 @@ def test( dataloaders: An iterable or collection of iterables specifying test samples. Alternatively, a :class:`~lightning.pytorch.core.datamodule.LightningDataModule` that defines - the `:class:`~lightning.pytorch.core.hooks.DataHooks.test_dataloader` hook. + the :class:`~lightning.pytorch.core.hooks.DataHooks.test_dataloader` hook. ckpt_path: Either ``"best"``, ``"last"``, ``"hpc"`` or path to the checkpoint you wish to test. If ``None`` and the model instance was passed, use the current weights. @@ -712,7 +712,7 @@ def test( verbose: If True, prints the test results. datamodule: A :class:`~lightning.pytorch.core.datamodule.LightningDataModule` that defines - the `:class:`~lightning.pytorch.core.hooks.DataHooks.test_dataloader` hook. + the :class:`~lightning.pytorch.core.hooks.DataHooks.test_dataloader` hook. For more information about multiple dataloaders, see this :ref:`section `. @@ -809,10 +809,10 @@ def predict( dataloaders: An iterable or collection of iterables specifying predict samples. Alternatively, a :class:`~lightning.pytorch.core.datamodule.LightningDataModule` that defines - the `:class:`~lightning.pytorch.core.hooks.DataHooks.predict_dataloader` hook. + the :class:`~lightning.pytorch.core.hooks.DataHooks.predict_dataloader` hook. datamodule: A :class:`~lightning.pytorch.core.datamodule.LightningDataModule` that defines - the `:class:`~lightning.pytorch.core.hooks.DataHooks.predict_dataloader` hook. + the :class:`~lightning.pytorch.core.hooks.DataHooks.predict_dataloader` hook. return_predictions: Whether to return predictions. ``True`` by default except when an accelerator that spawns processes is used (not supported). @@ -1523,9 +1523,9 @@ def logger(self, logger: Optional[Logger]) -> None: @property def loggers(self) -> List[Logger]: - """The list of class:`~lightning.pytorch.loggers.logger.Logger` used. + """The list of :class:`~lightning.pytorch.loggers.logger.Logger` used. - ..code-block:: python + .. code-block:: python for logger in trainer.loggers: logger.log_metrics({"foo": 1.0}) @@ -1540,13 +1540,12 @@ def loggers(self, loggers: Optional[List[Logger]]) -> None: def callback_metrics(self) -> _OUT_DICT: """The metrics available to callbacks. - This includes metrics logged via :meth:`~lightning.pytorch.core.module.LightningModule.log`. - - ..code-block:: python + .. code-block:: python def training_step(self, batch, batch_idx): self.log("a_val", 2.0) + callback_metrics = trainer.callback_metrics assert callback_metrics["a_val"] == 2.0 """ @@ -1588,7 +1587,7 @@ def estimated_stepping_batches(self) -> Union[int, float]: This accounts for gradient accumulation and the current trainer configuration. This might sets up your training dataloader if hadn't been set up already. - ..code-block:: python + .. code-block:: python def configure_optimizers(self): optimizer = ... From f55d10f5ee0cb335b477cb6e8a1a7f5114daf472 Mon Sep 17 00:00:00 2001 From: Jirka Borovec <6035284+Borda@users.noreply.github.com> Date: Thu, 4 May 2023 17:50:39 +0200 Subject: [PATCH 09/11] ruff: autofix PT (#17541) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- pyproject.toml | 1 + .../app/cli/pl-app-template/tests/test_app.py | 2 +- src/lightning/app/utilities/app_status.py | 3 +- .../callbacks/stochastic_weight_avg.py | 3 +- tests/integrations_app/conftest.py | 4 +- .../integrations_app/flagship/test_flashy.py | 2 +- .../local/test_collect_failures.py | 2 +- .../local/test_custom_work_dependencies.py | 2 +- .../local/test_idle_timeout.py | 2 +- tests/integrations_app/public/test_app_dag.py | 2 +- .../public/test_boring_app.py | 2 +- .../public/test_commands_and_api.py | 2 +- tests/integrations_app/public/test_drive.py | 2 +- .../public/test_installation_commands_app.py | 2 +- tests/integrations_app/public/test_payload.py | 2 +- .../public/test_quick_start.py | 2 +- .../public/test_template_react_ui.py | 2 +- .../public/test_template_streamlit_ui.py | 2 +- tests/integrations_app/public/test_v0_app.py | 4 +- tests/tests_app/cli/test_cmd_apps.py | 2 +- tests/tests_app/cli/test_cmd_clusters.py | 2 +- tests/tests_app/cli/test_cmd_install.py | 4 +- tests/tests_app/cli/test_cmd_pl_init.py | 2 +- .../components/multi_node/test_fabric.py | 6 ++- .../components/multi_node/test_trainer.py | 6 ++- .../components/serve/test_auto_scaler.py | 10 ++-- tests/tests_app/conftest.py | 10 ++-- tests/tests_app/core/test_lightning_api.py | 16 +++--- tests/tests_app/core/test_lightning_app.py | 4 +- tests/tests_app/core/test_lightning_flow.py | 8 +-- tests/tests_app/core/test_lightning_work.py | 4 +- tests/tests_app/core/test_queues.py | 2 +- tests/tests_app/frontend/conftest.py | 4 +- .../frontend/panel/test_panel_frontend.py | 2 +- tests/tests_app/plugin/test_plugin.py | 4 +- tests/tests_app/runners/test_cloud.py | 18 +++---- tests/tests_app/runners/test_multiprocess.py | 4 +- tests/tests_app/storage/test_path.py | 8 +-- .../tests_app/utilities/test_app_commands.py | 2 +- tests/tests_app/utilities/test_app_helpers.py | 2 +- tests/tests_app/utilities/test_auth.py | 2 +- tests/tests_app/utilities/test_cli_helpers.py | 2 +- tests/tests_app/utilities/test_exceptions.py | 6 +-- tests/tests_app/utilities/test_layout.py | 4 +- tests/tests_app/utilities/test_log_helpers.py | 8 +-- tests/tests_app/utilities/test_proxies.py | 6 +-- tests/tests_app/utilities/test_secrets.py | 2 +- tests/tests_app/utilities/test_state.py | 2 +- tests/tests_app/utilities/test_tree.py | 2 +- tests/tests_cloud/conftest.py | 2 +- tests/tests_fabric/accelerators/test_cpu.py | 2 +- tests/tests_fabric/accelerators/test_cuda.py | 2 +- tests/tests_fabric/accelerators/test_mps.py | 2 +- tests/tests_fabric/conftest.py | 16 +++--- .../tests_fabric/parity/test_parity_simple.py | 2 +- .../collectives/test_torch_collective.py | 2 +- .../plugins/environments/test_lightning.py | 2 +- .../plugins/environments/test_slurm.py | 2 +- .../plugins/precision/test_amp_integration.py | 2 +- .../plugins/precision/test_fsdp.py | 2 +- .../plugins/precision/test_half.py | 8 +-- tests/tests_fabric/strategies/test_ddp.py | 6 +-- .../tests_fabric/strategies/test_deepspeed.py | 4 +- .../strategies/test_deepspeed_integration.py | 2 +- .../strategies/test_fsdp_integration.py | 2 +- .../strategies/test_single_device.py | 2 +- tests/tests_fabric/test_cli.py | 4 +- tests/tests_fabric/test_connector.py | 38 ++++++------- tests/tests_fabric/test_fabric.py | 6 +-- tests/tests_fabric/test_wrappers.py | 4 +- .../tests_fabric/utilities/test_apply_func.py | 9 ++-- tests/tests_fabric/utilities/test_data.py | 6 +-- .../utilities/test_device_dtype_mixin.py | 2 +- .../utilities/test_device_parser.py | 4 +- .../tests_fabric/utilities/test_rank_zero.py | 4 +- tests/tests_fabric/utilities/test_warnings.py | 3 +- tests/tests_pytorch/accelerators/test_mps.py | 24 ++++++--- tests/tests_pytorch/accelerators/test_xla.py | 4 +- .../benchmarks/test_basic_parity.py | 2 +- .../progress/test_rich_progress_bar.py | 2 +- .../progress/test_tqdm_progress_bar.py | 10 ++-- .../callbacks/test_early_stopping.py | 12 ++--- .../test_gradient_accumulation_scheduler.py | 2 +- tests/tests_pytorch/callbacks/test_timer.py | 4 +- .../test_checkpoint_callback_frequency.py | 6 +-- .../checkpointing/test_model_checkpoint.py | 8 +-- tests/tests_pytorch/conftest.py | 36 ++++++------- .../core/test_lightning_module.py | 2 +- .../core/test_metric_result_integration.py | 2 +- tests/tests_pytorch/helpers/test_datasets.py | 2 +- tests/tests_pytorch/helpers/test_models.py | 2 +- tests/tests_pytorch/loggers/test_mlflow.py | 2 +- tests/tests_pytorch/loggers/test_neptune.py | 54 +++++++++---------- tests/tests_pytorch/loggers/test_wandb.py | 3 +- tests/tests_pytorch/loops/test_loops.py | 4 +- .../loops/test_training_epoch_loop.py | 4 +- .../tests_pytorch/loops/test_training_loop.py | 4 +- tests/tests_pytorch/models/test_cpu.py | 3 +- tests/tests_pytorch/models/test_gpu.py | 24 ++++++--- tests/tests_pytorch/models/test_hooks.py | 4 +- tests/tests_pytorch/models/test_hparams.py | 2 +- tests/tests_pytorch/models/test_onnx.py | 2 +- .../tests_pytorch/plugins/test_amp_plugins.py | 4 +- .../tests_pytorch/profilers/test_profiler.py | 16 +++--- tests/tests_pytorch/strategies/test_ddp.py | 4 +- .../strategies/test_ddp_spawn_strategy.py | 2 +- .../strategies/test_deepspeed_strategy.py | 6 +-- tests/tests_pytorch/strategies/test_fsdp.py | 4 +- .../tests_pytorch/strategies/test_registry.py | 4 +- tests/tests_pytorch/test_cli.py | 20 +++---- .../connectors/test_accelerator_connector.py | 32 +++++------ .../connectors/test_callback_connector.py | 9 ++-- .../trainer/connectors/test_data_connector.py | 10 ++-- .../connectors/test_signal_connector.py | 2 +- .../flags/test_check_val_every_n_epoch.py | 2 +- .../trainer/flags/test_min_max_epochs.py | 2 +- .../trainer/flags/test_overfit_batches.py | 2 +- .../logging_/test_eval_loop_logging.py | 8 +-- .../logging_/test_train_loop_logging.py | 4 +- .../trainer/optimization/test_optimizers.py | 5 +- .../test_estimated_stepping_batches.py | 4 +- .../tests_pytorch/trainer/test_dataloaders.py | 16 +++--- tests/tests_pytorch/trainer/test_trainer.py | 21 ++++---- tests/tests_pytorch/tuner/test_lr_finder.py | 2 +- .../tuner/test_scale_batch_size.py | 4 +- .../utilities/migration/test_migration.py | 2 +- .../utilities/test_combined_loader.py | 2 +- tests/tests_pytorch/utilities/test_grads.py | 2 +- tests/tests_pytorch/utilities/test_imports.py | 4 +- .../utilities/test_model_summary.py | 2 +- .../utilities/test_parameter_tying.py | 2 +- .../tests_pytorch/utilities/test_warnings.py | 3 +- 133 files changed, 406 insertions(+), 357 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e692aa8de2a54..e980b380efee3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -69,7 +69,7 @@ repos: name: Unused noqa additional_dependencies: #- pep8-naming - #- flake8-pytest-style + - flake8-pytest-style - flake8-bandit - flake8-simplify diff --git a/pyproject.toml b/pyproject.toml index e9d33961f3f89..f386356c7daa4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -60,6 +60,7 @@ select = [ extend-select = [ "C4", # see: https://pypi.org/project/flake8-comprehensions "SIM", # see: https://pypi.org/project/flake8-simplify +# "PT", # see: https://pypi.org/project/flake8-pytest-style ] ignore = [ "E731", # Do not assign a lambda expression, use a def diff --git a/src/lightning/app/cli/pl-app-template/tests/test_app.py b/src/lightning/app/cli/pl-app-template/tests/test_app.py index 6e724f53d8de9..3fc14bfcdbf69 100644 --- a/src/lightning/app/cli/pl-app-template/tests/test_app.py +++ b/src/lightning/app/cli/pl-app-template/tests/test_app.py @@ -1,7 +1,7 @@ import pytest -@pytest.mark.skip +@pytest.mark.skip() def test_is_running_in_cloud(monkeypatch): from app import Main diff --git a/src/lightning/app/utilities/app_status.py b/src/lightning/app/utilities/app_status.py index 2b383cb2956b4..1f40da05bc140 100644 --- a/src/lightning/app/utilities/app_status.py +++ b/src/lightning/app/utilities/app_status.py @@ -30,7 +30,8 @@ class WorkStatus(BaseModel): def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) - assert self.timestamp > 0 and self.timestamp < (int(datetime.now().timestamp()) + 10) + assert self.timestamp > 0 + assert self.timestamp < (int(datetime.now().timestamp()) + 10) class AppStatus(BaseModel): diff --git a/src/lightning/pytorch/callbacks/stochastic_weight_avg.py b/src/lightning/pytorch/callbacks/stochastic_weight_avg.py index e8dbf997899d7..dc6ae074a31b4 100644 --- a/src/lightning/pytorch/callbacks/stochastic_weight_avg.py +++ b/src/lightning/pytorch/callbacks/stochastic_weight_avg.py @@ -207,7 +207,8 @@ def on_train_epoch_start(self, trainer: "pl.Trainer", pl_module: "pl.LightningMo # We assert that there is only one optimizer on fit start default_scheduler_cfg = LRSchedulerConfig(self._swa_scheduler) - assert default_scheduler_cfg.interval == "epoch" and default_scheduler_cfg.frequency == 1 + assert default_scheduler_cfg.interval == "epoch" + assert default_scheduler_cfg.frequency == 1 if trainer.lr_scheduler_configs: scheduler_cfg = trainer.lr_scheduler_configs[0] diff --git a/tests/integrations_app/conftest.py b/tests/integrations_app/conftest.py index 2efd435e66318..ad0855293b7bb 100644 --- a/tests/integrations_app/conftest.py +++ b/tests/integrations_app/conftest.py @@ -54,7 +54,7 @@ def pytest_sessionfinish(session, exitstatus): t.join(0) -@pytest.fixture(scope="function", autouse=True) +@pytest.fixture(autouse=True) def cleanup(): from lightning.app.utilities.app_helpers import _LightningAppRef @@ -68,7 +68,7 @@ def cleanup(): _set_context(None) -@pytest.fixture(scope="function", autouse=True) +@pytest.fixture(autouse=True) def clear_app_state_state_variables(): """Resets global variables in order to prevent interference between tests.""" yield diff --git a/tests/integrations_app/flagship/test_flashy.py b/tests/integrations_app/flagship/test_flashy.py index e9237e40804af..c40cb155c2564 100644 --- a/tests/integrations_app/flagship/test_flashy.py +++ b/tests/integrations_app/flagship/test_flashy.py @@ -66,7 +66,7 @@ def validate_app_functionalities(app_page: "Page") -> None: expect(runs).to_have_count(1, timeout=120000) -@pytest.mark.cloud +@pytest.mark.cloud() def test_app_cloud() -> None: with run_app_in_cloud(_PATH_INTEGRATIONS_DIR) as (admin_page, view_page, fetch_logs, _): validate_app_functionalities(view_page) diff --git a/tests/integrations_app/local/test_collect_failures.py b/tests/integrations_app/local/test_collect_failures.py index 550626007d865..1ac54c0a0ce10 100644 --- a/tests/integrations_app/local/test_collect_failures.py +++ b/tests/integrations_app/local/test_collect_failures.py @@ -7,7 +7,7 @@ from lightning.app.testing.testing import run_app_in_cloud -@pytest.mark.cloud +@pytest.mark.cloud() def test_collect_failures_example_cloud() -> None: # logs are in order expected_logs = [ diff --git a/tests/integrations_app/local/test_custom_work_dependencies.py b/tests/integrations_app/local/test_custom_work_dependencies.py index 0b52aadd67d15..49cb4dddde958 100644 --- a/tests/integrations_app/local/test_custom_work_dependencies.py +++ b/tests/integrations_app/local/test_custom_work_dependencies.py @@ -7,7 +7,7 @@ from lightning.app.testing.testing import run_app_in_cloud -@pytest.mark.cloud +@pytest.mark.cloud() def test_custom_work_dependencies_example_cloud() -> None: # if requirements not installed, the app will fail with run_app_in_cloud( diff --git a/tests/integrations_app/local/test_idle_timeout.py b/tests/integrations_app/local/test_idle_timeout.py index edb04c1f8641f..ac251ca603a9b 100644 --- a/tests/integrations_app/local/test_idle_timeout.py +++ b/tests/integrations_app/local/test_idle_timeout.py @@ -7,7 +7,7 @@ from lightning.app.testing.testing import run_app_in_cloud -@pytest.mark.cloud +@pytest.mark.cloud() def test_idle_timeout_example_cloud() -> None: with run_app_in_cloud(os.path.join(_PATH_APPS, "idle_timeout")) as ( _, diff --git a/tests/integrations_app/public/test_app_dag.py b/tests/integrations_app/public/test_app_dag.py index 0bdbdcae47f18..199cb54e0f93b 100644 --- a/tests/integrations_app/public/test_app_dag.py +++ b/tests/integrations_app/public/test_app_dag.py @@ -7,7 +7,7 @@ from lightning.app.testing.testing import run_app_in_cloud -@pytest.mark.cloud +@pytest.mark.cloud() def test_app_dag_example_cloud() -> None: with run_app_in_cloud(os.path.join(_PATH_EXAMPLES, "dag")) as (_, _, fetch_logs, _): launch_log, finish_log = False, False diff --git a/tests/integrations_app/public/test_boring_app.py b/tests/integrations_app/public/test_boring_app.py index 40893bb4b5728..a58685df8147d 100644 --- a/tests/integrations_app/public/test_boring_app.py +++ b/tests/integrations_app/public/test_boring_app.py @@ -8,7 +8,7 @@ from lightning.app.testing.testing import run_app_in_cloud, wait_for -@pytest.mark.cloud +@pytest.mark.cloud() def test_boring_app_example_cloud() -> None: with run_app_in_cloud(os.path.join(_PATH_EXAMPLES, "boring"), app_name="app_dynamic.py", debug=True) as ( _, diff --git a/tests/integrations_app/public/test_commands_and_api.py b/tests/integrations_app/public/test_commands_and_api.py index a8af0c0088bbb..d74d6d46ef8ce 100644 --- a/tests/integrations_app/public/test_commands_and_api.py +++ b/tests/integrations_app/public/test_commands_and_api.py @@ -9,7 +9,7 @@ @pytest.mark.timeout(300) -@pytest.mark.cloud +@pytest.mark.cloud() def test_commands_and_api_example_cloud() -> None: with run_app_in_cloud(os.path.join(_PATH_EXAMPLES, "commands_and_api")) as ( _, diff --git a/tests/integrations_app/public/test_drive.py b/tests/integrations_app/public/test_drive.py index b17508bbfce96..ac49d8ca1fcbc 100644 --- a/tests/integrations_app/public/test_drive.py +++ b/tests/integrations_app/public/test_drive.py @@ -7,7 +7,7 @@ from lightning.app.testing.testing import run_app_in_cloud -@pytest.mark.cloud +@pytest.mark.cloud() def test_drive_example_cloud() -> None: with run_app_in_cloud(os.path.join(_PATH_EXAMPLES, "drive")) as ( _, diff --git a/tests/integrations_app/public/test_installation_commands_app.py b/tests/integrations_app/public/test_installation_commands_app.py index f80619e12959e..9130ea9f98361 100644 --- a/tests/integrations_app/public/test_installation_commands_app.py +++ b/tests/integrations_app/public/test_installation_commands_app.py @@ -6,7 +6,7 @@ from lightning.app.testing.testing import run_app_in_cloud -@pytest.mark.cloud +@pytest.mark.cloud() def test_installation_commands_app_example_cloud() -> None: # This is expected to pass, since the "setup" flag is passed with run_app_in_cloud( diff --git a/tests/integrations_app/public/test_payload.py b/tests/integrations_app/public/test_payload.py index 0ff968b4f8247..e94aaab2f3e12 100644 --- a/tests/integrations_app/public/test_payload.py +++ b/tests/integrations_app/public/test_payload.py @@ -7,7 +7,7 @@ from lightning.app.testing.testing import run_app_in_cloud -@pytest.mark.cloud +@pytest.mark.cloud() def test_payload_example_cloud() -> None: with run_app_in_cloud(os.path.join(_PATH_EXAMPLES, "payload")) as (_, _, fetch_logs, _): has_logs = False diff --git a/tests/integrations_app/public/test_quick_start.py b/tests/integrations_app/public/test_quick_start.py index 379494e775d80..6adb70960fc12 100644 --- a/tests/integrations_app/public/test_quick_start.py +++ b/tests/integrations_app/public/test_quick_start.py @@ -48,7 +48,7 @@ def test_quick_start_example(caplog, monkeypatch): assert result.exit_code == 0 -@pytest.mark.cloud +@pytest.mark.cloud() def test_quick_start_example_cloud() -> None: with run_app_in_cloud(os.path.join(_PATH_EXAMPLES, "lightning-quick-start")) as (_, view_page, _, _): diff --git a/tests/integrations_app/public/test_template_react_ui.py b/tests/integrations_app/public/test_template_react_ui.py index ca414758e9947..8ece90c431cce 100644 --- a/tests/integrations_app/public/test_template_react_ui.py +++ b/tests/integrations_app/public/test_template_react_ui.py @@ -7,7 +7,7 @@ from lightning.app.testing.testing import run_app_in_cloud, wait_for -@pytest.mark.cloud +@pytest.mark.cloud() def test_template_react_ui_example_cloud() -> None: """This test ensures streamlit works in the cloud by clicking a button and checking the logs.""" with run_app_in_cloud(os.path.join(_PATH_EXAMPLES, "template_react_ui")) as ( diff --git a/tests/integrations_app/public/test_template_streamlit_ui.py b/tests/integrations_app/public/test_template_streamlit_ui.py index d4cb5686402d3..8f0cec112cb67 100644 --- a/tests/integrations_app/public/test_template_streamlit_ui.py +++ b/tests/integrations_app/public/test_template_streamlit_ui.py @@ -7,7 +7,7 @@ from lightning.app.testing.testing import run_app_in_cloud, wait_for -@pytest.mark.cloud +@pytest.mark.cloud() def test_template_streamlit_ui_example_cloud() -> None: """This test ensures streamlit works in the cloud by clicking a button and checking the logs.""" with run_app_in_cloud(os.path.join(_PATH_EXAMPLES, "template_streamlit_ui")) as ( diff --git a/tests/integrations_app/public/test_v0_app.py b/tests/integrations_app/public/test_v0_app.py index 634fd10fd93b6..7a350ef97975d 100644 --- a/tests/integrations_app/public/test_v0_app.py +++ b/tests/integrations_app/public/test_v0_app.py @@ -59,7 +59,7 @@ def check_content(button_name, text_content): sleep(1) -@pytest.mark.cloud +@pytest.mark.cloud() @pytest.mark.skipif( os.environ.get("LIGHTNING_BYOC_CLUSTER_ID") is None, reason="missing LIGHTNING_BYOC_CLUSTER_ID environment variable", @@ -72,7 +72,7 @@ def test_v0_app_example_byoc_cloud() -> None: run_v0_app(fetch_logs, view_page) -@pytest.mark.cloud +@pytest.mark.cloud() def test_v0_app_example_cloud() -> None: with run_app_in_cloud(os.path.join(_PATH_EXAMPLES, "v0")) as ( _, diff --git a/tests/tests_app/cli/test_cmd_apps.py b/tests/tests_app/cli/test_cmd_apps.py index afb7ae77d7397..afe2e99f001e5 100644 --- a/tests/tests_app/cli/test_cmd_apps.py +++ b/tests/tests_app/cli/test_cmd_apps.py @@ -19,7 +19,7 @@ @pytest.mark.parametrize( - "current_state,desired_state,expected", + ("current_state", "desired_state", "expected"), [ ( V1LightningappInstanceStatus(phase=V1LightningappInstanceState.RUNNING), diff --git a/tests/tests_app/cli/test_cmd_clusters.py b/tests/tests_app/cli/test_cmd_clusters.py index 415e2c83ca7ba..9cee9dba69d52 100644 --- a/tests/tests_app/cli/test_cmd_clusters.py +++ b/tests/tests_app/cli/test_cmd_clusters.py @@ -34,7 +34,7 @@ def async_or_interrupt(request, monkeypatch): return request.param -@pytest.fixture +@pytest.fixture() def spec(): return V1ClusterSpec( driver=V1ClusterDriver( diff --git a/tests/tests_app/cli/test_cmd_install.py b/tests/tests_app/cli/test_cmd_install.py index fff9f8c37368c..a20c91d080988 100644 --- a/tests/tests_app/cli/test_cmd_install.py +++ b/tests/tests_app/cli/test_cmd_install.py @@ -111,7 +111,7 @@ def test_unpublished_component_url_parsing(): @pytest.mark.skip(reason="need to figure out how to authorize pip install from the private repo") @pytest.mark.parametrize( - "real_component, test_component_pip_name", + ("real_component", "test_component_pip_name"), [ ("lightning/lit-slack-messenger", "lit-slack"), ( @@ -353,7 +353,7 @@ def test_private_component_registry(): @mock.patch("lightning.app.cli.cmd_install.subprocess") @mock.patch("lightning.app.cli.cmd_install.os.chdir", mock.MagicMock()) @pytest.mark.parametrize( - "source_url, git_url, git_sha", + ("source_url", "git_url", "git_sha"), [ ( "https://github.com/PyTorchLightning/lightning-quick-start", diff --git a/tests/tests_app/cli/test_cmd_pl_init.py b/tests/tests_app/cli/test_cmd_pl_init.py index 664d3bcb89230..e4a0834c067ad 100644 --- a/tests/tests_app/cli/test_cmd_pl_init.py +++ b/tests/tests_app/cli/test_cmd_pl_init.py @@ -100,7 +100,7 @@ def test_pl_app_encode_icon(monkeypatch): @pytest.mark.parametrize( - "cwd, source_dir, script_path", + ("cwd", "source_dir", "script_path"), [ ("./", "./", "train.py"), ("./", "./code", "./code/train.py"), diff --git a/tests/tests_app/components/multi_node/test_fabric.py b/tests/tests_app/components/multi_node/test_fabric.py index 7e6b7bae8cd5c..85d4ac786de38 100644 --- a/tests/tests_app/components/multi_node/test_fabric.py +++ b/tests/tests_app/components/multi_node/test_fabric.py @@ -47,7 +47,9 @@ def check_lightning_fabric_mps(): @pytest.mark.skipif(not check_lightning_fabric_mps(), reason="Fabric not available or mps not available") -@pytest.mark.parametrize("accelerator_given,accelerator_expected", [("cpu", "cpu"), ("auto", "cpu"), ("gpu", "cpu")]) +@pytest.mark.parametrize( + ("accelerator_given", "accelerator_expected"), [("cpu", "cpu"), ("auto", "cpu"), ("gpu", "cpu")] +) def test_fabric_run_executor_mps_forced_cpu(accelerator_given, accelerator_expected): warning_str = ( r"Forcing accelerator=cpu as other accelerators \(specifically MPS\) are not supported " @@ -64,7 +66,7 @@ def test_fabric_run_executor_mps_forced_cpu(accelerator_given, accelerator_expec @pytest.mark.parametrize( - "args_given,args_expected", + ("args_given", "args_expected"), [ ({"devices": 1, "num_nodes": 1, "accelerator": "gpu"}, {"devices": 8, "num_nodes": 7, "accelerator": "auto"}), ({"strategy": "ddp_spawn"}, {"strategy": "ddp"}), diff --git a/tests/tests_app/components/multi_node/test_trainer.py b/tests/tests_app/components/multi_node/test_trainer.py index 249d7868652bb..eb22967a86dec 100644 --- a/tests/tests_app/components/multi_node/test_trainer.py +++ b/tests/tests_app/components/multi_node/test_trainer.py @@ -42,7 +42,9 @@ def check_lightning_pytorch_and_mps(): @pytest.mark.skipif(not check_lightning_pytorch_and_mps(), reason="pytorch_lightning and mps are required") -@pytest.mark.parametrize("accelerator_given,accelerator_expected", [("cpu", "cpu"), ("auto", "cpu"), ("gpu", "cpu")]) +@pytest.mark.parametrize( + ("accelerator_given", "accelerator_expected"), [("cpu", "cpu"), ("auto", "cpu"), ("gpu", "cpu")] +) def test_trainer_run_executor_mps_forced_cpu(accelerator_given, accelerator_expected): warning_str = ( r"Forcing accelerator=cpu as other accelerators \(specifically MPS\) are not supported " @@ -59,7 +61,7 @@ def test_trainer_run_executor_mps_forced_cpu(accelerator_given, accelerator_expe @pytest.mark.parametrize( - "args_given,args_expected", + ("args_given", "args_expected"), [ ({"devices": 1, "num_nodes": 1, "accelerator": "gpu"}, {"devices": 8, "num_nodes": 7, "accelerator": "auto"}), ({"strategy": "ddp_spawn"}, {"strategy": "ddp"}), diff --git a/tests/tests_app/components/serve/test_auto_scaler.py b/tests/tests_app/components/serve/test_auto_scaler.py index ed1dc8248ff48..47fb8d78cbe4f 100644 --- a/tests/tests_app/components/serve/test_auto_scaler.py +++ b/tests/tests_app/components/serve/test_auto_scaler.py @@ -71,7 +71,7 @@ def test_num_replicas_not_below_min_replicas(*_): @pytest.mark.parametrize( - "replicas, metrics, expected_replicas", + ("replicas", "metrics", "expected_replicas"), [ pytest.param(1, {"pending_requests": 1, "pending_works": 0}, 2, id="increase if no pending work"), pytest.param(1, {"pending_requests": 1, "pending_works": 1}, 1, id="dont increase if pending works"), @@ -172,7 +172,7 @@ def test_autoscaler_scale_down(monkeypatch): class TestLoadBalancerProcessRequest: - @pytest.mark.asyncio + @pytest.mark.asyncio() async def test_workers_not_ready_with_cold_start_proxy(self, monkeypatch): monkeypatch.setattr(ColdStartProxy, "handle_request", mock.AsyncMock()) load_balancer = _LoadBalancer( @@ -182,7 +182,7 @@ async def test_workers_not_ready_with_cold_start_proxy(self, monkeypatch): await load_balancer.process_request("test", req_id) load_balancer._cold_start_proxy.handle_request.assert_called_once_with("test") - @pytest.mark.asyncio + @pytest.mark.asyncio() async def test_workers_not_ready_without_cold_start_proxy(self, monkeypatch): load_balancer = _LoadBalancer( input_type=Text, @@ -195,7 +195,7 @@ async def test_workers_not_ready_without_cold_start_proxy(self, monkeypatch): with pytest.raises(HTTPException): await load_balancer.process_request("test", req_id) - @pytest.mark.asyncio + @pytest.mark.asyncio() async def test_workers_have_no_capacity_with_cold_start_proxy(self, monkeypatch): monkeypatch.setattr(ColdStartProxy, "handle_request", mock.AsyncMock()) load_balancer = _LoadBalancer( @@ -208,7 +208,7 @@ async def test_workers_have_no_capacity_with_cold_start_proxy(self, monkeypatch) await load_balancer.process_request("test", req_id) load_balancer._cold_start_proxy.handle_request.assert_called_once_with("test") - @pytest.mark.asyncio + @pytest.mark.asyncio() async def test_workers_are_free(self): load_balancer = _LoadBalancer( input_type=Text, diff --git a/tests/tests_app/conftest.py b/tests/tests_app/conftest.py index f7704af7b7677..1a03b6e356bfb 100644 --- a/tests/tests_app/conftest.py +++ b/tests/tests_app/conftest.py @@ -56,7 +56,7 @@ def pytest_sessionfinish(session, exitstatus): os.kill(child_pid, signal.SIGTERM) -@pytest.fixture(scope="function", autouse=True) +@pytest.fixture(autouse=True) def cleanup(): from lightning.app.utilities.app_helpers import _LightningAppRef @@ -70,7 +70,7 @@ def cleanup(): _set_context(None) -@pytest.fixture(scope="function", autouse=True) +@pytest.fixture(autouse=True) def clear_app_state_state_variables(): """Resets global variables in order to prevent interference between tests.""" yield @@ -83,14 +83,14 @@ def clear_app_state_state_variables(): cloud_compute._CLOUD_COMPUTE_STORE.clear() -@pytest.fixture +@pytest.fixture() def another_tmpdir(tmp_path: Path) -> py.path.local: random_dir = datetime.now().strftime("%m-%d-%Y-%H-%M-%S") tmp_path = os.path.join(tmp_path, random_dir) return py.path.local(tmp_path) -@pytest.fixture +@pytest.fixture() def caplog(caplog): """Workaround for https://github.com/pytest-dev/pytest/issues/3697. @@ -117,7 +117,7 @@ def caplog(caplog): logging.getLogger(name).propagate = propagate -@pytest.fixture +@pytest.fixture() def patch_constants(request): """This fixture can be used with indirect parametrization to patch values in `lightning.app.core.constants` for the duration of a test. diff --git a/tests/tests_app/core/test_lightning_api.py b/tests/tests_app/core/test_lightning_api.py index d8ce61398b60f..b5740ff05538c 100644 --- a/tests/tests_app/core/test_lightning_api.py +++ b/tests/tests_app/core/test_lightning_api.py @@ -208,7 +208,7 @@ def test_update_publish_state_and_maybe_refresh_ui(): @pytest.mark.parametrize("x_lightning_type", ["DEFAULT", "STREAMLIT"]) -@pytest.mark.anyio +@pytest.mark.anyio() async def test_start_server(x_lightning_type, monkeypatch): """This test relies on FastAPI TestClient and validates that the REST API properly provides: @@ -344,7 +344,7 @@ def get(self, timeout: int = 0): @pytest.mark.parametrize( - "path, expected_status_code", + ("path", "expected_status_code"), ( ("/api/v1", 404), ("/api/v1/asdf", 404), @@ -352,7 +352,7 @@ def get(self, timeout: int = 0): ("/api", 404), ), ) -@pytest.mark.anyio +@pytest.mark.anyio() async def test_state_api_routes(path, expected_status_code): async with AsyncClient(app=fastapi_service, base_url="http://test") as client: response = await client.get(path) @@ -360,7 +360,7 @@ async def test_state_api_routes(path, expected_status_code): @pytest.mark.skipif(not check_if_redis_running(), reason="redis not running") -@pytest.mark.anyio +@pytest.mark.anyio() async def test_health_endpoint_success(): global_app_state_store.store = {} global_app_state_store.add("1234") @@ -381,7 +381,7 @@ async def test_health_endpoint_success(): @pytest.mark.skipif( check_if_redis_running(), reason="this is testing the failure condition " "for which the redis should not run" ) -@pytest.mark.anyio +@pytest.mark.anyio() async def test_health_endpoint_failure(monkeypatch): monkeypatch.setenv("LIGHTNING_APP_STATE_URL", "http://someurl") # adding this to make is_running_in_cloud pass monkeypatch.setitem(os.environ, "LIGHTNING_CLOUD_QUEUE_TYPE", "redis") @@ -392,14 +392,14 @@ async def test_health_endpoint_failure(monkeypatch): @pytest.mark.parametrize( - "path, expected_status_code", + ("path", "expected_status_code"), ( ("/", 200), ("/asdf", 200), ("/view/component_a", 200), ), ) -@pytest.mark.anyio +@pytest.mark.anyio() async def test_frontend_routes(path, expected_status_code): async with AsyncClient(app=fastapi_service, base_url="http://test") as client: response = await client.get(path) @@ -564,7 +564,7 @@ def test_configure_api(): process.kill() -@pytest.mark.anyio +@pytest.mark.anyio() @mock.patch("lightning.app.core.api.UIRefresher", mock.MagicMock()) async def test_get_annotations(tmpdir): cwd = os.getcwd() diff --git a/tests/tests_app/core/test_lightning_app.py b/tests/tests_app/core/test_lightning_app.py index 006e5a45160cd..44de6de0dc659 100644 --- a/tests/tests_app/core/test_lightning_app.py +++ b/tests/tests_app/core/test_lightning_app.py @@ -427,7 +427,7 @@ def run(self): @pytest.mark.parametrize( - "queue_type_cls, default_timeout", + ("queue_type_cls", "default_timeout"), [ (MultiProcessQueue, STATE_UPDATE_TIMEOUT), pytest.param( @@ -438,7 +438,7 @@ def run(self): ], ) @pytest.mark.parametrize( - "sleep_time, expect", + ("sleep_time", "expect"), [ (1, 0), pytest.param(0, 10.0, marks=pytest.mark.xfail(strict=False, reason="failing...")), # fixme diff --git a/tests/tests_app/core/test_lightning_flow.py b/tests/tests_app/core/test_lightning_flow.py index ef28d29b06b77..383d497f8a17a 100644 --- a/tests/tests_app/core/test_lightning_flow.py +++ b/tests/tests_app/core/test_lightning_flow.py @@ -76,7 +76,7 @@ def run(self): @pytest.mark.parametrize( - "name,value", + ("name", "value"), [ ("x", 1), ("f", EmptyFlow()), @@ -100,7 +100,7 @@ def test_unsupported_attribute_declaration_outside_init_or_run(name, value): @pytest.mark.parametrize( - "name,value", + ("name", "value"), [ ("x", 1), ("f", EmptyFlow()), @@ -163,7 +163,7 @@ def run(self): @pytest.mark.parametrize( - "name,value", + ("name", "value"), [ ("_name", "name"), ("_changes", {"change": 1}), @@ -244,7 +244,7 @@ def run(self): @pytest.mark.parametrize( - "attribute,update_fn,expected", + ("attribute", "update_fn", "expected"), ( (1, lambda x: x + 1, 2), (0.5, lambda x: x + 0.5, 1.0), diff --git a/tests/tests_app/core/test_lightning_work.py b/tests/tests_app/core/test_lightning_work.py index 14d87fbabf23d..3b7437f95ba0a 100644 --- a/tests/tests_app/core/test_lightning_work.py +++ b/tests/tests_app/core/test_lightning_work.py @@ -85,7 +85,7 @@ def run(self): @pytest.mark.parametrize( - "name,value", + ("name", "value"), [ ("x", 1), ("f", EmptyFlow()), @@ -102,7 +102,7 @@ def test_unsupported_attribute_declaration_outside_init(name, value): @pytest.mark.parametrize( - "name,value", + ("name", "value"), [ ("_name", "name"), ("_changes", {"change": 1}), diff --git a/tests/tests_app/core/test_queues.py b/tests/tests_app/core/test_queues.py index 55c0523daf64b..d00432b734aad 100644 --- a/tests/tests_app/core/test_queues.py +++ b/tests/tests_app/core/test_queues.py @@ -103,7 +103,7 @@ def test_redis_queue_read_timeout(redis_mock): @pytest.mark.parametrize( - "queue_type, queue_process_mock", + ("queue_type", "queue_process_mock"), [(QueuingSystem.MULTIPROCESS, multiprocessing)], ) def test_process_queue_read_timeout(queue_type, queue_process_mock, monkeypatch): diff --git a/tests/tests_app/frontend/conftest.py b/tests/tests_app/frontend/conftest.py index 4b8f72766c9cc..6aa31d61874be 100644 --- a/tests/tests_app/frontend/conftest.py +++ b/tests/tests_app/frontend/conftest.py @@ -61,13 +61,13 @@ def mock_start_websocket(): yield -@pytest.fixture +@pytest.fixture() def app_state_state(): """Returns an AppState dict.""" return APP_STATE.copy() -@pytest.fixture +@pytest.fixture() def flow_state_state(): """Returns an AppState dict scoped to the flow.""" return FLOW_STATE.copy() diff --git a/tests/tests_app/frontend/panel/test_panel_frontend.py b/tests/tests_app/frontend/panel/test_panel_frontend.py index b27ead7460190..ff5425f3f95d0 100644 --- a/tests/tests_app/frontend/panel/test_panel_frontend.py +++ b/tests/tests_app/frontend/panel/test_panel_frontend.py @@ -138,7 +138,7 @@ def test_open_close_log_files(): @pytest.mark.parametrize( - ["value", "expected"], + ("value", "expected"), ( ("Yes", True), ("yes", True), diff --git a/tests/tests_app/plugin/test_plugin.py b/tests/tests_app/plugin/test_plugin.py index 81983ff91b2e9..da858ddcc1d9a 100644 --- a/tests/tests_app/plugin/test_plugin.py +++ b/tests/tests_app/plugin/test_plugin.py @@ -74,7 +74,7 @@ def run(self): @pytest.mark.skipif(sys.platform == "win32", reason="the plugin server is only intended to run on linux.") @pytest.mark.parametrize( - "body,message,tar_file_name,content", + ("body", "message", "tar_file_name", "content"), [ ( _Run( @@ -181,7 +181,7 @@ def run(self, name, entrypoint): @pytest.mark.skipif(sys.platform == "win32", reason="the plugin server is only intended to run on linux.") @pytest.mark.parametrize( - "plugin_source, actions", + ("plugin_source", "actions"), [ (_plugin_with_job_run_no_actions, []), (_plugin_with_job_run_toast, [{"content": "info:testing", "type": "TOAST"}]), diff --git a/tests/tests_app/runners/test_cloud.py b/tests/tests_app/runners/test_cloud.py index ab2fa57539760..2edb02efa3efc 100644 --- a/tests/tests_app/runners/test_cloud.py +++ b/tests/tests_app/runners/test_cloud.py @@ -116,7 +116,7 @@ def get_cloud_runtime_request_body(**kwargs) -> "CloudspaceIdRunsBody": return CloudspaceIdRunsBody(**default_request_body) -@pytest.fixture +@pytest.fixture() def cloud_backend(monkeypatch): cloud_backend = mock.MagicMock() monkeypatch.setattr(cloud, "LocalSourceCodeDir", mock.MagicMock()) @@ -125,7 +125,7 @@ def cloud_backend(monkeypatch): return cloud_backend -@pytest.fixture +@pytest.fixture() def project_id(): return "test-project-id" @@ -169,7 +169,7 @@ def test_run_on_deleted_cluster(self, cloud_backend): cloud_runtime.dispatch(name=app_name, cluster_id="unknown-cluster") @pytest.mark.parametrize( - "old_cluster,new_cluster", + ("old_cluster", "new_cluster"), [ ("test", "other"), ("test", "test"), @@ -578,7 +578,7 @@ def test_no_cache(self, tmpdir, monkeypatch): @mock.patch("lightning.app.runners.backends.cloud.LightningClient", mock.MagicMock()) @pytest.mark.parametrize( - "lightningapps,start_with_flow", + ("lightningapps", "start_with_flow"), [([], False), ([MagicMock()], False), ([MagicMock()], True)], ) def test_call_with_work_app(self, lightningapps, start_with_flow, monkeypatch, tmpdir): @@ -1456,7 +1456,7 @@ def test_open(self, monkeypatch): assert mock_client.cloud_space_service_create_cloud_space.call_args.kwargs["body"].name == "test_space" @pytest.mark.parametrize( - "path, expected_root, entries, expected_filtered_entries", + ("path", "expected_root", "entries", "expected_filtered_entries"), [ [".", ".", ["a.py", "b.ipynb"], ["a.py", "b.ipynb"]], ["a.py", ".", ["a.py", "b.ipynb"], ["a.py"]], @@ -1604,7 +1604,7 @@ def test_not_enabled(self, monkeypatch, capsys): class TestCloudspaceDispatch: @mock.patch.object(pathlib.Path, "exists") @pytest.mark.parametrize( - "custom_env_sync_path_value, cloudspace", + ("custom_env_sync_path_value", "cloudspace"), [ [None, V1CloudSpace(id="test_id", code_config=V1CloudSpaceInstanceConfig())], [ @@ -1833,7 +1833,7 @@ def test_load_app_from_file(): @pytest.mark.parametrize( - "print_format,expected", + ("print_format", "expected"), [ ( "web", @@ -2067,7 +2067,7 @@ def run(self): @pytest.mark.parametrize( - "project, run_instance, user, tab, lightning_cloud_url, expected_url", + ("project", "run_instance", "user", "tab", "lightning_cloud_url", "expected_url"), [ # Old style ( @@ -2120,7 +2120,7 @@ def test_get_app_url(monkeypatch, project, run_instance, user, tab, lightning_cl @pytest.mark.parametrize( - "user, project, cloudspace_name, tab, lightning_cloud_url, expected_url", + ("user", "project", "cloudspace_name", "tab", "lightning_cloud_url", "expected_url"), [ ( V1GetUserResponse(username="tester", features=V1UserFeatures()), diff --git a/tests/tests_app/runners/test_multiprocess.py b/tests/tests_app/runners/test_multiprocess.py index 8aa532d26f850..42615a1456b08 100644 --- a/tests/tests_app/runners/test_multiprocess.py +++ b/tests/tests_app/runners/test_multiprocess.py @@ -50,7 +50,7 @@ def run(self): @pytest.mark.skip(reason="hanging with timeout") # fixme @pytest.mark.parametrize( - "cloudspace_host, port, expected_host, expected_target", + ("cloudspace_host", "port", "expected_host", "expected_target"), [ (None, 7000, "localhost", "http://localhost:7000"), ("test.lightning.ai", 7000, "0.0.0.0", "https://7000-test.lightning.ai"), # noqa: S104 @@ -110,7 +110,7 @@ def test_multiprocess_runtime_sets_context(): @pytest.mark.parametrize( - "env,expected_url", + ("env", "expected_url"), [ ({}, "http://127.0.0.1:7501/view"), ({"APP_SERVER_HOST": "http://test"}, "http://test"), diff --git a/tests/tests_app/storage/test_path.py b/tests/tests_app/storage/test_path.py index 6a452efce8163..423a4e7117e3e 100644 --- a/tests/tests_app/storage/test_path.py +++ b/tests/tests_app/storage/test_path.py @@ -707,15 +707,15 @@ def test_filesystem(monkeypatch): class TestSharedStoragePath(TestCase): @mock.patch.dict(os.environ, {"LIGHTNING_STORAGE_PATH": "test-bucket/lightningapps/test-project/test-app"}) def test_shared_storage_path_storage_path_set(self): - self.assertEqual(pathlib.Path("test-bucket/lightningapps/test-project/test-app"), _shared_storage_path()) + assert pathlib.Path("test-bucket/lightningapps/test-project/test-app") == _shared_storage_path() @mock.patch.dict(os.environ, {"LIGHTNING_CLOUD_APP_ID": "test-app", "LIGHTNING_BUCKET_NAME": "test-bucket"}) def test_shared_storage_path_bucket_and_app_id_set(self): - self.assertEqual(pathlib.Path("test-bucket/lightningapps/test-app"), _shared_storage_path()) + assert pathlib.Path("test-bucket/lightningapps/test-app") == _shared_storage_path() @mock.patch.dict(os.environ, {"SHARED_MOUNT_DIRECTORY": "test-app/.shared"}) def test_shared_storage_path_mount_directory_set(self): - self.assertTrue(_shared_storage_path().match("*/test-app/.shared")) + assert _shared_storage_path().match("*/test-app/.shared") def test_shared_storage_path_no_envvars_set(self): - self.assertTrue(_shared_storage_path().match("*/.shared")) + assert _shared_storage_path().match("*/.shared") diff --git a/tests/tests_app/utilities/test_app_commands.py b/tests/tests_app/utilities/test_app_commands.py index 8b24e2f9c0ce3..deb37d3cc0ad0 100644 --- a/tests/tests_app/utilities/test_app_commands.py +++ b/tests/tests_app/utilities/test_app_commands.py @@ -8,7 +8,7 @@ @pytest.mark.parametrize( - "filename,expected_commands,expected_line_numbers", + ("filename", "expected_commands", "expected_line_numbers"), [ ("single_command.txt", ['echo "foo"'], [1]), ("multiple_commands.txt", ['echo "foo"', 'echo "bar"'], [1, 2]), diff --git a/tests/tests_app/utilities/test_app_helpers.py b/tests/tests_app/utilities/test_app_helpers.py index 0f8155dacfc6a..e5dbf2be6c8a8 100644 --- a/tests/tests_app/utilities/test_app_helpers.py +++ b/tests/tests_app/utilities/test_app_helpers.py @@ -188,7 +188,7 @@ def __init__(self, work): @pytest.mark.parametrize( - "flow,expected", + ("flow", "expected"), [ (Flow, True), (FlowWithURLLayout, False), diff --git a/tests/tests_app/utilities/test_auth.py b/tests/tests_app/utilities/test_auth.py index 26e1e8da0b9e3..785ce4802c181 100644 --- a/tests/tests_app/utilities/test_auth.py +++ b/tests/tests_app/utilities/test_auth.py @@ -6,7 +6,7 @@ @pytest.mark.parametrize( - "credential_string, expected_parsed, exception_message", + ("credential_string", "expected_parsed", "exception_message"), [ ("", None, "Credential string must follow the format username:password; the provided one ('') does not."), (":", None, "Username cannot be empty."), diff --git a/tests/tests_app/utilities/test_cli_helpers.py b/tests/tests_app/utilities/test_cli_helpers.py index e82a6e1acf668..cbcf34c180913 100644 --- a/tests/tests_app/utilities/test_cli_helpers.py +++ b/tests/tests_app/utilities/test_cli_helpers.py @@ -73,7 +73,7 @@ def test_arrow_time_callback(): @pytest.mark.parametrize( - "response, current_version, newer_version", + ("response", "current_version", "newer_version"), [ ( { diff --git a/tests/tests_app/utilities/test_exceptions.py b/tests/tests_app/utilities/test_exceptions.py index 9e712f5b08cfb..bcdd26b453d4f 100644 --- a/tests/tests_app/utilities/test_exceptions.py +++ b/tests/tests_app/utilities/test_exceptions.py @@ -10,7 +10,7 @@ from lightning.app.utilities.exceptions import _ApiExceptionHandler -@fixture +@fixture() def mock_api_handled_group(): @group(cls=_ApiExceptionHandler) def g(): @@ -19,7 +19,7 @@ def g(): return g -@fixture +@fixture() def mock_subcommand(mock_api_handled_group): @mock_api_handled_group.command() def cmd(): @@ -28,7 +28,7 @@ def cmd(): return cmd -@fixture +@fixture() def api_error_msg(): return "This is an internal error message" diff --git a/tests/tests_app/utilities/test_layout.py b/tests/tests_app/utilities/test_layout.py index 7acd8702eb600..ff86325a6e6b1 100644 --- a/tests/tests_app/utilities/test_layout.py +++ b/tests/tests_app/utilities/test_layout.py @@ -58,7 +58,7 @@ def configure_layout(self): @pytest.mark.parametrize( - "flow,expected_layout,expected_frontends", + ("flow", "expected_layout", "expected_frontends"), [ (FlowWithFrontend, {}, [("root", StaticWebFrontend)]), (FlowWithWorkWithFrontend, {}, [("root", StaticWebFrontend)]), @@ -122,7 +122,7 @@ def configure_layout(self): @pytest.mark.parametrize( - "flow,error_type,match", + ("flow", "error_type", "match"), [ (FlowWithBadLayout, TypeError, "is an unsupported layout format"), (FlowWithBadLayoutDict, ValueError, "missing a key 'content'."), diff --git a/tests/tests_app/utilities/test_log_helpers.py b/tests/tests_app/utilities/test_log_helpers.py index 19fc88d7aa59d..70e070c87d294 100644 --- a/tests/tests_app/utilities/test_log_helpers.py +++ b/tests/tests_app/utilities/test_log_helpers.py @@ -9,15 +9,15 @@ def test_known_error(self): with self.assertLogs("lightning.app.utilities.log_helpers") as captured: _error_callback(websocket, ValueError()) # check that there is only one log message - self.assertEqual(len(captured.records), 1) + assert len(captured.records) == 1 # and it contains the error message expected - self.assertIn("Error while reading logs (Malformed date format)", captured.records[0].getMessage()) + assert "Error while reading logs (Malformed date format)" in captured.records[0].getMessage() def test_unknown_error(self): websocket = mock.Mock() with self.assertLogs("lightning.app.utilities.log_helpers") as captured: _error_callback(websocket, IOError()) # check that there is only one log message - self.assertEqual(len(captured.records), 1) + assert len(captured.records) == 1 # and it contains the error message expected - self.assertIn("Error while reading logs (Unknown)", captured.records[0].getMessage()) + assert "Error while reading logs (Unknown)" in captured.records[0].getMessage() diff --git a/tests/tests_app/utilities/test_proxies.py b/tests/tests_app/utilities/test_proxies.py index 6f2c6f63f548e..a4661e2736aaa 100644 --- a/tests/tests_app/utilities/test_proxies.py +++ b/tests/tests_app/utilities/test_proxies.py @@ -67,7 +67,7 @@ def proxy_setattr(): @pytest.mark.parametrize( - ["parallel", "cache_calls"], + ("parallel", "cache_calls"), [ (True, True), (True, False), @@ -361,7 +361,7 @@ def run(self, *args, **kwargs): @pytest.mark.parametrize( - "origin,exists_remote,expected_get", + ("origin", "exists_remote", "expected_get"), [ (None, False, False), ("root.work", True, False), @@ -641,7 +641,7 @@ def test_state_observer(): @pytest.mark.parametrize( - "patch_constants, environment, expected_ip_addr", + ("patch_constants", "environment", "expected_ip_addr"), [ ({}, {}, "127.0.0.1"), ({"LIGHTNING_CLOUDSPACE_HOST": "any"}, {}, "0.0.0.0"), # noqa: S104 diff --git a/tests/tests_app/utilities/test_secrets.py b/tests/tests_app/utilities/test_secrets.py index f64ef45aa6d31..8305841557175 100644 --- a/tests/tests_app/utilities/test_secrets.py +++ b/tests/tests_app/utilities/test_secrets.py @@ -10,7 +10,7 @@ @pytest.mark.parametrize( - "secret_names, secrets, expected, expected_exception", + ("secret_names", "secrets", "expected", "expected_exception"), [ ([], [], {}, False), ( diff --git a/tests/tests_app/utilities/test_state.py b/tests/tests_app/utilities/test_state.py index 4cb9f20d3fc6b..9ec4b3a0fb3bc 100644 --- a/tests/tests_app/utilities/test_state.py +++ b/tests/tests_app/utilities/test_state.py @@ -24,7 +24,7 @@ def test_app_state_not_connected(_): @pytest.mark.parametrize( - "my_affiliation,global_affiliation,expected", + ("my_affiliation", "global_affiliation", "expected"), [ (None, (), ()), ((), (), ()), diff --git a/tests/tests_app/utilities/test_tree.py b/tests/tests_app/utilities/test_tree.py index f3333d6b66a74..e62564771eb58 100644 --- a/tests/tests_app/utilities/test_tree.py +++ b/tests/tests_app/utilities/test_tree.py @@ -36,7 +36,7 @@ def __init__(self): @pytest.mark.parametrize( - "input_tree, types,expected_sequence", + ("input_tree", "types", "expected_sequence"), [ (LeafFlow(), (LightningFlow,), ["root"]), (LeafWork(), (LightningFlow,), []), diff --git a/tests/tests_cloud/conftest.py b/tests/tests_cloud/conftest.py index 673d2bccd7848..7d587bceafcef 100644 --- a/tests/tests_cloud/conftest.py +++ b/tests/tests_cloud/conftest.py @@ -33,7 +33,7 @@ def reload_recursive_ex(module): return reload_recursive_ex(package) -@pytest.fixture(scope="function", autouse=True) +@pytest.fixture(autouse=True) def lit_home(monkeypatch): with tempfile.TemporaryDirectory() as tmp_dirname: monkeypatch.setattr(Path, "home", lambda: tmp_dirname) diff --git a/tests/tests_fabric/accelerators/test_cpu.py b/tests/tests_fabric/accelerators/test_cpu.py index b51fb6189c069..1c46790548779 100644 --- a/tests/tests_fabric/accelerators/test_cpu.py +++ b/tests/tests_fabric/accelerators/test_cpu.py @@ -32,7 +32,7 @@ def test_init_device_with_wrong_device_type(): @pytest.mark.parametrize( - "devices,expected", + ("devices", "expected"), [ (1, [torch.device("cpu")]), (2, [torch.device("cpu")] * 2), diff --git a/tests/tests_fabric/accelerators/test_cuda.py b/tests/tests_fabric/accelerators/test_cuda.py index f623125c4f4d3..06b23923871c0 100644 --- a/tests/tests_fabric/accelerators/test_cuda.py +++ b/tests/tests_fabric/accelerators/test_cuda.py @@ -48,7 +48,7 @@ def test_init_device_with_wrong_device_type(): @pytest.mark.parametrize( - "devices,expected", + ("devices", "expected"), [ ([], []), ([1], [torch.device("cuda", 1)]), diff --git a/tests/tests_fabric/accelerators/test_mps.py b/tests/tests_fabric/accelerators/test_mps.py index 913ff085781f5..03def205a82f7 100644 --- a/tests/tests_fabric/accelerators/test_mps.py +++ b/tests/tests_fabric/accelerators/test_mps.py @@ -37,7 +37,7 @@ def test_init_device_with_wrong_device_type(): @RunIf(mps=True) @pytest.mark.parametrize( - "devices,expected", + ("devices", "expected"), [ (1, [torch.device(_MAYBE_MPS, 0)]), ([0], [torch.device(_MAYBE_MPS, 0)]), diff --git a/tests/tests_fabric/conftest.py b/tests/tests_fabric/conftest.py index 1f32b51c40563..d089e87dad369 100644 --- a/tests/tests_fabric/conftest.py +++ b/tests/tests_fabric/conftest.py @@ -22,7 +22,7 @@ import lightning.fabric -@pytest.fixture(scope="function", autouse=True) +@pytest.fixture(autouse=True) def preserve_global_rank_variable(): """Ensures that the rank_zero_only.rank global variable gets reset in each test.""" from lightning.fabric.utilities.rank_zero import rank_zero_only @@ -33,7 +33,7 @@ def preserve_global_rank_variable(): setattr(rank_zero_only, "rank", rank) -@pytest.fixture(scope="function", autouse=True) +@pytest.fixture(autouse=True) def restore_env_variables(): """Ensures that environment variables set during the test do not leak out.""" env_backup = os.environ.copy() @@ -62,7 +62,7 @@ def restore_env_variables(): assert not leaked_vars, f"test is leaking environment variable(s): {set(leaked_vars)}" -@pytest.fixture(scope="function", autouse=True) +@pytest.fixture(autouse=True) def teardown_process_group(): """Ensures that the distributed process group gets closed before the next test runs.""" yield @@ -70,7 +70,7 @@ def teardown_process_group(): torch.distributed.destroy_process_group() -@pytest.fixture +@pytest.fixture() def reset_deterministic_algorithm(): """Ensures that torch determinism settings are reset before the next test runs.""" yield @@ -78,7 +78,7 @@ def reset_deterministic_algorithm(): torch.use_deterministic_algorithms(False) -@pytest.fixture +@pytest.fixture() def reset_cudnn_benchmark(): """Ensures that the `torch.backends.cudnn.benchmark` setting gets reset before the next test runs.""" yield @@ -94,7 +94,7 @@ def mock_xla_available(monkeypatch: pytest.MonkeyPatch, value: bool = True) -> N monkeypatch.setattr(lightning.fabric.strategies.launchers.xla, "_XLA_AVAILABLE", value) -@pytest.fixture(scope="function") +@pytest.fixture() def xla_available(monkeypatch: pytest.MonkeyPatch) -> None: mock_xla_available(monkeypatch) @@ -108,12 +108,12 @@ def mock_tpu_available(monkeypatch: pytest.MonkeyPatch, value: bool = True) -> N monkeypatch.setitem(sys.modules, "torch_xla.experimental", Mock()) -@pytest.fixture(scope="function") +@pytest.fixture() def tpu_available(monkeypatch: pytest.MonkeyPatch) -> None: mock_tpu_available(monkeypatch) -@pytest.fixture +@pytest.fixture() def caplog(caplog): """Workaround for https://github.com/pytest-dev/pytest/issues/3697. diff --git a/tests/tests_fabric/parity/test_parity_simple.py b/tests/tests_fabric/parity/test_parity_simple.py index 33ca3f7c71c78..3da685c781a96 100644 --- a/tests/tests_fabric/parity/test_parity_simple.py +++ b/tests/tests_fabric/parity/test_parity_simple.py @@ -115,7 +115,7 @@ def train_fabric(fabric): @pytest.mark.flaky(reruns=3) @pytest.mark.usefixtures("reset_deterministic_algorithm", "reset_cudnn_benchmark") @pytest.mark.parametrize( - "precision, accelerator", + ("precision", "accelerator"), [ (32, "cpu"), pytest.param(32, "cuda", marks=RunIf(min_cuda_gpus=1)), diff --git a/tests/tests_fabric/plugins/collectives/test_torch_collective.py b/tests/tests_fabric/plugins/collectives/test_torch_collective.py index cedf6fb3df882..620978a4f1849 100644 --- a/tests/tests_fabric/plugins/collectives/test_torch_collective.py +++ b/tests/tests_fabric/plugins/collectives/test_torch_collective.py @@ -48,7 +48,7 @@ def check_destroy_group(): @pytest.mark.parametrize( - ["fn_name", "kwargs", "return_key"], + ("fn_name", "kwargs", "return_key"), [ ("send", {"tensor": PASSED_TENSOR, "dst": 0, "tag": 0}, None), ("recv", {"tensor": PASSED_TENSOR, "src": 0, "tag": 0}, "tensor"), diff --git a/tests/tests_fabric/plugins/environments/test_lightning.py b/tests/tests_fabric/plugins/environments/test_lightning.py index fc69730b35b39..cc0179af4c3f5 100644 --- a/tests/tests_fabric/plugins/environments/test_lightning.py +++ b/tests/tests_fabric/plugins/environments/test_lightning.py @@ -48,7 +48,7 @@ def test_attributes_from_environment_variables(): @pytest.mark.parametrize( - "environ, creates_processes_externally", [({}, False), ({"LOCAL_RANK": "2"}, True), ({"NODE_RANK": "1"}, False)] + ("environ", "creates_processes_externally"), [({}, False), ({"LOCAL_RANK": "2"}, True), ({"NODE_RANK": "1"}, False)] ) def test_manual_user_launch(environ, creates_processes_externally): """Test that the environment switches to manual user mode when LOCAL_RANK env variable detected.""" diff --git a/tests/tests_fabric/plugins/environments/test_slurm.py b/tests/tests_fabric/plugins/environments/test_slurm.py index b3ee02845d8dd..80280a9c691ac 100644 --- a/tests/tests_fabric/plugins/environments/test_slurm.py +++ b/tests/tests_fabric/plugins/environments/test_slurm.py @@ -86,7 +86,7 @@ def test_attributes_from_environment_variables(caplog): @pytest.mark.parametrize( - "slurm_node_list,expected", + ("slurm_node_list", "expected"), [ ("127.0.0.1", "127.0.0.1"), ("alpha", "alpha"), diff --git a/tests/tests_fabric/plugins/precision/test_amp_integration.py b/tests/tests_fabric/plugins/precision/test_amp_integration.py index d3fb995348fb5..ad3e22b9e0e7d 100644 --- a/tests/tests_fabric/plugins/precision/test_amp_integration.py +++ b/tests/tests_fabric/plugins/precision/test_amp_integration.py @@ -58,7 +58,7 @@ def after_backward(self, model, optimizer): @pytest.mark.parametrize( - "accelerator, precision, expected_dtype", + ("accelerator", "precision", "expected_dtype"), [ ("cpu", "16-mixed", torch.bfloat16), ("cpu", "bf16-mixed", torch.bfloat16), diff --git a/tests/tests_fabric/plugins/precision/test_fsdp.py b/tests/tests_fabric/plugins/precision/test_fsdp.py index 202a2a70d8b77..16fcb8a8e7229 100644 --- a/tests/tests_fabric/plugins/precision/test_fsdp.py +++ b/tests/tests_fabric/plugins/precision/test_fsdp.py @@ -27,7 +27,7 @@ def test_fsdp_precision_support(*_): @RunIf(min_torch="1.12", min_cuda_gpus=1) -@pytest.mark.parametrize("precision, expected", [("16-mixed", torch.float16), ("bf16-mixed", torch.bfloat16)]) +@pytest.mark.parametrize(("precision", "expected"), [("16-mixed", torch.float16), ("bf16-mixed", torch.bfloat16)]) def test_fsdp_precision_config(precision, expected): plugin = FSDPPrecision(precision=precision, device="cuda") config = plugin.mixed_precision_config diff --git a/tests/tests_fabric/plugins/precision/test_half.py b/tests/tests_fabric/plugins/precision/test_half.py index c39d6f8a951a7..00d23df4ae5b6 100644 --- a/tests/tests_fabric/plugins/precision/test_half.py +++ b/tests/tests_fabric/plugins/precision/test_half.py @@ -18,7 +18,7 @@ @pytest.mark.parametrize( - "precision, expected_dtype", + ("precision", "expected_dtype"), [ ("bf16-true", torch.bfloat16), ("16-true", torch.half), @@ -31,7 +31,7 @@ def test_selected_dtype(precision, expected_dtype): @pytest.mark.parametrize( - "precision, expected_dtype", + ("precision", "expected_dtype"), [ ("bf16-true", torch.bfloat16), ("16-true", torch.half), @@ -46,7 +46,7 @@ def test_module_init_context(precision, expected_dtype): @pytest.mark.parametrize( - "precision, expected_dtype", + ("precision", "expected_dtype"), [ ("bf16-true", torch.bfloat16), ("16-true", torch.half), @@ -61,7 +61,7 @@ def test_forward_context(precision, expected_dtype): @pytest.mark.parametrize( - "precision, expected_dtype", + ("precision", "expected_dtype"), [ ("bf16-true", torch.bfloat16), ("16-true", torch.half), diff --git a/tests/tests_fabric/strategies/test_ddp.py b/tests/tests_fabric/strategies/test_ddp.py index 8074a07da08f2..42fd89ee9d2cf 100644 --- a/tests/tests_fabric/strategies/test_ddp.py +++ b/tests/tests_fabric/strategies/test_ddp.py @@ -30,7 +30,7 @@ @pytest.mark.parametrize( - ["process_group_backend", "device_str", "expected_process_group_backend"], + ("process_group_backend", "device_str", "expected_process_group_backend"), [ pytest.param("foo", "cpu", "foo"), pytest.param("foo", "cuda:0", "foo"), @@ -108,7 +108,7 @@ def __instancecheck__(self, instance): @pytest.mark.parametrize( - "clip_type,accelerator,precision", + ("clip_type", "accelerator", "precision"), [ ("norm", "cpu", "32-true"), ("val", "cpu", "32-true"), @@ -131,7 +131,7 @@ def test_ddp_grad_clipping(clip_type, accelerator, precision): @RunIf(min_cuda_gpus=2) @pytest.mark.parametrize( - "precision,expected_dtype", + ("precision", "expected_dtype"), [ (Precision(), torch.float32), (HalfPrecision("16-true"), torch.float16), diff --git a/tests/tests_fabric/strategies/test_deepspeed.py b/tests/tests_fabric/strategies/test_deepspeed.py index 8e1225bf799b9..e007bc22b71a1 100644 --- a/tests/tests_fabric/strategies/test_deepspeed.py +++ b/tests/tests_fabric/strategies/test_deepspeed.py @@ -26,7 +26,7 @@ from tests_fabric.helpers.runif import RunIf -@pytest.fixture +@pytest.fixture() def deepspeed_config(): return { "optimizer": {"type": "SGD", "params": {"lr": 3e-5}}, @@ -37,7 +37,7 @@ def deepspeed_config(): } -@pytest.fixture +@pytest.fixture() def deepspeed_zero_config(deepspeed_config): return {**deepspeed_config, "zero_allow_untested_optimizer": True, "zero_optimization": {"stage": 2}} diff --git a/tests/tests_fabric/strategies/test_deepspeed_integration.py b/tests/tests_fabric/strategies/test_deepspeed_integration.py index b988338327793..92d7e1e1a1ec9 100644 --- a/tests/tests_fabric/strategies/test_deepspeed_integration.py +++ b/tests/tests_fabric/strategies/test_deepspeed_integration.py @@ -107,7 +107,7 @@ def run(self): @RunIf(min_cuda_gpus=1, deepspeed=True) @pytest.mark.parametrize( - ["dataset_cls", "logging_batch_size_per_gpu", "expected_batch_size"], + ("dataset_cls", "logging_batch_size_per_gpu", "expected_batch_size"), [ (RandomDataset, None, 1), (RandomDataset, 10, 10), diff --git a/tests/tests_fabric/strategies/test_fsdp_integration.py b/tests/tests_fabric/strategies/test_fsdp_integration.py index af65ba4582ba1..76d01d007b471 100644 --- a/tests/tests_fabric/strategies/test_fsdp_integration.py +++ b/tests/tests_fabric/strategies/test_fsdp_integration.py @@ -195,7 +195,7 @@ def test_compile(compile_after_setup): @RunIf(min_cuda_gpus=2, skip_windows=True, standalone=True) @pytest.mark.parametrize( - "precision,expected_dtype", + ("precision", "expected_dtype"), [ ("32-true", torch.float32), ("16-true", torch.float16), diff --git a/tests/tests_fabric/strategies/test_single_device.py b/tests/tests_fabric/strategies/test_single_device.py index 05c11f703d301..f4232476d2ee4 100644 --- a/tests/tests_fabric/strategies/test_single_device.py +++ b/tests/tests_fabric/strategies/test_single_device.py @@ -160,7 +160,7 @@ def test_single_device_grad_clipping(clip_type, precision): ], ) @pytest.mark.parametrize( - "precision,dtype", + ("precision", "dtype"), [ (Precision(), torch.float32), (HalfPrecision("16-true"), torch.float16), diff --git a/tests/tests_fabric/test_cli.py b/tests/tests_fabric/test_cli.py index dc7fa487534df..164882d013bf1 100644 --- a/tests/tests_fabric/test_cli.py +++ b/tests/tests_fabric/test_cli.py @@ -25,7 +25,7 @@ from tests_fabric.helpers.runif import RunIf -@pytest.fixture +@pytest.fixture() def fake_script(tmp_path): script = tmp_path / "script.py" script.touch() @@ -150,7 +150,7 @@ def test_cli_torchrun_defaults(monkeypatch, fake_script): @pytest.mark.parametrize( - "devices,expected", + ("devices", "expected"), [ ("1", 1), ("2", 2), diff --git a/tests/tests_fabric/test_connector.py b/tests/tests_fabric/test_connector.py index d6ef1c32a8d95..d3a3be1ac6c33 100644 --- a/tests/tests_fabric/test_connector.py +++ b/tests/tests_fabric/test_connector.py @@ -61,7 +61,7 @@ def __instancecheck__(self, instance): @pytest.mark.parametrize( - ["accelerator", "devices"], [("tpu", "auto"), ("tpu", 1), ("tpu", [1]), ("tpu", 8), ("auto", 1), ("auto", 8)] + ("accelerator", "devices"), [("tpu", "auto"), ("tpu", 1), ("tpu", [1]), ("tpu", 8), ("auto", 1), ("auto", 8)] ) @RunIf(min_python="3.9") # mocking issue def test_accelerator_choice_tpu(accelerator, devices, tpu_available, monkeypatch): @@ -202,7 +202,7 @@ class Strat(DDPStrategy): @pytest.mark.parametrize( - "env_vars,expected_environment", + ("env_vars", "expected_environment"), [ ( { @@ -270,7 +270,7 @@ def test_interactive_compatible_strategy_ddp_fork(monkeypatch): @RunIf(mps=True) @pytest.mark.parametrize( - ["strategy", "strategy_class"], + ("strategy", "strategy_class"), ( ("ddp", DDPStrategy), ("dp", DataParallelStrategy), @@ -288,7 +288,7 @@ def test_invalid_ddp_strategy_with_mps(accelerator, strategy, strategy_class): @RunIf(mps=False) @pytest.mark.parametrize( - ["strategy", "strategy_class"], + ("strategy", "strategy_class"), [ ("ddp", DDPStrategy), ("ddp_spawn", DDPStrategy), @@ -340,7 +340,7 @@ def test_accelerator_gpu(): assert isinstance(connector.accelerator, CUDAAccelerator) -@pytest.mark.parametrize(["devices", "strategy_class"], [(1, SingleDeviceStrategy), (5, DDPStrategy)]) +@pytest.mark.parametrize(("devices", "strategy_class"), [(1, SingleDeviceStrategy), (5, DDPStrategy)]) def test_accelerator_cpu_with_devices(devices, strategy_class): connector = _Connector(accelerator="cpu", devices=devices) assert connector._parallel_devices == [torch.device("cpu")] * devices @@ -350,7 +350,7 @@ def test_accelerator_cpu_with_devices(devices, strategy_class): @RunIf(min_cuda_gpus=2) @pytest.mark.parametrize( - ["devices", "strategy_class"], [(1, SingleDeviceStrategy), ([1], SingleDeviceStrategy), (2, DDPStrategy)] + ("devices", "strategy_class"), [(1, SingleDeviceStrategy), ([1], SingleDeviceStrategy), (2, DDPStrategy)] ) def test_accelerator_gpu_with_devices(devices, strategy_class): connector = _Connector(accelerator="gpu", devices=devices) @@ -390,7 +390,7 @@ def test_invalid_strategy_choice(invalid_strategy): @pytest.mark.parametrize( - ["strategy", "strategy_class"], + ("strategy", "strategy_class"), [ ("ddp_spawn", DDPStrategy), ("ddp", DDPStrategy), @@ -403,7 +403,7 @@ def test_strategy_choice_cpu_str(strategy, strategy_class): @RunIf(min_cuda_gpus=2) @pytest.mark.parametrize( - ["strategy", "strategy_class"], + ("strategy", "strategy_class"), [ ("ddp_spawn", DDPStrategy), ("ddp", DDPStrategy), @@ -436,7 +436,7 @@ def test_validate_precision_type(precision): @pytest.mark.parametrize( - "precision,expected_precision,should_warn", + ("precision", "expected_precision", "should_warn"), [ (16, "16-mixed", True), ("16", "16-mixed", True), @@ -529,7 +529,9 @@ def test_strategy_choice_ddp_spawn(*_): @mock.patch("lightning.fabric.accelerators.cuda.num_cuda_devices", return_value=2) -@pytest.mark.parametrize("job_name,expected_env", [("some_name", SLURMEnvironment), ("bash", LightningEnvironment)]) +@pytest.mark.parametrize( + ("job_name", "expected_env"), [("some_name", SLURMEnvironment), ("bash", LightningEnvironment)] +) @pytest.mark.parametrize("strategy", ["auto", "ddp", DDPStrategy]) def test_strategy_choice_ddp_slurm(_, strategy, job_name, expected_env): if strategy and not isinstance(strategy, str): @@ -687,7 +689,7 @@ def test_devices_auto_choice_mps(): @pytest.mark.parametrize( - ["parallel_devices", "accelerator"], + ("parallel_devices", "accelerator"), [([torch.device("cpu")], "cuda"), ([torch.device("cuda", i) for i in range(8)], "tpu")], ) def test_parallel_devices_in_strategy_conflict_with_accelerator(parallel_devices, accelerator): @@ -696,7 +698,7 @@ def test_parallel_devices_in_strategy_conflict_with_accelerator(parallel_devices @pytest.mark.parametrize( - ["plugins", "expected"], + ("plugins", "expected"), [ ([LightningEnvironment(), SLURMEnvironment()], "ClusterEnvironment"), ([TorchCheckpointIO(), TorchCheckpointIO()], "CheckpointIO"), @@ -719,7 +721,7 @@ def test_passing_zero_and_empty_list_to_devices_flag(accelerator, devices): @pytest.mark.parametrize( - "expected_accelerator_flag,expected_accelerator_class", + ("expected_accelerator_flag", "expected_accelerator_class"), [ pytest.param("cuda", CUDAAccelerator, marks=RunIf(min_cuda_gpus=1)), pytest.param("mps", MPSAccelerator, marks=RunIf(mps=True)), @@ -768,7 +770,7 @@ def test_ddp_fork_on_unsupported_platform(_, __, strategy): @pytest.mark.parametrize( - "precision_str,precision_cls", + ("precision_str", "precision_cls"), [ ("64-true", DoublePrecision), ("32-true", Precision), @@ -796,9 +798,9 @@ class MyAMP(MixedPrecision): @RunIf(mps=False) -@pytest.mark.parametrize("strategy,devices", [("ddp", 2), ("ddp_spawn", 2)]) +@pytest.mark.parametrize(("strategy", "devices"), [("ddp", 2), ("ddp_spawn", 2)]) @pytest.mark.parametrize( - "is_custom_plugin,plugin_cls", + ("is_custom_plugin", "plugin_cls"), [(False, MixedPrecision), (True, MyAMP)], ) def test_precision_selection_amp_ddp(strategy, devices, is_custom_plugin, plugin_cls): @@ -815,7 +817,7 @@ def test_precision_selection_amp_ddp(strategy, devices, is_custom_plugin, plugin assert isinstance(connector.precision, plugin_cls) -@pytest.mark.parametrize(["strategy", "strategy_cls"], [("DDP", DDPStrategy), ("Ddp", DDPStrategy)]) +@pytest.mark.parametrize(("strategy", "strategy_cls"), [("DDP", DDPStrategy), ("Ddp", DDPStrategy)]) @mock.patch("lightning.fabric.accelerators.mps.MPSAccelerator.is_available", return_value=False) def test_strategy_str_passed_being_case_insensitive(_, strategy, strategy_cls): connector = _Connector(strategy=strategy) @@ -835,7 +837,7 @@ def test_precision_from_environment(_, precision): @pytest.mark.parametrize( - "accelerator, strategy, expected_accelerator, expected_strategy", + ("accelerator", "strategy", "expected_accelerator", "expected_strategy"), [ (None, None, CPUAccelerator, SingleDeviceStrategy), ("cpu", None, CPUAccelerator, SingleDeviceStrategy), diff --git a/tests/tests_fabric/test_fabric.py b/tests/tests_fabric/test_fabric.py index 076f6515acf2b..ce887fbbd0dda 100644 --- a/tests/tests_fabric/test_fabric.py +++ b/tests/tests_fabric/test_fabric.py @@ -104,7 +104,7 @@ def test_setup_compiled_module(setup_method): @pytest.mark.parametrize( - "accelerator, initial_device, target_device", + ("accelerator", "initial_device", "target_device"), [ ("cpu", "cpu", "cpu"), pytest.param("cpu", "cuda:0", "cpu", marks=RunIf(min_cuda_gpus=1)), @@ -513,7 +513,7 @@ def test_setup_dataloaders_replace_standard_sampler(shuffle, strategy): @pytest.mark.parametrize( - "accelerator, expected", + ("accelerator", "expected"), [ ("cpu", "cpu"), pytest.param("cuda", "cuda:0", marks=RunIf(min_cuda_gpus=1)), @@ -979,7 +979,7 @@ def test_all_reduce(): fabric._strategy.all_reduce.assert_has_calls([call(torch.tensor(4), **defaults), call(torch.tensor(5), **defaults)]) -@pytest.mark.parametrize("clip_val,max_norm", [(1e-3, None), (None, 1)]) +@pytest.mark.parametrize(("clip_val", "max_norm"), [(1e-3, None), (None, 1)]) def test_grad_clipping(clip_val, max_norm): fabric = Fabric(devices=1) diff --git a/tests/tests_fabric/test_wrappers.py b/tests/tests_fabric/test_wrappers.py index 72ce305506304..e96a506483679 100644 --- a/tests/tests_fabric/test_wrappers.py +++ b/tests/tests_fabric/test_wrappers.py @@ -126,7 +126,7 @@ def __init__(self): @pytest.mark.parametrize( - "precision, input_type, expected_type, accelerator, device_str", + ("precision", "input_type", "expected_type", "accelerator", "device_str"), [ pytest.param(32, torch.float16, torch.float16, "gpu", "cuda:0", marks=RunIf(min_cuda_gpus=1)), pytest.param(32, torch.float32, torch.float32, "gpu", "cuda:0", marks=RunIf(min_cuda_gpus=1)), @@ -227,7 +227,7 @@ def test_fabric_dataloader_iterator(): @pytest.mark.parametrize( - "src_device_str, dest_device_str", + ("src_device_str", "dest_device_str"), [ ("cpu", "cpu"), pytest.param("cpu", "cuda:0", marks=RunIf(min_cuda_gpus=1)), diff --git a/tests/tests_fabric/utilities/test_apply_func.py b/tests/tests_fabric/utilities/test_apply_func.py index f105ac8cc8c2c..d36fcc74757af 100644 --- a/tests/tests_fabric/utilities/test_apply_func.py +++ b/tests/tests_fabric/utilities/test_apply_func.py @@ -44,12 +44,15 @@ def test_convert_tensors_to_scalars(): result = convert_tensors_to_scalars({"tensor": torch.tensor(2.0)}) # note: `==` comparison as above is not sufficient, since `torch.tensor(x) == x` evaluates to truth - assert not isinstance(result["tensor"], Tensor) and result["tensor"] == 2.0 + assert not isinstance(result["tensor"], Tensor) + assert result["tensor"] == 2.0 data = {"tensor": torch.tensor([2.0])} result = convert_tensors_to_scalars(data) - assert not isinstance(result["tensor"], Tensor) and result["tensor"] == 2.0 - assert isinstance(data["tensor"], Tensor) and data["tensor"] == 2.0 # does not modify the input data + assert not isinstance(result["tensor"], Tensor) + assert result["tensor"] == 2.0 + assert isinstance(data["tensor"], Tensor) + assert data["tensor"] == 2.0 with pytest.raises(ValueError, match="does not contain a single element"): convert_tensors_to_scalars({"tensor": torch.tensor([1, 2, 3])}) diff --git a/tests/tests_fabric/utilities/test_data.py b/tests/tests_fabric/utilities/test_data.py index 542433e3e74cc..533e52c299a52 100644 --- a/tests/tests_fabric/utilities/test_data.py +++ b/tests/tests_fabric/utilities/test_data.py @@ -138,7 +138,7 @@ def __init__(self, dataset, **kwargs): @pytest.mark.parametrize( - ["cls", "args", "kwargs", "arg_names", "dataset", "checked_values"], + ("cls", "args", "kwargs", "arg_names", "dataset", "checked_values"), [ pytest.param( DataLoaderSubclass1, @@ -335,7 +335,7 @@ class AllDunder(Init, SetAttr, DelAttr): @pytest.mark.parametrize( - [ + ( "args", "kwargs", "default_kwargs", @@ -345,7 +345,7 @@ class AllDunder(Init, SetAttr, DelAttr): "expected_status", "expected_args", "expected_kwargs", - ], + ), [ pytest.param((), {}, {}, [], "a", 1, False, (), {}, id="empty"), pytest.param((1,), {}, {}, ["a"], "a", 2, True, (2,), {}, id="simple1"), diff --git a/tests/tests_fabric/utilities/test_device_dtype_mixin.py b/tests/tests_fabric/utilities/test_device_dtype_mixin.py index 101299068d544..bb1570eed0e20 100644 --- a/tests/tests_fabric/utilities/test_device_dtype_mixin.py +++ b/tests/tests_fabric/utilities/test_device_dtype_mixin.py @@ -23,7 +23,7 @@ def __init__(self) -> None: @pytest.mark.parametrize( - "dst_device_str,dst_type", + ("dst_device_str", "dst_type"), [ ("cpu", torch.half), ("cpu", torch.float), diff --git a/tests/tests_fabric/utilities/test_device_parser.py b/tests/tests_fabric/utilities/test_device_parser.py index 9c4f09b9f83ba..f9f9e49cf6afe 100644 --- a/tests/tests_fabric/utilities/test_device_parser.py +++ b/tests/tests_fabric/utilities/test_device_parser.py @@ -22,7 +22,7 @@ @pytest.mark.parametrize( - ["devices", "expected_root_gpu"], + ("devices", "expected_root_gpu"), [ pytest.param(None, None, id="No gpus, expect gpu root device to be None"), pytest.param([0], 0, id="Oth gpu, expect gpu root device to be 0."), @@ -36,7 +36,7 @@ def test_determine_root_gpu_device(devices, expected_root_gpu): @pytest.mark.parametrize( - ["devices", "expected_gpu_ids"], + ("devices", "expected_gpu_ids"), [ (0, None), ([], None), diff --git a/tests/tests_fabric/utilities/test_rank_zero.py b/tests/tests_fabric/utilities/test_rank_zero.py index 793588e8577c5..65b9704457501 100644 --- a/tests/tests_fabric/utilities/test_rank_zero.py +++ b/tests/tests_fabric/utilities/test_rank_zero.py @@ -8,7 +8,7 @@ @pytest.mark.parametrize( - "env_vars, expected", + ("env_vars", "expected"), [ ({"RANK": "0"}, 1), ({"SLURM_PROCID": "0"}, 1), @@ -37,7 +37,7 @@ def foo(): @pytest.mark.parametrize( - "environ,expected_rank", + ("environ", "expected_rank"), [ ({"JSM_NAMESPACE_RANK": "3"}, 3), ({"JSM_NAMESPACE_RANK": "3", "SLURM_PROCID": "2"}, 2), diff --git a/tests/tests_fabric/utilities/test_warnings.py b/tests/tests_fabric/utilities/test_warnings.py index bb4c4168df64e..a0165961cc69a 100644 --- a/tests/tests_fabric/utilities/test_warnings.py +++ b/tests/tests_fabric/utilities/test_warnings.py @@ -56,7 +56,8 @@ root_logger = logging.getLogger() lightning_logger = logging.getLogger("lightning.fabric") # should have a `StreamHandler` - assert lightning_logger.hasHandlers() and len(lightning_logger.handlers) == 1 + assert lightning_logger.hasHandlers() + assert len(lightning_logger.handlers) == 1 # set our own stream for testing handler = lightning_logger.handlers[0] assert isinstance(handler, logging.StreamHandler) diff --git a/tests/tests_pytorch/accelerators/test_mps.py b/tests/tests_pytorch/accelerators/test_mps.py index 1c61c5c9650b4..170e586254006 100644 --- a/tests/tests_pytorch/accelerators/test_mps.py +++ b/tests/tests_pytorch/accelerators/test_mps.py @@ -83,30 +83,38 @@ def test_single_gpu_batch_parse(): # batch is just a tensor batch = torch.rand(2, 3) batch = trainer.strategy.batch_to_device(batch, torch.device("mps")) - assert batch.device.index == 0 and batch.type() == "torch.mps.FloatTensor" + assert batch.device.index == 0 + assert batch.type() == "torch.mps.FloatTensor" # tensor list batch = [torch.rand(2, 3), torch.rand(2, 3)] batch = trainer.strategy.batch_to_device(batch, torch.device("mps")) - assert batch[0].device.index == 0 and batch[0].type() == "torch.mps.FloatTensor" - assert batch[1].device.index == 0 and batch[1].type() == "torch.mps.FloatTensor" + assert batch[0].device.index == 0 + assert batch[0].type() == "torch.mps.FloatTensor" + assert batch[1].device.index == 0 + assert batch[1].type() == "torch.mps.FloatTensor" # tensor list of lists batch = [[torch.rand(2, 3), torch.rand(2, 3)]] batch = trainer.strategy.batch_to_device(batch, torch.device("mps")) - assert batch[0][0].device.index == 0 and batch[0][0].type() == "torch.mps.FloatTensor" - assert batch[0][1].device.index == 0 and batch[0][1].type() == "torch.mps.FloatTensor" + assert batch[0][0].device.index == 0 + assert batch[0][0].type() == "torch.mps.FloatTensor" + assert batch[0][1].device.index == 0 + assert batch[0][1].type() == "torch.mps.FloatTensor" # tensor dict batch = [{"a": torch.rand(2, 3), "b": torch.rand(2, 3)}] batch = trainer.strategy.batch_to_device(batch, torch.device("mps")) - assert batch[0]["a"].device.index == 0 and batch[0]["a"].type() == "torch.mps.FloatTensor" - assert batch[0]["b"].device.index == 0 and batch[0]["b"].type() == "torch.mps.FloatTensor" + assert batch[0]["a"].device.index == 0 + assert batch[0]["a"].type() == "torch.mps.FloatTensor" + assert batch[0]["b"].device.index == 0 + assert batch[0]["b"].type() == "torch.mps.FloatTensor" # tuple of tensor list and list of tensor dict batch = ([torch.rand(2, 3) for _ in range(2)], [{"a": torch.rand(2, 3), "b": torch.rand(2, 3)} for _ in range(2)]) batch = trainer.strategy.batch_to_device(batch, torch.device("mps")) - assert batch[0][0].device.index == 0 and batch[0][0].type() == "torch.mps.FloatTensor" + assert batch[0][0].device.index == 0 + assert batch[0][0].type() == "torch.mps.FloatTensor" assert batch[1][0]["a"].device.index == 0 assert batch[1][0]["a"].type() == "torch.mps.FloatTensor" diff --git a/tests/tests_pytorch/accelerators/test_xla.py b/tests/tests_pytorch/accelerators/test_xla.py index 4b9747239cd5e..759a8d7500767 100644 --- a/tests/tests_pytorch/accelerators/test_xla.py +++ b/tests/tests_pytorch/accelerators/test_xla.py @@ -89,7 +89,7 @@ def test_accelerator_cpu_when_tpu_available(tpu_available): @RunIf(skip_windows=True) -@pytest.mark.parametrize(["accelerator", "devices"], [("auto", 8), ("auto", "auto"), ("tpu", "auto")]) +@pytest.mark.parametrize(("accelerator", "devices"), [("auto", 8), ("auto", "auto"), ("tpu", "auto")]) def test_accelerator_tpu(accelerator, devices, tpu_available): assert XLAAccelerator.is_available() @@ -302,7 +302,7 @@ def test_warning_if_tpus_not_used(tpu_available): @pytest.mark.parametrize( - ["devices", "expected_device_ids"], + ("devices", "expected_device_ids"), [ (1, [0]), (8, list(range(8))), diff --git a/tests/tests_pytorch/benchmarks/test_basic_parity.py b/tests/tests_pytorch/benchmarks/test_basic_parity.py index 226522d6449f0..42a097ad45aa8 100644 --- a/tests/tests_pytorch/benchmarks/test_basic_parity.py +++ b/tests/tests_pytorch/benchmarks/test_basic_parity.py @@ -48,7 +48,7 @@ def assert_parity_absolute(pl_values, pt_values, norm_by: float = 1, max_diff: f # ParityModuleMNIST runs with num_workers=1 @pytest.mark.parametrize( - "cls_model,max_diff_speed,max_diff_memory,num_epochs,num_runs", + ("cls_model", "max_diff_speed", "max_diff_memory", "num_epochs", "num_runs"), [ (ParityModuleRNN, 0.05, 0.001, 4, 3), (ParityModuleMNIST, 0.3, 0.001, 4, 3), # todo: lower this thr diff --git a/tests/tests_pytorch/callbacks/progress/test_rich_progress_bar.py b/tests/tests_pytorch/callbacks/progress/test_rich_progress_bar.py index 27480d6d71865..c372ecad2b3bc 100644 --- a/tests/tests_pytorch/callbacks/progress/test_rich_progress_bar.py +++ b/tests/tests_pytorch/callbacks/progress/test_rich_progress_bar.py @@ -212,7 +212,7 @@ def test_rich_progress_bar_refresh_rate_disabled(progress_update, tmpdir): @RunIf(rich=True) @pytest.mark.parametrize( - "refresh_rate,train_batches,val_batches,expected_call_count", + ("refresh_rate", "train_batches", "val_batches", "expected_call_count"), [ # note: there is always one extra update at the very end (+1) (3, 6, 6, 2 + 2 + 1), diff --git a/tests/tests_pytorch/callbacks/progress/test_tqdm_progress_bar.py b/tests/tests_pytorch/callbacks/progress/test_tqdm_progress_bar.py index 51f1e086877fb..54096eafb3fdc 100644 --- a/tests/tests_pytorch/callbacks/progress/test_tqdm_progress_bar.py +++ b/tests/tests_pytorch/callbacks/progress/test_tqdm_progress_bar.py @@ -335,7 +335,7 @@ def test_tqdm_progress_bar_value_on_colab(tmpdir): @pytest.mark.parametrize( - "train_batches,val_batches,refresh_rate,train_updates,val_updates", + ("train_batches", "val_batches", "refresh_rate", "train_updates", "val_updates"), [ [2, 3, 1, [0, 1, 2], [0, 1, 2, 3]], [0, 0, 3, None, None], @@ -373,7 +373,9 @@ def test_train_progress_bar_update_amount( assert progress_bar.val_progress_bar.n_values == val_updates -@pytest.mark.parametrize("test_batches,refresh_rate,updates", [(1, 3, [0, 1]), (3, 1, [0, 1, 2, 3]), (5, 3, [0, 3, 5])]) +@pytest.mark.parametrize( + ("test_batches", "refresh_rate", "updates"), [(1, 3, [0, 1]), (3, 1, [0, 1, 2, 3]), (5, 3, [0, 3, 5])] +) def test_test_progress_bar_update_amount(tmpdir, test_batches: int, refresh_rate: int, updates: list): """Test that test progress updates with the correct amount.""" model = BoringModel() @@ -415,7 +417,7 @@ def training_step(self, batch, batch_idx): @pytest.mark.parametrize( - "input_num, expected", + ("input_num", "expected"), [ [1, "1"], [1.0, "1.000"], @@ -553,7 +555,7 @@ def test_tqdm_progress_bar_can_be_pickled(): @pytest.mark.parametrize( - ["val_check_interval", "train_progress_bar_updates", "val_progress_bar_updates"], + ("val_check_interval", "train_progress_bar_updates", "val_progress_bar_updates"), [(4, [0, 3, 6, 7], [0, 3, 6, 7]), (0.5, [0, 3, 6, 7], [0, 3, 6, 7])], ) def test_progress_bar_max_val_check_interval( diff --git a/tests/tests_pytorch/callbacks/test_early_stopping.py b/tests/tests_pytorch/callbacks/test_early_stopping.py index ee7e228f03b32..375734dead18f 100644 --- a/tests/tests_pytorch/callbacks/test_early_stopping.py +++ b/tests/tests_pytorch/callbacks/test_early_stopping.py @@ -124,7 +124,7 @@ def test_early_stopping_no_extraneous_invocations(tmpdir): @pytest.mark.parametrize( - "loss_values, patience, expected_stop_epoch", + ("loss_values", "patience", "expected_stop_epoch"), [([6, 5, 5, 5, 5, 5], 3, 4), ([6, 5, 4, 4, 3, 3], 1, 3), ([6, 5, 6, 5, 5, 5], 3, 4)], ) def test_early_stopping_patience(tmpdir, loss_values: list, patience: int, expected_stop_epoch: int): @@ -152,7 +152,7 @@ def on_validation_epoch_end(self): @pytest.mark.parametrize("validation_step_none", [True, False]) @pytest.mark.parametrize( - "loss_values, patience, expected_stop_epoch", + ("loss_values", "patience", "expected_stop_epoch"), [([6, 5, 5, 5, 5, 5], 3, 4), ([6, 5, 4, 4, 3, 3], 1, 3), ([6, 5, 6, 5, 5, 5], 3, 4)], ) def test_early_stopping_patience_train( @@ -215,7 +215,7 @@ def test_early_stopping_no_val_step(tmpdir): @pytest.mark.parametrize( - "stopping_threshold,divergence_threshold,losses,expected_epoch", + ("stopping_threshold", "divergence_threshold", "losses", "expected_epoch"), [ (None, None, [8, 4, 2, 3, 4, 5, 8, 10], 5), (2.9, None, [9, 8, 7, 6, 5, 6, 4, 3, 2, 1], 8), @@ -268,7 +268,7 @@ def on_validation_epoch_end(self): @pytest.mark.parametrize( - "limit_train_batches,min_epochs,min_steps,stop_step", + ("limit_train_batches", "min_epochs", "min_steps", "stop_step"), [ # IF `min_steps` was set to a higher value than the `trainer.global_step` when `early_stopping` is being # triggered, THEN the trainer should continue until reaching `trainer.global_step == min_steps` and stop @@ -369,7 +369,7 @@ def on_train_end(self) -> None: @pytest.mark.parametrize( - "callbacks, expected_stop_epoch, check_on_train_epoch_end, strategy, devices, dist_diverge_epoch", + ("callbacks", "expected_stop_epoch", "check_on_train_epoch_end", "strategy", "devices", "dist_diverge_epoch"), [ ([EarlyStopping("abc"), EarlyStopping("cba", patience=3)], 3, False, "auto", 1, None), ([EarlyStopping("cba", patience=3), EarlyStopping("abc")], 3, False, "auto", 1, None), @@ -481,7 +481,7 @@ def test_early_stopping_squeezes(): @pytest.mark.parametrize("trainer", [Trainer(), None]) @pytest.mark.parametrize( - "log_rank_zero_only, world_size, global_rank, expected_log", + ("log_rank_zero_only", "world_size", "global_rank", "expected_log"), [ (False, 1, 0, "bar"), (False, 2, 0, "[rank: 0] bar"), diff --git a/tests/tests_pytorch/callbacks/test_gradient_accumulation_scheduler.py b/tests/tests_pytorch/callbacks/test_gradient_accumulation_scheduler.py index d149ba738bcb9..c7118c64e2e2a 100644 --- a/tests/tests_pytorch/callbacks/test_gradient_accumulation_scheduler.py +++ b/tests/tests_pytorch/callbacks/test_gradient_accumulation_scheduler.py @@ -47,7 +47,7 @@ def test_trainer_accumulate_grad_batches_zero_grad(tmpdir, accumulate_grad_batch @pytest.mark.parametrize( - ["accumulate_grad_batches", "expected_call_count"], + ("accumulate_grad_batches", "expected_call_count"), [ ({1: 2, 3: 4}, 10 + 5 + 5 + 3), ({0: 2, 2: 1}, 5 + 5 + 10 + 10), diff --git a/tests/tests_pytorch/callbacks/test_timer.py b/tests/tests_pytorch/callbacks/test_timer.py index cc9a5f278b69d..c160127e84ce3 100644 --- a/tests/tests_pytorch/callbacks/test_timer.py +++ b/tests/tests_pytorch/callbacks/test_timer.py @@ -53,7 +53,7 @@ def on_fit_start(self): @pytest.mark.parametrize( - "duration,expected", + ("duration", "expected"), [ (None, None), ("00:00:00:22", timedelta(seconds=22)), @@ -130,7 +130,7 @@ def test_timer_zero_duration_stop(tmpdir, interval): assert trainer.current_epoch == 0 -@pytest.mark.parametrize("min_steps,min_epochs", [(None, 2), (3, None), (3, 2)]) +@pytest.mark.parametrize(("min_steps", "min_epochs"), [(None, 2), (3, None), (3, 2)]) def test_timer_duration_min_steps_override(tmpdir, min_steps, min_epochs): model = BoringModel() duration = timedelta(0) diff --git a/tests/tests_pytorch/checkpointing/test_checkpoint_callback_frequency.py b/tests/tests_pytorch/checkpointing/test_checkpoint_callback_frequency.py index e9369df6b6cdf..230334f59c041 100644 --- a/tests/tests_pytorch/checkpointing/test_checkpoint_callback_frequency.py +++ b/tests/tests_pytorch/checkpointing/test_checkpoint_callback_frequency.py @@ -32,7 +32,7 @@ def test_disabled_checkpointing(tmpdir): @mock.patch("torch.save") @pytest.mark.parametrize( - ["epochs", "val_check_interval", "expected"], [(1, 1.0, 1), (2, 1.0, 2), (1, 0.25, 4), (2, 0.3, 6)] + ("epochs", "val_check_interval", "expected"), [(1, 1.0, 1), (2, 1.0, 2), (1, 0.25, 4), (2, 0.3, 6)] ) def test_default_checkpoint_freq(save_mock, tmpdir, epochs: int, val_check_interval: float, expected: int): model = BoringModel() @@ -52,7 +52,7 @@ def test_default_checkpoint_freq(save_mock, tmpdir, epochs: int, val_check_inter @mock.patch("torch.save") @pytest.mark.parametrize( - ["k", "epochs", "val_check_interval", "expected"], [(1, 1, 1.0, 1), (2, 2, 1.0, 2), (2, 1, 0.25, 4), (2, 2, 0.3, 6)] + ("k", "epochs", "val_check_interval", "expected"), [(1, 1, 1.0, 1), (2, 2, 1.0, 2), (2, 1, 0.25, 4), (2, 2, 0.3, 6)] ) @pytest.mark.parametrize("save_last", (False, True)) def test_top_k(save_mock, tmpdir, k: int, epochs: int, val_check_interval: float, expected: int, save_last: bool): @@ -87,7 +87,7 @@ def training_step(self, batch, batch_idx): @mock.patch("torch.save") @RunIf(min_cuda_gpus=2, standalone=True) -@pytest.mark.parametrize(["k", "epochs", "val_check_interval", "expected"], [(1, 1, 1.0, 1), (2, 2, 0.3, 4)]) +@pytest.mark.parametrize(("k", "epochs", "val_check_interval", "expected"), [(1, 1, 1.0, 1), (2, 2, 0.3, 4)]) def test_top_k_ddp(save_mock, tmpdir, k, epochs, val_check_interval, expected): class TestModel(BoringModel): def training_step(self, batch, batch_idx): diff --git a/tests/tests_pytorch/checkpointing/test_model_checkpoint.py b/tests/tests_pytorch/checkpointing/test_model_checkpoint.py index dac78e0477cd0..054e02d2eebf6 100644 --- a/tests/tests_pytorch/checkpointing/test_model_checkpoint.py +++ b/tests/tests_pytorch/checkpointing/test_model_checkpoint.py @@ -78,7 +78,7 @@ def mock(key): @pytest.mark.parametrize( - "validation_step_none,val_dataloaders_none,monitor", + ("validation_step_none", "val_dataloaders_none", "monitor"), [(False, False, "val_log"), (True, False, "train_log_epoch"), (False, True, "val_log")], ) @pytest.mark.parametrize("reduce_lr_on_plateau", [False, True]) @@ -184,7 +184,7 @@ def on_validation_epoch_end(self): @pytest.mark.parametrize( - "val_check_interval,reduce_lr_on_plateau,epoch_aligned", + ("val_check_interval", "reduce_lr_on_plateau", "epoch_aligned"), [(0.25, True, True), (0.25, False, True), (0.42, False, False)], ) def test_model_checkpoint_score_and_ckpt_val_check_interval( @@ -330,7 +330,9 @@ def test_model_checkpoint_to_yaml(tmpdir, save_top_k: int): assert d == best_k -@pytest.mark.parametrize("logger_version,expected", [(None, "version_0"), (1, "version_1"), ("awesome", "awesome")]) +@pytest.mark.parametrize( + ("logger_version", "expected"), [(None, "version_0"), (1, "version_1"), ("awesome", "awesome")] +) def test_model_checkpoint_path(tmpdir, logger_version: Union[None, int, str], expected: str): """Test that "version_" prefix is only added when logger's version is an integer.""" model = LogInTwoMethods() diff --git a/tests/tests_pytorch/conftest.py b/tests/tests_pytorch/conftest.py index f9a397c1241bb..8fddc54a3cebb 100644 --- a/tests/tests_pytorch/conftest.py +++ b/tests/tests_pytorch/conftest.py @@ -37,7 +37,7 @@ def datadir(): return Path(_PATH_DATASETS) -@pytest.fixture(scope="function", autouse=True) +@pytest.fixture(autouse=True) def preserve_global_rank_variable(): """Ensures that the rank_zero_only.rank global variable gets reset in each test.""" from lightning.pytorch.utilities.rank_zero import rank_zero_only @@ -48,7 +48,7 @@ def preserve_global_rank_variable(): setattr(rank_zero_only, "rank", rank) -@pytest.fixture(scope="function", autouse=True) +@pytest.fixture(autouse=True) def restore_env_variables(): """Ensures that environment variables set during the test do not leak out.""" env_backup = os.environ.copy() @@ -89,7 +89,7 @@ def restore_env_variables(): assert not leaked_vars, f"test is leaking environment variable(s): {set(leaked_vars)}" -@pytest.fixture(scope="function", autouse=True) +@pytest.fixture(autouse=True) def restore_signal_handlers(): """Ensures that signal handlers get restored before the next test runs. @@ -106,7 +106,7 @@ def restore_signal_handlers(): signal.signal(signum, handler) -@pytest.fixture(scope="function", autouse=True) +@pytest.fixture(autouse=True) def teardown_process_group(): """Ensures that the distributed process group gets closed before the next test runs.""" yield @@ -114,7 +114,7 @@ def teardown_process_group(): torch.distributed.destroy_process_group() -@pytest.fixture(scope="function", autouse=True) +@pytest.fixture(autouse=True) def reset_deterministic_algorithm(): """Ensures that torch determinism settings are reset before the next test runs.""" yield @@ -126,22 +126,22 @@ def mock_cuda_count(monkeypatch, n: int) -> None: monkeypatch.setattr(lightning.pytorch.accelerators.cuda, "num_cuda_devices", lambda: n) -@pytest.fixture(scope="function") +@pytest.fixture() def cuda_count_0(monkeypatch): mock_cuda_count(monkeypatch, 0) -@pytest.fixture(scope="function") +@pytest.fixture() def cuda_count_1(monkeypatch): mock_cuda_count(monkeypatch, 1) -@pytest.fixture(scope="function") +@pytest.fixture() def cuda_count_2(monkeypatch): mock_cuda_count(monkeypatch, 2) -@pytest.fixture(scope="function") +@pytest.fixture() def cuda_count_4(monkeypatch): mock_cuda_count(monkeypatch, 4) @@ -159,22 +159,22 @@ def __new__(cls, self, *args, **kwargs): monkeypatch.setattr(lightning.fabric.accelerators.mps.MPSAccelerator, "is_available", lambda *_: n > 0) -@pytest.fixture(scope="function") +@pytest.fixture() def mps_count_0(monkeypatch): mock_mps_count(monkeypatch, 0) -@pytest.fixture(scope="function") +@pytest.fixture() def mps_count_1(monkeypatch): mock_mps_count(monkeypatch, 1) -@pytest.fixture(scope="function") +@pytest.fixture() def mps_count_2(monkeypatch): mock_mps_count(monkeypatch, 2) -@pytest.fixture(scope="function") +@pytest.fixture() def mps_count_4(monkeypatch): mock_mps_count(monkeypatch, 4) @@ -191,7 +191,7 @@ def mock_xla_available(monkeypatch: pytest.MonkeyPatch, value: bool = True) -> N monkeypatch.setattr(lightning.fabric.strategies.launchers.xla, "_XLA_AVAILABLE", value) -@pytest.fixture(scope="function") +@pytest.fixture() def xla_available(monkeypatch: pytest.MonkeyPatch) -> None: mock_xla_available(monkeypatch) @@ -207,12 +207,12 @@ def mock_tpu_available(monkeypatch: pytest.MonkeyPatch, value: bool = True) -> N monkeypatch.setitem(sys.modules, "torch_xla.experimental", Mock()) -@pytest.fixture(scope="function") +@pytest.fixture() def tpu_available(monkeypatch) -> None: mock_tpu_available(monkeypatch) -@pytest.fixture +@pytest.fixture() def caplog(caplog): """Workaround for https://github.com/pytest-dev/pytest/issues/3697. @@ -239,7 +239,7 @@ def caplog(caplog): logging.getLogger(name).propagate = propagate -@pytest.fixture +@pytest.fixture() def tmpdir_server(tmpdir): Handler = partial(SimpleHTTPRequestHandler, directory=str(tmpdir)) from http.server import ThreadingHTTPServer @@ -253,7 +253,7 @@ def tmpdir_server(tmpdir): server.shutdown() -@pytest.fixture +@pytest.fixture() def single_process_pg(): """Initialize the default process group with only the current process for testing purposes. diff --git a/tests/tests_pytorch/core/test_lightning_module.py b/tests/tests_pytorch/core/test_lightning_module.py index 1a0be112743a6..6d612dd3c9b03 100644 --- a/tests/tests_pytorch/core/test_lightning_module.py +++ b/tests/tests_pytorch/core/test_lightning_module.py @@ -284,7 +284,7 @@ def configure_optimizers(self): @pytest.mark.parametrize( - "accelerator,device", + ("accelerator", "device"), [ pytest.param("gpu", "cuda:0", marks=RunIf(min_cuda_gpus=1)), pytest.param("mps", "mps:0", marks=RunIf(mps=True)), diff --git a/tests/tests_pytorch/core/test_metric_result_integration.py b/tests/tests_pytorch/core/test_metric_result_integration.py index 390908fe5d208..dd706102cb16a 100644 --- a/tests/tests_pytorch/core/test_metric_result_integration.py +++ b/tests/tests_pytorch/core/test_metric_result_integration.py @@ -530,7 +530,7 @@ def test_metric_result_dtype_promotion(reduce_fx): assert total.dtype == torch.double -@pytest.mark.parametrize(["reduce_fx", "expected"], [(max, -2), (min, 2)]) +@pytest.mark.parametrize(("reduce_fx", "expected"), [(max, -2), (min, 2)]) def test_result_metric_max_min(reduce_fx, expected): metadata = _Metadata("foo", "bar", reduce_fx=reduce_fx) metadata.sync = _Sync() diff --git a/tests/tests_pytorch/helpers/test_datasets.py b/tests/tests_pytorch/helpers/test_datasets.py index 2faef236facf7..c4e2ad06fa7e3 100644 --- a/tests/tests_pytorch/helpers/test_datasets.py +++ b/tests/tests_pytorch/helpers/test_datasets.py @@ -21,7 +21,7 @@ @pytest.mark.parametrize( - "dataset_cls,args", + ("dataset_cls", "args"), [(MNIST, {"root": _PATH_DATASETS}), (TrialMNIST, {"root": _PATH_DATASETS}), (AverageDataset, {})], ) def test_pickling_dataset_mnist(tmpdir, dataset_cls, args): diff --git a/tests/tests_pytorch/helpers/test_models.py b/tests/tests_pytorch/helpers/test_models.py index 3bf63d3e1a0c2..a52d8914308c7 100644 --- a/tests/tests_pytorch/helpers/test_models.py +++ b/tests/tests_pytorch/helpers/test_models.py @@ -24,7 +24,7 @@ @pytest.mark.parametrize( - "data_class,model_class", + ("data_class", "model_class"), [ (None, BoringModel), (None, BasicGAN), diff --git a/tests/tests_pytorch/loggers/test_mlflow.py b/tests/tests_pytorch/loggers/test_mlflow.py index d968805b5183b..239645c2a7e2c 100644 --- a/tests/tests_pytorch/loggers/test_mlflow.py +++ b/tests/tests_pytorch/loggers/test_mlflow.py @@ -286,7 +286,7 @@ def test_mlflow_logger_with_many_params(client, _, param, tmpdir): @pytest.mark.parametrize( - "status,expected", + ("status", "expected"), [ ("success", "FINISHED"), ("failed", "FAILED"), diff --git a/tests/tests_pytorch/loggers/test_neptune.py b/tests/tests_pytorch/loggers/test_neptune.py index 21c3a2ad2f372..2ccfb5ac14104 100644 --- a/tests/tests_pytorch/loggers/test_neptune.py +++ b/tests/tests_pytorch/loggers/test_neptune.py @@ -82,7 +82,7 @@ def get_root_object(self): return self -@pytest.fixture +@pytest.fixture() def tmpdir_unittest_fixture(request, tmpdir): """Proxy for pytest `tmpdir` fixture between pytest and unittest. @@ -105,13 +105,13 @@ def test_neptune_online(self, neptune): logger = NeptuneLogger(api_key="test", project="project") created_run_mock = logger.run - self.assertEqual(logger._run_instance, created_run_mock) + assert logger._run_instance == created_run_mock created_run_mock.exists.assert_called_once_with("sys/id") - self.assertEqual(logger.name, "Run test name") - self.assertEqual(logger.version, "TEST-1") - self.assertEqual(neptune.init_run.call_count, 1) - self.assertEqual(created_run_mock.__getitem__.call_count, 2) - self.assertEqual(created_run_mock.__setitem__.call_count, 1) + assert logger.name == "Run test name" + assert logger.version == "TEST-1" + assert neptune.init_run.call_count == 1 + assert created_run_mock.__getitem__.call_count == 2 + assert created_run_mock.__setitem__.call_count == 1 created_run_mock.__getitem__.assert_has_calls([call("sys/id"), call("sys/name")], any_order=True) created_run_mock.__setitem__.assert_called_once_with("source_code/integrations/pytorch-lightning", __version__) @@ -123,8 +123,8 @@ def test_neptune_offline(self, neptune): logger.experiment["foo"] = "bar" created_run_mock.exists.assert_called_once_with("sys/id") - self.assertEqual(logger._run_short_id, "OFFLINE") - self.assertEqual(logger._run_name, "offline-name") + assert logger._run_short_id == "OFFLINE" + assert logger._run_name == "offline-name" @patch("lightning.pytorch.loggers.neptune.Run", Run) @patch("lightning.pytorch.loggers.neptune.Handler", Run) @@ -133,22 +133,22 @@ def test_online_with_custom_run(self, neptune): logger = NeptuneLogger(run=created_run) assert logger._run_instance == created_run - self.assertEqual(logger._run_instance, created_run) - self.assertEqual(logger.version, "TEST-42") - self.assertEqual(neptune.init_run.call_count, 0) + assert logger._run_instance == created_run + assert logger.version == "TEST-42" + assert neptune.init_run.call_count == 0 @patch("lightning.pytorch.loggers.neptune.Run", Run) @patch("lightning.pytorch.loggers.neptune.Handler", Run) def test_neptune_pickling(self, neptune): unpickleable_run = Run() logger = NeptuneLogger(run=unpickleable_run) - self.assertEqual(0, neptune.init_run.call_count) + assert neptune.init_run.call_count == 0 pickled_logger = pickle.dumps(logger) unpickled = pickle.loads(pickled_logger) neptune.init_run.assert_called_once_with(name="Test name", run="TEST-42") - self.assertIsNotNone(unpickled.experiment) + assert unpickled.experiment is not None @patch("lightning.pytorch.loggers.neptune.Run", Run) @patch("lightning.pytorch.loggers.neptune.Handler", Run) @@ -255,8 +255,8 @@ def test_log_hyperparams(self, neptune): logger.log_hyperparams(params) # then - self.assertEqual(run_instance_mock.__setitem__.call_count, 1) - self.assertEqual(run_instance_mock.__getitem__.call_count, 0) + assert run_instance_mock.__setitem__.call_count == 1 + assert run_instance_mock.__getitem__.call_count == 0 run_instance_mock.__setitem__.assert_called_once_with(hyperparams_key, params) def test_log_metrics(self, neptune): @@ -280,8 +280,8 @@ def test_log_metrics(self, neptune): logger.log_metrics(metrics) # then: - self.assertEqual(run_instance_mock.__setitem__.call_count, 0) - self.assertEqual(run_instance_mock.__getitem__.call_count, 2) + assert run_instance_mock.__setitem__.call_count == 0 + assert run_instance_mock.__getitem__.call_count == 2 run_instance_mock.__getitem__.assert_any_call(metrics_foo_key) run_instance_mock.__getitem__.assert_any_call(metrics_bar_key) run_attr_mock.append.assert_has_calls([call(42), call(555)]) @@ -303,8 +303,8 @@ def test_log_model_summary(self, neptune): logger.log_model_summary(model) # then: - self.assertEqual(run_instance_mock.__setitem__.call_count, 1) - self.assertEqual(run_instance_mock.__getitem__.call_count, 0) + assert run_instance_mock.__setitem__.call_count == 1 + assert run_instance_mock.__getitem__.call_count == 0 run_instance_mock.__setitem__.assert_called_once_with(model_summary_key, file_from_content_mock) @patch("builtins.open", mock.mock_open(read_data="test")) @@ -337,11 +337,11 @@ def test_after_save_checkpoint(self, neptune): logger.after_save_checkpoint(cb_mock) # then: - self.assertEqual(run_instance_mock.__setitem__.call_count, 3) - self.assertEqual(run_instance_mock.__getitem__.call_count, 2) - self.assertEqual(run_attr_mock.upload.call_count, 2) + assert run_instance_mock.__setitem__.call_count == 3 + assert run_instance_mock.__getitem__.call_count == 2 + assert run_attr_mock.upload.call_count == 2 - self.assertEqual(mock_file.from_stream.call_count, 2) + assert mock_file.from_stream.call_count == 2 run_instance_mock.__getitem__.assert_any_call(f"{model_key_prefix}/checkpoints/model1") run_instance_mock.__getitem__.assert_any_call(f"{model_key_prefix}/checkpoints/model2/with/slashes") @@ -358,7 +358,7 @@ def test_save_dir(self, neptune): logger = NeptuneLogger(api_key="test", project="project") # expect - self.assertEqual(logger.save_dir, os.path.join(os.getcwd(), ".neptune")) + assert logger.save_dir == os.path.join(os.getcwd(), ".neptune") class TestNeptuneLoggerUtils(unittest.TestCase): @@ -376,7 +376,7 @@ def test__get_full_model_name(self): # expect: for expected_model_name, *key_and_path in test_input_data: - self.assertEqual(NeptuneLogger._get_full_model_name(*key_and_path), expected_model_name) + assert NeptuneLogger._get_full_model_name(*key_and_path) == expected_model_name def test__get_full_model_names_from_exp_structure(self): # given: @@ -393,4 +393,4 @@ def test__get_full_model_names_from_exp_structure(self): expected_keys = {"lvl1_1/lvl2/lvl3_1", "lvl1_1/lvl2/lvl3_2", "lvl1_2"} # expect: - self.assertEqual(NeptuneLogger._get_full_model_names_from_exp_structure(input_dict, "foo/bar"), expected_keys) + assert NeptuneLogger._get_full_model_names_from_exp_structure(input_dict, "foo/bar") == expected_keys diff --git a/tests/tests_pytorch/loggers/test_wandb.py b/tests/tests_pytorch/loggers/test_wandb.py index 08b0532ed84fc..bbdae2b0de0df 100644 --- a/tests/tests_pytorch/loggers/test_wandb.py +++ b/tests/tests_pytorch/loggers/test_wandb.py @@ -381,7 +381,8 @@ def test_wandb_log_model_with_score(wandb, monkeypatch, tmpdir): assert len(calls) == 1 score = calls[0][1]["metadata"]["score"] # model checkpoint monitors scalar tensors, but wandb can't serializable them - expect Python scalars in metadata - assert isinstance(score, int) and score == 3 + assert isinstance(score, int) + assert score == 3 @mock.patch("lightning.pytorch.loggers.wandb.Run", new=mock.Mock) diff --git a/tests/tests_pytorch/loops/test_loops.py b/tests/tests_pytorch/loops/test_loops.py index d6076347bbdc9..b45f82e417f97 100644 --- a/tests/tests_pytorch/loops/test_loops.py +++ b/tests/tests_pytorch/loops/test_loops.py @@ -192,7 +192,7 @@ def on_load_checkpoint(self, state_dict: Dict) -> None: @pytest.mark.parametrize("stop_epoch", (1, 2)) @pytest.mark.parametrize("stop_batch", (1, 2)) -@pytest.mark.parametrize("n_dataloaders,stop_dataloader", [(2, 0), (2, 1), (3, 2)]) +@pytest.mark.parametrize(("n_dataloaders", "stop_dataloader"), [(2, 0), (2, 1), (3, 2)]) def test_loop_restart_progress_multiple_dataloaders(tmpdir, n_dataloaders, stop_dataloader, stop_epoch, stop_batch): n_batches = 5 n_epochs = 3 @@ -605,7 +605,7 @@ def test_fit_loop_reset(tmpdir): @pytest.mark.parametrize( - ["train_datasets", "val_datasets"], + ("train_datasets", "val_datasets"), [([RandomDataset], [RandomDataset]), ([RandomDataset], [RandomDataset, RandomDataset])], ) @pytest.mark.parametrize("val_check_interval", [0.5, 1.0]) diff --git a/tests/tests_pytorch/loops/test_training_epoch_loop.py b/tests/tests_pytorch/loops/test_training_epoch_loop.py index 2d7929e11de1c..7d0690c5ac876 100644 --- a/tests/tests_pytorch/loops/test_training_epoch_loop.py +++ b/tests/tests_pytorch/loops/test_training_epoch_loop.py @@ -48,7 +48,7 @@ def test_no_val_on_train_epoch_loop_restart(tmpdir): @pytest.mark.parametrize( - "min_epochs, min_steps, current_epoch, global_step, early_stop, epoch_loop_done, raise_info_msg", + ("min_epochs", "min_steps", "current_epoch", "global_step", "early_stop", "epoch_loop_done", "raise_info_msg"), [ (None, None, 1, 4, True, True, False), (None, None, 1, 10, True, True, False), @@ -80,7 +80,7 @@ def test_should_stop_early_stopping_conditions_not_met( assert trainer.fit_loop._can_stop_early is early_stop -@pytest.mark.parametrize("min_epochs,min_steps,val_count", [(3, None, 3), (None, 3, 2)]) +@pytest.mark.parametrize(("min_epochs", "min_steps", "val_count"), [(3, None, 3), (None, 3, 2)]) def test_should_stop_triggers_validation_once(min_epochs, min_steps, val_count, tmp_path): """Regression test for issue #15708. diff --git a/tests/tests_pytorch/loops/test_training_loop.py b/tests/tests_pytorch/loops/test_training_loop.py index 6e484438ed839..fe73138577891 100644 --- a/tests/tests_pytorch/loops/test_training_loop.py +++ b/tests/tests_pytorch/loops/test_training_loop.py @@ -89,7 +89,7 @@ def run_training(**trainer_kwargs): assert torch.allclose(sequence0, sequence1) -@pytest.mark.parametrize(["max_epochs", "batch_idx_"], [(2, 5), (3, 8), (4, 12)]) +@pytest.mark.parametrize(("max_epochs", "batch_idx_"), [(2, 5), (3, 8), (4, 12)]) def test_on_train_batch_start_return_minus_one(max_epochs, batch_idx_, tmpdir): class CurrentModel(BoringModel): def on_train_batch_start(self, batch, batch_idx): @@ -176,7 +176,7 @@ def test_fit_loop_done_log_messages(caplog): @pytest.mark.parametrize( - "min_epochs, min_steps, current_epoch, early_stop, fit_loop_done, raise_debug_msg", + ("min_epochs", "min_steps", "current_epoch", "early_stop", "fit_loop_done", "raise_debug_msg"), [ (4, None, 100, True, True, False), (4, None, 3, False, False, False), diff --git a/tests/tests_pytorch/models/test_cpu.py b/tests/tests_pytorch/models/test_cpu.py index 4f0c7624b63aa..ed21acb1f68b9 100644 --- a/tests/tests_pytorch/models/test_cpu.py +++ b/tests/tests_pytorch/models/test_cpu.py @@ -80,7 +80,8 @@ def test_cpu_slurm_save_load(_, tmpdir): class _StartCallback(Callback): # set the epoch start hook so we can predict before the model does the full training def on_train_epoch_start(self, trainer, model): - assert trainer.global_step == real_global_step and trainer.global_step > 0 + assert trainer.global_step == real_global_step + assert trainer.global_step > 0 # predict with loaded model to make sure answers are the same mode = model.training model.eval() diff --git a/tests/tests_pytorch/models/test_gpu.py b/tests/tests_pytorch/models/test_gpu.py index 92e7b98e650f8..542197fe91b49 100644 --- a/tests/tests_pytorch/models/test_gpu.py +++ b/tests/tests_pytorch/models/test_gpu.py @@ -131,30 +131,38 @@ def test_single_gpu_batch_parse(): # batch is just a tensor batch = torch.rand(2, 3) batch = trainer.strategy.batch_to_device(batch, torch.device("cuda:0")) - assert batch.device.index == 0 and batch.type() == "torch.cuda.FloatTensor" + assert batch.device.index == 0 + assert batch.type() == "torch.cuda.FloatTensor" # tensor list batch = [torch.rand(2, 3), torch.rand(2, 3)] batch = trainer.strategy.batch_to_device(batch, torch.device("cuda:0")) - assert batch[0].device.index == 0 and batch[0].type() == "torch.cuda.FloatTensor" - assert batch[1].device.index == 0 and batch[1].type() == "torch.cuda.FloatTensor" + assert batch[0].device.index == 0 + assert batch[0].type() == "torch.cuda.FloatTensor" + assert batch[1].device.index == 0 + assert batch[1].type() == "torch.cuda.FloatTensor" # tensor list of lists batch = [[torch.rand(2, 3), torch.rand(2, 3)]] batch = trainer.strategy.batch_to_device(batch, torch.device("cuda:0")) - assert batch[0][0].device.index == 0 and batch[0][0].type() == "torch.cuda.FloatTensor" - assert batch[0][1].device.index == 0 and batch[0][1].type() == "torch.cuda.FloatTensor" + assert batch[0][0].device.index == 0 + assert batch[0][0].type() == "torch.cuda.FloatTensor" + assert batch[0][1].device.index == 0 + assert batch[0][1].type() == "torch.cuda.FloatTensor" # tensor dict batch = [{"a": torch.rand(2, 3), "b": torch.rand(2, 3)}] batch = trainer.strategy.batch_to_device(batch, torch.device("cuda:0")) - assert batch[0]["a"].device.index == 0 and batch[0]["a"].type() == "torch.cuda.FloatTensor" - assert batch[0]["b"].device.index == 0 and batch[0]["b"].type() == "torch.cuda.FloatTensor" + assert batch[0]["a"].device.index == 0 + assert batch[0]["a"].type() == "torch.cuda.FloatTensor" + assert batch[0]["b"].device.index == 0 + assert batch[0]["b"].type() == "torch.cuda.FloatTensor" # tuple of tensor list and list of tensor dict batch = ([torch.rand(2, 3) for _ in range(2)], [{"a": torch.rand(2, 3), "b": torch.rand(2, 3)} for _ in range(2)]) batch = trainer.strategy.batch_to_device(batch, torch.device("cuda:0")) - assert batch[0][0].device.index == 0 and batch[0][0].type() == "torch.cuda.FloatTensor" + assert batch[0][0].device.index == 0 + assert batch[0][0].type() == "torch.cuda.FloatTensor" assert batch[1][0]["a"].device.index == 0 assert batch[1][0]["a"].type() == "torch.cuda.FloatTensor" diff --git a/tests/tests_pytorch/models/test_hooks.py b/tests/tests_pytorch/models/test_hooks.py index 968f45a4036da..ccb075e7ca74f 100644 --- a/tests/tests_pytorch/models/test_hooks.py +++ b/tests/tests_pytorch/models/test_hooks.py @@ -100,7 +100,7 @@ def on_train_epoch_end(self): @pytest.mark.parametrize( - "accelerator,expected_device_str", + ("accelerator", "expected_device_str"), [ pytest.param("gpu", "cuda:0", marks=RunIf(min_cuda_gpus=1)), pytest.param("mps", "mps:0", marks=RunIf(mps=True)), @@ -667,7 +667,7 @@ def test_trainer_model_hook_system_fit_no_val_and_resume_max_steps(tmpdir): @pytest.mark.parametrize("batches", (0, 2)) @pytest.mark.parametrize( - ["verb", "noun", "dataloader", "key"], [("validate", "validation", "val", "x"), ("test", "test", "test", "y")] + ("verb", "noun", "dataloader", "key"), [("validate", "validation", "val", "x"), ("test", "test", "test", "y")] ) def test_trainer_model_hook_system_eval(tmpdir, batches, verb, noun, dataloader, key): called = [] diff --git a/tests/tests_pytorch/models/test_hparams.py b/tests/tests_pytorch/models/test_hparams.py index 18101d49568bb..27cfe14155839 100644 --- a/tests/tests_pytorch/models/test_hparams.py +++ b/tests/tests_pytorch/models/test_hparams.py @@ -487,7 +487,7 @@ def __init__(self, arg1, arg2): @pytest.mark.parametrize( - "cls,config", [(AnotherArgModel, {"arg1": 42}), (OtherArgsModel, {"arg1": 3.14, "arg2": "abc"})] + ("cls", "config"), [(AnotherArgModel, {"arg1": 42}), (OtherArgsModel, {"arg1": 3.14, "arg2": "abc"})] ) def test_single_config_models_fail(tmpdir, cls, config): """Test fail on passing unsupported config type.""" diff --git a/tests/tests_pytorch/models/test_onnx.py b/tests/tests_pytorch/models/test_onnx.py index da52c82a51a47..e9e0ffaed4975 100644 --- a/tests/tests_pytorch/models/test_onnx.py +++ b/tests/tests_pytorch/models/test_onnx.py @@ -59,7 +59,7 @@ def test_model_saves_on_gpu(tmpdir, accelerator): @pytest.mark.parametrize( - ["modelclass", "input_sample"], + ("modelclass", "input_sample"), [ (BoringModel, torch.randn(1, 32)), (UnorderedModel, (torch.rand(2, 3), torch.rand(2, 10))), diff --git a/tests/tests_pytorch/plugins/test_amp_plugins.py b/tests/tests_pytorch/plugins/test_amp_plugins.py index 5cca3a93aa518..360cecacd37e1 100644 --- a/tests/tests_pytorch/plugins/test_amp_plugins.py +++ b/tests/tests_pytorch/plugins/test_amp_plugins.py @@ -43,9 +43,9 @@ class MyAMP(MixedPrecisionPlugin): "SLURM_LOCALID": "0", }, ) -@pytest.mark.parametrize("strategy,devices", [("ddp", 2), ("ddp_spawn", 2)]) +@pytest.mark.parametrize(("strategy", "devices"), [("ddp", 2), ("ddp_spawn", 2)]) @pytest.mark.parametrize( - "custom_plugin,plugin_cls", + ("custom_plugin", "plugin_cls"), [ (False, MixedPrecisionPlugin), (True, MyAMP), diff --git a/tests/tests_pytorch/profilers/test_profiler.py b/tests/tests_pytorch/profilers/test_profiler.py index 477775d80b93c..3903fcf5f27a7 100644 --- a/tests/tests_pytorch/profilers/test_profiler.py +++ b/tests/tests_pytorch/profilers/test_profiler.py @@ -47,13 +47,13 @@ def _sleep_generator(durations): yield duration -@pytest.fixture +@pytest.fixture() def simple_profiler(): return SimpleProfiler() @pytest.mark.flaky(reruns=3) -@pytest.mark.parametrize(["action", "expected"], [("a", [3, 1]), ("b", [2]), ("c", [1])]) +@pytest.mark.parametrize(("action", "expected"), [("a", [3, 1]), ("b", [2]), ("c", [1])]) def test_simple_profiler_durations(simple_profiler, action: str, expected: list): """Ensure the reported durations are reasonably accurate.""" for duration in expected: @@ -256,13 +256,13 @@ def test_simple_profiler_summary(tmpdir, extended): assert expected_text == summary -@pytest.fixture +@pytest.fixture() def advanced_profiler(tmpdir): return AdvancedProfiler(dirpath=tmpdir, filename="profiler") @pytest.mark.flaky(reruns=3) -@pytest.mark.parametrize(["action", "expected"], [("a", [3, 1]), ("b", [2]), ("c", [1])]) +@pytest.mark.parametrize(("action", "expected"), [("a", [3, 1]), ("b", [2]), ("c", [1])]) def test_advanced_profiler_durations(advanced_profiler, action: str, expected: list): for duration in expected: with advanced_profiler.profile(action): @@ -315,7 +315,7 @@ def test_advanced_profiler_deepcopy(advanced_profiler): assert deepcopy(advanced_profiler) -@pytest.fixture +@pytest.fixture() def pytorch_profiler(tmpdir): return PyTorchProfiler(dirpath=tmpdir, filename="profiler") @@ -409,7 +409,7 @@ def test_pytorch_profiler_trainer_fit(fast_dev_run, boring_model_cls, tmpdir): assert any(f"fit-{pytorch_profiler.filename}" in f for f in files) -@pytest.mark.parametrize("fn, step_name", [("test", "test"), ("validate", "validation"), ("predict", "predict")]) +@pytest.mark.parametrize(("fn", "step_name"), [("test", "test"), ("validate", "validation"), ("predict", "predict")]) @pytest.mark.parametrize("boring_model_cls", [BoringModel, ManualOptimBoringModel]) def test_pytorch_profiler_trainer(fn, step_name, boring_model_cls, tmpdir): """Ensure that the profiler can be given to the trainer and test step are properly recorded.""" @@ -547,7 +547,7 @@ def test_pytorch_profiler_deepcopy(tmpdir): @pytest.mark.parametrize( - ["profiler", "expected"], + ("profiler", "expected"), [ (None, PassThroughProfiler), (SimpleProfiler(), SimpleProfiler), @@ -574,7 +574,7 @@ def test_trainer_profiler_incorrect_str_arg(): @pytest.mark.skipif(not _KINETO_AVAILABLE, reason="Requires PyTorch Profiler Kineto") @pytest.mark.parametrize( - ["trainer_config", "trainer_fn"], + ("trainer_config", "trainer_fn"), [ ({"limit_train_batches": 4, "limit_val_batches": 7}, "fit"), ({"limit_train_batches": 7, "limit_val_batches": 4, "num_sanity_val_steps": 0}, "fit"), diff --git a/tests/tests_pytorch/strategies/test_ddp.py b/tests/tests_pytorch/strategies/test_ddp.py index 1465e1b7696a2..5fed35b043237 100644 --- a/tests/tests_pytorch/strategies/test_ddp.py +++ b/tests/tests_pytorch/strategies/test_ddp.py @@ -123,7 +123,7 @@ def on_train_start(self, trainer: "pl.Trainer", pl_module: "pl.LightningModule") @pytest.mark.parametrize( - ["process_group_backend", "device_str", "expected_process_group_backend"], + ("process_group_backend", "device_str", "expected_process_group_backend"), [ pytest.param("foo", "cpu", "foo"), pytest.param("foo", "cuda:0", "foo"), @@ -148,7 +148,7 @@ def root_device(self): @pytest.mark.parametrize( - "strategy_name,expected_ddp_kwargs", + ("strategy_name", "expected_ddp_kwargs"), [ ("ddp", {}), ("ddp_find_unused_parameters_false", {"find_unused_parameters": False}), diff --git a/tests/tests_pytorch/strategies/test_ddp_spawn_strategy.py b/tests/tests_pytorch/strategies/test_ddp_spawn_strategy.py index db3d2f4813c45..cf8a588638fd0 100644 --- a/tests/tests_pytorch/strategies/test_ddp_spawn_strategy.py +++ b/tests/tests_pytorch/strategies/test_ddp_spawn_strategy.py @@ -147,7 +147,7 @@ def test_ddp_spawn_strategy_set_timeout(mock_init_process_group): @pytest.mark.parametrize( - "strategy_name,expected_ddp_kwargs", + ("strategy_name", "expected_ddp_kwargs"), [ ("ddp_spawn", {}), pytest.param("ddp_fork", {}, marks=RunIf(skip_windows=True)), diff --git a/tests/tests_pytorch/strategies/test_deepspeed_strategy.py b/tests/tests_pytorch/strategies/test_deepspeed_strategy.py index 702f526a5e995..19597846fd986 100644 --- a/tests/tests_pytorch/strategies/test_deepspeed_strategy.py +++ b/tests/tests_pytorch/strategies/test_deepspeed_strategy.py @@ -83,7 +83,7 @@ def automatic_optimization(self) -> bool: return False -@pytest.fixture +@pytest.fixture() def deepspeed_config(): return { "optimizer": {"type": "SGD", "params": {"lr": 3e-5}}, @@ -94,7 +94,7 @@ def deepspeed_config(): } -@pytest.fixture +@pytest.fixture() def deepspeed_zero_config(deepspeed_config): return {**deepspeed_config, "zero_allow_untested_optimizer": True, "zero_optimization": {"stage": 2}} @@ -199,7 +199,7 @@ def backward(self, loss: Tensor, *args, **kwargs) -> None: @RunIf(min_cuda_gpus=1, deepspeed=True) @pytest.mark.parametrize( - ["dataset_cls", "value"], + ("dataset_cls", "value"), [(RandomDataset, "auto"), (RandomDataset, 10), (RandomIterableDataset, "auto"), (RandomIterableDataset, 10)], ) @mock.patch("deepspeed.init_distributed", autospec=True) diff --git a/tests/tests_pytorch/strategies/test_fsdp.py b/tests/tests_pytorch/strategies/test_fsdp.py index 20de432e0235c..1a5a91b2ed4e5 100644 --- a/tests/tests_pytorch/strategies/test_fsdp.py +++ b/tests/tests_pytorch/strategies/test_fsdp.py @@ -174,7 +174,7 @@ def test_invalid_on_cpu(tmpdir): @RunIf(min_torch="1.12", min_cuda_gpus=1) -@pytest.mark.parametrize("precision, expected", [("16-mixed", torch.float16), ("bf16-mixed", torch.bfloat16)]) +@pytest.mark.parametrize(("precision", "expected"), [("16-mixed", torch.float16), ("bf16-mixed", torch.bfloat16)]) def test_precision_plugin_config(precision, expected): plugin = FSDPMixedPrecisionPlugin(precision=precision, device="cuda") config = plugin.mixed_precision_config @@ -280,7 +280,7 @@ def test_fsdp_strategy_full_state_dict(tmpdir, wrap_min_params): @RunIf(min_cuda_gpus=2, skip_windows=True, standalone=True, min_torch="1.12") @pytest.mark.parametrize( - "model, strategy, strategy_cfg", + ("model", "strategy", "strategy_cfg"), [ pytest.param(TestFSDPModel(), "fsdp", None, id="manually_wrapped"), pytest.param( diff --git a/tests/tests_pytorch/strategies/test_registry.py b/tests/tests_pytorch/strategies/test_registry.py index 39e9be39f579f..456a8bd3e2ddf 100644 --- a/tests/tests_pytorch/strategies/test_registry.py +++ b/tests/tests_pytorch/strategies/test_registry.py @@ -22,7 +22,7 @@ @pytest.mark.parametrize( - "strategy_name, init_params", + ("strategy_name", "init_params"), [ ("deepspeed", {}), ("deepspeed_stage_1", {"stage": 1}), @@ -70,7 +70,7 @@ def test_fsdp_strategy_registry(cuda_count_1): @pytest.mark.parametrize( - "strategy_name, strategy, expected_init_params", + ("strategy_name", "strategy", "expected_init_params"), [ ( "ddp_find_unused_parameters_false", diff --git a/tests/tests_pytorch/test_cli.py b/tests/tests_pytorch/test_cli.py index 22b5e1bfe539c..34861c15db62e 100644 --- a/tests/tests_pytorch/test_cli.py +++ b/tests/tests_pytorch/test_cli.py @@ -70,10 +70,10 @@ def mock_subclasses(baseclass, *subclasses): yield None -@pytest.fixture +@pytest.fixture() def cleandir(tmp_path, monkeypatch): monkeypatch.chdir(tmp_path) - yield + return @pytest.fixture(autouse=True) @@ -118,7 +118,7 @@ def _trainer_builder( return Trainer(limit_train_batches=limit_train_batches, fast_dev_run=fast_dev_run, callbacks=callbacks) -@pytest.mark.parametrize(["trainer_class", "model_class"], [(Trainer, Model), (_trainer_builder, _model_builder)]) +@pytest.mark.parametrize(("trainer_class", "model_class"), [(Trainer, Model), (_trainer_builder, _model_builder)]) def test_lightning_cli(trainer_class, model_class, monkeypatch): """Test that LightningCLI correctly instantiates model, trainer and calls fit.""" expected_model = {"model_param": 7} @@ -146,7 +146,8 @@ def on_train_start(callback, trainer, _): with mock.patch("sys.argv", ["any.py", "fit", "--model.model_param=7", "--trainer.limit_train_batches=100"]): cli = LightningCLI(model_class, trainer_class=trainer_class, save_config_callback=SaveConfigCallback) - assert hasattr(cli.trainer, "ran_asserts") and cli.trainer.ran_asserts + assert hasattr(cli.trainer, "ran_asserts") + assert cli.trainer.ran_asserts def test_lightning_cli_args_callbacks(cleandir): @@ -245,7 +246,8 @@ def test_lightning_cli_args(cleandir): cli_config = cli.config["fit"].as_dict() assert cli_config["seed_everything"] == 1234 - assert "model" not in loaded_config and "model" not in cli_config # no arguments to include + assert "model" not in loaded_config + assert "model" not in cli_config assert loaded_config["data"] == cli_config["data"] assert loaded_config["trainer"] == cli_config["trainer"] @@ -1519,11 +1521,11 @@ def test_pytorch_profiler_init_args(): @pytest.mark.parametrize( - ["args"], + "args", [ - (["--trainer.logger=False", "--model.foo=456"],), - ({"trainer": {"logger": False}, "model": {"foo": 456}},), - (Namespace(trainer=Namespace(logger=False), model=Namespace(foo=456)),), + ["--trainer.logger=False", "--model.foo=456"], + {"trainer": {"logger": False}, "model": {"foo": 456}}, + Namespace(trainer=Namespace(logger=False), model=Namespace(foo=456)), ], ) def test_lightning_cli_with_args_given(args): diff --git a/tests/tests_pytorch/trainer/connectors/test_accelerator_connector.py b/tests/tests_pytorch/trainer/connectors/test_accelerator_connector.py index 8abebdacaf2ea..5d4431bc9a1f4 100644 --- a/tests/tests_pytorch/trainer/connectors/test_accelerator_connector.py +++ b/tests/tests_pytorch/trainer/connectors/test_accelerator_connector.py @@ -59,7 +59,7 @@ @pytest.mark.parametrize( - ["accelerator", "devices"], [("tpu", "auto"), ("tpu", 1), ("tpu", [1]), ("tpu", 8), ("auto", 1), ("auto", 8)] + ("accelerator", "devices"), [("tpu", "auto"), ("tpu", 1), ("tpu", [1]), ("tpu", 8), ("auto", 1), ("auto", 8)] ) @RunIf(min_python="3.9") # mocking issue def test_accelerator_choice_tpu(accelerator, devices, tpu_available, monkeypatch): @@ -234,7 +234,7 @@ def test_interactive_compatible_strategy_ddp_fork(monkeypatch): @RunIf(mps=False) @pytest.mark.parametrize( - ["strategy", "strategy_class"], + ("strategy", "strategy_class"), [ ("ddp", DDPStrategy), ("ddp_spawn", DDPStrategy), @@ -279,7 +279,7 @@ def test_accelerator_gpu(): assert isinstance(trainer.accelerator, CUDAAccelerator) -@pytest.mark.parametrize(["devices", "strategy_class"], [(1, SingleDeviceStrategy), (5, DDPStrategy)]) +@pytest.mark.parametrize(("devices", "strategy_class"), [(1, SingleDeviceStrategy), (5, DDPStrategy)]) def test_accelerator_cpu_with_devices(devices, strategy_class): trainer = Trainer(accelerator="cpu", devices=devices) assert trainer.num_devices == devices @@ -289,7 +289,7 @@ def test_accelerator_cpu_with_devices(devices, strategy_class): @RunIf(min_cuda_gpus=2) @pytest.mark.parametrize( - ["devices", "strategy_class"], [(1, SingleDeviceStrategy), ([1], SingleDeviceStrategy), (2, DDPStrategy)] + ("devices", "strategy_class"), [(1, SingleDeviceStrategy), ([1], SingleDeviceStrategy), (2, DDPStrategy)] ) def test_accelerator_gpu_with_devices(devices, strategy_class): trainer = Trainer(accelerator="gpu", devices=devices) @@ -311,7 +311,7 @@ def test_set_devices_if_none_cpu(): @pytest.mark.parametrize( - ["strategy", "strategy_class"], + ("strategy", "strategy_class"), ( ("ddp_spawn", DDPStrategy), ("ddp_spawn_find_unused_parameters_false", DDPStrategy), @@ -332,7 +332,7 @@ def test_invalid_ddp_strategy_with_mps(accelerator, strategy, strategy_class, mp @pytest.mark.parametrize( - ["strategy", "strategy_class"], + ("strategy", "strategy_class"), [ ("ddp_spawn", DDPStrategy), ("ddp_spawn_find_unused_parameters_false", DDPStrategy), @@ -351,7 +351,7 @@ def test_strategy_choice_cpu_instance(): @pytest.mark.parametrize( - ["strategy", "strategy_class"], + ("strategy", "strategy_class"), [ ("ddp_spawn", DDPStrategy), ("ddp_spawn_find_unused_parameters_false", DDPStrategy), @@ -411,7 +411,7 @@ def test_strategy_choice_ddp_fork_cpu(): assert trainer.strategy.launcher._start_method == "fork" -@pytest.mark.parametrize("strategy,expected_cls", [("ddp", DDPStrategy), ("ddp_spawn", DDPStrategy)]) +@pytest.mark.parametrize(("strategy", "expected_cls"), [("ddp", DDPStrategy), ("ddp_spawn", DDPStrategy)]) def test_strategy_choice_ddp_cuda(strategy, expected_cls, mps_count_0, cuda_count_2): trainer = Trainer(fast_dev_run=True, strategy=strategy, accelerator="gpu", devices=1) assert isinstance(trainer.accelerator, CUDAAccelerator) @@ -419,7 +419,9 @@ def test_strategy_choice_ddp_cuda(strategy, expected_cls, mps_count_0, cuda_coun assert isinstance(trainer.strategy.cluster_environment, LightningEnvironment) -@pytest.mark.parametrize("job_name,expected_env", [("some_name", SLURMEnvironment), ("bash", LightningEnvironment)]) +@pytest.mark.parametrize( + ("job_name", "expected_env"), [("some_name", SLURMEnvironment), ("bash", LightningEnvironment)] +) @pytest.mark.parametrize("strategy", ["auto", "ddp", DDPStrategy]) def test_strategy_choice_ddp_slurm(cuda_count_2, strategy, job_name, expected_env): if strategy and not isinstance(strategy, str): @@ -583,7 +585,7 @@ def test_devices_auto_choice_cpu(monkeypatch, cuda_count_0): @pytest.mark.parametrize( - ["parallel_devices", "accelerator"], + ("parallel_devices", "accelerator"), [([torch.device("cpu")], "cuda"), ([torch.device("cuda", i) for i in range(8)], "tpu")], ) def test_parallel_devices_in_strategy_confilict_with_accelerator(parallel_devices, accelerator): @@ -608,7 +610,7 @@ def test_deterministic_init(deterministic): @pytest.mark.parametrize("cudnn_benchmark", (False, True)) @pytest.mark.parametrize( - ["benchmark_", "deterministic", "expected"], + ("benchmark_", "deterministic", "expected"), [ (None, False, None), (None, True, False), @@ -638,7 +640,7 @@ def test_benchmark_option(cudnn_benchmark, benchmark_, deterministic, expected): @pytest.mark.parametrize( - "sync_batchnorm,plugins,expected", + ("sync_batchnorm", "plugins", "expected"), [ (False, [], type(None)), (True, [], TorchSyncBatchNorm), @@ -681,7 +683,7 @@ def __init__(self, **kwargs): @pytest.mark.parametrize( - ["plugins", "expected"], + ("plugins", "expected"), [ ([LightningEnvironment(), SLURMEnvironment()], "ClusterEnvironment"), ([TorchCheckpointIO(), TorchCheckpointIO()], "CheckpointIO"), @@ -704,7 +706,7 @@ def test_passing_zero_and_empty_list_to_devices_flag(accelerator, devices): @pytest.mark.parametrize( - "expected_accelerator_flag,expected_accelerator_class", + ("expected_accelerator_flag", "expected_accelerator_class"), [ pytest.param("cuda", CUDAAccelerator, marks=RunIf(min_cuda_gpus=1)), pytest.param("mps", MPSAccelerator, marks=RunIf(mps=True)), @@ -754,7 +756,7 @@ def test_ddp_fork_on_unsupported_platform(_, strategy): @pytest.mark.parametrize( - ["strategy", "strategy_cls"], [("DDP", DDPStrategy), ("DDP_FIND_UNUSED_PARAMETERS_FALSE", DDPStrategy)] + ("strategy", "strategy_cls"), [("DDP", DDPStrategy), ("DDP_FIND_UNUSED_PARAMETERS_FALSE", DDPStrategy)] ) def test_strategy_str_passed_being_case_insensitive(strategy, strategy_cls): trainer = Trainer(accelerator="cpu", strategy=strategy) diff --git a/tests/tests_pytorch/trainer/connectors/test_callback_connector.py b/tests/tests_pytorch/trainer/connectors/test_callback_connector.py index fe3ca4c037b3c..71262df9179e8 100644 --- a/tests/tests_pytorch/trainer/connectors/test_callback_connector.py +++ b/tests/tests_pytorch/trainer/connectors/test_callback_connector.py @@ -149,9 +149,12 @@ def test_all_callback_states_saved_before_checkpoint_callback(tmpdir): state0 = ckpt["callbacks"]["StatefulCallback0"] state1 = ckpt["callbacks"]["StatefulCallback1{'unique': 'one'}"] state2 = ckpt["callbacks"]["StatefulCallback1{'unique': 'two'}"] - assert "content0" in state0 and state0["content0"] == 0 - assert "content1" in state1 and state1["content1"] == "one" - assert "content1" in state2 and state2["content1"] == "two" + assert "content0" in state0 + assert state0["content0"] == 0 + assert "content1" in state1 + assert state1["content1"] == "one" + assert "content1" in state2 + assert state2["content1"] == "two" assert ( "ModelCheckpoint{'monitor': None, 'mode': 'min', 'every_n_train_steps': 0, 'every_n_epochs': 1," " 'train_time_interval': None}" in ckpt["callbacks"] diff --git a/tests/tests_pytorch/trainer/connectors/test_data_connector.py b/tests/tests_pytorch/trainer/connectors/test_data_connector.py index 67981313d470b..e86ac68844505 100644 --- a/tests/tests_pytorch/trainer/connectors/test_data_connector.py +++ b/tests/tests_pytorch/trainer/connectors/test_data_connector.py @@ -377,7 +377,7 @@ def test_error_raised_with_float_limited_eval_batches(): @pytest.mark.parametrize( - "val_dl,warns", + ("val_dl", "warns"), [ (DataLoader(dataset=RandomDataset(32, 64), shuffle=True), True), (DataLoader(dataset=RandomDataset(32, 64), sampler=list(range(64))), False), @@ -419,7 +419,7 @@ def __init__(self): @pytest.mark.parametrize( - "instance,available", + ("instance", "available"), [ (None, True), (BoringModel().train_dataloader(), True), @@ -527,7 +527,7 @@ def test_invalid_hook_passed_in_datahook_selector(): dh_selector.get_instance("setup") -@pytest.mark.parametrize("devices, warn_context", [(1, no_warning_call), (2, pytest.warns)]) +@pytest.mark.parametrize(("devices", "warn_context"), [(1, no_warning_call), (2, pytest.warns)]) def test_eval_distributed_sampler_warning(devices, warn_context): """Test that a warning is raised when `DistributedSampler` is used with evaluation.""" model = BoringModel() @@ -577,7 +577,7 @@ def test_error_raised_with_insufficient_float_limit_train_dataloader(): @pytest.mark.parametrize( - "trainer_fn_name, dataloader_name", + ("trainer_fn_name", "dataloader_name"), [ ("fit", "train_dataloaders"), ("validate", "dataloaders"), @@ -612,7 +612,7 @@ def test_attach_data_input_validation_with_none_dataloader(trainer_fn_name, data @pytest.mark.parametrize( - "trainer_fn_name, dataloader_name, stage", + ("trainer_fn_name", "dataloader_name", "stage"), [ ("fit", "train_dataloaders", RunningStage.TRAINING), ("validate", "dataloaders", RunningStage.VALIDATING), diff --git a/tests/tests_pytorch/trainer/connectors/test_signal_connector.py b/tests/tests_pytorch/trainer/connectors/test_signal_connector.py index 0b7be9d5a9511..93ec16b91dbe3 100644 --- a/tests/tests_pytorch/trainer/connectors/test_signal_connector.py +++ b/tests/tests_pytorch/trainer/connectors/test_signal_connector.py @@ -142,7 +142,7 @@ def signal_handler(self): @pytest.mark.parametrize( - ["handler", "expected_return"], + ("handler", "expected_return"), [ (None, False), (signal.Handlers.SIG_IGN, True), diff --git a/tests/tests_pytorch/trainer/flags/test_check_val_every_n_epoch.py b/tests/tests_pytorch/trainer/flags/test_check_val_every_n_epoch.py index 5be563a52dc8a..e0c0762464de5 100644 --- a/tests/tests_pytorch/trainer/flags/test_check_val_every_n_epoch.py +++ b/tests/tests_pytorch/trainer/flags/test_check_val_every_n_epoch.py @@ -19,7 +19,7 @@ @pytest.mark.parametrize( - "max_epochs,expected_val_loop_calls,expected_val_batches", + ("max_epochs", "expected_val_loop_calls", "expected_val_batches"), [(1, 0, [0]), (4, 2, [0, 2, 0, 2]), (5, 2, [0, 2, 0, 2, 0])], ) def test_check_val_every_n_epoch(tmpdir, max_epochs, expected_val_loop_calls, expected_val_batches): diff --git a/tests/tests_pytorch/trainer/flags/test_min_max_epochs.py b/tests/tests_pytorch/trainer/flags/test_min_max_epochs.py index 8d1d6e35c1b0a..24ef36616060f 100644 --- a/tests/tests_pytorch/trainer/flags/test_min_max_epochs.py +++ b/tests/tests_pytorch/trainer/flags/test_min_max_epochs.py @@ -7,7 +7,7 @@ @pytest.mark.parametrize( - ["min_epochs", "max_epochs", "min_steps", "max_steps"], + ("min_epochs", "max_epochs", "min_steps", "max_steps"), [ (None, 3, None, -1), (None, None, None, 20), diff --git a/tests/tests_pytorch/trainer/flags/test_overfit_batches.py b/tests/tests_pytorch/trainer/flags/test_overfit_batches.py index 1817e77fb7bce..75001fd48596d 100644 --- a/tests/tests_pytorch/trainer/flags/test_overfit_batches.py +++ b/tests/tests_pytorch/trainer/flags/test_overfit_batches.py @@ -78,7 +78,7 @@ def val_dataloader(self): @pytest.mark.parametrize( - "stage,mode", + ("stage", "mode"), [(RunningStage.VALIDATING, "val"), (RunningStage.TESTING, "test"), (RunningStage.PREDICTING, "predict")], ) @pytest.mark.parametrize("overfit_batches", [0.11, 4]) diff --git a/tests/tests_pytorch/trainer/logging_/test_eval_loop_logging.py b/tests/tests_pytorch/trainer/logging_/test_eval_loop_logging.py index 9311c9ba57589..5b2d29e099966 100644 --- a/tests/tests_pytorch/trainer/logging_/test_eval_loop_logging.py +++ b/tests/tests_pytorch/trainer/logging_/test_eval_loop_logging.py @@ -118,7 +118,7 @@ def on_validation_epoch_end(self): assert all(isinstance(v, float) for v in trainer.progress_bar_metrics.values()) -@pytest.mark.parametrize(["batches", "log_interval", "max_epochs"], [(1, 1, 1), (64, 32, 2)]) +@pytest.mark.parametrize(("batches", "log_interval", "max_epochs"), [(1, 1, 1), (64, 32, 2)]) def test_eval_epoch_logging(tmpdir, batches, log_interval, max_epochs): class TestModel(BoringModel): def on_validation_epoch_end(self): @@ -210,7 +210,7 @@ def on_validation_epoch_end(self) -> None: assert trainer.logged_metrics["val_loss_step"] == model.val_losses[-1] -@pytest.mark.parametrize(["batches", "log_interval", "max_epochs"], [(1, 1, 1), (64, 32, 2)]) +@pytest.mark.parametrize(("batches", "log_interval", "max_epochs"), [(1, 1, 1), (64, 32, 2)]) def test_eval_epoch_only_logging(tmpdir, batches, log_interval, max_epochs): """Tests that on_test_epoch_end can be used to log, and we return them in the results.""" @@ -828,7 +828,7 @@ def test_dataloader(self): @pytest.mark.parametrize( - ["inputs", "expected"], + ("inputs", "expected"), [ pytest.param(inputs0, expected0, id="case0"), pytest.param(inputs1, expected1, id="case1"), @@ -922,7 +922,7 @@ def test_native_print_results_encodings(monkeypatch, encoding): @pytest.mark.parametrize( - ["inputs", "expected"], + ("inputs", "expected"), [ pytest.param(inputs0, expected0, id="case0"), pytest.param(inputs1, expected1, id="case1"), diff --git a/tests/tests_pytorch/trainer/logging_/test_train_loop_logging.py b/tests/tests_pytorch/trainer/logging_/test_train_loop_logging.py index 1159fc5410e36..9ae889cee772c 100644 --- a/tests/tests_pytorch/trainer/logging_/test_train_loop_logging.py +++ b/tests/tests_pytorch/trainer/logging_/test_train_loop_logging.py @@ -142,7 +142,7 @@ def on_train_epoch_end(self): @pytest.mark.parametrize( - ["batches", "fx", "result"], [(3, min, 0), (3, torch.max, 2), (11, max, 10), (5, "avg", 2), (5, "SUM", 10)] + ("batches", "fx", "result"), [(3, min, 0), (3, torch.max, 2), (11, max, 10), (5, "avg", 2), (5, "SUM", 10)] ) def test__training_step__log_max_reduce_fx(tmpdir, batches, fx, result): """Tests that log works correctly with different tensor types.""" @@ -343,7 +343,7 @@ def validation_step(self, batch, batch_idx): @pytest.mark.parametrize( - "devices, accelerator", + ("devices", "accelerator"), [ (1, "cpu"), (2, "cpu"), diff --git a/tests/tests_pytorch/trainer/optimization/test_optimizers.py b/tests/tests_pytorch/trainer/optimization/test_optimizers.py index d824117eeb014..8f04664a29c5a 100644 --- a/tests/tests_pytorch/trainer/optimization/test_optimizers.py +++ b/tests/tests_pytorch/trainer/optimization/test_optimizers.py @@ -180,7 +180,8 @@ def test_optimizer_return_options(tmpdir): # single optimizer model.configure_optimizers = lambda: opt_a opt, lr_sched = _init_optimizers_and_lr_schedulers(model) - assert len(opt) == 1 and len(lr_sched) == 0 + assert len(opt) == 1 + assert len(lr_sched) == 0 # opt tuple model.automatic_optimization = False @@ -461,7 +462,7 @@ def test_lr_scheduler_epoch_step_frequency(mocked_sched, check_val_every_n_epoch assert mocked_sched.call_count == expected_steps -@pytest.mark.parametrize("every_n_train_steps, epoch_interval", [(None, True), (2, False), (2, True)]) +@pytest.mark.parametrize(("every_n_train_steps", "epoch_interval"), [(None, True), (2, False), (2, True)]) def test_lr_scheduler_state_updated_before_saving(tmpdir, every_n_train_steps, epoch_interval): batches = 2 max_epochs = 1 diff --git a/tests/tests_pytorch/trainer/properties/test_estimated_stepping_batches.py b/tests/tests_pytorch/trainer/properties/test_estimated_stepping_batches.py index bf187d0cb764d..8a238923c46d9 100644 --- a/tests/tests_pytorch/trainer/properties/test_estimated_stepping_batches.py +++ b/tests/tests_pytorch/trainer/properties/test_estimated_stepping_batches.py @@ -93,7 +93,7 @@ def test_num_stepping_batches_with_max_steps(max_steps): assert trainer.estimated_stepping_batches == max_steps -@pytest.mark.parametrize("accumulate_grad_batches,expected_steps", [(2, 32), (3, 22)]) +@pytest.mark.parametrize(("accumulate_grad_batches", "expected_steps"), [(2, 32), (3, 22)]) def test_num_stepping_batches_accumulate_gradients(accumulate_grad_batches, expected_steps): """Test the total stepping batches when accumulation grad batches is configured.""" trainer = Trainer(max_epochs=1, accumulate_grad_batches=accumulate_grad_batches) @@ -105,7 +105,7 @@ def test_num_stepping_batches_accumulate_gradients(accumulate_grad_batches, expe @RunIf(mps=False) @pytest.mark.parametrize( - ["trainer_kwargs", "estimated_steps"], + ("trainer_kwargs", "estimated_steps"), [ ({"strategy": "ddp", "num_nodes": 1}, 10), ({"strategy": "ddp", "num_nodes": 2}, 5), diff --git a/tests/tests_pytorch/trainer/test_dataloaders.py b/tests/tests_pytorch/trainer/test_dataloaders.py index 0eb79c343bb44..7287569988c9d 100644 --- a/tests/tests_pytorch/trainer/test_dataloaders.py +++ b/tests/tests_pytorch/trainer/test_dataloaders.py @@ -276,7 +276,7 @@ def test_inf_dataloaders_with_limit_percent_batches(tmpdir): @pytest.mark.parametrize( - ["dataset", "limit_train_batches"], + ("dataset", "limit_train_batches"), [ (RandomDataset(32, 128), 10), (RandomIterableDataset(32, 128), 10), @@ -390,7 +390,7 @@ def test_datasets_dataloaders_with_limit_num_batches(tmpdir, dataset): @pytest.mark.skip() @pytest.mark.parametrize( - ["limit_train_batches", "limit_val_batches", "limit_test_batches"], + ("limit_train_batches", "limit_val_batches", "limit_test_batches"), [(1.0, 1.0, 1.0), (0.2, 0.4, 0.4)], ) def test_dataloaders_with_limit_percent_batches(tmpdir, limit_train_batches, limit_val_batches, limit_test_batches): @@ -415,7 +415,7 @@ def test_dataloaders_with_limit_percent_batches(tmpdir, limit_train_batches, lim assert trainer.num_test_batches == expected_test_batches -@pytest.mark.parametrize(["limit_train_batches", "limit_val_batches", "limit_test_batches"], [(1, 2, 3), (1, 2, 1e50)]) +@pytest.mark.parametrize(("limit_train_batches", "limit_val_batches", "limit_test_batches"), [(1, 2, 3), (1, 2, 1e50)]) def test_dataloaders_with_limit_num_batches(tmpdir, limit_train_batches, limit_val_batches, limit_test_batches): """Verify num_batches for train, val & test dataloaders passed with batch limit as number.""" model = MultiEvalDataLoaderModel() @@ -832,7 +832,7 @@ def test_dataloader_distributed_sampler_already_attached(tmpdir): @pytest.mark.parametrize( - ["mode", "num_training_batches"], + ("mode", "num_training_batches"), [("min_size", 16), ("max_size_cycle", 64), ("max_size", 64), ("sequential", 64 + 16 * 4)], ) def test_fit_multiple_train_loaders(tmpdir, mode, num_training_batches): @@ -954,8 +954,12 @@ def test_dataloaders_load_only_once_no_sanity_check(tmpdir): @pytest.mark.parametrize( ( - "num_sanity_val_steps, check_val_every_n_epoch, reload_dataloaders_every_n_epochs," - " train_reload_epochs_expect,val_reload_epochs_expect,val_step_epochs_expect" + "num_sanity_val_steps", + "check_val_every_n_epoch", + "reload_dataloaders_every_n_epochs", + "train_reload_epochs_expect", + "val_reload_epochs_expect", + "val_step_epochs_expect", ), [ # general case where sanity check reloads the dataloaders for validation on current_epoch=0 diff --git a/tests/tests_pytorch/trainer/test_trainer.py b/tests/tests_pytorch/trainer/test_trainer.py index 93f80cd2e9f1d..945b59426832a 100644 --- a/tests/tests_pytorch/trainer/test_trainer.py +++ b/tests/tests_pytorch/trainer/test_trainer.py @@ -171,7 +171,7 @@ def test_strict_model_load(monkeypatch, tmpdir, tmpdir_server, url_ckpt): @pytest.mark.parametrize( - ["accumulate_grad_batches", "limit_train_batches"], + ("accumulate_grad_batches", "limit_train_batches"), [ (3, 1.0), (3, 0.8), # not to be divisible by accumulate_grad_batches on purpose @@ -287,11 +287,12 @@ def test_loading_yaml(tmpdir): hparams_path = os.path.join(path_expt_dir, "hparams.yaml") tags = load_hparams_from_yaml(hparams_path) - assert tags["batch_size"] == 32 and tags["optimizer_name"] == "adam" + assert tags["batch_size"] == 32 + assert tags["optimizer_name"] == "adam" @pytest.mark.parametrize( - "save_top_k,save_last,expected_files", + ("save_top_k", "save_last", "expected_files"), [ pytest.param(-1, False, [f"epoch={i}.ckpt" for i in range(5)], id="CASE K=-1 (all)"), pytest.param(1, False, {"epoch=4.ckpt"}, id="CASE K=1 (2.5, epoch 4)"), @@ -495,7 +496,7 @@ def test_trainer_max_steps_and_epochs(tmpdir): @pytest.mark.parametrize( - "max_epochs,max_steps,incorrect_variable", + ("max_epochs", "max_steps", "incorrect_variable"), [ (-100, -1, "max_epochs"), (1, -2, "max_steps"), @@ -511,7 +512,7 @@ def test_trainer_max_steps_and_epochs_validation(max_epochs, max_steps, incorrec @pytest.mark.parametrize( - "max_epochs,max_steps,is_done,correct_trainer_epochs", + ("max_epochs", "max_steps", "is_done", "correct_trainer_epochs"), [ (None, -1, False, None), (-1, -1, False, -1), @@ -1223,7 +1224,7 @@ def setup(self, trainer, model, stage): assert model.stage == stage -@pytest.mark.parametrize("train_batches, max_steps, log_interval", [(10, 10, 1), (3, 10, 1), (3, 10, 5)]) +@pytest.mark.parametrize(("train_batches", "max_steps", "log_interval"), [(10, 10, 1), (3, 10, 1), (3, 10, 5)]) @patch("lightning.pytorch.loggers.tensorboard.TensorBoardLogger.log_metrics") def test_log_every_n_steps(log_metrics_mock, tmpdir, train_batches, max_steps, log_interval): class TestModel(BoringModel): @@ -1441,7 +1442,7 @@ def test_predict_return_predictions_cpu(return_predictions, precision, tmpdir): assert preds[0].dtype == (torch.float64 if precision == "64-true" else torch.float32) -@pytest.mark.parametrize(["max_steps", "max_epochs", "global_step"], [(10, 5, 10), (20, None, 20)]) +@pytest.mark.parametrize(("max_steps", "max_epochs", "global_step"), [(10, 5, 10), (20, None, 20)]) def test_repeated_fit_calls_with_max_epochs_and_steps(tmpdir, max_steps, max_epochs, global_step): """Ensure that the training loop is bound by `max_steps` and `max_epochs` for repeated calls of `trainer.fit`, and disabled if the limit is reached.""" @@ -1620,7 +1621,7 @@ def on_predict_start(self) -> None: @pytest.mark.parametrize( - "strategy,devices", [("auto", 1), pytest.param("ddp_spawn", 1, marks=RunIf(skip_windows=True))] + ("strategy", "devices"), [("auto", 1), pytest.param("ddp_spawn", 1, marks=RunIf(skip_windows=True))] ) def test_model_in_correct_mode_during_stages(tmpdir, strategy, devices): model = TrainerStagesModel() @@ -1859,7 +1860,7 @@ def training_step(self, batch, batch_idx): @pytest.mark.parametrize( - ["trainer_kwargs", "strategy_cls", "accelerator_cls", "devices"], + ("trainer_kwargs", "strategy_cls", "accelerator_cls", "devices"), [ ({"strategy": "auto"}, SingleDeviceStrategy, CPUAccelerator, 1), pytest.param({"strategy": "ddp"}, DDPStrategy, CPUAccelerator, 1, marks=RunIf(mps=False)), @@ -1968,7 +1969,7 @@ def test_dataloaders_are_not_loaded_if_disabled_through_limit_batches(running_st @pytest.mark.parametrize( - ["trainer_kwargs", "expected_device_ids"], + ("trainer_kwargs", "expected_device_ids"), [ ({}, [0]), ({"devices": 1}, [0]), diff --git a/tests/tests_pytorch/tuner/test_lr_finder.py b/tests/tests_pytorch/tuner/test_lr_finder.py index c8fba73ff636b..491f336701cfa 100644 --- a/tests/tests_pytorch/tuner/test_lr_finder.py +++ b/tests/tests_pytorch/tuner/test_lr_finder.py @@ -363,7 +363,7 @@ def test_multiple_lr_find_calls_gives_same_results(tmpdir): @pytest.mark.parametrize( - "skip_begin,skip_end,losses,expected_error", + ("skip_begin", "skip_end", "losses", "expected_error"), [ (0, 0, [], True), (10, 1, [], True), diff --git a/tests/tests_pytorch/tuner/test_scale_batch_size.py b/tests/tests_pytorch/tuner/test_scale_batch_size.py index 31ad3a6c6bd46..1e35ba2a9ec59 100644 --- a/tests/tests_pytorch/tuner/test_scale_batch_size.py +++ b/tests/tests_pytorch/tuner/test_scale_batch_size.py @@ -58,7 +58,7 @@ def predict_dataloader(self): return DataLoader(RandomDataset(32, 64), batch_size=getattr(self, "batch_size", 1)) -@pytest.mark.parametrize(["model_bs", "dm_bs"], [(2, -1), (2, 2), (2, None), (None, 2), (16, 16)]) +@pytest.mark.parametrize(("model_bs", "dm_bs"), [(2, -1), (2, 2), (2, None), (None, 2), (16, 16)]) def test_scale_batch_size_method_with_model_or_datamodule(tmpdir, model_bs, dm_bs): """Test the tuner method `Tuner.scale_batch_size` with a datamodule.""" trainer = Trainer(default_root_dir=tmpdir, limit_train_batches=1, limit_val_batches=0, max_epochs=1) @@ -449,7 +449,7 @@ def val_dataloader(self): tuner.scale_batch_size(model, method="validate") -@pytest.mark.parametrize("scale_method, expected_batch_size", [("power", 62), ("binsearch", 100)]) +@pytest.mark.parametrize(("scale_method", "expected_batch_size"), [("power", 62), ("binsearch", 100)]) @patch("lightning.pytorch.tuner.batch_size_scaling.is_oom_error", return_value=True) def test_dataloader_batch_size_updated_on_failure(_, tmpdir, scale_method, expected_batch_size): class CustomBatchSizeModel(BatchSizeModel): diff --git a/tests/tests_pytorch/utilities/migration/test_migration.py b/tests/tests_pytorch/utilities/migration/test_migration.py index 9c373ad1b6259..99c11205c2d08 100644 --- a/tests/tests_pytorch/utilities/migration/test_migration.py +++ b/tests/tests_pytorch/utilities/migration/test_migration.py @@ -26,7 +26,7 @@ @pytest.mark.parametrize( - "old_checkpoint, new_checkpoint", + ("old_checkpoint", "new_checkpoint"), [ ( {"epoch": 1, "global_step": 23, "checkpoint_callback_best": 0.34}, diff --git a/tests/tests_pytorch/utilities/test_combined_loader.py b/tests/tests_pytorch/utilities/test_combined_loader.py index 26f7e5359b882..f8425f5c676a3 100644 --- a/tests/tests_pytorch/utilities/test_combined_loader.py +++ b/tests/tests_pytorch/utilities/test_combined_loader.py @@ -39,7 +39,7 @@ @pytest.mark.parametrize( - ["dataset_1", "dataset_2"], + ("dataset_1", "dataset_2"), [ ([list(range(10)), list(range(20))]), ([range(10), range(20)]), diff --git a/tests/tests_pytorch/utilities/test_grads.py b/tests/tests_pytorch/utilities/test_grads.py index f4b5ee2d035fb..ede504bba713f 100644 --- a/tests/tests_pytorch/utilities/test_grads.py +++ b/tests/tests_pytorch/utilities/test_grads.py @@ -22,7 +22,7 @@ @pytest.mark.parametrize( - "norm_type,expected", + ("norm_type", "expected"), [ ( 1, diff --git a/tests/tests_pytorch/utilities/test_imports.py b/tests/tests_pytorch/utilities/test_imports.py index 0abb271caad19..a5e55518346db 100644 --- a/tests/tests_pytorch/utilities/test_imports.py +++ b/tests/tests_pytorch/utilities/test_imports.py @@ -61,7 +61,7 @@ def new_fn(*args, **kwargs): return new_fn -@pytest.fixture +@pytest.fixture() def clean_import(): """This fixture allows test to import {pytorch_}lightning* modules completely cleanly, regardless of the current state of the imported modules. @@ -80,7 +80,7 @@ def clean_import(): @pytest.mark.parametrize( - ["patch_name", "new_fn", "to_import"], + ("patch_name", "new_fn", "to_import"), [ ("torch.distributed.is_available", _shortcut_patch(is_available, ()), "lightning.pytorch"), ( diff --git a/tests/tests_pytorch/utilities/test_model_summary.py b/tests/tests_pytorch/utilities/test_model_summary.py index 7bb4ccf6258be..2e1f6b33613ee 100644 --- a/tests/tests_pytorch/utilities/test_model_summary.py +++ b/tests/tests_pytorch/utilities/test_model_summary.py @@ -246,7 +246,7 @@ def test_summary_with_scripted_modules(max_depth): @pytest.mark.parametrize("max_depth", [-1, 1]) @pytest.mark.parametrize( - ["example_input", "expected_size"], + ("example_input", "expected_size"), [ ([], UNKNOWN_SIZE), ((1, 2, 3), [UNKNOWN_SIZE] * 3), diff --git a/tests/tests_pytorch/utilities/test_parameter_tying.py b/tests/tests_pytorch/utilities/test_parameter_tying.py index 5910feec1961d..e45fb39f81b34 100644 --- a/tests/tests_pytorch/utilities/test_parameter_tying.py +++ b/tests/tests_pytorch/utilities/test_parameter_tying.py @@ -35,7 +35,7 @@ def forward(self, x): @pytest.mark.parametrize( - ["model", "expected_shared_params"], + ("model", "expected_shared_params"), [(BoringModel, []), (ParameterSharingModule, [["layer_1.weight", "layer_3.weight"]])], ) def test_find_shared_parameters(model, expected_shared_params): diff --git a/tests/tests_pytorch/utilities/test_warnings.py b/tests/tests_pytorch/utilities/test_warnings.py index 3757d804ae147..78f0570ee2947 100644 --- a/tests/tests_pytorch/utilities/test_warnings.py +++ b/tests/tests_pytorch/utilities/test_warnings.py @@ -27,7 +27,8 @@ root_logger = logging.getLogger() lightning_logger = logging.getLogger("lightning.pytorch") # should have a `StreamHandler` - assert lightning_logger.hasHandlers() and len(lightning_logger.handlers) == 1 + assert lightning_logger.hasHandlers() + assert len(lightning_logger.handlers) == 1 # set our own stream for testing handler = lightning_logger.handlers[0] assert isinstance(handler, logging.StreamHandler) From bdf00f9b6ad7cf7840de30a2961721bc8905ab04 Mon Sep 17 00:00:00 2001 From: Jirka Borovec <6035284+Borda@users.noreply.github.com> Date: Thu, 4 May 2023 17:51:10 +0200 Subject: [PATCH 10/11] update tags in bug issue (#17551) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .github/ISSUE_TEMPLATE/1_bug_report.yaml | 10 +++++----- .github/advanced-issue-labeler.yml | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/1_bug_report.yaml b/.github/ISSUE_TEMPLATE/1_bug_report.yaml index 15bd473f9e1fb..fb79592e57447 100644 --- a/.github/ISSUE_TEMPLATE/1_bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/1_bug_report.yaml @@ -32,11 +32,11 @@ body: description: select all version where you have experienced this issue multiple: true options: - - "v1_6" - - "v1_7" - - "v1_8" - - "v1_9" - - "v2_0" + - "v1.6" + - "v1.7" + - "v1.8" + - "v1.9" + - "v2.0" - "master" validations: required: true diff --git a/.github/advanced-issue-labeler.yml b/.github/advanced-issue-labeler.yml index a9c5dd8425529..e958c3f892515 100644 --- a/.github/advanced-issue-labeler.yml +++ b/.github/advanced-issue-labeler.yml @@ -6,14 +6,14 @@ policy: - id: ['versions'] label: - name: "ver: 1.6.x" - keys: ['v1_6'] + keys: ['v1_6', 'v1.6', '1.6.x'] - name: "ver: 1.7.x" - keys: ['v1_7'] + keys: ['v1_7', 'v1.7', '1.7.x'] - name: "ver: 1.8.x" - keys: ['v1_8'] + keys: ['v1_8', 'v1.8', '1.8.x'] - name: "ver: 1.9.x" - keys: ['v1_9'] + keys: ['v1_9', 'v1.9', '1.9.x'] - name: "ver: 2.0.x" - keys: ['v2_0'] + keys: ['v2_0', 'v2.0', '2.0+'] - name: "ver: 2.1.x" keys: ['master'] From 968693ad0630a9184352c17e461178f1fb2db52f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mochol=C3=AD?= Date: Thu, 4 May 2023 18:40:42 +0200 Subject: [PATCH 11/11] Remove duplicate import checks (#16648) --- requirements/collect_env_details.py | 1 + src/lightning/fabric/utilities/imports.py | 2 +- .../trainer/connectors/accelerator_connector.py | 3 --- src/lightning/pytorch/trainer/setup.py | 15 +++++++-------- src/lightning/pytorch/utilities/imports.py | 17 ----------------- .../pytorch/utilities/testing/_runif.py | 9 +-------- 6 files changed, 10 insertions(+), 37 deletions(-) diff --git a/requirements/collect_env_details.py b/requirements/collect_env_details.py index df0db8dd1f2c6..3dd2b8d642f5d 100644 --- a/requirements/collect_env_details.py +++ b/requirements/collect_env_details.py @@ -35,6 +35,7 @@ def info_system() -> dict: "OS": platform.system(), "architecture": platform.architecture(), "version": platform.version(), + "release": platform.release(), "processor": platform.processor(), "python": platform.python_version(), } diff --git a/src/lightning/fabric/utilities/imports.py b/src/lightning/fabric/utilities/imports.py index bdf3d6f3b34c6..d4a1cb029ea36 100644 --- a/src/lightning/fabric/utilities/imports.py +++ b/src/lightning/fabric/utilities/imports.py @@ -27,6 +27,6 @@ _TORCH_GREATER_EQUAL_1_12 = compare_version("torch", operator.ge, "1.12.0") _TORCH_GREATER_EQUAL_1_13 = compare_version("torch", operator.ge, "1.13.0") -_TORCH_GREATER_EQUAL_2_0 = compare_version("torch", operator.ge, "2.0.0", use_base_version=True) +_TORCH_GREATER_EQUAL_2_0 = compare_version("torch", operator.ge, "2.0.0") _TORCH_GREATER_EQUAL_2_1 = compare_version("torch", operator.ge, "2.1.0", use_base_version=True) _TORCH_EQUAL_2_0 = _TORCH_GREATER_EQUAL_2_0 and not _TORCH_GREATER_EQUAL_2_1 diff --git a/src/lightning/pytorch/trainer/connectors/accelerator_connector.py b/src/lightning/pytorch/trainer/connectors/accelerator_connector.py index 4d78fdd57a292..251c77a4e0114 100644 --- a/src/lightning/pytorch/trainer/connectors/accelerator_connector.py +++ b/src/lightning/pytorch/trainer/connectors/accelerator_connector.py @@ -416,9 +416,6 @@ def _choose_and_init_cluster_environment(self) -> ClusterEnvironment: def _choose_strategy(self) -> Union[Strategy, str]: if self._accelerator_flag == "ipu": - # TODO: Why would we block someone from using a IPU capable machine without graphcore? - # Don't these machines also have a regular CPU? - if not _LIGHTNING_GRAPHCORE_AVAILABLE: raise ImportError( "You have passed `accelerator='ipu'` but the IPU integration is not installed." diff --git a/src/lightning/pytorch/trainer/setup.py b/src/lightning/pytorch/trainer/setup.py index 8f137a9e7dd55..36f9c27e70983 100644 --- a/src/lightning/pytorch/trainer/setup.py +++ b/src/lightning/pytorch/trainer/setup.py @@ -28,12 +28,7 @@ XLAProfiler, ) from lightning.pytorch.utilities.exceptions import MisconfigurationException -from lightning.pytorch.utilities.imports import ( - _HPU_AVAILABLE, - _IPU_AVAILABLE, - _LIGHTNING_GRAPHCORE_AVAILABLE, - _LIGHTNING_HABANA_AVAILABLE, -) +from lightning.pytorch.utilities.imports import _LIGHTNING_GRAPHCORE_AVAILABLE, _LIGHTNING_HABANA_AVAILABLE from lightning.pytorch.utilities.rank_zero import rank_zero_info, rank_zero_warn @@ -167,17 +162,21 @@ def _log_device_info(trainer: "pl.Trainer") -> None: from lightning_graphcore import IPUAccelerator num_ipus = trainer.num_devices if isinstance(trainer.accelerator, IPUAccelerator) else 0 + ipu_available = IPUAccelerator.is_available() else: num_ipus = 0 - rank_zero_info(f"IPU available: {_IPU_AVAILABLE}, using: {num_ipus} IPUs") + ipu_available = False + rank_zero_info(f"IPU available: {ipu_available}, using: {num_ipus} IPUs") if _LIGHTNING_HABANA_AVAILABLE: from lightning_habana import HPUAccelerator num_hpus = trainer.num_devices if isinstance(trainer.accelerator, HPUAccelerator) else 0 + hpu_available = HPUAccelerator.is_available() else: num_hpus = 0 - rank_zero_info(f"HPU available: {_HPU_AVAILABLE}, using: {num_hpus} HPUs") + hpu_available = False + rank_zero_info(f"HPU available: {hpu_available}, using: {num_hpus} HPUs") if ( CUDAAccelerator.is_available() diff --git a/src/lightning/pytorch/utilities/imports.py b/src/lightning/pytorch/utilities/imports.py index 7992a9de91950..a28c2dd276465 100644 --- a/src/lightning/pytorch/utilities/imports.py +++ b/src/lightning/pytorch/utilities/imports.py @@ -25,25 +25,8 @@ _KINETO_AVAILABLE = torch.profiler.kineto_available() _OMEGACONF_AVAILABLE = package_available("omegaconf") -_POPTORCH_AVAILABLE = package_available("poptorch") _TORCHVISION_AVAILABLE = RequirementCache("torchvision") _LIGHTNING_COLOSSALAI_AVAILABLE = RequirementCache("lightning-colossalai") _LIGHTNING_BAGUA_AVAILABLE = RequirementCache("lightning-bagua") _LIGHTNING_HABANA_AVAILABLE = RequirementCache("lightning-habana") _LIGHTNING_GRAPHCORE_AVAILABLE = RequirementCache("lightning-graphcore") - -if _POPTORCH_AVAILABLE: - import poptorch - - _IPU_AVAILABLE = poptorch.ipuHardwareIsAvailable() -else: - _IPU_AVAILABLE = False - - -_HABANA_FRAMEWORK_AVAILABLE = package_available("habana_frameworks") -if _HABANA_FRAMEWORK_AVAILABLE: - from habana_frameworks.torch.utils.library_loader import is_habana_available - - _HPU_AVAILABLE = is_habana_available() -else: - _HPU_AVAILABLE = False diff --git a/src/lightning/pytorch/utilities/testing/_runif.py b/src/lightning/pytorch/utilities/testing/_runif.py index 27477248175b4..48e2536be0bfa 100644 --- a/src/lightning/pytorch/utilities/testing/_runif.py +++ b/src/lightning/pytorch/utilities/testing/_runif.py @@ -28,7 +28,7 @@ from lightning.pytorch.callbacks.progress.rich_progress import _RICH_AVAILABLE from lightning.pytorch.core.module import _ONNX_AVAILABLE from lightning.pytorch.strategies.deepspeed import _DEEPSPEED_AVAILABLE -from lightning.pytorch.utilities.imports import _IPU_AVAILABLE, _OMEGACONF_AVAILABLE +from lightning.pytorch.utilities.imports import _OMEGACONF_AVAILABLE _SKLEARN_AVAILABLE = RequirementCache("scikit-learn") @@ -40,7 +40,6 @@ def _RunIf( min_python: Optional[str] = None, bf16_cuda: bool = False, tpu: bool = False, - ipu: bool = False, mps: Optional[bool] = None, skip_windows: bool = False, standalone: bool = False, @@ -132,12 +131,6 @@ def test_wrapper(arg1): # used in conftest.py::pytest_collection_modifyitems kwargs["tpu"] = True - if ipu: - conditions.append(not _IPU_AVAILABLE) - reasons.append("IPU") - # used in conftest.py::pytest_collection_modifyitems - kwargs["ipu"] = True - if mps is not None: if mps: conditions.append(not MPSAccelerator.is_available())