'''simple docstring'''
# Copyright 2021 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 json
import os

from ...utils.constants import SAGEMAKER_PARALLEL_EC2_INSTANCES, TORCH_DYNAMO_MODES
from ...utils.dataclasses import ComputeEnvironment, SageMakerDistributedType
from ...utils.imports import is_botoa_available
from .config_args import SageMakerConfig
from .config_utils import (
    DYNAMO_BACKENDS,
    _ask_field,
    _ask_options,
    _convert_dynamo_backend,
    _convert_mixed_precision,
    _convert_sagemaker_distributed_mode,
    _convert_yes_no_to_bool,
)


if is_botoa_available():
   import botoa  # noqa: F401







def  _UpperCamelCase (     _a	:	List[str]			):




    """simple docstring"""



    __UpperCamelCase	:	Any		    =  botoa.client('iam'			)

    __UpperCamelCase	:	Optional[int]		    =  {
        'Version': '2012-10-17',
        'Statement': [
            {'Effect': 'Allow', 'Principal': {'Service': 'sagemaker.amazonaws.com'}, 'Action': 'sts:AssumeRole'}
        ],
    }
    try:
        # create the role, associated with the chosen trust policy
        iam_client.create_role(
            RoleName=UpperCAmelCase__				,     AssumeRolePolicyDocument=json.dumps(UpperCAmelCase__				,     indent=2			)			)
        __UpperCamelCase	:	int		    =  {
            'Version': '2012-10-17',
            'Statement': [
                {
                    'Effect': 'Allow',
                    'Action': [
                        'sagemaker:*',
                        'ecr:GetDownloadUrlForLayer',
                        'ecr:BatchGetImage',
                        'ecr:BatchCheckLayerAvailability',
                        'ecr:GetAuthorizationToken',
                        'cloudwatch:PutMetricData',
                        'cloudwatch:GetMetricData',
                        'cloudwatch:GetMetricStatistics',
                        'cloudwatch:ListMetrics',
                        'logs:CreateLogGroup',
                        'logs:CreateLogStream',
                        'logs:DescribeLogStreams',
                        'logs:PutLogEvents',
                        'logs:GetLogEvents',
                        's3:CreateBucket',
                        's3:ListBucket',
                        's3:GetBucketLocation',
                        's3:GetObject',
                        's3:PutObject',
                    ],
                    'Resource': '*',
                }
            ],
        }
        # attach policy to role
        iam_client.put_role_policy(
            RoleName=UpperCAmelCase__				,     PolicyName=f"""{role_name}_policy_permission"""				,     PolicyDocument=json.dumps(UpperCAmelCase__				,     indent=2			)				,     )
    except iam_client.exceptions.EntityAlreadyExistsException:
        print(f"""role {role_name} already exists. Using existing one"""			)







def  _UpperCamelCase (     _a	:	Optional[int]			):




    """simple docstring"""



    __UpperCamelCase	:	int		    =  botoa.client('iam'			)
    return iam_client.get_role(RoleName=UpperCAmelCase__			)["Role"]["Arn"]







def  _UpperCamelCase (     ):




    """simple docstring"""



    __UpperCamelCase	:	Tuple		    =  _ask_options(
        'How do you want to authorize?'				,     ['AWS Profile', 'Credentials (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY) ']				,     UpperCAmelCase__				,     )
    __UpperCamelCase	:	Optional[int]		    =  None
    if credentials_configuration == 0:
        __UpperCamelCase	:	Union[str, Any]		    =  _ask_field('Enter your AWS Profile name: [default] '				,     default='default'			)
        __UpperCamelCase	:	Optional[int]		    =  aws_profile
    else:
        print(
            'Note you will need to provide AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY when you launch you training script with,'
            '`accelerate launch --aws_access_key_id XXX --aws_secret_access_key YYY`'			)
        __UpperCamelCase	:	List[str]		    =  _ask_field('AWS Access Key ID: '			)
        __UpperCamelCase	:	Dict		    =  aws_access_key_id

        __UpperCamelCase	:	List[Any]		    =  _ask_field('AWS Secret Access Key: '			)
        __UpperCamelCase	:	Union[str, Any]		    =  aws_secret_access_key

    __UpperCamelCase	:	List[Any]		    =  _ask_field('Enter your AWS Region: [us-east-1]'				,     default='us-east-1'			)
    __UpperCamelCase	:	Any		    =  aws_region

    __UpperCamelCase	:	Any		    =  _ask_options(
        'Do you already have an IAM Role for executing Amazon SageMaker Training Jobs?'				,     ['Provide IAM Role name', 'Create new IAM role using credentials']				,     UpperCAmelCase__				,     )
    if role_management == 0:
        __UpperCamelCase	:	Any		    =  _ask_field('Enter your IAM role name: '			)
    else:
        __UpperCamelCase	:	Any		    =  'accelerate_sagemaker_execution_role'
        print(f"""Accelerate will create an iam role \"{iam_role_name}\" using the provided credentials"""			)
        _create_iam_role_for_sagemaker(UpperCAmelCase__			)

    __UpperCamelCase	:	Union[str, Any]		    =  _ask_field(
        'Do you want to use custom Docker image? [yes/NO]: '				,     _convert_yes_no_to_bool				,     default=UpperCAmelCase__				,     error_message='Please enter yes or no.'				,     )
    __UpperCamelCase	:	Optional[Any]		    =  None
    if is_custom_docker_image:
        __UpperCamelCase	:	Dict		    =  _ask_field('Enter your Docker image: '				,     lambda _a			: str(UpperCAmelCase__			).lower()			)

    __UpperCamelCase	:	Tuple		    =  _ask_field(
        'Do you want to provide SageMaker input channels with data locations? [yes/NO]: '				,     _convert_yes_no_to_bool				,     default=UpperCAmelCase__				,     error_message='Please enter yes or no.'				,     )
    __UpperCamelCase	:	Dict		    =  None
    if is_sagemaker_inputs_enabled:
        __UpperCamelCase	:	Optional[Any]		    =  _ask_field(
            'Enter the path to the SageMaker inputs TSV file with columns (channel_name, data_location): '				,     lambda _a			: str(UpperCAmelCase__			).lower()				,     )

    __UpperCamelCase	:	Union[str, Any]		    =  _ask_field(
        'Do you want to enable SageMaker metrics? [yes/NO]: '				,     _convert_yes_no_to_bool				,     default=UpperCAmelCase__				,     error_message='Please enter yes or no.'				,     )
    __UpperCamelCase	:	int		    =  None
    if is_sagemaker_metrics_enabled:
        __UpperCamelCase	:	Dict		    =  _ask_field(
            'Enter the path to the SageMaker metrics TSV file with columns (metric_name, metric_regex): '				,     lambda _a			: str(UpperCAmelCase__			).lower()				,     )

    __UpperCamelCase	:	Tuple		    =  _ask_options(
        'What is the distributed mode?'				,     ['No distributed training', 'Data parallelism']				,     _convert_sagemaker_distributed_mode				,     )
    __UpperCamelCase	:	str		    =  {}
    __UpperCamelCase	:	str		    =  _ask_field(
        'Do you wish to optimize your script with torch dynamo?[yes/NO]:'				,     _convert_yes_no_to_bool				,     default=UpperCAmelCase__				,     error_message='Please enter yes or no.'				,     )
    if use_dynamo:
        __UpperCamelCase	:	Tuple		    =  'dynamo_'
        __UpperCamelCase	:	Any		    =  _ask_options(
            'Which dynamo backend would you like to use?'				,     [x.lower() for x in DYNAMO_BACKENDS]				,     _convert_dynamo_backend				,     default=2				,     )
        __UpperCamelCase	:	Dict		    =  _ask_field(
            'Do you want to customize the defaults sent to torch.compile? [yes/NO]: '				,     _convert_yes_no_to_bool				,     default=UpperCAmelCase__				,     error_message='Please enter yes or no.'				,     )

        if use_custom_options:
            __UpperCamelCase	:	Any		    =  _ask_options(
                'Which mode do you want to use?'				,     UpperCAmelCase__				,     lambda _a			: TORCH_DYNAMO_MODES[int(UpperCAmelCase__			)]				,     default='default'				,     )
            __UpperCamelCase	:	Optional[Any]		    =  _ask_field(
                'Do you want the fullgraph mode or it is ok to break model into several subgraphs? [yes/NO]: '				,     _convert_yes_no_to_bool				,     default=UpperCAmelCase__				,     error_message='Please enter yes or no.'				,     )
            __UpperCamelCase	:	Optional[Any]		    =  _ask_field(
                'Do you want to enable dynamic shape tracing? [yes/NO]: '				,     _convert_yes_no_to_bool				,     default=UpperCAmelCase__				,     error_message='Please enter yes or no.'				,     )
    __UpperCamelCase	:	Optional[int]		    =  'Which EC2 instance type you want to use for your training?'
    if distributed_type != SageMakerDistributedType.NO:
        __UpperCamelCase	:	Any		    =  _ask_options(
            UpperCAmelCase__				,     UpperCAmelCase__				,     lambda _a			: SAGEMAKER_PARALLEL_EC2_INSTANCES[int(UpperCAmelCase__			)]			)
    else:
        eca_instance_query += "? [ml.p3.2xlarge]:"
        __UpperCamelCase	:	Dict		    =  _ask_field(UpperCAmelCase__				,     lambda _a			: str(UpperCAmelCase__			).lower()				,     default='ml.p3.2xlarge'			)

    __UpperCamelCase	:	Tuple		    =  1
    if distributed_type in (SageMakerDistributedType.DATA_PARALLEL, SageMakerDistributedType.MODEL_PARALLEL):
        __UpperCamelCase	:	Any		    =  _ask_field(
            'How many machines do you want use? [1]: '				,     UpperCAmelCase__				,     default=1				,     )

    __UpperCamelCase	:	Optional[Any]		    =  _ask_options(
        'Do you wish to use FP16 or BF16 (mixed precision)?'				,     ['no', 'fp16', 'bf16', 'fp8']				,     _convert_mixed_precision				,     )

    if use_dynamo and mixed_precision == "no":
        print(
            'Torch dynamo used without mixed precision requires TF32 to be efficient. Accelerate will enable it by default when launching your scripts.'			)

    return SageMakerConfig(
        image_uri=UpperCAmelCase__				,     compute_environment=ComputeEnvironment.AMAZON_SAGEMAKER				,     distributed_type=UpperCAmelCase__				,     use_cpu=UpperCAmelCase__				,     dynamo_config=UpperCAmelCase__				,     eca_instance_type=UpperCAmelCase__				,     profile=UpperCAmelCase__				,     region=UpperCAmelCase__				,     iam_role_name=UpperCAmelCase__				,     mixed_precision=UpperCAmelCase__				,     num_machines=UpperCAmelCase__				,     sagemaker_inputs_file=UpperCAmelCase__				,     sagemaker_metrics_file=UpperCAmelCase__				,     )




'''simple docstring'''
class 			__lowercase		:







     """simple docstring"""






     def __init__(		self    ):
         __UpperCamelCase	:	Any		    =  0
         __UpperCamelCase	:	Any		    =  0
         __UpperCamelCase	:	Any		    =  {}







     def lowerCAmelCase     (		self     ,			_lowerCamelCase    ):
         if vertex not in self.adjacency:
             __UpperCamelCase	:	Tuple		    =  {}
             self.num_vertices += 1







     def lowerCAmelCase     (		self     ,			_lowerCamelCase     ,			_lowerCamelCase     ,			_lowerCamelCase    ):
         self.add_vertex(_lowerCamelCase    )
         self.add_vertex(_lowerCamelCase    )

         if head == tail:
             return

         __UpperCamelCase	:	List[Any]		    =  weight
         __UpperCamelCase	:	Optional[int]		    =  weight







     def lowerCAmelCase     (		self    ):
         __UpperCamelCase	:	List[str]		    =  self.get_edges()
         for edge in edges:
             __UpperCamelCase    ,					__UpperCamelCase    ,					__UpperCamelCase	:	Optional[int]		    =  edge
             edges.remove((tail, head, weight)    )
         for i in range(len(_lowerCamelCase    )    ):
             __UpperCamelCase	:	Union[str, Any]		    =  list(edges[i]    )

         edges.sort(key=lambda _lowerCamelCase    : e[2]    )
         for i in range(len(_lowerCamelCase    ) - 1    ):
             if edges[i][2] >= edges[i + 1][2]:
                 __UpperCamelCase	:	Optional[int]		    =  edges[i][2] + 1
         for edge in edges:
             __UpperCamelCase    ,					__UpperCamelCase    ,					__UpperCamelCase	:	Optional[int]		    =  edge
             __UpperCamelCase	:	Tuple		    =  weight
             __UpperCamelCase	:	Optional[Any]		    =  weight







     def __str__(		self    ):
         __UpperCamelCase	:	Optional[Any]		    =  ''
         for tail in self.adjacency:
             for head in self.adjacency[tail]:
                 __UpperCamelCase	:	Tuple		    =  self.adjacency[head][tail]
                 string += f"""{head} -> {tail} == {weight}\n"""
         return string.rstrip('\n'    )







     def lowerCAmelCase     (		self    ):
         __UpperCamelCase	:	Any		    =  []
         for tail in self.adjacency:
             for head in self.adjacency[tail]:
                 output.append((tail, head, self.adjacency[head][tail])    )
         return output







     def lowerCAmelCase     (		self    ):
         return self.adjacency.keys()







     @staticmethod
     def lowerCAmelCase     (		_lowerCamelCase=None     ,			_lowerCamelCase=None    ):
         __UpperCamelCase	:	Tuple		    =  Graph()
         if vertices is None:
             __UpperCamelCase	:	List[Any]		    =  []
         if edges is None:
             __UpperCamelCase	:	Optional[int]		    =  []
         for vertex in vertices:
             g.add_vertex(_lowerCamelCase    )
         for edge in edges:
             g.add_edge(*_lowerCamelCase    )
         return g






     class 			__lowercase		:







          """simple docstring"""






          def __init__(		self    ):
              __UpperCamelCase	:	Union[str, Any]		    =  {}
              __UpperCamelCase	:	int		    =  {}







          def __len__(		self    ):
              return len(self.parent    )







          def lowerCAmelCase     (		self     ,			_lowerCamelCase    ):
              if item in self.parent:
                  return self.find(_lowerCamelCase    )

              __UpperCamelCase	:	Optional[Any]		    =  item
              __UpperCamelCase	:	List[str]		    =  0
              return item







          def lowerCAmelCase     (		self     ,			_lowerCamelCase    ):
              if item not in self.parent:
                  return self.make_set(_lowerCamelCase    )
              if item != self.parent[item]:
                  __UpperCamelCase	:	int		    =  self.find(self.parent[item]    )
              return self.parent[item]







          def lowerCAmelCase     (		self     ,			_lowerCamelCase     ,			_lowerCamelCase    ):
              __UpperCamelCase	:	Tuple		    =  self.find(_lowerCamelCase    )
              __UpperCamelCase	:	Any		    =  self.find(_lowerCamelCase    )

              if roota == roota:
                  return roota

              if self.rank[roota] > self.rank[roota]:
                  __UpperCamelCase	:	Dict		    =  roota
                  return roota

              if self.rank[roota] < self.rank[roota]:
                  __UpperCamelCase	:	Optional[Any]		    =  roota
                  return roota

              if self.rank[roota] == self.rank[roota]:
                  self.rank[roota] += 1
                  __UpperCamelCase	:	Dict		    =  roota
                  return roota
              return None







     @staticmethod
     def lowerCAmelCase     (		_lowerCamelCase    ):
         __UpperCamelCase	:	int		    =  graph.num_vertices

         __UpperCamelCase	:	str		    =  Graph.UnionFind()
         __UpperCamelCase	:	Tuple		    =  []
         while num_components > 1:
             __UpperCamelCase	:	Dict		    =  {}
             for vertex in graph.get_vertices():
                 __UpperCamelCase	:	str		    =  -1

             __UpperCamelCase	:	int		    =  graph.get_edges()
             for edge in edges:
                 __UpperCamelCase    ,					__UpperCamelCase    ,					__UpperCamelCase	:	List[str]		    =  edge
                 edges.remove((tail, head, weight)    )
             for edge in edges:
                 __UpperCamelCase    ,					__UpperCamelCase    ,					__UpperCamelCase	:	Dict		    =  edge
                 __UpperCamelCase	:	List[Any]		    =  union_find.find(_lowerCamelCase    )
                 __UpperCamelCase	:	str		    =  union_find.find(_lowerCamelCase    )
                 if seta != seta:
                     if cheap_edge[seta] == -1 or cheap_edge[seta][2] > weight:
                         __UpperCamelCase	:	str		    =  [head, tail, weight]

                     if cheap_edge[seta] == -1 or cheap_edge[seta][2] > weight:
                         __UpperCamelCase	:	str		    =  [head, tail, weight]
             for vertex in cheap_edge:
                 if cheap_edge[vertex] != -1:
                     __UpperCamelCase    ,					__UpperCamelCase    ,					__UpperCamelCase	:	List[str]		    =  cheap_edge[vertex]
                     if union_find.find(_lowerCamelCase    ) != union_find.find(_lowerCamelCase    ):
                         union_find.union(_lowerCamelCase     ,			_lowerCamelCase    )
                         mst_edges.append(cheap_edge[vertex]    )
                         __UpperCamelCase	:	int		    =  num_components - 1
         __UpperCamelCase	:	Union[str, Any]		    =  Graph.build(edges=_lowerCamelCase    )
         return mst



