



'''simple docstring'''







import inspect
from typing import List, Optional, Union

import torch
from torch import nn
from torch.nn import functional as F
from torchvision import transforms
from transformers import CLIPImageProcessor, CLIPModel, CLIPTextModel, CLIPTokenizer

from diffusers import (
    AutoencoderKL,
    DDIMScheduler,
    DiffusionPipeline,
    DPMSolverMultistepScheduler,
    LMSDiscreteScheduler,
    PNDMScheduler,
    UNetaDConditionModel,
)
from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion import StableDiffusionPipelineOutput

class    lowerCamelCase_				(						nn.Module	):






   '''simple docstring'''

   def __init__(	self  ,    __UpperCamelCase  ,    __UpperCamelCase=1.0			):
       super().__init__()

       UpperCamelCase__	     =      cut_size
       UpperCamelCase__	     =      cut_power







   def 						_UpperCamelCase							(	self  ,    __UpperCamelCase  ,    __UpperCamelCase			):
       UpperCamelCase__	     =      pixel_values.shape[2:4]
       UpperCamelCase__	     =      min(SCREAMING_SNAKE_CASE__  ,    SCREAMING_SNAKE_CASE__			)
       UpperCamelCase__	     =      min(SCREAMING_SNAKE_CASE__  ,    SCREAMING_SNAKE_CASE__  ,    self.cut_size			)
       UpperCamelCase__	     =      []
       for _ in range(SCREAMING_SNAKE_CASE__			):
           UpperCamelCase__	     =      int(torch.rand([]			) ** self.cut_power * (max_size - min_size) + min_size			)
           UpperCamelCase__	     =      torch.randint(0  ,    sideX - size + 1  ,    ()			)
           UpperCamelCase__	     =      torch.randint(0  ,    sideY - size + 1  ,    ()			)
           UpperCamelCase__	     =      pixel_values[:, :, offsety : offsety + size, offsetx : offsetx + size]
           cutouts.append(F.adaptive_avg_poolad(SCREAMING_SNAKE_CASE__  ,    self.cut_size			)			)
       return torch.cat(SCREAMING_SNAKE_CASE__			)





def     snake_case__			(lowerCAmelCase_       ,	lowerCAmelCase_						):
    UpperCamelCase__	     =      F.normalize(A__       ,	dim=-1						)
    UpperCamelCase__	     =      F.normalize(A__       ,	dim=-1						)
    return (x - y).norm(dim=-1						).div(2						).arcsin().pow(2						).mul(2						)





def     snake_case__			(lowerCAmelCase_       ,	lowerCAmelCase_						):
    for param in model.parameters():
        UpperCamelCase__	     =      value





class    lowerCamelCase_				(						lowercase__	):






   '''simple docstring'''

   def __init__(	self  ,    __UpperCamelCase  ,    __UpperCamelCase  ,    __UpperCamelCase  ,    __UpperCamelCase  ,    __UpperCamelCase  ,    __UpperCamelCase  ,    __UpperCamelCase  ,    ):
       super().__init__()
       self.register_modules(
           vae=SCREAMING_SNAKE_CASE__  ,    text_encoder=SCREAMING_SNAKE_CASE__  ,    clip_model=SCREAMING_SNAKE_CASE__  ,    tokenizer=SCREAMING_SNAKE_CASE__  ,    unet=SCREAMING_SNAKE_CASE__  ,    scheduler=SCREAMING_SNAKE_CASE__  ,    feature_extractor=SCREAMING_SNAKE_CASE__  ,    )

       UpperCamelCase__	     =      transforms.Normalize(mean=feature_extractor.image_mean  ,    std=feature_extractor.image_std			)
       UpperCamelCase__	     =      (
           feature_extractor.size
           if isinstance(feature_extractor.size  ,    SCREAMING_SNAKE_CASE__			)
           else feature_extractor.size["""shortest_edge"""]
       )
       UpperCamelCase__	     =      MakeCutouts(self.cut_out_size			)

       set_requires_grad(self.text_encoder  ,    SCREAMING_SNAKE_CASE__			)
       set_requires_grad(self.clip_model  ,    SCREAMING_SNAKE_CASE__			)


   def 						_UpperCamelCase							(	self  ,    __UpperCamelCase = "auto"			):

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


   def 						_UpperCamelCase							(	self			):
       self.enable_attention_slicing(SCREAMING_SNAKE_CASE__			)


   def 						_UpperCamelCase							(	self			):
       set_requires_grad(self.vae  ,    SCREAMING_SNAKE_CASE__			)


   def 						_UpperCamelCase							(	self			):
       set_requires_grad(self.vae  ,    SCREAMING_SNAKE_CASE__			)


   def 						_UpperCamelCase							(	self			):
       set_requires_grad(self.unet  ,    SCREAMING_SNAKE_CASE__			)


   def 						_UpperCamelCase							(	self			):
       set_requires_grad(self.unet  ,    SCREAMING_SNAKE_CASE__			)


   @torch.enable_grad()
   def 						_UpperCamelCase							(	self  ,    __UpperCamelCase  ,    __UpperCamelCase  ,    __UpperCamelCase  ,    __UpperCamelCase  ,    __UpperCamelCase  ,    __UpperCamelCase  ,    __UpperCamelCase  ,    __UpperCamelCase  ,    __UpperCamelCase=True  ,    ):
       UpperCamelCase__	     =      latents.detach().requires_grad_()

       UpperCamelCase__	     =      self.scheduler.scale_model_input(SCREAMING_SNAKE_CASE__  ,    SCREAMING_SNAKE_CASE__			)

       # predict the noise residual
       UpperCamelCase__	     =      self.unet(SCREAMING_SNAKE_CASE__  ,    SCREAMING_SNAKE_CASE__  ,    encoder_hidden_states=SCREAMING_SNAKE_CASE__			).sample

       if isinstance(self.scheduler  ,    (PNDMScheduler, DDIMScheduler, DPMSolverMultistepScheduler)			):
           UpperCamelCase__	     =      self.scheduler.alphas_cumprod[timestep]
           UpperCamelCase__	     =      1 - alpha_prod_t
           # compute predicted original sample from predicted noise also called
           # "predicted x_0" of formula (12) from https://arxiv.org/pdf/2010.02502.pdf
           UpperCamelCase__	     =      (latents - beta_prod_t ** 0.5 * noise_pred) / alpha_prod_t ** 0.5

           UpperCamelCase__	     =      torch.sqrt(SCREAMING_SNAKE_CASE__			)
           UpperCamelCase__	     =      pred_original_sample * (fac) + latents * (1 - fac)
       elif isinstance(self.scheduler  ,    SCREAMING_SNAKE_CASE__			):
           UpperCamelCase__	     =      self.scheduler.sigmas[index]
           UpperCamelCase__	     =      latents - sigma * noise_pred
       else:
           raise ValueError(f'scheduler type {type(self.scheduler			)} not supported'			)

       UpperCamelCase__	     =      1 / self.vae.config.scaling_factor * sample
       UpperCamelCase__	     =      self.vae.decode(SCREAMING_SNAKE_CASE__			).sample
       UpperCamelCase__	     =      (image / 2 + 0.5).clamp(0  ,    1			)

       if use_cutouts:
           UpperCamelCase__	     =      self.make_cutouts(SCREAMING_SNAKE_CASE__  ,    SCREAMING_SNAKE_CASE__			)
       else:
           UpperCamelCase__	     =      transforms.Resize(self.cut_out_size			)(SCREAMING_SNAKE_CASE__			)
       UpperCamelCase__	     =      self.normalize(SCREAMING_SNAKE_CASE__			).to(latents.dtype			)

       UpperCamelCase__	     =      self.clip_model.get_image_features(SCREAMING_SNAKE_CASE__			)
       UpperCamelCase__	     =      image_embeddings_clip / image_embeddings_clip.norm(p=2  ,    dim=-1  ,    keepdim=SCREAMING_SNAKE_CASE__			)

       if use_cutouts:
           UpperCamelCase__	     =      spherical_dist_loss(SCREAMING_SNAKE_CASE__  ,    SCREAMING_SNAKE_CASE__			)
           UpperCamelCase__	     =      dists.view([num_cutouts, sample.shape[0], -1]			)
           UpperCamelCase__	     =      dists.sum(2			).mean(0			).sum() * clip_guidance_scale
       else:
           UpperCamelCase__	     =      spherical_dist_loss(SCREAMING_SNAKE_CASE__  ,    SCREAMING_SNAKE_CASE__			).mean() * clip_guidance_scale

       UpperCamelCase__	     =      -torch.autograd.grad(SCREAMING_SNAKE_CASE__  ,    SCREAMING_SNAKE_CASE__			)[0]

       if isinstance(self.scheduler  ,    SCREAMING_SNAKE_CASE__			):
           UpperCamelCase__	     =      latents.detach() + grads * (sigma**2)
           UpperCamelCase__	     =      noise_pred_original
       else:
           UpperCamelCase__	     =      noise_pred_original - torch.sqrt(SCREAMING_SNAKE_CASE__			) * grads
       return noise_pred, latents







   @torch.no_grad()
   def __call__(	self  ,    __UpperCamelCase  ,    __UpperCamelCase = 5_12  ,    __UpperCamelCase = 5_12  ,    __UpperCamelCase = 50  ,    __UpperCamelCase = 7.5  ,    __UpperCamelCase = 1  ,    __UpperCamelCase = 0.0  ,    __UpperCamelCase = 1_00  ,    __UpperCamelCase = None  ,    __UpperCamelCase = 4  ,    __UpperCamelCase = True  ,    __UpperCamelCase = None  ,    __UpperCamelCase = None  ,    __UpperCamelCase = "pil"  ,    __UpperCamelCase = True  ,    ):

       if isinstance(SCREAMING_SNAKE_CASE__  ,    SCREAMING_SNAKE_CASE__			):
           UpperCamelCase__	     =      1
       elif isinstance(SCREAMING_SNAKE_CASE__  ,    SCREAMING_SNAKE_CASE__			):
           UpperCamelCase__	     =      len(SCREAMING_SNAKE_CASE__			)
       else:
           raise ValueError(f'`prompt` has to be of type `str` or `list` but is {type(SCREAMING_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}.'			)

       # get prompt text embeddings
       UpperCamelCase__	     =      self.tokenizer(
           SCREAMING_SNAKE_CASE__  ,    padding="max_length"  ,    max_length=self.tokenizer.model_max_length  ,    truncation=SCREAMING_SNAKE_CASE__  ,    return_tensors="pt"  ,    )
       UpperCamelCase__	     =      self.text_encoder(text_input.input_ids.to(self.device			)			)[0]
       # duplicate text embeddings for each generation per prompt
       UpperCamelCase__	     =      text_embeddings.repeat_interleave(SCREAMING_SNAKE_CASE__  ,    dim=0			)

       if clip_guidance_scale > 0:
           if clip_prompt is not None:
               UpperCamelCase__	     =      self.tokenizer(
                   SCREAMING_SNAKE_CASE__  ,    padding="max_length"  ,    max_length=self.tokenizer.model_max_length  ,    truncation=SCREAMING_SNAKE_CASE__  ,    return_tensors="pt"  ,    ).input_ids.to(self.device			)
           else:
               UpperCamelCase__	     =      text_input.input_ids.to(self.device			)
           UpperCamelCase__	     =      self.clip_model.get_text_features(SCREAMING_SNAKE_CASE__			)
           UpperCamelCase__	     =      text_embeddings_clip / text_embeddings_clip.norm(p=2  ,    dim=-1  ,    keepdim=SCREAMING_SNAKE_CASE__			)
           # duplicate text embeddings clip for each generation per prompt
           UpperCamelCase__	     =      text_embeddings_clip.repeat_interleave(SCREAMING_SNAKE_CASE__  ,    dim=0			)

       # 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.
       UpperCamelCase__	     =      guidance_scale > 1.0
       # get unconditional embeddings for classifier free guidance
       if do_classifier_free_guidance:
           UpperCamelCase__	     =      text_input.input_ids.shape[-1]
           UpperCamelCase__	     =      self.tokenizer([""]  ,    padding="max_length"  ,    max_length=SCREAMING_SNAKE_CASE__  ,    return_tensors="pt"			)
           UpperCamelCase__	     =      self.text_encoder(uncond_input.input_ids.to(self.device			)			)[0]
           # duplicate unconditional embeddings for each generation per prompt
           UpperCamelCase__	     =      uncond_embeddings.repeat_interleave(SCREAMING_SNAKE_CASE__  ,    dim=0			)

           # 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
           UpperCamelCase__	     =      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`.
       UpperCamelCase__	     =      (batch_size * num_images_per_prompt, self.unet.config.in_channels, height // 8, width // 8)
       UpperCamelCase__	     =      text_embeddings.dtype
       if latents is None:
           if self.device.type == "mps":
               # randn does not work reproducibly on mps
               UpperCamelCase__	     =      torch.randn(SCREAMING_SNAKE_CASE__  ,    generator=SCREAMING_SNAKE_CASE__  ,    device="cpu"  ,    dtype=SCREAMING_SNAKE_CASE__			).to(
                   self.device			)
           else:
               UpperCamelCase__	     =      torch.randn(SCREAMING_SNAKE_CASE__  ,    generator=SCREAMING_SNAKE_CASE__  ,    device=self.device  ,    dtype=SCREAMING_SNAKE_CASE__			)
       else:
           if latents.shape != latents_shape:
               raise ValueError(f'Unexpected latents shape, got {latents.shape}, expected {latents_shape}'			)
           UpperCamelCase__	     =      latents.to(self.device			)

       # set timesteps
       UpperCamelCase__	     =      """offset""" in set(inspect.signature(self.scheduler.set_timesteps			).parameters.keys()			)
       UpperCamelCase__	     =      {}
       if accepts_offset:
           UpperCamelCase__	     =      1

       self.scheduler.set_timesteps(SCREAMING_SNAKE_CASE__  ,    **SCREAMING_SNAKE_CASE__			)

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

       # scale the initial noise by the standard deviation required by the scheduler
       UpperCamelCase__	     =      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]
       UpperCamelCase__	     =      """eta""" in set(inspect.signature(self.scheduler.step			).parameters.keys()			)
       UpperCamelCase__	     =      {}
       if accepts_eta:
           UpperCamelCase__	     =      eta

       # check if the scheduler accepts generator
       UpperCamelCase__	     =      """generator""" in set(inspect.signature(self.scheduler.step			).parameters.keys()			)
       if accepts_generator:
           UpperCamelCase__	     =      generator

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

           # predict the noise residual
           UpperCamelCase__	     =      self.unet(SCREAMING_SNAKE_CASE__  ,    SCREAMING_SNAKE_CASE__  ,    encoder_hidden_states=SCREAMING_SNAKE_CASE__			).sample

           # perform classifier free guidance
           if do_classifier_free_guidance:
               UpperCamelCase__	     =      noise_pred.chunk(2			)
               UpperCamelCase__	     =      noise_pred_uncond + guidance_scale * (noise_pred_text - noise_pred_uncond)

           # perform clip guidance
           if clip_guidance_scale > 0:
               UpperCamelCase__	     =      (
                   text_embeddings.chunk(2			)[1] if do_classifier_free_guidance else text_embeddings
               )
               UpperCamelCase__	     =      self.cond_fn(
                   SCREAMING_SNAKE_CASE__  ,    SCREAMING_SNAKE_CASE__  ,    SCREAMING_SNAKE_CASE__  ,    SCREAMING_SNAKE_CASE__  ,    SCREAMING_SNAKE_CASE__  ,    SCREAMING_SNAKE_CASE__  ,    SCREAMING_SNAKE_CASE__  ,    SCREAMING_SNAKE_CASE__  ,    SCREAMING_SNAKE_CASE__  ,    )

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

       # scale and decode the image latents with vae
       UpperCamelCase__	     =      1 / self.vae.config.scaling_factor * latents
       UpperCamelCase__	     =      self.vae.decode(SCREAMING_SNAKE_CASE__			).sample

       UpperCamelCase__	     =      (image / 2 + 0.5).clamp(0  ,    1			)
       UpperCamelCase__	     =      image.cpu().permute(0  ,    2  ,    3  ,    1			).numpy()

       if output_type == "pil":
           UpperCamelCase__	     =      self.numpy_to_pil(SCREAMING_SNAKE_CASE__			)

       if not return_dict:
           return (image, None)

       return StableDiffusionPipelineOutput(images=SCREAMING_SNAKE_CASE__  ,    nsfw_content_detected=SCREAMING_SNAKE_CASE__			)









import logging
from pathlib import Path
from typing import Any, List, Tuple

import yaml


# loading package files: https://stackoverflow.com/a/20885799
try:
						import importlib.resources as pkg_resources
except ImportError:
						# Try backported to PY<37 `importlib_resources`.
						import importlib_resources as pkg_resources

from . import resources


UpperCAmelCase_			      =  '''https://github.com/huggingface/datasets/tree/main/src/datasets/utils'''
UpperCAmelCase_			      =  f"""{BASE_REF_URL}/{__file__}"""
UpperCAmelCase_			      =  logging.getLogger(__name__)
def   UpperCAmelCase							(		A__     )							->					Tuple[Any, str]:
	_snake_case					:							Optional[int]					     =   pkg_resources.read_text(A__				,  A__     )
	return yaml.safe_load(A__     ), f'''{BASE_REF_URL}/resources/{resource}'''


UpperCAmelCase_      ,				UpperCAmelCase_			      =  load_yaml_resource('''readme_structure.yaml''')

UpperCAmelCase_			      =  [
    '''[Needs More Information]''',
    '''[More Information Needed]''',
    '''(https://github.com/huggingface/datasets/blob/main/CONTRIBUTING.md#how-to-contribute-to-the-dataset-cards)''',
]

# Dictionary representation of section/readme, error_list, warning_list
UpperCAmelCase_			      =  Tuple[dict, List[str], List[str]]





class 		__SCREAMING_SNAKE_CASE      :






				"""simple docstring"""

				def __init__(				self						,	SCREAMING_SNAKE_CASE__						,	SCREAMING_SNAKE_CASE__						,	SCREAMING_SNAKE_CASE__ = None						,	SCREAMING_SNAKE_CASE__ = False      ):






					"""simple docstring"""

					_snake_case					:							Optional[Any]					     =   name
					_snake_case					:							str					     =   level
					_snake_case					:							Optional[Any]					     =   lines
					_snake_case					:							Any					     =   """"""
					_snake_case					:							int					     =   True
					_snake_case					:							Dict					     =   {}
					_snake_case					:							List[str]					     =   []
					_snake_case					:							Optional[Any]					     =   []
					if self.lines is not None:
						self.parse(suppress_parsing_errors=SCREAMING_SNAKE_CASE__      )







				def 		__lowerCamelCase(				self						,	SCREAMING_SNAKE_CASE__ = False      ):






					"""simple docstring"""

					_snake_case					:							Dict					     =   """"""
					_snake_case					:							Dict					     =   []
					_snake_case					:							str					     =   False
					for line in self.lines:
						if line.strip(""" \n"""      ) == "":
							continue
						elif line.strip(""" \n"""      )[:3] == "```":
							_snake_case					:							Tuple					     =   not code_start
						elif line.split()[0] == self.level + "#" and not code_start:
							if current_sub_level != "":
								_snake_case					:							int					     =   Section(SCREAMING_SNAKE_CASE__						,	self.level + """#"""						,	SCREAMING_SNAKE_CASE__      )
								_snake_case					:							Optional[int]					     =   []
							else:
								if current_lines != []:
									self.text += "".join(SCREAMING_SNAKE_CASE__      ).strip()
									if self.text != "" and self.text not in FILLER_TEXT:
										_snake_case					:							Any					     =   False
									_snake_case					:							Tuple					     =   []

							_snake_case					:							Optional[Any]					     =   """ """.join(line.split()[1:]      ).strip(""" \n"""      )
						else:
							current_lines.append(SCREAMING_SNAKE_CASE__      )
					else:
						if current_sub_level != "":
							if current_sub_level in self.content:
								self.parsing_error_list.append(
								    f'''Multiple sections with the same heading `{current_sub_level}` have been found. Please keep only one of these sections.'''      )
							_snake_case					:							Union[str, Any]					     =   Section(SCREAMING_SNAKE_CASE__						,	self.level + """#"""						,	SCREAMING_SNAKE_CASE__      )
						else:
							if current_lines != []:
								self.text += "".join(SCREAMING_SNAKE_CASE__      ).strip()
								if self.text != "" and self.text not in FILLER_TEXT:
									_snake_case					:							Dict					     =   False

					if self.level == "" and not suppress_parsing_errors:
						if self.parsing_error_list != [] or self.parsing_warning_list != []:
							_snake_case					:							List[Any]					     =   """\n""".join("""-\t""" + x for x in self.parsing_error_list + self.parsing_warning_list      )
							_snake_case					:							Optional[Any]					     =   f'''The following issues were found while parsing the README at `{self.name}`:\n''' + errors
							raise ValueError(SCREAMING_SNAKE_CASE__      )







				def 		__lowerCamelCase(				self						,	SCREAMING_SNAKE_CASE__      ):






					"""simple docstring"""

					_snake_case					:							Union[str, Any]					     =   []
					_snake_case					:							Tuple					     =   []
					if structure["allow_empty"] is False:
						# If content is expected
						if self.is_empty_text and self.content == {}:
							# If no content is found, mention it in the error_list
							error_list.append(f'''Expected some content in section `{self.name}` but it is empty.'''      )

					if structure["allow_empty_text"] is False:
						# If some text is expected
						if self.is_empty_text:
							# If no text is found, mention it in the error_list
							error_list.append(
							    f'''Expected some text in section `{self.name}` but it is empty (text in subsections are ignored).'''      )
        # Subsections Validation
					if structure["subsections"] is not None:
						# If subsections are expected
						if self.content == {}:
							# If no subsections are present
							_snake_case					:							Optional[int]					     =   [subsection["""name"""] for subsection in structure["""subsections"""]]
							# Mention the expected values in the error_list
							error_list.append(
							    f'''Section `{self.name}` expected the following subsections: {", ".join(["`"+x+"`" for x in values]      )}. Found \'None\'.'''      )
						else:
							# If some subsections are present
							_snake_case					:							Tuple					     =   [subsection["""name"""] for subsection in structure["""subsections"""]]
							_snake_case					:							Dict					     =   False
							for idx, name in enumerate(SCREAMING_SNAKE_CASE__      ):
								if name not in self.content:
									# If the expected subsection is not present
									error_list.append(f'''Section `{self.name}` is missing subsection: `{name}`.'''      )
									_snake_case					:							int					     =   True
								else:
									# If the subsection is present, validate subsection, return the result
									# and concat the errors from subsection to section error_list

									# Skip sublevel validation if current level is `###`
									if self.level == "###":
										continue
									else:
										_snake_case     , _snake_case     , _snake_case					:							Tuple					     =   self.content[name].validate(
										    structure["""subsections"""][idx]      )
									error_list += subsec_error_list
									warning_list += subsec_warning_list

							if has_missing_subsections:  # we only allow to have extra subsections if all the other ones are here
								for name in self.content:
									if name not in structure_names:
										# If an extra subsection is present
										warning_list.append(
										    f'''`{self.name}` has an extra subsection: `{name}`. Skipping further validation checks for this subsection as expected structure is unknown.'''      )
					if error_list:
						# If there are errors, do not return the dictionary as it is invalid
						return {}, error_list, warning_list
					else:
						return self.to_dict(), error_list, warning_list







				def 		__lowerCamelCase(				self      ):






					"""simple docstring"""

					return {
					    "name": self.name,
					    "text": self.text,
					    "is_empty_text": self.is_empty_text,
					    "subsections": [value.to_dict() for value in self.content.values()],
					}





class 		__SCREAMING_SNAKE_CASE      (				lowercase__      ):  # Level 0






				"""simple docstring"""

				def __init__(				self						,	SCREAMING_SNAKE_CASE__						,	SCREAMING_SNAKE_CASE__						,	SCREAMING_SNAKE_CASE__ = None						,	SCREAMING_SNAKE_CASE__ = False      ):






					"""simple docstring"""

					super().__init__(name=SCREAMING_SNAKE_CASE__						,	level=""""""      )  # Not using lines here as we need to use a child class parse
					_snake_case					:							Optional[int]					     =   structure
					_snake_case					:							str					     =   -2
					_snake_case					:							Any					     =   0
					_snake_case					:							int					     =   lines
					if self.lines is not None:
						self.parse(suppress_parsing_errors=SCREAMING_SNAKE_CASE__      )







				def 		__lowerCamelCase(				self      ):






					"""simple docstring"""

					if self.structure is None:
						_snake_case     , _snake_case     , _snake_case					:							List[Any]					     =   self._validate(SCREAMING_SNAKE_CASE__      )
					else:
						_snake_case     , _snake_case     , _snake_case					:							str					     =   self._validate(self.structure      )
					if error_list != [] or warning_list != []:
						_snake_case					:							List[Any]					     =   """\n""".join(["""-\t""" + x for x in error_list + warning_list]      )
						_snake_case					:							Any					     =   f'''The following issues were found for the README at `{self.name}`:\n''' + errors
						raise ValueError(SCREAMING_SNAKE_CASE__      )







				@classmethod
				def 		__lowerCamelCase(				cls						,	SCREAMING_SNAKE_CASE__						,	SCREAMING_SNAKE_CASE__ = None						,	SCREAMING_SNAKE_CASE__ = False      ):






					"""simple docstring"""

					with open(SCREAMING_SNAKE_CASE__						,	encoding="""utf-8"""      ) as f:
						_snake_case					:							List[str]					     =   f.readlines()
					return cls(SCREAMING_SNAKE_CASE__						,	SCREAMING_SNAKE_CASE__						,	SCREAMING_SNAKE_CASE__						,	suppress_parsing_errors=SCREAMING_SNAKE_CASE__      )







				@classmethod
				def 		__lowerCamelCase(				cls						,	SCREAMING_SNAKE_CASE__						,	SCREAMING_SNAKE_CASE__ = None						,	SCREAMING_SNAKE_CASE__ = "root"						,	SCREAMING_SNAKE_CASE__ = False      ):






					"""simple docstring"""

					_snake_case					:							Tuple					     =   string.split("""\n"""      )
					return cls(SCREAMING_SNAKE_CASE__						,	SCREAMING_SNAKE_CASE__						,	SCREAMING_SNAKE_CASE__						,	suppress_parsing_errors=SCREAMING_SNAKE_CASE__      )







				def 		__lowerCamelCase(				self						,	SCREAMING_SNAKE_CASE__ = False      ):






					"""simple docstring"""

					_snake_case					:							Optional[int]					     =   0

					for line in self.lines:
						self.yaml_tags_line_count += 1
						if line.strip(""" \n"""      ) == "---":
							self.tag_count += 1
							if self.tag_count == 2:
								break
						line_count += 1
					if self.tag_count == 2:
						_snake_case					:							Optional[int]					     =   self.lines[line_count + 1 :]  # Get the last + 1 th item.
					else:
						_snake_case					:							List[str]					     =   self.lines[self.tag_count :]
					super().parse(suppress_parsing_errors=SCREAMING_SNAKE_CASE__      )







				def __str__(				self      ):






					"""simple docstring"""

					return str(self.to_dict()      )







				def 		__lowerCamelCase(				self						,	SCREAMING_SNAKE_CASE__      ):






					"""simple docstring"""

					_snake_case					:							str					     =   []
					_snake_case					:							str					     =   []
					if self.yaml_tags_line_count == 0:
						warning_list.append("""Empty YAML markers are present in the README."""      )
					elif self.tag_count == 0:
						warning_list.append("""No YAML markers are present in the README."""      )
					elif self.tag_count == 1:
						warning_list.append("""Only the start of YAML tags present in the README."""      )
					# Check how many first level sections are present.
					_snake_case					:							List[str]					     =   len(self.content.keys()      )
					if num_first_level_keys > 1:
						# If more than one, add to the error list, continue
						error_list.append(
						    f'''The README has several first-level headings: {", ".join(["`"+x+"`" for x in list(self.content.keys()      )]      )}. Only one heading is expected. Skipping further validation for this README.'''      )
					elif num_first_level_keys < 1:
						# If less than one, append error.
						error_list.append(
						    """The README has no first-level headings. One heading is expected. Skipping further validation for this README."""      )

					else:
						# If one exactly
						_snake_case					:							List[str]					     =   list(self.content.keys()      )[0]  # Get the key
						if start_key.startswith("""Dataset Card for"""      ):  # Check correct start
							# If the starting is correct, validate all the sections
							_snake_case     , _snake_case     , _snake_case					:							List[Any]					     =   self.content[start_key].validate(
							    readme_structure["""subsections"""][0]      )
							error_list += sec_error_list
							warning_list += sec_warning_list
						else:
							# If not found, append error
							error_list.append(
							    """No first-level heading starting with `Dataset Card for` found in README. Skipping further validation for this README."""      )
					if error_list:
						# If there are errors, do not return the dictionary as it is invalid
						return {}, error_list, warning_list
					else:
						return self.to_dict(), error_list, warning_list


if __name__ == "__main__":
						from argparse import ArgumentParser

						UpperCAmelCase_			      =  ArgumentParser(usage='''Validate the content (excluding YAML tags) of a README.md file.''')
						ap.add_argument('''readme_filepath''')
						UpperCAmelCase_			      =  ap.parse_args()
						UpperCAmelCase_			      =  Path(args.readme_filepath)
						UpperCAmelCase_			      =  ReadMe.from_readme(readme_filepath)





