
'''simple docstring'''





import html

from ...feature_extraction_utils import BatchFeature, FeatureExtractionMixin
from ...utils import is_bsa_available, logging, requires_backends


if is_bsa_available():
 import bsa
 from bsa import BeautifulSoup


_lowerCAmelCase										=     logging.get_logger(__name__)






class 	lowerCAmelCase_(    lowerCamelCase_					):
  '''simple docstring'''




  def __init__(   self  ,**__UpperCAmelCase				)   ->		Dict:
      requires_backends(self  ,["""bs4"""]				)
      super().__init__(**lowerCAmelCase__				)




  def 							UpperCAmelCase_     (   self  ,__UpperCAmelCase				)   ->		Dict:
      lowerCAmelCase__			:  Dict											= []
      lowerCAmelCase__			:  List[str]											= []
      lowerCAmelCase__			:  int											= element if element.name else element.parent
      for parent in child.parents:  # type: bs4.element.Tag
          lowerCAmelCase__			:  Tuple											= parent.find_all(child.name  ,recursive=lowerCAmelCase__				)
          xpath_tags.append(child.name				)
          xpath_subscripts.append(
              0 if 1 == len(lowerCAmelCase__				) else next(i for i, s in enumerate(lowerCAmelCase__  ,1				) if s is child				)				)
          lowerCAmelCase__			:  Any											= parent
      xpath_tags.reverse()
      xpath_subscripts.reverse()
      return xpath_tags, xpath_subscripts




  def 							UpperCAmelCase_     (   self  ,__UpperCAmelCase				)   ->		Optional[Any]:
      lowerCAmelCase__			:  Optional[int]											= BeautifulSoup(lowerCAmelCase__  ,"""html.parser"""				)

      lowerCAmelCase__			:  List[Any]											= []
      lowerCAmelCase__			:  Union[str, Any]											= []
      lowerCAmelCase__			:  str											= []

      for element in html_code.descendants:
          if type(lowerCAmelCase__				) == bsa.element.NavigableString:
              if type(element.parent				) != bsa.element.Tag:
                  continue

              lowerCAmelCase__			:  int											= html.unescape(lowerCAmelCase__				).strip()
              if not text_in_this_tag:
                  continue

              all_doc_strings.append(lowerCAmelCase__				)

              lowerCAmelCase__				,       lowerCAmelCase__			:  List[str]											= self.xpath_soup(lowerCAmelCase__				)
              stringaxtag_seq.append(lowerCAmelCase__				)
              stringaxsubs_seq.append(lowerCAmelCase__				)

      if len(lowerCAmelCase__				) != len(lowerCAmelCase__				):
          raise ValueError("""Number of doc strings and xtags does not correspond"""				)
      if len(lowerCAmelCase__				) != len(lowerCAmelCase__				):
          raise ValueError("""Number of doc strings and xsubs does not correspond"""				)

      return all_doc_strings, stringaxtag_seq, stringaxsubs_seq




  def 							UpperCAmelCase_     (   self  ,__UpperCAmelCase  ,__UpperCAmelCase				)   ->		List[Any]:
      lowerCAmelCase__			:  Optional[int]											= """"""
      for tagname, subs in zip(lowerCAmelCase__  ,lowerCAmelCase__				):
          xpath += F"""/{tagname}"""
          if subs != 0:
              xpath += F"""[{subs}]"""
      return xpath






  def __call__(   self  ,__UpperCAmelCase				)   ->		BatchFeature:
      lowerCAmelCase__			:  Any											= False

      # Check that strings has a valid type
      if isinstance(lowerCAmelCase__  ,lowerCAmelCase__				):
          lowerCAmelCase__			:  Optional[Any]											= True
      elif isinstance(lowerCAmelCase__  ,(list, tuple)				):
          if len(lowerCAmelCase__				) == 0 or isinstance(html_strings[0]  ,lowerCAmelCase__				):
              lowerCAmelCase__			:  Any											= True

      if not valid_strings:
          raise ValueError(
              """HTML strings must of type `str`, `List[str]` (batch of examples), """
              F"""but is of type {type(lowerCAmelCase__				)}."""				)

      lowerCAmelCase__			:  List[Any]											= bool(isinstance(lowerCAmelCase__  ,(list, tuple)				) and (isinstance(html_strings[0]  ,lowerCAmelCase__				))				)

      if not is_batched:
          lowerCAmelCase__			:  Union[str, Any]											= [html_strings]

      # Get nodes + xpaths
      lowerCAmelCase__			:  Optional[Any]											= []
      lowerCAmelCase__			:  Dict											= []
      for html_string in html_strings:
          lowerCAmelCase__				,       lowerCAmelCase__				,       lowerCAmelCase__			:  Optional[Any]											= self.get_three_from_single(lowerCAmelCase__				)
          nodes.append(lowerCAmelCase__				)
          lowerCAmelCase__			:  Optional[int]											= []
          for node, tag_list, sub_list in zip(lowerCAmelCase__  ,lowerCAmelCase__  ,lowerCAmelCase__				):
              lowerCAmelCase__			:  List[str]											= self.construct_xpath(lowerCAmelCase__  ,lowerCAmelCase__				)
              xpath_strings.append(lowerCAmelCase__				)
          xpaths.append(lowerCAmelCase__				)

      # return as Dict
      lowerCAmelCase__			:  Optional[int]											= {"""nodes""": nodes, """xpaths""": xpaths}
      lowerCAmelCase__			:  int											= BatchFeature(data=lowerCAmelCase__  ,tensor_type=lowerCAmelCase__				)

      return encoded_inputs







'''simple docstring'''





import copy
from dataclasses import dataclass
from pathlib import Path
from typing import Dict, Optional, Union






@dataclass
class 	lowerCAmelCase_:
  '''simple docstring'''




  __lowercase							:				Optional[Union[str, Path]]           =				None
  __lowercase							:				bool           =				False
  __lowercase							:				bool           =				False
  __lowercase							:				bool           =				False
  __lowercase							:				Optional[Dict]           =				None
  __lowercase							:				Optional[str]           =				None
  __lowercase							:				bool           =				False
  __lowercase							:				bool           =				False
  __lowercase							:				bool           =				False
  __lowercase							:				bool           =				True
  __lowercase							:				Optional[int]           =				None
  __lowercase							:				int           =				1
  __lowercase							:				Optional[Union[str, bool]]           =				None
  __lowercase							:				bool           =				False
  __lowercase							:				Optional[Dict]           =				None
  __lowercase							:				Optional[str]           =				None




  def 							UpperCAmelCase_     (   self				)   ->		"DownloadConfig":
      return self.__class__(**{k: copy.deepcopy(__UpperCAmelCase				) for k, v in self.__dict__.items()}				)


