Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update deprecatedFrom validation and tests #877

Merged
merged 1 commit into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading