B
    d|                 @   s  d Z ddlZddlZddlZddlmZ ddlmZ ddl	m
Z ddl	mZ ddlmZmZmZ dd	lmZ ddlZdd
lmZ dZde ZdZG dd deZG dd deZG dd deZG dd deZ dd Z!G dd dej"Z#G dd de Z$G dd deZ%G dd deZ&G d d! d!e Z'G d"d# d#e Z(G d$d% d%e Z)G d&d' d'eZ*G d(d) d)eZ+G d*d+ d+e Z,G d,d- d-e Z-G d.d/ d/e Z.G d0d1 d1e Z/G d2d3 d3eZ0G d4d5 d5e Z1G d6d7 d7ej2j3eZ4G d8d9 d9e4Z5G d:d; d;e4Z6d<d= Z7dS )>a2  
This module provides class definitions corresponding to the elements that
can be found in a LIGO Light Weight XML file.  It also provides a class
representing an entire LIGO Light Weight XML document, a ContentHandler
class for use with SAX2 parsers, and a convenience function for
constructing a parser.
    N)sax)AttributesImpl)escape)unescape   )
__author____date____version__)types)reducezAhttp://ldas-sw.ligo.caltech.edu/doc/ligolwAPI/html/ligolw_dtd.txtzE<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE LIGO_LW SYSTEM "%s">	c               @   s   e Zd ZdZdS )ElementErrorz4
	Base class for exceptions generated by elements.
	N)__name__
__module____qualname____doc__ r   r   [/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/ligo/lw/ligolw.pyr   O   s   r   c                   s:   e Zd ZdZejejddf fdd	Zedd Z  Z	S )attributeproxyaw	  
	Expose an XML attribute of an Element subclass as Python instance
	attribute with support for an optional default value.

	The .getAttribute() and .setAttribute() methods of the instance to
	which this is attached are used to retrieve and set the unicode
	attribute value, respectively.

	When retrieving a value, the function given via the dec keyword
	argument will be used to convert the unicode into a native Python
	object (the default is to leave the unicode value as unicode).
	When setting a value, the function given via the enc keyword
	argument will be used to convert a native Python object to a
	unicode string.

	When retrieving a value, if .getAttribute() raises KeyError then
	AttributeError is raised unless a default value is provided in
	which case it is returned instead.

	If doc is provided it will be used as the documentation string,
	otherwise a default documentation string will be constructed
	identifying the attribute's name and explaining the default value
	if one is set.

	NOTE:  If an XML document is parsed and an element is encountered
	that does not have a value set for an attribute whose corresponding
	attributeproxy has a default value defined, then Python codes will
	be told the default value.  Therefore, the default value given here
	must match what the XML DTD says the default value is for that
	attribute.  Likewise, attributes for which the DTD does not define
	a default must not have a default defined here.  These conditions
	must both be met to not create a discrepancy between the behaviour
	of Python codes relying on this I/O library and other interfaces to
	the same document.

	Example:

	>>> class Test(Element):
	...	Scale = attributeproxy(u"Scale", enc = u"%.17g".__mod__, dec = float, default = 1.0, doc = "This is the scale (default = 1).")
	...
	>>> x = Test()
	>>> # have not set value, default will be returned
	>>> x.Scale
	1.0
	>>> x.Scale = 16
	>>> x.Scale
	16.0
	>>> # default can be retrieved via the .default attribute of the
	>>> # class attribute
	>>> Test.Scale.default
	1.0
	>>> # default is read-only
	>>> Test.Scale.default = 2.
	Traceback (most recent call last):
	  File "<stdin>", line 1, in <module>
	AttributeError: can't set attribute
	>>> # internally, value is stored as unicode (for XML)
	>>> assert x.getAttribute("Scale") == "16"
	>>> # deleting an attribute restores the default value if defined
	>>> del x.Scale
	>>> x.Scale
	1.0
	Nc       	         s    fdd}fdd}fdd}|d krRd }d k	rR|dt  7 }tt| |d k	rj|nd d k	rx|nd | || _d k	r| _d S )	Nc                sD   y|  }W n, tk
r:   d k	r*S td Y nX  |S )Nzattribute '%s' is not set)getAttributeKeyErrorAttributeError)selfval)decdefaultnamer   r   getter   s    z'attributeproxy.__init__.<locals>.getterc                s   |   | d S )N)setAttribute)r   value)encr   r   r   setter   s    z'attributeproxy.__init__.<locals>.setterc                s   |    d S )N)removeAttribute)r   )r   r   r   deleter   s    z(attributeproxy.__init__.<locals>.deleterzThe "%s" attribute.z  Default is "%s" if not set.)strsuperr   __init__r   _default)	r   r   r    r   r   docr   r!   r#   )	__class__)r   r   r    r   r   r&      s    .zattributeproxy.__init__c             C   s   | j S )zL
		Default value.  AttributeError is raised if no default
		value is set.
		)r'   )r   r   r   r   r      s    zattributeproxy.default)
r   r   r   r   six	text_typer&   propertyr   __classcell__r   r   )r)   r   r   V   s   ?r   c               @   s   e Zd ZdZdZe Ze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d Z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'd( Zejd)fd*d+ZdS )-Elementa  
	Base class for all element types.  This class is inspired by the
	class of the same name in the Python standard library's xml.dom
	package.  One important distinction is that the standard DOM
	element is used to represent the structure of a document at a much
	finer level of detail than here.  For example, in the case of the
	standard DOM element, each XML attribute is its own element being a
	child node of its tag, while here they are simply stored as
	attributes of the tag element itself.

	Despite the differences, the documentation for the xml.dom package,
	particularly that of the Element class and it's parent, the Node
	class, is useful as supplementary material in understanding how to
	use this class.
	Nc                s   t  fddt D S )Nc             3   s"   | ]}t t |tr|V  qd S )N)
isinstancegetattrr   ).0r   )clsr   r   	<genexpr>   s    z*Element.validattributes.<locals>.<genexpr>)	frozensetdir)r2   r   )r2   r   validattributes   s    zElement.validattributesc          	   C   sx   d| _ |dkrti | _nNt| |  kr6|| _n2td| jddd t| |   D f g | _	d| _
dS )z
		Construct an element.  The argument is a
		sax.xmlreader.AttributesImpl object (see the xml.sax
		documentation, but it's basically a dictionary-like thing)
		used to set the element attributes.
		Nz#%s element: invalid attribute(s) %sz, c             s   s   | ]}d | V  qdS )z'%s'Nr   )r1   keyr   r   r   r3      s    z#Element.__init__.<locals>.<genexpr>)
parentNoder   
attributessetkeysr6   r   tagNamejoin
childNodespcdata)r   attrsr   r   r   r&      s    2zElement.__init__c             C   s&   d|| j ddd | j D f S )z6
		Generate the string for the element's start tag.
		z%s<%s%s> c             s   s   | ]}d | V  qdS )z %s="%s"Nr   )r1   keyvaluer   r   r   r3      s    z$Element.start_tag.<locals>.<genexpr>)r<   r=   r9   items)r   indentr   r   r   	start_tag   s    zElement.start_tagc             C   s   d|| j f S )z4
		Generate the string for the element's end tag.
		z%s</%s>)r<   )r   rD   r   r   r   end_tag   s    zElement.end_tagc             C   s*   | j | | |_| t| j d  |S )zW
		Add a child to this element.  The child's parentNode
		attribute is updated, too.
		r   )r>   appendr8   _verifyChildrenlen)r   childr   r   r   appendChild   s    zElement.appendChildc             C   sN   x@t | jD ]2\}}||kr| j|| | |_| | |S qW t|dS )z
		Insert a new child node before an existing child. It must
		be the case that refchild is a child of this node; if not,
		ValueError is raised. newchild is returned.
		N)	enumerater>   insertr8   rH   
ValueError)r   newchildZrefchildi	childNoder   r   r   insertBefore   s    
zElement.insertBeforec             C   s>   x0t | jD ]"\}}||kr| j|= d|_|S qW t|dS )z
		Remove a child from this element.  The child element is
		returned, and it's parentNode element is reset.  If the
		child will not be used any more, you should call its
		unlink() method to promote garbage collection.
		N)rL   r>   r8   rN   )r   rJ   rP   rQ   r   r   r   removeChild
  s    zElement.removeChildc             C   s.   d| _ x| jD ]}|  qW | jdd= dS )zp
		Break internal references within the document tree rooted
		on this element to promote garbage collection.
		N)r8   r>   unlink)r   rJ   r   r   r   rT     s    zElement.unlinkc             C   sP   xBt | jD ]4\}}||krd|_|| j|< | |_| | |S qW t|dS )z
		Replace an existing node with a new node. It must be the
		case that oldchild is a child of this node; if not,
		ValueError is raised. newchild is returned.
		N)rL   r>   r8   rH   rN   )r   rO   ZoldchildrP   rQ   r   r   r   replaceChild"  s    	

zElement.replaceChildc                s,   t  fdd| jg } | r(||  |S )zj
		Return a list of elements below and including this element
		for which filter(element) returns True.
		c                s   | |   S )N)getElements)le)filterr   r   <lambda>9      z%Element.getElements.<locals>.<lambda>)r   r>   rG   )r   rY   rW   r   )rY   r   rV   4  s    
zElement.getElementsc                s   |   fddS )Nc                s
   | j  kS )N)r<   )rX   )r<   r   r   rZ   ?  r[   z.Element.getElementsByTagName.<locals>.<lambda>)rV   )r   r<   r   )r<   r   getElementsByTagName>  s    zElement.getElementsByTagNamec          	      s^   g }t | }xH| jD ]> y$t fdd|D r>|  W q tk
rT   Y qX qW |S )Nc             3   s    | ]\}}  ||kV  qd S )N)r   )r1   r   r   )cr   r   r3   F  s    z2Element.getChildrenByAttributes.<locals>.<genexpr>)tuplerC   r>   allrG   r   )r   r@   rW   r   )r]   r   getChildrenByAttributesA  s    
zElement.getChildrenByAttributesc             C   s
   || j kS )N)r9   )r   attrnamer   r   r   hasAttributeL  s    zElement.hasAttributec             C   s
   | j | S )N)r9   )r   ra   r   r   r   r   O  s    zElement.getAttributec             C   s   t || jj|< d S )N)r*   r+   r9   _attrs)r   ra   r   r   r   r   r   R  s    zElement.setAttributec             C   s(   y| j j|= W n tk
r"   Y nX d S )N)r9   rc   r   )r   ra   r   r   r   r"   Y  s    zElement.removeAttributec             C   s$   | j dk	r|  j |7  _ n|| _ dS )z-
		Add characters to the element's pcdata.
		N)r?   )r   contentr   r   r   
appendDatac  s    
zElement.appendDatac             C   s   dS )z
		Method used internally by some elements to verify that
		their children are from the allowed set and in the correct
		order following modifications to their child list.  i is
		the index of the child that has just changed.
		Nr   )r   rP   r   r   r   rH   l  s    zElement._verifyChildrenc             C   s   dS )zV
		Method invoked by document parser when it encounters the
		end-of-element event.
		Nr   )r   r   r   r   
endElementu  s    zElement.endElementrA   c             C   s   | | | | d x>| jD ]4}|j| jkrFtd|j| jf | ||t  q"W | jdk	r~| t| j | d | | 	| | d dS )z?
		Recursively write an element and it's children to a file.
		
zinvalid child %s for %sN)
writerE   r>   r<   validchildrenr   Indentr?   	xmlescaperF   )r   fileobjrD   r]   r   r   r   rh   |  s    


zElement.write)N)r   r   r   r   r<   r4   ri   classmethodr6   r&   rE   rF   rK   rR   rS   rT   rU   rV   r\   r`   rb   r   r   r"   re   rH   rf   sysstdoutrh   r   r   r   r   r.      s.   




		r.   c               @   s   e Zd ZdZdd ZdS )EmptyElementz7
	Parent class for Elements that cannot contain text.
	c             C   s   |  stdt|  d S )Nz%s does not hold text)isspace	TypeErrortype)r   rd   r   r   r   re     s    zEmptyElement.appendDataN)r   r   r   r   re   r   r   r   r   rp     s   rp   c             c   s2   x,| j D ]"}|V  xt|D ]
} | V  qW qW dS )zF
	Walk the XML tree of children below elem, returning each in order.
	N)r>   WalkChildren)elemrJ   r   r   r   rt     s    rt   c               @   s$   e Zd ZdZdd Zedd ZdS )LLWNameAttra?  
	Baseclass to hide pattern-matching of various element names.
	Subclasses must provide a .dec_pattern compiled regular expression
	defining a group "Name" that identifies the meaningful portion of
	the string, and a .enc_pattern that gives a format string to be
	used with "%" to reconstrct the full string.

	This is intended to be used to provide the enc and dec functions
	for an attributeproxy instance.

	Example:

	>>> import re
	>>> class Test(Element):
	...	class TestName(LLWNameAttr):
	...		dec_pattern = re.compile(r"(?P<Name>[a-z0-9_]+):test\Z")
	...		enc_pattern = u"%s:test"
	...
	...	Name = attributeproxy(u"Name", enc = TestName.enc, dec = TestName)
	...
	>>> x = Test()
	>>> x.Name = u"blah"
	>>> # internally, suffix has been appended
	>>> print(x.getAttribute("Name"))
	blah:test
	>>> # but attributeproxy reports original value
	>>> print(x.Name)
	blah
	>>> # only lower-case Latin letters, numerals, and '_' are allowed
	>>> x.Name = u"Hello-world"
	Traceback (most recent call last):
	  File "<stdin>", line 1, in <module>
	ValueError: invalid Name 'Hello-world'
	c             C   s0   y| j |d}W n tk
r*   Y nX |S )NName)Zdec_patternsearchgroupr   )r2   r   r   r   r   __new__  s
    zLLWNameAttr.__new__c             C   s&   | j | }| ||kr"td| |S )Nzinvalid Name '%s')Zenc_patternrN   )r2   r   sr   r   r   r      s    
zLLWNameAttr.encN)r   r   r   r   rz   rm   r    r   r   r   r   rv     s   "rv   c               @   sP   e Zd ZdZd Zed dddddddd	d
dgZedZedZ	e
dddZdS )LIGO_LWz
	LIGO_LW element.
	CommentParamTableArrayStream	IGWDFrameAdcDataAdcIntervalTimeDetectorrw   TypeNc                s\   | | j} dk	r& fdd|D }t|dkrTtd| j dk	rJd  ndf |d S )	z
		Scan xmldoc for a LIGO_LW element with .Name name.  Raises
		ValueError if not exactly 1 such element is found.  If name
		is None (default), then all LIGO_LW elements are considered
		to match (it is still an error if there is not exactly 1).
		Nc                s$   g | ]}| d r|j kr|qS )rw   )rb   rw   )r1   ru   )r   r   r   
<listcomp>  s    z'LIGO_LW.get_ligo_lw.<locals>.<listcomp>r   z.document must contain exactly one %s element%sz	 named %srA   r   )r\   r<   rI   rN   )r2   Zxmldocr   Zelemsr   )r   r   get_ligo_lw  s    "zLIGO_LW.get_ligo_lw)N)r   r   r   r   r<   r4   ri   r   rw   r   rm   r   r   r   r   r   r|     s   r|   c               @   s$   e Zd ZdZd ZejdfddZdS )r}   z
	Comment element.
	rA   c             C   sH   | | | | jd k	r*| t| j | | d | d d S )NrA   rg   )rh   rE   r?   rk   rF   )r   rl   rD   r   r   r   rh     s
    
zComment.writeN)r   r   r   r   r<   rn   ro   rh   r   r   r   r   r}     s   r}   c               @   sN   e Zd ZdZd ZedgZedZedZ	edZ
edZedZedZd	S )
r~   z
	Param element.
	r}   DataUnitrw   ScaleStartr   UnitN)r   r   r   r   r<   r4   ri   r   r   rw   r   r   r   r   r   r   r   r   r~     s   
r~   c               @   s:   e Zd ZdZd ZedddgZedZedZ	dd Z
d	S )
r   z
	Table element.
	r}   Columnr   rw   r   c             C   s   d}d}d}xv| j D ]l}|jtjkrJ|r0td|s8|r@td|d7 }q|jtjkrl|rbtd|d7 }q|rxtd|d7 }qW d S )Nr   z!only one Comment allowed in Tablez6Comment must come before Column(s) and Stream in Tabler   z*Column(s) must come before Stream in Tablez only one Stream allowed in Table)r>   r<   r}   r   r   )r   rP   ZncommentZncolumnnstreamrJ   r   r   r   rH   &  s"    

zTable._verifyChildrenN)r   r   r   r   r<   r4   ri   r   rw   r   rH   r   r   r   r   r     s   r   c               @   sL   e Zd ZdZd ZedZedZedZdd Z	dd Z
ejd	fd
dZdS )r   z
	Column element.
	rw   r   r   c             C   s&   d|| j ddd | j D f S )z6
		Generate the string for the element's start tag.
		z	%s<%s%s/>rA   c             s   s   | ]}d | V  qdS )z %s="%s"Nr   )r1   rB   r   r   r   r3   I  s    z#Column.start_tag.<locals>.<genexpr>)r<   r=   r9   rC   )r   rD   r   r   r   rE   E  s    zColumn.start_tagc             C   s   dS )z4
		Generate the string for the element's end tag.
		rA   r   )r   rD   r   r   r   rF   K  s    zColumn.end_tagrA   c             C   s   | | | | d dS )z?
		Recursively write an element and it's children to a file.
		rg   N)rh   rE   )r   rl   rD   r   r   r   rh   Q  s    zColumn.writeN)r   r   r   r   r<   r   rw   r   r   rE   rF   rn   ro   rh   r   r   r   r   r   ;  s   r   c               @   s@   e Zd ZdZd ZeddgZedZedZ	edZ
dd Zd	S )
r   z
	Array element.
	Dimr   rw   r   r   c             C   sF   d}x<| j D ]2}|jtjkr*|r>tdq|r6td|d7 }qW d S )Nr   z'Dim(s) must come before Stream in Arrayz only one Stream allowed in Arrayr   )r>   r<   r   r   )r   rP   r   rJ   r   r   r   rH   d  s    
zArray._verifyChildrenN)r   r   r   r   r<   r4   ri   r   rw   r   r   rH   r   r   r   r   r   Y  s   r   c               @   s   e Zd ZdZd ZedZedejd ej	d dZ
edejd ej	d dZedZedd	 Zejd
d	 Zejdd	 ZejdfddZdS )r   z
	Dim element.
	rw   r   real_8)r    r   r   r   c             C   s   | j d k	rtjd | j S d S )Nint_8s)r?   ligolwtypesToPyType)r   r   r   r   n{  s    zDim.nc             C   s    |d k	rt jd |nd | _d S )Nr   )r   
FormatFuncr?   )r   r   r   r   r   r     s    c             C   s
   d | _ d S )N)r?   )r   r   r   r   r     s    rA   c             C   sH   | | | | jd k	r*| t| j | | d | d d S )NrA   rg   )rh   rE   r?   rk   rF   )r   rl   rD   r   r   r   rh     s
    
z	Dim.writeN)r   r   r   r   r<   r   rw   r   r   r   r   r   r   r,   r   r!   r#   rn   ro   rh   r   r   r   r   r   p  s   r   c                   sT   e Zd ZdZd ZedZedddZedZedZ	edd	dZ
 fd
dZ  ZS )r   z
	Stream element.
	Content	Delimiter,)r   Encodingrw   r   Localc                s,   t t| j|  | jdkr(td| j d S )N)ZRemoter   zinvalid Type for Stream: '%s')r%   r   r&   r   r   )r   args)r)   r   r   r&     s    
zStream.__init__)r   r   r   r   r<   r   r   r   r   rw   r   r&   r-   r   r   )r)   r   r     s   r   c            
   @   s6   e Zd ZdZd Zedddddddd	d g	Zed
ZdS )r   z
	IGWDFrame element.
	r}   r~   r   r   r   r|   r   r   rw   N)	r   r   r   r   r<   r4   ri   r   rw   r   r   r   r   r     s   r   c               @   s*   e Zd ZdZd ZedddgZedZdS )r   z
	Detector element.
	r}   r~   r|   rw   N)	r   r   r   r   r<   r4   ri   r   rw   r   r   r   r   r     s   r   c               @   s0   e Zd ZdZd Zed dddddgZedZdS )	r   z
	AdcData element.
	r}   r~   r   r|   r   rw   N)	r   r   r   r   r<   r4   ri   r   rw   r   r   r   r   r     s   r   c               @   sL   e Zd ZdZd ZedddgZedej	d ej
d dZedZed	Zd
S )r   z
	AdcInterval element.
	r   r}   r   DeltaTr   )r    r   rw   	StartTimeN)r   r   r   r   r<   r4   ri   r   r   r   r   r   rw   r   r   r   r   r   r     s   r   c                   sl   e Zd ZdZd ZedZedddZ fddZdd	 Z	e
jd
fddZedddZedddZ  ZS )r   z
	Time element.
	rw   r   zISO-8601)r   c                s.   t t| j|  | jtjkr*td| j d S )Nzinvalid Type for Time: '%s')r%   r   r&   r   r   Z	TimeTypesr   )r   r   )r)   r   r   r&     s    zTime.__init__c             C   s`   | j dkrtj| j| _n@| j dkrDddlm} |t| j| _n| j dkr\t| j| _n d S )NzISO-8601GPSr   )LIGOTimeGPSUnix)	r   dateutilparserparser?   Zlalr   r$   float)r   r   r   r   r   rf     s    


zTime.endElementrA   c             C   s   | | | | jd k	r| jdkr@| tt| j  nX| jdkrb| tt| j n6| jdkr| td| j  n| tt| j | | d | d d S )NzISO-8601r   r   z%.16grA   rg   )	rh   rE   r?   r   rk   r*   r+   	isoformatrF   )r   rl   rD   r   r   r   rh     s    



z
Time.writeNc             C   s$   |  }|dk	r||_ tj |_|S )z
		Instantiate a Time element initialized to the current UTC
		time in the default format (ISO-8601).  The Name attribute
		will be set to the value of the Name parameter if given.
		N)rw   datetimeutcnowr?   )r2   rw   r   r   r   r   now  s
    zTime.nowc             C   s(   | t ddi}|dk	r||_||_|S )aY  
		Instantiate a Time element initialized to the value of the
		given GPS time.  The Name attribute will be set to the
		value of the Name parameter if given.

		Note:  the new Time element holds a reference to the GPS
		time, not a copy of it.  Subsequent modification of the GPS
		time object will be reflected in what gets written to disk.
		r   r   N)r   rw   r?   )r2   Zgpsrw   r   r   r   r   from_gps	  s
    zTime.from_gps)N)N)r   r   r   r   r<   r   rw   r   r&   rf   rn   ro   rh   rm   r   r   r-   r   r   )r)   r   r     s   r   c               @   s.   e Zd ZdZd ZedgZejdfddZ	dS )Documentz"
	Description of a LIGO LW file.
	r|   Nc             C   sh   | t | d |dk	r*| d|  x8| jD ].}|j| jkrVtd|j| jf | | q2W dS )z
		Write the document.
		rg   Nz.<?xml-stylesheet type="text/xsl" href="%s" ?>
zinvalid child %s for %s)rh   Headerr>   r<   ri   r   )r   rl   Zxsl_filer]   r   r   r   rh   "  s    

zDocument.write)
r   r   r   r   r<   r4   ri   rn   ro   rh   r   r   r   r   r     s   
r   c               @   s   e Zd ZdZi f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d Z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 )%LIGOLWContentHandlera  
	ContentHandler class for parsing LIGO Light Weight documents with a
	SAX2-compliant parser.

	Example:

	>>> # initialize empty Document tree into which parsed XML tree
	>>> # will be inserted
	>>> xmldoc = Document()
	>>> # create handler instance attached to Document object
	>>> handler = LIGOLWContentHandler(xmldoc)
	>>> # open file and parse
	>>> make_parser(handler).parse(open("demo.xml"))
	>>> # write XML (default to stdout)
	>>> xmldoc.write()

	NOTE:  this example is for illustration only.  Most users will wish
	to use the .load_*() functions in the ligo.lw.utils subpackage to
	load documents, and the .write_*() functions to write documents.
	Those functions provide additional features such as support for
	gzip'ed documents, MD5 hash computation, and Condor eviction
	trapping to avoid writing broken documents to disk.

	See also:  PartialLIGOLWContentHandler,
	FilteringLIGOLWContentHandler.
	c             C   s   | | _ | _dtjf| jdtjf| jdtjf| jdt	jf| j
dtjf| jdtjf| jdtjf| jdtjf| jdtjf| jdtjf| jdtjf| jdtjf| jdtjf| ji| _| j| dS )zo
		Initialize the handler by pointing it to the Document object
		into which the parsed file will be loaded.
		N)currentdocumentr   r<   startAdcDatar   startAdcIntervalr   
startArrayr   startColumnr}   startCommentr   startDetectorr   startDimr   startIGWDFramer|   startLIGO_LWr~   
startParamr   startStreamr   
startTabler   	startTime_startElementHandlersupdate)r   r   Zstart_handlersr   r   r   r&   U  s    zLIGOLWContentHandler.__init__c             C   s   t |S )N)r   )r   parentr@   r   r   r   r   m  s    z!LIGOLWContentHandler.startAdcDatac             C   s   t |S )N)r   )r   r   r@   r   r   r   r   p  s    z%LIGOLWContentHandler.startAdcIntervalc             C   s   t |S )N)r   )r   r   r@   r   r   r   r   s  s    zLIGOLWContentHandler.startArrayc             C   s   t |S )N)r   )r   r   r@   r   r   r   r   v  s    z LIGOLWContentHandler.startColumnc             C   s   t |S )N)r}   )r   r   r@   r   r   r   r   y  s    z!LIGOLWContentHandler.startCommentc             C   s   t |S )N)r   )r   r   r@   r   r   r   r   |  s    z"LIGOLWContentHandler.startDetectorc             C   s   t |S )N)r   )r   r   r@   r   r   r   r     s    zLIGOLWContentHandler.startDimc             C   s   t |S )N)r   )r   r   r@   r   r   r   r     s    z#LIGOLWContentHandler.startIGWDFramec             C   s   t |S )N)r|   )r   r   r@   r   r   r   r     s    z!LIGOLWContentHandler.startLIGO_LWc             C   s   t |S )N)r~   )r   r   r@   r   r   r   r     s    zLIGOLWContentHandler.startParamc             C   s   t |S )N)r   )r   r   r@   r   r   r   r     s    z LIGOLWContentHandler.startStreamc             C   s   t |S )N)r   )r   r   r@   r   r   r   r     s    zLIGOLWContentHandler.startTablec             C   s   t |S )N)r   )r   r   r@   r   r   r   r     s    zLIGOLWContentHandler.startTimec          
      s   |\}}y| j ||f }W n( tk
rB   td||p6tf Y nX tt fdd  D  y| j|| j | _W n@ t	k
r } z"t
|d| j t|f W d d }~X Y nX d S )Nz#unknown element %s for namespace %sc             3   s    | ]\}}  ||fV  qd S )N)getQNameByName)r1   r   r   )r@   r   r   r3     s    z6LIGOLWContentHandler.startElementNS.<locals>.<genexpr>zline %d: %s)r   r   r   	NameSpacer   dictrC   r   rK   	Exceptionrs   _locatorgetLineNumberr$   )r   uri_localnameqnamer@   uri	localnameZstart_handlerrX   r   )r@   r   startElementNS  s    z#LIGOLWContentHandler.startElementNSc          
   C   sf   |\}}y| j   W n@ tk
rV } z"t|d| j t|f W d d }~X Y nX | j j| _ d S )Nzline %d: %s)r   rf   r   rs   r   r   r$   r8   )r   r   r   r   r   rX   r   r   r   endElementNS  s    0z!LIGOLWContentHandler.endElementNSc          
   C   sZ   y| j t| W n@ tk
rT } z"t|d| j t|f W d d }~X Y nX d S )Nzline %d: %s)r   re   xmlunescaper   rs   r   r   r$   )r   rd   rX   r   r   r   
characters  s    zLIGOLWContentHandler.charactersN)r   r   r   r   r&   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   9  s$   r   c                   sD   e Zd ZdZ fddZ fddZ fddZ fdd	Z  ZS )
PartialLIGOLWContentHandlera6  
	LIGO LW content handler object that loads only those parts of the
	document matching some criteria.  Useful, for example, when one
	wishes to read only a single table from a file.

	Example:

	>>> from ligo.lw import utils as ligolw_utils
	>>> def contenthandler(document):
	...	return PartialLIGOLWContentHandler(document, lambda name, attrs: name == Table.tagName)
	...
	>>> xmldoc = ligolw_utils.load_filename("demo.xml", contenthandler = contenthandler)

	This parses "demo.xml" and returns an XML tree containing only the
	Table elements and their children.
	c                s    t t| | || _d| _dS )z
		Only those elements for which element_filter(name, attrs)
		evaluates to True, and the children of those elements, will
		be loaded.
		r   N)r%   r   r&   element_filterdepth)r   r   r   )r)   r   r   r&     s    z$PartialLIGOLWContentHandler.__init__c                sf   |\}}t t fdd  D }| jdks<| ||rbtt| ||f|  |  jd7  _d S )Nc             3   s    | ]\}}  ||fV  qd S )N)r   )r1   r   r   )r@   r   r   r3     s    z=PartialLIGOLWContentHandler.startElementNS.<locals>.<genexpr>r   r   )r   r   rC   r   r   r%   r   r   )r   r   r   r@   r   r   filter_attrs)r)   )r@   r   r     s
    z*PartialLIGOLWContentHandler.startElementNSc                s,   | j dkr(|  j d8  _ tt| j|  d S )Nr   r   )r   r%   r   r   )r   r   )r)   r   r   r     s    
z(PartialLIGOLWContentHandler.endElementNSc                s   | j dkrtt| | d S )Nr   )r   r%   r   r   )r   rd   )r)   r   r   r     s    
z&PartialLIGOLWContentHandler.characters)	r   r   r   r   r&   r   r   r   r-   r   r   )r)   r   r     s
   
r   c                   sD   e Zd ZdZ fddZ fddZ fddZ fdd	Z  ZS )
FilteringLIGOLWContentHandleraI  
	LIGO LW content handler that loads everything but those parts of a
	document that match some criteria.  Useful, for example, when one
	wishes to read everything except a single table from a file.

	Example:

	>>> from ligo.lw import utils as ligolw_utils
	>>> def contenthandler(document):
	...	return FilteringLIGOLWContentHandler(document, lambda name, attrs: name != Table.tagName)
	...
	>>> xmldoc = ligolw_utils.load_filename("demo.xml", contenthandler = contenthandler)

	This parses "demo.xml" and returns an XML tree with all the Table
	elements and their children removed.
	c                s    t t| | || _d| _dS )z
		Those elements for which element_filter(name, attrs)
		evaluates to False, and the children of those elements,
		will not be loaded.
		r   N)r%   r   r&   r   r   )r   r   r   )r)   r   r   r&     s    z&FilteringLIGOLWContentHandler.__init__c                sh   |\}}t t fdd  D }| jdkrV| ||rVtt| ||f|  n|  jd7  _d S )Nc             3   s    | ]\}}  ||fV  qd S )N)r   )r1   r   r   )r@   r   r   r3     s    z?FilteringLIGOLWContentHandler.startElementNS.<locals>.<genexpr>r   r   )r   r   rC   r   r   r%   r   r   )r   r   r   r@   r   r   r   )r)   )r@   r   r     s
    z,FilteringLIGOLWContentHandler.startElementNSc                s.   | j dkrtt| j|  n|  j d8  _ d S )Nr   r   )r   r%   r   r   )r   r   )r)   r   r   r     s    
z*FilteringLIGOLWContentHandler.endElementNSc                s   | j dkrtt| | d S )Nr   )r   r%   r   r   )r   rd   )r)   r   r   r     s    
z(FilteringLIGOLWContentHandler.characters)	r   r   r   r   r&   r   r   r   r-   r   r   )r)   r   r     s
   
r   c             C   sF   t  }||  |t jjd |t jjd |t jjd |S )as  
	Convenience function to construct a document parser with namespaces
	enabled and validation disabled.  Document validation is a nice
	feature, but enabling validation can require the LIGO LW DTD to be
	downloaded from the LDAS document server if the DTD is not included
	inline in the XML.  This requires a working connection to the
	internet and the server to be up.
	TF)r   make_parserZsetContentHandlerZ
setFeaturehandlerZfeature_namespacesZfeature_validationZfeature_external_ges)r   r   r   r   r   r     s    	
r   )8r   r   Zdateutil.parserr   rn   xmlr   Zxml.sax.xmlreaderr   Zxml.sax.saxutilsr   rk   r   r   rA   r   r   r	   r
   r   r*   	functoolsr   r   r   rj   r   r   r,   r   objectr.   rp   rt   r+   rv   r|   r}   r~   r   r   r   r   r   r   r   r   r   r   r   r   ZContentHandlerr   r   r   r   r   r   r   r   <module>!   sN   g Q	<


Pv,7