diff --git a/chatmastermind/tags.py b/chatmastermind/tags.py index bfe5fd5..544270c 100644 --- a/chatmastermind/tags.py +++ b/chatmastermind/tags.py @@ -1,7 +1,7 @@ """ Module implementing tag related functions and classes. """ -from typing import Type, TypeVar, Optional +from typing import Type, TypeVar, Optional, Final TagInst = TypeVar('TagInst', bound='Tag') TagLineInst = TypeVar('TagLineInst', bound='TagLine') @@ -16,9 +16,9 @@ class Tag(str): A single tag. A string that can contain anything but the default separator (' '). """ # default separator - default_separator = ' ' + default_separator: Final[str] = ' ' # alternative separators (e. g. for backwards compatibility) - alternative_separators = [','] + alternative_separators: Final[list[str]] = [','] def __new__(cls: Type[TagInst], string: str) -> TagInst: """ @@ -93,19 +93,21 @@ def match_tags(tags: set[Tag], tags_or: Optional[set[Tag]], tags_and: Optional[s class TagLine(str): """ - A line of tags. It starts with a prefix ('TAGS:'), followed by a list of tags, - separated by the defaut separator (' '). Any operations on a TagLine will sort - the tags. + A line of tags in a '.txt' file. It starts with a prefix ('TAGS:'), followed by + a list of tags, separated by the defaut separator (' '). Any operations on a + TagLine will sort the tags. """ # the prefix - prefix = 'TAGS:' + prefix: Final[str] = 'TAGS:' def __new__(cls: Type[TagLineInst], string: str) -> TagLineInst: """ - Make sure the tagline string starts with the prefix. + Make sure the tagline string starts with the prefix. Also replace newlines + and multiple spaces with ' ', in order to support multiline TagLines. """ if not string.startswith(cls.prefix): raise TagError(f"TagLine '{string}' is missing prefix '{cls.prefix}'") + string = ' '.join(string.split()) instance = super().__new__(cls, string) return instance @@ -114,7 +116,7 @@ class TagLine(str): """ Create a new TagLine from a set of tags. """ - return cls(' '.join([TagLine.prefix] + sorted([t for t in tags]))) + return cls(' '.join([cls.prefix] + sorted([t for t in tags]))) def tags(self) -> set[Tag]: """ diff --git a/tests/test_main.py b/tests/test_main.py index 8ce06cb..25cdc37 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -256,6 +256,10 @@ class TestTagLine(CmmTestCase): tagline = TagLine('TAGS: tag1 tag2') self.assertEqual(tagline, 'TAGS: tag1 tag2') + def test_valid_tagline_with_newline(self) -> None: + tagline = TagLine('TAGS: tag1\n tag2') + self.assertEqual(tagline, 'TAGS: tag1 tag2') + def test_invalid_tagline(self) -> None: with self.assertRaises(TagError): TagLine('tag1 tag2') @@ -273,6 +277,11 @@ class TestTagLine(CmmTestCase): tags = tagline.tags() self.assertEqual(tags, {Tag('tag1'), Tag('tag2')}) + def test_tags_with_newline(self) -> None: + tagline = TagLine('TAGS: tag1\n tag2') + tags = tagline.tags() + self.assertEqual(tags, {Tag('tag1'), Tag('tag2')}) + def test_merge(self) -> None: tagline1 = TagLine('TAGS: tag1 tag2') tagline2 = TagLine('TAGS: tag2 tag3')