


# Copyright 2022 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 argparse
import os
import subprocess

from packaging.version import Version, parse

from accelerate.commands.config.config_args import default_config_file, load_config_from_file


SCREAMING_SNAKE_CASE :   List[Any]							      =				"Run commands across TPU VMs for initial setup before running `accelerate launch`."



def        UpperCamelCase_(   lowerCamelCase_=None				)					->		Union[str, Any]:
    if subparsers is not None:
        _lowercase :							Optional[int]   	=	subparsers.add_parser('tpu-config'							,				description=_description				)
    else:
        _lowercase :							Optional[int]   	=	argparse.ArgumentParser('Accelerate tpu-config command'							,				description=_description				)
    # Core arguments
    _lowercase :							List[Any]   	=	parser.add_argument_group(
        'Config Arguments'							,				'Arguments that can be configured through `accelerate config`.'				)
    config_args.add_argument(
        '--config_file'							,				type=lowerCamelCase_							,				default=lowerCamelCase_							,				help='Path to the config file to use for accelerate.'							,				)
    config_args.add_argument(
        '--tpu_name'							,				default=lowerCamelCase_							,				help='The name of the TPU to use. If not specified, will use the TPU specified in the config file.'							,				)
    config_args.add_argument(
        '--tpu_zone'							,				default=lowerCamelCase_							,				help='The zone of the TPU to use. If not specified, will use the zone specified in the config file.'							,				)
    _lowercase :							Dict   	=	parser.add_argument_group('TPU Arguments'							,				'Arguments for options ran inside the TPU.'				)
    pod_args.add_argument(
        '--use_alpha'							,				action='store_true'							,				help='Whether to use `gcloud alpha` when running the TPU training script instead of `gcloud`.'							,				)
    pod_args.add_argument(
        '--command_file'							,				default=lowerCamelCase_							,				help='The path to the file containing the commands to run on the pod on startup.'							,				)
    pod_args.add_argument(
        '--command'							,				action='append'							,				nargs='+'							,				help='A command to run on the pod. Can be passed multiple times.'							,				)
    pod_args.add_argument(
        '--install_accelerate'							,				action='store_true'							,				help='Whether to install accelerate on the pod. Defaults to False.'							,				)
    pod_args.add_argument(
        '--accelerate_version'							,				default='latest'							,				help='The version of accelerate to install on the pod. If not specified, will use the latest pypi version. Specify \'dev\' to install from GitHub.'							,				)
    pod_args.add_argument(
        '--debug'							,				action='store_true'							,				help='If set, will print the command that would be run instead of running it.'				)

    if subparsers is not None:
        parser.set_defaults(func=lowerCamelCase_				)
    return parser



def        UpperCamelCase_(   lowerCamelCase_				)					->		int:
    _lowercase :							List[Any]   	=	None

    # Get the default from the config file if it exists.
    if args.config_file is not None or os.path.isfile(lowerCamelCase_				):
        _lowercase :							Union[str, Any]   	=	load_config_from_file(args.config_file				)
        if not args.command_file and defaults.command_file is not None and not args.command:
            _lowercase :							Optional[int]   	=	defaults.command_file
        if not args.command and defaults.commands is not None:
            _lowercase :							Optional[int]   	=	defaults.commands
        if not args.tpu_name:
            _lowercase :							Tuple   	=	defaults.tpu_name
        if not args.tpu_zone:
            _lowercase :							List[Any]   	=	defaults.tpu_zone
    if args.accelerate_version == "dev":
        _lowercase :							List[str]   	=	'git+https://github.com/huggingface/accelerate.git'
    elif args.accelerate_version == "latest":
        _lowercase :							Dict   	=	'accelerate -U'
    elif isinstance(parse(args.accelerate_version				)							,				lowerCamelCase_				):
        _lowercase :							Union[str, Any]   	=	F'''accelerate=={args.accelerate_version}'''

    if not args.command_file and not args.command:
        raise ValueError('You must specify either a command file or a command to run on the pod.'				)

    if args.command_file:
        with open(args.command_file							,				'r'				) as f:
            _lowercase :							List[str]   	=	[f.read().splitlines()]

    # To turn list of lists into list of strings
    if isinstance(args.command[0]							,				lowerCamelCase_				):
        _lowercase :							Optional[int]   	=	[line for cmd in args.command for line in cmd]
    # Default to the shared folder and install accelerate
    _lowercase :							List[str]   	=	['cd /usr/share']
    if args.install_accelerate:
        new_cmd += [F'''pip install {args.accelerate_version}''']
    new_cmd += args.command
    _lowercase :							Union[str, Any]   	=	'; '.join(lowerCamelCase_				)

    # Then send it to gcloud
    # Eventually try to use google-api-core to do this instead of subprocess
    _lowercase :							List[str]   	=	['gcloud']
    if args.use_alpha:
        cmd += ["alpha"]
    cmd += [
        "compute",
        "tpus",
        "tpu-vm",
        "ssh",
        args.tpu_name,
        "--zone",
        args.tpu_zone,
        "--command",
        args.command,
        "--worker",
        "all",
    ]
    if args.debug:
        print(F'''Running {" ".join(lowerCamelCase_				)}'''				)
        return
    subprocess.run(lowerCamelCase_				)
    print('Successfully setup pod.'				)



def        UpperCamelCase_(   )					->		Union[str, Any]:
    _lowercase :							Dict   	=	tpu_command_parser()
    _lowercase :							Optional[int]   	=	parser.parse_args()

    tpu_command_launcher(lowerCamelCase_				)






def        UpperCamelCase_(   lowerCamelCase_				)					->		int:
    assert (
        isinstance(lowerCamelCase_							,				lowerCamelCase_				) and number_of_steps > 0
    ), F'''number_of_steps needs to be positive integer, your input {number_of_steps}'''
    if number_of_steps == 1:
        return 1
    _lowercase	,       _lowercase :							Dict   	=	1, 1
    for _ in range(number_of_steps - 1				):
        _lowercase	,       _lowercase :							Tuple   	=	current + previous, current
    return current


if __name__ == "__main__":
 import doctest

 doctest.testmod()


