
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

A											=     get_logger()

A											=     None


class SCREAMING_SNAKE_CASE  (		TensorFormatter[Mapping, """jax.Array""", Mapping]							):






			"""simple docstring"""




			def __init__(    self ,				__UpperCamelCase=None ,				__UpperCamelCase=None ,				**__UpperCamelCase							):

				"""simple docstring"""


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

				if isinstance(__UpperCamelCase ,				__UpperCamelCase							):
					raise ValueError(
					    f"""Expected {device} to be a `str` not {type(__UpperCamelCase							)}, 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`.'							)
				snake_case_      		= device if isinstance(__UpperCamelCase ,				__UpperCamelCase							) 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:
					snake_case_      		= 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]							)}."""							)
					snake_case_      		= str(jax.devices()[0]							)
				snake_case_      		= jnp_array_kwargs


			@staticmethod
			def 			__lowerCAmelCase (    ):

				"""simple docstring"""


				import jax

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


			def 			__lowerCAmelCase (    self ,				__UpperCamelCase							):

				"""simple docstring"""


				import jax
				import jax.numpy as jnp

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


			def 			__lowerCAmelCase (    self ,				__UpperCamelCase							):

				"""simple docstring"""


				import jax
				import jax.numpy as jnp

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

				snake_case_      		= {}

				if isinstance(__UpperCamelCase ,				(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:
						snake_case_      		= {'dtype': jnp.intaa}
					else:
						snake_case_      		= {'dtype': jnp.intaa}
				elif isinstance(__UpperCamelCase ,				(np.number, np.ndarray)							) and np.issubdtype(value.dtype ,				np.floating							):
					snake_case_      		= {'dtype': jnp.floataa}
				elif config.PIL_AVAILABLE and "PIL" in sys.modules:
					import PIL.Image

					if isinstance(__UpperCamelCase ,				PIL.Image.Image							):
						snake_case_      		= np.asarray(__UpperCamelCase							)

        # 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:
					snake_case_      		= 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(__UpperCamelCase ,				**{**default_dtype, **self.jnp_array_kwargs}							)


			def 			__lowerCAmelCase (    self ,				__UpperCamelCase							):

				"""simple docstring"""


				import jax

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

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


			def 			__lowerCAmelCase (    self ,				__UpperCamelCase							):

				"""simple docstring"""


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


			def 			__lowerCAmelCase (    self ,				__UpperCamelCase							):

				"""simple docstring"""


				snake_case_      		= self.numpy_arrow_extractor().extract_row(__UpperCamelCase							)
				snake_case_      		= self.python_features_decoder.decode_row(__UpperCamelCase							)
				return self.recursive_tensorize(__UpperCamelCase							)


			def 			__lowerCAmelCase (    self ,				__UpperCamelCase							):

				"""simple docstring"""


				snake_case_      		= self.numpy_arrow_extractor().extract_column(__UpperCamelCase							)
				snake_case_      		= self.python_features_decoder.decode_column(__UpperCamelCase ,				pa_table.column_names[0]							)
				snake_case_      		= self.recursive_tensorize(__UpperCamelCase							)
				snake_case_      		= self._consolidate(__UpperCamelCase							)
				return column







			def 			__lowerCAmelCase (    self ,				__UpperCamelCase							):

				"""simple docstring"""


				snake_case_      		= self.numpy_arrow_extractor().extract_batch(__UpperCamelCase							)
				snake_case_      		= self.python_features_decoder.decode_batch(__UpperCamelCase							)
				snake_case_      		= self.recursive_tensorize(__UpperCamelCase							)
				for column_name in batch:
					snake_case_      		= self._consolidate(batch[column_name]							)
				return batch



from ..utils import DummyObject, requires_backends


class SCREAMING_SNAKE_CASE  (		metaclass=__snake_case							):






			"""simple docstring"""




			__A						  =  ["""torch""", """transformers""", """onnx"""]


			def __init__(    self ,				*__UpperCamelCase ,				**__UpperCamelCase							):

				"""simple docstring"""


				requires_backends(self ,				['torch', 'transformers', 'onnx']							)


			@classmethod
			def 			__lowerCAmelCase (    cls ,				*__UpperCamelCase ,				**__UpperCamelCase							):

				"""simple docstring"""


				requires_backends(cls ,				['torch', 'transformers', 'onnx']							)







			@classmethod
			def 			__lowerCAmelCase (    cls ,				*__UpperCamelCase ,				**__UpperCamelCase							):

				"""simple docstring"""


				requires_backends(cls ,				['torch', 'transformers', 'onnx']							)







class SCREAMING_SNAKE_CASE  (		metaclass=__snake_case							):






			"""simple docstring"""




			__A						  =  ["""torch""", """transformers""", """onnx"""]


			def __init__(    self ,				*__UpperCamelCase ,				**__UpperCamelCase							):

				"""simple docstring"""


				requires_backends(self ,				['torch', 'transformers', 'onnx']							)


			@classmethod
			def 			__lowerCAmelCase (    cls ,				*__UpperCamelCase ,				**__UpperCamelCase							):

				"""simple docstring"""


				requires_backends(cls ,				['torch', 'transformers', 'onnx']							)







			@classmethod
			def 			__lowerCAmelCase (    cls ,				*__UpperCamelCase ,				**__UpperCamelCase							):

				"""simple docstring"""


				requires_backends(cls ,				['torch', 'transformers', 'onnx']							)







class SCREAMING_SNAKE_CASE  (		metaclass=__snake_case							):






			"""simple docstring"""




			__A						  =  ["""torch""", """transformers""", """onnx"""]


			def __init__(    self ,				*__UpperCamelCase ,				**__UpperCamelCase							):

				"""simple docstring"""


				requires_backends(self ,				['torch', 'transformers', 'onnx']							)


			@classmethod
			def 			__lowerCAmelCase (    cls ,				*__UpperCamelCase ,				**__UpperCamelCase							):

				"""simple docstring"""


				requires_backends(cls ,				['torch', 'transformers', 'onnx']							)







			@classmethod
			def 			__lowerCAmelCase (    cls ,				*__UpperCamelCase ,				**__UpperCamelCase							):

				"""simple docstring"""


				requires_backends(cls ,				['torch', 'transformers', 'onnx']							)







class SCREAMING_SNAKE_CASE  (		metaclass=__snake_case							):






			"""simple docstring"""




			__A						  =  ["""torch""", """transformers""", """onnx"""]


			def __init__(    self ,				*__UpperCamelCase ,				**__UpperCamelCase							):

				"""simple docstring"""


				requires_backends(self ,				['torch', 'transformers', 'onnx']							)


			@classmethod
			def 			__lowerCAmelCase (    cls ,				*__UpperCamelCase ,				**__UpperCamelCase							):

				"""simple docstring"""


				requires_backends(cls ,				['torch', 'transformers', 'onnx']							)







			@classmethod
			def 			__lowerCAmelCase (    cls ,				*__UpperCamelCase ,				**__UpperCamelCase							):

				"""simple docstring"""


				requires_backends(cls ,				['torch', 'transformers', 'onnx']							)







class SCREAMING_SNAKE_CASE  (		metaclass=__snake_case							):






			"""simple docstring"""




			__A						  =  ["""torch""", """transformers""", """onnx"""]


			def __init__(    self ,				*__UpperCamelCase ,				**__UpperCamelCase							):

				"""simple docstring"""


				requires_backends(self ,				['torch', 'transformers', 'onnx']							)


			@classmethod
			def 			__lowerCAmelCase (    cls ,				*__UpperCamelCase ,				**__UpperCamelCase							):

				"""simple docstring"""


				requires_backends(cls ,				['torch', 'transformers', 'onnx']							)







			@classmethod
			def 			__lowerCAmelCase (    cls ,				*__UpperCamelCase ,				**__UpperCamelCase							):

				"""simple docstring"""


				requires_backends(cls ,				['torch', 'transformers', 'onnx']							)







class SCREAMING_SNAKE_CASE  (		metaclass=__snake_case							):






			"""simple docstring"""




			__A						  =  ["""torch""", """transformers""", """onnx"""]


			def __init__(    self ,				*__UpperCamelCase ,				**__UpperCamelCase							):

				"""simple docstring"""


				requires_backends(self ,				['torch', 'transformers', 'onnx']							)


			@classmethod
			def 			__lowerCAmelCase (    cls ,				*__UpperCamelCase ,				**__UpperCamelCase							):

				"""simple docstring"""


				requires_backends(cls ,				['torch', 'transformers', 'onnx']							)







			@classmethod
			def 			__lowerCAmelCase (    cls ,				*__UpperCamelCase ,				**__UpperCamelCase							):

				"""simple docstring"""


				requires_backends(cls ,				['torch', 'transformers', 'onnx']							)
