import inspect
import re
from hashlib import shaaaa
from typing import Dict, List

from .arrow import arrow
from .audiofolder import audiofolder
from .csv import csv
from .imagefolder import imagefolder
from .json import json
from .pandas import pandas
from .parquet import parquet
from .sql import sql  # noqa F401
from .text import text






def     lowerCAmelCase_			(   _SCREAMING_SNAKE_CASE     :				List[str]			):
						UpperCamelCase_		:							Tuple  =		[]
						for line in lines:
												UpperCamelCase_		:							List[str]  =		re.sub(R"""#.*"""		, """"""		, _SCREAMING_SNAKE_CASE			)  # remove comments
												if line:
																		filtered_lines.append(_SCREAMING_SNAKE_CASE			)
						UpperCamelCase_		:							List[Any]  =		"""\n""".join(_SCREAMING_SNAKE_CASE			)

						# Make a hash from all this code
						UpperCamelCase_		:							List[str]  =		full_str.encode("""utf-8"""			)
						return shaaaa(_SCREAMING_SNAKE_CASE			).hexdigest()


# get importable module names and hash for caching
SCREAMING_SNAKE_CASE		:     Optional[Any]         =	{
    "csv": (csv.__name__, _hash_python_lines(inspect.getsource(csv).splitlines())),
    "json": (json.__name__, _hash_python_lines(inspect.getsource(json).splitlines())),
    "pandas": (pandas.__name__, _hash_python_lines(inspect.getsource(pandas).splitlines())),
    "parquet": (parquet.__name__, _hash_python_lines(inspect.getsource(parquet).splitlines())),
    "arrow": (arrow.__name__, _hash_python_lines(inspect.getsource(arrow).splitlines())),
    "text": (text.__name__, _hash_python_lines(inspect.getsource(text).splitlines())),
    "imagefolder": (imagefolder.__name__, _hash_python_lines(inspect.getsource(imagefolder).splitlines())),
    "audiofolder": (audiofolder.__name__, _hash_python_lines(inspect.getsource(audiofolder).splitlines())),
}

# Used to infer the module to use based on the data files extensions
SCREAMING_SNAKE_CASE		:     Dict         =	{
    ".csv": ("csv", {}),
    ".tsv": ("csv", {"sep": "\t"}),
    ".json": ("json", {}),
    ".jsonl": ("json", {}),
    ".parquet": ("parquet", {}),
    ".arrow": ("arrow", {}),
    ".txt": ("text", {}),
}
_EXTENSION_TO_MODULE.update({ext: ("imagefolder", {}) for ext in imagefolder.ImageFolder.EXTENSIONS})
_EXTENSION_TO_MODULE.update({ext.upper(): ("imagefolder", {}) for ext in imagefolder.ImageFolder.EXTENSIONS})
_EXTENSION_TO_MODULE.update({ext: ("audiofolder", {}) for ext in audiofolder.AudioFolder.EXTENSIONS})
_EXTENSION_TO_MODULE.update({ext.upper(): ("audiofolder", {}) for ext in audiofolder.AudioFolder.EXTENSIONS})
SCREAMING_SNAKE_CASE		:     List[str]         =	{"imagefolder", "audiofolder"}

# Used to filter data files based on extensions given a module name
SCREAMING_SNAKE_CASE		:     Dict[str, List[str]]         =	{}
for _ext, (_module, _) in _EXTENSION_TO_MODULE.items():
	_MODULE_TO_EXTENSIONS.setdefault(_module, []).append(_ext)

_MODULE_TO_EXTENSIONS["imagefolder"].append(".zip")







_MODULE_TO_EXTENSIONS["audiofolder"].append(".zip")







import json
import multiprocessing
import os
import re
from collections import defaultdict

import torch
from accelerate import Accelerator
from accelerate.utils import set_seed
from arguments import HumanEvalArguments
from datasets import load_dataset, load_metric
from torch.utils.data import IterableDataset
from torch.utils.data.dataloader import DataLoader
from tqdm import tqdm

import transformers
from transformers import AutoModelForCausalLM, AutoTokenizer, HfArgumentParser, StoppingCriteria, StoppingCriteriaList


SCREAMING_SNAKE_CASE		:     Optional[int]         =	["\nclass", "\ndef", "\n#", "\n@", "\nprint", "\nif"]

class        UpperCamelCase						(				__a				):





						def __init__(self			,     __UpperCamelCase			,     __UpperCamelCase			,     __UpperCamelCase=None			,     __UpperCamelCase=1						)				->				List[str]:
												UpperCamelCase_		:							Dict  =		tokenizer
												UpperCamelCase_		:							Dict  =		dataset
												UpperCamelCase_		:							str  =		len(__UpperCamelCase						) if n_tasks is None else n_tasks
												UpperCamelCase_		:							int  =		n_copies





						def __iter__(self						)				->				Any:
												UpperCamelCase_		:							int  =		[]
												for task in range(self.n_tasks						):
																		# without strip, the model generate commented codes ...
																		prompts.append(self.tokenizer.eos_token + self.dataset[task]["""prompt"""].strip()						)
												UpperCamelCase_		:							Any  =		self.tokenizer(__UpperCamelCase			,     padding=__UpperCamelCase			,     return_tensors="""pt"""						)
												for task in range(self.n_tasks						):
																		for _ in range(self.n_copies						):
																								yield {
																								    "ids": outputs.input_ids[task],
																								    "task_id": task,
																								    "input_len": outputs.attention_mask[task].sum(),
																								}


class        UpperCamelCase						(				__a				):





						def __init__(self			,     __UpperCamelCase			,     __UpperCamelCase			,     __UpperCamelCase						)				->				Dict:
												UpperCamelCase_		:							List[Any]  =		start_length
												UpperCamelCase_		:							List[str]  =		eof_strings
												UpperCamelCase_		:							str  =		tokenizer





						def __call__(self			,     __UpperCamelCase			,     __UpperCamelCase			,     **__UpperCamelCase						)				->				Union[str, Any]:
												UpperCamelCase_		:							List[str]  =		self.tokenizer.batch_decode(input_ids[:, self.start_length :]						)
												UpperCamelCase_		:							List[Any]  =		[]
												for decoded_generation in decoded_generations:
																		done.append(any(stop_string in decoded_generation for stop_string in self.eof_strings						)						)
												return all(__UpperCamelCase						)






def     lowerCAmelCase_			(   _SCREAMING_SNAKE_CASE     :				Dict			):
						UpperCamelCase_		:							int  =		re.split("""(%s)""" % """|""".join(_SCREAMING_SNAKE_CASE			)		, _SCREAMING_SNAKE_CASE			)
						# last string should be ""
						return "".join(string_list[:-2]			)






def     lowerCAmelCase_			(   _SCREAMING_SNAKE_CASE     :				Optional[int]		, _SCREAMING_SNAKE_CASE     :				Optional[Any]		, _SCREAMING_SNAKE_CASE     :				Optional[Any]		, _SCREAMING_SNAKE_CASE     :				int		, _SCREAMING_SNAKE_CASE     :				List[str]		, _SCREAMING_SNAKE_CASE     :				Optional[Any]=20		, **_SCREAMING_SNAKE_CASE     :				List[str]			):
						UpperCamelCase_		:							Union[str, Any]  =		defaultdict(_SCREAMING_SNAKE_CASE			)  # dict of list of generated tokens
						for step, batch in tqdm(enumerate(_SCREAMING_SNAKE_CASE			)			):
												with torch.no_grad():
																		UpperCamelCase_		:							str  =		batch["""ids"""].shape[-1]
																		UpperCamelCase_		:							List[str]  =		accelerator.unwrap_model(_SCREAMING_SNAKE_CASE			).generate(
																		    input_ids=batch["""ids"""][:, : batch["""input_len"""]]		, num_return_sequences=_SCREAMING_SNAKE_CASE		, **_SCREAMING_SNAKE_CASE			)
																		# each task is generated batch_size times
																		UpperCamelCase_		:							List[str]  =		batch["""task_id"""].repeat(_SCREAMING_SNAKE_CASE			)
																		UpperCamelCase_		:							Union[str, Any]  =		accelerator.pad_across_processes(
																		    _SCREAMING_SNAKE_CASE		, dim=1		, pad_index=tokenizer.pad_token_id			)

																		UpperCamelCase_,UpperCamelCase_		:							Any  =		accelerator.gather((generated_tokens, generated_tasks)			)
																		UpperCamelCase_		:							str  =		generated_tokens.cpu().numpy()
																		UpperCamelCase_		:							List[Any]  =		generated_tasks.cpu().numpy()

																		for task, generated_tokens in zip(_SCREAMING_SNAKE_CASE		, _SCREAMING_SNAKE_CASE			):
																								gen_token_dict[task].append(_SCREAMING_SNAKE_CASE			)

						UpperCamelCase_		:							List[str]  =		[[] for _ in range(_SCREAMING_SNAKE_CASE			)]
						for task, generated_tokens in gen_token_dict.items():
												for s in generated_tokens:
																		UpperCamelCase_		:							List[Any]  =		tokenizer.decode(_SCREAMING_SNAKE_CASE		, skip_special_tokens=_SCREAMING_SNAKE_CASE		, clean_up_tokenization_spaces=_SCREAMING_SNAKE_CASE			)
																		code_gens[task].append(remove_last_block(_SCREAMING_SNAKE_CASE			)			)
						return code_gens






def     lowerCAmelCase_			(   ):
						# Setup configuration
						UpperCamelCase_		:							List[Any]  =		HfArgumentParser(_SCREAMING_SNAKE_CASE			)
						UpperCamelCase_		:							Optional[Any]  =		parser.parse_args()

						transformers.logging.set_verbosity_error()
						# enables code execution in code_eval metric
						UpperCamelCase_		:							int  =		args.HF_ALLOW_CODE_EVAL
						# make sure tokenizer plays nice with multiprocessing
						UpperCamelCase_		:							str  =		"""false"""

						if args.num_workers is None:
												UpperCamelCase_		:							List[str]  =		multiprocessing.cpu_count()

						# Use dataset load to feed to accelerate
						UpperCamelCase_		:							Optional[Any]  =		Accelerator()
						set_seed(args.seed		, device_specific=_SCREAMING_SNAKE_CASE			)

						# Load model and tokenizer
						UpperCamelCase_		:							str  =		AutoTokenizer.from_pretrained(args.model_ckpt			)
						UpperCamelCase_		:							Any  =		tokenizer.eos_token
						UpperCamelCase_		:							Tuple  =		AutoModelForCausalLM.from_pretrained(args.model_ckpt			)

						# Generation settings
						UpperCamelCase_		:							Union[str, Any]  =		{
						    """do_sample""": args.do_sample,
						    """temperature""": args.temperature,
						    """max_new_tokens""": args.max_new_tokens,
						    """top_p""": args.top_p,
						    """top_k""": args.top_k,
						    """stopping_criteria""": StoppingCriteriaList([EndOfFunctionCriteria(0		, _SCREAMING_SNAKE_CASE		, _SCREAMING_SNAKE_CASE			)]			),
						}

						# Load evaluation dataset and metric
						UpperCamelCase_		:							Optional[int]  =		load_dataset("""openai_humaneval"""			)
						UpperCamelCase_		:							Any  =		load_metric("""code_eval"""			)

						UpperCamelCase_		:							int  =		args.num_tasks if args.num_tasks is not None else len(human_eval["""test"""]			)
						UpperCamelCase_		:							List[str]  =		args.n_samples // args.batch_size

						UpperCamelCase_		:							Tuple  =		TokenizedDataset(_SCREAMING_SNAKE_CASE		, human_eval["""test"""]		, n_copies=_SCREAMING_SNAKE_CASE		, n_tasks=_SCREAMING_SNAKE_CASE			)
						# do not confuse args.batch_size, which is actually the num_return_sequences
						UpperCamelCase_		:							List[str]  =		DataLoader(_SCREAMING_SNAKE_CASE		, batch_size=1			)

						# Run a quick test to see if code evaluation is enabled
						try:
												UpperCamelCase_		:							str  =		code_eval_metric.compute(references=[""""""]		, predictions=[[""""""]]			)
						except ValueError as exception:
												print(
												    """Code evaluation not enabled. Read the warning below carefully and then use `--HF_ALLOW_CODE_EVAL=\"1\"`"""
												    """ flag to enable code evaluation."""			)
												raise exception

						UpperCamelCase_,UpperCamelCase_		:							int  =		accelerator.prepare(_SCREAMING_SNAKE_CASE		, _SCREAMING_SNAKE_CASE			)

						UpperCamelCase_		:							Optional[int]  =		complete_code(
						    _SCREAMING_SNAKE_CASE		, _SCREAMING_SNAKE_CASE		, _SCREAMING_SNAKE_CASE		, _SCREAMING_SNAKE_CASE		, n_tasks=_SCREAMING_SNAKE_CASE		, batch_size=args.batch_size		, **_SCREAMING_SNAKE_CASE		, )

						if accelerator.is_main_process:
												UpperCamelCase_		:							List[str]  =		[]

												for task in tqdm(range(_SCREAMING_SNAKE_CASE			)			):
																		UpperCamelCase_		:							int  =		human_eval["""test"""][task]["""test"""]
																		UpperCamelCase_		:							Tuple  =		f'''check({human_eval["test"][task]["entry_point"]})'''
																		references.append("""\n""" + test_func + """\n""" + entry_point			)

												# Evaluate completions with "code_eval" metric
												UpperCamelCase_,UpperCamelCase_		:							Any  =		code_eval_metric.compute(
												    references=_SCREAMING_SNAKE_CASE		, predictions=_SCREAMING_SNAKE_CASE		, num_workers=args.num_workers			)
												print(f'''Results: {pass_at_k}'''			)

												# Save results to json file
												with open(args.output_file		, """w"""			) as fp:
																		json.dump(_SCREAMING_SNAKE_CASE		, _SCREAMING_SNAKE_CASE			)


# For some reason the folliwng seems to be necessary sometimes for code_eval to work nice with multiprocessing
# https://stackoverflow.com/questions/60804599/python-multiprocessing-keeps-spawning-the-whole-script
if __name__ == "__main__":
	main()






