civics-cdf-validator 1.61.dev5__tar.gz → 1.61.dev6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {civics_cdf_validator-1.61.dev5/civics_cdf_validator.egg-info → civics_cdf_validator-1.61.dev6}/PKG-INFO +1 -1
- {civics_cdf_validator-1.61.dev5 → civics_cdf_validator-1.61.dev6/civics_cdf_validator.egg-info}/PKG-INFO +1 -1
- {civics_cdf_validator-1.61.dev5 → civics_cdf_validator-1.61.dev6}/rules.py +45 -0
- {civics_cdf_validator-1.61.dev5 → civics_cdf_validator-1.61.dev6}/version.py +1 -1
- {civics_cdf_validator-1.61.dev5 → civics_cdf_validator-1.61.dev6}/CONTRIBUTING.md +0 -0
- {civics_cdf_validator-1.61.dev5 → civics_cdf_validator-1.61.dev6}/LICENSE-2.0.txt +0 -0
- {civics_cdf_validator-1.61.dev5 → civics_cdf_validator-1.61.dev6}/MANIFEST.in +0 -0
- {civics_cdf_validator-1.61.dev5 → civics_cdf_validator-1.61.dev6}/README.md +0 -0
- {civics_cdf_validator-1.61.dev5 → civics_cdf_validator-1.61.dev6}/__init__.py +0 -0
- {civics_cdf_validator-1.61.dev5 → civics_cdf_validator-1.61.dev6}/base.py +0 -0
- {civics_cdf_validator-1.61.dev5 → civics_cdf_validator-1.61.dev6}/civics_cdf_validator.egg-info/SOURCES.txt +0 -0
- {civics_cdf_validator-1.61.dev5 → civics_cdf_validator-1.61.dev6}/civics_cdf_validator.egg-info/dependency_links.txt +0 -0
- {civics_cdf_validator-1.61.dev5 → civics_cdf_validator-1.61.dev6}/civics_cdf_validator.egg-info/entry_points.txt +0 -0
- {civics_cdf_validator-1.61.dev5 → civics_cdf_validator-1.61.dev6}/civics_cdf_validator.egg-info/requires.txt +0 -0
- {civics_cdf_validator-1.61.dev5 → civics_cdf_validator-1.61.dev6}/civics_cdf_validator.egg-info/top_level.txt +0 -0
- {civics_cdf_validator-1.61.dev5 → civics_cdf_validator-1.61.dev6}/gpunit_rules.py +0 -0
- {civics_cdf_validator-1.61.dev5 → civics_cdf_validator-1.61.dev6}/loggers.py +0 -0
- {civics_cdf_validator-1.61.dev5 → civics_cdf_validator-1.61.dev6}/office_utils.py +0 -0
- {civics_cdf_validator-1.61.dev5 → civics_cdf_validator-1.61.dev6}/setup.cfg +0 -0
- {civics_cdf_validator-1.61.dev5 → civics_cdf_validator-1.61.dev6}/setup.py +0 -0
- {civics_cdf_validator-1.61.dev5 → civics_cdf_validator-1.61.dev6}/stats.py +0 -0
- {civics_cdf_validator-1.61.dev5 → civics_cdf_validator-1.61.dev6}/validator.py +0 -0
|
@@ -1631,6 +1631,50 @@ class DuplicateContestNames(base.BaseRule):
|
|
|
1631
1631
|
raise loggers.ElectionError(error_log)
|
|
1632
1632
|
|
|
1633
1633
|
|
|
1634
|
+
class DuplicateBallotTitleSeatPair(base.BaseRule):
|
|
1635
|
+
"""Checks that each English (BallotTitle, Seat) combination is unique.
|
|
1636
|
+
|
|
1637
|
+
Adds Warning/Error if duplicate English (BallotTitle, Seat) combinations are
|
|
1638
|
+
found.
|
|
1639
|
+
"""
|
|
1640
|
+
|
|
1641
|
+
def elements(self):
|
|
1642
|
+
return ["ContestCollection"]
|
|
1643
|
+
|
|
1644
|
+
def check(self, element):
|
|
1645
|
+
error_log = []
|
|
1646
|
+
contest_elements = element.findall("Contest")
|
|
1647
|
+
contests_by_title_and_seat = collections.defaultdict(list)
|
|
1648
|
+
|
|
1649
|
+
for contest in contest_elements:
|
|
1650
|
+
ballot_title_element = get_language_to_text_map(
|
|
1651
|
+
contest.find("BallotTitle")
|
|
1652
|
+
)
|
|
1653
|
+
english_title = ballot_title_element.get("en")
|
|
1654
|
+
seat_element = contest.find("Seat")
|
|
1655
|
+
|
|
1656
|
+
ballot_title = english_title[0].strip() if english_title else ""
|
|
1657
|
+
seat = seat_element.text.strip() if element_has_text(seat_element) else ""
|
|
1658
|
+
|
|
1659
|
+
if not ballot_title:
|
|
1660
|
+
continue
|
|
1661
|
+
|
|
1662
|
+
ballot_title_and_seat = (ballot_title, seat)
|
|
1663
|
+
contests_by_title_and_seat[ballot_title_and_seat].append(contest)
|
|
1664
|
+
|
|
1665
|
+
for ballot_title_and_seat, contests in contests_by_title_and_seat.items():
|
|
1666
|
+
if len(contests) > 1:
|
|
1667
|
+
ballot_title, seat = ballot_title_and_seat
|
|
1668
|
+
error_message = (
|
|
1669
|
+
"Multiple Contests found with the same BallotTitle"
|
|
1670
|
+
f" ('{ballot_title}') and Seat ('{seat}')."
|
|
1671
|
+
)
|
|
1672
|
+
error_log.append(loggers.LogEntry(error_message, contests))
|
|
1673
|
+
|
|
1674
|
+
if error_log:
|
|
1675
|
+
raise loggers.ElectionError(error_log)
|
|
1676
|
+
|
|
1677
|
+
|
|
1634
1678
|
class UniqueStableID(base.TreeRule):
|
|
1635
1679
|
"""Check that every stableID is unique.
|
|
1636
1680
|
|
|
@@ -5538,6 +5582,7 @@ ELECTION_RULES = COMMON_RULES + (
|
|
|
5538
5582
|
ContestStartDateContainsCorrespondingEndDate,
|
|
5539
5583
|
CorrectCandidateSelectionCount,
|
|
5540
5584
|
DateStatusMatches,
|
|
5585
|
+
DuplicateBallotTitleSeatPair,
|
|
5541
5586
|
DuplicateContestNames,
|
|
5542
5587
|
DuplicatedPartyAbbreviation,
|
|
5543
5588
|
DuplicatedPartyName,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|