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
Esempio n. 4
0
    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,
        )