Repository: huggingface/accelerate
Pull request: Fix prod issues
# What does this PR do?

Fixes an issue caused by https://github.com/huggingface/accelerate/pull/3420 where said code only works if we're on torch 2.6+. Used a `hasattr` check instead here to make it work. 

Fixes https://github.com/huggingface/accelerate/issues/3438

(Did a new PR since the old one had outdated main).

I'll do a secondary patch with these fixes once merged


## Before submitting
- [ ] This PR fixes a typo or improves the docs (you can dismiss the other checks if that's the case).
- [ ] Did you read the [contributor guideline](https://github.com/huggingface/accelerate/blob/main/CONTRIBUTING.md#submitting-a-pull-request-pr),
      Pull Request section?
- [ ] Was this discussed/approved via a Github issue or the [forum](https://discuss.huggingface.co/)? Please add a link
      to it if that's the case.
- [ ] Did you make sure to update the documentation with your changes? Here are the
      [documentation guidelines](https://github.com/huggingface/accelerate/tree/main/docs), and
      [here are tips on formatting docstrings](https://github.com/huggingface/accelerate/tree/main/docs#writing-documentation---specification).
- [ ] Did you write any new necessary tests?


## Who can review?

Anyone in the community is free to review the PR once the tests have passed. Feel free to tag
members/contributors who may be interested in your PR.

@SunMarc @BenjaminBossan @IlyasMoutawwakil 

Problem statement:
Version 1.5.0 explicitly depends on pytest
# Issue
Using the latest release (v1.5.0) I get a `ModuleNotFoundError: No module named 'pytest'` when launching any script with `accelerate launch` if pytest is not installed in the virtual environment.

Using v1.4.0 everything works fine, and I think this is the expected behavior.

# Reproducibility
I run
`uv run accelerate launch hello.py`
with the following files:

**hello.py**
```hello.py
def main():
    print("Hello from temp!")


if __name__ == "__main__":
    main()
```

**pyproject.toml**
```
[project]
name = "temp"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
    "accelerate>=1.5.0",
]
```

The resulting full traceback:
```
  File "/home/ssm-user/temp/.venv/bin/accelerate", line 4, in <module>
    from accelerate.commands.accelerate_cli import main
  File "/home/ssm-user/temp/.venv/lib/python3.13/site-packages/accelerate/commands/accelerate_cli.py", line 22, in <module>
    from accelerate.commands.test import test_command_parser
  File "/home/ssm-user/temp/.venv/lib/python3.13/site-packages/accelerate/commands/test.py", line 19, in <module>
    from accelerate.test_utils import execute_subprocess_async, path_in_accelerate_package
  File "/home/ssm-user/temp/.venv/lib/python3.13/site-packages/accelerate/test_utils/__init__.py", line 14, in <module>
    from .testing import (
    ...<43 lines>...
    )
  File "/home/ssm-user/temp/.venv/lib/python3.13/site-packages/accelerate/test_utils/testing.py", line 30, in <module>
    import pytest
ModuleNotFoundError: No module named 'pytest'
```

Hints from issue discussion:
Thanks for flagging, should be fixed now with 1.5.1. Can you confirm?
Yes, v1.5.1 fixes this. Thanks @muellerzr!

Closing the issue 😄

Commit message: Fix default device

Patch to review:
diff --git a/src/accelerate/data_loader.py b/src/accelerate/data_loader.py
index 150d576a685..43f409ff12c 100644
--- a/src/accelerate/data_loader.py
+++ b/src/accelerate/data_loader.py
@@ -89,7 +89,9 @@ def __init__(self, *args, **kwargs):
 
     def __iter__(self):
         if self.generator is None:
-            self.generator = torch.Generator(device=torch.get_default_device())
+            self.generator = torch.Generator(
+                device=torch.get_default_device() if hasattr(torch, "get_default_device") else None
+            )
             self.generator.manual_seed(self.initial_seed)
 
         # Allow `self.epoch` to modify the seed of the generator
@@ -1167,13 +1169,19 @@ def prepare_data_loader(
             data_source=sampler.data_source,
             replacement=sampler.replacement,
             num_samples=sampler._num_samples,
-            generator=getattr(sampler, "generator", torch.Generator(device=torch.get_default_device())),
+            generator=getattr(
+                sampler,
+                "generator",
+                torch.Generator(device=torch.get_default_device() if hasattr(torch, "get_default_device") else None),
+            ),
             data_seed=data_seed,
         )
 
     if isinstance(dataloader.sampler, RandomSampler) and state.distributed_type == DistributedType.XLA:
         # isinstance(dataloader.sampler, RandomSampler) indicates the original dataloader has `shuffle` enabled.
-        generator = torch.Generator(device=torch.get_default_device()).manual_seed(42)
+        generator = torch.Generator(
+            device=torch.get_default_device() if hasattr(torch, "get_default_device") else None
+        ).manual_seed(42)
         dataloader.generator = generator
         dataloader.sampler.generator = generator
     # No change if no multiprocess
@@ -1192,7 +1200,9 @@ def prepare_data_loader(
         else:
             if not use_seedable_sampler and hasattr(sampler, "generator"):
                 if sampler.generator is None:
-                    sampler.generator = torch.Generator(device=torch.get_default_device())
+                    sampler.generator = torch.Generator(
+                        device=torch.get_default_device() if hasattr(torch, "get_default_device") else None
+                    )
                 synchronized_generator = sampler.generator
             batch_sampler = dataloader.sampler if sampler_is_batch_sampler else dataloader.batch_sampler
             new_batch_sampler = BatchSamplerShard(
diff --git a/src/accelerate/test_utils/testing.py b/src/accelerate/test_utils/testing.py
index 3eb715648e3..0cdd3eea79e 100644
--- a/src/accelerate/test_utils/testing.py
+++ b/src/accelerate/test_utils/testing.py
@@ -27,7 +27,6 @@
 from typing import List, Union
 from unittest import mock
 
-import pytest
 import torch
 
 import accelerate
@@ -56,6 +55,7 @@
     is_npu_available,
     is_pandas_available,
     is_pippy_available,
+    is_pytest_available,
     is_schedulefree_available,
     is_sdaa_available,
     is_tensorboard_available,
@@ -548,8 +548,15 @@ def run_first(test_case):
     This is especially useful in some test settings like on a Gaudi instance where a Gaudi device can only be used by a
     single process at a time. So we make sure all tests that run in a subprocess are launched first, to avoid device
     allocation conflicts.
+
+    If pytest is not installed, test will be returned as is.
     """
-    return pytest.mark.order(1)(test_case)
+
+    if is_pytest_available():
+        import pytest
+
+        return pytest.mark.order(1)(test_case)
+    return test_case
 
 
 class TempDirTestCase(unittest.TestCase):


Code review comments:
diff_hunk: @@ -89,7 +89,9 @@ def __init__(self, *args, **kwargs):
 
     def __iter__(self):
         if self.generator is None:
-            self.generator = torch.Generator(device=torch.get_default_device())
+            self.generator = torch.Generator(
+                device=torch.get_default_device() if hasattr(torch, "get_default_device") else None
path: src/accelerate/data_loader.py
text: @user1:
Note that according to the [docs](https://pytorch.org/docs/stable/generated/torch.Generator.html), the default value of `device` for `Generator` is `"cpu"`. Maybe `None` would also work but I think `"cpu"` is the safer bet.