Ńņ
5ł!Ic           @   sw   d  Z  d d k Z d d k l Z d d k l Z l Z d d k l Z l	 Z	 l
 Z
 l Z d e i f d     YZ d S(   s   

    treebeard.models
    ----------------

    Django models.

    :copyright: 2008 by Gustavo Picon
    :license: Apache License 2.0

i’’’’N(   t   Q(   t   modelst   transaction(   t   InvalidPositiont   InvalidMoveToDescendantt   PathOverflowt   MissingNodeOrderByt   Nodec           B   sÅ  e  Z d  Z e d    Z e d( e d   Z e d( e d   Z	 e d    Z
 e d    Z e d    Z e d    Z e d    Z e d( d	   Z e d( 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( d  Z! d   Z" d   Z# d   Z$ d   Z% e d   Z& d( d!  Z' d"   Z( d#   Z) d$   Z* d%   Z+ d& d) d'     YZ, RS(*   s   Node class.

    This is the base class that defines the API of all tree models in this
    library:

        - :class:`mp_tree.MP_Node` (materialized path)
        - :class:`ns_tree.NS_Node` (nested sets)
        - :class:`al_tree.AL_Node` (adjacency list)

    c         K   s
   t   d S(   s=  
        Adds a root node to the tree. The new root node will be the new
        rightmost root node. If you want to insert a root node at a specific
        position, use :meth:`add_sibling` in an already existing root node
        instead.

        :param \*\*kwargs: object creation data that will be passed to the inherited
            Node model

        :returns: the created node object. It will be save()d by this method.

        Example::

            MyNode.add_root(numval=1, strval='abcd')
            MyNode.add_root(**{'numval':1, 'strval':'abcd'})

        N(   t   NotImplementedError(   t   clst   kwargs(    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   add_root%   s    c         C   s  g  } g  } | d d d  D] } | | | f q ~ } xŠ | oČ | i    \ } } | d i   }	 | o | d |	 d <n | o | i |	   }
 n |  i |	   }
 | i |
 i  d | j oC | i g  } | d d d d  D] } | |
 | f qē ~  q= q= Wt i   | S(   s]  
        Loads a list/dictionary structure to the tree.


        :param bulk_data:
        
            The data that will be loaded, the structure is a list of
            dictionaries with 2 keys:

            - ``data``: will store arguments that will be passed for object
              creation, and

            - ``children``: a list of dictionaries, each one has it's own
              ``data`` and ``children`` keys (a recursive structure)


        :param parent:
            
            The node that will receive the structure as children, if not
            specified the first level of the structure will be loaded as root
            nodes


        :param keep_ids:

            If enabled, lads the nodes with the same id that are given in the
            structure. Will error if there are nodes without id info or if the
            ids are already used.


        :returns: A list of the added node ids.

        .. note::

            Any internal data that you may have stored in your
            nodes' data (:attr:`path`, :attr:`depth`) will be
            ignored.

        .. note::

            If your node model has :attr:`node_order_by` enabled, it will
            take precedence over the order in the structure.

        Example::

            data = [{'data':{'desc':'1'}},
                    {'data':{'desc':'2'}, 'children':[
                      {'data':{'desc':'21'}},
                      {'data':{'desc':'22'}},
                      {'data':{'desc':'23'}, 'children':[
                        {'data':{'desc':'231'}},
                      ]},
                      {'data':{'desc':'24'}},
                    ]},
                    {'data':{'desc':'3'}},
                    {'data':{'desc':'4'}, 'children':[
                      {'data':{'desc':'41'}},
                    ]},
            ]
            # parent = None
            MyNodeModel.load_data(data, None)
        
        Will create:

            * 1
            * 2

              * 21
              * 22
              * 23

                * 231

              * 24

            * 3
            * 4

              * 41

        Ni’’’’t   datat   idt   children(	   t   popt   copyt	   add_childR   t   appendR   t   extendR   t   commit_unless_managed(   R	   t	   bulk_datat   parentt   keep_idst   addedt   _[1]t   nodet   stackt   node_structt	   node_datat   node_objt   _[2](    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt	   load_bulk;   s"    U4 ;
c         C   s
   t   d S(   sZ  
        Dumps a tree branch to a python data structure.

        :param parent:
            
            The node whose descendants will be dumped. The node itself will be
            included in the dump. If not given, the entire tree will be dumped.

        :param keep_ids:

            Stores the id value (primary key) of every node. Enabled by
            default.

        :returns: A python data structure, describen with detail in
                  :meth:`load_bulk`

        Example::

           tree = MyNodeModel.dump_bulk()

           branch = MyNodeModel.dump_bulk(node_obj)

        N(   R   (   R	   R   R   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt	   dump_bulk§   s    c         C   s
   t   d S(   s   
        :returns: A queryset containing the root nodes in the tree.

        Example::

           MyNodeModel.get_root_nodes()
        N(   R   (   R	   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   get_root_nodesĆ   s    	c         C   s-   y |  i    d SWn t j
 o d SXd S(   s   
        :returns: The first root node in the tree or ``None`` if it is empty

        Example::

           MyNodeModel.get_first_root_node()
        i    N(   R"   t
   IndexErrort   None(   R	   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   get_first_root_nodeĻ   s    	c         C   s3   y |  i    i   d SWn t j
 o d SXd S(   s   
        :returns: The last root node in the tree or ``None`` if it is empty

        Example::

           MyNodeModel.get_last_root_node()

        i    N(   R"   t   reverseR#   R$   (   R	   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   get_last_root_nodeŽ   s    
c         C   s
   t   d S(   s   
        Checks for problems in the tree structure.

        Read the documentation of this method on every tree class for details.
        N(   R   (   R	   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   find_problemsī   s    c         C   s
   t   d S(   sō   
        Solves some problems that can appear when transactions are not used and
        a piece of code breaks, leaving the tree in an inconsistent state.

        Read the documentation of this method on every tree class for details.
        N(   R   (   R	   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   fix_treeų   s    c         C   s
   t   d S(   s   
        :returns: A list of nodes ordered as DFS, including the parent. If
                  no parent is given, the entire tree is returned.
        N(   R   (   R	   R   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   get_tree  s    c         C   sY   | d j o |  i   } n | i   } t |  } x | D] } | i   | _ q< W| S(   sł  
        Helper for a very common case: get a group of siblings and the number
        of *descendants* (not only children) in every sibling.

        :param parent:
            
            The parent of the siblings to return. If no parent is given, the
            root nodes will be returned.
        
        :returns:

            A `list` (**NOT** a Queryset) of node objects with an extra
            attribute: `descendants_count`.

        Example::

            # get a list of the root nodes
            root_nodes = MyModel.get_descendants_group_count()

            for node in root_nodes:
                print '%s by %s (%d replies)' % (node.comment, node.author,
                                                 node.descendants_count)
        N(   R$   R"   t   get_childrent   listt   get_descendant_countt   descendants_count(   R	   R   t   qsett   nodesR   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   get_descendants_group_count  s     c         C   s
   t   d S(   si   
        :returns: the depth (level) of the node

        Example::

           node.get_depth()
        N(   R   (   t   self(    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt	   get_depth3  s    c         C   s
   t   d S(   s   
        :returns: A queryset of all the node's siblings, including the node
            itself.

        Example::

           node.get_siblings()
        N(   R   (   R2   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   get_siblings>  s    	c         C   s
   t   d S(   st   
        :returns: A queryset of all the node's children

        Example::

           node.get_children()
        N(   R   (   R2   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyR+   J  s    c         C   s   |  i    i   S(   sw   
        :returns: The number of the node's children

        Example::

            node.get_children_count()
        (   R+   t   count(   R2   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   get_children_countU  s    c         C   s
   t   d S(   sŌ   
        :returns: A queryset of all the node's descendants, doesn't
            include the node itself (some subclasses may return a list).

        Example::
        
           node.get_descendants()
        N(   R   (   R2   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   get_descendantsc  s    	c         C   s   |  i    i   S(   s   
        :returns: the number of descendants of a node.

        Example::
        
           node.get_descendant_count()
        (   R7   R5   (   R2   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyR-   o  s    c         C   s-   y |  i    d SWn t j
 o d SXd S(   s   
        :returns: The leftmost node's child, or None if it has no children.

        Example::

           node.get_first_child()
        i    N(   R+   R#   R$   (   R2   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   get_first_childz  s    c         C   s3   y |  i    i   d SWn t j
 o d SXd S(   s   
        :returns: The rightmost node's child, or None if it has no children.

        Example::

           node.get_last_child()
        i    N(   R+   R&   R#   R$   (   R2   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   get_last_child  s    c         C   s   |  i    d S(   sĄ   
        :returns: The leftmost node's sibling, can return the node itself if it
            was the leftmost sibling.

        Example::
         
           node.get_first_sibling()
        i    (   R4   (   R2   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   get_first_sibling  s    	c         C   s   |  i    i   d S(   s¹   
        :returns: The rightmost node's sibling, can return the node itself if it
            was the rightmost sibling.

        Example::

            node.get_last_sibling()
        i    (   R4   R&   (   R2   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   get_last_sibling¢  s    	c         C   st   |  i    } g  } | D] } | | i q ~ } |  i | j o0 | i |  i  } | d j o | | d Sn d S(   s£   
        :returns: The previous node's sibling, or None if it was the leftmost
            sibling.

        Example::

           node.get_prev_sibling()
        i    i   N(   R4   t   pkt   index(   R2   t   siblingsR   t   objt   idst   idx(    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   get_prev_sibling®  s    
$c         C   s~   |  i    } g  } | D] } | | i q ~ } |  i | j o: | i |  i  } | t |  d j  o | | d Sn d S(   s    
        :returns: The next node's sibling, or None if it was the rightmost
            sibling.

        Example::

           node.get_next_sibling()
        i   N(   R4   R<   R=   t   len(   R2   R>   R   R?   R@   RA   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   get_next_siblingĄ  s    	$c         C   s(   t  |  i   i d | i g   d j S(   s  
        :returns: ``True`` if the node if a sibling of another node given as an
            argument, else, returns ``False``

        :param node:
        
            The node that will be checked as a sibling

        Example::

           node.is_sibling_of(node2)
        t   pk__ini    (   RC   R4   t   filterR<   (   R2   R   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   is_sibling_ofŃ  s    c         C   s(   t  | i   i d |  i g   d j S(   s	  
        :returns: ``True`` if the node is a child of another node given as an
            argument, else, returns ``False``

        :param node:

            The node that will be checked as a parent

        Example::

           node.is_child_of(node2)
        RE   i    (   RC   R+   RF   R<   (   R2   R   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   is_child_ofį  s    c         C   s
   t   d S(   s  
        :returns: ``True`` if the node if a descendant of another node given
            as an argument, else, returns ``False``

        :param node:

            The node that will be checked as an ancestor

        Example::

           node.is_descendant_of(node2)
        N(   R   (   R2   R   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   is_descendant_ofń  s    c         K   s
   t   d S(   sJ  
        Adds a child to the node. The new node will be the new rightmost
        child. If you want to insert a node at a specific position,
        use the :meth:`add_sibling` method of an already existing
        child node instead.

        :param \*\*kwargs:
        
            Object creation data that will be passed to the inherited Node
            model

        :returns: The created node object. It will be save()d by this method.

        Example::

           node.add_child(numval=1, strval='abcd')
           node.add_child(**{'numval': 1, 'strval': 'abcd'})

        N(   R   (   R2   R
   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyR     s    c         K   s
   t   d S(   s¶  
        Adds a new node as a sibling to the current node object.


        :param pos:
            The position, relative to the current node object, where the
            new node will be inserted, can be one of:

            - ``first-sibling``: the new node will be the new leftmost sibling
            - ``left``: the new node will take the node's place, which will be
              moved to the right 1 position
            - ``right``: the new node will be inserted at the right of the node
            - ``last-sibling``: the new node will be the new rightmost sibling
            - ``sorted-sibling``: the new node will be at the right position
              according to the value of node_order_by

        :param \*\*kwargs: 
        
            Object creation data that will be passed to the inherited
            Node model

        :returns:
            
            The created node object. It will be saved by this method.

        :raise InvalidPosition: when passing an invalid ``pos`` parm
        :raise InvalidPosition: when :attr:`node_order_by` is enabled and the
           ``pos`` parm wasn't ``sorted-sibling``
        :raise MissingNodeOrderBy: when passing ``sorted-sibling`` as ``pos``
           and the :attr:`node_order_by` attribute is missing



        Examples::

           node.add_sibling('sorted-sibling', numval=1, strval='abcd')
           node.add_sibling('sorted-sibling', **{'numval': 1, 'strval': 'abcd'})
        N(   R   (   R2   t   posR
   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   add_sibling  s    'c         C   s
   t   d S(   st   
        :returns: the root node for the current node object.

        Example::

          node.get_root()
        N(   R   (   R2   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   get_rootB  s    c         C   s   |  i    |  j S(   s   
        :returns: True if the node is a root node (else, returns False)

        Example::

           node.is_root()
        (   RL   (   R2   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   is_rootM  s    c         C   s   |  i    d j S(   s   
        :returns: True if the node is a leaf node (else, returns False)

        Example::

           node.is_leaf()
        i    (   R6   (   R2   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   is_leafX  s    c         C   s
   t   d S(   sž   
        :returns: A queryset containing the current node object's ancestors,
            starting by the root node and descending to the parent.
            (some subclasses may return a list)

        Example::

           node.get_ancestors()
        N(   R   (   R2   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   get_ancestorsc  s    
c         C   s
   t   d S(   s÷   
        :returns: the parent node of the current node object.
            Caches the result in the object itself to help in loops.
        
        :param update: Updates de cached value.

        Example::

           node.get_parent()

        N(   R   (   R2   t   update(    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt
   get_parentp  s    c         C   s
   t   d S(   sG	  
        Moves the current node and all it's descendants to a new position
        relative to another node.
        
        .. note:: The node can be moved under another root node.


        :param target:

            The node that will be used as a relative child/sibling when moving

        :param pos:
        
            The position, relative to the target node, where the
            current node object will be moved to, can be one of:

            - ``first-child``: the node will be the new leftmost child of the
              ``target`` node
            - ``last-child``: the node will be the new rightmost child of the
              ``target`` node
            - ``sorted-child``: the new node will be moved as a child of the
              ``target`` node according to the value of :attr:`node_order_by`
            - ``first-sibling``: the node will be the new leftmost sibling of the
              ``target`` node
            - ``left``: the node will take the ``target`` node's place, which will be
              moved to the right 1 position
            - ``right``: the node will be moved to the right of the ``target`` node
            - ``last-sibling``: the node will be the new rightmost sibling of the
              ``target`` node
            - ``sorted-sibling``: the new node will be moved as a sibling of the
              ``target`` node according to the value of :attr:`node_order_by`

            .. note:: If no ``pos`` is given the library will use
                     ``last-sibling``, or ``sorted-sibling`` if
                     :attr:`node_order_by` is enabled.

        :returns: None

        :raise InvalidPosition: when passing an invalid ``pos`` parm
        :raise InvalidPosition: when :attr:`node_order_by` is enabled and the
           ``pos`` parm wasn't ``sorted-sibling`` or ``sorted-child``
        :raise InvalidMoveToDescendant: when trying to move a node to one of
           it's own descendants
        :raise PathOverflow: when the library can't make room for the
           node's new position
        :raise MissingNodeOrderBy: when passing ``sorted-sibling`` or
           ``sorted-child`` as ``pos`` and the :attr:`node_order_by`
           attribute is missing
        
        Examples::
           
           node.move(node2, 'sorted-child')
           
           node.move(node2, 'prev-sibling')

        N(   R   (   R2   t   targetRJ   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   move  s    9c         C   s#   |  i  i i d |  i  i   d S(   sŲ   
        Removes a node and all it's descendants.
        
        .. note::
           
           Call our queryset's delete to handle children removal. Subclasses
           will handle extra maintenance.
        R   N(   t	   __class__t   objectsRF   R   t   delete(   R2   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyRV   »  s    	c         C   s¦   | d	 j o |  i o
 d } q+ d } n | d
 j o t d | f   n |  i o! | d j o t d d   n | d j o |  i o t d   n | S(   sE   
        prepare the pos variable for the add_sibling method
        s   sorted-siblings   last-siblings   first-siblingt   leftt   rights   Invalid relative position: %ss8   Must use %s in add_sibling when node_order_by is enableds    Missing node_order_by attribute.N(   s   first-siblings   lefts   rights   last-siblings   sorted-sibling(   s   sorted-sibling(   R$   t   node_order_byR   R   (   R2   RJ   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   _fix_add_sibling_optsĒ  s    


c      	   C   s¦   | d j o |  i o
 d } q+ d } n | d j o t d	 | f   n |  i o! | d j o t d
 d   n | d j o |  i o t d   n | S(   s9   
        prepare the pos var for the move method
        s   sorted-siblings   last-siblings   first-siblingRW   RX   s   first-childs
   last-childs   sorted-childs   Invalid relative position: %ss>   Must use %s or %s in add_sibling when node_order_by is enableds    Missing node_order_by attribute.N(   s   first-siblings   lefts   rights   last-siblings   sorted-siblings   first-childs
   last-childs   sorted-child(   s   sorted-childs   sorted-sibling(   s   sorted-siblings   sorted-child(   s   sorted-childs   sorted-sibling(   R$   RY   R   R   (   R2   RJ   (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   _fix_move_optsŚ  s    



 c         C   s  g  g  } } x |  i  D] } t | |  } | i t g  } | D]  \ } }	 | t h |	 | 6  q@ ~ t h | d | 6  g    | i | | f  q W| i t t i |   Sy  |  i | i	   d i
  }
 Wn  t j
 o d g  }
 } n X|
 | f S(   s§  
        :returns: The position a new node will be inserted related to the
        current node, and also a queryset of the nodes that must be moved
        to the right. Called only for Node models with :attr:`node_order_by`

        This function was taken from django-mptt (BSD licensed) by Jonathan Buchanan:
        http://code.google.com/p/django-mptt/source/browse/trunk/mptt/signals.py?spec=svn100&r=100#12
        s   %s__gti    N(   RY   t   getattrR   R    RF   t   reducet   operatort   or_t   _get_lastpos_in_patht   allt   pathR#   R$   (   R2   R>   t   newobjt   fieldst   filterst   fieldt   valueR   t   ft   vt   newpos(    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   get_sorted_pos_querysetļ  s    

 	1 t   Metac           B   s   e  Z d  Z e Z RS(   s!   
        Abstract model.
        (   t   __name__t
   __module__t   __doc__t   Truet   abstract(    (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyRl     s   N(    (-   Rm   Rn   Ro   t   classmethodR   R$   t   FalseR    Rp   R!   R"   R%   R'   R(   R)   R*   R1   R3   R4   R+   R6   R7   R-   R8   R9   R:   R;   RB   RD   RG   RH   RI   R   RK   RL   RM   RN   RO   RQ   RS   RV   RZ   R[   Rk   Rl   (    (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyR      sV   
k
	%																*				<				(   Ro   R^   t   django.db.modelsR    t	   django.dbR   R   t   treebeard.exceptionsR   R   R   R   t   ModelR   (    (    (    sR   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/models.pyt   <module>   s
   "