





"""simple docstring"""




import json
import os
import shutil
import warnings
from argparse import ArgumentParser, Namespace
from pathlib import Path
from typing import List

from ..utils import logging
from . import BaseTransformersCLICommand


try:
						from cookiecutter.main import cookiecutter

						UpperCamelCase_									=True
except ImportError:
						UpperCamelCase_									=False

UpperCamelCase_									=logging.get_logger(__name__)  # pylint: disable=invalid-name





def 	a_    (							_lowercase       ):
						return AddNewModelCommand(args.testing	,						args.testing_file	,						path=args.path       )






class 			_a						(				_lowerCAmelCase    ):






				@staticmethod
				def     snake_case     (			lowerCAmelCase__		:   str							)     ->				Optional[int]:




										'''simple docstring'''



										_UpperCamelCase      : Tuple         =   parser.add_parser('''add-new-model'''							)
										add_new_model_parser.add_argument('''--testing''',			action='''store_true''',			help='''If in testing mode.'''							)
										add_new_model_parser.add_argument('''--testing_file''',			type=lowerCamelCase_,			help='''Configuration file on which to run.'''							)
										add_new_model_parser.add_argument(
										    '''--path''',			type=lowerCamelCase_,			help='''Path to cookiecutter. Should only be used for testing purposes.'''							)
										add_new_model_parser.set_defaults(func=lowerCamelCase_							)






				def __init__(			self		:   Optional[int],			lowerCAmelCase__		:   Optional[Any],			lowerCAmelCase__		:   Union[str, Any],			lowerCAmelCase__		:   Any=None,			*lowerCAmelCase__		:   Any							)     ->				Any:




										'''simple docstring'''



										_UpperCamelCase      : int         =   testing
										_UpperCamelCase      : str         =   testing_file
										_UpperCamelCase      : Optional[Any]         =   path






				def     snake_case     (			self		:   List[str]							)     ->				int:




										'''simple docstring'''



										warnings.warn(
										    '''The command `transformers-cli add-new-model` is deprecated and will be removed in v5 of Transformers. '''
										    '''It is not actively maintained anymore, so might give a result that won\'t pass all tests and quality '''
										    '''checks, you should use `transformers-cli add-new-model-like` instead.'''							)
										if not _has_cookiecutter:
																raise ImportError(
																    '''Model creation dependencies are required to use the `add_new_model` command. Install them by running '''
																    '''the following at the root of your `transformers` clone:\n\n\t$ pip install -e .[modelcreation]\n'''							)
										# Ensure that there is no other `cookiecutter-template-xxx` directory in the current working directory
										_UpperCamelCase      : Dict         =   [directory for directory in os.listdir() if '''cookiecutter-template-''' == directory[:2_2]]
										if len(lowerCamelCase_							) > 0:
																raise ValueError(
																    '''Several directories starting with `cookiecutter-template-` in current working directory. '''
																    '''Please clean your directory by removing all folders starting with `cookiecutter-template-` or '''
																    '''change your working directory.'''							)

										_UpperCamelCase      : List[str]         =   (
										    Path(lowerCamelCase_							).parent.parent.parent.parent if self._path is None else Path(self._path							).parent.parent
										)
										_UpperCamelCase      : Union[str, Any]         =   path_to_transformer_root / '''templates''' / '''adding_a_new_model'''

										# Execute cookiecutter
										if not self._testing:
																cookiecutter(str(lowerCamelCase_							)							)
										else:
																with open(self._testing_file,			'''r'''							) as configuration_file:
																						_UpperCamelCase      : Dict         =   json.load(lowerCamelCase_							)

																cookiecutter(
																    str(path_to_cookiecutter if self._path is None else self._path							),			no_input=lowerCamelCase_,			extra_context=lowerCamelCase_,			)

										_UpperCamelCase      : int         =   [directory for directory in os.listdir() if '''cookiecutter-template-''' in directory[:2_2]][0]

										# Retrieve configuration
										with open(directory + '''/configuration.json''',			'''r'''							) as configuration_file:
																_UpperCamelCase      : Union[str, Any]         =   json.load(lowerCamelCase_							)

										_UpperCamelCase      : Dict         =   configuration['''lowercase_modelname''']
										_UpperCamelCase      : str         =   configuration['''generate_tensorflow_pytorch_and_flax''']
										os.remove(f"""{directory}/configuration.json"""							)

										_UpperCamelCase      : int         =   '''PyTorch''' in generate_tensorflow_pytorch_and_flax
										_UpperCamelCase      : Dict         =   '''TensorFlow''' in generate_tensorflow_pytorch_and_flax
										_UpperCamelCase      : str         =   '''Flax''' in generate_tensorflow_pytorch_and_flax

										_UpperCamelCase      : Any         =   f"""{path_to_transformer_root}/src/transformers/models/{lowercase_model_name}"""
										os.makedirs(lowerCamelCase_,			exist_ok=lowerCamelCase_							)
										os.makedirs(f"""{path_to_transformer_root}/tests/models/{lowercase_model_name}""",			exist_ok=lowerCamelCase_							)

										# Tests require submodules as they have parent imports
										with open(f"""{path_to_transformer_root}/tests/models/{lowercase_model_name}/__init__.py""",			'''w'''							):
																pass

										shutil.move(
										    f"""{directory}/__init__.py""",			f"""{model_dir}/__init__.py""",			)
										shutil.move(
										    f"""{directory}/configuration_{lowercase_model_name}.py""",			f"""{model_dir}/configuration_{lowercase_model_name}.py""",			)

										def remove_copy_lines(lowerCAmelCase__		:   List[Any]							):
																with open(lowerCamelCase_,			'''r'''							) as f:
																						_UpperCamelCase      : List[str]         =   f.readlines()
																with open(lowerCamelCase_,			'''w'''							) as f:
																						for line in lines:
																												if "# Copied from transformers." not in line:
																																		f.write(lowerCamelCase_							)

										if output_pytorch:
																if not self._testing:
																						remove_copy_lines(f"""{directory}/modeling_{lowercase_model_name}.py"""							)

																shutil.move(
																    f"""{directory}/modeling_{lowercase_model_name}.py""",			f"""{model_dir}/modeling_{lowercase_model_name}.py""",			)

																shutil.move(
																    f"""{directory}/test_modeling_{lowercase_model_name}.py""",			f"""{path_to_transformer_root}/tests/models/{lowercase_model_name}/test_modeling_{lowercase_model_name}.py""",			)
										else:
																os.remove(f"""{directory}/modeling_{lowercase_model_name}.py"""							)
																os.remove(f"""{directory}/test_modeling_{lowercase_model_name}.py"""							)

										if output_tensorflow:
																if not self._testing:
																						remove_copy_lines(f"""{directory}/modeling_tf_{lowercase_model_name}.py"""							)

																shutil.move(
																    f"""{directory}/modeling_tf_{lowercase_model_name}.py""",			f"""{model_dir}/modeling_tf_{lowercase_model_name}.py""",			)

																shutil.move(
																    f"""{directory}/test_modeling_tf_{lowercase_model_name}.py""",			f"""{path_to_transformer_root}/tests/models/{lowercase_model_name}/test_modeling_tf_{lowercase_model_name}.py""",			)
										else:
																os.remove(f"""{directory}/modeling_tf_{lowercase_model_name}.py"""							)
																os.remove(f"""{directory}/test_modeling_tf_{lowercase_model_name}.py"""							)

										if output_flax:
																if not self._testing:
																						remove_copy_lines(f"""{directory}/modeling_flax_{lowercase_model_name}.py"""							)

																shutil.move(
																    f"""{directory}/modeling_flax_{lowercase_model_name}.py""",			f"""{model_dir}/modeling_flax_{lowercase_model_name}.py""",			)

																shutil.move(
																    f"""{directory}/test_modeling_flax_{lowercase_model_name}.py""",			f"""{path_to_transformer_root}/tests/models/{lowercase_model_name}/test_modeling_flax_{lowercase_model_name}.py""",			)
										else:
																os.remove(f"""{directory}/modeling_flax_{lowercase_model_name}.py"""							)
																os.remove(f"""{directory}/test_modeling_flax_{lowercase_model_name}.py"""							)

										shutil.move(
										    f"""{directory}/{lowercase_model_name}.md""",			f"""{path_to_transformer_root}/docs/source/en/model_doc/{lowercase_model_name}.md""",			)

										shutil.move(
										    f"""{directory}/tokenization_{lowercase_model_name}.py""",			f"""{model_dir}/tokenization_{lowercase_model_name}.py""",			)

										shutil.move(
										    f"""{directory}/tokenization_fast_{lowercase_model_name}.py""",			f"""{model_dir}/tokenization_{lowercase_model_name}_fast.py""",			)

										from os import fdopen, remove
										from shutil import copymode, move
										from tempfile import mkstemp

										def replace(lowerCAmelCase__		:   int,			lowerCAmelCase__		:   str,			lowerCAmelCase__		:   Union[str, Any]							):
																# Create temp file
																_UpperCamelCase       ,							_UpperCamelCase      : Tuple         =   mkstemp()
																_UpperCamelCase      : Optional[Any]         =   False
																with fdopen(lowerCamelCase_,			'''w'''							) as new_file:
																						with open(lowerCamelCase_							) as old_file:
																												for line in old_file:
																																		new_file.write(lowerCamelCase_							)
																																		if line_to_copy_below in line:
																																								_UpperCamelCase      : Optional[Any]         =   True
																																								for line_to_copy in lines_to_copy:
																																														new_file.write(lowerCamelCase_							)

																if not line_found:
																						raise ValueError(f"""Line {line_to_copy_below} was not found in file."""							)

																# Copy the file permissions from the old file to the new file
																copymode(lowerCamelCase_,			lowerCamelCase_							)
																# Remove original file
																remove(lowerCamelCase_							)
																# Move new file
																move(lowerCamelCase_,			lowerCamelCase_							)

										def skip_units(lowerCAmelCase__		:   Dict							):
																return (
																    ("generating PyTorch" in line and not output_pytorch)
																    or ("generating TensorFlow" in line and not output_tensorflow)
																    or ("generating Flax" in line and not output_flax)
																)

										def replace_in_files(lowerCAmelCase__		:   str							):
																with open(lowerCamelCase_							) as datafile:
																						_UpperCamelCase      : Tuple         =   []
																						_UpperCamelCase      : str         =   False
																						_UpperCamelCase      : Any         =   False
																						for line in datafile:
																												if "# To replace in: " in line and "##" not in line:
																																		_UpperCamelCase      : int         =   line.split('''\"'''							)[1]
																																		_UpperCamelCase      : List[str]         =   skip_units(lowerCamelCase_							)
																												elif "# Below: " in line and "##" not in line:
																																		_UpperCamelCase      : str         =   line.split('''\"'''							)[1]
																																		_UpperCamelCase      : Optional[int]         =   skip_units(lowerCamelCase_							)
																												elif "# End." in line and "##" not in line:
																																		if not skip_file and not skip_snippet:
																																								replace(lowerCamelCase_,			lowerCamelCase_,			lowerCamelCase_							)

																																		_UpperCamelCase      : int         =   []
																												elif "# Replace with" in line and "##" not in line:
																																		_UpperCamelCase      : str         =   []
																												elif "##" not in line:
																																		lines_to_copy.append(lowerCamelCase_							)

																remove(lowerCamelCase_							)

										replace_in_files(f"""{directory}/to_replace_{lowercase_model_name}.py"""							)
										os.rmdir(lowerCamelCase_							)










"""simple docstring"""




class 			_a						:






				def __init__(			self		:   Optional[int],			lowerCAmelCase__		:   list							)     ->				None:




										'''simple docstring'''



										_UpperCamelCase      : Optional[int]         =   set_counts
										_UpperCamelCase      : Any         =   max(lowerCAmelCase__							)
										_UpperCamelCase      : int         =   len(lowerCAmelCase__							)
										_UpperCamelCase      : int         =   [1] * num_sets
										_UpperCamelCase      : List[Any]         =   list(range(lowerCAmelCase__							)							)






				def     snake_case     (			self		:   int,			lowerCAmelCase__		:   int,			lowerCAmelCase__		:   int							)     ->				bool:




										'''simple docstring'''



										_UpperCamelCase      : Optional[Any]         =   self.get_parent(lowerCAmelCase__							)
										_UpperCamelCase      : Any         =   self.get_parent(lowerCAmelCase__							)

										if src_parent == dst_parent:
																return False

										if self.ranks[dst_parent] >= self.ranks[src_parent]:
																self.set_counts[dst_parent] += self.set_counts[src_parent]
																_UpperCamelCase      : List[Any]         =   0
																_UpperCamelCase      : str         =   dst_parent
																if self.ranks[dst_parent] == self.ranks[src_parent]:
																						self.ranks[dst_parent] += 1
																_UpperCamelCase      : Union[str, Any]         =   self.set_counts[dst_parent]
										else:
																self.set_counts[src_parent] += self.set_counts[dst_parent]
																_UpperCamelCase      : Tuple         =   0
																_UpperCamelCase      : Optional[Any]         =   src_parent
																_UpperCamelCase      : int         =   self.set_counts[src_parent]

										_UpperCamelCase      : Optional[Any]         =   max(self.max_set,			lowerCAmelCase__							)
										return True






				def     snake_case     (			self		:   Optional[Any],			lowerCAmelCase__		:   int							)     ->				int:




										'''simple docstring'''



										if self.parents[disj_set] == disj_set:
																return disj_set
										_UpperCamelCase      : Union[str, Any]         =   self.get_parent(self.parents[disj_set]							)
										return self.parents[disj_set]



