




import importlib.metadata
import warnings
from copy import deepcopy

from packaging import version

from ..utils import logging
from .import_utils import is_accelerate_available, is_bitsandbytes_available


if is_bitsandbytes_available():
						import bitsandbytes as bnb
						import torch
						import torch.nn as nn

						from ..pytorch_utils import ConvaD

if is_accelerate_available():
						from accelerate import init_empty_weights
						from accelerate.utils import find_tied_parameters

__A   :  Union[str, Any]					=      logging.get_logger(__name__)

def 						snake_case__       (					_lowerCamelCase,  _lowerCamelCase,  _lowerCamelCase,  _lowerCamelCase=None,  _lowerCamelCase=None				)			->Optional[int]:






		"""simple docstring"""


		if "." in tensor_name:
				__lowercase				:		List[str]												=				tensor_name.split("."				)
				for split in splits[:-1]:
						__lowercase				:		Optional[Any]												=				getattr(_lowerCamelCase,  _lowerCamelCase				)
						if new_module is None:
								raise ValueError(F'{module} has no attribute {split}.'				)
						__lowercase				:		Any												=				new_module
				__lowercase				:		Dict												=				splits[-1]

		if tensor_name not in module._parameters and tensor_name not in module._buffers:
				raise ValueError(F'{module} does not have a parameter or a buffer named {tensor_name}.'				)
		__lowercase				:		str												=				tensor_name in module._buffers
		__lowercase				:		List[str]												=				getattr(_lowerCamelCase,  _lowerCamelCase				)

		if old_value.device == torch.device("meta"				) and device not in ["meta", torch.device("meta"				)] and value is None:
				raise ValueError(F'{tensor_name} is on the meta device, we need a `value` to put in on {device}.'				)

		__lowercase				:		Optional[Any]												=				False
		__lowercase				:		List[Any]												=				False
		if is_buffer or not is_bitsandbytes_available():
				__lowercase				:		int												=				False
				__lowercase				:		Tuple												=				False
		else:
				__lowercase				:		str												=				hasattr(bnb.nn,  "Params4bit"				) and isinstance(module._parameters[tensor_name],  bnb.nn.Paramsabit				)
				__lowercase				:		Any												=				isinstance(module._parameters[tensor_name],  bnb.nn.IntaParams				)

		if is_abit or is_abit:
				__lowercase				:		List[str]												=				module._parameters[tensor_name]
				if param.device.type != "cuda":
						if value is None:
								__lowercase				:		Optional[int]												=				old_value.to(_lowerCamelCase				)
						elif isinstance(_lowerCamelCase,  torch.Tensor				):
								__lowercase				:		Union[str, Any]												=				value.to("cpu"				)
								if value.dtype == torch.inta:
										__lowercase				:		Union[str, Any]												=				version.parse(importlib.metadata.version("bitsandbytes"				)				) > version.parse(
										    "0.37.2"				)
										if not is_abit_serializable:
												raise ValueError(
												    "Detected int8 weights but the version of bitsandbytes is not compatible with int8 serialization. "
												    "Make sure to download the latest `bitsandbytes` version. `pip install --upgrade bitsandbytes`."				)
						else:
								__lowercase				:		List[Any]												=				torch.tensor(_lowerCamelCase,  device="cpu"				)

						# Support models using `Conv1D` in place of `nn.Linear` (e.g. gpt2) by transposing the weight matrix prior to quantization.
						# Since weights are saved in the correct "orientation", we skip transposing when loading.
						if issubclass(module.source_cls,  _lowerCamelCase				) and fpaa_statistics is None:
								__lowercase				:		Optional[Any]												=				new_value.T

						__lowercase				:		Any												=				old_value.__dict__
						if is_abit:
								__lowercase				:		List[Any]												=				bnb.nn.IntaParams(_lowerCamelCase,  requires_grad=_lowerCamelCase,  **_lowerCamelCase				).to(_lowerCamelCase				)
						elif is_abit:
								__lowercase				:		Optional[int]												=				bnb.nn.Paramsabit(_lowerCamelCase,  requires_grad=_lowerCamelCase,  **_lowerCamelCase				).to(_lowerCamelCase				)

						__lowercase				:		List[Any]												=				new_value
						if fpaa_statistics is not None:
								setattr(module.weight,  "SCB",  fpaa_statistics.to(_lowerCamelCase				)				)

		else:
				if value is None:
						__lowercase				:		Optional[int]												=				old_value.to(_lowerCamelCase				)
				elif isinstance(_lowerCamelCase,  torch.Tensor				):
						__lowercase				:		int												=				value.to(_lowerCamelCase				)
				else:
						__lowercase				:		Union[str, Any]												=				torch.tensor(_lowerCamelCase,  device=_lowerCamelCase				)

				if is_buffer:
						__lowercase				:		Optional[int]												=				new_value
				else:
						__lowercase				:		List[Any]												=				nn.Parameter(_lowerCamelCase,  requires_grad=old_value.requires_grad				)
						__lowercase				:		Tuple												=				new_value

def 						snake_case__       (					_lowerCamelCase,  _lowerCamelCase=None,  _lowerCamelCase=None,  _lowerCamelCase=None,  _lowerCamelCase=False				)			->int:






		"""simple docstring"""


		for name, module in model.named_children():
				if current_key_name is None:
						__lowercase				:		Union[str, Any]												=				[]
				current_key_name.append(_lowerCamelCase				)

				if (isinstance(_lowerCamelCase,  nn.Linear				) or isinstance(_lowerCamelCase,  _lowerCamelCase				)) and name not in modules_to_not_convert:
						# Check if the current key is not in the `modules_to_not_convert`
						if not any(key in ".".join(_lowerCamelCase				) for key in modules_to_not_convert				):
								with init_empty_weights():
										if isinstance(_lowerCamelCase,  _lowerCamelCase				):
												__lowercase				:		List[Any]												=				module.weight.shape
										else:
												__lowercase				:		Optional[int]												=				module.in_features
												__lowercase				:		Union[str, Any]												=				module.out_features

										if quantization_config.quantization_method() == "llm_int8":
												__lowercase				:		Union[str, Any]												=				bnb.nn.LinearabitLt(
												    _lowerCamelCase,  _lowerCamelCase,  module.bias is not None,  has_fpaa_weights=quantization_config.llm_inta_has_fpaa_weight,  threshold=quantization_config.llm_inta_threshold,  )
												__lowercase				:		List[Any]												=				True
										else:
												if (
												    quantization_config.llm_inta_skip_modules is not None
												    and name in quantization_config.llm_inta_skip_modules
												):
														pass
												else:
														__lowercase				:		Optional[Any]												=				bnb.nn.Linearabit(
														    _lowerCamelCase,  _lowerCamelCase,  module.bias is not None,  quantization_config.bnb_abit_compute_dtype,  compress_statistics=quantization_config.bnb_abit_use_double_quant,  quant_type=quantization_config.bnb_abit_quant_type,  )
														__lowercase				:		str												=				True
                    # Store the module class in case we need to transpose the weight later
										__lowercase				:		Tuple												=				type(_lowerCamelCase				)
										# Force requires grad to False to avoid unexpected errors
										model._modules[name].requires_grad_(_lowerCamelCase				)
				if len(list(module.children()				)				) > 0:
						__lowercase				:		List[str]												=				_replace_with_bnb_linear(
						    _lowerCamelCase,  _lowerCamelCase,  _lowerCamelCase,  _lowerCamelCase,  has_been_replaced=_lowerCamelCase,  )
				# Remove the last key for recursion
				current_key_name.pop(-1				)
		return model, has_been_replaced

def 						snake_case__       (					_lowerCamelCase,  _lowerCamelCase=None,  _lowerCamelCase=None,  _lowerCamelCase=None				)			->List[Any]:






		"""simple docstring"""


		__lowercase				:		Tuple												=				["lm_head"] if modules_to_not_convert is None else modules_to_not_convert
		__lowercase				:		str												=				_replace_with_bnb_linear(
		    _lowerCamelCase,  _lowerCamelCase,  _lowerCamelCase,  _lowerCamelCase				)

		if not has_been_replaced:
				logger.warning(
				    "You are loading your model in 8bit or 4bit but no linear modules were found in your model."
				    " Please double check your model architecture, or submit an issue on github if you think this is"
				    " a bug."				)

		return model

def 						snake_case__       (					*_lowerCamelCase,  **_lowerCamelCase				)			->Optional[int]:






		"""simple docstring"""


		warnings.warn(
		    "`replace_8bit_linear` will be deprecated in a future version, please use `replace_with_bnb_linear` instead",  _lowerCamelCase,  )
		return replace_with_bnb_linear(*_lowerCamelCase,  **_lowerCamelCase				)

def 						snake_case__       (					*_lowerCamelCase,  **_lowerCamelCase				)			->List[Any]:






		"""simple docstring"""


		warnings.warn(
		    "`set_module_8bit_tensor_to_device` will be deprecated in a future version, please use `set_module_quantized_tensor_to_device` instead",  _lowerCamelCase,  )
		return set_module_quantized_tensor_to_device(*_lowerCamelCase,  **_lowerCamelCase				)





def 						snake_case__       (					_lowerCamelCase				)			->Tuple:






		"""simple docstring"""


		__lowercase				:		Optional[int]												=				deepcopy(_lowerCamelCase				)  # this has 0 cost since it is done inside `init_empty_weights` context manager`
		tied_model.tie_weights()

		__lowercase				:		str												=				find_tied_parameters(_lowerCamelCase				)
		# For compatibility with Accelerate < 0.18
		if isinstance(_lowerCamelCase,  _lowerCamelCase				):
				__lowercase				:		List[str]												=				sum(list(tied_params.values()				),  []				) + list(tied_params.keys()				)
		else:
				__lowercase				:		Dict												=				sum(_lowerCamelCase,  []				)
		__lowercase				:		Union[str, Any]												=				len(_lowerCamelCase				) > 0

		# Check if it is a base model
		__lowercase				:		Tuple												=				not hasattr(_lowerCamelCase,  model.base_model_prefix				)

		# Ignore this for base models (BertModel, GPT2Model, etc.)
		if (not has_tied_params) and is_base_model:
				return []

		# otherwise they have an attached head
		__lowercase				:		Optional[Any]												=				list(model.named_children()				)
		__lowercase				:		Union[str, Any]												=				[list_modules[-1][0]]

		# add last module together with tied weights
		__lowercase				:		List[str]												=				set(_lowerCamelCase				) - set(_lowerCamelCase				)
		__lowercase				:		List[str]												=				list(set(_lowerCamelCase				)				) + list(_lowerCamelCase				)

		# remove ".weight" from the keys
		__lowercase				:		List[str]												=				[".weight", ".bias"]
		__lowercase				:		Optional[int]												=				[]
		for name in list_untouched:
				for name_to_remove in names_to_remove:
						if name_to_remove in name:
								__lowercase				:		str												=				name.replace(_lowerCamelCase,  ""				)
				filtered_module_names.append(_lowerCamelCase				)

		return filtered_module_names






"""simple docstring"""







import os
import sys
import unittest


__A   :  Optional[Any]					=      os.path.abspath(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
sys.path.append(os.path.join(git_repo_path, 'utils'))

import check_dummies  # noqa: E402
from check_dummies import create_dummy_files, create_dummy_object, find_backend, read_init  # noqa: E402


# Align TRANSFORMERS_PATH in check_dummies with the current path
__A   :  Optional[Any]					=      os.path.join(git_repo_path, 'src', 'diffusers')




class       lowerCAmelCase__       (			unittest.TestCase    ):


				"""simple docstring"""





				def       snake_case    (     self					:	str						):
						__lowercase				:		int												=				find_backend("    if not is_torch_available():"						)
						self.assertEqual(lowercase__    ,   "torch"						)

						# backend_with_underscore = find_backend("    if not is_tensorflow_text_available():")
						# self.assertEqual(backend_with_underscore, "tensorflow_text")

						__lowercase				:		int												=				find_backend("    if not (is_torch_available() and is_transformers_available()):"						)
						self.assertEqual(lowercase__    ,   "torch_and_transformers"						)

						# double_backend_with_underscore = find_backend(
						#    "    if not (is_sentencepiece_available() and is_tensorflow_text_available()):"
						# )
						# self.assertEqual(double_backend_with_underscore, "sentencepiece_and_tensorflow_text")

						__lowercase				:		str												=				find_backend(
						    "    if not (is_torch_available() and is_transformers_available() and is_onnx_available()):"						)
						self.assertEqual(lowercase__    ,   "torch_and_transformers_and_onnx"						)



				def       snake_case    (     self					:	Any						):
						__lowercase				:		List[Any]												=				read_init()
						# We don't assert on the exact list of keys to allow for smooth grow of backend-specific objects
						self.assertIn("torch"    ,   lowercase__						)
						self.assertIn("torch_and_transformers"    ,   lowercase__						)
						self.assertIn("flax_and_transformers"    ,   lowercase__						)
						self.assertIn("torch_and_transformers_and_onnx"    ,   lowercase__						)

						# Likewise, we can't assert on the exact content of a key
						self.assertIn("UNet2DModel"    ,   objects["torch"]						)
						self.assertIn("FlaxUNet2DConditionModel"    ,   objects["flax"]						)
						self.assertIn("StableDiffusionPipeline"    ,   objects["torch_and_transformers"]						)
						self.assertIn("FlaxStableDiffusionPipeline"    ,   objects["flax_and_transformers"]						)
						self.assertIn("LMSDiscreteScheduler"    ,   objects["torch_and_scipy"]						)
						self.assertIn("OnnxStableDiffusionPipeline"    ,   objects["torch_and_transformers_and_onnx"]						)



				def       snake_case    (     self					:	Dict						):
						__lowercase				:		Tuple												=				create_dummy_object("CONSTANT"    ,   "'torch'"						)
						self.assertEqual(lowercase__    ,   "\nCONSTANT = None\n"						)

						__lowercase				:		Union[str, Any]												=				create_dummy_object("function"    ,   "'torch'"						)
						self.assertEqual(
						    lowercase__    ,   "\ndef function(*args, **kwargs):\n    requires_backends(function, 'torch')\n"						)

						__lowercase				:		Tuple												=				"\nclass FakeClass(metaclass=DummyObject):\n    _backends = 'torch'\n\n    def __init__(self, *args, **kwargs):\n        requires_backends(self, 'torch')\n\n    @classmethod\n    def from_config(cls, *args, **kwargs):\n        requires_backends(cls, 'torch')\n\n    @classmethod\n    def from_pretrained(cls, *args, **kwargs):\n        requires_backends(cls, 'torch')\n"
						__lowercase				:		Dict												=				create_dummy_object("FakeClass"    ,   "'torch'"						)
						self.assertEqual(lowercase__    ,   lowercase__						)



				def       snake_case    (     self					:	List[Any]						):
						__lowercase				:		Optional[int]												=				"# This file is autogenerated by the command `make fix-copies`, do not edit.\nfrom ..utils import DummyObject, requires_backends\n\n\nCONSTANT = None\n\n\ndef function(*args, **kwargs):\n    requires_backends(function, [\"torch\"])\n\n\nclass FakeClass(metaclass=DummyObject):\n    _backends = [\"torch\"]\n\n    def __init__(self, *args, **kwargs):\n        requires_backends(self, [\"torch\"])\n\n    @classmethod\n    def from_config(cls, *args, **kwargs):\n        requires_backends(cls, [\"torch\"])\n\n    @classmethod\n    def from_pretrained(cls, *args, **kwargs):\n        requires_backends(cls, [\"torch\"])\n"
						__lowercase				:		List[str]												=				create_dummy_files({"torch": ["CONSTANT", "function", "FakeClass"]}						)
						self.assertEqual(dummy_files["torch"]    ,   lowercase__						)
