
    D6i(                     Z    d dl Z ddlmZ  e j                  d      Ze G d d             Zy)    N   )str_coerciblez#^[A-Za-z0-9_-]+(\.[A-Za-z0-9_-]+)*$c                       e Zd ZdZd Ze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 Zd Zd Zd Zd Zd Zy)Ltreea  
    Ltree class wraps a valid string label path. It provides various
    convenience properties and methods.

    ::

        from sqlalchemy_utils import Ltree

        Ltree('1.2.3').path  # '1.2.3'


    Ltree always validates the given path.

    ::

        Ltree(None)  # raises TypeError

        Ltree('..')  # raises ValueError


    Validator is also available as class method.

    ::

        Ltree.validate('1.2.3')
        Ltree.validate(None)  # raises TypeError


    Ltree supports equality operators.

    ::

        Ltree('Countries.Finland') == Ltree('Countries.Finland')
        Ltree('Countries.Germany') != Ltree('Countries.Finland')


    Ltree objects are hashable.


    ::

        assert hash(Ltree('Finland')) == hash('Finland')


    Ltree objects have length.

    ::

        assert len(Ltree('1.2')) == 2
        assert len(Ltree('some.one.some.where'))  # 4


    You can easily find subpath indexes.

    ::

        assert Ltree('1.2.3').index('2.3') == 1
        assert Ltree('1.2.3.4.5').index('3.4') == 2


    Ltree objects can be sliced.


    ::

        assert Ltree('1.2.3')[0:2] == Ltree('1.2')
        assert Ltree('1.2.3')[1:] == Ltree('2.3')


    Finding longest common ancestor.


    ::

        assert Ltree('1.2.3.4.5').lca('1.2.3', '1.2.3.4', '1.2.3') == '1.2'
        assert Ltree('1.2.3.4.5').lca('1.2', '1.2.3') == '1'


    Ltree objects can be concatenated.

    ::

        assert Ltree('1.2') + Ltree('1.2') == Ltree('1.2.1.2')
    c                     t        |t              r|j                  | _        y t        |t              r| j	                  |       || _        y t        dj                  t        |      j                              )Nz7Ltree() argument must be a string or an Ltree, not '{}')	
isinstancer   pathstrvalidate	TypeErrorformattype__name__)selfpath_or_ltrees     d/home/azureuser/techstart-app/venv/lib/python3.12/site-packages/sqlalchemy_utils/primitives/ltree.py__init__zLtree.__init___   s_    mU+%**DIs+MM-(%DIIPP'00     c                 L    t         j                  |      t        d| d      y )N'z' is not a valid ltree path.)path_matchermatch
ValueError)clsr	   s     r   r   zLtree.validatel   s-    d#+q&BCDD ,r   c                 J    t        | j                  j                  d            S N.)lenr	   splitr   s    r   __len__zLtree.__len__q   s    499??3'((r   c                     t        |      j                  j                  d      }| j                  j                  d      }t        |      D ]  \  }}||t	        |      |z    |k(  s|c S  t        d      )Nr   zsubpath not found)r   r	   r   	enumerater   r   )r   othersubpathpartsindex_s         r   r'   zLtree.indext   sq    ,##))#.		$!%( 	HE1US\E12g=	 ,--r   c                 :    | dt        t        |             }||k(  S )z
        is left argument a descendant of right (or equal)?

        ::

            assert Ltree('1.2.3.4.5').descendant_of('1.2.3')
        N)r   r   r   r$   r%   s      r   descendant_ofzLtree.descendant_of|   s%     *U5\*+%r   c                 :    t        |      dt        |        }|| k(  S )z
        is left argument an ancestor of right (or equal)?

        ::

            assert Ltree('1.2.3').ancestor_of('1.2.3.4.5')
        N)r   r   r*   s      r   ancestor_ofzLtree.ancestor_of   s"     ,{T+$r   c                 @   t        |t              r't        | j                  j	                  d      |         S t        |t
              r6t        dj                  | j                  j	                  d      |               S t        d|j                  j                         )Nr   z$Ltree indices must be integers, not )
r   intr   r	   r   slicejoinr   	__class__r   )r   keys     r   __getitem__zLtree.__getitem__   sw    c3-c233U#$))//#"6s";<==>s}}?U?U>VWXXr   c                 J   |D cg c]&  }t        |      j                  j                  d      ( }}| j                  j                  d      t              D ]A  \  t	        fd|D              sdk(  r yt        dj                  d             c S  yc c}w )z
        Lowest common ancestor, i.e., longest common prefix of paths

        ::

            assert Ltree('1.2.3.4.5').lca('1.2.3', '1.2.3.4', '1.2.3') == '1.2'
        r   c              3   z   K   | ]2  }|   k7  xs$ t        |      d z   k  xs t              d z   k(   4 yw)   N)r   ).0r$   elementr'   r&   s     r   	<genexpr>zLtree.lca.<locals>.<genexpr>   sS        e' +u:*+u:*+s   8;r   N)r   r	   r   r#   anyr1   )r   othersr$   other_partsr9   r'   r&   s       @@@r   lcaz	Ltree.lca   s     BHHuU|((..s3HH		$'. 		7NE7  )	  A:SXXeAen566		7 Is   +B c                 ^    t        | j                  dz   t        |      j                  z         S r   )r   r	   r   r$   s     r   __add__zLtree.__add__   s$    TYY_uU|'8'8899r   c                     t        |      | z   S N)r   r@   s     r   __radd__zLtree.__radd__   s    U|d""r   c                     t        |t              r| j                  |j                  k(  S t        |t              r| j                  |k(  S t        S rC   )r   r   r	   r
   NotImplementedr@   s     r   __eq__zLtree.__eq__   s>    eU#99

**s#99%%!!r   c                 ,    t        | j                        S rC   )hashr	   r    s    r   __hash__zLtree.__hash__   s    DIIr   c                     | |k(   S rC    r@   s     r   __ne__zLtree.__ne__   s    EM""r   c                 N    | j                   j                   d| j                  dS )N())r2   r   r	   r    s    r   __repr__zLtree.__repr__   s$    ..))*!DII=::r   c                     | j                   S rC   r	   r    s    r   __unicode__zLtree.__unicode__   s    yyr   c                 <    || j                   j                  d      v S r   )r	   r   )r   labels     r   __contains__zLtree.__contains__   s    		,,,r   c                 4    | j                   |j                   kD  S rC   rS   r@   s     r   __gt__zLtree.__gt__       yy5::%%r   c                 4    | j                   |j                   k  S rC   rS   r@   s     r   __lt__zLtree.__lt__   rZ   r   c                 4    | j                   |j                   k\  S rC   rS   r@   s     r   __ge__zLtree.__ge__       yyEJJ&&r   c                 4    | j                   |j                   k  S rC   rS   r@   s     r   __le__zLtree.__le__   r_   r   N)r   
__module____qualname____doc__r   classmethodr   r!   r'   r+   r-   r4   r>   rA   rD   rG   rJ   rM   rQ   rT   rW   rY   r\   r^   ra   rL   r   r   r   r      s    Sj E E).	 	Y7*:#"#;-&&''r   r   )reutilsr   compiler   r   rL   r   r   <module>ri      s8    	 !rzz@A L' L' L'r   