
    iFT                    Z   d Z ddlmZ ddlZddlmZmZ ddlmZ ddl	m
Z
mZmZmZmZmZmZmZmZmZ ddlmZmZ e
rddlmZ dd	lmZmZmZmZ dd
lmZ dZ dZ!dZ"	 d%	 	 	 	 	 d&dZ#e G d de             Z$ G d de$      Z% G d de$      Z& G d de$      Z' G d de$      Z( G d de$      Z) G d de*      Z+d'dZ,d'dZ-	 	 	 	 	 	 d(dZ.	 	 	 	 	 	 d(d Z/d)d!Z0d*d"Z1d+d#Z2e3d$k(  rye,e_4        e0e_5        e1e_6        e2e_7        e-e_8        e1e$_6        e2e$_7        e0e$_5        e,e$_4        e-e$_8        y),a  

This module implements the SPARQL 1.1 Property path operators, as
defined in:

http://www.w3.org/TR/sparql11-query/#propertypaths

In SPARQL the syntax is as follows:

+--------------------+-------------------------------------------------+
|Syntax              | Matches                                         |
+====================+=================================================+
|iri                 | An IRI. A path of length one.                   |
+--------------------+-------------------------------------------------+
|^elt                | Inverse path (object to subject).               |
+--------------------+-------------------------------------------------+
|elt1 / elt2         | A sequence path of elt1 followed by elt2.       |
+--------------------+-------------------------------------------------+
|elt1 | elt2         | A alternative path of elt1 or elt2              |
|                    | (all possibilities are tried).                  |
+--------------------+-------------------------------------------------+
|elt*                | A path that connects the subject and object     |
|                    | of the path by zero or more matches of elt.     |
+--------------------+-------------------------------------------------+
|elt+                | A path that connects the subject and object     |
|                    | of the path by one or more matches of elt.      |
+--------------------+-------------------------------------------------+
|elt?                | A path that connects the subject and object     |
|                    | of the path by zero or one matches of elt.      |
+--------------------+-------------------------------------------------+
|!iri or             | Negated property set. An IRI which is not one of|
|!(iri\ :sub:`1`\ \| | iri\ :sub:`1`...iri\ :sub:`n`.                  |
|... \|iri\ :sub:`n`)| !iri is short for !(iri).                       |
+--------------------+-------------------------------------------------+
|!^iri or            | Negated property set where the excluded matches |
|!(^iri\ :sub:`1`\ \|| are based on reversed path. That is, not one of |
|...\|^iri\ :sub:`n`)| iri\ :sub:`1`...iri\ :sub:`n` as reverse paths. |
|                    | !^iri is short for !(^iri).                     |
+--------------------+-------------------------------------------------+
|!(iri\ :sub:`1`\ \| | A combination of forward and reverse            |
|...\|iri\ :sub:`j`\ | properties in a negated property set.           |
|\|^iri\ :sub:`j+1`\ |                                                 |
|\|... \|^iri\       |                                                 |
|:sub:`n`)|          |                                                 |
+--------------------+-------------------------------------------------+
|(elt)               | A group path elt, brackets control precedence.  |
+--------------------+-------------------------------------------------+

This module is used internally by the SPARQL engine, but the property paths
can also be used to query RDFLib Graphs directly.

Where possible the SPARQL syntax is mapped to Python operators, and property
path objects can be constructed from existing URIRefs.

>>> from rdflib import Graph, Namespace
>>> from rdflib.namespace import FOAF

>>> ~FOAF.knows
Path(~http://xmlns.com/foaf/0.1/knows)

>>> FOAF.knows/FOAF.name
Path(http://xmlns.com/foaf/0.1/knows / http://xmlns.com/foaf/0.1/name)

>>> FOAF.name|FOAF.givenName
Path(http://xmlns.com/foaf/0.1/name | http://xmlns.com/foaf/0.1/givenName)

Modifiers (?, \*, +) are done using \* (the multiplication operator) and
the strings '\*', '?', '+', also defined as constants in this file.

>>> FOAF.knows*OneOrMore
Path(http://xmlns.com/foaf/0.1/knows+)

The path objects can also be used with the normal graph methods.

First some example data:

>>> g=Graph()

>>> g=g.parse(data='''
... @prefix : <ex:> .
...
... :a :p1 :c ; :p2 :f .
... :c :p2 :e ; :p3 :g .
... :g :p3 :h ; :p2 :j .
... :h :p3 :a ; :p2 :g .
...
... :q :px :q .
...
... ''', format='n3') # doctest: +ELLIPSIS

>>> e = Namespace('ex:')

Graph contains:

>>> (e.a, e.p1/e.p2, e.e) in g
True

Graph generator functions, triples, subjects, objects, etc. :

>>> list(g.objects(e.c, (e.p3*OneOrMore)/e.p2)) # doctest: +NORMALIZE_WHITESPACE
[rdflib.term.URIRef('ex:j'), rdflib.term.URIRef('ex:g'),
    rdflib.term.URIRef('ex:f')]

A more complete set of tests:

>>> list(eval_path(g, (None, e.p1/e.p2, None)))==[(e.a, e.e)]
True
>>> list(eval_path(g, (e.a, e.p1|e.p2, None)))==[(e.a,e.c), (e.a,e.f)]
True
>>> list(eval_path(g, (e.c, ~e.p1, None))) == [ (e.c, e.a) ]
True
>>> list(eval_path(g, (e.a, e.p1*ZeroOrOne, None))) == [(e.a, e.a), (e.a, e.c)]
True
>>> list(eval_path(g, (e.c, e.p3*OneOrMore, None))) == [
...     (e.c, e.g), (e.c, e.h), (e.c, e.a)]
True
>>> list(eval_path(g, (e.c, e.p3*ZeroOrMore, None))) == [(e.c, e.c),
...     (e.c, e.g), (e.c, e.h), (e.c, e.a)]
True
>>> list(eval_path(g, (e.a, -e.p1, None))) == [(e.a, e.f)]
True
>>> list(eval_path(g, (e.a, -(e.p1|e.p2), None))) == []
True
>>> list(eval_path(g, (e.g, -~e.p2, None))) == [(e.g, e.j)]
True
>>> list(eval_path(g, (e.e, ~(e.p1/e.p2), None))) == [(e.e, e.a)]
True
>>> list(eval_path(g, (e.a, e.p1/e.p3/e.p3, None))) == [(e.a, e.h)]
True

>>> list(eval_path(g, (e.q, e.px*OneOrMore, None)))
[(rdflib.term.URIRef('ex:q'), rdflib.term.URIRef('ex:q'))]

>>> list(eval_path(g, (None, e.p1|e.p2, e.c)))
[(rdflib.term.URIRef('ex:a'), rdflib.term.URIRef('ex:c'))]

>>> list(eval_path(g, (None, ~e.p1, e.a))) == [ (e.c, e.a) ]
True
>>> list(eval_path(g, (None, e.p1*ZeroOrOne, e.c))) # doctest: +NORMALIZE_WHITESPACE
[(rdflib.term.URIRef('ex:c'), rdflib.term.URIRef('ex:c')),
 (rdflib.term.URIRef('ex:a'), rdflib.term.URIRef('ex:c'))]

>>> list(eval_path(g, (None, e.p3*OneOrMore, e.a))) # doctest: +NORMALIZE_WHITESPACE
[(rdflib.term.URIRef('ex:h'), rdflib.term.URIRef('ex:a')),
 (rdflib.term.URIRef('ex:g'), rdflib.term.URIRef('ex:a')),
 (rdflib.term.URIRef('ex:c'), rdflib.term.URIRef('ex:a'))]

>>> list(eval_path(g, (None, e.p3*ZeroOrMore, e.a))) # doctest: +NORMALIZE_WHITESPACE
[(rdflib.term.URIRef('ex:a'), rdflib.term.URIRef('ex:a')),
 (rdflib.term.URIRef('ex:h'), rdflib.term.URIRef('ex:a')),
 (rdflib.term.URIRef('ex:g'), rdflib.term.URIRef('ex:a')),
 (rdflib.term.URIRef('ex:c'), rdflib.term.URIRef('ex:a'))]

>>> list(eval_path(g, (None, -e.p1, e.f))) == [(e.a, e.f)]
True
>>> list(eval_path(g, (None, -(e.p1|e.p2), e.c))) == []
True
>>> list(eval_path(g, (None, -~e.p2, e.j))) == [(e.g, e.j)]
True
>>> list(eval_path(g, (None, ~(e.p1/e.p2), e.a))) == [(e.e, e.a)]
True
>>> list(eval_path(g, (None, e.p1/e.p3/e.p3, e.h))) == [(e.a, e.h)]
True

>>> list(eval_path(g, (e.q, e.px*OneOrMore, None)))
[(rdflib.term.URIRef('ex:q'), rdflib.term.URIRef('ex:q'))]

>>> list(eval_path(g, (e.c, (e.p2|e.p3)*ZeroOrMore, e.j)))
[(rdflib.term.URIRef('ex:c'), rdflib.term.URIRef('ex:j'))]

No vars specified:

>>> sorted(list(eval_path(g, (None, e.p3*OneOrMore, None)))) #doctest: +NORMALIZE_WHITESPACE
[(rdflib.term.URIRef('ex:c'), rdflib.term.URIRef('ex:a')),
 (rdflib.term.URIRef('ex:c'), rdflib.term.URIRef('ex:g')),
 (rdflib.term.URIRef('ex:c'), rdflib.term.URIRef('ex:h')),
 (rdflib.term.URIRef('ex:g'), rdflib.term.URIRef('ex:a')),
 (rdflib.term.URIRef('ex:g'), rdflib.term.URIRef('ex:h')),
 (rdflib.term.URIRef('ex:h'), rdflib.term.URIRef('ex:a'))]

    )annotationsN)ABCabstractmethod)total_ordering)
TYPE_CHECKINGAnyCallable	GeneratorIteratorListOptionalSetTupleUnion)NodeURIRef)_MulPathMod)Graph_ObjectType_PredicateType_SubjectType)NamespaceManager*+?c                    t        | t        t        f      r,t        | j                        dkD  rd| j                  |      z  S | j                  |      S )N   z(%s))
isinstanceSequencePathAlternativePathlenargsn3)argnamespace_managers     ;C:\Projects\mas-dev\.venv\Lib\site-packages\rdflib/paths.py_n3r'      sG     #o67CMA<M011166#$$    c                      e Zd ZU ded<   ded<   ded<   ded<   d	ed
<   e	 	 d	 	 	 	 	 	 	 dd       Zeddd       Zd Zd ZddZ	y)Pathz6Callable[[Path, Union[URIRef, Path]], AlternativePath]__or__zCallable[[Path], InvPath]
__invert__zCallable[[Path], NegatedPath]__neg__z3Callable[[Path, Union[URIRef, Path]], SequencePath]__truediv__zCallable[[Path, str], MulPath]__mul__Nc                     y N )selfgraphsubjobjs       r&   evalz	Path.eval   s     69r(   c                     y r1   r2   r3   r%   s     r&   r#   zPath.n3   s    ORr(   c                *    t        t        |             S r1   )hashreprr3   s    r&   __hash__zPath.__hash__   s    DJr(   c                0    t        |       t        |      k(  S r1   )r<   r3   others     r&   __eq__zPath.__eq__   s    DzT%[((r(   c                    t        |t        t        f      s$t        dt	        |       dt	        |      d      t	        |       t	        |      k  S )Nzunorderable types: z() < z())r   r*   r   	TypeErrorr<   r@   s     r&   __lt__zPath.__lt__   sB    %$.48JUL  DzDK''r(   NN)r4   r   r5   Optional[_SubjectType]r6   Optional[_ObjectType]return*Iterator[Tuple[_SubjectType, _ObjectType]]r1   r%   Optional[NamespaceManager]rI   str)rA   r   rI   bool)
__name__
__module____qualname____annotations__r   r7   r#   r>   rB   rE   r2   r(   r&   r*   r*      s    BB))**DD++ (,%)	99 %9 #	9
 
49 9 R R )(r(   r*   c                  B    e Zd ZddZ	 	 d	 	 	 	 	 	 	 ddZd	dZd
ddZy)InvPathc                    || _         y r1   r$   r3   r$   s     r&   __init__zInvPath.__init__  s	    r(   Nc              #  Z   K   t        ||| j                  |f      D ]  \  }}||f  y wr1   )	eval_pathr$   )r3   r4   r5   r6   sos         r&   r7   zInvPath.eval  s1      ec488T%:;DAqQ$J <s   )+c                "    d| j                   dS )NzPath(~)rV   r=   s    r&   __repr__zInvPath.__repr__  s    "hh((r(   c                4    dt        | j                  |      z  S )Nz^%s)r'   r$   r9   s     r&   r#   z
InvPath.n3  s    s488%6777r(   )r$   Union[Path, URIRef]rF   )r4   r   r5   rG   r6   rH   rI   z7Generator[Tuple[_ObjectType, _SubjectType], None, None]rI   rM   r1   rK   rO   rP   rQ   rX   r7   r_   r#   r2   r(   r&   rT   rT     sE     (,%)	 % #	
 
A)8r(   rT   c                  B    e Zd ZddZ	 	 d	 	 	 	 	 	 	 ddZd	dZd
ddZy)r   c                    g | _         |D ]M  }t        |t              r | xj                   |j                   z  c_         3| j                   j                  |       O y r1   )r"   r   r   appendr3   r"   as      r&   rX   zSequencePath.__init__  sA    /1	A!\*		QVV#			  #	 r(   Nc                    	 	 	 	 	 	 	 	 dfd	 	 	 	 	 	 	 	 dfd}|r | j                   ||      S |r || j                   ||      S  | j                   ||      S )Nc              3     K   | dd  r6t        || d   d f      D ]   \  }} | dd  ||      D ]  }||d   f  " y t        || d   |f      D ]  \  }}||f  y w)Nr   r   rZ   pathsr5   r6   r[   r\   r	_eval_seqr4   s         r&   ro   z$SequencePath.eval.<locals>._eval_seq$  s     
 QRy%edE!Hd-CDDAq&uQRy!S91g : E
 &edE!Hc-BCDAqQ$J D   AA c              3     K   | d d r6t        d | d   |f      D ]   \  }} | d d ||      D ]  }|d   |f  " y t        || d   |f      D ]  \  }}||f  y w)Nr   rk   rl   s         r&   _eval_seq_bwz'SequencePath.eval.<locals>._eval_seq_bw2  s     
 Sbz%edE"Is-CDDAq&uSbz4;dAg < E
 &edE!Hc-BCDAqQ$J Drp   )rm   List[Union[Path, URIRef]]r5   rG   r6   rH   rI   7Generator[Tuple[_SubjectType, _ObjectType], None, None])rm   rt   r5   rG   r6   r   rI   ru   )r"   )r3   r4   r5   r6   rs   ro   s    `   @r&   r7   zSequencePath.eval  s    	,	(	 '	 E			,	(	 	 E		 TYYc22		455TYYc22r(   c                L    ddj                  d | j                  D              z  S )NPath(%s)z / c              3  2   K   | ]  }t        |        y wr1   rM   .0xs     r&   	<genexpr>z(SequencePath.__repr__.<locals>.<genexpr>H       &Ay!s1vy   joinr"   r=   s    r&   r_   zSequencePath.__repr__G       EJJ&Atyy&AAAAr(   c                L    dj                  fd| j                  D              S )N/c              3  6   K   | ]  }t        |        y wr1   r'   r{   rh   r%   s     r&   r}   z"SequencePath.n3.<locals>.<genexpr>K       E9aA019   r   r9   s    `r&   r#   zSequencePath.n3J      xxE499EEEr(   r"   ra   rF   r4   r   r5   rG   r6   rH   rI   ru   rb   r1   rK   rc   r2   r(   r&   r   r     sH    $ (,%)	'3'3 %'3 #	'3
 
A'3RBFr(   r   c                  B    e Zd ZddZ	 	 d	 	 	 	 	 	 	 ddZd	dZd
ddZy)r    c                    g | _         |D ]M  }t        |t              r | xj                   |j                   z  c_         3| j                   j                  |       O y r1   )r"   r   r    rf   rg   s      r&   rX   zAlternativePath.__init__O  sA    /1	A!_-		QVV#			  #	 r(   Nc              #  ^   K   | j                   D ]  }t        ||||f      D ]  }|   y wr1   )r"   rZ   )r3   r4   r5   r6   r|   ys         r&   r7   zAlternativePath.evalW  s2      AutQn5 6 s   +-c                L    ddj                  d | j                  D              z  S )Nrw   z | c              3  2   K   | ]  }t        |        y wr1   ry   rz   s     r&   r}   z+AlternativePath.__repr__.<locals>.<genexpr>b  r~   r   r   r=   s    r&   r_   zAlternativePath.__repr__a  r   r(   c                L    dj                  fd| j                  D              S )N|c              3  6   K   | ]  }t        |        y wr1   r   r   s     r&   r}   z%AlternativePath.n3.<locals>.<genexpr>e  r   r   r   r9   s    `r&   r#   zAlternativePath.n3d  r   r(   r   rF   r   rb   r1   rK   rc   r2   r(   r&   r    r    N  sG    $ (,%)	 % #	
 
ABFr(   r    c                  H    e Zd ZddZ	 	 	 d	 	 	 	 	 	 	 	 	 ddZd	dZd
ddZy)MulPathc                    || _         || _        |t        k(  rd| _        d| _        y |t
        k(  rd| _        d| _        y |t        k(  rd| _        d| _        y t        d|z        )NTFzUnknown modifier %s)pathmod	ZeroOrOnezeromore
ZeroOrMore	OneOrMore	Exception)r3   r   r   s      r&   rX   zMulPath.__init__i  sc    	)DIDIJDIDIIDIDI1C788r(   Nc              #     	K    j                   r#|r!|r|r||k(  r||f n|r||f n|r||f 	 	 	 d	 	 	 	 	 	 	 d	 fd		 	 	 d	 	 	 	 	 	 	 d fdd	 fd}t               }|r2 	||t                     D ]  }||vs|j                  |       |  y |r2 ||t                     D ]  }||vs|j                  |       |  y  |       D ]  }||vs|j                  |       |  y w)Nc              3     K   |j                  |        t        | 	j                  d f      D ]<  \  }}|r||k(  r||f 	j                  s ||v r% |||      D ]  \  }}||f  > y wr1   addrZ   r   r   )
r5   r6   seenr[   r\   s2o2_fwdr4   r3   s
          r&   r   zMulPath.eval.<locals>._fwd  sx      HHTN!%$		4)@A1a3hQ$J99Dy "&q#t"4Be #5 B   A
A. A.c              3     K   |j                  |       t        d 	j                  |f      D ]<  \  }}| r| |k(  r||f 	j                  s ||v r% d ||      D ]  \  }}||f  > y wr1   r   )
r5   r6   r   r[   r\   r   r   _bwdr4   r3   s
          r&   r   zMulPath.eval.<locals>._bwd  sx      HHSM!%$		3)?@1tqyQ$J99Dy "&tQ"5B !e #6 Ar   c            	   3    K   	j                   rZt               } j                  d       D ]<  \  }}|| vr| j                  |       ||f || vs&| j                  |       ||f > t               }t	        d 	j
                  d f      D ]`  \  }}	j                  s||f ||vs|j                  |       t         |d t                           }|D ]  \  }}||k(  sJ ||f  b y wr1   )r   setsubject_objectsr   rZ   r   r   list)
seen1r[   r\   r   fs1o1r   r4   r3   s
          r&   _all_fwd_pathsz$MulPath.eval.<locals>._all_fwd_paths  s     yy "11$7DAq~		!d
~		!d
 8 5D!%$		4)@A1yyQ$J} asu!56&'FB#%7N7"$b&L '( Bs   AC1AC1+AC1)NNN)r5   rG   r6   rH   r   zOptional[Set[_SubjectType]]rI   ru   )r5   rG   r6   rH   r   zOptional[Set[_ObjectType]]rI   ru   )rI   ru   )r   r   r   )
r3   r4   r5   r6   firstr   doner|   r   r   s
   ``      @@r&   r7   zMulPath.evaly  s>     993;)ODj 3h ,0)-04	$(	$&	$ .	$ E		$( ,0)-/3	$(	$&	$ -	$ E		$(	)8 u$SU+D=HHQKG , $SU+D=HHQKG ,
 $%D=HHQKG &s   BC=
3C=>&C=%C=c                :    d| j                   | j                  dS )NzPath(r^   )r   r   r=   s    r&   r_   zMulPath.__repr__  s    #yy$((33r(   c                J    t        | j                  |      | j                  S r1   )r'   r   r   r9   s     r&   r#   z
MulPath.n3  s    TYY(9:DHHEEr(   )r   ra   r   r   )NNT)
r4   r   r5   rG   r6   rH   r   rN   rI   ru   rb   r1   rK   rc   r2   r(   r&   r   r   h  sZ    9& (,%)bb %b #	b
 b 
AbH4Fr(   r   c                  .    e Zd ZddZddZddZd	d
dZy)NegatedPathc                    |  t        |t        t        f      r	|g| _        y t        |t              r|j                  | _        y t        dd|z         )Nz%Can only negate URIRefs, InvPaths or zAlternativePaths, not: )r   r   rT   r"   r    r   rW   s     r&   rX   zNegatedPath.__init__  sM    cFG,-DI_-DI71467 r(   Nc              #    K   |j                  |d |f      D ]f  \  }}}| j                  D ]K  }t        |t              r||k(  s .t        |t              r||j
                  |f|v s= Rt        d|z         ||f h y w)NzInvalid path in NegatedPath: %s)triplesr"   r   r   rT   r$   r   )r3   r4   r5   r6   r[   pr\   rh   s           r&   r7   zNegatedPath.eval  s     }}dD#%67GAq!YYa(Av7+155!}-#$E$IJJ  d
 8s   A B#B'Bc                L    ddj                  d | j                  D              z  S )Nz
Path(! %s),c              3  2   K   | ]  }t        |        y wr1   ry   rz   s     r&   r}   z'NegatedPath.__repr__.<locals>.<genexpr>   r~   r   r   r=   s    r&   r_   zNegatedPath.__repr__  s     chh&Atyy&AAAAr(   c                R    ddj                  fd| j                  D              z  S )Nz!(%s)r   c              3  6   K   | ]  }t        |        y wr1   r   )r{   r$   r%   s     r&   r}   z!NegatedPath.n3.<locals>.<genexpr>  s     "T)33s,=#>)r   r   r9   s    `r&   r#   zNegatedPath.n3  s!    #(("T$))"TTUUr(   )r$   z'Union[AlternativePath, InvPath, URIRef]rF   rb   r1   rK   rc   r2   r(   r&   r   r     s    
BVr(   r   c                      e Zd Zy)PathListN)rO   rP   rQ   r2   r(   r&   r   r     s    r(   r   c                \    t        |t        t        f      st        d      t	        | |      S )z
    alternative path
    &Only URIRefs or Paths can be in paths!)r   r   r*   r   r    r@   s     r&   path_alternativer   
  s+     efd^,@AA4''r(   c                \    t        |t        t        f      st        d      t	        | |      S )z
    sequence path
    r   )r   r   r*   r   r   r@   s     r&   path_sequencer     s+     efd^,@AAe$$r(   c                V    t        j                  t        d             t        | |      S )Nzrdflib.path.evalPath() is deprecated, use the (snake-cased) eval_path(). The mixed-case evalPath() function name is incompatible with PEP8 recommendations and will be replaced by eval_path() in rdflib 7.0.0.)warningswarnDeprecationWarningrZ   r4   ts     r&   evalPathr     s-     MMS	
 UAr(   c                2    d | j                  |      D        S )Nc              3  ,   K   | ]  \  }}}||f  y wr1   r2   )r{   r[   r   r\   s       r&   r}   zeval_path.<locals>.<genexpr>6  s     3"2wq!QQF"2s   )r   r   s     r&   rZ   rZ   .  s     4%--"233r(   c                    t        | |      S )z
    cardinality path
    )r   )r   muls     r&   mul_pathr   9  s     1c?r(   c                    t        |       S )z
    inverse path
    )rT   r   s    r&   inv_pathr   @  s     1:r(   c                    t        |       S )z
    negated path
    )r   r   s    r&   neg_pathr   G  s     q>r(   __main__r1   )r$   Union[URIRef, Path]r%   rL   rI   rM   )r3   r   rA   r   )r4   r   r   zWTuple[Optional[_SubjectType], Union[None, Path, _PredicateType], Optional[_ObjectType]]rI   rJ   )r   r   r   r   rI   r   )r   r   rI   rT   )r   z'Union[URIRef, AlternativePath, InvPath]rI   r   )9__doc__
__future__r   r   abcr   r   	functoolsr   typingr   r   r	   r
   r   r   r   r   r   r   rdflib.termr   r   rdflib._type_checkingr   rdflib.graphr   r   r   r   rdflib.namespacer   r   r   r   r'   r*   rT   r   r    r   r   r   r   r   r   r   rZ   r   r   r   rO   r+   r/   r,   r-   r.   r2   r(   r&   <module>r      s  tl #  # $   %1MM1
 
		 OS%	%1K%% (3 ( (@8d 8(6F4 6FrFd F4yFd yFxV$ VD	t 	(% 0$444 04 z %FM FN FFN&FDODLDL"DK$Dr(   