


'''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[Any]								=			F"""{BASE_REF_URL}/{__file__}"""
a__    :   Optional[Any]								=			logging.getLogger(__name__)







def _UpperCamelCase			(	__A       )				->						Tuple[Any, str]:


      '''simple docstring'''



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


a__					,					a__    :   Tuple								=			load_yaml_resource('readme_structure.yaml')

a__    :   int								=			[
    '[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__    :   Any								=			Tuple[dict, List[str], List[str]]
class    lowercase_	:


    def __init__(	self    ,   a    ,   a    ,   a = None    ,   a = False       ):
          UpperCamelCase__      =							name
          UpperCamelCase__      =							level
          UpperCamelCase__      =							lines
          UpperCamelCase__      =							""
          UpperCamelCase__      =							True
          UpperCamelCase__      =							{}
          UpperCamelCase__      =							[]
          UpperCamelCase__      =							[]
          if self.lines is not None:
                self.parse(suppress_parsing_errors=a       )


    def   __a				(	self    ,   a = 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(a    ,   self.level + "#"    ,   a       )
                            UpperCamelCase__      =							[]
                      else:
                            if current_lines != []:
                                  self.text += "".join(a       ).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(a       )
          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(a    ,   self.level + "#"    ,   a       )
                else:
                      if current_lines != []:
                            self.text += "".join(a       ).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(a       )


    def   __a				(	self    ,   a       ):
          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(a       ):
                            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   __a				(	self       ):
          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    lowercase_	(       a__  ):  # Level 0


    def __init__(	self    ,   a    ,   a    ,   a = None    ,   a = False       ):
          super().__init__(name=a    ,   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=a       )


    def   __a				(	self       ):
          if self.structure is None:
                UpperCamelCase__   ,      UpperCamelCase__   ,      UpperCamelCase__      =							self._validate(a       )
          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(a       )


    @classmethod
    def   __a				(	cls    ,   a    ,   a = None    ,   a = False       ):
          with open(a    ,   encoding="utf-8"       ) as f:
                UpperCamelCase__      =							f.readlines()
          return cls(a    ,   a    ,   a    ,   suppress_parsing_errors=a       )


    @classmethod
    def   __a				(	cls    ,   a    ,   a = None    ,   a = "root"    ,   a = False       ):
          UpperCamelCase__      =							string.split("\n"       )
          return cls(a    ,   a    ,   a    ,   suppress_parsing_errors=a       )


    def   __a				(	self    ,   a = 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=a       )


    def __str__(	self       ):
          return str(self.to_dict()       )


    def   __a				(	self    ,   a       ):
          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

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









'''simple docstring'''







from __future__ import annotations

from collections.abc import Callable
from typing import Generic, TypeVar

a__    :   Dict								=			TypeVar('T')
a__    :   Optional[Any]								=			TypeVar('U')
class    lowercase_	(       Generic[T, U]  ):


    def __init__(	self    ,   a    ,   a       ):
          UpperCamelCase__      =							key
          UpperCamelCase__      =							val
          UpperCamelCase__      =							0
          UpperCamelCase__      =							None
          UpperCamelCase__      =							None


    def __repr__(	self       ):
          return "Node: key: {}, val: {}, freq: {}, has next: {}, has prev: {}".format(
              self.key    ,   self.val    ,   self.freq    ,   self.next is not None    ,   self.prev is not None       )

class    lowercase_	(       Generic[T, U]  ):


    def __init__(	self       ):
          UpperCamelCase__      =							DoubleLinkedListNode(a    ,   a       )
          UpperCamelCase__      =							DoubleLinkedListNode(a    ,   a       )
          UpperCamelCase__   ,      UpperCamelCase__      =							self.rear, self.head


    def __repr__(	self       ):
          UpperCamelCase__      =							["DoubleLinkedList"]
          UpperCamelCase__      =							self.head
          while node.next is not None:
                rep.append(str(a       )       )
                UpperCamelCase__      =							node.next
          rep.append(str(self.rear       )       )
          return ",\n    ".join(a       )


    def   __a				(	self    ,   a       ):
          UpperCamelCase__      =							self.rear.prev

          # All nodes other than self.head are guaranteed to have non-None previous
          assert previous is not None

          UpperCamelCase__      =							node
          UpperCamelCase__      =							previous
          UpperCamelCase__      =							node
          UpperCamelCase__      =							self.rear
          node.freq += 1
          self._position_node(a       )


    def   __a				(	self    ,   a       ):

          while node.prev is not None and node.prev.freq > node.freq:
                # swap node with previous node
                UpperCamelCase__      =							node.prev

                UpperCamelCase__      =							previous_node.prev
                UpperCamelCase__      =							node.prev
                UpperCamelCase__      =							previous_node
                UpperCamelCase__      =							node


    def   __a				(	self    ,   a       ):

          if node.prev is None or node.next is None:
                return None

          UpperCamelCase__      =							node.next
          UpperCamelCase__      =							node.prev
          UpperCamelCase__      =							None
          UpperCamelCase__      =							None
          return node

class    lowercase_	(       Generic[T, U]  ):
    __UpperCAmelCase       =      {}


    def __init__(	self    ,   a       ):
          UpperCamelCase__      =							DoubleLinkedList()
          UpperCamelCase__      =							capacity
          UpperCamelCase__      =							0
          UpperCamelCase__      =							0
          UpperCamelCase__      =							0
          UpperCamelCase__      =							{}


    def __repr__(	self       ):
          return (
              f'''CacheInfo(hits={self.hits}, misses={self.miss}, '''
              f'''capacity={self.capacity}, current_size={self.num_keys})'''
          )


    def __contains__(	self    ,   a       ):
          return key in self.cache


    def   __a				(	self    ,   a       ):

          if key in self.cache:
                self.hits += 1
                UpperCamelCase__      =							self.cache[key]
                UpperCamelCase__      =							self.list.remove(self.cache[key]       )
                assert node == value_node

                # node is guaranteed not None because it is in self.cache
                assert node is not None
                self.list.add(a       )
                return node.val
          self.miss += 1
          return None


    def   __a				(	self    ,   a    ,   a       ):

          if key not in self.cache:
                if self.num_keys >= self.capacity:
                      # delete first node when over capacity
                      UpperCamelCase__      =							self.list.head.next

                      # guaranteed to have a non-None first node when num_keys > 0
                      # explain to type checker via assertions
                      assert first_node is not None
                      assert first_node.key is not None
                      assert self.list.remove(a       ) is not None
                      # first_node guaranteed to be in list

                      del self.cache[first_node.key]
                      self.num_keys -= 1
                UpperCamelCase__      =							DoubleLinkedListNode(a    ,   a       )
                self.list.add(self.cache[key]       )
                self.num_keys += 1

          else:
                UpperCamelCase__      =							self.list.remove(self.cache[key]       )
                assert node is not None  # node guaranteed to be in list
                UpperCamelCase__      =							value
                self.list.add(a       )


    @classmethod
    def   __a				(	cls    ,   a = 1_28       ):

          def cache_decorator_inner(a       ) -> Callable[..., U]:
                def cache_decorator_wrapper(*a       ) -> U:
                      if func not in cls.decorator_function_to_instance_map:
                            UpperCamelCase__      =							LFUCache(a       )

                      UpperCamelCase__      =							cls.decorator_function_to_instance_map[func].get(args[0]       )
                      if result is None:
                            UpperCamelCase__      =							func(*a       )
                            cls.decorator_function_to_instance_map[func].put(args[0]    ,   a       )
                      return result

                def cache_info() -> LFUCache[T, U]:
                      return cls.decorator_function_to_instance_map[func]

                setattr(a    ,   "cache_info"    ,   a       )  # noqa: B010

                return cache_decorator_wrapper

          return cache_decorator_inner


if __name__ == "__main__":
  import doctest

  doctest.testmod()





