



import os
import sys
import warnings
from dataclasses import dataclass, field
from io import BytesIO
from typing import TYPE_CHECKING, Any, ClassVar, Dict, List, Optional, Union

import numpy as np
import pyarrow as pa

from .. import config
from ..download.streaming_download_manager import xopen
from ..table import array_cast
from ..utils.file_utils import is_local_path
from ..utils.py_utils import first_non_null_value, no_op_if_value_is_null, string_to_dict


if TYPE_CHECKING:
	import PIL.Image

	from .features import FeatureType


a	:   int       			=       None
a	:   Dict       			=       '<' if sys.byteorder == 'little' else '>'
# Origin: https://github.com/python-pillow/Pillow/blob/698951e19e19972aeed56df686868f1329981c12/src/PIL/Image.py#L3126 minus "|i1" which values are not preserved correctly when saving and loading an image
a	:   List[str]       			=       [
    np.dtype('|b1'),
    np.dtype('|u1'),
    np.dtype('<u2'),
    np.dtype('>u2'),
    np.dtype('<i2'),
    np.dtype('>i2'),
    np.dtype('<u4'),
    np.dtype('>u4'),
    np.dtype('<i4'),
    np.dtype('>i4'),
    np.dtype('<f4'),
    np.dtype('>f4'),
    np.dtype('<f8'),
    np.dtype('>f8'),
]







@dataclass
class 							_a							:
			A							=     True
			A							=     None
			# Automatically constructed
			A							=     '''PIL.Image.Image'''
			A							=     pa.struct({'''bytes''': pa.binary(), '''path''': pa.string()} )
			A							=     field(default='''Image'''      ,						init=__a      ,						repr=__a )

			def __call__(self )    ->					Any:
						return self.pa_type

			def 			__snake_case    (self,					SCREAMING_SNAKE_CASE_ )    ->					dict:
						if config.PIL_AVAILABLE:
									import PIL.Image
						else:
									raise ImportError("""To support encoding images, please install 'Pillow'.""" )

						if isinstance(_UpperCamelCase,					_UpperCamelCase ):
									UpperCAmelCase_:						Any					=			np.array(_UpperCamelCase )

						if isinstance(_UpperCamelCase,					_UpperCamelCase ):
									return {"path": value, "bytes": None}
						elif isinstance(_UpperCamelCase,					_UpperCamelCase ):
									return {"path": None, "bytes": value}
						elif isinstance(_UpperCamelCase,					np.ndarray ):
									# convert the image array to PNG/TIFF bytes
									return encode_np_array(_UpperCamelCase )
						elif isinstance(_UpperCamelCase,					PIL.Image.Image ):
									# convert the PIL image to bytes (default format is PNG/TIFF)
									return encode_pil_image(_UpperCamelCase )
						elif value.get("""path""" ) is not None and os.path.isfile(value["""path"""] ):
									# we set "bytes": None to not duplicate the data if they're already available locally
									return {"bytes": None, "path": value.get("""path""" )}
						elif value.get("""bytes""" ) is not None or value.get("""path""" ) is not None:
									# store the image bytes, and path is used to infer the image format using the file extension
									return {"bytes": value.get("""bytes""" ), "path": value.get("""path""" )}
						else:
									raise ValueError(
									    f'An image sample should have one of \'path\' or \'bytes\' but they are missing or None in {value}.' )

			def 			__snake_case    (self,					SCREAMING_SNAKE_CASE_,					SCREAMING_SNAKE_CASE_=None )    ->					"PIL.Image.Image":
						if not self.decode:
									raise RuntimeError("""Decoding is disabled for this feature. Please use Image(decode=True) instead.""" )

						if config.PIL_AVAILABLE:
									import PIL.Image
						else:
									raise ImportError("""To support decoding images, please install 'Pillow'.""" )

						if token_per_repo_id is None:
									UpperCAmelCase_:						List[str]					=			{}

						UpperCAmelCase_	,				UpperCAmelCase_:						int					=			value["""path"""], value["""bytes"""]
						if bytes_ is None:
									if path is None:
												raise ValueError(f'An image should have one of \'path\' or \'bytes\' but both are None in {value}.' )
									else:
												if is_local_path(_UpperCamelCase ):
															UpperCAmelCase_:						Union[str, Any]					=			PIL.Image.open(_UpperCamelCase )
												else:
															UpperCAmelCase_:						Union[str, Any]					=			path.split("""::""" )[-1]
															try:
																		UpperCAmelCase_:						Optional[Any]					=			string_to_dict(_UpperCamelCase,					config.HUB_DATASETS_URL )["""repo_id"""]
																		UpperCAmelCase_:						Any					=			token_per_repo_id.get(_UpperCamelCase )
															except ValueError:
																		UpperCAmelCase_:						Dict					=			None
															with xopen(_UpperCamelCase,					"""rb""",					use_auth_token=_UpperCamelCase ) as f:
																		UpperCAmelCase_:						List[Any]					=			BytesIO(f.read() )
															UpperCAmelCase_:						List[Any]					=			PIL.Image.open(bytes_ )
						else:
									UpperCAmelCase_:						Any					=			PIL.Image.open(BytesIO(bytes_ ) )
						image.load()  # to avoid "Too many open files" errors
						return image

			def 			__snake_case    (self )    ->					Union["FeatureType", Dict[str, "FeatureType"]]:
						from .features import Value

						return (
						    self
						    if self.decode
						    else {
						        "bytes": Value("""binary""" ),
						        "path": Value("""string""" ),
						    }
						)

			def 			__snake_case    (self,					SCREAMING_SNAKE_CASE_ )    ->					pa.StructArray:
						if pa.types.is_string(storage.type ):
									UpperCAmelCase_:						Union[str, Any]					=			pa.array([None] * len(_UpperCamelCase ),					type=pa.binary() )
									UpperCAmelCase_:						Dict					=			pa.StructArray.from_arrays([bytes_array, storage],					["""bytes""", """path"""],					mask=storage.is_null() )
						elif pa.types.is_binary(storage.type ):
									UpperCAmelCase_:						Any					=			pa.array([None] * len(_UpperCamelCase ),					type=pa.string() )
									UpperCAmelCase_:						Tuple					=			pa.StructArray.from_arrays([storage, path_array],					["""bytes""", """path"""],					mask=storage.is_null() )
						elif pa.types.is_struct(storage.type ):
									if storage.type.get_field_index("""bytes""" ) >= 0:
												UpperCAmelCase_:						Tuple					=			storage.field("""bytes""" )
									else:
												UpperCAmelCase_:						Tuple					=			pa.array([None] * len(_UpperCamelCase ),					type=pa.binary() )
									if storage.type.get_field_index("""path""" ) >= 0:
												UpperCAmelCase_:						Tuple					=			storage.field("""path""" )
									else:
												UpperCAmelCase_:						Dict					=			pa.array([None] * len(_UpperCamelCase ),					type=pa.string() )
									UpperCAmelCase_:						Optional[int]					=			pa.StructArray.from_arrays([bytes_array, path_array],					["""bytes""", """path"""],					mask=storage.is_null() )
						elif pa.types.is_list(storage.type ):
									UpperCAmelCase_:						str					=			pa.array(
									    [encode_np_array(np.array(_UpperCamelCase ) )["""bytes"""] if arr is not None else None for arr in storage.to_pylist()],					type=pa.binary(),					)
									UpperCAmelCase_:						Union[str, Any]					=			pa.array([None] * len(_UpperCamelCase ),					type=pa.string() )
									UpperCAmelCase_:						Union[str, Any]					=			pa.StructArray.from_arrays(
									    [bytes_array, path_array],					["""bytes""", """path"""],					mask=bytes_array.is_null() )
						return array_cast(_UpperCamelCase,					self.pa_type )

			def 			__snake_case    (self,					SCREAMING_SNAKE_CASE_ )    ->					pa.StructArray:

						@no_op_if_value_is_null
						def path_to_bytes(SCREAMING_SNAKE_CASE_ ):
									with xopen(_UpperCamelCase,					"""rb""" ) as f:
												UpperCAmelCase_:						Tuple					=			f.read()
									return bytes_

						UpperCAmelCase_:						List[Any]					=			pa.array(
						    [
						        (path_to_bytes(x["""path"""] ) if x["""bytes"""] is None else x["""bytes"""]) if x is not None else None
						        for x in storage.to_pylist()
						    ],					type=pa.binary(),					)
						UpperCAmelCase_:						List[Any]					=			pa.array(
						    [os.path.basename(_UpperCamelCase ) if path is not None else None for path in storage.field("""path""" ).to_pylist()],					type=pa.string(),					)
						UpperCAmelCase_:						Optional[int]					=			pa.StructArray.from_arrays([bytes_array, path_array],					["""bytes""", """path"""],					mask=bytes_array.is_null() )
						return array_cast(_UpperCamelCase,					self.pa_type )







def       lowerCAmelCase_     ():





			"""simple docstring"""


			if config.PIL_AVAILABLE:
						import PIL.Image
			else:
						raise ImportError("""To support encoding images, please install 'Pillow'."""   )

			global _IMAGE_COMPRESSION_FORMATS
			if _IMAGE_COMPRESSION_FORMATS is None:
						PIL.Image.init()
						UpperCAmelCase_:						Optional[Any]					=			list(set(PIL.Image.OPEN.keys()   ) & set(PIL.Image.SAVE.keys()   )   )
			return _IMAGE_COMPRESSION_FORMATS







def       lowerCAmelCase_     (lowerCAmelCase__:						"PIL.Image.Image"   ):





			"""simple docstring"""


			UpperCAmelCase_:						Optional[int]					=			BytesIO()
			if image.format in list_image_compression_formats():
						UpperCAmelCase_:						List[Any]					=			image.format
			else:
						UpperCAmelCase_:						Optional[Any]					=			"""PNG""" if image.mode in ["""1""", """L""", """LA""", """RGB""", """RGBA"""] else """TIFF"""
			image.save(__lowerCAmelCase						,		format=__lowerCAmelCase   )
			return buffer.getvalue()







def       lowerCAmelCase_     (lowerCAmelCase__:						"PIL.Image.Image"   ):





			"""simple docstring"""


			if hasattr(__lowerCAmelCase						,		"""filename"""   ) and image.filename != "":
						return {"path": image.filename, "bytes": None}
			else:
						return {"path": None, "bytes": image_to_bytes(__lowerCAmelCase   )}







def       lowerCAmelCase_     (lowerCAmelCase__:						np.ndarray   ):





			"""simple docstring"""


			if config.PIL_AVAILABLE:
						import PIL.Image
			else:
						raise ImportError("""To support encoding images, please install 'Pillow'."""   )

			UpperCAmelCase_:						Dict					=			array.dtype
			UpperCAmelCase_:						Any					=			dtype.byteorder if dtype.byteorder != """=""" else _NATIVE_BYTEORDER
			UpperCAmelCase_:						List[str]					=			dtype.kind
			UpperCAmelCase_:						Optional[int]					=			dtype.itemsize

			UpperCAmelCase_:						List[Any]					=			None

			# Multi-channel array case (only np.dtype("|u1") is allowed)
			if array.shape[2:]:
						UpperCAmelCase_:						Dict					=			np.dtype("""|u1"""   )
						if dtype_kind not in ["u", "i"]:
									raise TypeError(
									    F'Unsupported array dtype {dtype} for image encoding. Only {dest_dtype} is supported for multi-channel arrays.'   )
						if dtype is not dest_dtype:
									warnings.warn(F'Downcasting array dtype {dtype} to {dest_dtype} to be compatible with \'Pillow\''   )
    # Exact match
			elif dtype in _VALID_IMAGE_ARRAY_DTPYES:
						UpperCAmelCase_:						Tuple					=			dtype
			else:  # Downcast the type within the kind (np.can_cast(from_type, to_type, casting="same_kind") doesn't behave as expected, so do it manually)
						while dtype_itemsize >= 1:
									UpperCAmelCase_:						Any					=			dtype_byteorder + dtype_kind + str(__lowerCAmelCase   )
									UpperCAmelCase_:						Optional[int]					=			np.dtype(__lowerCAmelCase   )
									if dest_dtype in _VALID_IMAGE_ARRAY_DTPYES:
												warnings.warn(F'Downcasting array dtype {dtype} to {dest_dtype} to be compatible with \'Pillow\''   )
												break
									else:
												dtype_itemsize //= 2

			if dest_dtype is None:
						raise TypeError(
						    F'Cannot convert dtype {dtype} to a valid image dtype. Valid image dtypes: {_VALID_IMAGE_ARRAY_DTPYES}'   )
			UpperCAmelCase_:						List[str]					=			PIL.Image.fromarray(array.astype(__lowerCAmelCase   )   )
			return {"path": None, "bytes": image_to_bytes(__lowerCAmelCase   )}







def       lowerCAmelCase_     (lowerCAmelCase__:						Union[List[str], List[dict], List[np.ndarray], List["PIL.Image.Image"]]   ):





			"""simple docstring"""


			if config.PIL_AVAILABLE:
						import PIL.Image
			else:
						raise ImportError("""To support encoding images, please install 'Pillow'."""   )

			if objs:
						UpperCAmelCase_	,				UpperCAmelCase_:						Tuple					=			first_non_null_value(__lowerCAmelCase   )
						if isinstance(__lowerCAmelCase						,		__lowerCAmelCase   ):
									return [{"path": obj, "bytes": None} if obj is not None else None for obj in objs]
						if isinstance(__lowerCAmelCase						,		np.ndarray   ):
									UpperCAmelCase_:						Dict					=			no_op_if_value_is_null(__lowerCAmelCase   )
									return [obj_to_image_dict_func(__lowerCAmelCase   ) for obj in objs]
						elif isinstance(__lowerCAmelCase						,		PIL.Image.Image   ):
									UpperCAmelCase_:						Union[str, Any]					=			no_op_if_value_is_null(__lowerCAmelCase   )
									return [obj_to_image_dict_func(__lowerCAmelCase   ) for obj in objs]
						else:
									return objs
			else:
						return objs








from argparse import ArgumentParser

from .add_new_model import AddNewModelCommand
from .add_new_model_like import AddNewModelLikeCommand
from .convert import ConvertCommand
from .download import DownloadCommand
from .env import EnvironmentCommand
from .lfs import LfsCommands
from .pt_to_tf import PTtoTFCommand
from .run import RunCommand
from .serving import ServeCommand
from .user import UserCommands






def    lowerCamelCase__				(				):




			"""simple docstring"""


			lowerCAmelCase_						=	ArgumentParser("Transformers CLI tool"    ,							usage="transformers-cli <command> [<args>]"				)
			lowerCAmelCase_						=	parser.add_subparsers(help="transformers-cli command helpers"				)

			# Register commands
			ConvertCommand.register_subcommand(__lowerCAmelCase				)
			DownloadCommand.register_subcommand(__lowerCAmelCase				)
			EnvironmentCommand.register_subcommand(__lowerCAmelCase				)
			RunCommand.register_subcommand(__lowerCAmelCase				)
			ServeCommand.register_subcommand(__lowerCAmelCase				)
			UserCommands.register_subcommand(__lowerCAmelCase				)
			AddNewModelCommand.register_subcommand(__lowerCAmelCase				)
			AddNewModelLikeCommand.register_subcommand(__lowerCAmelCase				)
			LfsCommands.register_subcommand(__lowerCAmelCase				)
			PTtoTFCommand.register_subcommand(__lowerCAmelCase				)

			# Let's go
			lowerCAmelCase_						=	parser.parse_args()

			if not hasattr(__lowerCAmelCase    ,							"func"				):
						parser.print_help()
						exit(1				)

			# Run
			lowerCAmelCase_						=	args.func(__lowerCAmelCase				)
			service.run()


if __name__ == "__main__":
			main()



