Skip to content

Commit

Permalink
feat(xmllib): make checks for non-empty input consistent (DEV-4435) (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
Nora-Olivia-Ammann authored Dec 19, 2024
1 parent 58ff473 commit 0acc6dd
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 64 deletions.
90 changes: 90 additions & 0 deletions src/dsp_tools/xmllib/internal_helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
from __future__ import annotations

import warnings
from typing import Any

from dsp_tools.models.custom_warnings import DspToolsUserInfo
from dsp_tools.models.custom_warnings import DspToolsUserWarning
from dsp_tools.models.exceptions import InputError
from dsp_tools.xmllib.models.config_options import NewlineReplacement
from dsp_tools.xmllib.models.config_options import Permissions
from dsp_tools.xmllib.models.values import Richtext
from dsp_tools.xmllib.value_checkers import is_string_like
from dsp_tools.xmllib.value_converters import replace_newlines_with_tags


def create_richtext_with_checks(
value: str,
prop_name: str,
permissions: Permissions,
comment: str | None,
newline_replacement: NewlineReplacement,
res_id: str,
) -> Richtext:
"""
Creates a RichtextValue with checks and optional conversions
Args:
value: richttext value
prop_name: name of the property
permissions: permissions of the value
comment: comment for the value
newline_replacement: the replacement for the newlines in the string
res_id: id of the calling resource
Returns:
A richtext value
Raises:
Input Error if the input is a dictionary
"""
# Because of the richtext conversions, the input value is cast as a string.
# Values such as str(`pd.NA`) result in a non-empy string.
# Therefore, a check must occur before the conversion takes place.
check_richtext_before_conversion(value, prop_name, res_id)
value = replace_newlines_with_tags(str(value), newline_replacement)
return Richtext(value, prop_name, permissions, comment, res_id)


def check_richtext_before_conversion(value: Any, prop_name: str, res_id: str) -> None:
"""
Checks if the input which is expected to be richtext is a string.
Args:
value: Input value
prop_name: Property name
res_id: Resource ID
"""
if not is_string_like(value):
msg = f"Resource '{res_id}' has a richtext value that is not a string: Value: {value} | Property: {prop_name}"
warnings.warn(DspToolsUserWarning(msg))


def check_and_fix_collection_input(value: Any, prop_name: str, res_id: str) -> list[Any]:
"""
To allow varied input but ensure consistent typing internally, collections are converted.
As collections are expected to be non-empty a warning is emitted for the user.
Args:
value: Input value
prop_name: Property name
res_id: Resource ID
Returns:
The input as a list
Raises:
InputError: if the input is a dictionary
"""
msg = f"The input value of the resource with the ID '{res_id}' and the property '{prop_name}' "
match value:
case set() | list() | tuple():
if len(value) == 0:
msg += "is empty. Please note that no values will be added to the resource."
warnings.warn(DspToolsUserInfo(msg))
return list(value)
case dict():
msg += "is a dictionary. Only collections (list, set, tuple) are permissible."
raise InputError(msg)
case _:
return [value]
31 changes: 21 additions & 10 deletions src/dsp_tools/xmllib/models/dsp_base_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

from dsp_tools.models.custom_warnings import DspToolsUserWarning
from dsp_tools.models.exceptions import InputError
from dsp_tools.xmllib.internal_helpers import check_and_fix_collection_input
from dsp_tools.xmllib.models.config_options import Permissions
from dsp_tools.xmllib.models.geometry import Circle
from dsp_tools.xmllib.models.geometry import GeometryPoint
Expand Down Expand Up @@ -277,7 +278,8 @@ def add_comment_multiple(self, comments: Collection[str]) -> RegionResource:
region = region.add_comment_multiple(["comment 1", "comment 2"])
```
"""
self.comments.extend(comments)
vals = check_and_fix_collection_input(comments, "hasComment", self.res_id)
self.comments.extend(vals)
return self

def add_comment_optional(self, comment: Any) -> RegionResource:
Expand Down Expand Up @@ -457,7 +459,8 @@ def add_comment_multiple(self, comments: Collection[str]) -> LinkResource:
link_resource = link_resource.add_comment_multiple(["comment 1", "comment 2"])
```
"""
self.comments.extend(comments)
vals = check_and_fix_collection_input(comments, "hasComment", self.res_id)
self.comments.extend(vals)
return self

def add_comment_optional(self, comment: Any) -> LinkResource:
Expand Down Expand Up @@ -706,7 +709,8 @@ def add_comment_multiple(self, comments: Collection[str]) -> VideoSegmentResourc
video_segment = video_segment.add_comment_multiple(["comment 1", "comment 2"])
```
"""
self.comments.extend(comments)
vals = check_and_fix_collection_input(comments, "hasComment", self.res_id)
self.comments.extend(vals)
return self

def add_comment_optional(self, comment: Any) -> VideoSegmentResource:
Expand Down Expand Up @@ -765,7 +769,8 @@ def add_description_multiple(self, descriptions: Collection[str]) -> VideoSegmen
video_segment = video_segment.add_description_multiple(["description 1", "description 2"])
```
"""
self.descriptions.extend(descriptions)
vals = check_and_fix_collection_input(descriptions, "description", self.res_id)
self.descriptions.extend(vals)
return self

def add_description_optional(self, description: Any) -> VideoSegmentResource:
Expand Down Expand Up @@ -824,7 +829,8 @@ def add_keyword_multiple(self, keywords: Collection[str]) -> VideoSegmentResourc
video_segment = video_segment.add_keyword_multiple(["keyword 1", "keyword 2"])
```
"""
self.keywords.extend(keywords)
vals = check_and_fix_collection_input(keywords, "keywords", self.res_id)
self.keywords.extend(vals)
return self

def add_keyword_optional(self, keyword: Any) -> VideoSegmentResource:
Expand Down Expand Up @@ -883,7 +889,8 @@ def add_relates_to_multiple(self, relates_to: Collection[str]) -> VideoSegmentRe
video_segment = video_segment.add_relates_to_multiple(["target_resource_id_1", "target_resource_id_2"])
```
"""
self.relates_to.extend(relates_to)
vals = check_and_fix_collection_input(relates_to, "relatesTo", self.res_id)
self.relates_to.extend(vals)
return self

def add_relates_to_optional(self, relates_to: Any) -> VideoSegmentResource:
Expand Down Expand Up @@ -1087,7 +1094,8 @@ def add_comment_multiple(self, comments: Collection[str]) -> AudioSegmentResourc
audio_segment = audio_segment.add_comment_multiple(["comment 1", "comment 2"])
```
"""
self.comments.extend(comments)
vals = check_and_fix_collection_input(comments, "hasComment", self.res_id)
self.comments.extend(vals)
return self

def add_comment_optional(self, comment: Any) -> AudioSegmentResource:
Expand Down Expand Up @@ -1146,7 +1154,8 @@ def add_description_multiple(self, descriptions: Collection[str]) -> AudioSegmen
audio_segment = audio_segment.add_description_multiple(["description 1", "description 2"])
```
"""
self.descriptions.extend(descriptions)
vals = check_and_fix_collection_input(descriptions, "description", self.res_id)
self.descriptions.extend(vals)
return self

def add_description_optional(self, description: Any) -> AudioSegmentResource:
Expand Down Expand Up @@ -1205,7 +1214,8 @@ def add_keyword_multiple(self, keywords: Collection[str]) -> AudioSegmentResourc
audio_segment = audio_segment.add_keyword_multiple(["keyword 1", "keyword 2"])
```
"""
self.keywords.extend(keywords)
vals = check_and_fix_collection_input(keywords, "keywords", self.res_id)
self.keywords.extend(vals)
return self

def add_keyword_optional(self, keyword: Any) -> AudioSegmentResource:
Expand Down Expand Up @@ -1264,7 +1274,8 @@ def add_relates_to_multiple(self, relates_to: Collection[str]) -> AudioSegmentRe
audio_segment = audio_segment.add_relates_to_multiple(["target_resource_id_1", "target_resource_id_2"])
```
"""
self.relates_to.extend(relates_to)
vals = check_and_fix_collection_input(relates_to, "relatesTo", self.res_id)
self.relates_to.extend(vals)
return self

def add_relates_to_optional(self, relates_to: Any) -> AudioSegmentResource:
Expand Down
Loading

0 comments on commit 0acc6dd

Please sign in to comment.