Ñò
s"Ic           @   sß   d  Z  d d k Z d d k Z d d k l Z d d k l Z l Z l Z d d k	 l
 Z
 d d k l Z d d k l Z d d k l Z l Z d	 e i i f d
 „  ƒ  YZ d e i f d „  ƒ  YZ d e f d „  ƒ  YZ d S(   s÷  

    treebeard.mp_tree
    -----------------

    Materialized Path Tree.

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

    This is an efficient implementation of Materialized Path
    trees for Django 1.0+, as described by `Vadim Tropashko`_ in `SQL Design
    Patterns`_. Materialized Path is probably the fastest way of working with
    trees in SQL without the need of extra work in the database, like Oracle's
    ``CONNECT BY`` or sprocs and triggers for nested intervals.

    In a materialized path approach, every node in the tree will have a
    :attr:`~MP_Node.path` attribute, where the full path from the root
    to the node will be stored. This has the advantage of needing very simple
    and fast queries, at the risk of inconsistency because of the
    denormalization of ``parent``/``child`` foreign keys. This can be prevented
    with transactions.

    ``django-treebeard`` uses a particular approach: every step in the path has
    a fixed width and has no separators. This makes queries predictable and
    faster at the cost of using more characters to store a step. To address this
    problem, every step number is encoded.

    Also, two extra fields are stored in every node:
    :attr:`~MP_Node.depth` and :attr:`~MP_Node.numchild`.
    This makes the read operations faster, at the cost of a little more
    maintenance on tree updates/inserts/deletes. Don't worry, even with these
    extra steps, materialized path is more efficient than other approaches.

    .. note::
       
       The materialized path approach makes heavy use of ``LIKE`` in your
       database, with clauses like ``WHERE path LIKE '002003%'``. If you think
       that ``LIKE`` is too slow, you're right, but in this case the
       :attr:`~MP_Node.path` field is indexed in the database, and all
       ``LIKE`` clauses that don't **start** with a ``%`` character will use the
       index. This is what makes the materialized path approach so fast.


    .. _`Vadim Tropashko`: http://vadimtropashko.wordpress.com/
    .. _`Sql Design Patterns`:
       http://www.rampant-books.com/book_2006_1_sql_coding_styles.htm
    .. _`Django Model Inheritance with abstract classes`:
      http://docs.djangoproject.com/en/dev/topics/db/models/#abstract-base-classes
iÿÿÿÿN(   t   serializers(   t   modelst   transactiont
   connection(   t   Q(   t   settings(   t   Node(   t   InvalidMoveToDescendantt   PathOverflowt   MP_NodeQuerySetc           B   s   e  Z d  Z e d „ Z RS(   sg   
    Custom queryset for the tree node manager.

    Needed only for the customized delete method.
    c         C   sï  | o t  t |  ƒ i ƒ  nÄh  } x |  i d d ƒ D]{ } t } xT t d t | i ƒ | i ƒ D]3 } | i	 | i | ƒ } | | j o t
 } Pqc qc W| p | | | i <q7 q7 Wh  } g  } xæ | i ƒ  D]Ø \ } } | i	 | i | i d ƒ }	 |	 of |	 | j o | i t
 ƒ | |	 <n | |	 }
 |
 o- |
 i d j o |
 i d 8_ |
 i ƒ  qdn | i ƒ  p | i t d | i ƒ ƒ qÏ | i t d | i ƒ ƒ qÏ W| o/ |  i i i t t i | ƒ ƒ i d t
 ƒ n t i ƒ  d S(   s•   
        Custom delete method, will remove all descendant nodes to ensure a
        consistent tree (no orphans)

        :returns: ``None``
        t   deptht   pathi   i    t   path__startswitht   known_childrenN(   t   superR	   t   deletet   order_byt   Falset   ranget   lenR   t   steplent   _get_basepatht   Truet   itemsR
   t
   get_parentt   numchildt   savet   is_leaft   appendR   t   modelt   objectst   filtert   reducet   operatort   or_R   t   commit_unless_managed(   t   selfR   t   removedt   nodet   foundR
   R   t   parentst   toremovet
   parentpatht   parent(    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyR   I   sB       	 
#(   t   __name__t
   __module__t   __doc__R   R   (    (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyR	   A   s   t   MP_NodeManagerc           B   s   e  Z d  Z d „  Z RS(   s    Custom manager for nodes.
    c         C   s   t  |  i ƒ S(   s:   
        Sets the custom queryset as the default.
        (   R	   R   (   R$   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyt   get_query_set‡   s    (   R,   R-   R.   R0   (    (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyR/   ƒ   s   t   MP_Nodec           B   s7  e  Z d  Z d Z d Z g  Z e i d d d e ƒ Z	 e i
 ƒ  Z e i
 d d ƒ Z e ƒ  Z e d „  ƒ Z e d. e d	 „ ƒ Z e d
 „  ƒ Z e d „  ƒ Z e d. d „ ƒ Z e 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. d „ Z# d „  Z$ d „  Z% e& d „ Z' d. d „ Z( e d „  ƒ Z) e d  „  ƒ Z* e d! „  ƒ Z+ e d" „  ƒ Z, e d# „  ƒ Z- e d$ „  ƒ Z. e d. e& d% „ ƒ Z/ d& „  Z0 e d' „  ƒ Z1 e d( „  ƒ Z2 e d) „  ƒ Z3 e d* d+ „ ƒ Z4 d, d/ d- „  ƒ  YZ5 RS(0   s¶  
    Abstract model to create your own Materialized Path Trees.

    .. attribute:: steplen
       
       Attribute that defines the length of each step in the :attr:`path` of
       a node.  The default value of *4* allows a maximum of
       *1679615* children per node. Increase this value if you plan to store
       large trees (a ``steplen`` of *5* allows more than *60M* children per
       node). Note that increasing this value, while increasing the number of
       children per node, will decrease the max :attr:`depth` of the tree (by
       default: *63*). To increase the max :attr:`depth`, increase the
       max_length attribute of the :attr:`path` field in your model.

    .. attribute:: alphabet

       Attribute: the alphabet that will be used in base conversions
       when encoding the path steps into strings. The default value,
       ``0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ`` is the most optimal possible
       value that is portable between the supported databases (which means:
       their default collation will order the :attr:`path` field correctly).

       .. note::

          In case you know what you are doing, there is a test that is disabled
          by default that can tell you the optimal default alphabet in your
          enviroment. To run the test you must enable the
          :envvar:`TREEBEARD_TEST_ALPHABET` enviroment variable::
       
             $ TREEBEARD_TEST_ALPHABET=1 python manage.py test treebeard.TestTreeAlphabet

          On my Ubuntu 8.04.1 system, these are the optimal values for the three
          supported databases in their *default* configuration:

           ================ ==============================================================
           Database         Optimal Alphabet
           ================ ==============================================================
           MySQL 5.0.51     0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
           PostgreSQL 8.2.7 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
           Sqlite3          0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
           ================ ==============================================================

    .. attribute:: node_order_by

       Attribute: a list of model fields that will be used for node
       ordering. When enabled, all tree operations will assume this ordering.

       Example::

          node_order_by = ['field1', 'field2', 'field3']

    .. attribute:: path
        
       ``CharField``, stores the full materialized path for each node. The
       default value of it's max_length, *255*, is the max efficient and
       portable value for a ``varchar``. Increase it to allow deeper trees (max
       depth by default: *63*)

       .. note::
          
          `django-treebeard` uses Django's abstract model inheritance, so:

          1. To change the max_length value of the path in your model, you
             can't just define it since you'd get a django exception, you have
             to modify the already defined attribute::

               class MyNodeModel(MP_Node):
                   pass

               MyNodeModel._meta.get_field('path').max_length = 1024
          2. You can't rely on Django's `auto_now` properties in date fields
             for sorting, you'll have to manually set the value before creating
             a node::

               
               class TestNodeSortedAutoNow(MP_Node):
                   desc = models.CharField(max_length=255)
                   created = models.DateTimeField(auto_now_add=True)
                   node_order_by = ['created']

               TestNodeSortedAutoNow.add_root(desc='foo',
                                              created=datetime.datetime.now())

       .. note::

          For performance, and if your database allows it, you can safely
          define the path column as ASCII (not utf-8/unicode/iso8859-1/etc) to
          keep the index smaller (and faster). Also note that some databases
          (mysql) have a small index size limit. InnoDB for instance has a
          limit of 765 bytes per index, so that would be the limit if your path
          is ASCII encoded. If your path column in InnoDB is using unicode,
          the index limit will be 255 characters since in MySQL's indexes,
          unicode means 3 bytes.



       .. note::

          treebeard uses **numconv** for path encoding:
          http://code.google.com/p/numconv/

    .. attribute:: depth

       ``PositiveIntegerField``, depth of a node in the tree. A root node
       has a depth of *1*.

    .. attribute:: numchild

       ``PositiveIntegerField``, the number of children of the node.


    .. warning::
       
       Do not change the values of :attr:`path`, :attr:`depth` or
       :attr:`numchild` directly: use one of the included methods instead.
       Consider these values *read-only*.

    .. warning::

       Do not change the values of the :attr:`steplen`, :attr:`alphabet` or
       :attr:`node_order_by` after saving your first model. Doing so will
       corrupt the tree. If you *must* do it:
         
         1. Backup the tree with :meth:`dump_bulk`
         2. Empty your model's table
         3. Change :attr:`depth`, :attr:`alphabet` and/or
            :attr:`node_order_by` in your model
         4. Restore your backup using :meth:`load_bulk` with
            ``keep_ids=True`` to keep the same primary keys you had.

    Example::

       class SortedNode(MP_Node):
          node_order_by = ['numval', 'strval']

          numval = models.IntegerField()
          strval = models.CharField(max_length=255)

    Read the API reference of :class:`treebeard.Node` for info on methods
    available in this class, or read the following section for methods with
    particular arguments or exceptions.
    i   t$   0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZt
   max_lengthiÿ   t   uniquet   defaulti    c         K   s–   |  i  ƒ  } | o | i o | i d |  S| o |  i | i ƒ } n |  i d d d ƒ } |  |   } d | _ | | _ | i ƒ  t	 i
 ƒ  | S(   s¢   
        Adds a root node to the tree.

        See: :meth:`treebeard.Node.add_root`

        :raise PathOverflow: when no more root objects can be added
        s   sorted-siblingi   N(   t   get_last_root_nodet   node_order_byt   add_siblingt	   _inc_pathR   t	   _get_patht   NoneR
   R   R   R#   (   t   clst   kwargst	   last_roott   newpatht   newobj(    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyt   add_root*  s    		

c         C   sy  | o |  i  i d | i ƒ } n |  i  i ƒ  } g  h  } } x3t i d | ƒ D]} | d } | d } t | ƒ |  i }	 | d =| d =| d =d | j o | d =n h | d 6}
 | o | d	 |
 d <n | o |	 d
 j p# | o- t | ƒ t | i ƒ j o | i |
 ƒ nM |  i	 | |	 d
 ƒ } | | } d | j o g  | d <n | d i |
 ƒ |
 | | <qR W| S(   sp   
        Dumps a tree branch to a python data structure.

        See: :meth:`treebeard.Node.dump_bulk`
        R   t   pythont   fieldsR   R
   R   t   idt   datat   pki   t   children(
   R   R   R   t   allR    t	   serializeR   R   R   R   (   R<   R+   t   keep_idst   qsett   rett   lnkt   pyobjRC   R   R
   R@   R*   t	   parentobj(    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyt	   dump_bulkL  s6     

#
c         C   sø   g  g  g  } } } xÔ |  i  i ƒ  D]Ã } t } x< | i D]1 } | |  i j o | i | i ƒ t } Pq: q: W| o q$ n t | i ƒ |  i	 o | i | i ƒ q$ n y | i
 t ƒ } Wq$ |  i j
 o | i | i ƒ q$ Xq$ W| | | f S(   sF  
        Checks for problems in the tree structure, problems can occur when:

           1. your code breaks and you get incomplete transactions (always
              use transactions!)
           2. changing the ``steplen`` value in a model (you must :meth:`dump_bulk`
              first, change ``steplen`` and then :meth:`load_bulk`

        :returns: A tuple of three lists:
                  
                  1. a list of ids of nodes with characters not found in the
                     ``alphabet``
                  2. a list of ids of nodes when a wrong ``path`` length
                     according to ``steplen``
                  3. a list of ids of orphaned nodes

        .. note::
           
           These problems can't be solved automatically.

        Example::

           MyNodeModel.find_problems()

        (   R   RH   R   R   t   alphabetR   RD   R   R   R   R   t   DoesNotExist(   R<   t
   evil_charst   bad_steplent   orphansR&   t   found_errort   charR+   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyt   find_problemsz  s(     
 	c         C   s<   |  i  d t ƒ } |  i i ƒ  i ƒ  |  i | d t ƒ d S(   sw  
        Solves some problems that can appear when transactions are not used and
        a piece of code breaks, leaving the tree in an inconsistent state.

        The problems this method solves are:
        
           1. Nodes with an incorrect ``level`` or ``numchild`` values due to
              incorrect code and lack of database transactions.
           2. "Holes" in the tree. This is normal if you move/delete nodes a
              lot. Holes in a tree don't affect performance,
           3. Incorrect ordering of nodes when ``node_order_by`` is enabled.
              Ordering is enforced on *node insertion*, so if an attribute in
              ``node_order_by`` is modified after the node is inserted, the
              tree ordering will be inconsistent.

        If these problems don't apply to you, you'll never need to use this
        method.

        .. note::

           Currently what this method does is:

           1. Backup the tree with :meth:`dump_data`
           2. Remove all nodes in the tree.
           3. Restore the tree with :meth:`load_data`

           So, even when the primary keys of your nodes will be preserved, this
           method isn't foreign-key friendly. That needs complex in-place
           tree reordering, not available at the moment (hint: patches are
           welcome).

        Example::

           MyNodeModel.fix_tree()


        N(   RP   R;   R   R   RH   R   t	   load_bulk(   R<   t   dump(    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyt   fix_treeª  s    'c         C   sU   | d j o |  i i ƒ  S| i ƒ  p  |  i i d | i d | i ƒ S|  i i ƒ  S(   s
  
        :returns: A *queryset* of nodes ordered as DFS, including the parent. If
                  no parent is given, the entire tree is returned.

        See: :meth:`treebeard.Node.get_tree`

        .. note::

            This metod returns a queryset.
        R   t
   depth__gteN(   R;   R   RH   R   R   R   R
   t   none(   R<   R+   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyt   get_treeÖ  s    c         C   s   |  i  i d d ƒ S(   s‰   
        :returns: A queryset containing the root nodes in the tree.

        Example::

           MyNodeModel.get_root_nodes()
        R
   i   (   R   R   (   R<   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyt   get_root_nodesë  s    	c      	   C   s  | o) | i  d } |  i | i ƒ } d } n d } g  } d } d h |  i i d 6| |  i d 6| d 6| d 6} t i ƒ  } | i | | ƒ g  } g  } | i	 D] }	 | |	 d	 q¥ ~ }
 xM | i
 ƒ  D]? } |  t t |
 | d
  ƒ ƒ   } | d | _ | i | ƒ qÌ Wt i ƒ  | S(   sÃ   
        Helper for a very common case: get a group of siblings and the number
        of *descendants* in every sibling.

        See: :meth:`treebeard.Node.get_descendants_group_count`
        i   s   AND path BETWEEN %s AND %st    sô   SELECT * FROM %(table)s AS t1 INNER JOIN  (SELECT    SUBSTR(path, 1, %(subpathlen)s) AS subpath,    COUNT(1)-1 AS count    FROM %(table)s    WHERE depth >= %(depth)s %(extrand)s   GROUP BY subpath) AS t2  ON t1.path=t2.subpath  ORDER BY t1.patht   tablet
   subpathlenR
   t   extrandi    iþÿÿÿiÿÿÿÿ(   R
   t   _get_children_path_intervalR   t   _metat   db_tableR   R   t   cursort   executet   descriptiont   fetchallt   dictt   zipt   descendants_countR   R   R#   (   R<   R+   R
   t   paramsRc   t   sqlRg   RL   t   _[1]t   fieldt   field_namest	   node_dataR&   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyt   get_descendants_group_countø  s.    
( 
c         C   s   |  i  S(   sh   
        :returns: the depth (level) of the node

        See: :meth:`treebeard.Node.get_depth`
        (   R
   (   R$   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyt	   get_depth9  s    c         C   sj   |  i  i i d |  i ƒ } |  i d j o; |  i |  i |  i d ƒ } | i d |  i | ƒ ƒ } n | S(   s›   
        :returns: A queryset of all the node's siblings, including the node
            itself.

        See: :meth:`treebeard.Node.get_siblings`
        R
   i   t   path__range(   t	   __class__R   R   R
   R   R   Rd   (   R$   RK   R*   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyt   get_siblingsB  s    	c         C   sM   |  i  ƒ  o |  i i i ƒ  S|  i i i d |  i d d |  i |  i ƒ ƒ S(   ss   
        :returns: A queryset of all the node's children

        See: :meth:`treebeard.Node.get_children`
        R
   i   Rv   (   R   Rw   R   R]   R   R
   Rd   R   (   R$   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyt   get_childrenR  s    c         C   s<   y! |  i  ƒ  i d |  i ƒ d SWn t j
 o d SXd S(   sŸ   
        :returns: The next node's sibling, or None if it was the rightmost
            sibling.

        See: :meth:`treebeard.Node.get_next_sibling`
        t   path__gti    N(   Rx   R   R   t
   IndexErrorR;   (   R$   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyt   get_next_sibling^  s    !c         C   s   |  i  i |  ƒ i d |  i ƒ S(   s­   
        :returns: A queryset of all the node's descendants as DFS, doesn't
            include the node itself

        See: :meth:`treebeard.Node.get_descendants`
        RF   (   Rw   R^   t   excludeRD   (   R$   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyt   get_descendantsk  s    c         C   sB   y' |  i  ƒ  i d |  i ƒ i ƒ  d SWn t j
 o d SXd S(   s¢   
        :returns: The previous node's sibling, or None if it was the leftmost
            sibling.

        See: :meth:`treebeard.Node.get_prev_sibling`
        t   path__lti    N(   Rx   R   R   t   reverseR{   R;   (   R$   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyt   get_prev_siblingu  s    'c         C   s   |  i  S(   sª   
        :returns: The number the node's children, calculated in the most
        efficient possible way.

        See: :meth:`treebeard.Node.get_children_count`
        (   R   (   R$   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyt   get_children_count‚  s    c         C   sZ   |  i  | i  j } |  i  d j o4 |  i |  i |  i  d ƒ } | o | i i | ƒ S| S(   sº   
        :returns: ``True`` if the node if a sibling of another node given as an
            argument, else, returns ``False``

        See: :meth:`treebeard.Node.is_sibling_of`
        i   (   R
   R   R   t
   startswith(   R$   R&   t   auxR*   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyt   is_sibling_ofŒ  s
    c         C   s*   |  i  i | i  ƒ o |  i | i d j S(   s¶   
        :returns: ``True`` is the node if a child of another node given as an
            argument, else, returns ``False``

        See: :meth:`treebeard.Node.is_child_of`
        i   (   R   Rƒ   R
   (   R$   R&   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyt   is_child_of›  s    c         C   s&   |  i  i | i  ƒ o |  i | i j S(   sÀ   
        :returns: ``True`` if the node if a descendant of another node given
            as an argument, else, returns ``False``

        See: :meth:`treebeard.Node.is_descendant_of`
        (   R   Rƒ   R
   (   R$   R&   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyt   is_descendant_of¥  s    c         K   s   |  i  ƒ  o! |  i o |  i ƒ  i d |  S|  i |   } |  i d | _ |  i  ƒ  p |  i |  i ƒ  i ƒ | _ nW |  i |  i | i d ƒ | _ t	 | i ƒ | i i
 i d ƒ i j o t d ƒ ‚ n | i ƒ  |  | _ |  i d 7_ |  i ƒ  | S(   sž   
        Adds a child to the node.

        See: :meth:`treebeard.Node.add_child`

        :raise PathOverflow: when no more child nodes can be added
        s   sorted-siblingi   R   sk   The new node is too deep in the tree, try increasing the path.max_length property and UPDATE your  database(   R   R7   t   get_last_childR8   Rw   R
   R9   R   R:   R   Re   t	   get_fieldR3   R   R   t   _cached_parent_objR   (   R$   R=   R@   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyt	   add_child¯  s    	
	
c         K   sw  |  i  | ƒ } |  i |   } |  i | _ | d j oo |  i |  i ƒ  | ƒ } y  |  i | i ƒ  d i ƒ } Wn t j
 o d } n X| d j o
 d } q³ n d g  } } g  } |  i
 | | |  i |  | | d t ƒ \ } } |  i | |  i d ƒ }	 |	 o | i |  i |	 d ƒ ƒ n t i ƒ  }
 x$ | D] \ } } |
 i | | ƒ q6W| | _ | i ƒ  t i ƒ  | S(   sá   
        Adds a new node as a sibling to the current node object.

        See: :meth:`treebeard.Node.add_sibling`

        :raise PathOverflow: when the library can't make room for the
           node's new position
        s   sorted-siblingi    s   last-siblingi   t   incN(   t   _fix_add_sibling_optsRw   R
   t   get_sorted_pos_querysetRx   t   _get_lastpos_in_pathRH   R   R{   R;   t   _move_add_sibling_auxR   R   R   t   _get_sql_update_numchildR   Rg   Rh   R   R   R#   (   R$   t   posR=   R@   t   siblingst   newpost   stmtst   _R?   R*   Rg   Ro   t   vals(    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyR8   Ó  s6    
 ! 	

c         C   s#   |  i  i i d |  i d |  i !ƒ S(   st   
        :returns: the root node for the current node object.

        See: :meth:`treebeard.Node.get_root`
        R   i    (   Rw   R   t   getR   R   (   R$   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyt   get_root  s    c         C   sf   g  } t  d t |  i ƒ |  i ƒ d D] } | |  i d | !q' ~ } |  i i i d | ƒ i d ƒ S(   sÍ   
        :returns: A queryset containing the current node object's ancestors,
            starting by the root node and descending to the parent.

        See: :meth:`treebeard.Node.get_ancestors`
        i    i   t   path__inR
   (   R   R   R   R   Rw   R   R   R   (   R$   Rp   R’   t   paths(    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyt   get_ancestors  s    @c         C   s•   t  |  i ƒ |  i } | d j o d Sy | o
 |  ` n |  i SWn t j
 o n X|  i |  i | d ƒ } |  i i i d | ƒ |  _ |  i S(   s¼   
        :returns: the parent node of the current node object.
            Caches the result in the object itself to help in loops.

        See: :meth:`treebeard.Node.get_parent`
        i   NR   (	   R   R   R   RŠ   t   AttributeErrorR   Rw   R   R˜   (   R$   t   updateR
   R*   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyR     s    
c         C   sÍ  |  i  | ƒ } |  i } |  i | | | i ƒ \ } } } } } | i |  ƒ o t d ƒ ‚ n | | i j o^ | d j pL | d	 j o | i | i ƒ  i j p& | d j o | i | i ƒ  i j o d S| d j oo |  i | i	 ƒ  |  ƒ } y  |  i
 | i ƒ  d i ƒ } Wn t j
 o d } n X| d j o
 d } qIn g  } |  i | | | | | | | t ƒ \ } } |  i | | | ƒ t i ƒ  }	 x$ | D] \ }
 } |	 i |
 | ƒ qŸWt i ƒ  d S(
   s  
        Moves the current node and all it's descendants to a new position
        relative to another node.

        See: :meth:`treebeard.Node.move`
        
        :raise PathOverflow: when the library can't make room for the
           node's new position
        s    Can't move node to a descendant.t   leftt   rights   last-siblings   first-siblingNs   sorted-siblingi    (   R    s   last-sibling(   t   _fix_move_optsR   t   _fix_move_to_childR
   R‡   R   t   get_last_siblingt   get_first_siblingRŽ   Rx   R   RH   R{   R;   R   R   t   _updates_after_moveR   Rg   Rh   R   R#   (   R$   t   targetR’   t   oldpatht   newdepthR“   R”   R•   R?   Rg   Ro   R—   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyt   move/  s>    		  c         C   s   | o | d | |  i  !Sd S(   sM   
        :returns: The base path of another path up to a given depth
        i    R`   (   R   (   R<   R   R
   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyR   g  s    c         C   sY   |  i  | | d ƒ } t i | t |  i ƒ |  i ƒ } d | d |  i t | ƒ | f S(   s¾   
        Builds a path given some values

        :param path: the base path
        :param depth: the depth of the  node
        :param newstep: the value (integer) of the new step
        i   s   %s%s%st   0(   R   t   numconvt   int2strR   RQ   R   (   R<   R   R
   t   newstepR*   t   key(    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyR:   q  s    	!c         C   s¢   t  |  i ƒ } t i | |  i | |  i ƒ d } t i | | |  i ƒ } t  | ƒ |  i j o t d | f ƒ ‚ n d | |  i  d |  i t  | ƒ | f S(   sN   
        :returns: The path of the next sibling of a given node path.
        i   s   Path Overflow from: '%s's   %s%s%sRª   (   R   RQ   R«   t   str2intR   R¬   R   (   R<   R   t   baseR”   R®   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyR9     s    $"c         C   s'   t  i | |  i t |  i ƒ |  i ƒ S(   sI   
        :returns: The integer value of the last step in a path.
        (   R«   R¯   R   R   RQ   (   R<   R   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyR     s    c         C   s$   | o | d t  | ƒ |  i !Sd S(   s<   
        :returns: The parent path for a given path
        i    R`   (   R   R   (   R<   R   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyt   _get_parent_path_from_path–  s    c         C   s.   | |  i  d |  i | |  i  d |  i f S(   sR   
        :returns: An interval of all possible children paths for a node.
        i    iÿÿÿÿ(   RQ   R   (   R<   R   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyRd      s    c	         C   s  | d j p  | d j oY | | i  ƒ  j oF | i  ƒ  }	 |  i |	 i ƒ }
 | o | i |  i | |
 ƒ ƒ q	n—| d	 j o‚ | i ƒ  } h | i d | i ƒ d 6| i d | i ƒ d 6| d 6| } |  i | i ƒ } h d d 6| d 6| d d 6| } n |  i	 | i | | ƒ }
 xÈ | i
 ƒ  D]º } |  i | i |  i | i ƒ ƒ \ } } | i | | f ƒ | os | i | i ƒ o  | d | t | d ƒ } n | i i | i ƒ o& | d | i t | d ƒ | _ qáq'q'W| o | i |  i | |
 ƒ ƒ n | |
 f S(
   s¥   
        Handles the reordering of nodes and branches when adding/moving
        nodes.

        :returns: A tuple containing the old path and the new path.
        s   last-siblingR    t	   path__gteRŸ   Rz   s   first-siblingi   i    N(   R£   R9   R   R   t   _get_sql_newpath_in_branchesR;   Rx   R   R   R:   R€   Rƒ   R   (   R<   R’   R”   R¨   R¦   R“   R•   R§   t
   movebrancht   lastR?   t   basenumR&   Ro   R—   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyR   ©  s<    	 !
  .c         C   s¾   | i  } d } d } g  } | d	 j oƒ | } | d 7} | i ƒ  o" d } d } |  i i i ƒ  } n, | i ƒ  } h d d 6d d 6d d 6| } | i d 7_ d } n | | | | | f S(
   sO   
        Update preliminar vars in :meth:`move` when moving to a child
        s   first-childs
   last-childs   sorted-childi   s   first-siblings   last-siblings   sorted-siblingN(   s   first-childs
   last-childs   sorted-child(   R
   R;   R   Rw   R   R]   Rˆ   R   (   R$   R’   R¦   R¨   R+   R”   R“   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyR¢   à  s$    	


c         C   sÜ   t  i d j o3 t | ƒ t | ƒ j o | i |  i | ƒ ƒ n |  i | ƒ } |  i | ƒ } | o | p | o | p | | j oL | o | i |  i | d ƒ ƒ n | o | i |  i | d ƒ ƒ qØ n d S(   sÝ   
        
        Updates the list of sql statements needed after moving nodes.

        1. :attr:`depth` updates *ONLY* needed by mysql databases (*sigh*)
        2. update the number of children of parent nodes
        t   mysqlt   decRŒ   N(   R   t   DATABASE_ENGINER   R   t   _get_sql_update_depth_in_branchR±   R‘   (   R<   R§   R?   R•   t   oldparentpatht   newparentpath(    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyR¥   ÿ  s    	)c   	      C   s  d |  i  i f } t i d j o
 d } n! t i d j o
 d } n d } d | f g } | t | ƒ d g } t | ƒ t | ƒ j oK t i d j o; | i d	 | f ƒ | i | t | ƒ d |  i g ƒ n d
 } | i | d g ƒ d | d i | ƒ | f } | | f S(   s¯   
        :returns" The sql needed to move a branch to another position.

        .. note::

           The generated sql will only update the depth values if needed.

        s   UPDATE %s SETt   sqlite3s"   %s||SUBSTR(path, %s, LENGTH(path))R·   s   CONCAT(%s, SUBSTR(path, %s))s   %s||SUBSTR(path, %s)s   path=%si   s   depth=LENGTH(%s)/%%ss   WHERE path LIKE %st   %s   %s %s %ss   , (	   Re   Rf   R   R¹   R   R   t   extendR   t   join(	   R<   R§   R?   t   sql1t   sqlpatht   sql2R—   t   sql3Ro   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyR³     s    

)'c         C   s0   d |  i  i f } |  i | d g } | | f S(   sn   
        :returns: The sql needed to update the depth of all the nodes in a
                  branch.
        s8   UPDATE %s SET depth=LENGTH(path)/%%s WHERE path LIKE %%sR¾   (   Re   Rf   R   (   R<   R   Ro   R—   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyRº   H  s    RŒ   c         C   s;   d |  i  i h d d 6d d 6| f } | g } | | f S(   sG   
        :returns: The sql needed the numchild value of a node
        s1   UPDATE %s SET numchild=numchild%s1 WHERE path=%%st   +RŒ   t   -R¸   (   Re   Rf   (   R<   R   t   incdecRo   R—   (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyR‘   V  s
    		t   Metac           B   s   e  Z d  Z e Z d g Z RS(   s!   
        Abstract model.
        R   (   R,   R-   R.   R   t   abstractt   ordering(    (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyRÈ   b  s   N(    (6   R,   R-   R.   R   RQ   R7   R   t	   CharFieldR   R   t   PositiveIntegerFieldR
   R   R/   R   t   classmethodRA   R;   RP   RX   R[   R^   R_   Rt   Ru   Rx   Ry   R|   R~   R   R‚   R…   R†   R‡   R‹   R8   R™   Rœ   R   R   R©   R   R:   R9   R   R±   Rd   R   R¢   R¥   R³   Rº   R‘   RÈ   (    (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyR1   Ž   sd   Ž		"-0,@						
		
		
	
	$0			8
	
	5	-(   R.   R!   R«   t   django.coreR    t	   django.dbR   R   R   t   django.db.modelsR   t   django.confR   t   treebeard.modelsR   t   treebeard.exceptionsR   R   t   queryt   QuerySetR	   t   ManagerR/   R1   (    (    (    sS   /afs/sipb.mit.edu/project/remit/demo-code/django-treebeard-1.1/treebeard/mp_tree.pyt   <module>3   s   B