
import logging
import os
import threading
import time


try:
						import warnings
except ImportError:
						_snake_case      :							Optional[int]     	=    None

try:
						import msvcrt
except ImportError:
						_snake_case      :							List[str]     	=    None

try:
						import fcntl
except ImportError:
						_snake_case      :							int     	=    None


# Backward compatibility
# ------------------------------------------------
try:
						TimeoutError
except NameError:
						_snake_case      :							int     	=    OSError


# Data
# ------------------------------------------------
_snake_case      :							str     	=    [
    "Timeout",
    "BaseFileLock",
    "WindowsFileLock",
    "UnixFileLock",
    "SoftFileLock",
    "FileLock",
]

_snake_case      :							List[Any]     	=    "3.0.12"


_snake_case      :							List[Any]     	=    None

def  __snake_case							(	):







				'''simple docstring'''


				global _logger
				lowercase         =      _logger or logging.getLogger(__name__						)
				return _logger





class   UpperCamelCase_      (      __a		):







						'''simple docstring'''



						def __init__(			self							:List[str]		,    lowerCAmelCase__							:int     )  ->Dict:
										lowercase         =      lock_file
										return None





						def __str__(			self							:Optional[int]     )  ->Tuple:
										lowercase         =      F'''The file lock \'{self.lock_file}\' could not be acquired.'''
										return temp





class   UpperCamelCase_      :







						'''simple docstring'''



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





						def __enter__(			self							:List[str]     )  ->str:
										return self.lock





						def __exit__(			self							:Union[str, Any]		,    lowerCAmelCase__							:Dict		,    lowerCAmelCase__							:Tuple		,    lowerCAmelCase__							:List[str]     )  ->Optional[int]:
										self.lock.release()
										return None





class   UpperCamelCase_      :







						'''simple docstring'''



						def __init__(			self							:Any		,    lowerCAmelCase__							:Any		,    lowerCAmelCase__							:Optional[int]=-1		,    lowerCAmelCase__							:int=None     )  ->Dict:
										lowercase         =      max_filename_length if max_filename_length is not None else 255
										# Hash the filename if it's too long
										lowercase         =      self.hash_filename_if_too_long(lowerCAmelCase__		,    lowerCAmelCase__     )
										# The path to the lock file.
										lowercase         =      lock_file

										# The file descriptor for the *_lock_file* as it is returned by the
										# os.open() function.
										# This file lock is only NOT None, if the object currently holds the
										# lock.
										lowercase         =      None

										# The default timeout value.
										lowercase         =      timeout

										# We use this lock primarily for the lock counter.
										lowercase         =      threading.Lock()

										# The lock counter is used for implementing the nested locking
										# mechanism. Whenever the lock is acquired, the counter is increased and
										# the lock is only released, when this value is 0 again.
										lowercase         =      0
										return None





						@property
						def        SCREAMING_SNAKE_CASE(			self							:Optional[Any]     )  ->str:
										return self._lock_file





						@property
						def        SCREAMING_SNAKE_CASE(			self							:Dict     )  ->Dict:
										return self._timeout





						@timeout.setter
						def        SCREAMING_SNAKE_CASE(			self							:Union[str, Any]		,    lowerCAmelCase__							:Optional[Any]     )  ->List[str]:
										lowercase         =      float(lowerCAmelCase__     )
										return None





						def        SCREAMING_SNAKE_CASE(			self							:Any     )  ->str:
										raise NotImplementedError()





						def        SCREAMING_SNAKE_CASE(			self							:Union[str, Any]     )  ->str:
										raise NotImplementedError()





						@property
						def        SCREAMING_SNAKE_CASE(			self							:Optional[Any]     )  ->Any:
										return self._lock_file_fd is not None





						def        SCREAMING_SNAKE_CASE(			self							:List[str]		,    lowerCAmelCase__							:Optional[Any]=None		,    lowerCAmelCase__							:int=0.05     )  ->Optional[int]:
										# Use the default timeout, if no timeout is provided.
										if timeout is None:
														lowercase         =      self.timeout

										# Increment the number right at the beginning.
										# We can still undo it, if something fails.
										with self._thread_lock:
														self._lock_counter += 1

										lowercase         =      id(self     )
										lowercase         =      self._lock_file
										lowercase         =      time.time()
										try:
														while True:
																		with self._thread_lock:
																						if not self.is_locked:
																										logger().debug(F'''Attempting to acquire lock {lock_id} on {lock_filename}'''     )
																										self._acquire()

																		if self.is_locked:
																						logger().debug(F'''Lock {lock_id} acquired on {lock_filename}'''     )
																						break
																		elif timeout >= 0 and time.time() - start_time > timeout:
																						logger().debug(F'''Timeout on acquiring lock {lock_id} on {lock_filename}'''     )
																						raise Timeout(self._lock_file     )
																		else:
																						logger().debug(
																						    F'''Lock {lock_id} not acquired on {lock_filename}, waiting {poll_intervall} seconds ...'''     )
																						time.sleep(lowerCAmelCase__     )
										except:  # noqa
														# Something did go wrong, so decrement the counter.
														with self._thread_lock:
																		lowercase         =      max(0		,    self._lock_counter - 1     )

														raise
										return _Acquire_ReturnProxy(lock=self     )





						def        SCREAMING_SNAKE_CASE(			self							:str		,    lowerCAmelCase__							:Any=False     )  ->int:
										with self._thread_lock:
														if self.is_locked:
																		self._lock_counter -= 1

																		if self._lock_counter == 0 or force:
																						lowercase         =      id(self     )
																						lowercase         =      self._lock_file

																						logger().debug(F'''Attempting to release lock {lock_id} on {lock_filename}'''     )
																						self._release()
																						lowercase         =      0
																						logger().debug(F'''Lock {lock_id} released on {lock_filename}'''     )

										return None





						def __enter__(			self							:List[str]     )  ->Any:
										self.acquire()
										return self





						def __exit__(			self							:List[Any]		,    lowerCAmelCase__							:int		,    lowerCAmelCase__							:Tuple		,    lowerCAmelCase__							:str     )  ->Optional[int]:
										self.release()
										return None





						def __del__(			self							:Tuple     )  ->str:
										self.release(force=lowerCAmelCase__     )
										return None





						def        SCREAMING_SNAKE_CASE(			self							:Dict		,    lowerCAmelCase__							:str		,    lowerCAmelCase__							:int     )  ->str:
										lowercase         =      os.path.basename(lowerCAmelCase__     )
										if len(lowerCAmelCase__     ) > max_length and max_length > 0:
														lowercase         =      os.path.dirname(lowerCAmelCase__     )
														lowercase         =      str(hash(lowerCAmelCase__     )     )
														lowercase         =      filename[: max_length - len(lowerCAmelCase__     ) - 8] + "..." + hashed_filename + ".lock"
														return os.path.join(lowerCAmelCase__		,    lowerCAmelCase__     )
										else:
														return path





class   UpperCamelCase_      (      __a		):







						'''simple docstring'''



						def __init__(			self							:List[str]		,    lowerCAmelCase__							:str		,    lowerCAmelCase__							:List[str]=-1		,    lowerCAmelCase__							:List[str]=None     )  ->Any:
										from .file_utils import relative_to_absolute_path

										super().__init__(lowerCAmelCase__		,    timeout=lowerCAmelCase__		,    max_filename_length=lowerCAmelCase__     )
										lowercase         =      "\\\\?\\" + relative_to_absolute_path(self.lock_file     )





						def        SCREAMING_SNAKE_CASE(			self							:str     )  ->Optional[int]:
										lowercase         =      os.O_RDWR | os.O_CREAT | os.O_TRUNC

										try:
														lowercase         =      os.open(self._lock_file		,    lowerCAmelCase__     )
										except OSError:
														pass
										else:
														try:
																		msvcrt.locking(lowerCAmelCase__		,    msvcrt.LK_NBLCK		,    1     )
														except OSError:
																		os.close(lowerCAmelCase__     )
														else:
																		lowercase         =      fd
										return None





						def        SCREAMING_SNAKE_CASE(			self							:int     )  ->List[Any]:
										lowercase         =      self._lock_file_fd
										lowercase         =      None
										msvcrt.locking(lowerCAmelCase__		,    msvcrt.LK_UNLCK		,    1     )
										os.close(lowerCAmelCase__     )

										try:
														os.remove(self._lock_file     )
										# Probably another instance of the application
										# that acquired the file lock.
										except OSError:
														pass
										return None





class   UpperCamelCase_      (      __a		):







						'''simple docstring'''



						def __init__(			self							:Any		,    lowerCAmelCase__							:int		,    lowerCAmelCase__							:Union[str, Any]=-1		,    lowerCAmelCase__							:str=None     )  ->Dict:
										lowercase         =      os.statvfs(os.path.dirname(lowerCAmelCase__     )     ).f_namemax
										super().__init__(lowerCAmelCase__		,    timeout=lowerCAmelCase__		,    max_filename_length=lowerCAmelCase__     )





						def        SCREAMING_SNAKE_CASE(			self							:str     )  ->Tuple:
										lowercase         =      os.O_RDWR | os.O_CREAT | os.O_TRUNC
										lowercase         =      os.open(self._lock_file		,    lowerCAmelCase__     )

										try:
														fcntl.flock(lowerCAmelCase__		,    fcntl.LOCK_EX | fcntl.LOCK_NB     )
										except OSError:
														os.close(lowerCAmelCase__     )
										else:
														lowercase         =      fd
										return None





						def        SCREAMING_SNAKE_CASE(			self							:int     )  ->Union[str, Any]:
										# Do not remove the lockfile:
										#
										#   https://github.com/benediktschmitt/py-filelock/issues/31
										#   https://stackoverflow.com/questions/17708885/flock-removing-locked-file-without-race-condition
										lowercase         =      self._lock_file_fd
										lowercase         =      None
										fcntl.flock(lowerCAmelCase__		,    fcntl.LOCK_UN     )
										os.close(lowerCAmelCase__     )
										return None





class   UpperCamelCase_      (      __a		):







						'''simple docstring'''



						def        SCREAMING_SNAKE_CASE(			self							:Optional[int]     )  ->Tuple:
										lowercase         =      os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_TRUNC
										try:
														lowercase         =      os.open(self._lock_file		,    lowerCAmelCase__     )
										except OSError:
														pass
										else:
														lowercase         =      fd
										return None





						def        SCREAMING_SNAKE_CASE(			self							:Dict     )  ->int:
										os.close(self._lock_file_fd     )
										lowercase         =      None

										try:
														os.remove(self._lock_file     )
										# The file is already deleted and that's what we want.
										except OSError:
														pass
										return None




_snake_case      :							str     	=    None

if msvcrt:
						_snake_case      :							List[Any]     	=    WindowsFileLock
elif fcntl:
						_snake_case      :							Any     	=    UnixFileLock
else:
						_snake_case      :							Tuple     	=    SoftFileLock

						if warnings is not None:
												warnings.warn("only soft file lock is available")


import os
from argparse import ArgumentParser, Namespace

from ..data import SingleSentenceClassificationProcessor as Processor
from ..pipelines import TextClassificationPipeline
from ..utils import is_tf_available, is_torch_available, logging
from . import BaseTransformersCLICommand


if not is_tf_available() and not is_torch_available():
						raise RuntimeError("At least one of PyTorch or TensorFlow 2.0+ should be installed to use CLI training")

# TF training parameters
_snake_case      :							Any     	=    False
_snake_case      :							int     	=    False

def  __snake_case							(	__magic_name__						):







				'''simple docstring'''


				return TrainCommand(__magic_name__						)





class   UpperCamelCase_      (      __a		):







						'''simple docstring'''



						@staticmethod
						def        SCREAMING_SNAKE_CASE(			lowerCAmelCase__							:ArgumentParser     )  ->str:
										lowercase         =      parser.add_parser("train"		,    help="CLI tool to train a model on a task."     )

										train_parser.add_argument(
										    "--train_data"		,    type=lowerCAmelCase__		,    required=lowerCAmelCase__		,    help="path to train (and optionally evaluation) dataset as a csv with tab separated labels and sentences."		,    )
										train_parser.add_argument(
										    "--column_label"		,    type=lowerCAmelCase__		,    default=0		,    help="Column of the dataset csv file with example labels."     )
										train_parser.add_argument(
										    "--column_text"		,    type=lowerCAmelCase__		,    default=1		,    help="Column of the dataset csv file with example texts."     )
										train_parser.add_argument(
										    "--column_id"		,    type=lowerCAmelCase__		,    default=2		,    help="Column of the dataset csv file with example ids."     )
										train_parser.add_argument(
										    "--skip_first_row"		,    action="store_true"		,    help="Skip the first row of the csv file (headers)."     )

										train_parser.add_argument("--validation_data"		,    type=lowerCAmelCase__		,    default=""		,    help="path to validation dataset."     )
										train_parser.add_argument(
										    "--validation_split"		,    type=lowerCAmelCase__		,    default=0.1		,    help="if validation dataset is not provided, fraction of train dataset to use as validation dataset."		,    )

										train_parser.add_argument("--output"		,    type=lowerCAmelCase__		,    default="./"		,    help="path to saved the trained model."     )

										train_parser.add_argument(
										    "--task"		,    type=lowerCAmelCase__		,    default="text_classification"		,    help="Task to train the model on."     )
										train_parser.add_argument(
										    "--model"		,    type=lowerCAmelCase__		,    default="bert-base-uncased"		,    help="Model's name or path to stored model."     )
										train_parser.add_argument("--train_batch_size"		,    type=lowerCAmelCase__		,    default=32		,    help="Batch size for training."     )
										train_parser.add_argument("--valid_batch_size"		,    type=lowerCAmelCase__		,    default=64		,    help="Batch size for validation."     )
										train_parser.add_argument("--learning_rate"		,    type=lowerCAmelCase__		,    default=3E-5		,    help="Learning rate."     )
										train_parser.add_argument("--adam_epsilon"		,    type=lowerCAmelCase__		,    default=1E-0_8		,    help="Epsilon for Adam optimizer."     )
										train_parser.set_defaults(func=lowerCAmelCase__     )





						def __init__(			self							:Optional[int]		,    lowerCAmelCase__							:Namespace     )  ->str:
										lowercase         =      logging.get_logger("transformers-cli/training"     )

										lowercase         =      "tf" if is_tf_available() else "torch"

										os.makedirs(args.output		,    exist_ok=lowerCAmelCase__     )
										lowercase         =      args.output

										lowercase         =      args.column_label
										lowercase         =      args.column_text
										lowercase         =      args.column_id

										self.logger.info(F'''Loading {args.task} pipeline for {args.model}'''     )
										if args.task == "text_classification":
														lowercase         =      TextClassificationPipeline.from_pretrained(args.model     )
										elif args.task == "token_classification":
														raise NotImplementedError
										elif args.task == "question_answering":
														raise NotImplementedError

										self.logger.info(F'''Loading dataset from {args.train_data}'''     )
										lowercase         =      Processor.create_from_csv(
										    args.train_data		,    column_label=args.column_label		,    column_text=args.column_text		,    column_id=args.column_id		,    skip_first_row=args.skip_first_row		,    )
										lowercase         =      None
										if args.validation_data:
														self.logger.info(F'''Loading validation dataset from {args.validation_data}'''     )
														lowercase         =      Processor.create_from_csv(
														    args.validation_data		,    column_label=args.column_label		,    column_text=args.column_text		,    column_id=args.column_id		,    skip_first_row=args.skip_first_row		,    )

										lowercase         =      args.validation_split
										lowercase         =      args.train_batch_size
										lowercase         =      args.valid_batch_size
										lowercase         =      args.learning_rate
										lowercase         =      args.adam_epsilon





						def        SCREAMING_SNAKE_CASE(			self							:List[str]     )  ->List[str]:
										if self.framework == "tf":
														return self.run_tf()
										return self.run_torch()





						def        SCREAMING_SNAKE_CASE(			self							:List[Any]     )  ->Dict:
										raise NotImplementedError





						def        SCREAMING_SNAKE_CASE(			self							:Any     )  ->str:
										self.pipeline.fit(
										    self.train_dataset		,    validation_data=self.valid_dataset		,    validation_split=self.validation_split		,    learning_rate=self.learning_rate		,    adam_epsilon=self.adam_epsilon		,    train_batch_size=self.train_batch_size		,    valid_batch_size=self.valid_batch_size		,    )

										# Save trained pipeline
										self.pipeline.save_pretrained(self.output     )
