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

deprecated: deprecate isSequenceOf (DEV-3525) #920

Merged
merged 22 commits into from
Apr 24, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
{"type": "fix", "section": "Bug Fixes", "hidden": false },
{"type": "chore", "section": "Maintenance", "hidden": false },
{"type": "refactor", "section": "Maintenance", "hidden": false },
{"type": "docs", "section": "Documentation", "hidden": false }
{"type": "docs", "section": "Documentation", "hidden": false },
{"type": "deprecated", "section": "Deprecated", "hidden": false }
]
pull-request-title-pattern: 'chore: release ${version}'
54 changes: 31 additions & 23 deletions docs/file-formats/json-project/ontologies.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,10 +222,10 @@ The following DSP base properties are available:
A resource that has a property derived from `seqnum` must also have a property derived from `isPartOf`.
- `hasColor`: Defines a color value.
- `hasComment`: Defines a standard comment.
- `isSequenceOf`: A special variant of `hasLinkTo`. It says that an instance of the given resource class is a section
of an audio/video resource.
- `hasSequenceBounds`: This base property is used together with `isSequenceOf`. It denotes a time interval of an audio/
video resource.
- `isSequenceOf` **(⚠ deprecated)**: A special variant of `hasLinkTo`.
It says that an instance of the given resource class is a section of an audio/video resource.
- `hasSequenceBounds` **(⚠ deprecated)**: This base property is used together with `isSequenceOf`.
It denotes a time interval of an audio/video resource.



Expand All @@ -250,25 +250,25 @@ These three are related as follows:

#### Overview

| DSP base property (`super`) | `object` | `gui_element` |
| --------------------------- | ------------------------------------------------------------------ | -------------------------------------- |
| hasValue | BooleanValue | Checkbox |
| hasColor | ColorValue | Colorpicker |
| hasValue | DateValue | Date |
| hasValue | DecimalValue | Spinbox, <br>SimpleText |
| hasValue | GeonameValue | Geonames |
| hasValue | IntValue | Spinbox, <br>SimpleText |
| hasValue | ListValue | List |
| hasValue | TextValue | SimpleText, <br>Textarea, <br>Richtext |
| hasComment | TextValue | Richtext |
| hasValue | TimeValue | TimeStamp |
| hasValue | UriValue | SimpleText |
| hasLinkTo | (resourceclass) | Searchbox |
| hasRepresentation | Representation | Searchbox |
| isPartOf | (resourceclass) | Searchbox |
| seqnum | IntValue | Spinbox, <br>SimpleText |
| isSequenceOf | (AudioRepresentation, <br>MovingImageRepresentation, <br>subclass) | Searchbox |
| hasSequenceBounds | IntervalValue | Interval |
| DSP base property (`super`) | `object` | `gui_element` |
| ------------------------------------- | ------------------------------------------------------------------ | -------------------------------------- |
| hasValue | BooleanValue | Checkbox |
| hasColor | ColorValue | Colorpicker |
| hasValue | DateValue | Date |
| hasValue | DecimalValue | Spinbox, <br>SimpleText |
| hasValue | GeonameValue | Geonames |
| hasValue | IntValue | Spinbox, <br>SimpleText |
| hasValue | ListValue | List |
| hasValue | TextValue | SimpleText, <br>Textarea, <br>Richtext |
| hasComment | TextValue | Richtext |
| hasValue | TimeValue | TimeStamp |
| hasValue | UriValue | SimpleText |
| hasLinkTo | (resourceclass) | Searchbox |
| hasRepresentation | Representation | Searchbox |
| isPartOf | (resourceclass) | Searchbox |
| seqnum | IntValue | Spinbox, <br>SimpleText |
| isSequenceOf **(⚠ deprecated)** | (AudioRepresentation, <br>MovingImageRepresentation, <br>subclass) | Searchbox |
| hasSequenceBounds **(⚠ deprecated)** | IntervalValue | Interval |


#### `BooleanValue`
Expand Down Expand Up @@ -819,6 +819,10 @@ Example: See the [`isPartOf` Property](#ispartof-property) above.

#### `isSequenceOf` Property

| <center>Deprecated</center> |
| ----------------------------------------------------- |
| This property is deprecated and will be removed soon. |

`"object": <AudioRepresentation/MovingImageRepresentation or a subclass of one of them>`

This property can be used, together with a `hasSequenceBounds` property, on a resource representing a sequence of an
Expand Down Expand Up @@ -892,6 +896,10 @@ Example:

#### `hasSequenceBounds` Property

| <center>Deprecated</center> |
| ----------------------------------------------------- |
| This property is deprecated and will be removed soon. |

`"object": "IntervalValue"`

This property represents a time interval of an audio or video. It can be used together with an `isSequenceOf` property
Expand Down
2 changes: 2 additions & 0 deletions src/dsp_tools/cli/entry_point.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from dsp_tools.models.exceptions import InternalError
from dsp_tools.models.exceptions import UserError
from dsp_tools.utils.logger_config import logger_config
from dsp_tools.utils.warnings_config import initialize_warnings


def main() -> None:
Expand Down Expand Up @@ -58,6 +59,7 @@ def run(args: list[str]) -> None:
)
_check_version()
_log_cli_arguments(parsed_arguments)
initialize_warnings()

try:
parsed_arguments = _derive_sipi_url(
Expand Down
17 changes: 16 additions & 1 deletion src/dsp_tools/commands/excel2json/properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from dsp_tools.commands.excel2json.utils import get_labels
from dsp_tools.commands.excel2json.utils import get_wrong_row_numbers
from dsp_tools.commands.excel2json.utils import read_and_clean_all_sheets
from dsp_tools.models.custom_warnings import DspToolsFutureWarning
from dsp_tools.models.exceptions import InputError

languages = ["en", "de", "fr", "it", "rm"]
Expand Down Expand Up @@ -63,6 +64,8 @@ def excel2properties(

_do_property_excel_compliance(df=property_df, excelfile=excelfile)

_check_for_deprecated_syntax(property_df)

# transform every row into a property
props = [
_row2prop(
Expand All @@ -83,6 +86,19 @@ def excel2properties(
return props, True


def _check_for_deprecated_syntax(df: pd.DataFrame) -> None:
_check_for_deprecated_isSequenceOf(df)
jnussbaum marked this conversation as resolved.
Show resolved Hide resolved


def _check_for_deprecated_isSequenceOf(df: pd.DataFrame) -> None:
if any(x in y for y in list(df["super"]) for x in ["isSequenceOf", "hasSequenceBounds"]):
msg = (
"Deprecation Warning: Your Excel file contains deprecated super-properties. "
"Support for the following super-properties will be removed soon: isSequenceOf, hasSequenceBounds"
)
warnings.warn(DspToolsFutureWarning(msg))


def _read_check_property_df(excelfile: str) -> pd.DataFrame:
sheets_df_dict = read_and_clean_all_sheets(excelfile=excelfile)
if len(sheets_df_dict) != 1:
Expand Down Expand Up @@ -129,7 +145,6 @@ def _rename_deprecated_hlist(df: pd.DataFrame, excelfile: str) -> pd.DataFrame:


def _do_property_excel_compliance(df: pd.DataFrame, excelfile: str) -> None:
# If it does not pass any one of the tests, the function stops
required_columns = {
"name",
"super",
Expand Down
9 changes: 9 additions & 0 deletions src/dsp_tools/commands/excel2xml/excel2xml_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from regex import Match

from dsp_tools.commands.excel2xml.propertyelement import PropertyElement
from dsp_tools.models.custom_warnings import DspToolsFutureWarning
from dsp_tools.models.datetimestamp import DateTimeStamp
from dsp_tools.models.exceptions import BaseError
from dsp_tools.utils.date_util import is_full_date
Expand Down Expand Up @@ -1099,6 +1100,10 @@ def make_interval_prop(
See https://docs.dasch.swiss/latest/DSP-TOOLS/file-formats/xml-data-file/#interval-prop
"""

if name == "hasSequenceBounds":
msg = "Deprecation Warning: Support for the hasSequenceBounds property will be removed soon"
warnings.warn(DspToolsFutureWarning(msg))

# check the input: prepare a list with valid values
values = prepare_value(value)

Expand Down Expand Up @@ -1245,6 +1250,10 @@ def make_resptr_prop(
See https://docs.dasch.swiss/latest/DSP-TOOLS/file-formats/xml-data-file/#resptr-prop
"""

if name == "isSequenceOf":
msg = "Deprecation Warning: Support for the isSequenceOf property will be removed soon"
warnings.warn(DspToolsFutureWarning(msg))

# check the input: prepare a list with valid values
values = prepare_value(value)

Expand Down
34 changes: 34 additions & 0 deletions src/dsp_tools/commands/project/create/project_validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import importlib.resources
import json
import warnings
from pathlib import Path
from typing import Any
from typing import Union
Expand All @@ -13,6 +14,7 @@
import regex

from dsp_tools.commands.excel2json.lists import expand_lists_from_excel
from dsp_tools.models.custom_warnings import DspToolsFutureWarning
from dsp_tools.models.exceptions import BaseError


Expand Down Expand Up @@ -209,6 +211,37 @@ def _check_for_undefined_cardinalities(project_definition: dict[str, Any]) -> bo
return True


def _check_for_deprecated_syntax(project_definition: dict[str, Any]) -> bool:
return _check_for_deprecated_isSequenceOf(project_definition)


def _check_for_deprecated_isSequenceOf(project_definition: dict[str, Any]) -> bool:
ontos = project_definition["project"]["ontologies"]
isSequenceOf_matches = []
for index in range(len(ontos)):
pth = f"$.project.ontologies[{index}].properties[?super[*] == isSequenceOf]"
isSequenceOf_matches.extend(jsonpath_ng.ext.parse(pth).find(project_definition))

hasSequenceBounds_matches = []
for index in range(len(ontos)):
pth = f"$.project.ontologies[{index}].properties[?super[*] == hasSequenceBounds]"
hasSequenceBounds_matches.extend(jsonpath_ng.ext.parse(pth).find(project_definition))

sequence_resource_matches = []
for index in range(len(ontos)):
pth = f"$.project.ontologies[{index}].resources[?cardinalities.propname == isSequenceOf]"
sequence_resource_matches.extend(jsonpath_ng.ext.parse(pth).find(project_definition))

if any([isSequenceOf_matches, hasSequenceBounds_matches, sequence_resource_matches]):
msg = (
"Deprecation Warning: Your JSON project definition contains deprecated properties. "
"Support for the following properties will be removed soon: isSequenceOf, hasSequenceBounds"
)
warnings.warn(DspToolsFutureWarning(msg))

return True


def validate_project(
input_file_or_json: Union[dict[str, Any], str],
expand_lists: bool = True,
Expand Down Expand Up @@ -280,6 +313,7 @@ def validate_project(
_check_for_undefined_super_resource(project_definition)
_check_for_undefined_cardinalities(project_definition)
_check_for_duplicate_names(project_definition)
_check_for_deprecated_syntax(project_definition)

# cardinalities check for circular references
return _check_cardinalities_of_circular_references(project_definition)
Expand Down
22 changes: 22 additions & 0 deletions src/dsp_tools/models/custom_warnings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from typing import Protocol
from typing import runtime_checkable

from termcolor import cprint


@runtime_checkable
class DspToolsWarning(Protocol):
"""Protocol for warnings that implement a custom showwarnings() function"""

@classmethod
def showwarning(cls, message: str) -> None:
"""Functionality that should be executed when a warning of this class is emitted"""


class DspToolsFutureWarning(FutureWarning):
"""Class for user-facing deprecation warnings"""

@classmethod
def showwarning(cls, message: str) -> None:
"""Print the warning, without context"""
cprint(message, color="red", attrs=["bold"])
27 changes: 27 additions & 0 deletions src/dsp_tools/utils/warnings_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import warnings
from typing import TextIO

from dsp_tools.models.custom_warnings import DspToolsWarning


def initialize_warnings() -> None:
"""
This function makes sure that DSP-TOOLS internal warnings are displayed in their custom way how they specify it.
This is done by monkeypatching the behavior of the warnings module, as officially recommended by the Python docs:
https://docs.python.org/3/library/warnings.html#warnings.showwarning
"""

def _custom_showwarning(
message: Warning | str,
category: type[Warning],
filename: str,
lineno: int,
file: TextIO | None = None,
line: str | None = None,
) -> None:
if issubclass(category, DspToolsWarning):
category.showwarning(str(message))
else:
warnings.showwarning(message, category, filename, lineno, file, line)

warnings.showwarning = _custom_showwarning
21 changes: 21 additions & 0 deletions src/dsp_tools/utils/xml_validation.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import importlib.resources
import warnings
from datetime import datetime
from pathlib import Path
from typing import Any
Expand All @@ -10,6 +11,7 @@
from loguru import logger
from lxml import etree

from dsp_tools.models.custom_warnings import DspToolsFutureWarning
from dsp_tools.models.exceptions import InputError
from dsp_tools.utils.xml_utils import parse_and_remove_comments_from_xml_file
from dsp_tools.utils.xml_utils import remove_namespaces_from_xml
Expand Down Expand Up @@ -53,6 +55,8 @@ def validate_xml(input_file: Union[str, Path, etree._ElementTree[Any]]) -> bool:
if not all_good:
problems.append(msg)

_check_for_deprecated_syntax(xml_no_namespace)

if len(problems) > 0:
err_msg = grand_separator.join(problems)
logger.opt(exception=True).error(err_msg)
Expand Down Expand Up @@ -141,6 +145,23 @@ def _find_mixed_encodings_in_one_text_prop(
return False, msg


def _check_for_deprecated_syntax(data_xml: etree._Element) -> None:
_check_for_deprecated_isSequenceOf(data_xml)


def _check_for_deprecated_isSequenceOf(data_xml: etree._Element) -> None:
isSequenceOf_matches = data_xml.findall("resource/resptr-prop")
isSequenceOf_matches = [x for x in isSequenceOf_matches if x.attrib.get("name") == "isSequenceOf"]
hasSequenceBounds_matches = data_xml.findall("resource/interval-prop")
hasSequenceBounds_matches = [x for x in hasSequenceBounds_matches if x.attrib.get("name") == "hasSequenceBounds"]
if any([isSequenceOf_matches, hasSequenceBounds_matches]):
msg = (
"Deprecation Warning: Your XML data file contains deprecated properties. "
"Support for the following properties will be removed soon: isSequenceOf, hasSequenceBounds"
)
warnings.warn(DspToolsFutureWarning(msg))


def check_if_only_one_encoding_is_used_per_prop_in_root(
root: etree._Element,
) -> list[TextValueData]:
Expand Down
Empty file.