def _candidate_to_selection_description( candidate: Candidate, sequence_order: int) -> SelectionDescription: """ Given a `Candidate` and its position in a list of candidates, returns an equivalent `SelectionDescription`. The selection's `object_id` will contain the candidates's `object_id` within, but will have a "c-" prefix attached, so you'll be able to tell that they're related. """ return SelectionDescription(f"c-{candidate.object_id}", candidate.get_candidate_id(), sequence_order)
def candidates(draw: _DrawType, party_list: Optional[List[Party]]): """ Generates a `Candidate` object, assigning it one of the parties from `party_list` at random, with a chance that there will be no party assigned at all. :param draw: Hidden argument, used by Hypothesis. :param party_list: A list of `Party` objects. If None, then the resulting `Candidate` will have no party. """ if party_list: party = party_list[draw(integers(0, len(party_list) - 1))] party_id = party.get_party_id() else: party_id = None return Candidate( str(draw(uuids())), draw(internationalized_human_names()), party_id, draw(one_of(just(None), urls())), )
def get_fake_election(self) -> ElectionDescription: """ Get a single Fake Election object that is manually constructed with default values """ fake_ballot_style = BallotStyle("some-ballot-style-id") fake_ballot_style.geopolitical_unit_ids = ["some-geopoltical-unit-id"] fake_referendum_ballot_selections = [ # Referendum selections are simply a special case of `candidate` in the object model SelectionDescription("some-object-id-affirmative", "some-candidate-id-1", 0), SelectionDescription("some-object-id-negative", "some-candidate-id-2", 1), ] sequence_order = 0 number_elected = 1 votes_allowed = 1 fake_referendum_contest = ReferendumContestDescription( "some-referendum-contest-object-id", "some-geopoltical-unit-id", sequence_order, VoteVariationType.one_of_m, number_elected, votes_allowed, "some-referendum-contest-name", fake_referendum_ballot_selections, ) fake_candidate_ballot_selections = [ SelectionDescription("some-object-id-candidate-1", "some-candidate-id-1", 0), SelectionDescription("some-object-id-candidate-2", "some-candidate-id-2", 1), SelectionDescription("some-object-id-candidate-3", "some-candidate-id-3", 2), ] sequence_order_2 = 1 number_elected_2 = 2 votes_allowed_2 = 2 fake_candidate_contest = CandidateContestDescription( "some-candidate-contest-object-id", "some-geopoltical-unit-id", sequence_order_2, VoteVariationType.one_of_m, number_elected_2, votes_allowed_2, "some-candidate-contest-name", fake_candidate_ballot_selections, ) fake_election = ElectionDescription( election_scope_id="some-scope-id", type=ElectionType.unknown, start_date=datetime.now(), end_date=datetime.now(), geopolitical_units=[ GeopoliticalUnit( "some-geopoltical-unit-id", "some-gp-unit-name", ReportingUnitType.unknown, ) ], parties=[Party("some-party-id-1"), Party("some-party-id-2")], candidates=[ Candidate("some-candidate-id-1"), Candidate("some-candidate-id-2"), Candidate("some-candidate-id-3"), ], contests=[fake_referendum_contest, fake_candidate_contest], ballot_styles=[fake_ballot_style], ) return fake_election
def _contest_name_to_description( self, name: str, contest_uid_maker: UidMaker, gp_uid_maker: UidMaker, ) -> Tuple[ContestDescription, List[Candidate], GeopoliticalUnit, Dict[ str, str]]: selections: List[SelectionDescription] = [] candidates: List[Candidate] = [] # We're collecting the candidates at the same time that we're collecting the selections # to make sure that the object_id's are properly synchronized. Consider the case where # we ended up with two candidates with identical names. In the Dominion CSV, we'd have # no way to tell if they were actually the same person running in two separate contests, # or whether they were distinct. This solution ensures that we create a fresh Candidate # one-to-one with every SelectionDescription. # This method will be called separately for every contest name, and the resulting lists # of candidates should be merged to make the complete list that goes into an # ElectionDescription. candidate_to_column: Dict[str, str] = {} for c in self.metadata.contest_map[name]: id_str = c.object_id id_number = int( id_str[1:]) # total hack: stripping off the first char candidate = Candidate( object_id=id_str, ballot_name=_str_to_internationalized_text_en(c.choice_name), party_id=c.party_name if c.party_name != "" else None, image_uri=None, ) # To make our lives easier, we're going to use identical object_ids for selections # and candidates, and hopefully this won't break anything. candidates.append(candidate) selections.append( SelectionDescription( object_id=candidate.object_id, candidate_id=candidate.object_id, sequence_order=id_number, )) candidate_to_column[candidate.object_id] = c.to_string() gp = GeopoliticalUnit( object_id=gp_uid_maker.next(), name=name, type=ReportingUnitType.unknown, ) id_number, id_str = contest_uid_maker.next_int() number_elected = self.metadata.max_votes_for_map[name] vote_variation_type = (VoteVariationType.one_of_m if number_elected == 1 else VoteVariationType.n_of_m) vote_allowed = None if number_elected < 2 else number_elected return ( ContestDescription( object_id=id_str, electoral_district_id=gp.object_id, sequence_order=id_number, vote_variation=vote_variation_type, number_elected=number_elected, votes_allowed=vote_allowed, name=name, ballot_selections=selections, ballot_title=_str_to_internationalized_text_en(name), ), candidates, gp, candidate_to_column, )