
    d2                         d 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 d	 Z G d
 de          Z G d dej        e          Z G d dej        e          ZdS )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:

    )PathN   )linkextension)Node)lazyattrAttributeSetc                 ,    t          j        | |          S )zGuess the link class.)r   _get_link_class)	parent_idnames     +lib/python3.11/site-packages/tables/link.py_g_get_link_classr      s     (D999    c                   b     e Zd ZdZed             Zd fd	Z	 	 ddZddZd Z	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                 >     G d dt                     } ||           S )z
        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 Zd Zd ZdS )Link._v_attrs.<locals>.NoAttrsc                 :    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__?   *      /151H I J J Jr   c                 :    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__C   r   r   c                     d S N r   s    r   _g_closez'Link._v_attrs.<locals>.NoAttrs._g_closeG   s    r   N)r   
__module____qualname__r   r    r%   r#   r   r   NoAttrsr   >   sG        J J JJ J J    r   r(   r   )r   r(   s     r   _v_attrszLink._v_attrs7   s<    
	 
	 
	 
	 
	l 
	 
	 
	 wt}}r   NFc                 p    |d u| _         || _        	 t                                          |||           d S r"   )_v_newtargetsuper__init__r   
parentnoder   r,   _logr   s        r   r.   zLink.__init__K   s;    D(2T400000r   c                 p    |                      ||||          }|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   r3   r4   r5   r6   newnodes         r   copyz	Link.copyS   sH     ,,G)2-:  < < 	$$Wgt<<<r   c                 2    |                      |||          S )zrMove or rename this link.

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

        )r3   r4   r5   )_f_move)r   r3   r4   r5   s       r   movez	Link.moved   s&     ||i&/  1 1 	1r   c                 *    |                                  S )z$Remove this link from the hierarchy.)	_f_remover$   s    r   removezLink.removen   s     ~~r   c                 0    |                      ||          S )zuRename this link in place.

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

        )r4   r5   )	_f_rename)r   r4   r5   s      r   renamezLink.renames   s     ~~g~CCCr   c                      t          |           S r"   )strr$   s    r   __repr__zLink.__repr__|   s    4yyr   NF)NNFF)NNF)r   r&   r'   __doc__r   r)   r.   r;   r>   rA   rD   rG   __classcell__r   s   @r   r   r   "   s         (   X&1 1 1 1 1 1 ,0,1   "1 1 1 1     
D D D D      r   r   c                   N    e Zd ZdZdZdZdZd Zd Zd Z	d Z
d	 Zd
 Zd Zd ZdS )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)r,   dereferenceis_danglingr;   r>   rA   rD   r.   __str__rG   __unicode__r   __dict__)_f__c__g__v_c                 *    |                                  S )aD  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()

        )rO   r$   s    r   __call__zSoftLink.__call__   s      !!!r   c                     | j         rZ| j        }| j                            d          s| j                            | j                  }| j                            |          S d S )N/)	_v_isopenr,   
startswithr8   _g_join_v_file	_get_node)r   r,   s     r   rO   zSoftLink.dereference   s]    > 	[F;))#.. =//<<<))&1114r   c                    |t           j        v s|d d         t           j        v rt                              | |          S | j        st          j        d          |                                 rd S | 	                                }	 |                    |          S # t          $ r |                    |          cY S w xY w)N   the node object is closed)rM   _link_attrnames_link_attrprefixesobject__getattribute__r\   tbClosedNodeErrorrP   rO   AttributeErrorr   )r   attrnametarget_nodes      r   rg   zSoftLink.__getattribute__   s     000! ;;;**4:::  	9$%@AAA 		94**,,K9"33H===! 9 9 9"..x888889s   B B=<B=c                 V   |t           j        v s|d d         t           j        v rt                              | ||           d S | j        st          j        d          |                                 rt          d          | 
                                                    ||           d S )Nrb   rc   softlink target does not exist)rM   rd   re   rf   r    r\   rh   ri   rP   
ValueErrorrO   )r   rk   r   s      r   r    zSoftLink.__setattr__   s     000! ;;;tXu55555  	<$%@AAA 	<=>>>**8U;;;;;r   c                     | j         st          j        d          |                                 rt	          d          |                                                     |          S )zd__getitem__ must be defined in the SoftLink class in order for array
        indexing syntax to workrc   rn   )r\   rh   ri   rP   ro   rO   __getitem__)r   keys     r   rq   zSoftLink.__getitem__  sc     ~ 	7$%@AAA 	7=>>>##%%11#666r   c                     | j         st          j        d          |                                 rt	          d          |                                                     ||           dS )zd__setitem__ must be defined in the SoftLink class in order for array
        indexing syntax to workrc   rn   N)r\   rh   ri   rP   ro   rO   __setitem__)r   rr   r   s      r   rt   zSoftLink.__setitem__  sk     ~ 	7$%@AAA 	7=>>>**366666r   c                 8    |                                  | j        vS r"   )rO   r_   r$   s    r   rP   zSoftLink.is_dangling  s    $$&&$,67r   c                    t          | j                  }| j                            d          s| j                            | j                  }| j        rdnd}|| j        v rdnd}| | j         d| j        j	         d| j         | S )a   Return a short string representation of the link.

        Examples
        --------

        ::

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

        r[    zclosed z (dangling) () -> )
rF   r,   r]   r8   r^   r\   r_   _v_pathnamer   r   )r   r,   closeddanglings       r   rQ   zSoftLink.__str__  s     T[!!{%%c** 	9^++DK88F~494<//22] +4+ + +t~/F + +;+ (+ + 	,r   N)r   r&   r'   rI   
_c_classidrd   re   rY   rO   rg   r    rq   rt   rP   rQ   r#   r   r   rM   rM      s        3 3l J?O 6" " "$	 	 	9 9 9*< < <	7 	7 	7	7 	7 	78 8 8, , , , ,r   rM   c                   J     e Zd ZdZdZd fd	Zd Zd Zd Z fd	Z	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.

    EXTERNALLINKNFc                 `    d | _         	 t                                          ||||           d S r"   )extfiler-   r.   r/   s        r   r.   zExternalLink.__init__H  s5    	 	T6488888r   c                 J    | j                             d          \  }}|d|z   fS )z=Return the external filename and nodepath from `self.target`.z:/r[   )r,   split)r   filenamer,   s      r   _get_filename_nodezExternalLink._get_filename_nodeO  s-      ;,,T22&v%%r   c                    |                                  \  }}t          |                                          s9t          t          | j        j                                      |                    }| j        | j        j        st          j
        |fi || _        n8| j        j        |k    sJ | j        j        |                    dd          k    s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()

        Nmoder)r   r   is_absoluterF   r_   r   	with_namer   isopenrh   	open_filer   getr`   )r   kwargsr   r,   s       r   rY   zExternalLink.__call__V  s    0  2244&H~~))++ 	L 4 566@@JJKKH<t|':<;;F;;DLL <(H4444<$

63(?(?????|%%f---r   c                 d    | j         }|$|j        r|                                 d| _         dS dS dS )z'Safely unmount self.extfile, if opened.N)r   r   close)r   r   s     r   umountzExternalLink.umount~  s>     ,7>MMOOODLLL r   c                 p    |                                   t                                                       dS )z#Especific close for external links.N)r   r-   _f_close)r   r   s    r   r   zExternalLink._f_close  s.     	r   c                 >    | 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()

        rx   ry   )rz   r   r   r,   r$   s    r   rQ   zExternalLink.__str__  s9     # ! !t~'> ! !;! ! 	"r   rH   )r   r&   r'   rI   r}   r.   r   rY   r   r   rQ   rJ   rK   s   @r   r   r   3  s         $  J9 9 9 9 9 9& & &&. &. &.P         " " " " " " "r   r   )rI   pathlibr   tablesrh   rw   r   noder   utilsr   attributesetr	   r   r   rM   r   r#   r   r   <module>r      s4   "                             & & & & & &: : :[ [ [ [ [4 [ [ [|p, p, p, p, p,}%t p, p, p,fj" j" j" j" j"=-t j" j" j" j" j"r   