
"""simple docstring"""





import inspect
from typing import Callable, List, Optional, Union

import torch
from transformers import CLIPImageProcessor, CLIPTextModel, CLIPTokenizer

from diffusers import DiffusionPipeline
from diffusers.models import AutoencoderKL, UNetaDConditionModel
from diffusers.pipelines.stable_diffusion import StableDiffusionPipelineOutput
from diffusers.pipelines.stable_diffusion.safety_checker import StableDiffusionSafetyChecker
from diffusers.schedulers import DDIMScheduler, LMSDiscreteScheduler, PNDMScheduler
from diffusers.utils import logging


UpperCamelCase_       :    int						      =			logging.get_logger(__name__)  # pylint: disable=invalid-name



class __lowerCAmelCase					(       _lowercase   ):




			"""simple docstring"""







			def __init__(					self    :       List[Any]							, _snake_case    :       AutoencoderKL							, _snake_case    :       CLIPTextModel							, _snake_case    :       CLIPTokenizer							, _snake_case    :       UNetaDConditionModel							, _snake_case    :       Union[DDIMScheduler, PNDMScheduler, LMSDiscreteScheduler]							, _snake_case    :       StableDiffusionSafetyChecker							, _snake_case    :       CLIPImageProcessor							, )   ->			List[Any]:







								"""simple docstring"""
								super().__init__()
								self.register_modules(
								    vae=_snake_case							, text_encoder=_snake_case							, tokenizer=_snake_case							, unet=_snake_case							, scheduler=_snake_case							, safety_checker=_snake_case							, feature_extractor=_snake_case							, )




			def   lowerCamelCase__  (					self    :       Tuple							, _snake_case    :       Optional[Union[str, int]] = "auto"						)   ->			List[str]:







								"""simple docstring"""
								if slice_size == "auto":
													# half the attention head size is usually a good trade-off between
													# speed and memory
													A_								=    self.unet.config.attention_head_dim // 2
								self.unet.set_attention_slice(_snake_case						)




			def   lowerCamelCase__  (					self    :       Any						)   ->			Optional[int]:







								"""simple docstring"""
								self.enable_attention_slicing(_snake_case						)






			@torch.no_grad()
			def __call__(					self    :       Tuple							, _snake_case    :       Union[str, List[str]]							, _snake_case    :       int = 512							, _snake_case    :       int = 512							, _snake_case    :       int = 50							, _snake_case    :       float = 7.5							, _snake_case    :       Optional[Union[str, List[str]]] = None							, _snake_case    :       Optional[int] = 1							, _snake_case    :       float = 0.0							, _snake_case    :       Optional[torch.Generator] = None							, _snake_case    :       Optional[torch.FloatTensor] = None							, _snake_case    :       Optional[str] = "pil"							, _snake_case    :       bool = True							, _snake_case    :       Optional[Callable[[int, int, torch.FloatTensor], None]] = None							, _snake_case    :       int = 1							, _snake_case    :       Optional[torch.FloatTensor] = None							, **_snake_case    :       List[str]							, )   ->			Optional[int]:







								"""simple docstring"""

								if isinstance(_snake_case							, _snake_case						):
													A_								=    1
								elif isinstance(_snake_case							, _snake_case						):
													A_								=    len(_snake_case						)
								else:
													raise ValueError(F'`prompt` has to be of type `str` or `list` but is {type(_snake_case						)}'						)

								if height % 8 != 0 or width % 8 != 0:
													raise ValueError(F'`height` and `width` have to be divisible by 8 but are {height} and {width}.'						)

								if (callback_steps is None) or (
								    callback_steps is not None and (not isinstance(_snake_case							, _snake_case						) or callback_steps <= 0)
								):
													raise ValueError(
													    F'`callback_steps` has to be a positive integer but is {callback_steps} of type'
													    F' {type(_snake_case						)}.'						)

								# get prompt text embeddings
								A_								=    self.tokenizer(
								    _snake_case							, padding="max_length"							, max_length=self.tokenizer.model_max_length							, return_tensors="pt"							, )
								A_								=    text_inputs.input_ids

								if text_input_ids.shape[-1] > self.tokenizer.model_max_length:
													A_								=    self.tokenizer.batch_decode(text_input_ids[:, self.tokenizer.model_max_length :]						)
													logger.warning(
													    "The following part of your input was truncated because CLIP can only handle sequences up to"
													    F' {self.tokenizer.model_max_length} tokens: {removed_text}'						)
													A_								=    text_input_ids[:, : self.tokenizer.model_max_length]

								if text_embeddings is None:
													A_								=    self.text_encoder(text_input_ids.to(self.device						)						)[0]

								# duplicate text embeddings for each generation per prompt, using mps friendly method
								A_			,     A_			,     A_								=    text_embeddings.shape
								A_								=    text_embeddings.repeat(1							, _snake_case							, 1						)
								A_								=    text_embeddings.view(bs_embed * num_images_per_prompt							, _snake_case							, -1						)

								# here `guidance_scale` is defined analog to the guidance weight `w` of equation (2)
								# of the Imagen paper: https://arxiv.org/pdf/2205.11487.pdf . `guidance_scale = 1`
								# corresponds to doing no classifier free guidance.
								A_								=    guidance_scale > 1.0
								# get unconditional embeddings for classifier free guidance
								if do_classifier_free_guidance:
													A_								=    42
													if negative_prompt is None:
																		A_								=    [""]
													elif type(_snake_case						) is not type(_snake_case						):
																		raise TypeError(
																		    F'`negative_prompt` should be the same type to `prompt`, but got {type(_snake_case						)} !='
																		    F' {type(_snake_case						)}.'						)
													elif isinstance(_snake_case							, _snake_case						):
																		A_								=    [negative_prompt]
													elif batch_size != len(_snake_case						):
																		raise ValueError(
																		    F'`negative_prompt`: {negative_prompt} has batch size {len(_snake_case						)}, but `prompt`:'
																		    F' {prompt} has batch size {batch_size}. Please make sure that passed `negative_prompt` matches'
																		    " the batch size of `prompt`."						)
													else:
																		A_								=    negative_prompt

													A_								=    text_input_ids.shape[-1]
													A_								=    self.tokenizer(
													    _snake_case							, padding="max_length"							, max_length=_snake_case							, truncation=_snake_case							, return_tensors="pt"							, )
													A_								=    self.text_encoder(uncond_input.input_ids.to(self.device						)						)[0]

													# duplicate unconditional embeddings for each generation per prompt, using mps friendly method
													A_								=    uncond_embeddings.shape[1]
													A_								=    uncond_embeddings.repeat(_snake_case							, _snake_case							, 1						)
													A_								=    uncond_embeddings.view(batch_size * num_images_per_prompt							, _snake_case							, -1						)

													# For classifier free guidance, we need to do two forward passes.
													# Here we concatenate the unconditional and text embeddings into a single batch
													# to avoid doing two forward passes
													A_								=    torch.cat([uncond_embeddings, text_embeddings]						)

								# get the initial random noise unless the user supplied it

								# Unlike in other pipelines, latents need to be generated in the target device
								# for 1-to-1 results reproducibility with the CompVis implementation.
								# However this currently doesn't work in `mps`.
								A_								=    (batch_size * num_images_per_prompt, self.unet.config.in_channels, height // 8, width // 8)
								A_								=    (batch_size * num_images_per_prompt, self.unet.config.in_channels, 64, 64)
								A_								=    text_embeddings.dtype
								if latents is None:
													if self.device.type == "mps":
																		# randn does not exist on mps
																		A_								=    torch.randn(
																		    _snake_case							, generator=_snake_case							, device="cpu"							, dtype=_snake_case						).to(self.device						)
																		A_								=    torch.randn(_snake_case							, generator=_snake_case							, device="cpu"							, dtype=_snake_case						).to(
																		    self.device						)
													else:
																		A_								=    torch.randn(
																		    _snake_case							, generator=_snake_case							, device=self.device							, dtype=_snake_case						)
																		A_								=    torch.randn(_snake_case							, generator=_snake_case							, device=self.device							, dtype=_snake_case						)
								else:
													if latents_reference.shape != latents_shape:
																		raise ValueError(F'Unexpected latents shape, got {latents.shape}, expected {latents_shape}'						)
													A_								=    latents_reference.to(self.device						)
													A_								=    latents.to(self.device						)

								# This is the key part of the pipeline where we
								# try to ensure that the generated images w/ the same seed
								# but different sizes actually result in similar images
								A_								=    (latents_shape[3] - latents_shape_reference[3]) // 2
								A_								=    (latents_shape[2] - latents_shape_reference[2]) // 2
								A_								=    latents_shape_reference[3] if dx >= 0 else latents_shape_reference[3] + 2 * dx
								A_								=    latents_shape_reference[2] if dy >= 0 else latents_shape_reference[2] + 2 * dy
								A_								=    0 if dx < 0 else dx
								A_								=    0 if dy < 0 else dy
								A_								=    max(-dx							, 0						)
								A_								=    max(-dy							, 0						)
								# import pdb
								# pdb.set_trace()
								A_								=    latents_reference[:, :, dy : dy + h, dx : dx + w]

								# set timesteps
								self.scheduler.set_timesteps(_snake_case						)

								# Some schedulers like PNDM have timesteps as arrays
								# It's more optimized to move all timesteps to correct device beforehand
								A_								=    self.scheduler.timesteps.to(self.device						)

								# scale the initial noise by the standard deviation required by the scheduler
								A_								=    latents * self.scheduler.init_noise_sigma

								# prepare extra kwargs for the scheduler step, since not all schedulers have the same signature
								# eta (η) is only used with the DDIMScheduler, it will be ignored for other schedulers.
								# eta corresponds to η in DDIM paper: https://arxiv.org/abs/2010.02502
								# and should be between [0, 1]
								A_								=    "eta" in set(inspect.signature(self.scheduler.step						).parameters.keys()						)
								A_								=    {}
								if accepts_eta:
													A_								=    eta

								for i, t in enumerate(self.progress_bar(_snake_case						)						):
													# expand the latents if we are doing classifier free guidance
													A_								=    torch.cat([latents] * 2						) if do_classifier_free_guidance else latents
													A_								=    self.scheduler.scale_model_input(_snake_case							, _snake_case						)

													# predict the noise residual
													A_								=    self.unet(_snake_case							, _snake_case							, encoder_hidden_states=_snake_case						).sample

													# perform guidance
													if do_classifier_free_guidance:
																		A_			,     A_								=    noise_pred.chunk(2						)
																		A_								=    noise_pred_uncond + guidance_scale * (noise_pred_text - noise_pred_uncond)

													# compute the previous noisy sample x_t -> x_t-1
													A_								=    self.scheduler.step(_snake_case							, _snake_case							, _snake_case							, **_snake_case						).prev_sample

													# call the callback, if provided
													if callback is not None and i % callback_steps == 0:
																		callback(_snake_case							, _snake_case							, _snake_case						)

								A_								=    1 / 0.1_8_2_1_5 * latents
								A_								=    self.vae.decode(_snake_case						).sample

								A_								=    (image / 2 + 0.5).clamp(0							, 1						)

								# we always cast to float32 as this does not cause significant overhead and is compatible with bfloat16
								A_								=    image.cpu().permute(0							, 2							, 3							, 1						).float().numpy()

								if self.safety_checker is not None:
													A_								=    self.feature_extractor(self.numpy_to_pil(_snake_case						)							, return_tensors="pt"						).to(
													    self.device						)
													A_			,     A_								=    self.safety_checker(
													    images=_snake_case							, clip_input=safety_checker_input.pixel_values.to(text_embeddings.dtype						)						)
								else:
													A_								=    None

								if output_type == "pil":
													A_								=    self.numpy_to_pil(_snake_case						)

								if not return_dict:
													return (image, has_nsfw_concept)

								return StableDiffusionPipelineOutput(images=_snake_case							, nsfw_content_detected=_snake_case						)






"""simple docstring"""





import shutil
import tempfile
import unittest
from unittest.mock import patch

from transformers import (
    DefaultFlowCallback,
    IntervalStrategy,
    PrinterCallback,
    ProgressCallback,
    Trainer,
    TrainerCallback,
    TrainingArguments,
    is_torch_available,
)
from transformers.testing_utils import require_torch


if is_torch_available():
		from transformers.trainer import DEFAULT_CALLBACKS

		from .test_trainer import RegressionDataset, RegressionModelConfig, RegressionPreTrainedModel



class __lowerCAmelCase					(       _lowercase   ):




			"""simple docstring"""







			def __init__(					self    :       Optional[int]						)   ->			str:







								"""simple docstring"""
								A_								=    []




			def   lowerCamelCase__  (					self    :       Tuple							, _snake_case    :       List[str]							, _snake_case    :       Optional[int]							, _snake_case    :       Optional[int]							, **_snake_case    :       str						)   ->			int:







								"""simple docstring"""
								self.events.append("on_init_end"						)




			def   lowerCamelCase__  (					self    :       Dict							, _snake_case    :       Union[str, Any]							, _snake_case    :       List[Any]							, _snake_case    :       Tuple							, **_snake_case    :       Tuple						)   ->			List[str]:







								"""simple docstring"""
								self.events.append("on_train_begin"						)




			def   lowerCamelCase__  (					self    :       List[Any]							, _snake_case    :       Any							, _snake_case    :       Optional[Any]							, _snake_case    :       Tuple							, **_snake_case    :       Optional[int]						)   ->			str:







								"""simple docstring"""
								self.events.append("on_train_end"						)




			def   lowerCamelCase__  (					self    :       Dict							, _snake_case    :       str							, _snake_case    :       List[Any]							, _snake_case    :       str							, **_snake_case    :       Optional[int]						)   ->			Dict:







								"""simple docstring"""
								self.events.append("on_epoch_begin"						)




			def   lowerCamelCase__  (					self    :       Optional[int]							, _snake_case    :       Optional[int]							, _snake_case    :       Any							, _snake_case    :       Optional[Any]							, **_snake_case    :       Optional[Any]						)   ->			str:







								"""simple docstring"""
								self.events.append("on_epoch_end"						)




			def   lowerCamelCase__  (					self    :       List[Any]							, _snake_case    :       List[str]							, _snake_case    :       str							, _snake_case    :       Optional[Any]							, **_snake_case    :       Optional[int]						)   ->			List[str]:







								"""simple docstring"""
								self.events.append("on_step_begin"						)




			def   lowerCamelCase__  (					self    :       Optional[Any]							, _snake_case    :       Union[str, Any]							, _snake_case    :       Optional[Any]							, _snake_case    :       Any							, **_snake_case    :       Union[str, Any]						)   ->			List[str]:







								"""simple docstring"""
								self.events.append("on_step_end"						)




			def   lowerCamelCase__  (					self    :       Tuple							, _snake_case    :       Dict							, _snake_case    :       Dict							, _snake_case    :       Union[str, Any]							, **_snake_case    :       List[str]						)   ->			Optional[int]:







								"""simple docstring"""
								self.events.append("on_evaluate"						)




			def   lowerCamelCase__  (					self    :       Optional[int]							, _snake_case    :       Optional[Any]							, _snake_case    :       int							, _snake_case    :       int							, **_snake_case    :       List[Any]						)   ->			List[str]:







								"""simple docstring"""
								self.events.append("on_predict"						)




			def   lowerCamelCase__  (					self    :       List[str]							, _snake_case    :       Union[str, Any]							, _snake_case    :       List[str]							, _snake_case    :       Optional[Any]							, **_snake_case    :       List[Any]						)   ->			Union[str, Any]:







								"""simple docstring"""
								self.events.append("on_save"						)




			def   lowerCamelCase__  (					self    :       Dict							, _snake_case    :       Dict							, _snake_case    :       List[Any]							, _snake_case    :       Optional[int]							, **_snake_case    :       Dict						)   ->			str:







								"""simple docstring"""
								self.events.append("on_log"						)






			def   lowerCamelCase__  (					self    :       Tuple							, _snake_case    :       Optional[Any]							, _snake_case    :       str							, _snake_case    :       int							, **_snake_case    :       List[Any]						)   ->			int:







								"""simple docstring"""
								self.events.append("on_prediction_step"						)





@require_torch
class __lowerCAmelCase					(       unittest.TestCase   ):




			"""simple docstring"""







			def   lowerCamelCase__  (					self    :       Union[str, Any]						)   ->			Dict:







								"""simple docstring"""
								A_								=    tempfile.mkdtemp()




			def   lowerCamelCase__  (					self    :       str						)   ->			Tuple:







								"""simple docstring"""
								shutil.rmtree(self.output_dir						)




			def   lowerCamelCase__  (					self    :       List[str]							, _snake_case    :       Any=0							, _snake_case    :       Optional[int]=0							, _snake_case    :       int=64							, _snake_case    :       Optional[int]=64							, _snake_case    :       List[Any]=None							, _snake_case    :       List[Any]=False							, **_snake_case    :       Optional[int]						)   ->			List[Any]:







								"""simple docstring"""
								# disable_tqdm in TrainingArguments has a flaky default since it depends on the level of logging. We make sure
								# its set to False since the tests later on depend on its value.
								A_								=    RegressionDataset(length=_snake_case						)
								A_								=    RegressionDataset(length=_snake_case						)
								A_								=    RegressionModelConfig(a=_snake_case							, b=_snake_case						)
								A_								=    RegressionPreTrainedModel(_snake_case						)

								A_								=    TrainingArguments(self.output_dir							, disable_tqdm=_snake_case							, report_to=[]							, **_snake_case						)
								return Trainer(
								    _snake_case							, _snake_case							, train_dataset=_snake_case							, eval_dataset=_snake_case							, callbacks=_snake_case							, )




			def   lowerCamelCase__  (					self    :       List[Any]							, _snake_case    :       Optional[Any]							, _snake_case    :       List[Any]						)   ->			Union[str, Any]:







								"""simple docstring"""
								self.assertEqual(len(_snake_case						)							, len(_snake_case						)						)

								# Order doesn't matter
								A_								=    sorted(_snake_case							, key=lambda _snake_case						: cb.__name__ if isinstance(_snake_case							, _snake_case						) else cb.__class__.__name__						)
								A_								=    sorted(_snake_case							, key=lambda _snake_case						: cb.__name__ if isinstance(_snake_case							, _snake_case						) else cb.__class__.__name__						)

								for cba, cba in zip(_snake_case							, _snake_case						):
													if isinstance(_snake_case							, _snake_case						) and isinstance(_snake_case							, _snake_case						):
																		self.assertEqual(_snake_case							, _snake_case						)
													elif isinstance(_snake_case							, _snake_case						) and not isinstance(_snake_case							, _snake_case						):
																		self.assertEqual(_snake_case							, cba.__class__						)
													elif not isinstance(_snake_case							, _snake_case						) and isinstance(_snake_case							, _snake_case						):
																		self.assertEqual(cba.__class__							, _snake_case						)
													else:
																		self.assertEqual(_snake_case							, _snake_case						)




			def   lowerCamelCase__  (					self    :       List[Any]							, _snake_case    :       Union[str, Any]						)   ->			Optional[Any]:







								"""simple docstring"""
								A_								=    ["on_init_end", "on_train_begin"]
								A_								=    0
								A_								=    len(trainer.get_eval_dataloader()						)
								A_								=    ["on_prediction_step"] * len(trainer.get_eval_dataloader()						) + ["on_log", "on_evaluate"]
								for _ in range(trainer.state.num_train_epochs						):
													expected_events.append("on_epoch_begin"						)
													for _ in range(_snake_case						):
																		step += 1
																		expected_events += ["on_step_begin", "on_step_end"]
																		if step % trainer.args.logging_steps == 0:
																							expected_events.append("on_log"						)
																		if trainer.args.evaluation_strategy == IntervalStrategy.STEPS and step % trainer.args.eval_steps == 0:
																							expected_events += evaluation_events.copy()
																		if step % trainer.args.save_steps == 0:
																							expected_events.append("on_save"						)
													expected_events.append("on_epoch_end"						)
													if trainer.args.evaluation_strategy == IntervalStrategy.EPOCH:
																		expected_events += evaluation_events.copy()
								expected_events += ["on_log", "on_train_end"]
								return expected_events




			def   lowerCamelCase__  (					self    :       List[Any]						)   ->			int:







								"""simple docstring"""
								A_								=    self.get_trainer()
								A_								=    DEFAULT_CALLBACKS.copy() + [ProgressCallback]
								self.check_callbacks_equality(trainer.callback_handler.callbacks							, _snake_case						)

								# Callbacks passed at init are added to the default callbacks
								A_								=    self.get_trainer(callbacks=[MyTestTrainerCallback]						)
								expected_callbacks.append(_snake_case						)
								self.check_callbacks_equality(trainer.callback_handler.callbacks							, _snake_case						)

								# TrainingArguments.disable_tqdm controls if use ProgressCallback or PrinterCallback
								A_								=    self.get_trainer(disable_tqdm=_snake_case						)
								A_								=    DEFAULT_CALLBACKS.copy() + [PrinterCallback]
								self.check_callbacks_equality(trainer.callback_handler.callbacks							, _snake_case						)




			def   lowerCamelCase__  (					self    :       Optional[Any]						)   ->			List[Any]:







								"""simple docstring"""
								A_								=    DEFAULT_CALLBACKS.copy() + [ProgressCallback]
								A_								=    self.get_trainer()

								# We can add, pop, or remove by class name
								trainer.remove_callback(_snake_case						)
								expected_callbacks.remove(_snake_case						)
								self.check_callbacks_equality(trainer.callback_handler.callbacks							, _snake_case						)

								A_								=    self.get_trainer()
								A_								=    trainer.pop_callback(_snake_case						)
								self.assertEqual(cb.__class__							, _snake_case						)
								self.check_callbacks_equality(trainer.callback_handler.callbacks							, _snake_case						)

								trainer.add_callback(_snake_case						)
								expected_callbacks.insert(0							, _snake_case						)
								self.check_callbacks_equality(trainer.callback_handler.callbacks							, _snake_case						)

								# We can also add, pop, or remove by instance
								A_								=    self.get_trainer()
								A_								=    trainer.callback_handler.callbacks[0]
								trainer.remove_callback(_snake_case						)
								expected_callbacks.remove(_snake_case						)
								self.check_callbacks_equality(trainer.callback_handler.callbacks							, _snake_case						)

								A_								=    self.get_trainer()
								A_								=    trainer.callback_handler.callbacks[0]
								A_								=    trainer.pop_callback(_snake_case						)
								self.assertEqual(_snake_case							, _snake_case						)
								self.check_callbacks_equality(trainer.callback_handler.callbacks							, _snake_case						)

								trainer.add_callback(_snake_case						)
								expected_callbacks.insert(0							, _snake_case						)
								self.check_callbacks_equality(trainer.callback_handler.callbacks							, _snake_case						)






			def   lowerCamelCase__  (					self    :       Union[str, Any]						)   ->			Union[str, Any]:







								"""simple docstring"""
								import warnings

								# XXX: for now ignore scatter_gather warnings in this test since it's not relevant to what's being tested
								warnings.simplefilter(action="ignore"							, category=_snake_case						)

								A_								=    self.get_trainer(callbacks=[MyTestTrainerCallback]						)
								trainer.train()
								A_								=    trainer.callback_handler.callbacks[-2].events
								self.assertEqual(_snake_case							, self.get_expected_events(_snake_case						)						)

								# Independent log/save/eval
								A_								=    self.get_trainer(callbacks=[MyTestTrainerCallback]							, logging_steps=5						)
								trainer.train()
								A_								=    trainer.callback_handler.callbacks[-2].events
								self.assertEqual(_snake_case							, self.get_expected_events(_snake_case						)						)

								A_								=    self.get_trainer(callbacks=[MyTestTrainerCallback]							, save_steps=5						)
								trainer.train()
								A_								=    trainer.callback_handler.callbacks[-2].events
								self.assertEqual(_snake_case							, self.get_expected_events(_snake_case						)						)

								A_								=    self.get_trainer(callbacks=[MyTestTrainerCallback]							, eval_steps=5							, evaluation_strategy="steps"						)
								trainer.train()
								A_								=    trainer.callback_handler.callbacks[-2].events
								self.assertEqual(_snake_case							, self.get_expected_events(_snake_case						)						)

								A_								=    self.get_trainer(callbacks=[MyTestTrainerCallback]							, evaluation_strategy="epoch"						)
								trainer.train()
								A_								=    trainer.callback_handler.callbacks[-2].events
								self.assertEqual(_snake_case							, self.get_expected_events(_snake_case						)						)

								# A bit of everything
								A_								=    self.get_trainer(
								    callbacks=[MyTestTrainerCallback]							, logging_steps=3							, save_steps=10							, eval_steps=5							, evaluation_strategy="steps"							, )
								trainer.train()
								A_								=    trainer.callback_handler.callbacks[-2].events
								self.assertEqual(_snake_case							, self.get_expected_events(_snake_case						)						)

								# warning should be emitted for duplicated callbacks
								with patch("transformers.trainer_callback.logger.warning"						) as warn_mock:
													A_								=    self.get_trainer(
													    callbacks=[MyTestTrainerCallback, MyTestTrainerCallback]							, )
													assert str(_snake_case						) in warn_mock.call_args[0][0]




