def test_two_delegations_at_the_same_level_that_agree_reinforce_each_other( self): self._do_delegate(self.me, self.high_delegate, self.proposal) self._do_delegate(self.me, self.low_delegate, self.proposal) Decision(self.high_delegate, self.poll).make(Vote.YES) Decision(self.low_delegate, self.poll).make(Vote.YES) self.assertEqual(self.decision.reload().result, Vote.YES)
def test_delegation_is_not_used_if_user_has_voted_directly(self): self._do_delegate(self.first, self.second, self.proposal) self._do_delegate(self.second, self.first, self.proposal) Decision(self.second, self.poll).make(Vote.NO) Decision(self.first, self.poll).make(Vote.YES) self.assertEqual( Decision(self.second, self.poll).is_self_decided(), True) self.assertEqual(Decision(self.second, self.poll).result, Vote.NO)
def create(cls, principal, agent, scope, replay=True): from adhocracy.lib.democracy import Decision delegation = Delegation(principal, agent, scope) meta.Session.add(delegation) meta.Session.flush() if replay: log.debug("Replaying the vote for Delegation: %s" % delegation) Decision.replay_decisions(delegation) return delegation
def setUp(self): super(TestDecisionWithDelegation, self).setUp() self.me = tt_make_user(name='me') self.high_delegate = tt_make_user(name='high_delegate') self.low_delegate = tt_make_user(name='low_delegate') self.proposal = tt_make_proposal(creator=self.me, voting=True) self.poll = Poll.create(self.proposal, self.proposal.creator, Poll.ADOPT) self.decision = Decision(self.me, self.poll) self.instance = tt_get_instance()
def test_vote_by_creator(self): from adhocracy.lib.democracy import Decision proposal = tt_make_proposal(voting=True) poll = proposal.polls[0] self.assertEqual(0, len(list(poll.votes))) decision = Decision(proposal.creator, poll) votes = decision.make(Vote.YES) self.assertEqual(len(votes), 1) self.assertEqual(len(decision.votes), 1) self.assertEqual(votes[0].orientation, Vote.YES) self.assertEqual(votes[0].user, proposal.creator)
def test_two_delegations_at_the_same_level_that_disagree_cancel_each_other( self): # This is meant as a safeguard: if I don't fully trust my delegates # I can delegate to n delegates, and my vote will only be autocast # if they all agree # If not, I need to decide myself self._do_delegate(self.me, self.high_delegate, self.proposal) self._do_delegate(self.me, self.low_delegate, self.proposal) Decision(self.high_delegate, self.poll).make(Vote.YES) Decision(self.low_delegate, self.poll).make(Vote.NO) self.assertEqual(self.decision.reload().result, None, "needs to cast his own vote")
def create(cls, scope, user, action, subject=None, with_vote=False): from tally import Tally from vote import Vote from adhocracy.lib.democracy import Decision poll = Poll(scope, user, action, subject=subject) meta.Session.add(poll) meta.Session.flush() if with_vote: decision = Decision(user, poll) decision.make(Vote.YES) Tally.create_from_poll(poll) meta.Session.flush() return poll
def test_vote_by_other_user(self): from adhocracy.lib.democracy import Decision proposal = tt_make_proposal(voting=True) poll = proposal.polls[0] self.assertEqual(0, len(list(poll.votes))) # make a new user and let him vote new_user = tt_make_user() decision = Decision(new_user, poll) votes = decision.make(Vote.YES) self.assertEqual(len(votes), 1) self.assertEqual(len(decision.votes), 1) self.assertEqual(len(poll.votes), 1) self.assertEqual(votes[0].orientation, Vote.YES)
def combine_polls(cls, polls, at_time=None): from adhocracy.lib.democracy import Decision from vote import Vote if at_time is None: at_time = datetime.utcnow() result_voters = {} undecided = [] for poll in polls: for decision in Decision.for_poll(poll, at_time=at_time): if not decision.is_decided(): continue for option in [Vote.YES, Vote.NO, Vote.ABSTAIN]: voters = result_voters.get(option, []) if option == result and decision.user not in voters: voters = voters.append(decision.user) if option != result and decision.user in voters: undecided.append(decision.user) result_voters[option] = voters for option in [Vote.YES, Vote.NO, Vote.ABSTAIN]: users = result_voters.get(option, []) for user in undecided: if user in users: users = users.remove(user) result_voters[option] = users return Tally(None, len(result_voters.get(Vote.YES, [])), len(result_voters.get(Vote.NO, [])), len(result_voters.get(Vote.ABSTAIN, [])))
def _get_required_participation(self): if self._required_participation is None: from adhocracy.lib.democracy import Decision avg = Decision.average_decisions(self) required = int(math.ceil(max(2, avg * self.required_majority))) self._required_participation = required return self._required_participation
def combine_polls(cls, polls, at_time=None): from adhocracy.lib.democracy import Decision from vote import Vote if at_time is None: at_time = datetime.utcnow() voters = {Vote.YES: Set(), Vote.NO: Set(), Vote.ABSTAIN: Set()} for poll in polls: for decision in Decision.for_poll(poll, at_time=at_time): if not decision.is_decided(): continue result = decision.result if result is not None: voters_ = voters.get(result) voters_.add(decision.user) # Do the math. We count only non-contradictory votes. yes = voters[Vote.YES] no = voters[Vote.NO] abstain = voters[Vote.ABSTAIN] return Tally(None, len(yes - no - abstain), len(no - yes - abstain), len(abstain - yes - no))
def test_if_mutual_delegation_is_broken_breaker_gets_one_delegation(self): self._do_delegate(self.first, self.second, self.proposal) self._do_delegate(self.second, self.first, self.proposal) Decision(self.first, self.poll).make(Vote.YES) node = DelegationNode(self.first, self.proposal) self.assertEqual(node.number_of_delegations(), 1)
def test_second_identical_vote(self): from adhocracy.lib.democracy import Decision proposal = tt_make_proposal(voting=True) poll = proposal.polls[0] self.assertEqual(0, len(list(poll.votes))) decision = Decision(proposal.creator, poll) votes = decision.make(Vote.YES) self.assertEqual(len(votes), 1) self.assertEqual(len(decision.votes), 1) self.assertEqual(len(poll.votes), 1) # a second, identical vote by the same user decision = Decision(proposal.creator, poll) votes = decision.make(Vote.YES) self.assertEqual(len(votes), 1) self.assertEqual(len(decision.votes), 2) self.assertEqual(len(poll.votes), 2)
def setUp(self): self.me = tt_make_user(name='me') self.high_delegate = tt_make_user(name='high_delegate') self.low_delegate = tt_make_user(name='low_delegate') self.proposal = tt_make_proposal(creator=self.me, voting=True) self.poll = Poll.create(self.proposal, self.proposal.creator, Poll.ADOPT) self.decision = Decision(self.me, self.poll) self.instance = tt_get_instance()
def num_principals(self): if self.__num_principals is None: principals = set(map(lambda d: d.principal, self.dnode.transitive_inbound())) if self.poll: principals = filter( lambda p: not Decision(p, self.poll).is_self_decided(), principals) self.__num_principals = len(principals) return self.__num_principals
def create_from_poll(cls, poll, at_time=None): from adhocracy.lib.democracy import Decision from vote import Vote if at_time is None: at_time = datetime.utcnow() results = {} for decision in Decision.for_poll(poll, at_time=at_time): if not decision.is_decided(): continue results[decision.result] = results.get(decision.result, 0) + 1 tally = Tally(poll, results.get(Vote.YES, 0), results.get(Vote.NO, 0), results.get(Vote.ABSTAIN, 0)) tally.create_time = at_time meta.Session.add(tally) meta.Session.flush() return tally
def make_from_poll(tally_cls, poll, at_time=None, user_filter=None): from adhocracy.lib.democracy import Decision from adhocracy.model import Vote if at_time is None: at_time = datetime.utcnow() results = {} decisions = Decision.for_poll(poll, at_time=at_time, user_filter=user_filter) for decision in decisions: if not decision.is_decided(): continue results[decision.result] = results.get(decision.result, 0) + 1 tally = tally_cls(poll, results.get(Vote.YES, 0), results.get(Vote.NO, 0), results.get(Vote.ABSTAIN, 0)) tally.create_time = at_time return tally
def setUp(self): self.proposal = tt_make_proposal(voting=True) self.poll = Poll.create(self.proposal, self.proposal.creator, Poll.ADOPT) self.decision = Decision(self.proposal.creator, self.poll)
def setUp(self): super(TestDecisionWithoutDelegation, self).setUp() self.proposal = tt_make_proposal(voting=True) self.poll = Poll.create(self.proposal, self.proposal.creator, Poll.ADOPT) self.decision = Decision(self.proposal.creator, self.poll)
def test_delegated_decisions_are_not_self_decided(self): self._do_delegate(self.me, self.high_delegate, self.proposal) Decision(self.high_delegate, self.poll).make(Vote.YES) self.decision.reload() self.assertFalse(self.decision.is_self_decided())
def test_own_vote_overrides_delegations(self): self._do_delegate(self.me, self.high_delegate, self.proposal) Decision(self.high_delegate, self.poll).make(Vote.YES) self.decision.make(Vote.NO) self.assertEqual(self.decision.reload().result, Vote.NO)
class TestDecisionWithDelegation(TestController): def setUp(self): self.me = tt_make_user(name='me') self.high_delegate = tt_make_user(name='high_delegate') self.low_delegate = tt_make_user(name='low_delegate') self.proposal = tt_make_proposal(creator=self.me, voting=True) self.poll = Poll.create(self.proposal, self.proposal.creator, Poll.ADOPT) self.decision = Decision(self.me, self.poll) self.instance = tt_get_instance() def _do_delegate(self, from_user, delegatee, scope): from adhocracy.model.delegation import Delegation delegation = Delegation.create(from_user, delegatee, scope) return delegation def test_delegation_without_vote_is_no_vote(self): self._do_delegate(self.me, self.high_delegate, self.proposal) self.decision.reload() self.assertEqual(len(self.decision.votes), 0) self.assertFalse(self.decision.is_decided()) self.assertEqual(self.decision.result, None) def test_can_do_general_delegate_to_other_user(self): self._do_delegate(self.me, self.high_delegate, self.proposal) Decision(self.high_delegate, self.poll).make(Vote.YES) self.assertEqual(self.decision.reload().result, Vote.YES) def test_delegation_can_decide_a_decision(self): self._do_delegate(self.me, self.high_delegate, self.proposal) Decision(self.high_delegate, self.poll).make(Vote.YES) self.decision.reload() self.assertTrue(self.decision.is_decided()) def test_delegated_decisions_are_not_self_decided(self): self._do_delegate(self.me, self.high_delegate, self.proposal) Decision(self.high_delegate, self.poll).make(Vote.YES) self.decision.reload() self.assertFalse(self.decision.is_self_decided()) def test_two_delegations_at_the_same_level_that_disagree_cancel_each_other( self): # This is meant as a safeguard: if I don't fully trust my delegates # I can delegate to n delegates, and my vote will only be autocast # if they all agree # If not, I need to decide myself self._do_delegate(self.me, self.high_delegate, self.proposal) self._do_delegate(self.me, self.low_delegate, self.proposal) Decision(self.high_delegate, self.poll).make(Vote.YES) Decision(self.low_delegate, self.poll).make(Vote.NO) self.assertEqual(self.decision.reload().result, None, "needs to cast his own vote") def test_two_delegations_at_the_same_level_that_agree_reinforce_each_other( self): self._do_delegate(self.me, self.high_delegate, self.proposal) self._do_delegate(self.me, self.low_delegate, self.proposal) Decision(self.high_delegate, self.poll).make(Vote.YES) Decision(self.low_delegate, self.poll).make(Vote.YES) self.assertEqual(self.decision.reload().result, Vote.YES) def test_two_delegations_at_the_same_level_are_both_relevant_votes(self): self._do_delegate(self.me, self.high_delegate, self.proposal) self._do_delegate(self.me, self.low_delegate, self.proposal) Decision(self.high_delegate, self.poll).make(Vote.YES) Decision(self.low_delegate, self.poll).make(Vote.YES) self.assertEqual(len(self.decision.reload().relevant_votes), 2) def test_own_vote_overrides_delegations(self): self._do_delegate(self.me, self.high_delegate, self.proposal) Decision(self.high_delegate, self.poll).make(Vote.YES) self.decision.make(Vote.NO) self.assertEqual(self.decision.reload().result, Vote.NO) def test_delegation_is_recorded_as_just_another_vote(self): self._do_delegate(self.me, self.high_delegate, self.proposal) self.assertEqual(len(self.decision.reload().votes), 0) Decision(self.high_delegate, self.poll).make(Vote.YES) self.assertEqual(len(self.decision.reload().votes), 1) def test_delegation_is_transitive(self): self._do_delegate(self.me, self.low_delegate, self.proposal) self._do_delegate(self.low_delegate, self.high_delegate, self.proposal) Decision(self.high_delegate, self.poll).make(Vote.YES) self.assertEqual(self.decision.reload().result, Vote.YES) def test_delegation_is_transitive_across_delegation_levels(self): self._do_delegate(self.me, self.low_delegate, self.proposal) self._do_delegate(self.low_delegate, self.high_delegate, self.proposal) Decision(self.high_delegate, self.poll).make(Vote.YES) self.assertEqual(self.decision.reload().result, Vote.YES)
def test_delegation_can_decide_a_decision(self): self._do_delegate(self.me, self.high_delegate, self.proposal) Decision(self.high_delegate, self.poll).make(Vote.YES) self.decision.reload() self.assertTrue(self.decision.is_decided())
def test_can_do_general_delegate_to_other_user(self): self._do_delegate(self.me, self.high_delegate, self.proposal) Decision(self.high_delegate, self.poll).make(Vote.YES) self.assertEqual(self.decision.reload().result, Vote.YES)
def test_delegation_is_recorded_as_just_another_vote(self): self._do_delegate(self.me, self.high_delegate, self.proposal) self.assertEqual(len(self.decision.reload().votes), 0) Decision(self.high_delegate, self.poll).make(Vote.YES) self.assertEqual(len(self.decision.reload().votes), 1)
def test_delegation_is_transitive_across_delegation_levels(self): self._do_delegate(self.me, self.low_delegate, self.proposal) self._do_delegate(self.low_delegate, self.high_delegate, self.proposal) Decision(self.high_delegate, self.poll).make(Vote.YES) self.assertEqual(self.decision.reload().result, Vote.YES)
class TestDecisionWithDelegation(TestController): def setUp(self): super(TestDecisionWithDelegation, self).setUp() self.me = tt_make_user(name='me') self.high_delegate = tt_make_user(name='high_delegate') self.low_delegate = tt_make_user(name='low_delegate') self.proposal = tt_make_proposal(creator=self.me, voting=True) self.poll = Poll.create(self.proposal, self.proposal.creator, Poll.ADOPT) self.decision = Decision(self.me, self.poll) self.instance = tt_get_instance() def _do_delegate(self, from_user, delegatee, scope): from adhocracy.model.delegation import Delegation delegation = Delegation.create(from_user, delegatee, scope) return delegation def test_delegation_without_vote_is_no_vote(self): self._do_delegate(self.me, self.high_delegate, self.proposal) self.decision.reload() self.assertEqual(len(self.decision.votes), 0) self.assertFalse(self.decision.is_decided()) self.assertEqual(self.decision.result, None) def test_can_do_general_delegate_to_other_user(self): self._do_delegate(self.me, self.high_delegate, self.proposal) Decision(self.high_delegate, self.poll).make(Vote.YES) self.assertEqual(self.decision.reload().result, Vote.YES) def test_delegation_can_decide_a_decision(self): self._do_delegate(self.me, self.high_delegate, self.proposal) Decision(self.high_delegate, self.poll).make(Vote.YES) self.decision.reload() self.assertTrue(self.decision.is_decided()) def test_delegated_decisions_are_not_self_decided(self): self._do_delegate(self.me, self.high_delegate, self.proposal) Decision(self.high_delegate, self.poll).make(Vote.YES) self.decision.reload() self.assertFalse(self.decision.is_self_decided()) def test_two_delegations_at_the_same_level_that_disagree_cancel_each_other( self): # This is meant as a safeguard: if I don't fully trust my delegates # I can delegate to n delegates, and my vote will only be autocast # if they all agree # If not, I need to decide myself self._do_delegate(self.me, self.high_delegate, self.proposal) self._do_delegate(self.me, self.low_delegate, self.proposal) Decision(self.high_delegate, self.poll).make(Vote.YES) Decision(self.low_delegate, self.poll).make(Vote.NO) self.assertEqual(self.decision.reload().result, None, "needs to cast his own vote") def test_two_delegations_at_the_same_level_that_agree_reinforce_each_other( self): self._do_delegate(self.me, self.high_delegate, self.proposal) self._do_delegate(self.me, self.low_delegate, self.proposal) Decision(self.high_delegate, self.poll).make(Vote.YES) Decision(self.low_delegate, self.poll).make(Vote.YES) self.assertEqual(self.decision.reload().result, Vote.YES) def test_two_delegations_at_the_same_level_are_both_relevant_votes(self): self._do_delegate(self.me, self.high_delegate, self.proposal) self._do_delegate(self.me, self.low_delegate, self.proposal) Decision(self.high_delegate, self.poll).make(Vote.YES) Decision(self.low_delegate, self.poll).make(Vote.YES) self.assertEqual(len(self.decision.reload().relevant_votes), 2) def test_own_vote_overrides_delegations(self): self._do_delegate(self.me, self.high_delegate, self.proposal) Decision(self.high_delegate, self.poll).make(Vote.YES) self.decision.make(Vote.NO) self.assertEqual(self.decision.reload().result, Vote.NO) def test_delegation_is_recorded_as_just_another_vote(self): self._do_delegate(self.me, self.high_delegate, self.proposal) self.assertEqual(len(self.decision.reload().votes), 0) Decision(self.high_delegate, self.poll).make(Vote.YES) self.assertEqual(len(self.decision.reload().votes), 1) def test_delegation_is_transitive(self): self._do_delegate(self.me, self.low_delegate, self.proposal) self._do_delegate(self.low_delegate, self.high_delegate, self.proposal) Decision(self.high_delegate, self.poll).make(Vote.YES) self.assertEqual(self.decision.reload().result, Vote.YES) def test_delegation_is_transitive_across_delegation_levels(self): self._do_delegate(self.me, self.low_delegate, self.proposal) self._do_delegate(self.low_delegate, self.high_delegate, self.proposal) Decision(self.high_delegate, self.poll).make(Vote.YES) self.assertEqual(self.decision.reload().result, Vote.YES)
class TestDecisionWithoutDelegation(TestController): def setUp(self): super(TestDecisionWithoutDelegation, self).setUp() self.proposal = tt_make_proposal(voting=True) self.poll = Poll.create(self.proposal, self.proposal.creator, Poll.ADOPT) self.decision = Decision(self.proposal.creator, self.poll) def test_new_decisions_have_no_votes(self): self.assertEqual(len(self.decision.votes), 0) self.assertEqual(len(self.decision.relevant_votes), 0) self.assertEqual(self.decision.result, None, "Not voted yet == not recorded for quorum") # TODO: this quorum thing needs additional tests def test_new_decisions_are_not_decided(self): self.assertFalse(self.decision.is_decided()) self.assertFalse(self.decision.is_self_decided()) def test_can_vote_directly(self): self.decision.make(Vote.YES) self.assertEqual(self.decision.result, Vote.YES) def test_decision_with_a_vote_is_decided(self): self.decision.make(Vote.YES) self.assertTrue(self.decision.is_decided()) self.assertTrue(self.decision.is_self_decided()) def test_can_override_previous_choice(self): self.decision.make(Vote.YES) self.assertEqual(self.decision.result, Vote.YES) self.decision.make(Vote.ABSTAIN) self.assertEqual(self.decision.result, Vote.ABSTAIN) self.decision.make(Vote.NO) self.assertEqual(self.decision.result, Vote.NO) def test_direct_votes_always_have_only_one_relevant_vote(self): self.decision.make(Vote.YES) self.decision.make(Vote.NO) self.decision.make(Vote.ABSTAIN) self.assertEqual(len(self.decision.relevant_votes), 1) # History access def test_multiple_votes_for_one_decision_are_recorded_for_posterity(self): self.decision.make(Vote.YES) self.decision.make(Vote.YES) self.assertEqual(len(self.decision.votes), 2) def test_old_decisions_can_be_retrieved(self): self.decision.make(Vote.YES) self.decision.make(Vote.YES) self.decision.make(Vote.NO) # votes are FIFO self.assertEqual(self.decision.votes[0].orientation, Vote.NO) self.assertEqual(self.decision.votes[1].orientation, Vote.YES) self.assertEqual(self.decision.votes[2].orientation, Vote.YES)
def test_two_delegations_at_the_same_level_are_both_relevant_votes(self): self._do_delegate(self.me, self.high_delegate, self.proposal) self._do_delegate(self.me, self.low_delegate, self.proposal) Decision(self.high_delegate, self.poll).make(Vote.YES) Decision(self.low_delegate, self.poll).make(Vote.YES) self.assertEqual(len(self.decision.reload().relevant_votes), 2)
class TestDecisionWithoutDelegation(TestController): def setUp(self): self.proposal = tt_make_proposal(voting=True) self.poll = Poll.create(self.proposal, self.proposal.creator, Poll.ADOPT) self.decision = Decision(self.proposal.creator, self.poll) def test_new_decisions_have_no_votes(self): self.assertEqual(len(self.decision.votes), 0) self.assertEqual(len(self.decision.relevant_votes), 0) self.assertEqual(self.decision.result, None, "Not voted yet == not recorded for quorum") # TODO: this quorum thing needs additional tests def test_new_decisions_are_not_decided(self): self.assertFalse(self.decision.is_decided()) self.assertFalse(self.decision.is_self_decided()) def test_can_vote_directly(self): self.decision.make(Vote.YES) self.assertEqual(self.decision.result, Vote.YES) def test_decision_with_a_vote_is_decided(self): self.decision.make(Vote.YES) self.assertTrue(self.decision.is_decided()) self.assertTrue(self.decision.is_self_decided()) def test_can_override_previous_choice(self): self.decision.make(Vote.YES) self.assertEqual(self.decision.result, Vote.YES) self.decision.make(Vote.ABSTAIN) self.assertEqual(self.decision.result, Vote.ABSTAIN) self.decision.make(Vote.NO) self.assertEqual(self.decision.result, Vote.NO) def test_direct_votes_always_have_only_one_relevant_vote(self): self.decision.make(Vote.YES) self.decision.make(Vote.NO) self.decision.make(Vote.ABSTAIN) self.assertEqual(len(self.decision.relevant_votes), 1) # History access def test_multiple_votes_for_one_decision_are_recorded_for_posterity(self): self.decision.make(Vote.YES) self.decision.make(Vote.YES) self.assertEqual(len(self.decision.votes), 2) def test_old_decisions_can_be_retrieved(self): self.decision.make(Vote.YES) self.decision.make(Vote.YES) self.decision.make(Vote.NO) # votes are FIFO self.assertEqual(self.decision.votes[0].orientation, Vote.NO) self.assertEqual(self.decision.votes[1].orientation, Vote.YES) self.assertEqual(self.decision.votes[2].orientation, Vote.YES)