
'''simple docstring'''





import logging
import os
import threading
import time


try:
					import warnings
except ImportError:
					_SCREAMING_SNAKE_CASE    :      List[str]          =			None

try:
					import msvcrt
except ImportError:
					_SCREAMING_SNAKE_CASE    :      Optional[Any]          =			None

try:
					import fcntl
except ImportError:
					_SCREAMING_SNAKE_CASE    :      List[str]          =			None


# Backward compatibility
# ------------------------------------------------
try:
					TimeoutError
except NameError:
					_SCREAMING_SNAKE_CASE    :      Tuple          =			OSError


# Data
# ------------------------------------------------
_SCREAMING_SNAKE_CASE    :      Optional[int]          =			[
    """Timeout""",
    """BaseFileLock""",
    """WindowsFileLock""",
    """UnixFileLock""",
    """SoftFileLock""",
    """FileLock""",
]

_SCREAMING_SNAKE_CASE    :      List[str]          =			"""3.0.12"""


_SCREAMING_SNAKE_CASE    :      Tuple          =			None

def 				SCREAMING_SNAKE_CASE     (      ) ->       List[str]:

				"""simple docstring"""







				global _logger
				A__  :	Dict         =							_logger or logging.getLogger(__name__       )
				return _logger







class  UpperCamelCase__		(    SCREAMING_SNAKE_CASE_   ):







	'''simple docstring'''





	def __init__(			self				,       UpperCamelCase__		):
					A__  :	List[str]         =							lock_file
					return None





	def __str__(			self		):
					A__  :	Any         =							F"The file lock '{self.lock_file}' could not be acquired."
					return temp







class  UpperCamelCase__		:







	'''simple docstring'''





	def __init__(			self				,       UpperCamelCase__		):
					A__  :	Union[str, Any]         =							lock
					return None





	def __enter__(			self		):
					return self.lock





	def __exit__(			self				,       UpperCamelCase__				,       UpperCamelCase__				,       UpperCamelCase__		):
					self.lock.release()
					return None







class  UpperCamelCase__		:







	'''simple docstring'''





	def __init__(			self				,       UpperCamelCase__				,       UpperCamelCase__=-1				,       UpperCamelCase__=None		):
					A__  :	Any         =							max_filename_length if max_filename_length is not None else 255
					# Hash the filename if it's too long
					A__  :	Tuple         =							self.hash_filename_if_too_long(UpperCamelCase__				,       UpperCamelCase__		)
					# The path to the lock file.
					A__  :	Any         =							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.
					A__  :	Union[str, Any]         =							None

					# The default timeout value.
					A__  :	List[str]         =							timeout

					# We use this lock primarily for the lock counter.
					A__  :	Dict         =							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.
					A__  :	List[Any]         =							0
					return None





	@property
	def   __snake_case				(			self		):
					return self._lock_file





	@property
	def   __snake_case				(			self		):
					return self._timeout





	@timeout.setter
	def   __snake_case				(			self				,       UpperCamelCase__		):
					A__  :	Optional[int]         =							float(UpperCamelCase__		)
					return None





	def   __snake_case				(			self		):
					raise NotImplementedError()





	def   __snake_case				(			self		):
					raise NotImplementedError()





	@property
	def   __snake_case				(			self		):
					return self._lock_file_fd is not None





	def   __snake_case				(			self				,       UpperCamelCase__=None				,       UpperCamelCase__=0.0_5		):





					if timeout is None:
									A__  :	Optional[Any]         =							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

					A__  :	Any         =							id(self		)
					A__  :	Optional[int]         =							self._lock_file
					A__  :	str         =							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(UpperCamelCase__		)
					except:  # noqa
									# Something did go wrong, so decrement the counter.
									with self._thread_lock:
													A__  :	Optional[int]         =							max(0				,       self._lock_counter - 1		)

									raise
					return _Acquire_ReturnProxy(lock=self		)





	def   __snake_case				(			self				,       UpperCamelCase__=False		):





					with self._thread_lock:
									if self.is_locked:
													self._lock_counter -= 1

													if self._lock_counter == 0 or force:
																	A__  :	Optional[int]         =							id(self		)
																	A__  :	str         =							self._lock_file

																	logger().debug(F"Attempting to release lock {lock_id} on {lock_filename}"		)
																	self._release()
																	A__  :	Dict         =							0
																	logger().debug(F"Lock {lock_id} released on {lock_filename}"		)

					return None





	def __enter__(			self		):
					self.acquire()
					return self





	def __exit__(			self				,       UpperCamelCase__				,       UpperCamelCase__				,       UpperCamelCase__		):
					self.release()
					return None





	def __del__(			self		):
					self.release(force=UpperCamelCase__		)
					return None





	def   __snake_case				(			self				,       UpperCamelCase__				,       UpperCamelCase__		):
					A__  :	Union[str, Any]         =							os.path.basename(UpperCamelCase__		)
					if len(UpperCamelCase__		) > max_length and max_length > 0:
									A__  :	List[str]         =							os.path.dirname(UpperCamelCase__		)
									A__  :	Optional[Any]         =							str(hash(UpperCamelCase__		)		)
									A__  :	str         =							filename[: max_length - len(UpperCamelCase__		) - 8] + '''...''' + hashed_filename + '''.lock'''
									return os.path.join(UpperCamelCase__				,       UpperCamelCase__		)
					else:
									return path







class  UpperCamelCase__		(    SCREAMING_SNAKE_CASE_   ):







	'''simple docstring'''





	def __init__(			self				,       UpperCamelCase__				,       UpperCamelCase__=-1				,       UpperCamelCase__=None		):
					from .file_utils import relative_to_absolute_path

					super().__init__(UpperCamelCase__				,       timeout=UpperCamelCase__				,       max_filename_length=UpperCamelCase__		)
					A__  :	Any         =							'''\\\\?\\''' + relative_to_absolute_path(self.lock_file		)





	def   __snake_case				(			self		):
					A__  :	List[Any]         =							os.O_RDWR | os.O_CREAT | os.O_TRUNC

					try:
									A__  :	Union[str, Any]         =							os.open(self._lock_file				,       UpperCamelCase__		)
					except OSError:
									pass
					else:
									try:
													msvcrt.locking(UpperCamelCase__				,       msvcrt.LK_NBLCK				,       1		)
									except OSError:
													os.close(UpperCamelCase__		)
									else:
													A__  :	Dict         =							fd
					return None





	def   __snake_case				(			self		):
					A__  :	Optional[int]         =							self._lock_file_fd
					A__  :	str         =							None
					msvcrt.locking(UpperCamelCase__				,       msvcrt.LK_UNLCK				,       1		)
					os.close(UpperCamelCase__		)

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







class  UpperCamelCase__		(    SCREAMING_SNAKE_CASE_   ):







	'''simple docstring'''





	def __init__(			self				,       UpperCamelCase__				,       UpperCamelCase__=-1				,       UpperCamelCase__=None		):
					A__  :	int         =							os.statvfs(os.path.dirname(UpperCamelCase__		)		).f_namemax
					super().__init__(UpperCamelCase__				,       timeout=UpperCamelCase__				,       max_filename_length=UpperCamelCase__		)





	def   __snake_case				(			self		):
					A__  :	List[Any]         =							os.O_RDWR | os.O_CREAT | os.O_TRUNC
					A__  :	List[str]         =							os.open(self._lock_file				,       UpperCamelCase__		)

					try:
									fcntl.flock(UpperCamelCase__				,       fcntl.LOCK_EX | fcntl.LOCK_NB		)
					except OSError:
									os.close(UpperCamelCase__		)
					else:
									A__  :	Union[str, Any]         =							fd
					return None





	def   __snake_case				(			self		):
					A__  :	str         =							self._lock_file_fd
					A__  :	int         =							None
					fcntl.flock(UpperCamelCase__				,       fcntl.LOCK_UN		)
					os.close(UpperCamelCase__		)
					return None







class  UpperCamelCase__		(    SCREAMING_SNAKE_CASE_   ):







	'''simple docstring'''





	def   __snake_case				(			self		):
					A__  :	List[Any]         =							os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_TRUNC
					try:
									A__  :	Any         =							os.open(self._lock_file				,       UpperCamelCase__		)
					except OSError:
									pass
					else:
									A__  :	Optional[Any]         =							fd
					return None





	def   __snake_case				(			self		):
					os.close(self._lock_file_fd		)
					A__  :	List[Any]         =							None

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




_SCREAMING_SNAKE_CASE    :      str          =			None

if msvcrt:
					_SCREAMING_SNAKE_CASE    :      int          =			WindowsFileLock
elif fcntl:
					_SCREAMING_SNAKE_CASE    :      Tuple          =			UnixFileLock
else:
					_SCREAMING_SNAKE_CASE    :      List[str]          =			SoftFileLock

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

import sacrebleu as scb
from packaging import version
from sacrebleu import TER

import datasets


_SCREAMING_SNAKE_CASE    :      Union[str, Any]          =			'\\n@inproceedings{snover-etal-2006-study,\n    title = "A Study of Translation Edit Rate with Targeted Human Annotation",\n    author = "Snover, Matthew  and\n      Dorr, Bonnie  and\n      Schwartz, Rich  and\n      Micciulla, Linnea  and\n      Makhoul, John",\n    booktitle = "Proceedings of the 7th Conference of the Association for Machine Translation in the Americas: Technical Papers",\n    month = aug # " 8-12",\n    year = "2006",\n    address = "Cambridge, Massachusetts, USA",\n    publisher = "Association for Machine Translation in the Americas",\n    url = "https://aclanthology.org/2006.amta-papers.25",\n    pages = "223--231",\n}\n@inproceedings{post-2018-call,\n    title = "A Call for Clarity in Reporting {BLEU} Scores",\n    author = "Post, Matt",\n    booktitle = "Proceedings of the Third Conference on Machine Translation: Research Papers",\n    month = oct,\n    year = "2018",\n    address = "Belgium, Brussels",\n    publisher = "Association for Computational Linguistics",\n    url = "https://www.aclweb.org/anthology/W18-6319",\n    pages = "186--191",\n}\n'

_SCREAMING_SNAKE_CASE    :      Tuple          =			'\\nTER (Translation Edit Rate, also called Translation Error Rate) is a metric to quantify the edit operations that a\nhypothesis requires to match a reference translation. We use the implementation that is already present in sacrebleu\n(https://github.com/mjpost/sacreBLEU#ter), which in turn is inspired by the TERCOM implementation, which can be found\nhere: https://github.com/jhclark/tercom.\n\nThe implementation here is slightly different from sacrebleu in terms of the required input format. The length of\nthe references and hypotheses lists need to be the same, so you may need to transpose your references compared to\nsacrebleu\'s required input format. See https://github.com/huggingface/datasets/issues/3154#issuecomment-950746534\n\nSee the README.md file at https://github.com/mjpost/sacreBLEU#ter for more information.\n'

_SCREAMING_SNAKE_CASE    :      Optional[Any]          =			'\nProduces TER scores alongside the number of edits and reference length.\n\nArgs:\n    predictions (list of str): The system stream (a sequence of segments).\n    references (list of list of str): A list of one or more reference streams (each a sequence of segments).\n    normalized (boolean): If `True`, applies basic tokenization and normalization to sentences. Defaults to `False`.\n    ignore_punct (boolean): If `True`, applies basic tokenization and normalization to sentences. Defaults to `False`.\n    support_zh_ja_chars (boolean): If `True`, tokenization/normalization supports processing of Chinese characters,\n                                    as well as Japanese Kanji, Hiragana, Katakana, and Phonetic Extensions of Katakana.\n                                    Only applies if `normalized = True`. Defaults to `False`.\n    case_sensitive (boolean): If `False`, makes all predictions and references lowercase to ignore differences in case. Defaults to `False`.\n\nReturns:\n    \'score\' (float): TER score (num_edits / sum_ref_lengths * 100)\n    \'num_edits\' (int): The cumulative number of edits\n    \'ref_length\' (float): The cumulative average reference length\n\nExamples:\n    Example 1:\n        >>> predictions = ["does this sentence match??",\n        ...                     "what about this sentence?",\n        ...                     "What did the TER metric user say to the developer?"]\n        >>> references = [["does this sentence match", "does this sentence match!?!"],\n        ...             ["wHaT aBoUt ThIs SeNtEnCe?", "wHaT aBoUt ThIs SeNtEnCe?"],\n        ...             ["Your jokes are...", "...TERrible"]]\n        >>> ter = datasets.load_metric("ter")\n        >>> results = ter.compute(predictions=predictions,\n        ...                         references=references,\n        ...                         case_sensitive=True)\n        >>> print(results)\n        {\'score\': 150.0, \'num_edits\': 15, \'ref_length\': 10.0}\n\n    Example 2:\n        >>> predictions = ["does this sentence match??",\n        ...                     "what about this sentence?"]\n        >>> references = [["does this sentence match", "does this sentence match!?!"],\n        ...             ["wHaT aBoUt ThIs SeNtEnCe?", "wHaT aBoUt ThIs SeNtEnCe?"]]\n        >>> ter = datasets.load_metric("ter")\n        >>> results = ter.compute(predictions=predictions,\n        ...                         references=references,\n        ...                         case_sensitive=True)\n        >>> print(results)\n        {\'score\': 62.5, \'num_edits\': 5, \'ref_length\': 8.0}\n\n    Example 3:\n        >>> predictions = ["does this sentence match??",\n        ...                     "what about this sentence?"]\n        >>> references = [["does this sentence match", "does this sentence match!?!"],\n        ...             ["wHaT aBoUt ThIs SeNtEnCe?", "wHaT aBoUt ThIs SeNtEnCe?"]]\n        >>> ter = datasets.load_metric("ter")\n        >>> results = ter.compute(predictions=predictions,\n        ...                         references=references,\n        ...                         normalized=True,\n        ...                         case_sensitive=True)\n        >>> print(results)\n        {\'score\': 57.14285714285714, \'num_edits\': 6, \'ref_length\': 10.5}\n\n    Example 4:\n        >>> predictions = ["does this sentence match??",\n        ...                     "what about this sentence?"]\n        >>> references = [["does this sentence match", "does this sentence match!?!"],\n        ...             ["wHaT aBoUt ThIs SeNtEnCe?", "wHaT aBoUt ThIs SeNtEnCe?"]]\n        >>> ter = datasets.load_metric("ter")\n        >>> results = ter.compute(predictions=predictions,\n        ...                         references=references,\n        ...                         ignore_punct=True,\n        ...                         case_sensitive=False)\n        >>> print(results)\n        {\'score\': 0.0, \'num_edits\': 0, \'ref_length\': 8.0}\n\n    Example 5:\n        >>> predictions = ["does this sentence match??",\n        ...                    "what about this sentence?",\n        ...                    "What did the TER metric user say to the developer?"]\n        >>> references = [["does this sentence match", "does this sentence match!?!"],\n        ...             ["wHaT aBoUt ThIs SeNtEnCe?", "wHaT aBoUt ThIs SeNtEnCe?"],\n        ...             ["Your jokes are...", "...TERrible"]]\n        >>> ter = datasets.load_metric("ter")\n        >>> results = ter.compute(predictions=predictions,\n        ...                         references=references,\n        ...                         ignore_punct=True,\n        ...                         case_sensitive=False)\n        >>> print(results)\n        {\'score\': 100.0, \'num_edits\': 10, \'ref_length\': 10.0}\n'







@datasets.utils.file_utils.add_start_docstrings(_DESCRIPTION,			_KWARGS_DESCRIPTION   )
class  UpperCamelCase__		(    datasets.Metric   ):







	'''simple docstring'''





	def   __snake_case				(			self		):
					if version.parse(scb.__version__		) < version.parse('''1.4.12'''		):
									raise ImportWarning(
									    '''To use `sacrebleu`, the module `sacrebleu>=1.4.12` is required, and the current version of `sacrebleu` doesn\'t match this condition.\n'''
									    '''You can install it with `pip install "sacrebleu>=1.4.12"`.'''		)
					return datasets.MetricInfo(
					    description=_DESCRIPTION				,       citation=_CITATION				,       homepage='''http://www.cs.umd.edu/~snover/tercom/'''				,       inputs_description=_KWARGS_DESCRIPTION				,       features=datasets.Features(
					        {
					            '''predictions''': datasets.Value('''string'''				,       id='''sequence'''		),
					            '''references''': datasets.Sequence(datasets.Value('''string'''				,       id='''sequence'''		)				,       id='''references'''		),
					        }		)				,       codebase_urls=['''https://github.com/mjpost/sacreBLEU#ter''']				,       reference_urls=[
					        '''https://github.com/jhclark/tercom''',
					    ]				,       )





	def   __snake_case				(			self				,       UpperCamelCase__				,       UpperCamelCase__				,       UpperCamelCase__ = False				,       UpperCamelCase__ = False				,       UpperCamelCase__ = False				,       UpperCamelCase__ = False				,       ):
					A__  :	List[Any]         =							len(references[0]		)
					if any(len(UpperCamelCase__		) != references_per_prediction for refs in references		):
									raise ValueError('''Sacrebleu requires the same number of references for each prediction'''		)
					A__  :	Dict         =							[[refs[i] for refs in references] for i in range(UpperCamelCase__		)]

					A__  :	Optional[Any]         =							TER(
					    normalized=UpperCamelCase__				,       no_punct=UpperCamelCase__				,       asian_support=UpperCamelCase__				,       case_sensitive=UpperCamelCase__				,       )
					A__  :	str         =							sb_ter.corpus_score(UpperCamelCase__				,       UpperCamelCase__		)

					return {"score": output.score, "num_edits": output.num_edits, "ref_length": output.ref_length}