
    iD                       d 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
mZ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mZmZmZmZ ddlmZmZmZ ddlZ ddl!Z ddl"Z dd	l#m$Z$ erdd
lm%Z% g dZ& ede      Z' ed      Z(d:dZ)d;dZ*d<d=dZ+d>dZ,	 d?	 	 	 	 	 d@dZ-	 	 	 dA	 	 	 	 	 	 	 	 	 dBdZ.dCdZ/dDdZ0i dddddddddddddddd d!d d"d d#d$d$d$d%d%d&d'd(d'd'd'Z1d?dEd)Z2dFdGd*Z3	 d?	 	 	 	 	 	 	 dHd+Z4d, ddd-f	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dId.Z5edJd/       Z6ed0d1	 	 	 	 	 dKd2       Z6dd1	 	 	 	 	 dKd3Z6d4Z7	 d5e7z   d6z   Z8	 e8d7z   Z9	 e7d5z   Z:	 e8d8z   Z;	 dLd9Z<y)Mz
Some utility functions.

Miscellaneous utilities

* list2set
* first
* uniq
* more_than

Term characterisation and generation

* to_term
* from_n3

Date/time utilities

* date_time
* parse_date_time

    )annotations)timegm)splitext)altzonegmtime	localtimetimetimezone)TYPE_CHECKINGAnyCallableDictHashableIterableIteratorListOptionalSetTupleTypeVarUnionoverload)quoteurlsplit
urlunsplitN)sign)Graph)list2setfirstuniq	more_thanto_termfrom_n3	date_timeparse_date_timeguess_format
find_rootsget_tree	_coalesce_iri2uri
_HashableT)bound_AnyTc                n    t               }| D cg c]  }||vs|j                  |      r| c}S c c}w )zX
    Return a new list without duplicates.
    Preserves the order, unlike set(seq)
    )setadd)seqseenxs      :C:\Projects\mas-dev\.venv\Lib\site-packages\rdflib/util.pyr   r   M   s3    
 5D@s!atmDHHQKAs@@@s   	222c                    | D ]  }|c S  y)z_
    return the first element in a python sequence
    for graphs, use graph.value instead
    N )r1   results     r4   r   r   W   s    
      c                @    |rt        d | D              S t        |       S )z,removes duplicate strings from the sequence.c              3  <   K   | ]  }|j                           y wN)strip).0ss     r4   	<genexpr>zuniq.<locals>.<genexpr>d   s     /h1779hs   )r/   )sequencer<   s     r4   r    r    a   s     /h///8}r8   c                .    d}| D ]  }|dz  }||kD  s y y)z>Returns 1 if sequence has more items than number and 0 if not.r      r6   )r@   numberiitems       r4   r!   r!   i   s)    	A	Qv:  r8   c                   | s|S | j                  d      r3| j                  d      r"t        j                  j	                  | dd       S | j                  d      r3| j                  d      r"t        j                  j                  | dd       S | j                  d      rt        j                  j                  |       S d| z  }t        |      )a  
    Creates and returns an Identifier of type corresponding
    to the pattern of the given positional argument string ``s``:

    '' returns the ``default`` keyword argument value or ``None``

    '<s>' returns ``URIRef(s)`` (i.e. without angle brackets)

    '"s"' returns ``Literal(s)`` (i.e. without doublequotes)

    '_s' returns ``BNode(s)`` (i.e. without leading underscore)

    <>rB   "_zUnrecognised term syntax: '%s')
startswithendswithrdflibtermURIRefLiteralBNode	Exception)r>   defaultmsgs      r4   r"   r"   s   s      	
c	qzz#{{!!!Ab'**	
c	qzz#{{""1Qr7++	
c	{{  ##.2nr8   c                8   | s|S | j                  d      r@t        j                  j                  | dd j	                  d      j                  d            S | j                  d      r| j                  d      rd}nd}| j                  |d      \  }}|t        |      d }d}d}|j                  d	      }	|	d
k\  rt        ||	dz   d |||      }n|j                  d      r|dd }|j                  dd      }|j                  dd      }|j	                  d      j                  d      }t        j                  j                  |||      S | dk(  s| dk(  r"t        j                  j                  | dk(        S | j                         j                  ddd      j                  ddd      j                  ddd      j                         rd| j                         v rCt        j                  j                  | t        j                  j                  j                         S d| v rLt        j                  j                  t#        |       t        j                  j                  j$                        S t        j                  j                  t'        |       t        j                  j                  j(                        S | j                  d      r.t        | dd       }
t        j*                  j-                  ||
      S | j                  d      r.t        | dd       }
t        j*                  j/                  ||
      S | j                  d      r"t        j                  j1                  | dd       S d| v r|;t        j                  j3                  t        j*                  j/                               }| j5                  dd      \  }}t7        |j9                               |   }t        j                  j;                  |      |   S t        j                  j1                  |       S )a  
    Creates the Identifier corresponding to the given n3 string.

        >>> from rdflib.term import URIRef, Literal
        >>> from rdflib.namespace import NamespaceManager
        >>> from_n3('<http://ex.com/foo>') == URIRef('http://ex.com/foo')
        True
        >>> from_n3('"foo"@de') == Literal('foo', lang='de')
        True
        >>> from_n3('"""multi\nline\nstring"""@en') == Literal(
        ...     'multi\nline\nstring', lang='en')
        True
        >>> from_n3('42') == Literal(42)
        True
        >>> from_n3(Literal(42).n3()) == Literal(42)
        True
        >>> from_n3('"42"^^xsd:integer') == Literal(42)
        True
        >>> from rdflib import RDFS
        >>> from_n3('rdfs:label') == RDFS['label']
        True
        >>> nsm = NamespaceManager(rdflib.graph.Graph())
        >>> nsm.bind('dbpedia', 'http://dbpedia.org/resource/')
        >>> berlin = URIRef('http://dbpedia.org/resource/Berlin')
        >>> from_n3('dbpedia:Berlin', nsm=nsm) == berlin
        True

    rG   rB   rI   zraw-unicode-escapezunicode-escaperJ   z"""Nz^^r      @z\"z\xz\\xtruefalse. -e)datatype{[z_::)rL   rN   rO   rP   encodedecodersplitlenrfindr#   replacerQ   lower	isnumeric	namespaceXSDdoublefloatdecimalintintegergraphQuotedGraphr   rR   NamespaceManagersplitdict
namespaces	Namespace)r>   rT   backendnsmquotesvaluerestr_   languagedtoffset
identifierprefix	last_partnss                 r4   r#   r#      si   D ||C {{!!aGNN/0778HI
 	
 
c	<<FFhhvq)tc&km$ ::d#q=
 tHqLN3WgsKHs#8eS) eV, 1299:JK{{""5(H==	
fW{{""1;//			b!		b!		b!				 !'');;&&q63C3C3G3G3N3N&OO!8;;&&uQx&:J:J:N:N:V:V&WW{{""3q6F4D4D4H4H4P4P"QQ	
c	QqW%
 ||''<<	
c	QqW%
 ||!!':66	
d	{{  12''	;""33FLL4F4F4HICGGCO	#.."#F+))"-i88{{  ##r8   c           	         | 
t               } |r1t        |       }|d   r
t        dz  }n	t        dz  }d|dz  |dz  fz  }nt	        |       }d}|\	  }}}}}	}
}}}d|||||	|
|fz  }|S )ah  http://www.w3.org/TR/NOTE-datetime ex: 1997-07-16T19:20:30Z

    >>> date_time(1126482850)
    '2005-09-11T23:54:10Z'

    @@ this will change depending on where it is run
    #>>> date_time(1126482850, local_time_zone=True)
    #'2005-09-11T19:54:10-04:00'

    >>> date_time(1)
    '1970-01-01T00:00:01Z'

    >>> date_time(0)
    '1970-01-01T00:00:00Z'
       <   z
-%02d:%02dZz!%0004d-%02d-%02dT%02d:%02d:%02d%s)r	   r   r   r
   r   )tlocal_time_zone
time_tupletz_minstzdyearmonthdayhhmmsswdyzr>   s                  r4   r$   r$      s      	yFq\
a=mG"nGgmWr\::AY
-7*D%b"b"a+tUCRS.QQAHr8   c                   d| vr| dz  } | j                  d      \  }}|dd |dd }}|r|dk(  r|dd }d}n6t        |dd       }t        |d	d
       }t        |      |z  |dz  z   dz  }| }|j                  d      \  }	}
}|j                  d      \  }}}t        t        |	      t        |
      t        |      t        |      t        |      t        |      dddf	      }||z   }|S )a  always returns seconds in UTC

    # tests are written like this to make any errors easier to understand
    >>> parse_date_time('2005-09-11T23:54:10Z') - 1126482850.0
    0.0

    >>> parse_date_time('2005-09-11T16:54:10-07:00') - 1126482850.0
    0.0

    >>> parse_date_time('1970-01-01T00:00:01Z') - 1.0
    0.0

    >>> parse_date_time('1970-01-01T00:00:00Z') - 0.0
    0.0
    >>> parse_date_time("2005-09-05T10:42:00") - 1125916920.0
    0.0
    Tz
T00:00:00Zr   r   Nr   rI            r   r]   rb   )ru   rp   r   r   )valymdr	   hmstz_str	tz_offset
signed_hrsminssecsr   r   r   hourminutesecondr   s                   r4   r%   r%   "  s	   & #~|		#ICq)T!"XCVs]CRy	_
6!A;Z 4'*r/9R?E	yy~D%99S>D&&	TCJC#d)S[#f+qRSUVW	A 	
IAHr8   xmlrdfowln3ttlturtlenttrixxhtmlrdfahtmlsvgnqnquadstrigjsonzjson-ldjsonldc                    |xs t         }|j                  t        |             xs |j                  | j                               S )a9  
    Guess RDF serialization based on file suffix. Uses
    ``SUFFIX_FORMAT_MAP`` unless ``fmap`` is provided. Examples:

        >>> guess_format('path/to/file.rdf')
        'xml'
        >>> guess_format('path/to/file.owl')
        'xml'
        >>> guess_format('path/to/file.ttl')
        'turtle'
        >>> guess_format('path/to/file.json')
        'json-ld'
        >>> guess_format('path/to/file.xhtml')
        'rdfa'
        >>> guess_format('path/to/file.svg')
        'rdfa'
        >>> guess_format('path/to/file.xhtml', {'xhtml': 'grddl'})
        'grddl'

    This also works with just the suffixes, with or without leading dot, and
    regardless of letter case::

        >>> guess_format('.rdf')
        'xml'
        >>> guess_format('rdf')
        'xml'
        >>> guess_format('RDF')
        'xml'
    )SUFFIX_FORMAT_MAPget_get_extri   )fpathfmaps     r4   r&   r&   b  s6    < $$D88HUO$?(??r8   c                    t        |       d   }|dk(  r| j                  d      r| }|r|j                         }|j                  d      r|dd }|S )a)  
    Gets the file extension from a file(path); stripped of leading '.' and in
    lower case. Examples:

        >>> _get_ext("path/to/file.txt")
        'txt'
        >>> _get_ext("OTHER.PDF")
        'pdf'
        >>> _get_ext("noext")
        ''
        >>> _get_ext(".rdf")
        'rdf'
    rI   r\   r[   rB   N)r   rL   ri   )r   ri   exts      r4   r   r     sU     5/"
C
byU%%c*iik
~~c!"gJr8   c                    t               }|
t               }| j                  |      D ]A  \  }}|j                  |       ||v r|j                  |       ||vs1|j                  |       C |S )a  
    Find the roots in some sort of transitive hierarchy.

    find_roots(graph, rdflib.RDFS.subClassOf)
    will return a set of all roots of the sub-class hierarchy

    Assumes triple of the form (child, prop, parent), i.e. the direction of
    RDFS.subClassOf or SKOS.broader

    )r/   subject_objectsr0   remove)rr   proproots	non_rootsr3   r   s         r4   r'   r'     sh      (+uI}%%d+1a:LLOIIIaL , Lr8   c                    | S r;   r6   )r3   s    r4   <lambda>r     s    qr8   downc           
         |
t               }||v ry|j                  |       g }|dk(  r| j                  ||      }n| j                  ||      }|D ]'  }	t	        | |	|||||      }
|
s|j                  |
       )  ||      t        ||      fS )a  
    Return a nested list/tuple structure representing the tree
    built by the transitive property given, starting from the root given

    i.e.

    get_tree(graph,
       rdflib.URIRef("http://xmlns.com/foaf/0.1/Person"),
       rdflib.RDFS.subClassOf)

    will return the structure for the subClassTree below person.

    dir='down' assumes triple of the form (child, prop, parent),
    i.e. the direction of RDFS.subClassOf or SKOS.broader
    Any other dir traverses in the other direction

    Nr   )key)r/   r0   subjectsobjectsr(   appendsorted)rr   rootr   mappersortkeydonedirtreebranchesbranchr   s              r4   r(   r(     s    6 |ut|HHTND f}>>$-==t,UFD&'4EKKN 
 4L&7344r8   c                     y r;   r6   rT   argss     r4   r)   r)     s    @Cr8   .)rT   c                     y r;   r6   r   s     r4   r)   r)     s     r8   c                     |D ]  }||c S  | S )a  
    This is a null coalescing function, it will return the first non-`None`
    argument passed to it, otherwise it will return ``default`` which is `None`
    by default.

    For more info regarding the rationale of this function see deferred `PEP 505
    <https://peps.python.org/pep-0505/>`_.

    :param args: Values to consider as candidates to return, the first arg that
        is not `None` will be returned. If no argument is passed this function
        will return None.
    :param default: The default value to return if none of the args are not
        `None`.
    :return: The first ``args`` that is not `None`, otherwise the value of
        ``default`` if there are no ``args`` or if all ``args`` are `None`.
    r6   )rT   r   args      r4   r)   r)     s    & ?J  Nr8   z!$&'()*+,;=%z:@z/?/c                   t        |       }|\  }}}}}|dvr| S t        |t              }t        |t              }t        |t              }|j                  r+|j                  j                  d      j                  d      }nd}d|v rd| d}|j                  r| d|j                   }|j                  rPt        |j                  t              }|j                  r"t        |j                  t              }| d| }| d	| }t        |||||f      }	| j                  d
      r|	j                  d
      s|	d
z  }	|	S )u  
    Prior art:

    * `iri_to_uri from Werkzeug <https://github.com/pallets/werkzeug/blob/92c6380248c7272ee668e1f8bbd80447027ccce2/src/werkzeug/urls.py#L926-L931>`_

    >>> _iri2uri("https://dbpedia.org/resource/Almería")
    'https://dbpedia.org/resource/Almer%C3%ADa'
    )httphttps)safeidnaasciir\   rb   ra   ]rX   #)r   r   _PATH_SAFE_CHARS_QUERY_SAFE_CHARShostnamerc   rd   portusername_USERNAME_SAFE_CHARSpasswordr   rM   )
iripartsschemenetlocpathqueryfragmentauthpass_quoteduris
             r4   r*   r*   8  s8    SME.3+VVT5( &&
,-D%/0EX$56H~~&&v.55g>
f}VHAzz81UZZL)~~U^^*>?>>5IJKV1[M*D66(#
ffdE8<
=C
||Cc!2s
Jr8   )r1   zIterable[_HashableT]returnzList[_HashableT])r1   zIterable[_AnyT]r   Optional[_AnyT])r   )r@   zIterable[str]r<   rp   r   zSet[str])r@   zIterable[Any]rC   rp   r   rp   r;   )r>   Optional[str]rT    Optional[rdflib.term.Identifier]r   r   )NNN)
r>   strrT   r   ry   r   rz   z+Optional[rdflib.namespace.NamespaceManager]r   z&Optional[Union[rdflib.term.Node, str]])NF)r   r   r   rp   )r   r   r   zOptional[Dict[str, str]]r   r   )T)r   r   ri   boolr   r   )rr   r   r   rdflib.term.URIRefr   Optional[Set[rdflib.term.Node]]r   zSet[rdflib.term.Node])rr   r   r   zrdflib.term.Noder   r   r   z.Callable[[rdflib.term.Node], rdflib.term.Node]r   zOptional[Callable[[Any], Any]]r   r   r   r   r   z,Optional[Tuple[rdflib.term.Node, List[Any]]])r   r   rT   r-   r   r-   )r   r   rT   r   r   r   )r   r   r   r   )=__doc__
__future__r   calendarr   os.pathr   r	   r   r   r   r
   typingr   r   r   r   r   r   r   r   r   r   r   r   r   r   urllib.parser   r   r   rdflib.graphrN   rdflib.namespacerdflib.termrdflib.compatr   r   __all__r+   r-   r   r   r    r!   r"   r#   r$   r%   r   r&   r   r'   r(   r)   _RFC3986_SUBDELIMS_RFC3986_PCHAR_NUr   r   r   r*   r6   r8   r4   <module>r     s  , #   < ;     5 4    "  \2
A CG?%> "!7;	l$
l$l$ l$ 
5	l$
 ,l$^ F)X	5	5 
5 	$	
 
8 	$ F V F 
6 	( h F I i  y! (@D6 .2
 + 	@ >I.2,0.5.5
.5 .5 ;	.5
 ,.5 *.5 
.5 2.5b 
 C 
 C 
7:%4 
 8<%42 # 
 ,,t3  &,  *C/ 
 %s* /r8   