Skip to content

Commit

Permalink
Update deprecatedFrom validation and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
IanCa committed Feb 29, 2024
1 parent 869458e commit bbe7cce
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 11 deletions.
5 changes: 4 additions & 1 deletion hed/errors/error_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,10 @@ class SchemaWarnings:
class SchemaAttributeErrors:
SCHEMA_ATTRIBUTE_INVALID = 'SCHEMA_ATTRIBUTE_INVALID'
SCHEMA_ATTRIBUTE_VALUE_INVALID = 'SCHEMA_ATTRIBUTE_VALUE_INVALID'
SCHEMA_DEPRECATION_ERROR = 'SCHEMA_DEPRECATION_ERROR'
SCHEMA_DEPRECATED_INVALID = "SCHEMA_DEPRECATED_INVALID"
SCHEMA_CHILD_OF_DEPRECATED = "SCHEMA_CHILD_OF_DEPRECATED"
SCHEMA_ATTRIBUTE_VALUE_DEPRECATED = "SCHEMA_ATTRIBUTE_VALUE_DEPRECATED"
SCHEMA_SUGGESTED_TAG_INVALID = "SCHEMA_SUGGESTED_TAG_INVALID"

SCHEMA_UNIT_CLASS_INVALID = "SCHEMA_UNIT_CLASS_INVALID"
Expand All @@ -136,7 +139,7 @@ class SchemaAttributeErrors:
SCHEMA_IN_LIBRARY_INVALID = "SCHEMA_IN_LIBRARY_INVALID"

SCHEMA_DEFAULT_UNITS_INVALID = "SCHEMA_DEFAULT_UNITS_INVALID"
SCHEMA_CHILD_OF_DEPRECATED = "SCHEMA_CHILD_OF_DEPRECATED"
SCHEMA_DEFAULT_UNITS_DEPRECATED = "SCHEMA_DEFAULT_UNITS_DEPRECATED"
SCHEMA_CONVERSION_FACTOR_NOT_POSITIVE = "SCHEMA_CONVERSION_FACTOR_NOT_POSITIVE"


Expand Down
17 changes: 15 additions & 2 deletions hed/errors/schema_error_messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,24 @@ def schema_warning_non_placeholder_class(tag_name, invalid_attribute_name):


@hed_error(SchemaAttributeErrors.SCHEMA_DEPRECATED_INVALID,
actual_code=SchemaAttributeErrors.SCHEMA_ATTRIBUTE_VALUE_INVALID)
actual_code=SchemaAttributeErrors.SCHEMA_DEPRECATION_ERROR)
def schema_error_SCHEMA_DEPRECATED_INVALID(tag_name, invalid_deprecated_version):
return f"'{tag_name}' has invalid or unknown value in attribute deprecatedFrom: '{invalid_deprecated_version}'."


@hed_error(SchemaAttributeErrors.SCHEMA_CHILD_OF_DEPRECATED,
actual_code=SchemaAttributeErrors.SCHEMA_ATTRIBUTE_VALUE_INVALID)
actual_code=SchemaAttributeErrors.SCHEMA_DEPRECATION_ERROR)
def schema_error_SCHEMA_CHILD_OF_DEPRECATED(deprecated_tag, non_deprecated_child):
return f"Deprecated tag '{deprecated_tag}' has a child that is not deprecated: '{non_deprecated_child}'."


@hed_error(SchemaAttributeErrors.SCHEMA_ATTRIBUTE_VALUE_DEPRECATED,
actual_code=SchemaAttributeErrors.SCHEMA_DEPRECATION_ERROR)
def schema_error_SCHEMA_ATTRIBUTE_VALUE_DEPRECATED(tag, deprecated_suggestion, attribute_name):
return (f"Tag '{tag}' {attribute_name} uses '{deprecated_suggestion}' which has been deprecated "
f"and an alternative method of tagging should be used.")


@hed_error(SchemaAttributeErrors.SCHEMA_SUGGESTED_TAG_INVALID,
actual_code=SchemaAttributeErrors.SCHEMA_ATTRIBUTE_VALUE_INVALID)
def schema_error_SCHEMA_SUGGESTED_TAG_INVALID(suggestedTag, invalidSuggestedTag, attribute_name):
Expand All @@ -85,6 +92,12 @@ def schema_error_SCHEMA_DEFAULT_UNITS_INVALID(tag, bad_unit, valid_units):
return f"Tag '{tag}' has an invalid defaultUnit '{bad_unit}'. Valid units are: '{valid_units}'."


@hed_error(SchemaAttributeErrors.SCHEMA_DEFAULT_UNITS_DEPRECATED,
actual_code=SchemaAttributeErrors.SCHEMA_DEPRECATION_ERROR)
def schema_error_SCHEMA_DEFAULT_UNITS_DEPRECATED(unit_class, bad_unit):
return f"Unit class '{unit_class}' defaultUnit '{bad_unit}' is deprecated. Please find an alternative default."


@hed_error(SchemaAttributeErrors.SCHEMA_CONVERSION_FACTOR_NOT_POSITIVE,
actual_code=SchemaAttributeErrors.SCHEMA_ATTRIBUTE_VALUE_INVALID)
def schema_error_SCHEMA_CONVERSION_FACTOR_NOT_POSITIVE(tag, conversion_factor):
Expand Down
72 changes: 65 additions & 7 deletions hed/schema/schema_attribute_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from hed.errors.error_types import SchemaWarnings, ValidationErrors, SchemaAttributeErrors
from hed.errors.error_reporter import ErrorHandler
from hed.schema.hed_cache import get_hed_versions
from hed.schema.hed_schema_constants import HedKey, character_types
from hed.schema.hed_schema_constants import HedKey, character_types, HedSectionKey
from hed.schema.schema_validation_util import schema_version_for_library
from semantic_version import Version

Expand All @@ -39,6 +39,36 @@ def tag_is_placeholder_check(hed_schema, tag_entry, attribute_name):
return issues


def attribute_is_deprecated(hed_schema, tag_entry, attribute_name):
""" Check if the attribute is deprecated.
does not check value.
Parameters:
hed_schema (HedSchema): The schema to use for validation
tag_entry (HedSchemaEntry): The schema entry for this tag.
attribute_name (str): The name of this attribute
Returns:
list: A list of issues. Each issue is a dictionary.
"""
issues = []
# Attributes has to check properties
section_key = HedSectionKey.Attributes
if tag_entry.section_key == HedSectionKey.Attributes:
section_key = HedSectionKey.Properties

attribute_entry = hed_schema.get_tag_entry(attribute_name, section_key)
if (attribute_entry and attribute_entry.has_attribute(HedKey.DeprecatedFrom)
and not tag_entry.has_attribute(HedKey.DeprecatedFrom)):
issues += ErrorHandler.format_error(SchemaAttributeErrors.SCHEMA_ATTRIBUTE_VALUE_DEPRECATED,
tag_entry.name,
attribute_entry.name,
attribute_name)

return issues


# todo: This needs to be refactored, these next several functions are near identical
def tag_exists_check(hed_schema, tag_entry, attribute_name):
""" Check if the list of possible tags exists in the schema.
Expand All @@ -56,11 +86,18 @@ def tag_exists_check(hed_schema, tag_entry, attribute_name):
possible_tags = tag_entry.attributes.get(attribute_name, "")
split_tags = possible_tags.split(",")
for org_tag in split_tags:
if org_tag and org_tag not in hed_schema.tags:
org_entry = hed_schema.tags.get(org_tag)
if org_tag and not org_entry:
issues += ErrorHandler.format_error(SchemaAttributeErrors.SCHEMA_SUGGESTED_TAG_INVALID,
tag_entry.name,
org_tag,
attribute_name)
elif (org_entry and org_entry.has_attribute(HedKey.DeprecatedFrom)
and not tag_entry.has_attribute(HedKey.DeprecatedFrom)):
issues += ErrorHandler.format_error(SchemaAttributeErrors.SCHEMA_ATTRIBUTE_VALUE_DEPRECATED,
tag_entry.name,
org_tag,
attribute_name)

return issues

Expand All @@ -70,11 +107,18 @@ def unit_class_exists(hed_schema, tag_entry, attribute_name):
possible_unit_classes = tag_entry.attributes.get(attribute_name, "")
split_tags = possible_unit_classes.split(",")
for org_tag in split_tags:
if org_tag and org_tag not in hed_schema.unit_classes:
unit_class_entry = hed_schema.unit_classes.get(org_tag)
if org_tag and not unit_class_entry:
issues += ErrorHandler.format_error(SchemaAttributeErrors.SCHEMA_UNIT_CLASS_INVALID,
tag_entry.name,
org_tag,
attribute_name)
elif (unit_class_entry and unit_class_entry.has_attribute(HedKey.DeprecatedFrom)
and not tag_entry.has_attribute(HedKey.DeprecatedFrom)):
issues += ErrorHandler.format_error(SchemaAttributeErrors.SCHEMA_ATTRIBUTE_VALUE_DEPRECATED,
tag_entry.name,
org_tag,
attribute_name)

return issues

Expand All @@ -83,24 +127,38 @@ def value_class_exists(hed_schema, tag_entry, attribute_name):
issues = []
possible_value_classes = tag_entry.attributes.get(attribute_name, "")
split_tags = possible_value_classes.split(",")

for org_tag in split_tags:
if org_tag and org_tag not in hed_schema.value_classes:
value_class_entry = hed_schema.value_classes.get(org_tag)
if org_tag and not value_class_entry:
issues += ErrorHandler.format_error(SchemaAttributeErrors.SCHEMA_VALUE_CLASS_INVALID,
tag_entry.name,
org_tag,
attribute_name)
elif (value_class_entry and value_class_entry.has_attribute(HedKey.DeprecatedFrom)
and not tag_entry.has_attribute(HedKey.DeprecatedFrom)):
issues += ErrorHandler.format_error(SchemaAttributeErrors.SCHEMA_ATTRIBUTE_VALUE_DEPRECATED,
tag_entry.name,
org_tag,
attribute_name)

return issues


def unit_exists(hed_schema, tag_entry, attribute_name):
issues = []
default_unit = tag_entry.attributes.get(attribute_name, "")
if default_unit and default_unit not in tag_entry.derivative_units:
unit = tag_entry.attributes.get(attribute_name, "")
unit_entry = tag_entry.derivative_units.get(unit)
if unit and not unit_entry:
issues += ErrorHandler.format_error(SchemaAttributeErrors.SCHEMA_DEFAULT_UNITS_INVALID,
tag_entry.name,
default_unit,
unit,
tag_entry.units)
elif (unit_entry and unit_entry.has_attribute(HedKey.DeprecatedFrom)
and not tag_entry.has_attribute(HedKey.DeprecatedFrom)):
issues += ErrorHandler.format_error(SchemaAttributeErrors.SCHEMA_DEFAULT_UNITS_DEPRECATED,
tag_entry.name,
unit_entry.name)

return issues

Expand Down
4 changes: 3 additions & 1 deletion hed/schema/schema_compliance.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ def check_attributes(self):
for tag_entry in self.hed_schema[section_key].values():
self.error_handler.push_error_context(ErrorContext.SCHEMA_TAG, tag_entry.name)
for attribute_name in tag_entry.attributes:
validators = self.attribute_validators.get(attribute_name, [])
# Always check deprecated
validators = self.attribute_validators.get(attribute_name, []) \
+ [schema_attribute_validators.attribute_is_deprecated]
for validator in validators:
self.error_handler.push_error_context(ErrorContext.SCHEMA_ATTRIBUTE, attribute_name)
new_issues = validator(self.hed_schema, tag_entry, attribute_name)
Expand Down

0 comments on commit bbe7cce

Please sign in to comment.