




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


_lowerCamelCase			 =						'https://github.com/huggingface/datasets/tree/main/src/datasets/utils'
_lowerCamelCase			 =						F"{BASE_REF_URL}/{__file__}"
_lowerCamelCase			 =						logging.getLogger(__name__)




def 					SCREAMING_SNAKE_CASE	(       __UpperCamelCase			:						str      )  ->							Tuple[Any, str]:
    UpperCAmelCase_							 =     pkg_resources.read_text(__UpperCamelCase       ,     __UpperCamelCase      )
    return yaml.safe_load(__UpperCamelCase      ), f'{BASE_REF_URL}/resources/{resource}'


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

_lowerCamelCase			 =						[
    '[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
_lowerCamelCase			 =						Tuple[dict, List[str], List[str]]



class 			a     :

     '''simple docstring'''





     def __init__(	self   :			List[Any]					,    __snake_case   :			str					,    __snake_case   :			str					,    __snake_case   :			List[str] = None					,    __snake_case   :			bool = False				):
         UpperCAmelCase_							 =     name
         UpperCAmelCase_							 =     level
         UpperCAmelCase_							 =     lines
         UpperCAmelCase_							 =     ''''''
         UpperCAmelCase_							 =     True
         UpperCAmelCase_							 =     {}
         UpperCAmelCase_							 =     []
         UpperCAmelCase_							 =     []
         if self.lines is not None:
             self.parse(suppress_parsing_errors=__snake_case				)
     def   lowerCamelCase_   (	self   :			List[Any]					,    __snake_case   :			bool = False				):
         UpperCAmelCase_							 =     ''''''
         UpperCAmelCase_							 =     []
         UpperCAmelCase_							 =     False
         for line in self.lines:
             if line.strip(''' \n'''				) == "":
                 continue
             elif line.strip(''' \n'''				)[:3] == "```":
                 UpperCAmelCase_							 =     not code_start
             elif line.split()[0] == self.level + "#" and not code_start:
                 if current_sub_level != "":
                     UpperCAmelCase_							 =     Section(__snake_case					,    self.level + '''#'''					,    __snake_case				)
                     UpperCAmelCase_							 =     []
                 else:
                     if current_lines != []:
                         self.text += "".join(__snake_case				).strip()
                         if self.text != "" and self.text not in FILLER_TEXT:
                             UpperCAmelCase_							 =     False
                         UpperCAmelCase_							 =     []

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

         if self.level == "" and not suppress_parsing_errors:
             if self.parsing_error_list != [] or self.parsing_warning_list != []:
                 UpperCAmelCase_							 =     UpperCAmelCase_							 =     '''\n'''.join('''-\t''' + x for x in self.parsing_error_list + self.parsing_warning_list				)
                 UpperCAmelCase_							 =     F'The following issues were found while parsing the README at `{self.name}`:\n' + errors
                 raise ValueError(__snake_case				)
     def   lowerCamelCase_   (	self   :			Union[str, Any]					,    __snake_case   :			dict				):
         UpperCAmelCase_							 =     []
         UpperCAmelCase_							 =     []
         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
                 UpperCAmelCase_							 =     [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
                 UpperCAmelCase_							 =     [subsection['''name'''] for subsection in structure['''subsections''']]
                 UpperCAmelCase_							 =     False
                 for idx, name in enumerate(__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}`.'				)
                         UpperCAmelCase_							 =     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:
                             UpperCAmelCase_ ,							UpperCAmelCase_ ,							UpperCAmelCase_							 =     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   :			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     (   _A			):  # Level 0

     '''simple docstring'''





     def __init__(	self   :			Dict					,    __snake_case   :			str					,    __snake_case   :			List[str]					,    __snake_case   :			dict = None					,    __snake_case   :			bool = False				):
         super().__init__(name=__snake_case					,    level=''''''				)  # Not using lines here as we need to use a child class parse
         UpperCAmelCase_							 =     structure
         UpperCAmelCase_							 =     -2
         UpperCAmelCase_							 =     0
         UpperCAmelCase_							 =     lines
         if self.lines is not None:
             self.parse(suppress_parsing_errors=__snake_case				)
     def   lowerCamelCase_   (	self   :			Optional[Any]				):
         if self.structure is None:
             UpperCAmelCase_ ,							UpperCAmelCase_ ,							UpperCAmelCase_							 =     self._validate(__snake_case				)
         else:
             UpperCAmelCase_ ,							UpperCAmelCase_ ,							UpperCAmelCase_							 =     self._validate(self.structure				)
         if error_list != [] or warning_list != []:
             UpperCAmelCase_							 =     '''\n'''.join(['''-\t''' + x for x in error_list + warning_list]				)
             UpperCAmelCase_							 =     F'The following issues were found for the README at `{self.name}`:\n' + errors
             raise ValueError(__snake_case				)
     @classmethod
     def   lowerCamelCase_   (	cls   :			Dict					,    __snake_case   :			Path					,    __snake_case   :			dict = None					,    __snake_case   :			bool = False				):
         with open(__snake_case					,    encoding='''utf-8'''				) as f:
             UpperCAmelCase_							 =     f.readlines()
         return cls(__snake_case					,    __snake_case					,    __snake_case					,    suppress_parsing_errors=__snake_case				)
     @classmethod
     def   lowerCamelCase_   (	cls   :			Dict					,    __snake_case   :			str					,    __snake_case   :			dict = None					,    __snake_case   :			str = "root"					,    __snake_case   :			bool = False				):
         UpperCAmelCase_							 =     string.split('''\n'''				)
         return cls(__snake_case					,    __snake_case					,    __snake_case					,    suppress_parsing_errors=__snake_case				)
     def   lowerCamelCase_   (	self   :			Union[str, Any]					,    __snake_case   :			bool = False				):
         # Skip Tags
         UpperCAmelCase_							 =     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:
             UpperCAmelCase_							 =     self.lines[line_count + 1 :]  # Get the last + 1 th item.
         else:
             UpperCAmelCase_							 =     self.lines[self.tag_count :]
         super().parse(suppress_parsing_errors=__snake_case				)
     def __str__(	self   :			Optional[int]				):
         return str(self.to_dict()				)




     def   lowerCamelCase_   (	self   :			Optional[int]					,    __snake_case   :			Any				):
         UpperCAmelCase_							 =     []
         UpperCAmelCase_							 =     []
         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.
         UpperCAmelCase_							 =     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
             UpperCAmelCase_							 =     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
                 UpperCAmelCase_ ,							UpperCAmelCase_ ,							UpperCAmelCase_							 =     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

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











from __future__ import annotations

from enum import Enum, unique
from typing import TypeVar

# Create a generic variable that can be 'Enum', or any subclass.
_lowerCamelCase			 =						TypeVar('T', bound='Enum')



@unique
class 			a     (   _A			):

     '''simple docstring'''





     lowerCAmelCase				:       Optional[Any]   		=  80
     lowerCAmelCase				:       List[str]   		=  70
     lowerCAmelCase				:       Optional[Any]   		=  60
     lowerCAmelCase				:       Optional[Any]   		=  50
     lowerCAmelCase				:       List[Any]   		=  40
     lowerCAmelCase				:       Dict   		=  30
     lowerCAmelCase				:       List[Any]   		=  20
     lowerCAmelCase				:       List[Any]   		=  10



@unique
class 			a     (   _A			):

     '''simple docstring'''





     lowerCAmelCase				:       Dict   		=  24
     lowerCAmelCase				:       Union[str, Any]   		=  21
     lowerCAmelCase				:       Tuple   		=  18
     lowerCAmelCase				:       str   		=  15
     lowerCAmelCase				:       Dict   		=  12
     lowerCAmelCase				:       Dict   		=  9
     lowerCAmelCase				:       Tuple   		=  6
     lowerCAmelCase				:       Any   		=  3
     lowerCAmelCase				:       List[str]   		=  2
     lowerCAmelCase				:       Any   		=  1
     lowerCAmelCase				:       str   		=  -1
     lowerCAmelCase				:       Any   		=  -2
     lowerCAmelCase				:       List[str]   		=  -3
     lowerCAmelCase				:       Dict   		=  -6
     lowerCAmelCase				:       int   		=  -9
     lowerCAmelCase				:       Optional[Any]   		=  -12
     lowerCAmelCase				:       List[str]   		=  -15
     lowerCAmelCase				:       Any   		=  -18
     lowerCAmelCase				:       int   		=  -21
     lowerCAmelCase				:       Union[str, Any]   		=  -24
     @classmethod
     def   lowerCamelCase_   (	cls   :			type[T]				):
         return {unit.name: unit.value for unit in cls if unit.value > 0}




     @classmethod
     def   lowerCamelCase_   (	cls   :			type[T]				):
         return {unit.name: unit.value for unit in cls if unit.value < 0}




def 					SCREAMING_SNAKE_CASE	(       __UpperCamelCase			:						float      )  ->							str:
    UpperCAmelCase_							 =     SIUnit.get_positive() if value > 0 else SIUnit.get_negative()
    for name_prefix, value_prefix in prefixes.items():
        UpperCAmelCase_							 =     value / (10**value_prefix)
        if numerical_part > 1:
            return f'{numerical_part!s} {name_prefix}'
    return str(__UpperCamelCase      )




def 					SCREAMING_SNAKE_CASE	(       __UpperCamelCase			:						float      )  ->							str:
    for prefix in BinaryUnit:
        UpperCAmelCase_							 =     value / (2**prefix.value)
        if numerical_part > 1:
            return f'{numerical_part!s} {prefix.name}'
    return str(__UpperCamelCase      )


if __name__ == "__main__":
 import doctest

 doctest.testmod()





