





'''simple docstring'''

import io
import itertools
import json
from dataclasses import dataclass
from typing import Optional

import pyarrow as pa
import pyarrow.json as paj

import datasets
from datasets.table import table_cast
from datasets.utils.file_utils import readline


a   	=    datasets.utils.logging.get_logger(__name__)







@dataclass
class __a			( datasets.BuilderConfig      ):
   __UpperCamelCase :			str						   =						None
   __UpperCamelCase :			int						   =						'utf-8'
   __UpperCamelCase :			Tuple						   =						None
   __UpperCamelCase :			Union[str, Any]						   =						None
   __UpperCamelCase :			Optional[int]						   =						True  # deprecated
   __UpperCamelCase :			int						   =						None  # deprecated
   __UpperCamelCase :			Any						   =						10 << 20  # 10MB
   __UpperCamelCase :			Optional[int]						   =						None







class __a			( datasets.ArrowBasedBuilder      ):
   __UpperCamelCase :			List[str]						   =						JsonConfig





   def   UpperCAmelCase__  (       self					:      Dict     ):

      '''simple docstring'''

      if self.config.block_size is not None:
         logger.warning("""The JSON loader parameter `block_size` is deprecated. Please use `chunksize` instead"""     )
         __SCREAMING_SNAKE_CASE   				=							self.config.block_size
      if self.config.use_threads is not True:
         logger.warning(
             """The JSON loader parameter `use_threads` is deprecated and doesn\'t have any effect anymore."""     )
      if self.config.newlines_in_values is not None:
         raise ValueError("""The JSON loader parameter `newlines_in_values` is no longer supported"""     )
      return datasets.DatasetInfo(features=self.config.features     )





   def   UpperCAmelCase__  (       self					:      str					,lowerCamelCase					:      Optional[int]     ):

      '''simple docstring'''

      if not self.config.data_files:
         raise ValueError(f"""At least one data file must be specified, but got data_files={self.config.data_files}"""     )
      __SCREAMING_SNAKE_CASE   				=							dl_manager.download_and_extract(self.config.data_files     )
      if isinstance(lowerCamelCase					,(str, list, tuple)     ):
         __SCREAMING_SNAKE_CASE   				=							data_files
         if isinstance(lowerCamelCase					,lowerCamelCase     ):
            __SCREAMING_SNAKE_CASE   				=							[files]
         __SCREAMING_SNAKE_CASE   				=							[dl_manager.iter_files(lowerCamelCase     ) for file in files]
         return [datasets.SplitGenerator(name=datasets.Split.TRAIN					,gen_kwargs={"""files""": files}     )]
      __SCREAMING_SNAKE_CASE   				=							[]
      for split_name, files in data_files.items():
         if isinstance(lowerCamelCase					,lowerCamelCase     ):
            __SCREAMING_SNAKE_CASE   				=							[files]
         __SCREAMING_SNAKE_CASE   				=							[dl_manager.iter_files(lowerCamelCase     ) for file in files]
         splits.append(datasets.SplitGenerator(name=lowerCamelCase					,gen_kwargs={"""files""": files}     )     )
      return splits





   def   UpperCAmelCase__  (       self					:      Dict					,lowerCamelCase					:      Optional[Any]     ):

      '''simple docstring'''

      if self.config.features is not None:
         # adding missing columns
         for column_name in set(self.config.features     ) - set(pa_table.column_names     ):
            __SCREAMING_SNAKE_CASE   				=							self.config.features.arrow_schema.field(lowerCamelCase     ).type
            __SCREAMING_SNAKE_CASE   				=							pa_table.append_column(lowerCamelCase					,pa.array([None] * len(lowerCamelCase     )					,type=lowerCamelCase     )     )
         # more expensive cast to support nested structures with keys in a different order
         # allows str <-> int/float or str to Audio for example
         __SCREAMING_SNAKE_CASE   				=							table_cast(lowerCamelCase					,self.config.features.arrow_schema     )
      return pa_table





   def   UpperCAmelCase__  (       self					:      Dict					,lowerCamelCase					:      Union[str, Any]     ):

      '''simple docstring'''

      for file_idx, file in enumerate(itertools.chain.from_iterable(lowerCamelCase     )     ):
         # If the file is one json object and if we need to look at the list of items in one specific field
         if self.config.field is not None:
            with open(lowerCamelCase					,encoding=self.config.encoding					,errors=self.config.encoding_errors     ) as f:
               __SCREAMING_SNAKE_CASE   				=							json.load(lowerCamelCase     )

            # We keep only the field we are interested in
            __SCREAMING_SNAKE_CASE   				=							dataset[self.config.field]

            # We accept two format: a list of dicts or a dict of lists
            if isinstance(lowerCamelCase					,(list, tuple)     ):
               __SCREAMING_SNAKE_CASE   				=							set().union(*[row.keys() for row in dataset]     )
               __SCREAMING_SNAKE_CASE   				=							{col: [row.get(lowerCamelCase     ) for row in dataset] for col in keys}
            else:
               __SCREAMING_SNAKE_CASE   				=							dataset
            __SCREAMING_SNAKE_CASE   				=							pa.Table.from_pydict(lowerCamelCase     )
            yield file_idx, self._cast_table(lowerCamelCase     )

         # If the file has one json object per line
         else:
            with open(lowerCamelCase					,"""rb"""     ) as f:
               __SCREAMING_SNAKE_CASE   				=							0
               # Use block_size equal to the chunk size divided by 32 to leverage multithreading
               # Set a default minimum value of 16kB if the chunk size is really small
               __SCREAMING_SNAKE_CASE   				=							max(self.config.chunksize // 32					,16 << 10     )
               __SCREAMING_SNAKE_CASE   				=							(
                   self.config.encoding_errors if self.config.encoding_errors is not None else """strict"""
               )
               while True:
                  __SCREAMING_SNAKE_CASE   				=							f.read(self.config.chunksize     )
                  if not batch:
                     break
                  # Finish current line
                  try:
                     batch += f.readline()
                  except (AttributeError, io.UnsupportedOperation):
                     batch += readline(lowerCamelCase     )
                  # PyArrow only accepts utf-8 encoded bytes
                  if self.config.encoding != "utf-8":
                     __SCREAMING_SNAKE_CASE   				=							batch.decode(self.config.encoding					,errors=lowerCamelCase     ).encode("""utf-8"""     )
                  try:
                     while True:
                        try:
                           __SCREAMING_SNAKE_CASE   				=							paj.read_json(
                               io.BytesIO(lowerCamelCase     )					,read_options=paj.ReadOptions(block_size=lowerCamelCase     )     )
                           break
                        except (pa.ArrowInvalid, pa.ArrowNotImplementedError) as e:
                           if (
                               isinstance(lowerCamelCase					,pa.ArrowInvalid     )
                               and "straddling" not in str(lowerCamelCase     )
                               or block_size > len(lowerCamelCase     )
                           ):
                              raise
                           else:
                              # Increase the block size in case it was too small.
                              # The block size will be reset for the next file.
                              logger.debug(
                                  f"""Batch of {len(lowerCamelCase     )} bytes couldn\'t be parsed with block_size={block_size}. Retrying with block_size={block_size * 2}."""     )
                              block_size *= 2
                  except pa.ArrowInvalid as e:
                     try:
                        with open(
                            lowerCamelCase					,encoding=self.config.encoding					,errors=self.config.encoding_errors     ) as f:
                           __SCREAMING_SNAKE_CASE   				=							json.load(lowerCamelCase     )
                     except json.JSONDecodeError:
                        logger.error(f"""Failed to read file \'{file}\' with error {type(lowerCamelCase     )}: {e}"""     )
                        raise e
                     # If possible, parse the file as a list of json objects and exit the loop
                     if isinstance(lowerCamelCase					,lowerCamelCase     ):  # list is the only sequence type supported in JSON
                        try:
                           __SCREAMING_SNAKE_CASE   				=							set().union(*[row.keys() for row in dataset]     )
                           __SCREAMING_SNAKE_CASE   				=							{col: [row.get(lowerCamelCase     ) for row in dataset] for col in keys}
                           __SCREAMING_SNAKE_CASE   				=							pa.Table.from_pydict(lowerCamelCase     )
                        except (pa.ArrowInvalid, AttributeError) as e:
                           logger.error(f"""Failed to read file \'{file}\' with error {type(lowerCamelCase     )}: {e}"""     )
                           raise ValueError(f"""Not able to read records in the JSON file at {file}."""     ) from None
                        yield file_idx, self._cast_table(lowerCamelCase     )
                        break
                     else:
                        logger.error(f"""Failed to read file \'{file}\' with error {type(lowerCamelCase     )}: {e}"""     )
                        raise ValueError(
                            f"""Not able to read records in the JSON file at {file}. """
                            f"""You should probably indicate the field of the JSON file containing your records. """
                            f"""This JSON file contain the following fields: {str(list(dataset.keys()     )     )}. """
                            f"""Select the correct one and provide it as `field=\'XXX\'` to the dataset loading method. """     ) from None
                        # Uncomment for debugging (will print the Arrow table size and elements)
                        # logger.warning(f"pa_table: {pa_table} num rows: {pa_table.num_rows}")
                        # logger.warning('\n'.join(str(pa_table.slice(i, 1).to_pydict()) for i in range(pa_table.num_rows)))
                  yield (file_idx, batch_idx), self._cast_table(lowerCamelCase     )
                  batch_idx += 1








from collections import UserDict
from typing import Union

import numpy as np
import requests

from ..utils import (
    add_end_docstrings,
    logging,
)
from .audio_classification import ffmpeg_read
from .base import PIPELINE_INIT_ARGS, Pipeline


lowercase_   							=  logging.get_logger(__name__)





@add_end_docstrings(SCREAMING_SNAKE_CASE				)
class 					__lowerCAmelCase	(   SCREAMING_SNAKE_CASE				):




  def __init__(							self				,  **lowerCAmelCase   )    ->					Tuple:
        '''simple docstring'''






        super().__init__(**lowerCAmelCase   )

        if self.framework != "pt":
              raise ValueError(F'''The {self.__class__} is only available in PyTorch.'''   )
        # No specific FOR_XXX available yet




  def __call__(							self				,  lowerCAmelCase				,  **lowerCAmelCase   )    ->					int:
        '''simple docstring'''






        return super().__call__(lowerCAmelCase				,  **lowerCAmelCase   )




  def     A__	(							self				,  **lowerCAmelCase   )    ->					Optional[Any]:
        '''simple docstring'''






        _lowercase      			={}
        if "candidate_labels" in kwargs:
              _lowercase      			=kwargs['candidate_labels']
        if "hypothesis_template" in kwargs:
              _lowercase      			=kwargs['hypothesis_template']

        return preprocess_params, {}, {}




  def     A__	(							self				,  lowerCAmelCase				,  lowerCAmelCase=None				,  lowerCAmelCase="This is a sound of {}."   )    ->					Tuple:
        '''simple docstring'''






        if isinstance(lowerCAmelCase				,  lowerCAmelCase   ):
              if audio.startswith('http://'   ) or audio.startswith('https://'   ):
                    # We need to actually check for a real protocol, otherwise it's impossible to use a local file
                    # like http_huggingface_co.png
                    _lowercase      			=requests.get(lowerCAmelCase   ).content
              else:
                    with open(lowerCAmelCase				,  'rb'   ) as f:
                          _lowercase      			=f.read()

        if isinstance(lowerCAmelCase				,  lowerCAmelCase   ):
              _lowercase      			=ffmpeg_read(lowerCAmelCase				,  self.feature_extractor.sampling_rate   )

        if not isinstance(lowerCAmelCase				,  np.ndarray   ):
              raise ValueError('We expect a numpy ndarray as input'   )
        if len(audio.shape   ) != 1:
              raise ValueError('We expect a single channel audio input for ZeroShotAudioClassificationPipeline'   )

        _lowercase      			=self.feature_extractor(
            [audio]				,  sampling_rate=self.feature_extractor.sampling_rate				,  return_tensors='pt'   )
        _lowercase      			=candidate_labels
        _lowercase      			=[hypothesis_template.format(lowerCAmelCase   ) for x in candidate_labels]
        _lowercase      			=self.tokenizer(lowerCAmelCase				,  return_tensors=self.framework				,  padding=lowerCAmelCase   )
        _lowercase      			=[text_inputs]
        return inputs




  def     A__	(							self				,  lowerCAmelCase   )    ->					Dict:
        '''simple docstring'''






        _lowercase      			=model_inputs.pop('candidate_labels'   )
        _lowercase      			=model_inputs.pop('text_inputs'   )
        if isinstance(text_inputs[0]				,  lowerCAmelCase   ):
              _lowercase      			=text_inputs[0]
        else:
              # Batching case.
              _lowercase      			=text_inputs[0][0]

        _lowercase      			=self.model(**lowerCAmelCase				,  **lowerCAmelCase   )

        _lowercase      			={
            'candidate_labels': candidate_labels,
            'logits': outputs.logits_per_audio,
        }
        return model_outputs




  def     A__	(							self				,  lowerCAmelCase   )    ->					Tuple:
        '''simple docstring'''






        _lowercase      			=model_outputs.pop('candidate_labels'   )
        _lowercase      			=model_outputs['logits'][0]

        if self.framework == "pt":
              _lowercase      			=logits.softmax(dim=0   )
              _lowercase      			=probs.tolist()
        else:
              raise ValueError('`tf` framework not supported.'   )

        _lowercase      			=[
            {'score': score, 'label': candidate_label}
            for score, candidate_label in sorted(zip(lowerCAmelCase				,  lowerCAmelCase   )				,  key=lambda lowerCAmelCase   : -x[0]   )
        ]
        return result


