Repository: Lightning-AI/pytorch-lightning
File: src/lightning/fabric/fabric.py (Python)

Code before:
        Example::

            # Single optimizer
            optimizer = fabric.setup_optimizers(optimizer)

            # Multiple optimizers
            opt1, opt2 = fabric.setup_optimizers(opt1, opt2)

        """
        self._validate_setup_optimizers(optimizers)
        optimizers = [self._strategy.setup_optimizer(optimizer) for optimizer in optimizers]
        optimizers = [
            _FabricOptimizer(optimizer=optimizer, strategy=self._strategy, callbacks=self._callbacks)
            for optimizer in optimizers
        ]
        return optimizers[0] if len(optimizers) == 1 else tuple(optimizers)

    def setup_dataloaders(
        self, *dataloaders: DataLoader, use_distributed_sampler: bool = True, move_to_device: bool = True
    ) -> Union[DataLoader, list[DataLoader]]:
        r"""Set up one or multiple dataloaders for accelerated training. If you need different settings for each
        dataloader, call this method individually for each one.

        Args:
            *dataloaders: One or more PyTorch :class:`~torch.utils.data.DataLoader` instances to set up.
                Must provide at least one dataloader.
            use_distributed_sampler: If set ``True`` (default), automatically wraps or replaces the sampler on the
                dataloader(s) for distributed training. If you have a custom sampler defined, set this argument
                to ``False``.
            move_to_device: If set ``True`` (default), moves the data returned by the dataloader(s) automatically to
                the correct device. Set this to ``False`` and alternatively use :meth:`to_device` manually on the
                returned data.

        Returns:
            If a single dataloader is passed, returns the wrapped dataloader. If multiple dataloaders are passed,
            returns a list of wrapped dataloaders in the same order they were passed in.

        Example::

            # Single dataloader
            train_loader = fabric.setup_dataloaders(train_loader)

            # Multiple dataloaders
            train_loader, val_loader = fabric.setup_dataloaders(train_loader, val_loader)

        """
        self._validate_setup_dataloaders(dataloaders)
        dataloaders = [
            self._setup_dataloader(
                dataloader, use_distributed_sampler=use_distributed_sampler, move_to_device=move_to_device
            )

Review comment (suggestion):
The documentation states 'Must provide at least one dataloader' but the method signature `*dataloaders` allows zero dataloaders. This inconsistency should be clarified - either the signature should be updated to require at least one dataloader, or the documentation should reflect that zero dataloaders are allowed.

Code after:

            # Single optimizer
            optimizer = fabric.setup_optimizers(optimizer)

            # Multiple optimizers
            opt1, opt2 = fabric.setup_optimizers(opt1, opt2)

        """
        self._validate_setup_optimizers(optimizers)
        optimizers = [self._strategy.setup_optimizer(optimizer) for optimizer in optimizers]
        optimizers = [
            _FabricOptimizer(optimizer=optimizer, strategy=self._strategy, callbacks=self._callbacks)
            for optimizer in optimizers
        ]
        return optimizers[0] if len(optimizers) == 1 else tuple(optimizers)

    def setup_dataloaders(
        self, *dataloaders: DataLoader, use_distributed_sampler: bool = True, move_to_device: bool = True
    ) -> Union[DataLoader, list[DataLoader]]:
        r"""Set up one or multiple dataloaders for accelerated training. If you need different settings for each
        dataloader, call this method individually for each one.

        Args:
            *dataloaders: One or more PyTorch :class:`~torch.utils.data.DataLoader` instances to set up.
            use_distributed_sampler: If set ``True`` (default), automatically wraps or replaces the sampler on the
                dataloader(s) for distributed training. If you have a custom sampler defined, set this argument
                to ``False``.
            move_to_device: If set ``True`` (default), moves the data returned by the dataloader(s) automatically to
                the correct device. Set this to ``False`` and alternatively use :meth:`to_device` manually on the
                returned data.

        Returns:
            If a single dataloader is passed, returns the wrapped dataloader. If multiple dataloaders are passed,
            returns a list of wrapped dataloaders in the same order they were passed in.

        Example::

            # Single dataloader
            train_loader = fabric.setup_dataloaders(train_loader)

            # Multiple dataloaders
            train_loader, val_loader = fabric.setup_dataloaders(train_loader, val_loader)

        """
        self._validate_setup_dataloaders(dataloaders)
        dataloaders = [
            self._setup_dataloader(
                dataloader, use_distributed_sampler=use_distributed_sampler, move_to_device=move_to_device
            )
            for dataloader in dataloaders
        ]