






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

					__snake_case    :    int         =     True
except ImportError:
					__snake_case    :    Tuple         =     False

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







def 	_UpperCamelCase   (    UpperCamelCase_       :					Namespace		)  ->   str:

						"""simple docstring"""



						return AddNewModelCommand(args.testing    ,       args.testing_file    ,       path=args.path		)


class     __SCREAMING_SNAKE_CASE					(   __lowercase):






						@staticmethod
						def       UpperCamelCase__      (	_UpperCamelCase   ):






												"""simple docstring"""
												lowerCAmelCase__    						=						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=_UpperCamelCase     ,						help='Configuration file on which to run.'   )
												add_new_model_parser.add_argument(
												    '--path'     ,						type=_UpperCamelCase     ,						help='Path to cookiecutter. Should only be used for testing purposes.'   )
												add_new_model_parser.set_defaults(func=_UpperCamelCase   )






						def __init__(	self     ,						_UpperCamelCase     ,						_UpperCamelCase     ,						_UpperCamelCase=None     ,						*_UpperCamelCase   ):






												"""simple docstring"""
												lowerCAmelCase__    						=						testing
												lowerCAmelCase__    						=						testing_file
												lowerCAmelCase__    						=						path







						def       UpperCamelCase__      (	self   ):






												"""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
												lowerCAmelCase__    						=						[directory for directory in os.listdir() if 'cookiecutter-template-' == directory[:22]]
												if len(_UpperCamelCase   ) > 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.'   )

												lowerCAmelCase__    						=						(
												    Path(_UpperCamelCase   ).parent.parent.parent.parent if self._path is None else Path(self._path   ).parent.parent
												)
												lowerCAmelCase__    						=						path_to_transformer_root / 'templates' / 'adding_a_new_model'

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

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

												lowerCAmelCase__    						=						[directory for directory in os.listdir() if 'cookiecutter-template-' in directory[:22]][0]

												# Retrieve configuration
												with open(directory + '/configuration.json'     ,						'r'   ) as configuration_file:
																		lowerCAmelCase__    						=						json.load(_UpperCamelCase   )

												lowerCAmelCase__    						=						configuration['lowercase_modelname']
												lowerCAmelCase__    						=						configuration['generate_tensorflow_pytorch_and_flax']
												os.remove(F"{directory}/configuration.json"   )

												lowerCAmelCase__    						=						'PyTorch' in generate_tensorflow_pytorch_and_flax
												lowerCAmelCase__    						=						'TensorFlow' in generate_tensorflow_pytorch_and_flax
												lowerCAmelCase__    						=						'Flax' in generate_tensorflow_pytorch_and_flax

												lowerCAmelCase__    						=						F"{path_to_transformer_root}/src/transformers/models/{lowercase_model_name}"
												os.makedirs(_UpperCamelCase     ,						exist_ok=_UpperCamelCase   )
												os.makedirs(F"{path_to_transformer_root}/tests/models/{lowercase_model_name}"     ,						exist_ok=_UpperCamelCase   )

												# 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(_UpperCamelCase   ):
																		with open(_UpperCamelCase     ,						'r'   ) as f:
																								lowerCAmelCase__    						=						f.readlines()
																		with open(_UpperCamelCase     ,						'w'   ) as f:
																								for line in lines:
																														if "# Copied from transformers." not in line:
																																				f.write(_UpperCamelCase   )

												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(_UpperCamelCase     ,						_UpperCamelCase     ,						_UpperCamelCase   ):
																		# Create temp file
																		lowerCAmelCase__						,       lowerCAmelCase__    						=						mkstemp()
																		lowerCAmelCase__    						=						False
																		with fdopen(_UpperCamelCase     ,						'w'   ) as new_file:
																								with open(_UpperCamelCase   ) as old_file:
																														for line in old_file:
																																				new_file.write(_UpperCamelCase   )
																																				if line_to_copy_below in line:
																																										lowerCAmelCase__    						=						True
																																										for line_to_copy in lines_to_copy:
																																																new_file.write(_UpperCamelCase   )

																		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(_UpperCamelCase     ,						_UpperCamelCase   )
																		# Remove original file
																		remove(_UpperCamelCase   )
																		# Move new file
																		move(_UpperCamelCase     ,						_UpperCamelCase   )

												def skip_units(_UpperCamelCase   ):
																		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(_UpperCamelCase   ):
																		with open(_UpperCamelCase   ) as datafile:
																								lowerCAmelCase__    						=						[]
																								lowerCAmelCase__    						=						False
																								lowerCAmelCase__    						=						False
																								for line in datafile:
																														if "# To replace in: " in line and "##" not in line:
																																				lowerCAmelCase__    						=						line.split('"'   )[1]
																																				lowerCAmelCase__    						=						skip_units(_UpperCamelCase   )
																														elif "# Below: " in line and "##" not in line:
																																				lowerCAmelCase__    						=						line.split('"'   )[1]
																																				lowerCAmelCase__    						=						skip_units(_UpperCamelCase   )
																														elif "# End." in line and "##" not in line:
																																				if not skip_file and not skip_snippet:
																																										replace(_UpperCamelCase     ,						_UpperCamelCase     ,						_UpperCamelCase   )

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

																		remove(_UpperCamelCase   )

												replace_in_files(F"{directory}/to_replace_{lowercase_model_name}.py"   )
												os.rmdir(_UpperCamelCase   )













__snake_case    :    Tuple         =     range(2, 20 + 1)
__snake_case    :    str         =     [10**k for k in range(ks[-1] + 1)]
__snake_case    :    dict[int, dict[int, list[list[int]]]]         =     {}







def 	_UpperCamelCase   (    UpperCamelCase_       :					Optional[int]    ,       UpperCamelCase_       :					List[Any]    ,       UpperCamelCase_       :					List[Any]    ,       UpperCamelCase_       :					Tuple		)  ->   List[Any]:

						"""simple docstring"""



						lowerCAmelCase__    						=						sum(a_i[j] for j in range(UpperCamelCase_    ,       len(UpperCamelCase_		)		)		)
						lowerCAmelCase__    						=						sum(a_i[j] * base[j] for j in range(min(len(UpperCamelCase_		)    ,       UpperCamelCase_		)		)		)

						lowerCAmelCase__						,       lowerCAmelCase__    						=						0, 0
						lowerCAmelCase__    						=						n - i

						lowerCAmelCase__    						=						memo.get(UpperCamelCase_		)

						if sub_memo is not None:
												lowerCAmelCase__    						=						sub_memo.get(UpperCamelCase_		)

												if jumps is not None and len(UpperCamelCase_		) > 0:
																		# find and make the largest jump without going over
																		lowerCAmelCase__    						=						-1
																		for _k in range(len(UpperCamelCase_		) - 1    ,       -1    ,       -1		):
																								if jumps[_k][2] <= k and jumps[_k][1] <= max_dn:
																														lowerCAmelCase__    						=						_k
																														break

																		if max_jump >= 0:
																								lowerCAmelCase__						,       lowerCAmelCase__						,       lowerCAmelCase__    						=						jumps[max_jump]
																								# since the difference between jumps is cached, add c
																								lowerCAmelCase__    						=						diff + c
																								for j in range(min(UpperCamelCase_    ,       len(UpperCamelCase_		)		)		):
																														lowerCAmelCase__						,       lowerCAmelCase__    						=						divmod(UpperCamelCase_    ,       10		)
																								if new_c > 0:
																														add(UpperCamelCase_    ,       UpperCamelCase_    ,       UpperCamelCase_		)

												else:
																		lowerCAmelCase__    						=						[]
						else:
												lowerCAmelCase__    						=						{c: []}
												lowerCAmelCase__    						=						sub_memo

						if dn >= max_dn or c + diff >= base[k]:
												return diff, dn

						if k > ks[0]:
												while True:
																		# keep doing smaller jumps
																		lowerCAmelCase__						,       lowerCAmelCase__    						=						next_term(UpperCamelCase_    ,       k - 1    ,       i + dn    ,       UpperCamelCase_		)
																		diff += _diff
																		dn += terms_jumped

																		if dn >= max_dn or c + diff >= base[k]:
																								break
						else:
												# would be too small a jump, just compute sequential terms instead
												lowerCAmelCase__						,       lowerCAmelCase__    						=						compute(UpperCamelCase_    ,       UpperCamelCase_    ,       i + dn    ,       UpperCamelCase_		)
												diff += _diff
												dn += terms_jumped

						lowerCAmelCase__    						=						sub_memo[c]

						# keep jumps sorted by # of terms skipped
						lowerCAmelCase__    						=						0
						while j < len(UpperCamelCase_		):
												if jumps[j][1] > dn:
																		break
												j += 1

						# cache the jump for this value digitsum(b) and c
						sub_memo[c].insert(UpperCamelCase_    ,       (diff, dn, k)		)
						return (diff, dn)







def 	_UpperCamelCase   (    UpperCamelCase_       :					Tuple    ,       UpperCamelCase_       :					List[str]    ,       UpperCamelCase_       :					int    ,       UpperCamelCase_       :					Tuple		)  ->   List[str]:

						"""simple docstring"""



						if i >= n:
												return 0, i
						if k > len(UpperCamelCase_		):
												a_i.extend([0 for _ in range(k - len(UpperCamelCase_		)		)]		)

						# note: a_i -> b * 10^k + c
						# ds_b -> digitsum(b)
						# ds_c -> digitsum(c)
						lowerCAmelCase__    						=						i
						lowerCAmelCase__						,       lowerCAmelCase__						,       lowerCAmelCase__    						=						0, 0, 0
						for j in range(len(UpperCamelCase_		)		):
												if j >= k:
																		ds_b += a_i[j]
												else:
																		ds_c += a_i[j]

						while i < n:
												i += 1
												lowerCAmelCase__    						=						ds_c + ds_b
												diff += addend
												lowerCAmelCase__    						=						0
												for j in range(UpperCamelCase_		):
																		lowerCAmelCase__    						=						a_i[j] + addend
																		lowerCAmelCase__						,       lowerCAmelCase__    						=						divmod(UpperCamelCase_    ,       10		)

																		ds_c += a_i[j]

												if addend > 0:
																		break

						if addend > 0:
												add(UpperCamelCase_    ,       UpperCamelCase_    ,       UpperCamelCase_		)
						return diff, i - start_i







def 	_UpperCamelCase   (    UpperCamelCase_       :					Tuple    ,       UpperCamelCase_       :					Optional[int]    ,       UpperCamelCase_       :					List[str]		)  ->   List[str]:

						"""simple docstring"""



						for j in range(UpperCamelCase_    ,       len(UpperCamelCase_		)		):
												lowerCAmelCase__    						=						digits[j] + addend
												if s >= 10:
																		lowerCAmelCase__						,       lowerCAmelCase__    						=						divmod(UpperCamelCase_    ,       10		)
																		lowerCAmelCase__    						=						addend // 10 + quotient
												else:
																		lowerCAmelCase__    						=						s
																		lowerCAmelCase__    						=						addend // 10

												if addend == 0:
																		break

						while addend > 0:
												lowerCAmelCase__						,       lowerCAmelCase__    						=						divmod(UpperCamelCase_    ,       10		)
												digits.append(UpperCamelCase_		)







def 	_UpperCamelCase   (    UpperCamelCase_       :					int = 10**15		)  ->   int:

						"""simple docstring"""



						lowerCAmelCase__    						=						[1]
						lowerCAmelCase__    						=						1
						lowerCAmelCase__    						=						0
						while True:
												lowerCAmelCase__						,       lowerCAmelCase__    						=						next_term(UpperCamelCase_    ,       20    ,       i + dn    ,       UpperCamelCase_		)
												dn += terms_jumped
												if dn == n - i:
																		break

						lowerCAmelCase__    						=						0
						for j in range(len(UpperCamelCase_		)		):
												a_n += digits[j] * 10**j
						return a_n


if __name__ == "__main__":
					print(f'{solution() = }')





