
"""simple docstring"""

import collections

from .utils import ExplicitEnum, is_torch_available, logging


if is_torch_available():
					import torch


_A				=					logging.get_logger(__name__)






class 			_lowercase  :




	def __init__(					self						,					UpperCAmelCase_						,					UpperCAmelCase_=21						,					UpperCAmelCase_=[]						,					UpperCAmelCase_=None   )						->				Union[str, Any]:
			lowerCamelCase	:     Optional[Any]            =       model
			lowerCamelCase	:     List[Any]            =       trace_batch_nums
			lowerCamelCase	:     Any            =       abort_after_batch_num

			# keep a LIFO buffer of frames to dump as soon as inf/nan is encountered to give context to the problem emergence
			lowerCamelCase	:     List[Any]            =       collections.deque([]						,					UpperCAmelCase_   )
			lowerCamelCase	:     Tuple            =       []
			lowerCamelCase	:     Optional[int]            =       0
			lowerCamelCase	:     Dict            =       0
			lowerCamelCase	:     Dict            =       False
			lowerCamelCase	:     int            =       '                 '

			self.analyse_model()

			self.register_forward_hook()




	def      _UpperCamelCase       (					self						,					UpperCAmelCase_=None   )						->				List[Any]:
			if frame is not None:
					self.expand_frame(UpperCAmelCase_   )
			self.frames.append('\n'.join(self.frame   )   )
			lowerCamelCase	:     str            =       []  # start a new frame




	def      _UpperCamelCase       (					self						,					UpperCAmelCase_   )						->				Dict:
			self.frame.append(UpperCAmelCase_   )




	def      _UpperCamelCase       (					self   )						->				str:
			print('\n'.join(self.frames   )   )
			lowerCamelCase	:     Dict            =       []




	def      _UpperCamelCase       (					self   )						->				Union[str, Any]:
			lowerCamelCase	:     Union[str, Any]            =       []




	def      _UpperCamelCase       (					self   )						->				str:
			print(F"""\nDetected inf/nan during batch_number={self.batch_number}"""   )
			print(F"""Last {len(self.frames   )} forward frames:"""   )
			print(F"""{'abs min':8} {'abs max':8} metadata"""   )
			print('\n'.join(self.frames   )   )
			print('\n\n'   )
			lowerCamelCase	:     List[str]            =       []




	def      _UpperCamelCase       (					self   )						->				Dict:
			# extract the fully qualified module names, to be able to report at run time. e.g.:
			# encoder.block.2.layer.0.SelfAttention.o
			#
			# for shared weights only the first shared module name will be registered
			lowerCamelCase	:     Optional[int]            =       {m: name for name, m in self.model.named_modules()}
			# self.longest_module_name = max(len(v) for v in self.module_names.values())




	def      _UpperCamelCase       (					self						,					UpperCAmelCase_						,					UpperCAmelCase_   )						->				str:
			if torch.is_tensor(UpperCAmelCase_   ):
					self.expand_frame(get_abs_min_max(UpperCAmelCase_						,					UpperCAmelCase_   )   )
					if detect_overflow(UpperCAmelCase_						,					UpperCAmelCase_   ):
							lowerCamelCase	:     Optional[int]            =       True
			elif var is None:
					self.expand_frame(F"""{'None':>17} {ctx}"""   )
			else:
					self.expand_frame(F"""{'not a tensor':>17} {ctx}"""   )




	def      _UpperCamelCase       (					self   )						->				Optional[Any]:
			self.expand_frame(F"""\n\n{self.prefix} *** Starting batch number={self.batch_number} ***"""   )
			self.expand_frame(F"""{'abs min':8} {'abs max':8} metadata"""   )




	def      _UpperCamelCase       (					self   )						->				List[Any]:
			self.expand_frame(F"""{self.prefix} *** Finished batch number={self.batch_number-1} ***\n\n"""   )




	def      _UpperCamelCase       (					self						,					UpperCAmelCase_						,					UpperCAmelCase_						,					UpperCAmelCase_   )						->				int:
			self.expand_frame(F"""{self.prefix} {self.module_names[module]} {module.__class__.__name__}"""   )

			# params
			for name, p in module.named_parameters(recurse=UpperCAmelCase_   ):
					self.analyse_variable(UpperCAmelCase_						,					UpperCAmelCase_   )

			# inputs
			if isinstance(UpperCAmelCase_						,					UpperCAmelCase_   ):
					for i, x in enumerate(UpperCAmelCase_   ):
							self.analyse_variable(UpperCAmelCase_						,					F"""input[{i}]"""   )
			else:
					self.analyse_variable(UpperCAmelCase_						,					'input'   )

			# outputs
			if isinstance(UpperCAmelCase_						,					UpperCAmelCase_   ):
					for i, x in enumerate(UpperCAmelCase_   ):
							# possibly a tuple of tuples
							if isinstance(UpperCAmelCase_						,					UpperCAmelCase_   ):
									for j, y in enumerate(UpperCAmelCase_   ):
											self.analyse_variable(UpperCAmelCase_						,					F"""output[{i}][{j}]"""   )
							else:
									self.analyse_variable(UpperCAmelCase_						,					F"""output[{i}]"""   )
			else:
					self.analyse_variable(UpperCAmelCase_						,					'output'   )

			self.save_frame()




	def      _UpperCamelCase       (					self   )						->				str:
			self.model.apply(self._register_forward_hook   )




	def      _UpperCamelCase       (					self						,					UpperCAmelCase_   )						->				Optional[Any]:
			module.register_forward_hook(self.forward_hook   )




	def      _UpperCamelCase       (					self						,					UpperCAmelCase_						,					UpperCAmelCase_						,					UpperCAmelCase_   )						->				Optional[int]:
			# - input is a tuple of packed inputs (could be non-Tensors)
			# - output could be a Tensor or a tuple of Tensors and non-Tensors

			lowerCamelCase	:     Dict            =       False

			lowerCamelCase	:     Any            =       True if self.batch_number in self.trace_batch_nums else False
			if trace_mode:
					self.reset_saved_frames()

			if self.total_calls == 0:
					self.batch_start_frame()
			self.total_calls += 1

			# count batch numbers - the very first forward hook of the batch will be called when the
			# batch completes - i.e. it gets called very last - we know this batch has finished
			if module == self.model:
					self.batch_number += 1
					lowerCamelCase	:     Tuple            =       True

			self.create_frame(UpperCAmelCase_						,					UpperCAmelCase_						,					UpperCAmelCase_   )

			# if last_frame_of_batch:
			#     self.batch_end_frame()

			if trace_mode:
					self.trace_frames()

			if last_frame_of_batch:
					self.batch_start_frame()

			if self.detected_overflow and not trace_mode:
					self.dump_saved_frames()

					# now we can abort, as it's pointless to continue running
					raise ValueError(
					    'DebugUnderflowOverflow: inf/nan detected, aborting as there is no point running further. '
					    'Please scroll up above this traceback to see the activation values prior to this event.'   )

			# abort after certain batch if requested to do so
			if self.abort_after_batch_num is not None and self.batch_number > self.abort_after_batch_num:
					raise ValueError(
					    F"""DebugUnderflowOverflow: aborting after {self.batch_number} batches due to"""
					    F""" `abort_after_batch_num={self.abort_after_batch_num}` arg"""   )


def 						UpperCAmelCase   (						a_,		a_     ):





		'''simple docstring'''


		lowerCamelCase	:     Optional[Any]            =       var.abs()
		return F"""{abs_var.min():8.2e} {abs_var.max():8.2e} {ctx}"""
def 						UpperCAmelCase   (						a_,		a_     ):





		'''simple docstring'''


		lowerCamelCase	:     List[Any]            =       False
		if torch.isnan(_snake_case     ).any().item():
				lowerCamelCase	:     Union[str, Any]            =       True
				print(F"""{ctx} has nans"""     )
		if torch.isinf(_snake_case     ).any().item():
				lowerCamelCase	:     Dict            =       True
				print(F"""{ctx} has infs"""     )

		# if needed to monitor large elements can enable the following
		if 0:  # and detected:
				lowerCamelCase	:     List[str]            =       var[torch.ge(var.abs(),		100     )]
				if naaa.numel() > 0:
						print(F"""{ctx}:  n100={naaa.numel()}"""     )
				lowerCamelCase	:     int            =       var[torch.ge(var.abs(),		1000     )]
				if naaaa.numel() > 0:
						print(F"""{ctx}: n1000={naaaa.numel()}"""     )
				lowerCamelCase	:     Dict            =       var[torch.ge(var.abs(),		1_0000     )]
				if naaaaa.numel() > 0:
						print(F"""{ctx}: n10000={naaaaa.numel()}"""     )

		if 0:
				print(F"""min={var.min():9.2e} max={var.max():9.2e}"""     )

		if 0:
				print(F"""min={var.min():9.2e} max={var.max():9.2e} var={var.var():9.2e} mean={var.mean():9.2e} ({ctx})"""     )

		return detected






class 			_lowercase  (							__UpperCAmelCase						):
	lowercase_								=      """underflow_overflow"""
	lowercase_								=      """tpu_metrics_debug"""












from __future__ import annotations

import inspect
import unittest
from typing import List, Tuple

from transformers import ConvNextConfig
from transformers.testing_utils import require_tf, require_vision, slow
from transformers.utils import cached_property, is_tf_available, is_vision_available

from ...test_configuration_common import ConfigTester
from ...test_modeling_tf_common import TFModelTesterMixin, floats_tensor, ids_tensor
from ...test_pipeline_mixin import PipelineTesterMixin


if is_tf_available():
		import tensorflow as tf

		from transformers import TFConvNextForImageClassification, TFConvNextModel


if is_vision_available():
		from PIL import Image

		from transformers import ConvNextImageProcessor


class 				__UpperCamelCase      :





				'''simple docstring'''



				def __init__(			self							,			UpperCAmelCase_							,			UpperCAmelCase_=13							,			UpperCAmelCase_=32							,			UpperCAmelCase_=3							,			UpperCAmelCase_=4							,			UpperCAmelCase_=[10, 20, 30, 40]							,			UpperCAmelCase_=[2, 2, 3, 2]							,			UpperCAmelCase_=True							,			UpperCAmelCase_=True							,			UpperCAmelCase_=37							,			UpperCAmelCase_="gelu"							,			UpperCAmelCase_=10							,			UpperCAmelCase_=0.02							,			UpperCAmelCase_=3							,			UpperCAmelCase_=None							,			):
											lowerCAmelCase =		parent
											lowerCAmelCase =		batch_size
											lowerCAmelCase =		image_size
											lowerCAmelCase =		num_channels
											lowerCAmelCase =		num_stages
											lowerCAmelCase =		hidden_sizes
											lowerCAmelCase =		depths
											lowerCAmelCase =		is_training
											lowerCAmelCase =		use_labels
											lowerCAmelCase =		intermediate_size
											lowerCAmelCase =		hidden_act
											lowerCAmelCase =		type_sequence_label_size
											lowerCAmelCase =		initializer_range
											lowerCAmelCase =		scope



				def    __snake_case		(			self    ):
											lowerCAmelCase =		floats_tensor([self.batch_size, self.num_channels, self.image_size, self.image_size]    )

											lowerCAmelCase =		None
											if self.use_labels:
																		lowerCAmelCase =		ids_tensor([self.batch_size]							,			self.type_sequence_label_size    )

											lowerCAmelCase =		self.get_config()

											return config, pixel_values, labels



				def    __snake_case		(			self    ):
											return ConvNextConfig(
											    num_channels=self.num_channels							,			hidden_sizes=self.hidden_sizes							,			depths=self.depths							,			num_stages=self.num_stages							,			hidden_act=self.hidden_act							,			is_decoder=UpperCAmelCase_							,			initializer_range=self.initializer_range							,			)



				def    __snake_case		(			self							,			UpperCAmelCase_							,			UpperCAmelCase_							,			UpperCAmelCase_    ):
											lowerCAmelCase =		TFConvNextModel(config=UpperCAmelCase_    )
											lowerCAmelCase =		model(UpperCAmelCase_							,			training=UpperCAmelCase_    )
											# expected last hidden states: B, C, H // 32, W // 32
											self.parent.assertEqual(
											    result.last_hidden_state.shape							,			(self.batch_size, self.hidden_sizes[-1], self.image_size // 32, self.image_size // 32)							,			)



				def    __snake_case		(			self							,			UpperCAmelCase_							,			UpperCAmelCase_							,			UpperCAmelCase_    ):
											lowerCAmelCase =		self.type_sequence_label_size
											lowerCAmelCase =		TFConvNextForImageClassification(UpperCAmelCase_    )
											lowerCAmelCase =		model(UpperCAmelCase_							,			labels=UpperCAmelCase_							,			training=UpperCAmelCase_    )
											self.parent.assertEqual(result.logits.shape							,			(self.batch_size, self.type_sequence_label_size)    )






				def    __snake_case		(			self    ):
											lowerCAmelCase =		self.prepare_config_and_inputs()
											lowerCAmelCase ,  lowerCAmelCase ,  lowerCAmelCase =		config_and_inputs
											lowerCAmelCase =		{'''pixel_values''': pixel_values}
											return config, inputs_dict




@require_tf
class 				__UpperCamelCase      (			__UpperCAmelCase  ,       __UpperCAmelCase  ,       unittest.TestCase	):





				'''simple docstring'''



				__a				:			Union[str, Any]					    =(TFConvNextModel, TFConvNextForImageClassification) if is_tf_available() else ()
				__a				:			Optional[int]					    =(
				    {"""feature-extraction""": TFConvNextModel, """image-classification""": TFConvNextForImageClassification}
				    if is_tf_available()
				    else {}
				)

				__a				:			Any					    =False
				__a				:			int					    =False
				__a				:			Union[str, Any]					    =False
				__a				:			Optional[Any]					    =False
				__a				:			List[Any]					    =False



				def    __snake_case		(			self    ):
											lowerCAmelCase =		TFConvNextModelTester(self    )
											lowerCAmelCase =		ConfigTester(
											    self							,			config_class=UpperCAmelCase_							,			has_text_modality=UpperCAmelCase_							,			hidden_size=37							,			)



				@unittest.skip(reason='''ConvNext does not use inputs_embeds'''    )
				def    __snake_case		(			self    ):
											pass



				@unittest.skipIf(
				    not is_tf_available() or len(tf.config.list_physical_devices('''GPU'''    )    ) == 0							,			reason='''TF does not support backprop for grouped convolutions on CPU.'''							,			)
				@slow
				def    __snake_case		(			self    ):
											super().test_keras_fit()



				@unittest.skip(reason='''ConvNext does not support input and output embeddings'''    )
				def    __snake_case		(			self    ):
											pass



				def    __snake_case		(			self    ):
											lowerCAmelCase ,  lowerCAmelCase =		self.model_tester.prepare_config_and_inputs_for_common()

											for model_class in self.all_model_classes:
																		lowerCAmelCase =		model_class(UpperCAmelCase_    )
																		lowerCAmelCase =		inspect.signature(model.call    )
																		# signature.parameters is an OrderedDict => so arg_names order is deterministic
																		lowerCAmelCase =		[*signature.parameters.keys()]

																		lowerCAmelCase =		['''pixel_values''']
																		self.assertListEqual(arg_names[:1]							,			UpperCAmelCase_    )



				def    __snake_case		(			self    ):
											lowerCAmelCase =		self.model_tester.prepare_config_and_inputs()
											self.model_tester.create_and_check_model(*UpperCAmelCase_    )



				@unittest.skipIf(
				    not is_tf_available() or len(tf.config.list_physical_devices('''GPU'''    )    ) == 0							,			reason='''TF does not support backprop for grouped convolutions on CPU.'''							,			)
				def    __snake_case		(			self    ):
											super().test_dataset_conversion()



				def    __snake_case		(			self    ):
											def check_hidden_states_output(UpperCAmelCase_							,			UpperCAmelCase_							,			UpperCAmelCase_    ):
																		lowerCAmelCase =		model_class(UpperCAmelCase_    )

																		lowerCAmelCase =		model(**self._prepare_for_class(UpperCAmelCase_							,			UpperCAmelCase_    )    )
																		lowerCAmelCase =		outputs.encoder_hidden_states if config.is_encoder_decoder else outputs.hidden_states

																		lowerCAmelCase =		self.model_tester.num_stages
																		self.assertEqual(len(UpperCAmelCase_    )							,			expected_num_stages + 1    )

																		# ConvNext's feature maps are of shape (batch_size, num_channels, height, width)
																		self.assertListEqual(
																		    list(hidden_states[0].shape[-2:]    )							,			[self.model_tester.image_size // 4, self.model_tester.image_size // 4]							,			)

											lowerCAmelCase ,  lowerCAmelCase =		self.model_tester.prepare_config_and_inputs_for_common()

											for model_class in self.all_model_classes:
																		lowerCAmelCase =		True
																		check_hidden_states_output(UpperCAmelCase_							,			UpperCAmelCase_							,			UpperCAmelCase_    )

																		# check that output_hidden_states also work using config
																		del inputs_dict["output_hidden_states"]
																		lowerCAmelCase =		True

																		check_hidden_states_output(UpperCAmelCase_							,			UpperCAmelCase_							,			UpperCAmelCase_    )



				def    __snake_case		(			self    ):
											lowerCAmelCase ,  lowerCAmelCase =		self.model_tester.prepare_config_and_inputs_for_common()

											def check_equivalence(UpperCAmelCase_							,			UpperCAmelCase_							,			UpperCAmelCase_							,			UpperCAmelCase_={}    ):
																		lowerCAmelCase =		model(UpperCAmelCase_							,			return_dict=UpperCAmelCase_							,			**UpperCAmelCase_    )
																		lowerCAmelCase =		model(UpperCAmelCase_							,			return_dict=UpperCAmelCase_							,			**UpperCAmelCase_    ).to_tuple()

																		def recursive_check(UpperCAmelCase_							,			UpperCAmelCase_    ):
																									if isinstance(UpperCAmelCase_							,			(List, Tuple)    ):
																																for tuple_iterable_value, dict_iterable_value in zip(UpperCAmelCase_							,			UpperCAmelCase_    ):
																																							recursive_check(UpperCAmelCase_							,			UpperCAmelCase_    )
																									elif tuple_object is None:
																																return
																									else:
																																self.assertTrue(
																																    all(tf.equal(UpperCAmelCase_							,			UpperCAmelCase_    )    )							,			msg=(
																																        '''Tuple and dict output are not equal. Difference:'''
																																        F""" {tf.math.reduce_max(tf.abs(tuple_object - dict_object    )    )}"""
																																    )							,			)

																									recursive_check(UpperCAmelCase_							,			UpperCAmelCase_    )

											for model_class in self.all_model_classes:
																		lowerCAmelCase =		model_class(UpperCAmelCase_    )

																		lowerCAmelCase =		self._prepare_for_class(UpperCAmelCase_							,			UpperCAmelCase_    )
																		lowerCAmelCase =		self._prepare_for_class(UpperCAmelCase_							,			UpperCAmelCase_    )
																		check_equivalence(UpperCAmelCase_							,			UpperCAmelCase_							,			UpperCAmelCase_    )

																		lowerCAmelCase =		self._prepare_for_class(UpperCAmelCase_							,			UpperCAmelCase_							,			return_labels=UpperCAmelCase_    )
																		lowerCAmelCase =		self._prepare_for_class(UpperCAmelCase_							,			UpperCAmelCase_							,			return_labels=UpperCAmelCase_    )
																		check_equivalence(UpperCAmelCase_							,			UpperCAmelCase_							,			UpperCAmelCase_    )

																		lowerCAmelCase =		self._prepare_for_class(UpperCAmelCase_							,			UpperCAmelCase_    )
																		lowerCAmelCase =		self._prepare_for_class(UpperCAmelCase_							,			UpperCAmelCase_    )
																		check_equivalence(UpperCAmelCase_							,			UpperCAmelCase_							,			UpperCAmelCase_							,			{'''output_hidden_states''': True}    )

																		lowerCAmelCase =		self._prepare_for_class(UpperCAmelCase_							,			UpperCAmelCase_							,			return_labels=UpperCAmelCase_    )
																		lowerCAmelCase =		self._prepare_for_class(UpperCAmelCase_							,			UpperCAmelCase_							,			return_labels=UpperCAmelCase_    )
																		check_equivalence(UpperCAmelCase_							,			UpperCAmelCase_							,			UpperCAmelCase_							,			{'''output_hidden_states''': True}    )



				def    __snake_case		(			self    ):
											lowerCAmelCase =		self.model_tester.prepare_config_and_inputs()
											self.model_tester.create_and_check_for_image_classification(*UpperCAmelCase_    )






				@slow
				def    __snake_case		(			self    ):
											lowerCAmelCase =		TFConvNextModel.from_pretrained('''facebook/convnext-tiny-224'''    )
											self.assertIsNotNone(UpperCAmelCase_    )




def    UpperCAmelCase							(  ):
							lowerCAmelCase =		Image.open('''./tests/fixtures/tests_samples/COCO/000000039769.png'''				)
							return image


@require_tf
@require_vision
class 				__UpperCamelCase      (			unittest.TestCase	):





				'''simple docstring'''



				@cached_property
				def    __snake_case		(			self    ):
											return ConvNextImageProcessor.from_pretrained('''facebook/convnext-tiny-224'''    ) if is_vision_available() else None






				@slow
				def    __snake_case		(			self    ):
											lowerCAmelCase =		TFConvNextForImageClassification.from_pretrained('''facebook/convnext-tiny-224'''    )

											lowerCAmelCase =		self.default_image_processor
											lowerCAmelCase =		prepare_img()
											lowerCAmelCase =		image_processor(images=UpperCAmelCase_							,			return_tensors='''tf'''    )

											# forward pass
											lowerCAmelCase =		model(**UpperCAmelCase_    )

											# verify the logits
											lowerCAmelCase =		tf.TensorShape((1, 10_00)    )
											self.assertEqual(outputs.logits.shape							,			UpperCAmelCase_    )

											lowerCAmelCase =		tf.constant([-0.0260, -0.4739, 0.1911]    )

											tf.debugging.assert_near(outputs.logits[0, :3]							,			UpperCAmelCase_							,			atol=1E-4    )



