<commit_before>from datetime import datetime
import logging

from sqlalchemy import or_

import adhocracy.model as model
from adhocracy.model import Delegation

log = logging.getLogger(__name__)

class DelegationNode(object):
    """
    A ``DelegationNode`` describes a part of the voting delegation graph
    sorrounding a ``Delegateable`` (i.e. a ``Category``, ``Issue`` or 
    ``Proposal``) and a ``User``. 
    
    **TODO:** Developing a good caching strategy for this class would be 
    useful in order to cache the delegation graph to memcached.
    
    :param user: The ``User`` at the center of this ``DelegationNode``.
    :param delegateable: A ``Delegateable``.   
    """
    
    def __init__(self, user, delegateable):
        self.user = user
        self.delegateable = delegateable
    
    def _query_traverse(self, querymod, recurse, at_time=None):
        if not at_time: # shouldn't this be if at_time is None: ?
            at_time = datetime.utcnow()
        
        query = model.meta.Session.query(Delegation)
        query = query.filter(Delegation.scope==self.delegateable)
        query = query.filter(Delegation.create_time<=at_time)
        query = query.filter(or_(Delegation.revoke_time == None,
                                 Delegation.revoke_time > at_time))
        query = querymod(query)
        delegations = query.all()
        if recurse:
            for parent in self.delegateable.parents:
                node = DelegationNode(self.user, parent)
                delegations += node._query_traverse(querymod, recurse, at_time)
        return delegations
    
    def inbound(self, recurse=True, at_time=None, should_filter=True):
        """
        Retrieve all inbound delegations (i.e. those that the user has received
        from other users in order to vote on their behalf) that apply to the 
        ``Delegateable``. 
        
        :param recurse: if ``True``, search will include delegations on parent 
            ``Delegateables`` in breadth-first traversal order.
        :param at_time: return the delegation graph at the given time, defaults
            to the current time. 
        :returns: list of ``Delegation``
        """
        delegations = self._query_traverse(lambda q: q.filter(Delegation.agent==self.user),
                                           recurse, at_time)
        #print 'inbound', delegations
        if should_filter:
            by_principal = dict()
            for delegation in set(delegations):
                by_principal[delegation.principal] = by_principal.get(delegation.principal, []) + [delegation]
            delegations = [self.filter_delegations(ds)[0] for ds in by_principal.values()]
        
        delegations = self._filter_out_overridden_delegations(delegations)
        return self._filter_out_overrides_by_direct_vote(delegations)
    
    def transitive_inbound(self, recurse=True, at_time=None, _path=None):
        """
        Retrieve inbound delegations recursing through the delegation graph as well 
        as through the category tree.
        
        :param recurse: if ``True``, search will include delegations on parent 
            ``Delegateables`` in breadth-first traversal order.
        :param at_time: return the delegation graph at the given time, defaults
            to the current time. 
        :returns: list of ``Delegation``
        """
        if _path == None:
            _path = []
        elif self.user in _path: 
            return [] # we already visited this node
        # circle detection uses this path of visited nodes
        _path.append(self.user)
        
        delegations = self.inbound(recurse=recurse, at_time=at_time, should_filter=False)
        for delegation in list(delegations):
            ddnode = DelegationNode(delegation.principal, self.delegateable)
            additional_delegations = ddnode.transitive_inbound(recurse=recurse, at_time=at_time, _path=_path)<commit_msg>[svn r548] removed unneeded print<commit_after>from datetime import datetime
import logging

from sqlalchemy import or_

import adhocracy.model as model
from adhocracy.model import Delegation

log = logging.getLogger(__name__)

class DelegationNode(object):
    """
    A ``DelegationNode`` describes a part of the voting delegation graph
    sorrounding a ``Delegateable`` (i.e. a ``Category``, ``Issue`` or 
    ``Proposal``) and a ``User``. 
    
    **TODO:** Developing a good caching strategy for this class would be 
    useful in order to cache the delegation graph to memcached.
    
    :param user: The ``User`` at the center of this ``DelegationNode``.
    :param delegateable: A ``Delegateable``.   
    """
    
    def __init__(self, user, delegateable):
        self.user = user
        self.delegateable = delegateable
    
    def _query_traverse(self, querymod, recurse, at_time=None):
        if not at_time: # shouldn't this be if at_time is None: ?
            at_time = datetime.utcnow()
        
        query = model.meta.Session.query(Delegation)
        query = query.filter(Delegation.scope==self.delegateable)
        query = query.filter(Delegation.create_time<=at_time)
        query = query.filter(or_(Delegation.revoke_time == None,
                                 Delegation.revoke_time > at_time))
        query = querymod(query)
        delegations = query.all()
        if recurse:
            for parent in self.delegateable.parents:
                node = DelegationNode(self.user, parent)
                delegations += node._query_traverse(querymod, recurse, at_time)
        return delegations
    
    def inbound(self, recurse=True, at_time=None, should_filter=True):
        """
        Retrieve all inbound delegations (i.e. those that the user has received
        from other users in order to vote on their behalf) that apply to the 
        ``Delegateable``. 
        
        :param recurse: if ``True``, search will include delegations on parent 
            ``Delegateables`` in breadth-first traversal order.
        :param at_time: return the delegation graph at the given time, defaults
            to the current time. 
        :returns: list of ``Delegation``
        """
        delegations = self._query_traverse(lambda q: q.filter(Delegation.agent==self.user),
                                           recurse, at_time)
        if should_filter:
            by_principal = dict()
            for delegation in set(delegations):
                by_principal[delegation.principal] = by_principal.get(delegation.principal, []) + [delegation]
            delegations = [self.filter_delegations(ds)[0] for ds in by_principal.values()]
        
        delegations = self._filter_out_overridden_delegations(delegations)
        return self._filter_out_overrides_by_direct_vote(delegations)
    
    def transitive_inbound(self, recurse=True, at_time=None, _path=None):
        """
        Retrieve inbound delegations recursing through the delegation graph as well 
        as through the category tree.
        
        :param recurse: if ``True``, search will include delegations on parent 
            ``Delegateables`` in breadth-first traversal order.
        :param at_time: return the delegation graph at the given time, defaults
            to the current time. 
        :returns: list of ``Delegation``
        """
        if _path == None:
            _path = []
        elif self.user in _path: 
            return [] # we already visited this node
        # circle detection uses this path of visited nodes
        _path.append(self.user)
        
        delegations = self.inbound(recurse=recurse, at_time=at_time, should_filter=False)
        for delegation in list(delegations):
            ddnode = DelegationNode(delegation.principal, self.delegateable)
            additional_delegations = ddnode.transitive_inbound(recurse=recurse, at_time=at_time, _path=_path)
{'fraction_non_alphanumeric': 0.08563465923486192, 'fraction_numerical': 0.0006333924499619965, 'mean_word_length': 2.487190812720848, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4811943', 'n_tokens_mistral': 2219, 'n_tokens_neox': 2193, 'n_words': 642}