ChatMasterMind Application Refactor and Enhancement #8

Merged
juk0de merged 122 commits from restructurings into main 2023-09-12 07:36:07 +02:00
Showing only changes of commit 604e5ccf73 - Show all commits

View File

@ -30,6 +30,67 @@ class Tag(str):
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):
"""
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':
"""
Merges the tags of all given taglines into the current one
and returns a new TagLine.
Merges the tags of all given taglines into the current one and returns a new TagLine.
"""
merged_tags = self.tags()
for tl in taglines:
merged_tags |= tl.tags()
return self.from_set(set(sorted(merged_tags)))
tags_merge = [tl.tags() for tl in taglines]
return self.from_set(merge_tags(self.tags(), tags_merge))
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.
"""
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.
"""
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
tuple element is the old name, the second one is the new name.
"""
new_tags = self.tags()
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)))
return self.from_set(rename_tags(self.tags(), tags_rename))
def match_tags(self, tags_or: Optional[set[Tag]], tags_and: Optional[set[Tag]],
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
exclusion is still done if 'tags_not' is not 'None').
"""
tag_set = self.tags()
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
return match_tags(self.tags(), tags_or, tags_and, tags_not)