diff --git a/.pylintrc b/.pylintrc index 838f62f78..38e63ae1a 100644 --- a/.pylintrc +++ b/.pylintrc @@ -93,7 +93,8 @@ disable=raw-checker-failed, logging-fstring-interpolation, broad-exception-raised, use-dict-literal, - use-implicit-booleaness-not-comparison + use-implicit-booleaness-not-comparison, + too-many-return-statements diff --git a/server/activity_log/slack_worker.py b/server/activity_log/slack_worker.py index 15dfd0c96..b89fafba4 100644 --- a/server/activity_log/slack_worker.py +++ b/server/activity_log/slack_worker.py @@ -11,7 +11,6 @@ from ..sentry import configure_sentry -# pylint: disable=too-many-return-statements def slack_message(activity: activity_log.Activity): base = activity.base org_link = urljoin(config.HTTP_ORIGIN, f"/support/orgs/{base.organization_id}") diff --git a/server/api/shared.py b/server/api/shared.py index d887e6a17..d95e3a1c1 100644 --- a/server/api/shared.py +++ b/server/api/shared.py @@ -526,15 +526,32 @@ def ballot_vote_deltas( if reported is None: reported = {choice.id: "0" for choice in contest.choices} - deltas = {} - for choice in contest.choices: - reported_vote = ( - 0 if reported[choice.id] in ["o", "u"] else int(reported[choice.id]) - ) - audited_vote = ( - 0 if audited[choice.id] in ["o", "u"] else int(audited[choice.id]) - ) - deltas[choice.id] = reported_vote - audited_vote + # Special case for ES&S overvotes/undervotes. + has_overvote = "o" in reported.values() + has_undervote = "u" in reported.values() + audited_votes = sum(map(int, (audited.values()))) + # If the audited result correctly identified overvote/undervote, return no + # delta. Otherwise, return discrepancies as usual, but substituting in + # overvotes/undervotes. + if has_overvote: + if audited_votes > 1: + return None + else: + deltas = { + choice.id: 1 - int(audited[choice.id]) for choice in contest.choices + } + elif has_undervote: + if audited_votes < 1: + return None + else: + deltas = { + choice.id: 0 - int(audited[choice.id]) for choice in contest.choices + } + else: + deltas = { + choice.id: int(reported[choice.id]) - int(audited[choice.id]) + for choice in contest.choices + } if all(delta == 0 for delta in deltas.values()): return None diff --git a/server/tests/ballot_comparison/snapshots/snap_test_ballot_comparison.py b/server/tests/ballot_comparison/snapshots/snap_test_ballot_comparison.py index 1548d5381..b5ea4b6c5 100644 --- a/server/tests/ballot_comparison/snapshots/snap_test_ballot_comparison.py +++ b/server/tests/ballot_comparison/snapshots/snap_test_ballot_comparison.py @@ -55,8 +55,8 @@ J1,0002,BATCH2,5,0002000175,"Round 1: 0.128937575131137250, 0.240487859312182291",AUDITED,Choice 1-2,Choice 1-2,,,Choice 2-2,Choice 2-2,,\r J2,0001,BATCH1,1,0001013415,Round 1: 0.228946820159681463,AUDITED,"Choice 1-1, INVALID_WRITE_IN",Choice 1-1,,,"Choice 2-1, INVALID_WRITE_IN",Choice 2-1,,\r J2,0001,BATCH1,3,0001013417,Round 1: 0.457121710197159606,AUDITED,Choice 1-1,Choice 1-1,,,Choice 2-1,Choice 2-1,,\r -J2,0001,BATCH2,3,0001000417,Round 1: 0.269793733438455805,AUDITED,"Choice 1-1, Choice 1-2",Overvote,Choice 1-1: -1; Choice 1-2: -1,,"Choice 2-1, Choice 2-3",Overvote,Choice 2-1: -1; Choice 2-3: -1,\r -J2,0002,BATCH1,3,0002003173,Round 1: 0.328294241227374952,AUDITED,Choice 1-2,Overvote,Choice 1-2: -1,1,Choice 2-2,Overvote,Choice 2-2: -1,1\r +J2,0001,BATCH2,3,0001000417,Round 1: 0.269793733438455805,AUDITED,"Choice 1-1, Choice 1-2",Overvote,,,"Choice 2-1, Choice 2-3",Overvote,,\r +J2,0002,BATCH1,3,0002003173,Round 1: 0.328294241227374952,AUDITED,Choice 1-2,Overvote,Choice 1-1: +1,1,Choice 2-2,Overvote,Choice 2-1: +1; Choice 2-3: +1,1\r J2,0002,BATCH2,1,0002000171,Round 1: 0.390715133294243377,AUDITED,Choice 1-1,Choice 1-1,,,Choice 2-3,Choice 2-3,,\r J2,0002,BATCH2,2,0002000172,Round 1: 0.064290634474137509,AUDITED,Choice 1-1,Choice 1-1,,,Choice 2-3,Choice 2-3,,\r J2,0002,BATCH2,5,0002000175,Round 1: 0.212277542626930704,AUDITED,Choice 1-1,Choice 1-1,,,Choice 2-3,Choice 2-3,,\r