
    Kg]7                       d Z ddlmZ ddlmZmZmZmZ ddlm	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 erddlmZ 	 	 	 	 	 	 ddZ G d de      Z G d dej0                  e      Z G d dej2                  e      Zy)a  Create links in the HDF5 file.

This module implements containers for soft and external links.  Hard
links doesn't need a container as such as they are the same as regular
nodes (groups or leaves).

Classes:

    SoftLink
    ExternalLink

Functions:

Misc variables:

    )annotations)AnyLiteralNoReturnTYPE_CHECKING)PathN   )linkextension)Node)lazyattrAttributeSet)Groupc                .    t        j                  | |      S )zGuess the link class.)r
   _get_link_class)	parent_idnames     +lib/python3.12/site-packages/tables/link.py_g_get_link_classr   "   s     ((D99    c                       e Zd ZdZed	d       Z	 	 d
	 	 	 	 	 	 	 	 	 d fdZ	 	 	 	 d	 	 	 	 	 	 	 	 	 ddZ	 	 	 d	 	 	 	 	 	 	 ddZddZ		 d
	 	 	 	 	 ddZ
d Z xZS )Linka  Abstract base class for all PyTables links.

    A link is a node that refers to another node.  The Link class inherits from
    Node class and the links that inherits from Link are SoftLink and
    ExternalLink.  There is not a HardLink subclass because hard links behave
    like a regular Group or Leaf.  Contrarily to other nodes, links cannot have
    HDF5 attributes.  This is an HDF5 library limitation that might be solved
    in future releases.

    See :ref:`LinksTutorial` for a small tutorial on how to work with links.

    .. rubric:: Link attributes

    .. attribute:: target

        The path string to the pointed node.

    c                0     G d dt               } ||       S )zAttributes.

        A *NoAttrs* instance replacing the typical *AttributeSet* instance of
        other node objects.  The purpose of *NoAttrs* is to make clear that
        HDF5 attributes are not supported in link nodes.
        c                  $    e Zd ZddZddZddZy)Link._v_attrs.<locals>.NoAttrsc                F    t        d| j                  j                  z        )Nz1you cannot get attributes from this `%s` instanceKeyError	__class____name__)selfr   s     r   __getattr__z*Link._v_attrs.<locals>.NoAttrs.__getattr__H   &    $&*nn&=&=> r   c                F    t        d| j                  j                  z        )Nz/you cannot set attributes to this `%s` instancer   )r!   r   values      r   __setattr__z*Link._v_attrs.<locals>.NoAttrs.__setattr__N   r#   r   c                     y N r!   s    r   _g_closez'Link._v_attrs.<locals>.NoAttrs._g_closeT   s    r   N)r   strreturnr   )r   r,   r%   r   r-   r   r-   None)r    
__module____qualname__r"   r&   r+   r)   r   r   NoAttrsr   G   s    r   r2   r   )r!   r2   s     r   _v_attrszLink._v_attrs>   s    	l 	  t}r   c                J    |d u| _         || _        	 t        |   |||       y r(   )_v_newtargetsuper__init__r!   
parentnoder   r6   _logr   s        r   r8   zLink.__init__Y   s,     D(2T40r   c                j    | j                  ||||      }|j                  j                  ||d       |S )zCopy this link and return the new one.

        See :meth:`Node._f_copy` for a complete explanation of the arguments.
        Please note that there is no recursive flag since links do not have
        child nodes.

        )	newparentnewname	overwritecreateparentsT)_f_copy	_v_parent
_g_refnode)r!   r=   r>   r?   r@   newnodes         r   copyz	Link.copyg   sB     ,,'	  
 	$$Wgt<r   c                *    | j                  |||      S )zrMove or rename this link.

        See :meth:`Node._f_move` for a complete explanation of the arguments.

        )r=   r>   r?   )_f_move)r!   r=   r>   r?   s       r   movez	Link.move   s!     ||I  
 	
r   c                "    | j                         S )z$Remove this link from the hierarchy.)	_f_remover*   s    r   removezLink.remove   s    ~~r   c                (    | j                  ||      S )zuRename this link in place.

        See :meth:`Node._f_rename` for a complete explanation of the arguments.

        )r>   r?   )	_f_rename)r!   r>   r?   s      r   renamezLink.rename   s     ~~g~CCr   c                    t        |       S r(   )r,   r*   s    r   __repr__zLink.__repr__   s    4yr   )r-   r   NF
r:   r   r   r,   r6   
str | Noner;   boolr-   r/   )NNFF)
r=   Group | Noner>   rS   r?   rT   r@   rT   r-   r   )NNF)r=   rU   r>   rS   r?   rT   r-   r/   r.   )r>   rS   r?   rT   r-   r/   )r    r0   r1   __doc__r   r3   r8   rE   rH   rK   rN   rP   __classcell__r   s   @r   r   r   )   s   (  < "11 1 	1
 1 
1  #'"#  	
  
4 #'"	

 
 	

 

 
 =BD!D59D	Dr   r   c                  \    e Zd ZdZdZdZ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y)SoftLinka;  Represents a soft link (aka symbolic link).

    A soft link is a reference to another node in the *same* file hierarchy.
    Provided that the target node exists, its attributes and methods can be
    accessed directly from the softlink using the normal `.` syntax.

    Softlinks also have the following public methods/attributes:

        * `target`
        * `dereference()`
        * `copy()`
        * `move()`
        * `remove()`
        * `rename()`
        * `is_dangling()`

    Note that these will override any correspondingly named methods/attributes
    of the target node.

    For backwards compatibility, it is also possible to obtain the target node
    via the `__call__()` special method (this action is called *dereferencing*;
    see below)

    Examples
    --------
    ::

        >>> import numpy as np
        >>> f = tb.open_file('/tmp/test_softlink.h5', 'w')
        >>> a = f.create_array('/', 'A', np.arange(10))
        >>> link_a = f.create_soft_link('/', 'link_A', target='/A')

        # transparent read/write access to a softlinked node
        >>> link_a[0] = -1
        >>> link_a[:], link_a.dtype
        (array([-1,  1,  2,  3,  4,  5,  6,  7,  8,  9]), dtype('int64'))

        # dereferencing a softlink using the __call__() method
        >>> link_a() is a
        True

        # SoftLink.remove() overrides Array.remove()
        >>> link_a.remove()
        >>> print(link_a)
        <closed tables.link.SoftLink at ...>
        >>> a[:], a.dtype
        (array([-1,  1,  2,  3,  4,  5,  6,  7,  8,  9]), dtype('int64'))
        >>> f.close()

    SOFTLINK)r6   dereferenceis_danglingrE   rH   rK   rN   r8   __str__rP   __unicode__r   __dict__)_f__c__g__v_c                "    | j                         S )aC  Dereference `self.target` and return the object.

        Examples
        --------
        ::

            >>> f = tb.open_file('tables/tests/slink.h5')
            >>> f.root.arr2
            /arr2 (SoftLink) -> /arr
            >>> print(f.root.arr2())
            /arr (Array(2,)) ''
            >>> f.close()

        )r\   r*   s    r   __call__zSoftLink.__call__   s     !!r   c                    | j                   rg| j                  }| j                  j                  d      s%| j                  j	                  | j                        }| j
                  j                  |      S y)zDereference a link./N)	_v_isopenr6   
startswithrB   _g_join_v_file	_get_node)r!   r6   s     r   r\   zSoftLink.dereference   sT    >>[[F;;))#.//<<<))&11r   c                d   |t         j                  v s|d d t         j                  v rt        j	                  | |      S | j
                  st        j                  d      | j                         ry | j                         }	 |j	                  |      S # t        $ r |j                  |      cY S w xY w)N   the node object is closed)rZ   _link_attrnames_link_attrprefixesobject__getattribute__ri   tbClosedNodeErrorr]   r\   AttributeErrorr"   )r!   attrnametarget_nodes      r   rt   zSoftLink.__getattribute__  s     000|x:::**4:: $$%@AA**,K9"33H==! 9"..x889s   B B/.B/c                :   |t         j                  v s|d d t         j                  v rt        j	                  | ||       y | j
                  st        j                  d      | j                         rt        d      | j                         j	                  ||       y )Nro   rp   softlink target does not exist)rZ   rq   rr   rs   r&   ri   ru   rv   r]   
ValueErrorr\   )r!   rx   r%   s      r   r&   zSoftLink.__setattr__  s     000|x:::tXu5 $$%@AA=>>**8U;r   c                    | j                   st        j                  d      | j                         rt	        d      | j                         j                  |      S )zGetitem magic method.

        The __getitem__ must be defined in the SoftLink class in order
        for array indexing syntax to work.
        rp   r{   )ri   ru   rv   r]   r|   r\   __getitem__)r!   keys     r   r~   zSoftLink.__getitem__.  sO     ~~$$%@AA=>>##%11#66r   c                    | j                   st        j                  d      | j                         rt	        d      | j                         j                  ||       y)zSetitem magic method.

        The __setitem__ method must be defined in the SoftLink class
        in order for array indexing syntax to work.
        rp   r{   N)ri   ru   rv   r]   r|   r\   __setitem__)r!   r   r%   s      r   r   zSoftLink.__setitem__;  sN     ~~$$%@AA=>>**36r   c                :    | j                         | j                  vS )z$Return True if the link is dangling.)r\   rl   r*   s    r   r]   zSoftLink.is_danglingH  s    $$&$,,67r   c                \   t        | j                        }| j                  j                  d      s%| j                  j	                  | j                        }| j
                  rdnd}|| j                  v rdnd}| | j                   d| j                  j                   d| j                   | S )zReturn a short string representation of the link.

        Examples
        --------
        ::

            >>> f = tb.open_file('tables/tests/slink.h5')
            >>> f.root.arr2
            /arr2 (SoftLink) -> /arr
            >>> f.close()

        rh    zclosed z (dangling) () -> )
r,   r6   rj   rB   rk   ri   rl   _v_pathnamer   r    )r!   r6   closeddanglings       r   r^   zSoftLink.__str__L  s     T[[!{{%%c*^^++DKK8F~~94<</2]ht''(4>>+B+B*C5{{mH:'	
r   N)r-   zNode | None)rx   r,   r-   r   )rx   r,   r%   r   r-   r/   )r   r,   r-   r   )r   r,   r%   r   r-   r/   )r-   rT   r-   r,   )r    r0   r1   rV   
_c_classidrq   rr   rf   r\   rt   r&   r~   r   r]   r^   r)   r   r   rZ   rZ      sF    1h JO 6""	9.<"778
r   rZ   c                  l     e Zd ZdZdZ	 	 d		 	 	 	 	 	 	 	 	 d
 fdZddZddZddZd fdZ	ddZ
 xZS )ExternalLinka  Represents an external link.

    An external link is a reference to a node in *another* file.
    Getting access to the pointed node (this action is called
    *dereferencing*) is done via the :meth:`__call__` special method
    (see below).

    .. rubric:: ExternalLink attributes

    .. attribute:: extfile

        The external file handler, if the link has been dereferenced.
        In case the link has not been dereferenced yet, its value is
        None.

    EXTERNALLINKc                :    d | _         	 t        | 	  ||||       y r(   )extfiler7   r8   r9   s        r   r8   zExternalLink.__init__z  s&     	 	T648r   c                L    | j                   j                  d      \  }}|d|z   fS )z=Return the external filename and nodepath from `self.target`.z:/rh   )r6   split)r!   filenamer6   s      r   _get_filename_nodezExternalLink._get_filename_node  s,      ;;,,T2&v%%r   c                   | j                         \  }}t        |      j                         s5t        t        | j                  j
                        j                  |z        }| j                  | j                  j                  st        j                  |fi || _        nF| j                  j
                  |k(  sJ | j                  j                  |j                  dd      k(  sJ | j                  j                  |      S )a  Dereference self.target and return the object.

        You can pass all the arguments supported by the :func:`open_file`
        function (except filename, of course) so as to open the referenced
        external file.

        Examples
        --------
        ::

            >>> f = tb.open_file('tables/tests/elink.h5')
            >>> f.root.pep.pep2
            /pep/pep2 (ExternalLink) -> elink2.h5:/pep
            >>> pep2 = f.root.pep.pep2(mode='r')  # open in 'r'ead mode
            >>> print(pep2)
            /pep (Group) ''
            >>> pep2._v_file.filename       # belongs to referenced file
            'tables/tests/elink2.h5'
            >>> f.close()

        moder)r   r   is_absoluter,   rl   r   parentr   isopenru   	open_filer   getrm   )r!   kwargsr   r6   s       r   rf   zExternalLink.__call__  s    ,  224&H~))+ 4 5 56==HIH<<t||':':<<;F;DL <<((H444<<$$

63(????||%%f--r   c                j    | j                   }|%|j                  r|j                          d| _         yyy)z'Safely unmount self.extfile, if opened.N)r   r   close)r!   r   s     r   umountzExternalLink.umount  s/    ,,7>>MMODL $2r   c                B    | j                          t        | 	          y)z#Especific close for external links.N)r   r7   _f_close)r!   r   s    r   r   zExternalLink._f_close  s    r   c                f    | j                    d| j                  j                   d| j                   S )a  Return a short string representation of the link.

        Examples
        --------
        ::

            >>> f = tb.open_file('tables/tests/elink.h5')
            >>> f.root.pep.pep2
            /pep/pep2 (ExternalLink) -> elink2.h5:/pep
            >>> f.close()

        r   r   )r   r   r    r6   r*   s    r   r^   zExternalLink.__str__  s6      4>>#:#:";5{{m	
r   rQ   rR   )r-   ztuple[str, str])r-   r   r.   r   )r    r0   r1   rV   r   r8   r   rf   r   r   r^   rW   rX   s   @r   r   r   e  sf    $  J "99 9 	9
 9 
9&$.L 

r   r   )r   intr   r,   r-   z@Literal['ExternalLink', 'HardLink', 'SoftLink', 'UnImplemented'])rV   
__future__r   typingr   r   r   r   pathlibr   tablesru   r   r
   noder   utilsr   attributesetr   groupr   r   r   rZ   r   r)   r   r   <module>r      s   " # 8 8      &:::E:t4 tnB
}%%t B
Jk
=--t k
r   