



import datasets

from .evaluate import evaluate


UpperCAmelCase   :							List[Any]							 ="""\
@article{hendrycks2021cuad,
      title={CUAD: An Expert-Annotated NLP Dataset for Legal Contract Review},
      author={Dan Hendrycks and Collin Burns and Anya Chen and Spencer Ball},
      journal={arXiv preprint arXiv:2103.06268},
      year={2021}
}
"""

UpperCAmelCase   :							Optional[Any]							 ="""
This metric wrap the official scoring script for version 1 of the Contract
Understanding Atticus Dataset (CUAD).
Contract Understanding Atticus Dataset (CUAD) v1 is a corpus of more than 13,000 labels in 510
commercial legal contracts that have been manually labeled to identify 41 categories of important
clauses that lawyers look for when reviewing contracts in connection with corporate transactions.
"""

UpperCAmelCase   :							Any							 ="""
Computes CUAD scores (EM, F1, AUPR, Precision@80%Recall, and Precision@90%Recall).
Args:
    predictions: List of question-answers dictionaries with the following key-values:
        - 'id': id of the question-answer pair as given in the references (see below)
        - 'prediction_text': list of possible texts for the answer, as a list of strings
        depending on a threshold on the confidence probability of each prediction.
    references: List of question-answers dictionaries with the following key-values:
        - 'id': id of the question-answer pair (see above),
        - 'answers': a Dict in the CUAD dataset format
            {
                'text': list of possible texts for the answer, as a list of strings
                'answer_start': list of start positions for the answer, as a list of ints
            }
            Note that answer_start values are not taken into account to compute the metric.
Returns:
    'exact_match': Exact match (the normalized answer exactly match the gold answer)
    'f1': The F-score of predicted tokens versus the gold answer
    'aupr': Area Under the Precision-Recall curve
    'prec_at_80_recall': Precision at 80% recall
    'prec_at_90_recall': Precision at 90% recall
Examples:
    >>> predictions = [{'prediction_text': ['The seller:', 'The buyer/End-User: Shenzhen LOHAS Supply Chain Management Co., Ltd.'], 'id': 'LohaCompanyltd_20191209_F-1_EX-10.16_11917878_EX-10.16_Supply Agreement__Parties'}]
    >>> references = [{'answers': {'answer_start': [143, 49], 'text': ['The seller:', 'The buyer/End-User: Shenzhen LOHAS Supply Chain Management Co., Ltd.']}, 'id': 'LohaCompanyltd_20191209_F-1_EX-10.16_11917878_EX-10.16_Supply Agreement__Parties'}]
    >>> cuad_metric = datasets.load_metric(\"cuad\")
    >>> results = cuad_metric.compute(predictions=predictions, references=references)
    >>> print(results)
    {'exact_match': 100.0, 'f1': 100.0, 'aupr': 0.0, 'prec_at_80_recall': 1.0, 'prec_at_90_recall': 1.0}
"""


@datasets.utils.file_utils.add_start_docstrings(_DESCRIPTION      ,   _KWARGS_DESCRIPTION      )
class       _lowercase   (datasets.Metric      ):
				'''simple docstring'''







				def       _lowerCamelCase					( self    ):

									'''simple docstring'''


									return datasets.MetricInfo(
									    description=_DESCRIPTION     , citation=_CITATION     , inputs_description=_KWARGS_DESCRIPTION     , features=datasets.Features(
									        {
									            "predictions": {
									                "id": datasets.Value("string"    ),
									                "prediction_text": datasets.features.Sequence(datasets.Value("string"    )    ),
									            },
									            "references": {
									                "id": datasets.Value("string"    ),
									                "answers": datasets.features.Sequence(
									                    {
									                        "text": datasets.Value("string"    ),
									                        "answer_start": datasets.Value("int32"    ),
									                    }    ),
									            },
									        }    )     , codebase_urls=["https://www.atticusprojectai.org/cuad"]     , reference_urls=["https://www.atticusprojectai.org/cuad"]     , )

				def       _lowerCamelCase					( self     , snake_case__     , snake_case__    ):

									'''simple docstring'''


									UpperCamelCase_		  =   {prediction["id"]: prediction["prediction_text"] for prediction in predictions}
									UpperCamelCase_		  =   [
									    {
									        "paragraphs": [
									            {
									                "qas": [
									                    {
									                        "answers": [{"text": answer_text} for answer_text in ref["answers"]["text"]],
									                        "id": ref["id"],
									                    }
									                    for ref in references
									                ]
									            }
									        ]
									    }
									]
									UpperCamelCase_		  =   evaluate(dataset=snake_case__     , predictions=snake_case__    )
									return score





import argparse
import glob
import importlib.util
import os
import re

import black
from doc_builder.style_doc import style_docstrings_in_code


# All paths are set with the intent you should run this script from the root of the repo with the command
# python utils/check_copies.py
UpperCAmelCase   :							Any							 ="""src/diffusers"""
UpperCAmelCase   :							Union[str, Any]							 ="""."""


# This is to make sure the diffusers module imported is the one in the repo.
UpperCAmelCase   :							int							 =importlib.util.spec_from_file_location(
    """diffusers""",
    os.path.join(DIFFUSERS_PATH, """__init__.py"""),
    submodule_search_locations=[DIFFUSERS_PATH],
)
UpperCAmelCase   :							Optional[Any]							 =spec.loader.load_module()



def    _lowerCAmelCase    (_lowerCAmelCase   ,	_lowerCAmelCase):
					return line.startswith(_lowerCAmelCase) or len(_lowerCAmelCase) <= 1 or re.search(r"^\s*\)(\s*->.*:|:)\s*$"   ,	_lowerCAmelCase) is not None



def    _lowerCAmelCase    (_lowerCAmelCase):
					UpperCamelCase_		  =   object_name.split(".")
					UpperCamelCase_		  =   0

					# First let's find the module where our object lives.
					UpperCamelCase_		  =   parts[i]
					while i < len(_lowerCAmelCase) and not os.path.isfile(os.path.join(_lowerCAmelCase   ,	f"""{module}.py""")):
										i += 1
										if i < len(_lowerCAmelCase):
															UpperCamelCase_		  =   os.path.join(_lowerCAmelCase   ,	parts[i])
					if i >= len(_lowerCAmelCase):
										raise ValueError(f"""`object_name` should begin with the name of a module of diffusers but got {object_name}.""")

					with open(os.path.join(_lowerCAmelCase   ,	f"""{module}.py""")   ,	"r"   ,	encoding="utf-8"   ,	newline="\n") as f:
										UpperCamelCase_		  =   f.readlines()

					# Now let's find the class / func in the code!
					UpperCamelCase_		  =   ""
					UpperCamelCase_		  =   0
					for name in parts[i + 1 :]:
										while (
										    line_index < len(_lowerCAmelCase) and re.search(rf"""^{indent}(class|def)\s+{name}(\(|\:)"""   ,	lines[line_index]) is None
										):
															line_index += 1
										indent += "    "
										line_index += 1

					if line_index >= len(_lowerCAmelCase):
										raise ValueError(f""" {object_name} does not match any function or class in {module}.""")

					# We found the beginning of the class / func, now let's find the end (when the indent diminishes).
					UpperCamelCase_		  =   line_index
					while line_index < len(_lowerCAmelCase) and _should_continue(lines[line_index]   ,	_lowerCAmelCase):
										line_index += 1
					# Clean up empty lines at the end (if any).
					while len(lines[line_index - 1]) <= 1:
										line_index -= 1

					UpperCamelCase_		  =   lines[start_index:line_index]
					return "".join(_lowerCAmelCase)


UpperCAmelCase   :							Any							 =re.compile(r"""^(\s*)#\s*Copied from\s+diffusers\.(\S+\.\S+)\s*($|\S.*$)""")
UpperCAmelCase   :							Any							 =re.compile(r"""^\s*(\S+)->(\S+)(\s+.*|$)""")
UpperCAmelCase   :							Dict							 =re.compile(r"""<FILL\s+[^>]*>""")



def    _lowerCAmelCase    (_lowerCAmelCase):
					UpperCamelCase_		  =   code.split("\n")
					UpperCamelCase_		  =   0
					while idx < len(_lowerCAmelCase) and len(lines[idx]) == 0:
										idx += 1
					if idx < len(_lowerCAmelCase):
										return re.search(r"^(\s*)\S"   ,	lines[idx]).groups()[0]
					return ""



def    _lowerCAmelCase    (_lowerCAmelCase):
					UpperCamelCase_		  =   len(get_indent(_lowerCAmelCase)) > 0
					if has_indent:
										UpperCamelCase_		  =   f"""class Bla:\n{code}"""
					UpperCamelCase_		  =   black.Mode(target_versions={black.TargetVersion.PYaa}   ,	line_length=1_19   ,	preview=_lowerCAmelCase)
					UpperCamelCase_		  =   black.format_str(_lowerCAmelCase   ,	mode=_lowerCAmelCase)
					UpperCamelCase_  ,    UpperCamelCase_		  =   style_docstrings_in_code(_lowerCAmelCase)
					return result[len("class Bla:\n") :] if has_indent else result



def    _lowerCAmelCase    (_lowerCAmelCase   ,	_lowerCAmelCase=False):
					with open(_lowerCAmelCase   ,	"r"   ,	encoding="utf-8"   ,	newline="\n") as f:
										UpperCamelCase_		  =   f.readlines()
					UpperCamelCase_		  =   []
					UpperCamelCase_		  =   0
					# Not a for loop cause `lines` is going to change (if `overwrite=True`).
					while line_index < len(_lowerCAmelCase):
										UpperCamelCase_		  =   _re_copy_warning.search(lines[line_index])
										if search is None:
															line_index += 1
															continue

										# There is some copied code here, let's retrieve the original.
										UpperCamelCase_  ,    UpperCamelCase_  ,    UpperCamelCase_		  =   search.groups()
										UpperCamelCase_		  =   find_code_in_diffusers(_lowerCAmelCase)
										UpperCamelCase_		  =   get_indent(_lowerCAmelCase)

										UpperCamelCase_		  =   line_index + 1 if indent == theoretical_indent else line_index + 2
										UpperCamelCase_		  =   theoretical_indent
										UpperCamelCase_		  =   start_index

										# Loop to check the observed code, stop when indentation diminishes or if we see a End copy comment.
										UpperCamelCase_		  =   True
										while line_index < len(_lowerCAmelCase) and should_continue:
															line_index += 1
															if line_index >= len(_lowerCAmelCase):
																				break
															UpperCamelCase_		  =   lines[line_index]
															UpperCamelCase_		  =   _should_continue(_lowerCAmelCase   ,	_lowerCAmelCase) and re.search(f"""^{indent}# End copy"""   ,	_lowerCAmelCase) is None
										# Clean up empty lines at the end (if any).
										while len(lines[line_index - 1]) <= 1:
															line_index -= 1

										UpperCamelCase_		  =   lines[start_index:line_index]
										UpperCamelCase_		  =   "".join(_lowerCAmelCase)

										# Remove any nested `Copied from` comments to avoid circular copies
										UpperCamelCase_		  =   [line for line in theoretical_code.split("\n") if _re_copy_warning.search(_lowerCAmelCase) is None]
										UpperCamelCase_		  =   "\n".join(_lowerCAmelCase)

										# Before comparing, use the `replace_pattern` on the original code.
										if len(_lowerCAmelCase) > 0:
															UpperCamelCase_		  =   replace_pattern.replace("with"   ,	"").split(",")
															UpperCamelCase_		  =   [_re_replace_pattern.search(_lowerCAmelCase) for p in patterns]
															for pattern in patterns:
																				if pattern is None:
																									continue
																				UpperCamelCase_  ,    UpperCamelCase_  ,    UpperCamelCase_		  =   pattern.groups()
																				UpperCamelCase_		  =   re.sub(_lowerCAmelCase   ,	_lowerCAmelCase   ,	_lowerCAmelCase)
																				if option.strip() == "all-casing":
																									UpperCamelCase_		  =   re.sub(obja.lower()   ,	obja.lower()   ,	_lowerCAmelCase)
																									UpperCamelCase_		  =   re.sub(obja.upper()   ,	obja.upper()   ,	_lowerCAmelCase)

            # Blackify after replacement. To be able to do that, we need the header (class or function definition)
            # from the previous line
															UpperCamelCase_		  =   blackify(lines[start_index - 1] + theoretical_code)
															UpperCamelCase_		  =   theoretical_code[len(lines[start_index - 1]) :]

										# Test for a diff and act accordingly.
										if observed_code != theoretical_code:
															diffs.append([object_name, start_index])
															if overwrite:
																				UpperCamelCase_		  =   lines[:start_index] + [theoretical_code] + lines[line_index:]
																				UpperCamelCase_		  =   start_index + 1

					if overwrite and len(_lowerCAmelCase) > 0:
										# Warn the user a file has been modified.
										print(f"""Detected changes, rewriting {filename}.""")
										with open(_lowerCAmelCase   ,	"w"   ,	encoding="utf-8"   ,	newline="\n") as f:
															f.writelines(_lowerCAmelCase)
					return diffs



def    _lowerCAmelCase    (_lowerCAmelCase = False):
					UpperCamelCase_		  =   glob.glob(os.path.join(_lowerCAmelCase   ,	"**/*.py")   ,	recursive=_lowerCAmelCase)
					UpperCamelCase_		  =   []
					for filename in all_files:
										UpperCamelCase_		  =   is_copy_consistent(_lowerCAmelCase   ,	_lowerCAmelCase)
										diffs += [f"""- {filename}: copy does not match {d[0]} at line {d[1]}""" for d in new_diffs]
					if not overwrite and len(_lowerCAmelCase) > 0:
										UpperCamelCase_		  =   "\n".join(_lowerCAmelCase)
										raise Exception(
										    "Found the following copy inconsistencies:\n"
										    + diff
										    + "\nRun `make fix-copies` or `python utils/check_copies.py --fix_and_overwrite` to fix them.")


if __name__ == "__main__":
	UpperCAmelCase   :							List[str]							 =argparse.ArgumentParser()
	parser.add_argument("""--fix_and_overwrite""", action="""store_true""", help="""Whether to fix inconsistencies.""")
	UpperCAmelCase   :							Tuple							 =parser.parse_args()

	check_copies(args.fix_and_overwrite)
