3 Commits

Author SHA1 Message Date
juk0de 0f41b0b1ee configuration: added 'asdict()' as an instance function 2023-08-19 08:04:58 +02:00
juk0de af56de204b added testcases for messages.py 2023-08-19 08:04:58 +02:00
juk0de e3aaa6154a added new module 'message.py' 2023-08-19 08:04:58 +02:00
2 changed files with 55 additions and 11 deletions
+3
View File
@@ -64,3 +64,6 @@ class Config():
def to_file(self, path: str) -> None:
with open(path, 'w') as f:
yaml.dump(asdict(self), f)
def asdict(self) -> dict[str, Any]:
return asdict(self)
+52 -11
View File
@@ -1,10 +1,14 @@
"""
Module implementing message related functions and classes.
"""
from typing import Type, TypeVar
import pathlib
from typing import Type, TypeVar, Optional, Any
from dataclasses import dataclass, asdict
from .tags import Tag
QuestionInst = TypeVar('QuestionInst', bound='Question')
AnswerInst = TypeVar('AnswerInst', bound='Answer')
MessageInst = TypeVar('MessageInst', bound='Message')
class MessageError(Exception):
@@ -39,16 +43,16 @@ def source_code(text: str, include_delims: bool = False) -> list[str]:
class Question(str):
"""
A single question with a defined prefix.
A single question with a defined header.
"""
prefix = '=== QUESTION ==='
header = '=== QUESTION ==='
def __new__(cls: Type[QuestionInst], string: str) -> QuestionInst:
"""
Make sure the question string does not contain the prefix.
Make sure the question string does not contain the header.
"""
if cls.prefix in string:
raise MessageError(f"Question '{string}' contains the prefix '{cls.prefix}'")
if cls.header in string:
raise MessageError(f"Question '{string}' contains the header '{cls.header}'")
instance = super().__new__(cls, string)
return instance
@@ -61,16 +65,16 @@ class Question(str):
class Answer(str):
"""
A single answer with a defined prefix.
A single answer with a defined header.
"""
prefix = '=== ANSWER ==='
header = '=== ANSWER ==='
def __new__(cls: Type[AnswerInst], string: str) -> AnswerInst:
"""
Make sure the answer string does not contain the prefix.
Make sure the answer string does not contain the header.
"""
if cls.prefix in string:
raise MessageError(f"Answer '{string}' contains the prefix '{cls.prefix}'")
if cls.header in string:
raise MessageError(f"Answer '{string}' contains the header '{cls.header}'")
instance = super().__new__(cls, string)
return instance
@@ -79,3 +83,40 @@ class Answer(str):
Extract and return all source code sections.
"""
return source_code(self, include_delims)
@dataclass
class Message():
"""
Single message. Consists of a question and optionally an answer, a set of tags
and a file path.
"""
question: Question
answer: Optional[Answer]
tags: Optional[set[Tag]]
path: Optional[pathlib.Path]
# @classmethod
# def from_file(cls: Type[MessageInst], path: str) -> MessageInst:
# """
# Create a Message from the given file. Expects the following file structure:
# * TagLine (from 'self.tags')
# * Question.Header
# * Question
# * Answer.Header
# """
# pass
def to_file(self, path: str) -> None:
"""
Write Message to the given file. Creates the following file structure:
* TagLine (from 'self.tags')
* Question.Header
* Question
* Answer.Header
* Answer
"""
pass
def asdict(self) -> dict[str, Any]:
return asdict(self)