o
    \hK:                     @   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_element_initialize_xml_detector)selfargskwargs r   Z/home/air/segue/gemini/backup/venv/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n|d| jfv r'|||< n|||| 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"   is_empty_elementr#   r   append	_root_tag_root_tag_encountered)r   r$   r%   r!   	attr_dictkeyvalue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   r9      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OverflowErrorr9   )r   r$   	real_namer;   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
   HTML_ENTITY_TO_CHARACTERgetr9   )r   r$   	characterr;   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.   endDatar9   r   r:   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.   rR   lenr9   r   r:   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   rT   r   r.   rR   r9   )r   r;   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.   rR   r9   _document_might_be_xmlr	   r:   r   r   r   	handle_pi  s   

z!BeautifulSoupHTMLParser.handle_piN)T)__name__
__module____qualname____doc__r,   r   r   r    r'   r"   r#   r9   rM   rQ   rS   rU   rX   rZ   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   rc   parser_kwargsr   extra_parser_kwargsargr5   	__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_encodingsis_htmlexclude_encodings)
isinstancestrr   markuprC   declared_html_encodingcontains_replacement_characters)	r   ro   user_specified_encodingdocument_declared_encodingrl   ri   rj   try_encodings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)rc   r   r.   feedcloseAssertionErrorr   r   )r   ro   r   r   parserrL   r   r   r   rw   t  s   


zHTMLParserTreeBuilder.feed)NN)NNN)r[   r\   r]   r^   is_xml	picklable
HTMLPARSERNAMEr   r   featuresTRACKS_LINE_NUMBERSr   rv   rw   __classcell__r   r   rg   r   r     s    

1)r^   __license____all__html.parserr   syswarningsbs4.elementr   r   r   r   r	   
bs4.dammitr
   r   bs4.builderr   r   r   r   r   r}   r   r   r   r   r   r   <module>   s   	 z