



'''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


a  :     Dict       =       """https://github.com/huggingface/datasets/tree/main/src/datasets/utils"""
a  :     Optional[int]       =       F'''{BASE_REF_URL}/{__file__}'''
a  :     Tuple       =       logging.getLogger(__name__)



def  __lowerCamelCase    (   _lowercase						) ->     str:
							UpperCAmelCase	:						int					=						pkg_resources.read_text(lowerCAmelCase__      ,							lowerCAmelCase__						)
							return yaml.safe_load(lowerCAmelCase__						), F'''{BASE_REF_URL}/resources/{resource}'''


a    , a  :     List[Any]       =       load_yaml_resource("""readme_structure.yaml""")

a  :     str       =       [
    """[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
a  :     Dict       =       Tuple[dict, List[str], List[str]]

class      UpperCamelCase_					:





	def __init__(    self						,						A						,						A						,						A = None						,						A = False       )     ->     Optional[int]:
								UpperCAmelCase	:						str					=						name
								UpperCAmelCase	:						Optional[int]					=						level
								UpperCAmelCase	:						Union[str, Any]					=						lines
								UpperCAmelCase	:						Optional[int]					=						""""""
								UpperCAmelCase	:						List[str]					=						True
								UpperCAmelCase	:						int					=						{}
								UpperCAmelCase	:						Tuple					=						[]
								UpperCAmelCase	:						int					=						[]
								if self.lines is not None:
															self.parse(suppress_parsing_errors=__UpperCAmelCase       )





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

																						UpperCAmelCase	:						List[str]					=						""" """.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.'''       )
																						UpperCAmelCase	:						Tuple					=						Section(__UpperCAmelCase						,						self.level + """#"""						,						__UpperCAmelCase       )
															else:
																						if current_lines != []:
																													self.text += "".join(__UpperCAmelCase       ).strip()
																													if self.text != "" and self.text not in FILLER_TEXT:
																																				UpperCAmelCase	:						Dict					=						False

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





	def 					_lowercase(    self						,						A       )     ->     ReadmeValidatorOutput:
								UpperCAmelCase	:						Optional[Any]					=						[]
								UpperCAmelCase	:						int					=						[]
								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	:						Optional[Any]					=						[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	:						Any					=						[subsection["""name"""] for subsection in structure["""subsections"""]]
																						UpperCAmelCase	:						List[str]					=						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}`.'''       )
																																				UpperCAmelCase	:						str					=						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	:						Any					=						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 					_lowercase(    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_					(				__SCREAMING_SNAKE_CASE     ):  # Level 0





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





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





	@classmethod
	def 					_lowercase(    cls						,						A						,						A = None						,						A = False       )     ->     Union[str, Any]:
								with open(__UpperCAmelCase						,						encoding="""utf-8"""       ) as f:
															UpperCAmelCase	:						List[str]					=						f.readlines()
								return cls(__UpperCAmelCase						,						__UpperCAmelCase						,						__UpperCAmelCase						,						suppress_parsing_errors=__UpperCAmelCase       )





	@classmethod
	def 					_lowercase(    cls						,						A						,						A = None						,						A = "root"						,						A = False       )     ->     str:
								UpperCAmelCase	:						Any					=						string.split("""\n"""       )
								return cls(__UpperCAmelCase						,						__UpperCAmelCase						,						__UpperCAmelCase						,						suppress_parsing_errors=__UpperCAmelCase       )





	def 					_lowercase(    self						,						A = False       )     ->     List[str]:
								UpperCAmelCase	:						str					=						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	:						int					=						self.lines[line_count + 1 :]  # Get the last + 1 th item.
								else:
															UpperCAmelCase	:						int					=						self.lines[self.tag_count :]
								super().parse(suppress_parsing_errors=__UpperCAmelCase       )





	def __str__(    self       )     ->     Any:
								return str(self.to_dict()       )






	def 					_lowercase(    self						,						A       )     ->     str:
								UpperCAmelCase	:						Optional[Any]					=						[]
								UpperCAmelCase	:						Optional[int]					=						[]
								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	:						Union[str, Any]					=						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[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
																						UpperCAmelCase	:						Tuple					=						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

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






'''simple docstring'''
from __future__ import annotations


def 	lowercase_						( lowerCAmelCase__						:	int      ,				lowerCAmelCase__						:	int      ,				lowerCAmelCase__						:	int			):

			"""simple docstring"""





			assert (
			    c % greatest_common_divisor(lowerCAmelCase__      ,				lowerCAmelCase__			) == 0
			)  # greatest_common_divisor(a,b) function implemented below
			((__UpperCAmelCase)					,	(__UpperCAmelCase)					,	(__UpperCAmelCase)) :   int    					=  extended_gcd(lowerCAmelCase__      ,				lowerCAmelCase__			)  # extended_gcd(a,b) function implemented below
			__UpperCAmelCase :   Union[str, Any]    					=  c / d
			return (r * x, r * y)


def 	lowercase_						( lowerCAmelCase__						:	int      ,				lowerCAmelCase__						:	int      ,				lowerCAmelCase__						:	int      ,				lowerCAmelCase__						:	int = 2			):

			"""simple docstring"""





			((__UpperCAmelCase)					,	(__UpperCAmelCase)) :   List[str]    					=  diophantine(lowerCAmelCase__      ,				lowerCAmelCase__      ,				lowerCAmelCase__			)  # Initial value
			__UpperCAmelCase :   List[str]    					=  greatest_common_divisor(lowerCAmelCase__      ,				lowerCAmelCase__			)
			__UpperCAmelCase :   List[str]    					=  a // d
			__UpperCAmelCase :   Tuple    					=  b // d

			for i in range(lowerCAmelCase__			):
						__UpperCAmelCase :   List[Any]    					=  xa + i * q
						__UpperCAmelCase :   Tuple    					=  ya - i * p
						print(lowerCAmelCase__      ,				lowerCAmelCase__			)


def 	lowercase_						( lowerCAmelCase__						:	int      ,				lowerCAmelCase__						:	int			):

			"""simple docstring"""





			if a < b:
						__UpperCAmelCase					,	__UpperCAmelCase :   List[str]    					=  b, a

			while a % b != 0:
						__UpperCAmelCase					,	__UpperCAmelCase :   Optional[int]    					=  b, a % b

			return b


def 	lowercase_						( lowerCAmelCase__						:	int      ,				lowerCAmelCase__						:	int			):

			"""simple docstring"""





			assert a >= 0 and b >= 0

			if b == 0:
						__UpperCAmelCase					,	__UpperCAmelCase					,	__UpperCAmelCase :   List[str]    					=  a, 1, 0
			else:
						((__UpperCAmelCase)					,	(__UpperCAmelCase)					,	(__UpperCAmelCase)) :   str    					=  extended_gcd(lowerCAmelCase__      ,				a % b			)
						__UpperCAmelCase :   Optional[Any]    					=  q
						__UpperCAmelCase :   Dict    					=  p - q * (a // b)

			assert a % d == 0 and b % d == 0
			assert d == a * x + b * y

			return (d, x, y)


if __name__ == "__main__":
					from doctest import testmod

					testmod(name='''diophantine''', verbose=True)
					testmod(name='''diophantine_all_soln''', verbose=True)
					testmod(name='''extended_gcd''', verbose=True)
					testmod(name='''greatest_common_divisor''', verbose=True)




