'''simple docstring'''

# Lint as: python3
import sys
from collections.abc import Mapping
from typing import TYPE_CHECKING, Dict, Optional

import numpy as np
import pyarrow as pa

from .. import config
from ..utils.logging import get_logger
from ..utils.py_utils import map_nested
from .formatting import TensorFormatter


if TYPE_CHECKING:
  import jax
  import jaxlib

UpperCamelCase__  :						Dict					=      get_logger()

UpperCamelCase__  :						Optional[dict]					=      None


class 					_lowercase						(   TensorFormatter[Mapping, '''jax.Array''', Mapping] ):
      '''simple docstring'''


      def __init__(					self       ,lowerCamelCase_=None       ,lowerCamelCase_=None       ,**lowerCamelCase_				)      ->      Optional[Any]:



         '''simple docstring'''



         super().__init__(features=__snake_case				)
         import jax
         from jaxlib.xla_client import Device

         if isinstance(__snake_case       ,__snake_case				):
            raise ValueError(
                f'''Expected {device} to be a `str` not {type(__snake_case				)}, as `jaxlib.xla_extension.Device` '''
                '''is not serializable neither with `pickle` nor with `dill`. Instead you can surround '''
                '''the device with `str()` to get its string identifier that will be internally mapped '''
                '''to the actual `jaxlib.xla_extension.Device`.'''				)
         UpperCAmelCase__				:					str 					=	device if isinstance(__snake_case       ,__snake_case				) else str(jax.devices()[0]				)
         # using global variable since `jaxlib.xla_extension.Device` is not serializable neither
         # with `pickle` nor with `dill`, so we need to use a global variable instead
         global DEVICE_MAPPING
         if DEVICE_MAPPING is None:
            UpperCAmelCase__				:					Dict 					=	self._map_devices_to_str()
         if self.device not in list(DEVICE_MAPPING.keys()				):
            logger.warning(
                f'''Device with string identifier {self.device} not listed among the available '''
                f'''devices: {list(DEVICE_MAPPING.keys()				)}, so falling back to the default '''
                f'''device: {str(jax.devices()[0]				)}.'''				)
            UpperCAmelCase__				:					Dict 					=	str(jax.devices()[0]				)
         UpperCAmelCase__				:					Dict 					=	jnp_array_kwargs




      @staticmethod
      def 		lowerCAmelCase__       (					)      ->      Any:



         '''simple docstring'''



         import jax

         return {str(__snake_case				): device for device in jax.devices()}




      def 		lowerCAmelCase__       (					self       ,lowerCamelCase_				)      ->      List[str]:



         '''simple docstring'''



         import jax
         import jax.numpy as jnp

         if isinstance(__snake_case       ,__snake_case				) and column:
            if all(
                isinstance(__snake_case       ,jax.Array				) and x.shape == column[0].shape and x.dtype == column[0].dtype for x in column				):
               return jnp.stack(__snake_case       ,axis=0				)
         return column




      def 		lowerCAmelCase__       (					self       ,lowerCamelCase_				)      ->      List[Any]:



         '''simple docstring'''



         import jax
         import jax.numpy as jnp

         if isinstance(__snake_case       ,(str, bytes, type(__snake_case				))				):
            return value
         elif isinstance(__snake_case       ,(np.character, np.ndarray)				) and np.issubdtype(value.dtype       ,np.character				):
            return value.tolist()

         UpperCAmelCase__				:					Union[str, Any] 					=	{}

         if isinstance(__snake_case       ,(np.number, np.ndarray)				) and np.issubdtype(value.dtype       ,np.integer				):
            # the default int precision depends on the jax config
            # see https://jax.readthedocs.io/en/latest/notebooks/Common_Gotchas_in_JAX.html#double-64bit-precision
            if jax.config.jax_enable_xaa:
               UpperCAmelCase__				:					int 					=	{'''dtype''': jnp.intaa}
            else:
               UpperCAmelCase__				:					Dict 					=	{'''dtype''': jnp.intaa}
         elif isinstance(__snake_case       ,(np.number, np.ndarray)				) and np.issubdtype(value.dtype       ,np.floating				):
            UpperCAmelCase__				:					Tuple 					=	{'''dtype''': jnp.floataa}
         elif config.PIL_AVAILABLE and "PIL" in sys.modules:
            import PIL.Image

            if isinstance(__snake_case       ,PIL.Image.Image				):
               UpperCAmelCase__				:					Any 					=	np.asarray(__snake_case				)

        # using global variable since `jaxlib.xla_extension.Device` is not serializable neither
        # with `pickle` nor with `dill`, so we need to use a global variable instead
         global DEVICE_MAPPING
         if DEVICE_MAPPING is None:
            UpperCAmelCase__				:					List[Any] 					=	self._map_devices_to_str()

         with jax.default_device(DEVICE_MAPPING[self.device]				):
            # calling jnp.array on a np.ndarray does copy the data
            # see https://github.com/google/jax/issues/4486
            return jnp.array(__snake_case       ,**{**default_dtype, **self.jnp_array_kwargs}				)




      def 		lowerCAmelCase__       (					self       ,lowerCamelCase_				)      ->      str:



         '''simple docstring'''



         import jax

         # support for torch, tf, jax etc.
         if config.TORCH_AVAILABLE and "torch" in sys.modules:
            import torch

            if isinstance(__snake_case       ,torch.Tensor				):
               return self._tensorize(data_struct.detach().cpu().numpy()[()]				)
         if hasattr(__snake_case       ,'''__array__'''				) and not isinstance(__snake_case       ,jax.Array				):
            UpperCAmelCase__				:					int 					=	data_struct.__array__()
         # support for nested types like struct of list of struct
         if isinstance(__snake_case       ,np.ndarray				):
            if data_struct.dtype == object:  # jax arrays cannot be instantied from an array of objects
               return self._consolidate([self.recursive_tensorize(__snake_case				) for substruct in data_struct]				)
         elif isinstance(__snake_case       ,(list, tuple)				):
            return self._consolidate([self.recursive_tensorize(__snake_case				) for substruct in data_struct]				)
         return self._tensorize(__snake_case				)




      def 		lowerCAmelCase__       (					self       ,lowerCamelCase_				)      ->      List[str]:



         '''simple docstring'''



         return map_nested(self._recursive_tensorize       ,__snake_case       ,map_list=__snake_case				)




      def 		lowerCAmelCase__       (					self       ,lowerCamelCase_				)      ->      int:



         '''simple docstring'''



         UpperCAmelCase__				:					List[str] 					=	self.numpy_arrow_extractor().extract_row(__snake_case				)
         UpperCAmelCase__				:					List[str] 					=	self.python_features_decoder.decode_row(__snake_case				)
         return self.recursive_tensorize(__snake_case				)




      def 		lowerCAmelCase__       (					self       ,lowerCamelCase_				)      ->      str:



         '''simple docstring'''



         UpperCAmelCase__				:					Any 					=	self.numpy_arrow_extractor().extract_column(__snake_case				)
         UpperCAmelCase__				:					Union[str, Any] 					=	self.python_features_decoder.decode_column(__snake_case       ,pa_table.column_names[0]				)
         UpperCAmelCase__				:					Dict 					=	self.recursive_tensorize(__snake_case				)
         UpperCAmelCase__				:					Tuple 					=	self._consolidate(__snake_case				)
         return column




      def 		lowerCAmelCase__       (					self       ,lowerCamelCase_				)      ->      Tuple:



         '''simple docstring'''



         UpperCAmelCase__				:					Optional[int] 					=	self.numpy_arrow_extractor().extract_batch(__snake_case				)
         UpperCAmelCase__				:					List[str] 					=	self.python_features_decoder.decode_batch(__snake_case				)
         UpperCAmelCase__				:					Optional[int] 					=	self.recursive_tensorize(__snake_case				)
         for column_name in batch:
            UpperCAmelCase__				:					List[Any] 					=	self._consolidate(batch[column_name]				)
         return batch








from ..utils import DummyObject, requires_backends

class     A__   (       metaclass=snake_case__      ):







    """simple docstring"""

    __magic_name__         =						['flax', 'transformers']
    def __init__(			self     ,   *__snake_case     ,   **__snake_case       ):
         requires_backends(self     ,   ['''flax''', '''transformers''']       )
    @classmethod
    def 						a_     (			cls     ,   *__snake_case     ,   **__snake_case       ):
         requires_backends(cls     ,   ['''flax''', '''transformers''']       )




    @classmethod
    def 						a_     (			cls     ,   *__snake_case     ,   **__snake_case       ):
         requires_backends(cls     ,   ['''flax''', '''transformers''']       )






class     A__   (       metaclass=snake_case__      ):







    """simple docstring"""

    __magic_name__         =						['flax', 'transformers']
    def __init__(			self     ,   *__snake_case     ,   **__snake_case       ):
         requires_backends(self     ,   ['''flax''', '''transformers''']       )
    @classmethod
    def 						a_     (			cls     ,   *__snake_case     ,   **__snake_case       ):
         requires_backends(cls     ,   ['''flax''', '''transformers''']       )




    @classmethod
    def 						a_     (			cls     ,   *__snake_case     ,   **__snake_case       ):
         requires_backends(cls     ,   ['''flax''', '''transformers''']       )






class     A__   (       metaclass=snake_case__      ):







    """simple docstring"""

    __magic_name__         =						['flax', 'transformers']
    def __init__(			self     ,   *__snake_case     ,   **__snake_case       ):
         requires_backends(self     ,   ['''flax''', '''transformers''']       )
    @classmethod
    def 						a_     (			cls     ,   *__snake_case     ,   **__snake_case       ):
         requires_backends(cls     ,   ['''flax''', '''transformers''']       )




    @classmethod
    def 						a_     (			cls     ,   *__snake_case     ,   **__snake_case       ):
         requires_backends(cls     ,   ['''flax''', '''transformers''']       )






class     A__   (       metaclass=snake_case__      ):







    """simple docstring"""

    __magic_name__         =						['flax', 'transformers']
    def __init__(			self     ,   *__snake_case     ,   **__snake_case       ):
         requires_backends(self     ,   ['''flax''', '''transformers''']       )
    @classmethod
    def 						a_     (			cls     ,   *__snake_case     ,   **__snake_case       ):
         requires_backends(cls     ,   ['''flax''', '''transformers''']       )




    @classmethod
    def 						a_     (			cls     ,   *__snake_case     ,   **__snake_case       ):
         requires_backends(cls     ,   ['''flax''', '''transformers''']       )




