o
    7?eG:                     @   s   d Z dZdgZddlmZ ddlZddlZddlmZm	Z	m
Z
mZmZ ddlmZmZ ddlmZmZmZmZmZ d	ZG d
d deeZG dd deZdS )zCUse the HTMLParser library to parse HTML files that aren't too bad.MITHTMLParserTreeBuilder    )
HTMLParserN)CDataCommentDeclarationDoctypeProcessingInstruction)EntitySubstitutionUnicodeDammit)DetectsXMLParsedAsHTMLParserRejectedMarkupHTMLHTMLTreeBuilderSTRICTzhtml.parserc                   @   s|   e Zd ZdZdZdZdd Zdd Zdd	 ZdddZ	dddZ
dd Zdd Zdd Zdd Zdd Zdd Zdd ZdS )BeautifulSoupHTMLParserzA subclass of the Python standard library's HTMLParser class, which
    listens for HTMLParser events and translates them into calls
    to Beautiful Soup's tree construction API.
    ignorereplacec                 O   s:   | d| j| _tj| g|R i | g | _|   dS )a  Constructor.

        :param on_duplicate_attribute: A strategy for what to do if a
            tag includes the same attribute more than once. Accepted
            values are: REPLACE (replace earlier values with later
            ones, the default), IGNORE (keep the earliest value
            encountered), or a callable. A callable must take three
            arguments: the dictionary of attributes already processed,
            the name of the duplicate attribute, and the most recent value
            encountered.           
        on_duplicate_attributeN)popREPLACEr   r   __init__already_closed_empty_elementZ_initialize_xml_detector)selfargskwargs r   X/home/www/facesmatcher.com/pyenv/lib/python3.10/site-packages/bs4/builder/_htmlparser.pyr   .   s   	z BeautifulSoupHTMLParser.__init__c                 C   s   t |)N)r   )r   messager   r   r   errorJ   s   zBeautifulSoupHTMLParser.errorc                 C   s   | j ||dd}| | dS )zHandle an incoming empty-element tag.

        This is only called when the markup looks like <tag/>.

        :param name: Name of the tag.
        :param attrs: Dictionary of the tag's attributes.
        F)handle_empty_elementN)handle_starttaghandle_endtag)r   nameattrstagr   r   r   handle_startendtagZ   s   z*BeautifulSoupHTMLParser.handle_startendtagTc                 C   s   i }|D ]0\}}|du rd}||v r.| j }|| jkrq2|d| jfv r'|||< q2|||| n|||< d}q|  \}	}
| jj|dd||	|
d}|r[|jr[|r[| j|dd | j	| | j
du rg| | dS dS )a3  Handle an opening tag, e.g. '<tag>'

        :param name: Name of the tag.
        :param attrs: Dictionary of the tag's attributes.
        :param handle_empty_element: True if this tag is known to be
            an empty-element tag (i.e. there is not expected to be any
            closing tag).
        N z"")
sourceline	sourceposF)check_already_closed)r   IGNOREr   getpossoupr!   Zis_empty_elementr"   r   appendZ	_root_tagZ_root_tag_encountered)r   r#   r$   r    	attr_dictkeyvalueZon_dupe	attrvaluer(   r)   r%   r   r   r   r!   i   s0   





z'BeautifulSoupHTMLParser.handle_starttagc                 C   s.   |r|| j v r| j | dS | j| dS )zHandle a closing tag, e.g. '</tag>'
        
        :param name: A tag name.
        :param check_already_closed: True if this tag is expected to
           be the closing portion of an empty-element tag,
           e.g. '<tag></tag>'.
        N)r   remover-   r"   )r   r#   r*   r   r   r   r"      s   	z%BeautifulSoupHTMLParser.handle_endtagc                 C   s   | j | dS )z4Handle some textual data that shows up between tags.N)r-   handle_datar   datar   r   r   r4      s   z#BeautifulSoupHTMLParser.handle_datac                 C   s   | drt|dd}n| drt|dd}nt|}d}|dk rN| jjdfD ]!}|s1q,z
t|g|}W q, tyM } zW Y d}~q,d}~ww |skzt|}W n t	t
fyj } zW Y d}~nd}~ww |pnd}| | dS )zHandle a numeric character reference by converting it to the
        corresponding Unicode character and treating it as textual
        data.

        :param name: Character number, possibly in hexadecimal.
        x   XN   zwindows-1252u   �)
startswithintlstripr-   original_encoding	bytearraydecodeUnicodeDecodeErrorchr
ValueErrorOverflowErrorr4   )r   r#   Z	real_namer6   encodinger   r   r   handle_charref   s2   

z&BeautifulSoupHTMLParser.handle_charrefc                 C   s0   t j|}|dur|}nd| }| | dS )zHandle a named entity reference by converting it to the
        corresponding Unicode character(s) and treating it as textual
        data.

        :param name: Name of the entity reference.
        Nz&%s)r
   ZHTML_ENTITY_TO_CHARACTERgetr4   )r   r#   	characterr6   r   r   r   handle_entityref   s
   z(BeautifulSoupHTMLParser.handle_entityrefc                 C   s&   | j   | j | | j t dS )zOHandle an HTML comment.

        :param data: The text of the comment.
        N)r-   endDatar4   r   r5   r   r   r   handle_comment   s   
z&BeautifulSoupHTMLParser.handle_commentc                 C   s6   | j   |tdd }| j | | j t dS )zYHandle a DOCTYPE declaration.

        :param data: The text of the declaration.
        zDOCTYPE N)r-   rK   lenr4   r   r5   r   r   r   handle_decl   s   
z#BeautifulSoupHTMLParser.handle_declc                 C   sN   |  drt}|tdd }nt}| j  | j| | j| dS )z{Handle a declaration of unknown type -- probably a CDATA block.

        :param data: The text of the declaration.
        zCDATA[N)upperr;   r   rM   r   r-   rK   r4   )r   r6   clsr   r   r   unknown_decl  s   
z$BeautifulSoupHTMLParser.unknown_declc                 C   s0   | j   | j | | | | j t dS )z\Handle a processing instruction.

        :param data: The text of the instruction.
        N)r-   rK   r4   Z_document_might_be_xmlr	   r5   r   r   r   	handle_pi  s   

z!BeautifulSoupHTMLParser.handle_piN)T)__name__
__module____qualname____doc__r+   r   r   r   r&   r!   r"   r4   rG   rJ   rL   rN   rQ   rR   r   r   r   r   r   $   s     

7(	
r   c                       sR   e Zd ZdZdZdZeZeee	gZ
dZd fdd	Z		dddZd	d
 Z  ZS )r   zpA Beautiful soup `TreeBuilder` that uses the `HTMLParser` parser,
    found in the Python standard library.
    FTNc                    sp   t  }dD ]}||v r||}|||< qtt| jdi | |p#g }|p'i }|| d|d< ||f| _dS )a  Constructor.

        :param parser_args: Positional arguments to pass into 
            the BeautifulSoupHTMLParser constructor, once it's
            invoked.
        :param parser_kwargs: Keyword arguments to pass into 
            the BeautifulSoupHTMLParser constructor, once it's
            invoked.
        :param kwargs: Keyword arguments for the superclass constructor.
        )r   Fconvert_charrefsNr   )dictr   superr   r   updateparser_args)r   r[   Zparser_kwargsr   Zextra_parser_kwargsargr1   	__class__r   r   r   *  s   

zHTMLParserTreeBuilder.__init__c           	      c   s^    t |tr|dddfV  dS |g}|g}||g}t|||d|d}|j|j|j|jfV  dS )a  Run any preliminary steps necessary to make incoming markup
        acceptable to the parser.

        :param markup: Some markup -- probably a bytestring.
        :param user_specified_encoding: The user asked to try this encoding.
        :param document_declared_encoding: The markup itself claims to be
            in this encoding.
        :param exclude_encodings: The user asked _not_ to try any of
            these encodings.

        :yield: A series of 4-tuples:
         (markup, encoding, declared encoding,
          has undergone character replacement)

         Each 4-tuple represents a strategy for converting the
         document to Unicode and parsing it. Each strategy will be tried 
         in turn.
        NFT)known_definite_encodingsuser_encodingsZis_htmlexclude_encodings)
isinstancestrr   markupr>   Zdeclared_html_encodingZcontains_replacement_characters)	r   rd   Zuser_specified_encodingZdocument_declared_encodingra   r_   r`   Ztry_encodingsZdammitr   r   r   prepare_markupC  s$   

z$HTMLParserTreeBuilder.prepare_markupc              
   C   sb   | j \}}t|i |}| j|_z|| W n ty' } zt|d}~ww |  g |_dS )z{Run some incoming markup through some parsing process,
        populating the `BeautifulSoup` object in self.soup.
        N)r[   r   r-   feedAssertionErrorr   closer   )r   rd   r   r   parserrF   r   r   r   rf   t  s   

zHTMLParserTreeBuilder.feed)NN)NNN)rS   rT   rU   rV   Zis_xmlZ	picklable
HTMLPARSERNAMEr   r   featuresZTRACKS_LINE_NUMBERSr   re   rf   __classcell__r   r   r]   r   r     s    

1)rV   __license____all__html.parserr   syswarningsZbs4.elementr   r   r   r   r	   Z
bs4.dammitr
   r   Zbs4.builderr   r   r   r   r   rj   r   r   r   r   r   r   <module>   s   	 z