o
    ӷ6i,                     @   s|   d Z ddlZddlZddlZddlZddlmZ dZdd Z	de
fdd	Z					dd
dZdddZdd Zdd ZdS )zL
Utilities for working with lists of model instances which represent
trees.
    N)gettext)drilldown_tree_for_nodeget_cached_treesprevious_current_nexttree_item_iteratorc                 C   sH   t dg| dg}t |d\}}}t| t| t| t|||S )z
    From http://www.wordaligned.org/articles/zippy-triples-served-with-python

    Creates an iterator which returns (previous, current, next) triples,
    with ``None`` filling in when there is no previous or next
    available.
    N   )	itertoolschainteenextzip)itemsextendprevcurnex r   O/var/www/hoanhtaovolam_webdjango/env/lib/python3.10/site-packages/mptt/utils.pyr      s   r   Fc           
      c   s    i }d}d}t | D ]r\}}}|du r|j}t||j}	|rLt||j|	k |d< |rK|d r>|d dt|d   |d< |d rK|d || nd|d< |rVg |d< |	}|ritt|	t||jd|d< ntt|	|d d|d< |t	|fV  qdS )	a>  
    Given a list of tree items, iterates over the list, generating
    two-tuples of the current tree item and a ``dict`` containing
    information about the tree structure around the item, with the
    following keys:

       ``'new_level'``
          ``True`` if the current item is the start of a new level in
          the tree, ``False`` otherwise.

       ``'closed_levels'``
          A list of levels which end after the current item. This will
          be an empty list if the next item is at the same level as the
          current item.

    If ``ancestors`` is ``True``, the following key will also be
    available:

       ``'ancestors'``
          A list of representations of the ancestors of the current
          node, in descending order (root node first, immediate parent
          last).

          For example: given the sample tree below, the contents of the
          list which would be available under the ``'ancestors'`` key
          are given on the right::

             Books                    ->  []
                Sci-fi                ->  ['Books']
                   Dystopian Futures  ->  ['Books', 'Sci-fi']

          You can overload the default representation by providing an
          optional ``callback`` function which takes a single argument
          and performs coercion as required.

    Nr   	new_levelclosed_levels	ancestorsT   )
r   
_mptt_metagetattr
level_attrlenappendlistrangecopydeepcopy)
r   r   callback	structureoptsfirst_item_levelpreviouscurrentnext_current_levelr   r   r   r   *   s>   %
r   c                 C   sH   |r|   n|  }|r|r|r| j|||||}t|  | g|S )a  
    Creates a drilldown tree for the given node. A drilldown tree
    consists of a node's ancestors, itself and its immediate children
    or all descendants, all in tree order.

    Optional arguments may be given to specify a ``Model`` class which
    is related to the node's class, for the purpose of adding related
    item counts to the node's children:

    ``rel_cls``
       A ``Model`` class which has a relation to the node's class.

    ``rel_field``
       The name of the field in ``rel_cls`` which holds the relation
       to the node's class.

    ``count_attr``
       The name of an attribute which should be added to each child in
       the drilldown tree, containing a count of how many instances
       of ``rel_cls`` are related through ``rel_field``.

    ``cumulative``
       If ``True``, the count will be for each child and all of its
       descendants, otherwise it will be for each child itself.

    ``all_descendants``
       If ``True``, return all descendants, not just immediate children.
    )get_descendantsget_children_tree_manageradd_related_countr   r	   get_ancestors)noderel_cls	rel_field
count_attr
cumulativeall_descendantschildrenr   r   r   r   |   s   $
r   c           
      C   s   | j j}t|du rtjn|}d|jd|j |j|j	|j
df}|| | ddD ]/}t||j}g }|dd D ]
}|t|| q;dd	| t|}	||	 || q+dS )
z
    Given an mptt queryset, prints some debug information to stdout.
    Use this when things go wrong.
    Please include the output from this method when filing bug issues.
    Npkz%s_idprettytree_idlftr   z{}{}z- )modelr   csvwritersysstdoutr   parent_attrtree_id_attr	left_attr
right_attrwriteroworder_byr   r   formatstr)
qsfiler$   r<   headernlevelrowfieldrow_textr   r   r   print_debug_info   s(   
	
rO   c                 C   s>   t |  }|r| }t|dr|jjs|jjs|S |sd S )Nr   )r   mropophasattr_metaabstractproxy)model_classbasesbr   r   r   _get_tree_model   s   rY   c           
         sP  g } fdd}| rt | do| j }g }d}d}dd d| D ]}g |_|dk|_| }|du s<|rQ||k rQ| }|jj}|jj|jj	 |jj
n||k r`ttdt| f |t|krq|g  |t|ksf|| | ||kr||||d  }	|	durt|||	 |	j| nd}	||ks|	du r|| q$|S )	a  
    Cache the parents and children on a queryset of MPTT instances.
    Args:
        queryset:
            List or queryset of _all_ the nodes that will have a cache.
            Instances not in the queryset will not be retrieved using the
            cache.
    Notes:
        Takes a list/queryset of model objects in MPTT (ordered by depth ASC)
        and caches the children and parent of every node. This allows up and down
        traversal through the tree without the need for further queries. Use cases
        include using a recursively included template or arbitrarily traversing
        trees.
        Any instance which has no parent in the provided queryset will be added
        to the top nodes list.
        For it to return proper results, queryset _must_ be ordered by ascending
        level.
    Returns:
        A list of top-level nodes, one node per tree root.
    See Also:
        Aliases to this function are also available:
        ``mptt.templatetags.mptt_tag.cache_tree_children``
           Use for recursive rendering in templates.
        ``mptt.querysets.TreeQuerySet.get_cached_trees``
           Useful for chaining with queries; e.g.,
           `Node.objects.filter(**kwargs).get_cached_trees()`
    c                    sb   |D ],}t |t | kr.t | t |    kr,t |   kr,t |kr.|  S  qqdS )a  
        Find the parent of ``obj`` in a list of items of the upper level.
        Args:
            obj: Instance to find a parent for.
            tree_level: List of instances at the upper level.
        Returns:
            The instance that is the correct parent for ``obj``.
            ``None`` if ``obj`` has no parent in the list.
        Notes:
            ``lft`` and ``right`` define the bounds of a tree node.
            Any child node has bounds inside the bounds of its
             parent.
        N)r   )obj
tree_levelitemrA   rB   r@   r   r   find_parent   s    z%get_cached_trees.<locals>.find_parentqueryN r   z Node %s not in depth-first orderr   )rR   r_   has_filters_cached_children_mptt_use_cached_ancestors	get_levelr   r?   r@   rA   rB   
ValueError_typer   r   setattr)
queryset	top_nodesr^   is_filteredtree
root_levelr?   rZ   
node_levelparentr   r]   r   r      sN   



r   )NNNFF)N)__doc__r    r;   r   r=   django.utils.translationr   rf   __all__r   rF   r   r   rO   rY   r   r   r   r   r   <module>   s$    T

,