tags.py: converted most TagLine functions to module functions

This commit is contained in:
juk0de 2023-08-18 12:11:56 +02:00
parent ef46f5efc9
commit 604e5ccf73

View File

@ -30,6 +30,67 @@ class Tag(str):
return instance return instance
def delete_tags(tags: set[Tag], tags_delete: set[Tag]) -> set[Tag]:
"""
Deletes the given tags and returns a new set.
"""
return tags.difference(tags_delete)
def add_tags(tags: set[Tag], tags_add: set[Tag]) -> set[Tag]:
"""
Adds the given tags and returns a new set.
"""
return set(sorted(tags | tags_add))
def merge_tags(tags: set[Tag], tags_merge: list[set[Tag]]) -> set[Tag]:
"""
Merges the tags in 'tags_merge' into the current one and returns a new set.
"""
for ts in tags_merge:
tags |= ts
return tags
def rename_tags(tags: set[Tag], tags_rename: set[tuple[Tag, Tag]]) -> set[Tag]:
"""
Renames the given tags and returns a new set. The first tuple element
is the old name, the second one is the new name.
"""
for t in tags_rename:
if t[0] in tags:
tags.remove(t[0])
tags.add(t[1])
return set(sorted(tags))
def match_tags(tags: set[Tag], tags_or: Optional[set[Tag]], tags_and: Optional[set[Tag]],
tags_not: Optional[set[Tag]]) -> bool:
"""
Checks if the given set 'tags' matches the given tag requirements:
- 'tags_or' : matches if this TagLine contains ANY of those tags
- 'tags_and': matches if this TagLine contains ALL of those tags
- 'tags_not': matches if this TagLine contains NONE of those tags
Note that it's sufficient if 'tags' matches one of 'tags_or' or 'tags_and',
i. e. you can select a TagLine if it either contains one of the tags in 'tags_or'
or all of the tags in 'tags_and' but it must never contain any of the tags in
'tags_not'. If 'tags_or' and 'tags_and' are 'None', they match all tags (tag
exclusion is still done if 'tags_not' is not 'None').
"""
required_tags_present = False
excluded_tags_missing = False
if ((tags_or is None and tags_and is None)
or (tags_or and any(tag in tags for tag in tags_or)) # noqa: W503
or (tags_and and all(tag in tags for tag in tags_and))): # noqa: W503
required_tags_present = True
if ((tags_not is None)
or (not any(tag in tags for tag in tags_not))): # noqa: W503
excluded_tags_missing = True
return required_tags_present and excluded_tags_missing
class TagLine(str): class TagLine(str):
""" """
A line of tags. It starts with a prefix ('TAGS:'), followed by a list of tags, A line of tags. It starts with a prefix ('TAGS:'), followed by a list of tags,
@ -71,37 +132,29 @@ class TagLine(str):
def merge(self, taglines: set['TagLine']) -> 'TagLine': def merge(self, taglines: set['TagLine']) -> 'TagLine':
""" """
Merges the tags of all given taglines into the current one Merges the tags of all given taglines into the current one and returns a new TagLine.
and returns a new TagLine.
""" """
merged_tags = self.tags() tags_merge = [tl.tags() for tl in taglines]
for tl in taglines: return self.from_set(merge_tags(self.tags(), tags_merge))
merged_tags |= tl.tags()
return self.from_set(set(sorted(merged_tags)))
def delete_tags(self, tags: set[Tag]) -> 'TagLine': def delete_tags(self, tags_delete: set[Tag]) -> 'TagLine':
""" """
Deletes the given tags and returns a new TagLine. Deletes the given tags and returns a new TagLine.
""" """
return self.from_set(self.tags().difference(tags)) return self.from_set(delete_tags(self.tags(), tags_delete))
def add_tags(self, tags: set[Tag]) -> 'TagLine': def add_tags(self, tags_add: set[Tag]) -> 'TagLine':
""" """
Adds the given tags and returns a new TagLine. Adds the given tags and returns a new TagLine.
""" """
return self.from_set(set(sorted(self.tags() | tags))) return self.from_set(add_tags(self.tags(), tags_add))
def rename_tags(self, tags: set[tuple[Tag, Tag]]) -> 'TagLine': def rename_tags(self, tags_rename: set[tuple[Tag, Tag]]) -> 'TagLine':
""" """
Renames the given tags and returns a new TagLine. The first Renames the given tags and returns a new TagLine. The first
tuple element is the old name, the second one is the new name. tuple element is the old name, the second one is the new name.
""" """
new_tags = self.tags() return self.from_set(rename_tags(self.tags(), tags_rename))
for t in tags:
if t[0] in new_tags:
new_tags.remove(t[0])
new_tags.add(t[1])
return self.from_set(set(sorted(new_tags)))
def match_tags(self, tags_or: Optional[set[Tag]], tags_and: Optional[set[Tag]], def match_tags(self, tags_or: Optional[set[Tag]], tags_and: Optional[set[Tag]],
tags_not: Optional[set[Tag]]) -> bool: tags_not: Optional[set[Tag]]) -> bool:
@ -117,14 +170,4 @@ class TagLine(str):
'tags_not'. If 'tags_or' and 'tags_and' are 'None', they match all tags (tag 'tags_not'. If 'tags_or' and 'tags_and' are 'None', they match all tags (tag
exclusion is still done if 'tags_not' is not 'None'). exclusion is still done if 'tags_not' is not 'None').
""" """
tag_set = self.tags() return match_tags(self.tags(), tags_or, tags_and, tags_not)
required_tags_present = False
excluded_tags_missing = False
if ((tags_or is None and tags_and is None)
or (tags_or and any(tag in tag_set for tag in tags_or)) # noqa: W503
or (tags_and and all(tag in tag_set for tag in tags_and))): # noqa: W503
required_tags_present = True
if ((tags_not is None)
or (not any(tag in tag_set for tag in tags_not))): # noqa: W503
excluded_tags_missing = True
return required_tags_present and excluded_tags_missing