B
    q\O                 @   s   d Z ddlZddlZddlZddlmZ dddgZejdd Zdd
dZ	e	Z
yddlmZ ejZ	W n ek
rx   Y nX ejdddZdd Zdd ZdS )z8
This module includes a fast iterator-based XML parser.
    N)dataget_xml_iteratorget_xml_encodingxml_readlinesc          	   c   sb   t | r| V  dS tj| dd8}tjdr8|jV  nt|tj	rL|V  n|jV  W dQ R X dS )a  
    Returns a function suitable for streaming input, or a file object.

    This function is only useful if passing off to C code where:

       - If it's a real file object, we want to use it as a real
         C file object to avoid the Python overhead.

       - If it's not a real file object, it's much handier to just
         have a Python function to call.

    This is somewhat quirky behavior, of course, which is why it is
    private.  For a more useful version of similar behavior, see
    `astropy.utils.misc.get_readable_fileobj`.

    Parameters
    ----------
    fd : object
        May be:

            - a file object.  If the file is uncompressed, this raw
              file object is returned verbatim.  Otherwise, the read
              method is returned.

            - a function that reads from a stream, in which case it is
              returned verbatim.

            - a file path, in which case it is opened.  Again, like a
              file object, if it's uncompressed, a raw file object is
              returned, otherwise its read method.

            - an object with a :meth:`read` method, in which case that
              method is returned.

    Returns
    -------
    fd : context-dependent
        See above.
    NZbinary)encodingwin)
callabler   get_readable_fileobjsysplatform
startswithread
isinstanceioFileIO)fdZnew_fd r   ;lib/python3.7/site-packages/astropy/utils/xml/iterparser.py_convert_to_fd_or_read_function   s    )
r      c       	      #   s   ddl m} t| s| j}n| }g g  fdd} fdd}|  d _| _| _j _	 j
}||}x8|r||d xD ]
}|V  qW d d = ||}qzW |d	d xD ]
}|V  qW d S )
Nr   )expatc                s(    d| | j jff d d = d S )NT)appendCurrentLineNumberCurrentColumnNumber)nameattr)parserqueuetextr   r   startT   s    
z_fast_iterparse.<locals>.startc                s(    d| d  j jff d S )NF )r   joinstripr   r   )r   )r   r   r   r   r   endY   s    z_fast_iterparse.<locals>.endTFr    )Zxml.parsersr   r   r   ZParserCreateZspecified_attributesZStartElementHandlerZEndElementHandlerr   ZCharacterDataHandlerParse)	r   Z
buffersizer   r   r   r#   r$   r   elemr   )r   r   r   r   _fast_iterparseI   s0    





r&      )_iterparserFc          	   c   s8   t | &}|rt|}nt|}t|V  W dQ R X dS )a  
    Returns an iterator over the elements of an XML file.

    The iterator doesn't ever build a tree, so it is much more memory
    and time efficient than the alternative in ``cElementTree``.

    Parameters
    ----------
    fd : readable file-like object or read function

    Returns
    -------
    parts : iterator

        The iterator returns 4-tuples (*start*, *tag*, *data*, *pos*):

            - *start*: when `True` is a start element event, otherwise
              an end element event.

            - *tag*: The name of the element

            - *data*: Depends on the value of *event*:

                - if *start* == `True`, data is a dictionary of
                  attributes

                - if *start* == `False`, data is a string containing
                  the text content of the element

            - *pos*: Tuple (*line*, *col*) indicating the source of the
              event.
    N)r   _slow_iterparser&   iter)sourceZ_debug_python_based_parserr   contextr   r   r   r   {   s
    "

c          	   C   sF   t | *}t|\}}}}|r&|dkr.tdW dQ R X |dpDdS )z
    Determine the encoding of an XML file by reading its header.

    Parameters
    ----------
    source : readable file-like object, read function or str path

    Returns
    -------
    encoding : str
    ZxmlzInvalid XML fileNr   zutf-8)r   nextOSErrorget)r+   iteratorr   tagr   posr   r   r   r      s
    
c          	   C   s8   t | }tj| |d}|d | }W dQ R X |S )a  
    Get the lines from a given XML file.  Correctly determines the
    encoding and always returns unicode.

    Parameters
    ----------
    source : readable file-like object, read function or str path

    Returns
    -------
    lines : list of unicode
    )r   r   N)r   r   r	   seek	readlines)r+   r   inputZ	xml_linesr   r   r   r      s
    
)r   )F)__doc__
contextlibr   r
   Zastropy.utilsr   __all__contextmanagerr   r&   r)   r    r(   Z
IterParserImportErrorr   r   r   r   r   r   r   <module>   s"   
7
*
)