





import json
import os
import subprocess
import unittest
from ast import literal_eval

import pytest
from parameterized import parameterized_class

from . import is_sagemaker_available


if is_sagemaker_available():
 from sagemaker import Session, TrainingJobAnalytics
 from sagemaker.huggingface import HuggingFace


@pytest.mark.skipif(
    literal_eval(os.getenv('''TEST_SAGEMAKER'''     ,					'''False'''				)				) is not True     ,					reason='''Skipping test because should only be run when releasing minor transformers version'''     ,					)
@pytest.mark.usefixtures('''sm_env'''				)
@parameterized_class(
    [
        {
            '''framework''': '''pytorch''',
            '''script''': '''run_glue.py''',
            '''model_name_or_path''': '''distilbert-base-cased''',
            '''instance_type''': '''ml.g4dn.xlarge''',
            '''results''': {'''train_runtime''': 6_50, '''eval_accuracy''': 0.6, '''eval_loss''': 0.9},
        },
        {
            '''framework''': '''tensorflow''',
            '''script''': '''run_tf.py''',
            '''model_name_or_path''': '''distilbert-base-cased''',
            '''instance_type''': '''ml.g4dn.xlarge''',
            '''results''': {'''train_runtime''': 6_00, '''eval_accuracy''': 0.3, '''eval_loss''': 0.9},
        },
    ]				)
class        __magic_name__	(				unittest.TestCase				):





     """simple docstring"""



     def     SCREAMING_SNAKE_CASE		(				self							:int	):





        '''simple docstring'''




        if self.framework == "pytorch":
           subprocess.run(
               f"cp ./examples/pytorch/text-classification/run_glue.py {self.env.test_path}/run_glue.py".split()      ,   encoding="utf-8"      ,   check=snake_case      ,   )
        assert hasattr(self      ,   "env"	)



     def     SCREAMING_SNAKE_CASE		(				self							:Optional[int]      ,   snake_case							:List[Any]=1	):





        '''simple docstring'''




        return HuggingFace(
            entry_point=self.script      ,   source_dir=self.env.test_path      ,   role=self.env.role      ,   image_uri=self.env.image_uri      ,   base_job_name=f"{self.env.base_job_name}-single"      ,   instance_count=snake_case      ,   instance_type=self.instance_type      ,   debugger_hook_config=snake_case      ,   hyperparameters={**self.env.hyperparameters, "model_name_or_path": self.model_name_or_path}      ,   metric_definitions=self.env.metric_definitions      ,   py_version="py36"      ,   )



     def     SCREAMING_SNAKE_CASE		(				self							:Any      ,   snake_case							:List[str]	):





        '''simple docstring'''




        TrainingJobAnalytics(snake_case	).export_csv(f"{self.env.test_path}/{job_name}_metrics.csv"	)





     def     SCREAMING_SNAKE_CASE		(				self							:Dict	):





        '''simple docstring'''




        A_       :					Optional[int]        =      self.create_estimator()

        # run training
        estimator.fit()

        # result dataframe
        A_       :					List[str]        =      TrainingJobAnalytics(estimator.latest_training_job.name	).dataframe()

        # extract kpis
        A_       :					Dict        =      list(result_metrics_df[result_metrics_df.metric_name == "eval_accuracy"]["value"]	)
        A_       :					Optional[Any]        =      list(result_metrics_df[result_metrics_df.metric_name == "eval_loss"]["value"]	)
        # get train time from SageMaker job, this includes starting, preprocessing, stopping
        A_       :					str        =      (
            Session().describe_training_job(estimator.latest_training_job.name	).get("TrainingTimeInSeconds"      ,   999_999	)
        )

        # assert kpis
        assert train_runtime <= self.results["train_runtime"]
        assert all(t >= self.results["eval_accuracy"] for t in eval_accuracy	)
        assert all(t <= self.results["eval_loss"] for t in eval_loss	)

        # dump tests result into json file to share in PR
        with open(f"{estimator.latest_training_job.name}.json"      ,   "w"	) as outfile:
           json.dump({"train_time": train_runtime, "eval_accuracy": eval_accuracy, "eval_loss": eval_loss}      ,   snake_case	)







# Copyright 2023 The HuggingFace Team. All rights reserved.
#
# 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.

import torch

from accelerate import PartialState
from accelerate.utils.operations import broadcast, gather, gather_object, pad_across_processes, reduce

def   __snake_case    (       _lowerCAmelCase			:			Optional[int]						)			->    Dict:
   return (torch.arange(state.num_processes						) + 1.0 + (state.num_processes * state.process_index)).to(state.device						)

def   __snake_case    (       _lowerCAmelCase			:			Tuple						)			->    Optional[Any]:
   A_       :					Optional[Any]        =      create_tensor(_lowerCAmelCase						)
   A_       :					Dict        =      gather(_lowerCAmelCase						)
   assert gathered_tensor.tolist() == list(range(1					,					state.num_processes**2 + 1						)						)

def   __snake_case    (       _lowerCAmelCase			:			List[Any]						)			->    Any:
   A_       :					int        =      [state.process_index]
   A_       :					Union[str, Any]        =      gather_object(_lowerCAmelCase						)
   assert len(_lowerCAmelCase						) == state.num_processes, f"{gathered_obj}, {len(_lowerCAmelCase						)} != {state.num_processes}"
   assert gathered_obj == list(range(state.num_processes						)						), f"{gathered_obj} != {list(range(state.num_processes						)						)}"

def   __snake_case    (       _lowerCAmelCase			:			Union[str, Any]						)			->    Optional[Any]:
   A_       :					List[str]        =      create_tensor(_lowerCAmelCase						)
   A_       :					Optional[Any]        =      broadcast(_lowerCAmelCase						)
   assert broadcasted_tensor.shape == torch.Size([state.num_processes]						)
   assert broadcasted_tensor.tolist() == list(range(1					,					state.num_processes + 1						)						)

def   __snake_case    (       _lowerCAmelCase			:			Dict						)			->    str:
   # We need to pad the tensor with one more element if we are the main process
   # to ensure that we can pad
   if state.is_main_process:
      A_       :					Tuple        =      torch.arange(state.num_processes + 1						).to(state.device						)
   else:
      A_       :					List[str]        =      torch.arange(state.num_processes						).to(state.device						)
   A_       :					Any        =      pad_across_processes(_lowerCAmelCase						)
   assert padded_tensor.shape == torch.Size([state.num_processes + 1]						)
   if not state.is_main_process:
      assert padded_tensor.tolist() == list(range(0					,					state.num_processes						)						) + [0]

def   __snake_case    (       _lowerCAmelCase			:			List[Any]						)			->    Tuple:
   # For now runs on only two processes
   if state.num_processes != 2:
      return
   A_       :					str        =      create_tensor(_lowerCAmelCase						)
   A_       :					int        =      reduce(_lowerCAmelCase					,					"sum"						)
   A_       :					Optional[Any]        =      torch.tensor([4.0, 6]						).to(state.device						)
   assert torch.allclose(_lowerCAmelCase					,					_lowerCAmelCase						), f"{reduced_tensor} != {truth_tensor}"

def   __snake_case    (       _lowerCAmelCase			:			Union[str, Any]						)			->    Dict:
   # For now runs on only two processes
   if state.num_processes != 2:
      return
   A_       :					List[str]        =      create_tensor(_lowerCAmelCase						)
   A_       :					Tuple        =      reduce(_lowerCAmelCase					,					"mean"						)
   A_       :					List[str]        =      torch.tensor([2.0, 3]						).to(state.device						)
   assert torch.allclose(_lowerCAmelCase					,					_lowerCAmelCase						), f"{reduced_tensor} != {truth_tensor}"

def   __snake_case    (       _lowerCAmelCase			:			List[str]						)			->    Dict:
   # For xla_spawn (TPUs)
   main()

def   __snake_case    (       )			->    List[str]:
   A_       :					Tuple        =      PartialState()
   state.print(f"State: {state}"						)
   state.print("testing gather"						)
   test_gather(_lowerCAmelCase						)
   state.print("testing gather_object"						)
   test_gather_object(_lowerCAmelCase						)
   state.print("testing broadcast"						)
   test_broadcast(_lowerCAmelCase						)
   state.print("testing pad_across_processes"						)
   test_pad_across_processes(_lowerCAmelCase						)
   state.print("testing reduce_sum"						)
   test_reduce_sum(_lowerCAmelCase						)
   state.print("testing reduce_mean"						)
   test_reduce_mean(_lowerCAmelCase						)


if __name__ == "__main__":
 main()
