"""simple docstring"""




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 	UpperCAmelCase       (						UpperCamelCase__					):






							"""simple docstring"""





							A__						  =				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      UpperCamelCase__:





						def __init__(							self		,__UpperCAmelCase		,__UpperCAmelCase		,__UpperCAmelCase = None		,__UpperCAmelCase = False  )       ->					Optional[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 					snake_case__						(							self		,__UpperCAmelCase = False  )       ->					Optional[Any]:
													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 					snake_case__						(							self		,__UpperCAmelCase  )       ->					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 					snake_case__						(							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      UpperCamelCase__(      __A			):  # Level 0





						def __init__(							self		,__UpperCAmelCase		,__UpperCAmelCase		,__UpperCAmelCase = None		,__UpperCAmelCase = False  )       ->					List[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 					snake_case__						(							self  )       ->					Tuple:
													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 					snake_case__						(							cls		,__UpperCAmelCase		,__UpperCAmelCase = None		,__UpperCAmelCase = False  )       ->					List[str]:
													with open(__UpperCAmelCase		,encoding='utf-8'  ) as f:
																				A__						  =				f.readlines()
													return cls(__UpperCAmelCase		,__UpperCAmelCase		,__UpperCAmelCase		,suppress_parsing_errors=__UpperCAmelCase  )





						@classmethod
						def 					snake_case__						(							cls		,__UpperCAmelCase		,__UpperCAmelCase = None		,__UpperCAmelCase = "root"		,__UpperCAmelCase = False  )       ->					int:
													A__						  =				string.split('\n'  )
													return cls(__UpperCAmelCase		,__UpperCAmelCase		,__UpperCAmelCase		,suppress_parsing_errors=__UpperCAmelCase  )





						def 					snake_case__						(							self		,__UpperCAmelCase = False  )       ->					Optional[Any]:
													# 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  )       ->					Tuple:
													return str(self.to_dict()  )





						def 					snake_case__						(							self		,__UpperCAmelCase  )       ->					Tuple:
													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

				__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)






"""simple docstring"""




def 	UpperCAmelCase       (						UpperCamelCase__ = 100							,     UpperCamelCase__ = 100					):






							"""simple docstring"""





							return max(
							    sum(int(UpperCamelCase__					) for x in str(base**power					)					)
							    for base in range(UpperCamelCase__					)
							    for power in range(UpperCamelCase__					)					)


# Tests
if __name__ == "__main__":
				import doctest

				doctest.testmod()





