Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,11 @@ The following classes of votes are supported:
- Approval voting
- Ranked voting
- Score voting (also called range or cardinal voting)

These vote classes can be converted to each other by objects in the `convert`
module, where you can also find utilities to facilitate district-wise
elections.
elections. Combining the above components can create complex systems such as
mixed-member proportional or multilevel compensatory systems.

The `candidate` and `vote` allow for validity checking of candidate nominations
and cast ballots respectively.
Expand Down
2 changes: 2 additions & 0 deletions tests/evaluate/test_mixed.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,5 @@
def test_smith_score(votes, expected_winner):
winner = SMITH_SCORE.evaluate(votes, n_seats=1)
assert winner == expected_winner


160 changes: 160 additions & 0 deletions tests/io/data/debian2003.abif
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
3: [Bdale Garbee]>[Branden Robinson]>[Martin Michlmayr]>[None Of The Above]
1: [Moshe Zadka]>[Martin Michlmayr]>[Bdale Garbee]>[Branden Robinson]>[None Of The Above]
4: [Bdale Garbee]>[Martin Michlmayr]>[Branden Robinson]
15: [Branden Robinson]>[Bdale Garbee]>[Martin Michlmayr]>[Moshe Zadka]>[None Of The Above]
10: [Bdale Garbee]>[Martin Michlmayr]>[Branden Robinson]>[None Of The Above]>[Moshe Zadka]
2: [Martin Michlmayr]>[Branden Robinson]>[None Of The Above]>[Bdale Garbee]>[Moshe Zadka]
5: [Branden Robinson]>[Bdale Garbee]
7: [Bdale Garbee]>[Branden Robinson]>[Martin Michlmayr]>[None Of The Above]>[Moshe Zadka]
10: [Branden Robinson]>[Bdale Garbee]>[Martin Michlmayr]>[Moshe Zadka]
5: [Bdale Garbee]>[Branden Robinson]>[Martin Michlmayr]>[Moshe Zadka]
2: [Moshe Zadka]>[Martin Michlmayr]>[Branden Robinson]=[Bdale Garbee]>[None Of The Above]
12: [Martin Michlmayr]>[Bdale Garbee]>[Branden Robinson]>[None Of The Above]>[Moshe Zadka]
3: [Martin Michlmayr]>[Branden Robinson]>[None Of The Above]
2: [Branden Robinson]>[Bdale Garbee]>[None Of The Above]>[Martin Michlmayr]>[Moshe Zadka]
15: [Branden Robinson]>[Martin Michlmayr]>[Bdale Garbee]>[Moshe Zadka]>[None Of The Above]
4: [Branden Robinson]=[Martin Michlmayr]>[Bdale Garbee]>[None Of The Above]>[Moshe Zadka]
3: [Branden Robinson]>[Martin Michlmayr]>[None Of The Above]>[Bdale Garbee]>[Moshe Zadka]
7: [Branden Robinson]>[Martin Michlmayr]>[Bdale Garbee]>[Moshe Zadka]
8: [Bdale Garbee]>[Martin Michlmayr]>[Branden Robinson]>[Moshe Zadka]>[None Of The Above]
7: [Branden Robinson]>[Bdale Garbee]>[None Of The Above]
10: [Bdale Garbee]>[Branden Robinson]
9: [Martin Michlmayr]>[Branden Robinson]>[Bdale Garbee]>[Moshe Zadka]>[None Of The Above]
11: [Bdale Garbee]>[Branden Robinson]>[Martin Michlmayr]>[Moshe Zadka]>[None Of The Above]
13: [Martin Michlmayr]>[Branden Robinson]>[Bdale Garbee]>[None Of The Above]>[Moshe Zadka]
1: [Bdale Garbee]>[Branden Robinson]>[Moshe Zadka]>[None Of The Above]>[Martin Michlmayr]
2: [Branden Robinson]
3: [Branden Robinson]>[Martin Michlmayr]>[Moshe Zadka]>[Bdale Garbee]>[None Of The Above]
4: [Branden Robinson]>[Bdale Garbee]>[Martin Michlmayr]
2: [Martin Michlmayr]>[Bdale Garbee]>[Moshe Zadka]>[None Of The Above]
1: [Bdale Garbee]>[Martin Michlmayr]>[Branden Robinson]=[Moshe Zadka]=[None Of The Above]
2: [Martin Michlmayr]>[Bdale Garbee]>[None Of The Above]>[Moshe Zadka]>[Branden Robinson]
8: [Martin Michlmayr]>[Bdale Garbee]>[None Of The Above]
9: [Bdale Garbee]>[Martin Michlmayr]>[Branden Robinson]>[Moshe Zadka]
8: [Martin Michlmayr]>[Bdale Garbee]>[Branden Robinson]>[Moshe Zadka]>[None Of The Above]
1: [Bdale Garbee]>[Branden Robinson]=[Martin Michlmayr]
6: [Bdale Garbee]>[Martin Michlmayr]>[None Of The Above]>[Moshe Zadka]>[Branden Robinson]
1: [Moshe Zadka]>[Branden Robinson]>[Bdale Garbee]>[Martin Michlmayr]>[None Of The Above]
26: [Branden Robinson]>[Martin Michlmayr]>[Bdale Garbee]>[None Of The Above]>[Moshe Zadka]
1: [Bdale Garbee]>[Branden Robinson]>[Martin Michlmayr]>[Moshe Zadka]=[None Of The Above]
4: [Martin Michlmayr]>[Branden Robinson]>[Bdale Garbee]>[None Of The Above]
2: [Bdale Garbee]>[None Of The Above]>[Martin Michlmayr]=[Moshe Zadka]>[Branden Robinson]
3: [Bdale Garbee]>[Branden Robinson]>[None Of The Above]>[Martin Michlmayr]>[Moshe Zadka]
2: [Branden Robinson]>[Martin Michlmayr]>[Moshe Zadka]>[Bdale Garbee]
1: [Martin Michlmayr]>[Bdale Garbee]>[Moshe Zadka]
3: [Martin Michlmayr]>[Bdale Garbee]
3: [Martin Michlmayr]>[Branden Robinson]>[Bdale Garbee]
5: [Martin Michlmayr]>[Bdale Garbee]>[Moshe Zadka]>[Branden Robinson]>[None Of The Above]
1: [Martin Michlmayr]>[Moshe Zadka]>[Branden Robinson]=[Bdale Garbee]>[None Of The Above]
3: [Branden Robinson]>[Martin Michlmayr]>[None Of The Above]>[Moshe Zadka]>[Bdale Garbee]
1: [Branden Robinson]>[Moshe Zadka]>[Bdale Garbee]>[Martin Michlmayr]
3: [Martin Michlmayr]=[Bdale Garbee]>[Branden Robinson]>[Moshe Zadka]>[None Of The Above]
8: [Branden Robinson]>[Bdale Garbee]>[Martin Michlmayr]>[None Of The Above]>[Moshe Zadka]
1: [Branden Robinson]>[Martin Michlmayr]>[None Of The Above]
3: [Branden Robinson]>[Bdale Garbee]>[Martin Michlmayr]>[None Of The Above]
1: [Martin Michlmayr]>[Moshe Zadka]>[Branden Robinson]>[None Of The Above]>[Bdale Garbee]
1: [Moshe Zadka]
3: [Martin Michlmayr]>[Bdale Garbee]>[Branden Robinson]>[None Of The Above]
4: [Martin Michlmayr]>[Bdale Garbee]>[Branden Robinson]
6: [Martin Michlmayr]>[Bdale Garbee]>[None Of The Above]>[Branden Robinson]>[Moshe Zadka]
3: [Branden Robinson]=[Bdale Garbee]>[Martin Michlmayr]>[None Of The Above]>[Moshe Zadka]
5: [Branden Robinson]>[Bdale Garbee]>[Moshe Zadka]>[Martin Michlmayr]>[None Of The Above]
3: [Bdale Garbee]>[None Of The Above]>[Moshe Zadka]>[Martin Michlmayr]>[Branden Robinson]
3: [Martin Michlmayr]=[Bdale Garbee]>[Branden Robinson]>[None Of The Above]>[Moshe Zadka]
2: [Bdale Garbee]>[Martin Michlmayr]>[None Of The Above]>[Branden Robinson]=[Moshe Zadka]
1: [Martin Michlmayr]=[Bdale Garbee]>[Branden Robinson]>[Moshe Zadka]=[None Of The Above]
4: [Martin Michlmayr]>[Branden Robinson]>[Bdale Garbee]>[Moshe Zadka]
1: [Moshe Zadka]>[Martin Michlmayr]>[Bdale Garbee]
1: [Martin Michlmayr]>[Moshe Zadka]>[Bdale Garbee]>[None Of The Above]
3: [Branden Robinson]>[None Of The Above]
1: [Moshe Zadka]>[Martin Michlmayr]>[Bdale Garbee]>[None Of The Above]
2: [Martin Michlmayr]>[Moshe Zadka]>[Bdale Garbee]>[Branden Robinson]>[None Of The Above]
1: [Bdale Garbee]>[Martin Michlmayr]>[Branden Robinson]>[Moshe Zadka]=[None Of The Above]
3: [Bdale Garbee]
2: [Branden Robinson]>[Martin Michlmayr]=[Moshe Zadka]=[Bdale Garbee]
3: [Martin Michlmayr]>[Branden Robinson]=[Bdale Garbee]>[None Of The Above]>[Moshe Zadka]
3: [Bdale Garbee]>[Branden Robinson]=[Martin Michlmayr]>[Moshe Zadka]
4: [Branden Robinson]=[Martin Michlmayr]>[Bdale Garbee]>[Moshe Zadka]
1: [Branden Robinson]=[Bdale Garbee]>[Martin Michlmayr]>[Moshe Zadka]>[None Of The Above]
3: [Branden Robinson]>[None Of The Above]>[Martin Michlmayr]>[Bdale Garbee]>[Moshe Zadka]
1: [Branden Robinson]>[None Of The Above]>[Martin Michlmayr]=[Moshe Zadka]=[Bdale Garbee]
1: [Branden Robinson]>[Martin Michlmayr]>[Moshe Zadka]=[None Of The Above]=[Bdale Garbee]
1: [Moshe Zadka]>[Martin Michlmayr]>[Branden Robinson]>[Bdale Garbee]>[None Of The Above]
9: [Martin Michlmayr]>[Bdale Garbee]>[Branden Robinson]>[Moshe Zadka]
1: [Branden Robinson]=[None Of The Above]>[Martin Michlmayr]>[Bdale Garbee]>[Moshe Zadka]
3: [Bdale Garbee]>[Moshe Zadka]>[Martin Michlmayr]>[None Of The Above]>[Branden Robinson]
6: [Bdale Garbee]>[Martin Michlmayr]>[Moshe Zadka]>[None Of The Above]>[Branden Robinson]
1: [Bdale Garbee]>[None Of The Above]
3: [Bdale Garbee]>[Branden Robinson]>[Moshe Zadka]>[Martin Michlmayr]>[None Of The Above]
2: [Bdale Garbee]>[Martin Michlmayr]>[Moshe Zadka]>[None Of The Above]
1: [Branden Robinson]>[Martin Michlmayr]>[None Of The Above]>[Moshe Zadka]=[Bdale Garbee]
5: [Bdale Garbee]>[Martin Michlmayr]>[None Of The Above]
1: [Bdale Garbee]>[Branden Robinson]>[Martin Michlmayr]=[Moshe Zadka]
4: [Bdale Garbee]>[Martin Michlmayr]>[Moshe Zadka]>[Branden Robinson]>[None Of The Above]
1: [Martin Michlmayr]>[Moshe Zadka]>[Bdale Garbee]>[Branden Robinson]
4: [Bdale Garbee]>[Martin Michlmayr]>[None Of The Above]>[Branden Robinson]>[Moshe Zadka]
1: [Bdale Garbee]>[Moshe Zadka]>[Branden Robinson]=[None Of The Above]
1: [Branden Robinson]>[Martin Michlmayr]=[Bdale Garbee]>[None Of The Above]
1: [Martin Michlmayr]>[None Of The Above]
1: [Bdale Garbee]>[Martin Michlmayr]=[Moshe Zadka]>[None Of The Above]
1: [Bdale Garbee]>[Martin Michlmayr]>[Branden Robinson]>[None Of The Above]
1: [Martin Michlmayr]>[Branden Robinson]=[Bdale Garbee]>[None Of The Above]
3: [Branden Robinson]>[Martin Michlmayr]>[Bdale Garbee]>[None Of The Above]
1: [Branden Robinson]=[Martin Michlmayr]=[Bdale Garbee]>[None Of The Above]>[Moshe Zadka]
1: [Bdale Garbee]>[Branden Robinson]>[None Of The Above]>[Martin Michlmayr]=[Moshe Zadka]
2: [Martin Michlmayr]=[Bdale Garbee]>[Moshe Zadka]>[Branden Robinson]>[None Of The Above]
1: [Martin Michlmayr]=[Bdale Garbee]>[Branden Robinson]>[Moshe Zadka]
1: [Martin Michlmayr]>[None Of The Above]>[Bdale Garbee]
1: [Branden Robinson]>[Martin Michlmayr]=[Bdale Garbee]>[Moshe Zadka]
3: [Martin Michlmayr]>[Branden Robinson]>[Moshe Zadka]>[Bdale Garbee]>[None Of The Above]
4: [Branden Robinson]>[Martin Michlmayr]=[Bdale Garbee]>[Moshe Zadka]>[None Of The Above]
4: [Branden Robinson]>[Bdale Garbee]>[Moshe Zadka]>[Martin Michlmayr]
2: [Martin Michlmayr]
1: [Branden Robinson]=[Bdale Garbee]>[Martin Michlmayr]=[Moshe Zadka]
1: [Branden Robinson]=[Martin Michlmayr]>[Bdale Garbee]>[None Of The Above]
1: [Martin Michlmayr]>[Bdale Garbee]>[Moshe Zadka]>[None Of The Above]>[Branden Robinson]
1: [Martin Michlmayr]>[Branden Robinson]>[Moshe Zadka]
1: [Branden Robinson]=[Bdale Garbee]>[Martin Michlmayr]>[Moshe Zadka]
3: [Bdale Garbee]>[Branden Robinson]>[Martin Michlmayr]
2: [Bdale Garbee]>[Martin Michlmayr]
2: [Bdale Garbee]>[Martin Michlmayr]>[Moshe Zadka]>[Branden Robinson]
2: [Branden Robinson]>[Bdale Garbee]>[Martin Michlmayr]=[Moshe Zadka]
3: [Martin Michlmayr]>[Branden Robinson]=[Bdale Garbee]>[Moshe Zadka]>[None Of The Above]
2: [Bdale Garbee]>[Branden Robinson]>[None Of The Above]
1: [Bdale Garbee]>[None Of The Above]>[Martin Michlmayr]>[Branden Robinson]>[Moshe Zadka]
1: [Branden Robinson]=[Bdale Garbee]>[Moshe Zadka]>[Martin Michlmayr]>[None Of The Above]
1: [Martin Michlmayr]=[Bdale Garbee]>[None Of The Above]>[Branden Robinson]=[Moshe Zadka]
1: [Branden Robinson]>[Bdale Garbee]>[Martin Michlmayr]=[Moshe Zadka]>[None Of The Above]
1: [Branden Robinson]>[Bdale Garbee]>[None Of The Above]>[Martin Michlmayr]=[Moshe Zadka]
1: [Bdale Garbee]>[Branden Robinson]>[Martin Michlmayr]=[Moshe Zadka]=[None Of The Above]
2: [Branden Robinson]>[Martin Michlmayr]=[Moshe Zadka]=[Bdale Garbee]>[None Of The Above]
1: [Branden Robinson]>[Bdale Garbee]>[None Of The Above]>[Moshe Zadka]>[Martin Michlmayr]
2: [Martin Michlmayr]>[Bdale Garbee]>[Branden Robinson]=[Moshe Zadka]>[None Of The Above]
2: [Martin Michlmayr]>[Branden Robinson]=[Bdale Garbee]>[Moshe Zadka]
1: [Branden Robinson]>[None Of The Above]>[Martin Michlmayr]>[Moshe Zadka]=[Bdale Garbee]
1: [Moshe Zadka]>[Bdale Garbee]>[Branden Robinson]>[Martin Michlmayr]>[None Of The Above]
3: [Branden Robinson]>[Martin Michlmayr]=[Bdale Garbee]>[None Of The Above]>[Moshe Zadka]
1: [Bdale Garbee]>[Moshe Zadka]>[Martin Michlmayr]>[Branden Robinson]
1: [None Of The Above]>[Moshe Zadka]>[Bdale Garbee]>[Branden Robinson]>[Martin Michlmayr]
2: [Bdale Garbee]>[Branden Robinson]>[Martin Michlmayr]=[None Of The Above]>[Moshe Zadka]
1: [None Of The Above]
1: [Martin Michlmayr]>[None Of The Above]>[Bdale Garbee]>[Moshe Zadka]>[Branden Robinson]
2: [Branden Robinson]=[Martin Michlmayr]>[Bdale Garbee]>[Moshe Zadka]>[None Of The Above]
1: [Martin Michlmayr]>[Bdale Garbee]>[Branden Robinson]=[None Of The Above]
1: [Martin Michlmayr]>[Bdale Garbee]>[Branden Robinson]=[Moshe Zadka]=[None Of The Above]
2: [Martin Michlmayr]>[Branden Robinson]=[Bdale Garbee]
1: [Martin Michlmayr]>[Branden Robinson]>[Moshe Zadka]>[Bdale Garbee]
1: [Martin Michlmayr]>[Bdale Garbee]>[Moshe Zadka]>[Branden Robinson]
2: [Martin Michlmayr]>[Branden Robinson]
1: [Martin Michlmayr]=[Bdale Garbee]>[Branden Robinson]=[Moshe Zadka]
1: [Bdale Garbee]>[Branden Robinson]=[Moshe Zadka]=[Martin Michlmayr]
1: [Martin Michlmayr]=[Moshe Zadka]>[Bdale Garbee]>[Branden Robinson]
1: [Bdale Garbee]>[Moshe Zadka]>[Branden Robinson]>[Martin Michlmayr]>[None Of The Above]
1: [Martin Michlmayr]>[Branden Robinson]>[Moshe Zadka]=[Bdale Garbee]
1: [Branden Robinson]=[Martin Michlmayr]=[Moshe Zadka]=[Bdale Garbee]>[None Of The Above]
1: [Martin Michlmayr]>[Moshe Zadka]>[Bdale Garbee]>[None Of The Above]>[Branden Robinson]
1: [Martin Michlmayr]>[Branden Robinson]>[Bdale Garbee]>[Moshe Zadka]=[None Of The Above]
1: [Branden Robinson]=[Bdale Garbee]>[Moshe Zadka]>[None Of The Above]>[Martin Michlmayr]
1: [Martin Michlmayr]>[Branden Robinson]>[None Of The Above]>[Moshe Zadka]=[Bdale Garbee]
1: [Branden Robinson]>[Moshe Zadka]
1: [Moshe Zadka]>[Bdale Garbee]>[None Of The Above]
84 changes: 43 additions & 41 deletions tests/io/test_blt.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,52 +31,51 @@ def test_incomplete_header():

def test_maemo_blt():
with open(os.path.join(DATA_DIR, 'maemo.blt'), encoding='utf8') as infile:
votes, n_seats, cands, name = votelib.io.blt.load(infile)
assert name == 'Community Council Election Q1 2018'
assert [cand.name for cand in cands] == [
voting_setup = votelib.io.blt.load(infile)
assert voting_setup.election_name == 'Community Council Election Q1 2018'
assert [cand.name for cand in voting_setup.candidates] == [
'mosen (Timo Könnecke)',
'sicelo (Sicelo Mhlongo)',
'juiceme (Jussi Ohenoja)',
'm4r0v3r (Martin Ghosal)',
'eekkelund (Eetu Kahelin)',
]
assert not any(cand.withdrawn for cand in cands)
assert n_seats == 3
assert not any(cand.withdrawn for cand in voting_setup.candidates)
assert voting_setup.n_seats == 3
assert sum(
n_votes for rvote, n_votes in votes.items()
n_votes for rvote, n_votes in voting_setup.votes.items()
if rvote and rvote[0].name == 'juiceme (Jussi Ohenoja)'
) == 31


def test_rational_blt():
with open(os.path.join(DATA_DIR, 'rational.blt'), encoding='utf8') as infile:
votes, n_seats, cands, name = votelib.io.blt.load(infile)
assert name == 'RationalMedia Board 2020 Election'
assert [cand.name for cand in cands] == [
voting_setup = votelib.io.blt.load(infile)
assert voting_setup.election_name == 'RationalMedia Board 2020 Election'
assert [cand.name for cand in voting_setup.candidates] == [
'Dysk',
'GrammarCommie',
'LeftyGreenMario',
'RoninMacbeth',
'Other',
]
assert not any(cand.withdrawn for cand in cands)
assert n_seats == 4
assert not any(cand.withdrawn for cand in voting_setup.candidates)
assert voting_setup.n_seats == 4
assert sum(
n_votes for rvote, n_votes in votes.items()
n_votes for rvote, n_votes in voting_setup.votes.items()
if rvote and rvote[0].name == 'GrammarCommie'
) == 0



def test_atwood_so_blt():
with open(os.path.join(DATA_DIR, 'atwood_so.blt'), encoding='utf8') as infile:
votes, n_seats, cands, name = votelib.io.blt.loads(infile.read())
assert name == 'Gardening Club Election'
assert [cand.name for cand in cands] == ['Amy', 'Bob', 'Chuck', 'Diane']
assert all(cand.withdrawn == (cand.name == 'Bob') for cand in cands)
assert n_seats == 2
voting_setup = votelib.io.blt.loads(infile.read())
assert voting_setup.election_name == 'Gardening Club Election'
assert [cand.name for cand in voting_setup.candidates] == ['Amy', 'Bob', 'Chuck', 'Diane']
assert all(cand.withdrawn == (cand.name == 'Bob') for cand in voting_setup.candidates)
assert voting_setup.n_seats == 2
assert sum(
n_votes for rvote, n_votes in votes.items()
n_votes for rvote, n_votes in voting_setup.votes.items()
if rvote and rvote[0].name == 'Amy'
) == 3

Expand All @@ -89,8 +88,8 @@ def test_fail_empty():

def test_maemo():
with open(os.path.join(DATA_DIR, 'maemo.blt'), encoding='utf8') as infile:
votes, n_seats, cands, name = votelib.io.blt.load(infile)
assert [cand.name for cand in STV_EVAL.evaluate(votes, n_seats)] == [
voting_setup = votelib.io.blt.load(infile)
assert [cand.name for cand in STV_EVAL.evaluate(voting_setup.votes, voting_setup.n_seats)] == [
'juiceme (Jussi Ohenoja)',
'mosen (Timo Könnecke)',
'eekkelund (Eetu Kahelin)'
Expand All @@ -99,17 +98,17 @@ def test_maemo():

def test_rational():
with open(os.path.join(DATA_DIR, 'rational.blt'), encoding='utf8') as infile:
votes, n_seats, cands, name = votelib.io.blt.load(infile)
assert set(cand.name for cand in STV_EVAL.evaluate(votes, n_seats)) == {
voting_setup = votelib.io.blt.load(infile)
assert set(cand.name for cand in STV_EVAL.evaluate(voting_setup.votes, voting_setup.n_seats)) == {
'LeftyGreenMario', 'Dysk', 'GrammarCommie', 'RoninMacbeth'
}


def test_gnome_26():
# https://vote.gnome.org/results.php?election_id=26
with open(os.path.join(DATA_DIR, 'gnome_26.blt'), encoding='utf8') as infile:
votes, n_seats, cands, name = votelib.io.blt.load(infile)
assert set(cand.name for cand in STV_EVAL.evaluate(votes, n_seats)) == {
voting_setup = votelib.io.blt.load(infile)
assert set(cand.name for cand in STV_EVAL.evaluate(voting_setup.votes, voting_setup.n_seats)) == {
'Allan Day', 'Carlos Soriano', 'Ekaterina Gerasimova',
'Federico Mena Quintero', 'Nuritzi Sanchez', 'Philip Chimento',
'Robert McQueen',
Expand All @@ -119,60 +118,63 @@ def test_gnome_26():
def test_gnome_26_roundtrip():
with open(os.path.join(DATA_DIR, 'gnome_26.blt'), encoding='utf8') as infile:
blt_text = infile.read()
loaded = votelib.io.blt.loads(blt_text)
roundtripped = votelib.io.blt.dumps(*loaded)
voting_setup = votelib.io.blt.loads(blt_text)
roundtripped = votelib.io.blt.dumps(voting_setup)
assert roundtripped.strip() == blt_text.strip()
buffer = io.StringIO()
roundtripped_fileobj = votelib.io.blt.dump(buffer, *loaded)
roundtripped_fileobj = votelib.io.blt.dump(buffer, voting_setup)
assert buffer.getvalue().strip() == blt_text.strip()


def test_nocand():
TEST_S = '''3 1
test_s = '''3 1
-2
4 2 1 3 0
2 3 2 1 0

1 2 3 0
0
'''
votes, n_seats, cands, name = votelib.io.blt.loads(TEST_S)
voting_setup = votelib.io.blt.loads(test_s)
cands = voting_setup.candidates
assert len(cands) == 3
assert cands[1].withdrawn
assert votes == {
assert voting_setup.votes == {
(cands[1], cands[0], cands[2]): 4,
(cands[2], cands[1], cands[0]): 2,
(cands[1], cands[2]): 1,
}
assert n_seats == 1
assert name is None
assert voting_setup.n_seats == 1
assert voting_setup.election_name is None


def test_incomplete_body():
TEST_S = '''3 1
test_s = '''3 1
-2
4 2 1 3 0
'''
with pytest.raises(votelib.io.blt.BLTParseError) as excinfo:
votelib.io.blt.loads(TEST_S)
votelib.io.blt.loads(test_s)
assert 'incomplete' in str(excinfo.value)


def test_incomplete_row():
TEST_S = '''3 1
test_s = '''3 1
-2
4 2 1 3
0
'''
with pytest.raises(votelib.io.blt.BLTParseError) as excinfo:
votelib.io.blt.loads(TEST_S)
votelib.io.blt.loads(test_s)
assert 'must be zero-terminated' in str(excinfo.value)

def test_incomplete_row():
TEST_S = '''3 1

def test_row_float():
test_s = '''3 1
-2
4 2 1 3.5 0
0
'''
with pytest.raises(votelib.io.blt.BLTParseError) as excinfo:
votelib.io.blt.loads(TEST_S)

votelib.io.blt.loads(test_s)
assert 'invalid BLT numberline item' in str(excinfo.value)
Loading