civics-cdf-validator 1.52.dev5__tar.gz → 1.52.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.
Files changed (22) hide show
  1. {civics_cdf_validator-1.52.dev5/civics_cdf_validator.egg-info → civics_cdf_validator-1.52.dev6}/PKG-INFO +1 -1
  2. {civics_cdf_validator-1.52.dev5 → civics_cdf_validator-1.52.dev6/civics_cdf_validator.egg-info}/PKG-INFO +1 -1
  3. {civics_cdf_validator-1.52.dev5 → civics_cdf_validator-1.52.dev6}/rules.py +45 -19
  4. {civics_cdf_validator-1.52.dev5 → civics_cdf_validator-1.52.dev6}/version.py +1 -1
  5. {civics_cdf_validator-1.52.dev5 → civics_cdf_validator-1.52.dev6}/CONTRIBUTING.md +0 -0
  6. {civics_cdf_validator-1.52.dev5 → civics_cdf_validator-1.52.dev6}/LICENSE-2.0.txt +0 -0
  7. {civics_cdf_validator-1.52.dev5 → civics_cdf_validator-1.52.dev6}/MANIFEST.in +0 -0
  8. {civics_cdf_validator-1.52.dev5 → civics_cdf_validator-1.52.dev6}/README.md +0 -0
  9. {civics_cdf_validator-1.52.dev5 → civics_cdf_validator-1.52.dev6}/__init__.py +0 -0
  10. {civics_cdf_validator-1.52.dev5 → civics_cdf_validator-1.52.dev6}/base.py +0 -0
  11. {civics_cdf_validator-1.52.dev5 → civics_cdf_validator-1.52.dev6}/civics_cdf_validator.egg-info/SOURCES.txt +0 -0
  12. {civics_cdf_validator-1.52.dev5 → civics_cdf_validator-1.52.dev6}/civics_cdf_validator.egg-info/dependency_links.txt +0 -0
  13. {civics_cdf_validator-1.52.dev5 → civics_cdf_validator-1.52.dev6}/civics_cdf_validator.egg-info/entry_points.txt +0 -0
  14. {civics_cdf_validator-1.52.dev5 → civics_cdf_validator-1.52.dev6}/civics_cdf_validator.egg-info/requires.txt +0 -0
  15. {civics_cdf_validator-1.52.dev5 → civics_cdf_validator-1.52.dev6}/civics_cdf_validator.egg-info/top_level.txt +0 -0
  16. {civics_cdf_validator-1.52.dev5 → civics_cdf_validator-1.52.dev6}/gpunit_rules.py +0 -0
  17. {civics_cdf_validator-1.52.dev5 → civics_cdf_validator-1.52.dev6}/loggers.py +0 -0
  18. {civics_cdf_validator-1.52.dev5 → civics_cdf_validator-1.52.dev6}/office_utils.py +0 -0
  19. {civics_cdf_validator-1.52.dev5 → civics_cdf_validator-1.52.dev6}/setup.cfg +0 -0
  20. {civics_cdf_validator-1.52.dev5 → civics_cdf_validator-1.52.dev6}/setup.py +0 -0
  21. {civics_cdf_validator-1.52.dev5 → civics_cdf_validator-1.52.dev6}/stats.py +0 -0
  22. {civics_cdf_validator-1.52.dev5 → civics_cdf_validator-1.52.dev6}/validator.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: civics_cdf_validator
3
- Version: 1.52.dev5
3
+ Version: 1.52.dev6
4
4
  Summary: Checks if an election feed follows best practices
5
5
  Home-page: https://github.com/google/civics_cdf_validator
6
6
  Author: Google Civics
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: civics_cdf_validator
3
- Version: 1.52.dev5
3
+ Version: 1.52.dev6
4
4
  Summary: Checks if an election feed follows best practices
5
5
  Home-page: https://github.com/google/civics_cdf_validator
6
6
  Author: Google Civics
@@ -118,9 +118,29 @@ def _has_government_body(element):
118
118
  return bool(governmental_body or government_body)
119
119
 
120
120
 
121
- def get_external_id_values(element, value_type, return_elements=False):
122
- """Helper to gather all Values of external ids for a given type."""
123
- external_ids = element.findall(".//ExternalIdentifier")
121
+ def get_external_id_values(
122
+ element, value_type, return_elements=False, search_subelements=True
123
+ ):
124
+ """Helper to gather all Values of external ids for a given type.
125
+
126
+ If search_subelements is True, will search all subelements, if False, will
127
+ only search child elements.
128
+
129
+ Args:
130
+ element: element to be processed
131
+ value_type: external id value type
132
+ return_elements: Boolean if True return elements, if False return values.
133
+ search_subelements: Boolean to instruct the function to recursively search
134
+ subelements.
135
+
136
+ Returns:
137
+ A list of external id values or external identifier elements
138
+ """
139
+ external_ids = []
140
+ if search_subelements:
141
+ external_ids = element.findall(".//ExternalIdentifier")
142
+ else:
143
+ external_ids = element.findall("ExternalIdentifiers/ExternalIdentifier")
124
144
  values = []
125
145
  for extern_id in external_ids:
126
146
  id_type = extern_id.find("Type")
@@ -1608,26 +1628,23 @@ class UniqueStableID(base.TreeRule):
1608
1628
  Add an error message if stable id is not unique
1609
1629
  """
1610
1630
 
1611
- _TOP_LEVEL_ENTITIES = frozenset(
1612
- ["Party", "GpUnit", "Office", "Person", "Candidate", "Contest"]
1613
- )
1614
-
1615
1631
  def check(self):
1616
1632
  error_log = []
1617
1633
  stable_obj_dict = dict()
1618
1634
  for _, element in etree.iterwalk(self.election_tree, events=("end",)):
1619
- if "Election" not in element.tag:
1620
- if element.tag in self._TOP_LEVEL_ENTITIES:
1621
- if "objectId" in element.attrib:
1622
- object_id = element.get("objectId")
1623
- stable_ids = get_external_id_values(element, "stable")
1624
- for stable_id in stable_ids:
1625
- if stable_id in stable_obj_dict.keys():
1626
- stable_obj_dict.get(stable_id).append(object_id)
1627
- else:
1628
- object_id_list = []
1629
- object_id_list.append(object_id)
1630
- stable_obj_dict[stable_id] = object_id_list
1635
+ stable_ids = get_external_id_values(
1636
+ element, "stable", search_subelements=False
1637
+ )
1638
+ if not stable_ids:
1639
+ continue
1640
+ elem_id = self._get_object_id_or_name(element)
1641
+ for stable_id in stable_ids:
1642
+ if stable_id in stable_obj_dict.keys():
1643
+ stable_obj_dict.get(stable_id).append(elem_id)
1644
+ else:
1645
+ elem_id_list = []
1646
+ elem_id_list.append(elem_id)
1647
+ stable_obj_dict[stable_id] = elem_id_list
1631
1648
  for k, v in stable_obj_dict.items():
1632
1649
  if len(v) > 1:
1633
1650
  error_message = (
@@ -1637,6 +1654,15 @@ class UniqueStableID(base.TreeRule):
1637
1654
  if error_log:
1638
1655
  raise loggers.ElectionError(error_log)
1639
1656
 
1657
+ def _get_object_id_or_name(self, element):
1658
+ if "objectId" in element.attrib:
1659
+ return element.get("objectId")
1660
+ names_by_language = get_language_to_text_map(element.find("Name"))
1661
+ if "en" in names_by_language:
1662
+ return names_by_language["en"][0]
1663
+ for names in names_by_language.values():
1664
+ return names[0]
1665
+
1640
1666
 
1641
1667
  class MissingStableIds(base.BaseRule):
1642
1668
  """Check that each NIST object in the feed have a stable Id.
@@ -5,4 +5,4 @@ No dependencies should be added to this module.
5
5
  See https://packaging.python.org/guides/single-sourcing-package-version/
6
6
  """
7
7
 
8
- __version__ = '1.52.dev5'
8
+ __version__ = '1.52.dev6'