
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


lowercase        =  logging.get_logger(__name__)





class       __A(				UpperCAmelCase       ):

					def __init__(	self					:     Optional[Any]   ,					**__UpperCamelCase					:     Any   ):
												requires_backends(self   ,					["""bs4"""]   )
												super().__init__(**__UpperCamelCase   )

					def    lowercase__      (	self					:     Any   ,					__UpperCamelCase					:     Tuple   ):
												lowerCamelCase_							  =					[]
												lowerCamelCase_							  =					[]
												lowerCamelCase_							  =					element if element.name else element.parent
												for parent in child.parents:  # type: bs4.element.Tag
																			lowerCamelCase_							  =					parent.find_all(child.name   ,					recursive=__UpperCamelCase   )
																			xpath_tags.append(child.name   )
																			xpath_subscripts.append(
																			    0 if 1 == len(__UpperCamelCase   ) else next(i for i, s in enumerate(__UpperCamelCase   ,					1   ) if s is child   )   )
																			lowerCamelCase_							  =					parent
												xpath_tags.reverse()
												xpath_subscripts.reverse()
												return xpath_tags, xpath_subscripts

					def    lowercase__      (	self					:     Tuple   ,					__UpperCamelCase					:     str   ):
												lowerCamelCase_							  =					BeautifulSoup(__UpperCamelCase   ,					"""html.parser"""   )

												lowerCamelCase_							  =					[]
												lowerCamelCase_							  =					[]
												lowerCamelCase_							  =					[]

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

																										lowerCamelCase_							  =					html.unescape(__UpperCamelCase   ).strip()
																										if not text_in_this_tag:
																																	continue

																										all_doc_strings.append(__UpperCamelCase   )

																										lowerCamelCase_  ,   lowerCamelCase_							  =					self.xpath_soup(__UpperCamelCase   )
																										stringaxtag_seq.append(__UpperCamelCase   )
																										stringaxsubs_seq.append(__UpperCamelCase   )

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

												return all_doc_strings, stringaxtag_seq, stringaxsubs_seq

					def    lowercase__      (	self					:     str   ,					__UpperCamelCase					:     Optional[Any]   ,					__UpperCamelCase					:     int   ):
												lowerCamelCase_							  =					""""""
												for tagname, subs in zip(__UpperCamelCase   ,					__UpperCamelCase   ):
																			xpath += F'''/{tagname}'''
																			if subs != 0:
																										xpath += F'''[{subs}]'''
												return xpath



					def __call__(	self					:     Any   ,					__UpperCamelCase					:     int   ):
												lowerCamelCase_							  =					False

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

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

												lowerCamelCase_							  =					bool(isinstance(__UpperCamelCase   ,					(list, tuple)   ) and (isinstance(html_strings[0]   ,					__UpperCamelCase   ))   )

												if not is_batched:
																			lowerCamelCase_							  =					[html_strings]

												# Get nodes + xpaths
												lowerCamelCase_							  =					[]
												lowerCamelCase_							  =					[]
												for html_string in html_strings:
																			lowerCamelCase_  ,   lowerCamelCase_  ,   lowerCamelCase_							  =					self.get_three_from_single(__UpperCamelCase   )
																			nodes.append(__UpperCamelCase   )
																			lowerCamelCase_							  =					[]
																			for node, tag_list, sub_list in zip(__UpperCamelCase   ,					__UpperCamelCase   ,					__UpperCamelCase   ):
																										lowerCamelCase_							  =					self.construct_xpath(__UpperCamelCase   ,					__UpperCamelCase   )
																										xpath_strings.append(__UpperCamelCase   )
																			xpaths.append(__UpperCamelCase   )

												# return as Dict
												lowerCamelCase_							  =					{"""nodes""": nodes, """xpaths""": xpaths}
												lowerCamelCase_							  =					BatchFeature(data=__UpperCamelCase   ,					tensor_type=__UpperCamelCase   )

												return encoded_inputs







from ..utils import DummyObject, requires_backends





class       __A(				metaclass=UpperCAmelCase       ):
					SCREAMING_SNAKE_CASE			    =    ['''torch''', '''scipy''']

					def __init__(	self					:     Any   ,					*__UpperCamelCase					:     str   ,					**__UpperCamelCase					:     Any   ):
												requires_backends(self   ,					["""torch""", """scipy"""]   )

					@classmethod
					def    lowercase__      (	cls					:     Dict   ,					*__UpperCamelCase					:     str   ,					**__UpperCamelCase					:     Dict   ):
												requires_backends(cls   ,					["""torch""", """scipy"""]   )



					@classmethod
					def    lowercase__      (	cls					:     str   ,					*__UpperCamelCase					:     Optional[int]   ,					**__UpperCamelCase					:     Optional[int]   ):
												requires_backends(cls   ,					["""torch""", """scipy"""]   )





