





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


snake_case__   :				str						=	'https://github.com/huggingface/datasets/tree/main/src/datasets/utils'
snake_case__   :				List[str]						=	f'{BASE_REF_URL}/{__file__}'
snake_case__   :				List[Any]						=	logging.getLogger(__name__)



def _a							(      lowerCamelCase:  str					)      ->		Tuple[Any, str]:







      '''simple docstring'''






      __A			  =							pkg_resources.read_text(lowerCamelCase   ,							lowerCamelCase					)
      return yaml.safe_load(lowerCamelCase					), F"""{BASE_REF_URL}/resources/{resource}"""


snake_case__		,       snake_case__   :				Optional[Any]						=	load_yaml_resource('readme_structure.yaml')

snake_case__   :				Any						=	[
    '[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
snake_case__   :				Dict						=	Tuple[dict, List[str], List[str]]





class A_   :




   def __init__(self      :List[str]       ,  _UpperCamelCase      :str       ,  _UpperCamelCase      :str       ,  _UpperCamelCase      :List[str] = None       ,  _UpperCamelCase      :bool = False					)->   Union[str, Any]:
         __A			  =							name
         __A			  =							level
         __A			  =							lines
         __A			  =							''''''
         __A			  =							True
         __A			  =							{}
         __A			  =							[]
         __A			  =							[]
         if self.lines is not None:
               self.parse(suppress_parsing_errors=_UpperCamelCase					)




   def _lowerCAmelCase (self      :Union[str, Any]       ,  _UpperCamelCase      :bool = False					)->   List[str]:
         __A			  =							''''''
         __A			  =							[]
         __A			  =							False
         for line in self.lines:
               if line.strip(''' \n'''					) == "":
                     continue
               elif line.strip(''' \n'''					)[:3] == "```":
                     __A			  =							not code_start
               elif line.split()[0] == self.level + "#" and not code_start:
                     if current_sub_level != "":
                           __A			  =							Section(_UpperCamelCase       ,  self.level + '''#'''       ,  _UpperCamelCase					)
                           __A			  =							[]
                     else:
                           if current_lines != []:
                                 self.text += "".join(_UpperCamelCase					).strip()
                                 if self.text != "" and self.text not in FILLER_TEXT:
                                       __A			  =							False
                                 __A			  =							[]

                     __A			  =							''' '''.join(line.split()[1:]					).strip(''' \n'''					)
               else:
                     current_lines.append(_UpperCamelCase					)
         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."""					)
                     __A			  =							Section(_UpperCamelCase       ,  self.level + '''#'''       ,  _UpperCamelCase					)
               else:
                     if current_lines != []:
                           self.text += "".join(_UpperCamelCase					).strip()
                           if self.text != "" and self.text not in FILLER_TEXT:
                                 __A			  =							False

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




   def _lowerCAmelCase (self      :Tuple       ,  _UpperCamelCase      :dict					)->   ReadmeValidatorOutput:
         __A			  =							[]
         __A			  =							[]
         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
                     __A			  =							[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
                     __A			  =							[subsection['''name'''] for subsection in structure['''subsections''']]
                     __A			  =							False
                     for idx, name in enumerate(_UpperCamelCase					):
                           if name not in self.content:
                                 # If the expected subsection is not present
                                 error_list.append(f"""Section `{self.name}` is missing subsection: `{name}`."""					)
                                 __A			  =							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:
                                       __A  ,		__A  ,		__A			  =							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      :Optional[Any]					)->   dict:
         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 A_   (     _lowerCamelCase  ):  # Level 0




   def __init__(self      :Dict       ,  _UpperCamelCase      :str       ,  _UpperCamelCase      :List[str]       ,  _UpperCamelCase      :dict = None       ,  _UpperCamelCase      :bool = False					)->   Union[str, Any]:
         super().__init__(name=_UpperCamelCase       ,  level=''''''					)  # Not using lines here as we need to use a child class parse
         __A			  =							structure
         __A			  =							-2
         __A			  =							0
         __A			  =							lines
         if self.lines is not None:
               self.parse(suppress_parsing_errors=_UpperCamelCase					)




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




   @classmethod
   def _lowerCAmelCase (cls      :Optional[Any]       ,  _UpperCamelCase      :Path       ,  _UpperCamelCase      :dict = None       ,  _UpperCamelCase      :bool = False					)->   Optional[int]:
         with open(_UpperCamelCase       ,  encoding='''utf-8'''					) as f:
               __A			  =							f.readlines()
         return cls(_UpperCamelCase       ,  _UpperCamelCase       ,  _UpperCamelCase       ,  suppress_parsing_errors=_UpperCamelCase					)




   @classmethod
   def _lowerCAmelCase (cls      :Dict       ,  _UpperCamelCase      :str       ,  _UpperCamelCase      :dict = None       ,  _UpperCamelCase      :str = "root"       ,  _UpperCamelCase      :bool = False					)->   str:
         __A			  =							string.split('''\n'''					)
         return cls(_UpperCamelCase       ,  _UpperCamelCase       ,  _UpperCamelCase       ,  suppress_parsing_errors=_UpperCamelCase					)




   def _lowerCAmelCase (self      :Any       ,  _UpperCamelCase      :bool = False					)->   Dict:
         # Skip Tags
         __A			  =							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:
               __A			  =							self.lines[line_count + 1 :]  # Get the last + 1 th item.
         else:
               __A			  =							self.lines[self.tag_count :]
         super().parse(suppress_parsing_errors=_UpperCamelCase					)




   def __str__(self      :Any					)->   Optional[int]:
         return str(self.to_dict()					)






   def _lowerCAmelCase (self      :List[Any]       ,  _UpperCamelCase      :Union[str, Any]					)->   Dict:
         __A			  =							[]
         __A			  =							[]
         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.
         __A			  =							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
               __A			  =							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
                     __A  ,		__A  ,		__A			  =							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

       snake_case__   :				Dict						=	ArgumentParser(usage='Validate the content (excluding YAML tags) of a README.md file.')
       ap.add_argument('readme_filepath')
       snake_case__   :				str						=	ap.parse_args()
       snake_case__   :				Union[str, Any]						=	Path(args.readme_filepath)
       snake_case__   :				List[Any]						=	ReadMe.from_readme(readme_filepath)












def _a							(      lowerCamelCase:  list					)      ->		list:







      '''simple docstring'''






      __A			  =							len(lowerCamelCase					)
      for cycle_start in range(0   ,							array_len - 1					):
            __A			  =							array[cycle_start]

            __A			  =							cycle_start
            for i in range(cycle_start + 1   ,							lowerCamelCase					):
                  if array[i] < item:
                        pos += 1

            if pos == cycle_start:
                  continue

            while item == array[pos]:
                  pos += 1

            __A  ,		__A			  =							item, array[pos]
            while pos != cycle_start:
                  __A			  =							cycle_start
                  for i in range(cycle_start + 1   ,							lowerCamelCase					):
                        if array[i] < item:
                              pos += 1

                  while item == array[pos]:
                        pos += 1

                  __A  ,		__A			  =							item, array[pos]

      return array


if __name__ == "__main__":
       assert cycle_sort([4, 5, 3, 2, 1]) == [1, 2, 3, 4, 5]
       assert cycle_sort([0, 1, -10, 15, 2, -2]) == [-10, -2, 0, 1, 2, 15]





