



import json
import os
from datetime import date
from pathlib import Path

from tabulate import DataRow, TableFormat, tabulate


UpperCAmelCase_									=							TableFormat(
    lineabove=None,
    linebelowheader=None,
    linebetweenrows=None,
    linebelow=None,
    headerrow=DataRow("", "|", "|"),
    datarow=DataRow("", "|", "|"),
    padding=1,
    with_header_hide=None,
)


UpperCAmelCase_									=							[]
UpperCAmelCase_									=							[]

UpperCAmelCase_									=							{"type": "section", "text": {"type": "plain_text", "text": "No failed tests! 🤗", "emoji": True}}

UpperCAmelCase_									=							[
    {
        "type": "header",
        "text": {
            "type": "plain_text",
            "text": F"""🤗 Accelerate nightly {os.environ.get('TEST_TYPE', '')} test results""",
            "emoji": True,
        },
    }
]

UpperCAmelCase_									=							0
for log in Path().glob("*.log"):
    UpperCAmelCase_									=							0
    with open(log, "r") as f:
        for line in f:
            UpperCAmelCase_									=							json.loads(line)
            if line.get("nodeid", "") != "":
                UpperCAmelCase_									=							line["nodeid"]
                if line.get("duration", None) is not None:
                    UpperCAmelCase_									=							F"""{line['duration']:.4f}"""
                    if line.get("outcome", "") == "failed":
                        section_num_failed += 1
                        failed.append([test, duration, log.name.split("_")[0]])
                        total_num_failed += 1
    group_info.append([str(log), section_num_failed, failed])
    UpperCAmelCase_									=							[]
    log.unlink()

UpperCAmelCase_									=							""
UpperCAmelCase_									=							[]
if total_num_failed > 0:
    for name, num_failed, failed_tests in group_info:
        if num_failed > 0:
            if num_failed == 1:
                message += F"*{name[1:]}: {num_failed} failed test*\n"
            else:
                message += F"*{name[1:]}: {num_failed} failed tests*\n"
            UpperCAmelCase_									=							[]
            UpperCAmelCase_									=							{}
            for test in failed_tests:
                UpperCAmelCase_									=							test[0].split("::")
                UpperCAmelCase_									=							data[0].split("/")[-1]
                if data[0] not in filesafailed:
                    UpperCAmelCase_									=							[data[1:]]
                else:
                    filesafailed[data[0]] += [data[1:]]
                failed_table.append(data)

            UpperCAmelCase_									=							[test[0] for test in failed_table]
            UpperCAmelCase_									=							list(set(files))
            # Count number of instances in failed_tests
            UpperCAmelCase_									=							[]
            for file in individual_files:
                table.append([file, len(filesafailed[file])])

            UpperCAmelCase_									=							tabulate(
                table,
                headers=["Test Location", "Num Failed"],
                tablefmt=hf_table_format,
                stralign="right",
            )
            message += F"\n```\n{failed_table}\n```"
            all_filesafailed.append(filesafailed)
    if len(message) > 3_0_0_0:
        UpperCAmelCase_									=							"Too many failed tests, please see the full report in the Action results."
        UpperCAmelCase_									=							len(err) + 1_0
        UpperCAmelCase_									=							message[: 3_0_0_0 - offset] + F"""\n...\n```\n{err}"""
    print(F"""### {message}""")
else:
    UpperCAmelCase_									=							"No failed tests! 🤗"
    print(F"""## {message}""")
    payload.append(no_error_payload)

if os.environ.get("TEST_TYPE", "") != "":
    from slack_sdk import WebClient

    UpperCAmelCase_									=							WebClient(token=os.environ["SLACK_API_TOKEN"])
    if message != "No failed tests! 🤗":
        UpperCAmelCase_									=							{
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text": message,
            },
        }
        payload.append(md_report)
        UpperCAmelCase_									=							{
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text": "*For more details:*",
            },
            "accessory": {
                "type": "button",
                "text": {
                    "type": "plain_text",
                    "text": "Check Action results",
                    "emoji": True,
                },
                "url": F"""https://github.com/{os.environ['GITHUB_REPOSITORY']}/actions/runs/{os.environ['GITHUB_RUN_ID']}""",
            },
        }
        payload.append(action_button)
        UpperCAmelCase_									=							{
            "type": "context",
            "elements": [
                {
                    "type": "plain_text",
                    "text": F"""Nightly {os.environ.get('TEST_TYPE')} test results for {date.today()}""",
                }
            ],
        }
        payload.append(date_report)
    UpperCAmelCase_									=							client.chat_postMessage(channel="#accelerate-ci-daily", text=message, blocks=payload)
    UpperCAmelCase_									=							response.data["ts"]
    for failed_file in all_filesafailed:
        for test_location, test_failures in failed_file.items():
            # Keep only the first instance of the test name
            UpperCAmelCase_									=							""
            for i, row in enumerate(test_failures):
                if row[0] != test_class:
                    UpperCAmelCase_									=							row[0]
                else:
                    UpperCAmelCase_									=							""

            UpperCAmelCase_									=							{
                "type": "section",
                "text": {
                    "type": "mrkdwn",
                    "text": F"""Test location: {test_location}\n```\n{tabulate(test_failures, headers=['Class', 'Test'], tablefmt=hf_table_format, stralign='right')}\n```""",
                },
            }

            client.chat_postMessage(
                channel="#accelerate-ci-daily",
                thread_ts=ts,
                blocks=[payload],
            )




import numpy as np
import torch
from torch.utils.data import Dataset, IterableDataset

from ..utils.generic import ModelOutput





class 		UpperCAmelCase						(						snake_case_				):





   def __init__(	self       ,     _lowerCAmelCase       ,     _lowerCAmelCase       ,     _lowerCAmelCase			):
         _lowerCAmelCase 			=  dataset
         _lowerCAmelCase 			=  process
         _lowerCAmelCase 			=  params





   def __len__(	self			):
         return len(self.dataset			)





   def __getitem__(	self       ,     _lowerCAmelCase			):
         _lowerCAmelCase 			=  self.dataset[i]
         _lowerCAmelCase 			=  self.process(_lowerCAmelCase       ,     **self.params			)
         return processed






class 		UpperCAmelCase						(						snake_case_				):





   def __init__(	self       ,     _lowerCAmelCase       ,     _lowerCAmelCase       ,     _lowerCAmelCase       ,     _lowerCAmelCase=None			):
         _lowerCAmelCase 			=  loader
         _lowerCAmelCase 			=  infer
         _lowerCAmelCase 			=  params
         if loader_batch_size == 1:
               # Let's spare some time by deactivating altogether
               _lowerCAmelCase 			=  None
         _lowerCAmelCase 			=  loader_batch_size

         # Internal bookkeeping
         _lowerCAmelCase 			=  None
         _lowerCAmelCase 			=  None





   def __len__(	self			):
         return len(self.loader			)





   def __iter__(	self			):
         _lowerCAmelCase 			=  iter(self.loader			)
         return self





   def 	__lowerCAmelCase							(	self			):
         if isinstance(self._loader_batch_data       ,     torch.Tensor			):
               # Batch data is simple tensor, just fetch the slice
               _lowerCAmelCase 			=  self._loader_batch_data[self._loader_batch_index]
         else:
               # Batch data is assumed to be BaseModelOutput (or dict)
               _lowerCAmelCase 			=  {}
               for k, element in self._loader_batch_data.items():
                     if isinstance(_lowerCAmelCase       ,     _lowerCAmelCase			):
                           # Convert ModelOutput to tuple first
                           _lowerCAmelCase 			=  element.to_tuple()
                           if isinstance(element[0]       ,     torch.Tensor			):
                                 _lowerCAmelCase 			=  tuple(el[self._loader_batch_index].unsqueeze(0			) for el in element			)
                           elif isinstance(element[0]       ,     np.ndarray			):
                                 _lowerCAmelCase 			=  tuple(np.expand_dims(el[self._loader_batch_index]       ,     0			) for el in element			)
                           continue
                     if k in {"hidden_states", "past_key_values", "attentions"} and isinstance(_lowerCAmelCase       ,     _lowerCAmelCase			):
                           # Those are stored as lists of tensors so need specific unbatching.
                           if isinstance(element[0]       ,     torch.Tensor			):
                                 _lowerCAmelCase 			=  tuple(el[self._loader_batch_index].unsqueeze(0			) for el in element			)
                           elif isinstance(element[0]       ,     np.ndarray			):
                                 _lowerCAmelCase 			=  tuple(np.expand_dims(el[self._loader_batch_index]       ,     0			) for el in element			)
                           continue
                     if element is None:
                           # This can happen for optional data that get passed around
                           _lowerCAmelCase 			=  None
                     elif isinstance(element[self._loader_batch_index]       ,     torch.Tensor			):
                           # Take correct batch data, but make it looked like batch_size=1
                           # For compatibility with other methods within transformers

                           _lowerCAmelCase 			=  element[self._loader_batch_index].unsqueeze(0			)
                     elif isinstance(element[self._loader_batch_index]       ,     np.ndarray			):
                           # Take correct batch data, but make it looked like batch_size=1
                           # For compatibility with other methods within transformers
                           _lowerCAmelCase 			=  np.expand_dims(element[self._loader_batch_index]       ,     0			)
                     else:
                           # This is typically a list, so no need to `unsqueeze`.
                           _lowerCAmelCase 			=  element[self._loader_batch_index]
            # Recreate the element by reusing the original class to make it look
            # batch_size=1
               _lowerCAmelCase 			=  self._loader_batch_data.__class__(_lowerCAmelCase			)
         self._loader_batch_index += 1
         return result





   def 	__lowerCAmelCase							(	self			):
         if self._loader_batch_index is not None and self._loader_batch_index < self.loader_batch_size:
               # We are currently unrolling a batch so we just need to return
               # the current item within a batch
               return self.loader_batch_item()

         # We're out of items within a batch
         _lowerCAmelCase 			=  next(self.iterator			)
         _lowerCAmelCase 			=  self.infer(_lowerCAmelCase       ,     **self.params			)
         # We now have a batch of "inferred things".
         if self.loader_batch_size is not None:
               # Try to infer the size of the batch
               if isinstance(_lowerCAmelCase       ,     torch.Tensor			):
                     _lowerCAmelCase 			=  processed
               else:
                     _lowerCAmelCase 			=  list(processed.keys()			)[0]
                     _lowerCAmelCase 			=  processed[key]
               if isinstance(_lowerCAmelCase       ,     _lowerCAmelCase			):
                     _lowerCAmelCase 			=  len(_lowerCAmelCase			)
               else:
                     _lowerCAmelCase 			=  first_tensor.shape[0]
               if 0 < observed_batch_size < self.loader_batch_size:
                     # could be last batch so we can't unroll as many
                     # elements.
                     _lowerCAmelCase 			=  observed_batch_size
               # Setting internal index to unwrap the batch
               _lowerCAmelCase 			=  processed
               _lowerCAmelCase 			=  0
               return self.loader_batch_item()
         else:
               # We're not unrolling batches
               return processed






class 		UpperCAmelCase						(						snake_case_				):





   def __init__(	self       ,     _lowerCAmelCase       ,     _lowerCAmelCase       ,     _lowerCAmelCase       ,     _lowerCAmelCase=None			):
         super().__init__(_lowerCAmelCase       ,     _lowerCAmelCase       ,     _lowerCAmelCase			)





   def __iter__(	self			):
         _lowerCAmelCase 			=  iter(self.loader			)
         _lowerCAmelCase 			=  None
         return self





   def 	__lowerCAmelCase							(	self			):
         if self.subiterator is None:
               _lowerCAmelCase 			=  self.infer(next(self.iterator			)       ,     **self.params			)
         try:
               # Try to return next item
               _lowerCAmelCase 			=  next(self.subiterator			)
         except StopIteration:
               # When a preprocess iterator ends, we can start lookig at the next item
               # ChunkIterator will keep feeding until ALL elements of iterator
               # all have created their subiterator and have been iterating against.
               #
               # Another way to look at it, is we're basically flattening lists of lists
               # into a single list, but with generators
               _lowerCAmelCase 			=  self.infer(next(self.iterator			)       ,     **self.params			)
               _lowerCAmelCase 			=  next(self.subiterator			)
         return processed






class 		UpperCAmelCase						(						snake_case_				):





   def __iter__(	self			):
         _lowerCAmelCase 			=  iter(self.loader			)
         return self





   def 	__lowerCAmelCase							(	self			):
         # Extremely similar to PipelineIterator in its unpacking mechanism
         # BUT, we have an extra required item which is the presence of `is_last`
         # That is because everything is flattened by `PipelineChunkIterator` we
         # need to keep track of how to regroup here in the original `process`
         # boundaries so that `process` and `postprocess` see the same data.

         # This iterator accumulates items (possibly while unbatching) until it
         # its a `is_last` and then just passes it on to the caller.
         _lowerCAmelCase 			=  False
         _lowerCAmelCase 			=  []
         if self._loader_batch_index is not None and self._loader_batch_index < self.loader_batch_size:
               while self._loader_batch_index < self.loader_batch_size:
                     _lowerCAmelCase 			=  self.loader_batch_item()
                     _lowerCAmelCase 			=  item.pop('''is_last'''			)
                     accumulator.append(_lowerCAmelCase			)
                     if is_last:
                           return accumulator

         while not is_last:
               _lowerCAmelCase 			=  self.infer(next(self.iterator			)       ,     **self.params			)
               if self.loader_batch_size is not None:
                     if isinstance(_lowerCAmelCase       ,     torch.Tensor			):
                           _lowerCAmelCase 			=  processed
                     else:
                           _lowerCAmelCase 			=  list(processed.keys()			)[0]
                           _lowerCAmelCase 			=  processed[key]
                     if isinstance(_lowerCAmelCase       ,     _lowerCAmelCase			):
                           _lowerCAmelCase 			=  len(_lowerCAmelCase			)
                     else:
                           _lowerCAmelCase 			=  first_tensor.shape[0]
                     if 0 < observed_batch_size < self.loader_batch_size:
                           # could be last batch so we can't unroll as many
                           # elements.
                           _lowerCAmelCase 			=  observed_batch_size
                     _lowerCAmelCase 			=  processed
                     _lowerCAmelCase 			=  0
                     while self._loader_batch_index < self.loader_batch_size:
                           _lowerCAmelCase 			=  self.loader_batch_item()
                           _lowerCAmelCase 			=  item.pop('''is_last'''			)
                           accumulator.append(_lowerCAmelCase			)
                           if is_last:
                                 return accumulator
               else:
                     _lowerCAmelCase 			=  processed
                     _lowerCAmelCase 			=  item.pop('''is_last'''			)
                     accumulator.append(_lowerCAmelCase			)
         return accumulator






class 		UpperCAmelCase						(						snake_case_				):





   def __init__(	self       ,     _lowerCAmelCase       ,     _lowerCAmelCase			):
         _lowerCAmelCase 			=  dataset
         _lowerCAmelCase 			=  key





   def __len__(	self			):
         return len(self.dataset			)





   def __getitem__(	self       ,     _lowerCAmelCase			):
         return self.dataset[i][self.key]






class 		UpperCAmelCase						(						snake_case_				):





   def __init__(	self       ,     _lowerCAmelCase       ,     _lowerCAmelCase       ,     _lowerCAmelCase			):
         _lowerCAmelCase 			=  dataset
         _lowerCAmelCase 			=  keya
         _lowerCAmelCase 			=  keya





   def __len__(	self			):
         return len(self.dataset			)





   def __getitem__(	self       ,     _lowerCAmelCase			):
         return {"text": self.dataset[i][self.keya], "text_pair": self.dataset[i][self.keya]}