



"""simple docstring"""




import inspect
import unittest

import torch
import torch.nn as nn

from accelerate.hooks import (
    AlignDevicesHook,
    ModelHook,
    SequentialHook,
    add_hook_to_module,
    attach_align_device_hook,
    remove_hook_from_module,
    remove_hook_from_submodules,
)
from accelerate.test_utils import require_multi_gpu






class       UpperCAmelCase_    (							nn.Module		):



      def __init__(	self	:      str		):
           super().__init__()
           _UpperCAmelCase     :      Dict														=       nn.Linear(3	,      4		)
           _UpperCAmelCase     :      Optional[Any]														=       nn.BatchNormad(4		)
           _UpperCAmelCase     :      Optional[Any]														=       nn.Linear(4	,      5		)



      def 		snake_case_   (	self	:      int	,      A	:      Tuple		):
           return self.lineara(self.batchnorm(self.lineara(A		)		)		)







class       UpperCAmelCase_    (							_UpperCamelCase		):



      def 		snake_case_   (	self	:      Optional[int]	,      A	:      List[Any]	,      *A	:      Any	,      **A	:      List[str]		):
           return (args[0] + 1,) + args[1:], kwargs







class       UpperCAmelCase_    (							_UpperCamelCase		):



      def 		snake_case_   (	self	:      Union[str, Any]	,      A	:      int	,      A	:      str		):
           return output + 1







class       UpperCAmelCase_    (							unittest.TestCase		):



      def 		snake_case_   (	self	:      int		):
           _UpperCAmelCase     :      int														=       ModelForTest()
           _UpperCAmelCase     :      List[Any]														=       ModelHook()

           add_hook_to_module(A	,      A		)
           self.assertEqual(test_model._hf_hook	,      A		)
           self.assertTrue(hasattr(A	,      "_old_forward"		)		)

           # Check adding the hook did not change the name or the signature
           self.assertEqual(test_model.forward.__name__	,      "forward"		)
           self.assertListEqual(list(inspect.signature(test_model.forward		).parameters		)	,      ["x"]		)

           remove_hook_from_module(A		)
           self.assertFalse(hasattr(A	,      "_hf_hook"		)		)
           self.assertFalse(hasattr(A	,      "_old_forward"		)		)



      def 		snake_case_   (	self	:      List[Any]		):
           _UpperCAmelCase     :      List[str]														=       ModelForTest()
           _UpperCAmelCase     :      List[str]														=       ModelHook()

           add_hook_to_module(A	,      A		)
           add_hook_to_module(A	,      A	,      append=A		)

           self.assertEqual(isinstance(test_model._hf_hook	,      A		)	,      A		)
           self.assertEqual(len(test_model._hf_hook.hooks		)	,      2		)
           self.assertTrue(hasattr(A	,      "_old_forward"		)		)

           # Check adding the hook did not change the name or the signature
           self.assertEqual(test_model.forward.__name__	,      "forward"		)
           self.assertListEqual(list(inspect.signature(test_model.forward		).parameters		)	,      ["x"]		)

           remove_hook_from_module(A		)
           self.assertFalse(hasattr(A	,      "_hf_hook"		)		)
           self.assertFalse(hasattr(A	,      "_old_forward"		)		)



      def 		snake_case_   (	self	:      List[Any]		):
           _UpperCAmelCase     :      str														=       ModelForTest()
           _UpperCAmelCase     :      int														=       torch.randn(2	,      3		)
           _UpperCAmelCase     :      int														=       test_model(x + 1		)
           _UpperCAmelCase     :      List[Any]														=       test_model(x + 2		)

           _UpperCAmelCase     :      Tuple														=       PreForwardHook()
           add_hook_to_module(A	,      A		)
           _UpperCAmelCase     :      Dict														=       test_model(A		)
           self.assertTrue(torch.allclose(A	,      A	,      atol=1e-5		)		)

           # Attaching a hook to a model when it already has one replaces, does not chain
           _UpperCAmelCase     :      str														=       PreForwardHook()
           add_hook_to_module(A	,      A		)
           _UpperCAmelCase     :      Union[str, Any]														=       test_model(A		)
           self.assertTrue(torch.allclose(A	,      A	,      atol=1e-5		)		)

           # You need to use the sequential hook to chain two or more hooks
           _UpperCAmelCase     :      Dict														=       SequentialHook(PreForwardHook()	,      PreForwardHook()		)
           add_hook_to_module(A	,      A		)

           _UpperCAmelCase     :      Union[str, Any]														=       test_model(A		)
           assert torch.allclose(A	,      A	,      atol=1e-5		)



      def 		snake_case_   (	self	:      List[Any]		):
           _UpperCAmelCase     :      Union[str, Any]														=       ModelForTest()
           _UpperCAmelCase     :      Any														=       torch.randn(2	,      3		)
           _UpperCAmelCase     :      Dict														=       test_model(A		)

           _UpperCAmelCase     :      Dict														=       PostForwardHook()
           add_hook_to_module(A	,      A		)
           _UpperCAmelCase     :      Optional[Any]														=       test_model(A		)
           self.assertTrue(torch.allclose(A	,      output + 1	,      atol=1e-5		)		)

           # Attaching a hook to a model when it already has one replaces, does not chain
           _UpperCAmelCase     :      Dict														=       PostForwardHook()
           add_hook_to_module(A	,      A		)
           _UpperCAmelCase     :      int														=       test_model(A		)
           self.assertTrue(torch.allclose(A	,      output + 1	,      atol=1e-5		)		)

           # You need to use the sequential hook to chain two or more hooks
           _UpperCAmelCase     :      Optional[int]														=       SequentialHook(PostForwardHook()	,      PostForwardHook()		)
           add_hook_to_module(A	,      A		)

           _UpperCAmelCase     :      Optional[int]														=       test_model(A		)
           assert torch.allclose(A	,      output + 2	,      atol=1e-5		)



      def 		snake_case_   (	self	:      Tuple		):
           _UpperCAmelCase     :      Optional[int]														=       ModelForTest()
           _UpperCAmelCase     :      str														=       torch.randn(2	,      3		)
           _UpperCAmelCase     :      List[Any]														=       test_model(A		)

           _UpperCAmelCase     :      Tuple														=       PostForwardHook()
           add_hook_to_module(A	,      A		)
           _UpperCAmelCase     :      int														=       test_model(A		)
           self.assertTrue(torch.allclose(A	,      output + 1		)		)
           self.assertTrue(outputa.requires_grad		)

           _UpperCAmelCase     :      Any														=       True
           _UpperCAmelCase     :      Any														=       test_model(A		)
           self.assertFalse(outputa.requires_grad		)



      @require_multi_gpu
      def 		snake_case_   (	self	:      Optional[Any]		):
           _UpperCAmelCase     :      Optional[Any]														=       ModelForTest()
           # Everything is on CPU
           self.assertEqual(model.lineara.weight.device	,      torch.device("cpu"		)		)
           self.assertEqual(model.batchnorm.weight.device	,      torch.device("cpu"		)		)
           self.assertEqual(model.lineara.weight.device	,      torch.device("cpu"		)		)

           # This will move each submodule on different devices
           add_hook_to_module(model.lineara	,      AlignDevicesHook(execution_device=0		)		)
           add_hook_to_module(model.batchnorm	,      AlignDevicesHook(execution_device=0		)		)
           add_hook_to_module(model.lineara	,      AlignDevicesHook(execution_device=1		)		)

           self.assertEqual(model.lineara.weight.device	,      torch.device(0		)		)
           self.assertEqual(model.batchnorm.weight.device	,      torch.device(0		)		)
           self.assertEqual(model.batchnorm.running_mean.device	,      torch.device(0		)		)
           self.assertEqual(model.lineara.weight.device	,      torch.device(1		)		)

           # We can still make a forward pass. The input does not need to be on any particular device
           _UpperCAmelCase     :      Dict														=       torch.randn(2	,      3		)
           _UpperCAmelCase     :      Optional[Any]														=       model(A		)
           self.assertEqual(output.device	,      torch.device(1		)		)

           # We can add a general hook to put back output on same device as input.
           add_hook_to_module(A	,      AlignDevicesHook(io_same_device=A		)		)
           _UpperCAmelCase     :      Optional[Any]														=       torch.randn(2	,      3		).to(0		)
           _UpperCAmelCase     :      int														=       model(A		)
           self.assertEqual(output.device	,      torch.device(0		)		)



      def 		snake_case_   (	self	:      Tuple		):
           _UpperCAmelCase     :      Tuple														=       ModelForTest()

           # Everything is on CPU
           self.assertEqual(model.lineara.weight.device	,      torch.device("cpu"		)		)
           self.assertEqual(model.batchnorm.weight.device	,      torch.device("cpu"		)		)
           self.assertEqual(model.lineara.weight.device	,      torch.device("cpu"		)		)

           # This will move each submodule on different devices
           _UpperCAmelCase     :      int														=       {"execution_device": 0 if torch.cuda.is_available() else "cpu", "offload": True}

           add_hook_to_module(model.lineara	,      AlignDevicesHook(**A		)		)
           add_hook_to_module(model.batchnorm	,      AlignDevicesHook(**A		)		)
           add_hook_to_module(model.lineara	,      AlignDevicesHook(**A		)		)

           # Parameters have been offloaded, so on the meta device
           self.assertEqual(model.lineara.weight.device	,      torch.device("meta"		)		)
           self.assertEqual(model.batchnorm.weight.device	,      torch.device("meta"		)		)
           self.assertEqual(model.lineara.weight.device	,      torch.device("meta"		)		)
           # Buffers are not included in the offload by default, so are on the execution device
           _UpperCAmelCase     :      str														=       torch.device(hook_kwargs["execution_device"]		)
           self.assertEqual(model.batchnorm.running_mean.device	,      A		)

           _UpperCAmelCase     :      Union[str, Any]														=       torch.randn(2	,      3		)
           _UpperCAmelCase     :      Any														=       model(A		)
           self.assertEqual(output.device	,      A		)

           # Removing hooks loads back the weights in the model.
           remove_hook_from_module(model.lineara		)
           remove_hook_from_module(model.batchnorm		)
           remove_hook_from_module(model.lineara		)
           self.assertEqual(model.lineara.weight.device	,      torch.device("cpu"		)		)
           self.assertEqual(model.batchnorm.weight.device	,      torch.device("cpu"		)		)
           self.assertEqual(model.lineara.weight.device	,      torch.device("cpu"		)		)

           # Now test with buffers included in the offload
           _UpperCAmelCase     :      Any														=       {
               "execution_device": 0 if torch.cuda.is_available() else "cpu",
               "offload": True,
               "offload_buffers": True,
           }

           add_hook_to_module(model.lineara	,      AlignDevicesHook(**A		)		)
           add_hook_to_module(model.batchnorm	,      AlignDevicesHook(**A		)		)
           add_hook_to_module(model.lineara	,      AlignDevicesHook(**A		)		)

           # Parameters have been offloaded, so on the meta device, buffers included
           self.assertEqual(model.lineara.weight.device	,      torch.device("meta"		)		)
           self.assertEqual(model.batchnorm.weight.device	,      torch.device("meta"		)		)
           self.assertEqual(model.lineara.weight.device	,      torch.device("meta"		)		)
           self.assertEqual(model.batchnorm.running_mean.device	,      torch.device("meta"		)		)

           _UpperCAmelCase     :      Any														=       torch.randn(2	,      3		)
           _UpperCAmelCase     :      List[Any]														=       model(A		)
           self.assertEqual(output.device	,      A		)

           # Removing hooks loads back the weights in the model.
           remove_hook_from_module(model.lineara		)
           remove_hook_from_module(model.batchnorm		)
           remove_hook_from_module(model.lineara		)
           self.assertEqual(model.lineara.weight.device	,      torch.device("cpu"		)		)
           self.assertEqual(model.batchnorm.weight.device	,      torch.device("cpu"		)		)
           self.assertEqual(model.lineara.weight.device	,      torch.device("cpu"		)		)



      def 		snake_case_   (	self	:      List[str]		):
           _UpperCAmelCase     :      List[str]														=       ModelForTest()

           # Everything is on CPU
           self.assertEqual(model.lineara.weight.device	,      torch.device("cpu"		)		)
           self.assertEqual(model.batchnorm.weight.device	,      torch.device("cpu"		)		)
           self.assertEqual(model.lineara.weight.device	,      torch.device("cpu"		)		)

           # This will move each submodule on different devices
           _UpperCAmelCase     :      Dict														=       0 if torch.cuda.is_available() else "cpu"
           attach_align_device_hook(A	,      execution_device=A	,      offload=A		)

           # Parameters have been offloaded, so on the meta device
           self.assertEqual(model.lineara.weight.device	,      torch.device("meta"		)		)
           self.assertEqual(model.batchnorm.weight.device	,      torch.device("meta"		)		)
           self.assertEqual(model.lineara.weight.device	,      torch.device("meta"		)		)
           # Buffers are not included in the offload by default, so are on the execution device
           _UpperCAmelCase     :      Dict														=       torch.device(A		)
           self.assertEqual(model.batchnorm.running_mean.device	,      A		)

           _UpperCAmelCase     :      List[str]														=       torch.randn(2	,      3		)
           _UpperCAmelCase     :      Optional[Any]														=       model(A		)
           self.assertEqual(output.device	,      A		)

           # Removing hooks loads back the weights in the model.
           remove_hook_from_submodules(A		)
           self.assertEqual(model.lineara.weight.device	,      torch.device("cpu"		)		)
           self.assertEqual(model.batchnorm.weight.device	,      torch.device("cpu"		)		)
           self.assertEqual(model.lineara.weight.device	,      torch.device("cpu"		)		)

           # Now test with buffers included in the offload
           attach_align_device_hook(A	,      execution_device=A	,      offload=A	,      offload_buffers=A		)

           # Parameters have been offloaded, so on the meta device, buffers included
           self.assertEqual(model.lineara.weight.device	,      torch.device("meta"		)		)
           self.assertEqual(model.batchnorm.weight.device	,      torch.device("meta"		)		)
           self.assertEqual(model.lineara.weight.device	,      torch.device("meta"		)		)
           self.assertEqual(model.batchnorm.running_mean.device	,      torch.device("meta"		)		)

           _UpperCAmelCase     :      int														=       torch.randn(2	,      3		)
           _UpperCAmelCase     :      int														=       model(A		)
           self.assertEqual(output.device	,      A		)

           # Removing hooks loads back the weights in the model.
           remove_hook_from_submodules(A		)
           self.assertEqual(model.lineara.weight.device	,      torch.device("cpu"		)		)
           self.assertEqual(model.batchnorm.weight.device	,      torch.device("cpu"		)		)
           self.assertEqual(model.lineara.weight.device	,      torch.device("cpu"		)		)



      def 		snake_case_   (	self	:      Optional[Any]		):
           _UpperCAmelCase     :      Any														=       ModelForTest()

           # Everything is on CPU
           self.assertEqual(model.lineara.weight.device	,      torch.device("cpu"		)		)
           self.assertEqual(model.batchnorm.weight.device	,      torch.device("cpu"		)		)
           self.assertEqual(model.lineara.weight.device	,      torch.device("cpu"		)		)

           # This will move each submodule on different devices
           _UpperCAmelCase     :      str														=       0 if torch.cuda.is_available() else "cpu"
           attach_align_device_hook(
               A	,      execution_device=A	,      offload=A	,      weights_map=model.state_dict()		)

           # Parameters have been offloaded, so on the meta device
           self.assertEqual(model.lineara.weight.device	,      torch.device("meta"		)		)
           self.assertEqual(model.batchnorm.weight.device	,      torch.device("meta"		)		)
           self.assertEqual(model.lineara.weight.device	,      torch.device("meta"		)		)
           # Buffers are not included in the offload by default, so are on the execution device
           _UpperCAmelCase     :      Union[str, Any]														=       torch.device(A		)
           self.assertEqual(model.batchnorm.running_mean.device	,      A		)

           _UpperCAmelCase     :      Union[str, Any]														=       torch.randn(2	,      3		)
           _UpperCAmelCase     :      Optional[Any]														=       model(A		)
           self.assertEqual(output.device	,      A		)

           # Removing hooks loads back the weights in the model.
           remove_hook_from_submodules(A		)
           self.assertEqual(model.lineara.weight.device	,      torch.device("cpu"		)		)
           self.assertEqual(model.batchnorm.weight.device	,      torch.device("cpu"		)		)
           self.assertEqual(model.lineara.weight.device	,      torch.device("cpu"		)		)

           # Now test with buffers included in the offload
           attach_align_device_hook(
               A	,      execution_device=A	,      offload=A	,      weights_map=model.state_dict()	,      offload_buffers=A	,      )

           # Parameters have been offloaded, so on the meta device, buffers included
           self.assertEqual(model.lineara.weight.device	,      torch.device("meta"		)		)
           self.assertEqual(model.batchnorm.weight.device	,      torch.device("meta"		)		)
           self.assertEqual(model.lineara.weight.device	,      torch.device("meta"		)		)
           self.assertEqual(model.batchnorm.running_mean.device	,      torch.device("meta"		)		)

           _UpperCAmelCase     :      Optional[int]														=       torch.randn(2	,      3		)
           _UpperCAmelCase     :      Dict														=       model(A		)
           self.assertEqual(output.device	,      A		)

           # Removing hooks loads back the weights in the model.
           remove_hook_from_submodules(A		)
           self.assertEqual(model.lineara.weight.device	,      torch.device("cpu"		)		)
           self.assertEqual(model.batchnorm.weight.device	,      torch.device("cpu"		)		)
           self.assertEqual(model.lineara.weight.device	,      torch.device("cpu"		)		)





"""simple docstring"""




import requests

_lowerCAmelCase							:   List[Any]				=				"https://newsapi.org/v1/articles?source=bbc-news&sortBy=top&apiKey="

def 		__snake_case		( SCREAMING_SNAKE_CASE__      :		str							)    ->  None:





     '''simple docstring'''

     _UpperCAmelCase     :      List[str]														=       requests.get(_NEWS_API + bbc_news_api_key							).json()
     # each article in the list is a dict
     for i, article in enumerate(bbc_news_page["articles"]		,    1							):
          print(f'{i}.) {article["title"]}'							)


if __name__ == "__main__":
 fetch_bbc_news(bbc_news_api_key="<Your BBC News API key goes here>")
