civics-cdf-validator 1.57.dev8__tar.gz → 1.57.dev10__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.57.dev8/civics_cdf_validator.egg-info → civics_cdf_validator-1.57.dev10}/PKG-INFO +1 -1
  2. {civics_cdf_validator-1.57.dev8 → civics_cdf_validator-1.57.dev10}/base.py +16 -0
  3. {civics_cdf_validator-1.57.dev8 → civics_cdf_validator-1.57.dev10/civics_cdf_validator.egg-info}/PKG-INFO +1 -1
  4. {civics_cdf_validator-1.57.dev8 → civics_cdf_validator-1.57.dev10}/rules.py +9 -56
  5. {civics_cdf_validator-1.57.dev8 → civics_cdf_validator-1.57.dev10}/version.py +1 -1
  6. {civics_cdf_validator-1.57.dev8 → civics_cdf_validator-1.57.dev10}/CONTRIBUTING.md +0 -0
  7. {civics_cdf_validator-1.57.dev8 → civics_cdf_validator-1.57.dev10}/LICENSE-2.0.txt +0 -0
  8. {civics_cdf_validator-1.57.dev8 → civics_cdf_validator-1.57.dev10}/MANIFEST.in +0 -0
  9. {civics_cdf_validator-1.57.dev8 → civics_cdf_validator-1.57.dev10}/README.md +0 -0
  10. {civics_cdf_validator-1.57.dev8 → civics_cdf_validator-1.57.dev10}/__init__.py +0 -0
  11. {civics_cdf_validator-1.57.dev8 → civics_cdf_validator-1.57.dev10}/civics_cdf_validator.egg-info/SOURCES.txt +0 -0
  12. {civics_cdf_validator-1.57.dev8 → civics_cdf_validator-1.57.dev10}/civics_cdf_validator.egg-info/dependency_links.txt +0 -0
  13. {civics_cdf_validator-1.57.dev8 → civics_cdf_validator-1.57.dev10}/civics_cdf_validator.egg-info/entry_points.txt +0 -0
  14. {civics_cdf_validator-1.57.dev8 → civics_cdf_validator-1.57.dev10}/civics_cdf_validator.egg-info/requires.txt +0 -0
  15. {civics_cdf_validator-1.57.dev8 → civics_cdf_validator-1.57.dev10}/civics_cdf_validator.egg-info/top_level.txt +0 -0
  16. {civics_cdf_validator-1.57.dev8 → civics_cdf_validator-1.57.dev10}/gpunit_rules.py +0 -0
  17. {civics_cdf_validator-1.57.dev8 → civics_cdf_validator-1.57.dev10}/loggers.py +0 -0
  18. {civics_cdf_validator-1.57.dev8 → civics_cdf_validator-1.57.dev10}/office_utils.py +0 -0
  19. {civics_cdf_validator-1.57.dev8 → civics_cdf_validator-1.57.dev10}/setup.cfg +0 -0
  20. {civics_cdf_validator-1.57.dev8 → civics_cdf_validator-1.57.dev10}/setup.py +0 -0
  21. {civics_cdf_validator-1.57.dev8 → civics_cdf_validator-1.57.dev10}/stats.py +0 -0
  22. {civics_cdf_validator-1.57.dev8 → civics_cdf_validator-1.57.dev10}/validator.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: civics_cdf_validator
3
- Version: 1.57.dev8
3
+ Version: 1.57.dev10
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
@@ -16,6 +16,7 @@ limitations under the License.
16
16
 
17
17
  from __future__ import print_function
18
18
 
19
+ from collections.abc import Set
19
20
  import datetime
20
21
  import functools
21
22
  import re
@@ -93,6 +94,21 @@ class BaseRule(SchemaHandler):
93
94
  def setup(self):
94
95
  """Perform any rule specific setup before checking."""
95
96
 
97
+ def get_element_names_for_types(self, element_types: Set[str]) -> set[str]:
98
+ element_names = set()
99
+ for _, element in etree.iterwalk(self.schema_tree):
100
+ tag = self.strip_schema_ns(element)
101
+ if (
102
+ tag == "element"
103
+ and element.get("type") in element_types
104
+ and element.get("name") is not None
105
+ ):
106
+ element_names.add(element.get("name"))
107
+ return element_names
108
+
109
+ def get_element_names_for_type(self, element_type: str) -> set[str]:
110
+ return self.get_element_names_for_types({element_type})
111
+
96
112
 
97
113
  class TreeRule(BaseRule):
98
114
  """Rule that checks entire tree."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: civics_cdf_validator
3
- Version: 1.57.dev8
3
+ Version: 1.57.dev10
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
@@ -34,6 +34,7 @@ from six.moves.urllib.parse import urlparse
34
34
 
35
35
  _PARTY_LEADERSHIP_TYPES = ["party-leader-id", "party-chair-id"]
36
36
  _INDEPENDENT_PARTY_NAMES = frozenset(["independent", "nonpartisan"])
37
+ _IDREF_TYPES = frozenset(["xs:IDREF", "xs:IDREFS"])
37
38
  # The set of external identifiers that contain references to other entities.
38
39
  _IDREF_EXTERNAL_IDENTIFIERS = frozenset(
39
40
  ["jurisdiction-id"] + _PARTY_LEADERSHIP_TYPES
@@ -49,7 +50,7 @@ _CONTEST_STAGE_TYPES = frozenset([
49
50
  "official",
50
51
  "unnamed",
51
52
  ])
52
- _INTERNATIONALIZED_TEXT_ELEMENTS = [
53
+ _INTERNATIONALIZED_TEXT_ELEMENTS_WITH_ONLY_ONE_TEXT_PER_LANGUAGE = [
53
54
  # go/keep-sorted start
54
55
  "BallotName",
55
56
  "BallotSubTitle",
@@ -441,9 +442,7 @@ class EmptyText(base.BaseRule):
441
442
  return ["Text"]
442
443
 
443
444
  def check(self, element):
444
- if (element.text is None or not element.text.strip()) or (
445
- element.text is None and element.get("language") is not None
446
- ):
445
+ if element.text is None or not element.text.strip():
447
446
  raise loggers.ElectionError.from_message("Text is empty", element)
448
447
 
449
448
 
@@ -451,18 +450,7 @@ class EmptyString(base.BaseRule):
451
450
  """Check that string fields are not empty or strictly whitespace."""
452
451
 
453
452
  def elements(self):
454
- """Returns all elements of type xs:string from the schema."""
455
- string_elements = []
456
- for _, element in etree.iterwalk(self.schema_tree):
457
- tag = self.strip_schema_ns(element)
458
- if (
459
- tag
460
- and tag == "element"
461
- and element.get("type") == "xs:string"
462
- and element.get("name") is not None
463
- ):
464
- string_elements.append(element.get("name"))
465
- return string_elements
453
+ return list(self.get_element_names_for_type("xs:string"))
466
454
 
467
455
  # pylint: disable=g-explicit-length-test
468
456
  def check(self, element):
@@ -961,15 +949,7 @@ class UniqueLabel(base.BaseRule):
961
949
  self.labels = set()
962
950
 
963
951
  def elements(self):
964
- eligible_elements = []
965
- for _, element in etree.iterwalk(self.schema_tree):
966
- tag = self.strip_schema_ns(element)
967
- if tag == "element":
968
- elem_type = element.get("type")
969
- if elem_type == "InternationalizedText":
970
- if element.get("name") not in eligible_elements:
971
- eligible_elements.append(element.get("name"))
972
- return eligible_elements
952
+ return list(self.get_element_names_for_type("InternationalizedText"))
973
953
 
974
954
  def check(self, element):
975
955
  element_label = element.get("label")
@@ -3939,7 +3919,7 @@ class MultipleInternationalizedTextWithSameLanguageCode(base.BaseRule):
3939
3919
  """Checks for multiple InternationalizedText with the same language code."""
3940
3920
 
3941
3921
  def elements(self):
3942
- return _INTERNATIONALIZED_TEXT_ELEMENTS
3922
+ return _INTERNATIONALIZED_TEXT_ELEMENTS_WITH_ONLY_ONE_TEXT_PER_LANGUAGE
3943
3923
 
3944
3924
  def check(self, element):
3945
3925
  language_map = get_language_to_text_map(element)
@@ -3952,22 +3932,10 @@ class MultipleInternationalizedTextWithSameLanguageCode(base.BaseRule):
3952
3932
 
3953
3933
 
3954
3934
  class AllInternationalizedTextHaveEnVersion(base.BaseRule):
3955
- """Checks for Internationalized Text Elements missing the english version."""
3935
+ """Checks for InternationalizedText elements missing an English version."""
3956
3936
 
3957
3937
  def elements(self):
3958
- return [
3959
- "BallotName",
3960
- "Directions",
3961
- "BallotSubTitle",
3962
- "BallotTitle",
3963
- "Name",
3964
- "InternationalizedName",
3965
- "InternationalizedAbbreviation",
3966
- "Alias",
3967
- "FullName",
3968
- "Profession",
3969
- "Title",
3970
- ]
3938
+ return list(self.get_element_names_for_type("InternationalizedText"))
3971
3939
 
3972
3940
  def check(self, element):
3973
3941
  language_map = get_language_to_text_map(element)
@@ -4518,29 +4486,14 @@ class UnreferencedEntitiesBase(base.TreeRule):
4518
4486
  self.top_level_entity_types = top_level_entity_types
4519
4487
  self.warned_entity_types = warned_entity_types
4520
4488
 
4521
- def _get_idref_elements(self):
4522
- """Returns the names of all XML elements in the schema of type IDREF or IDREFS."""
4523
-
4524
- idref_elements = set()
4525
- for _, element in etree.iterwalk(self.schema_tree):
4526
- tag = self.strip_schema_ns(element)
4527
- if (
4528
- tag
4529
- and tag == "element"
4530
- and element.get("type") in ("xs:IDREF", "xs:IDREFS")
4531
- ):
4532
- idref_elements.add(element.get("name"))
4533
- return idref_elements
4534
-
4535
4489
  def _gather_referenced_entities(self):
4536
4490
  """Create a set of all entities referenced by either IDREF(S) elements or external identifiers."""
4537
-
4538
- idref_elements = self._get_idref_elements()
4539
4491
  referenced_entities = set()
4540
4492
  for external_id_type in _IDREF_EXTERNAL_IDENTIFIERS:
4541
4493
  referenced_entities.update(
4542
4494
  get_external_id_values(self.election_tree, external_id_type)
4543
4495
  )
4496
+ idref_elements = self.get_element_names_for_types(_IDREF_TYPES)
4544
4497
  for _, element in etree.iterwalk(self.election_tree):
4545
4498
  tag = self.strip_schema_ns(element)
4546
4499
  if tag and tag in idref_elements:
@@ -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.57.dev8'
8
+ __version__ = '1.57.dev10'