py2403homework.utils 源代码

"""
提供了一些有用的类型,用于生成作业文档源文件。

This module provides some useful types to generate source files of homework documentation.
"""

import logging
import datetime
import abc
import time
import unicodedata

__all__ = ['Library', 'Generatable', 'Simple', 'Event', 'Homework']

logger = logging.getLogger(__name__)

date_like = datetime.date | str | None

[文档] class Generatable(metaclass=abc.ABCMeta): r""" :term:`可生成文档类型 <doc-generatable>`\ 的抽象基类。 Abstract base class of :term:`doc-generatable` types. """
[文档] @abc.abstractmethod def dumps(self) -> str: """ 实现生成 reStructuredText 形式的文档的功能。 Implement generating reStructuredText format of a documentation. :return: reStructuredText 源码 sourcecode :rtype: str """ pass
[文档] class Simple(Generatable): r""" :term:`可生成文档类型 <doc-generatable>`\ 的一个简单实现。 A simple implementation of a :term:`doc-generatable` type. :arg title: 章节标题,不能超过一行 section title within a line :arg content: 标题后的正文 the body after ``title`` """ #: 装饰标题所使用的标点符号 #: #: punctuation character for marking titles TITLE_SYMBOL: str = '~' def __init__(self, title: str, content: str | None = None): #: 由 ``title`` 参数设置 #: #: set by argument ``title`` self.title = title if content: #: 由 ``content`` 参数设置 #: #: set by argument ``content`` self.content = content else: self.content = ''
[文档] def __str__(self): """ :meth:`.dumps` 方法的快捷方式。 The shortcut for :meth:`.dumps`. :rtype: str """ return self.dumps()
[文档] def dumps(self) -> str: r""" 生成文档。 Generate the documentation. 先调用 :meth:`.generate_title` 生成标题部分,与后面的 :attr:`content` 以 ``\n\n`` 相隔,即一个空行。 Call :meth:`.generate_title` first to generate the title part, followed by ``\n\n`` (A blank line), then :attr:`content`. """ return self.generate_title() + '\n\n' + self.content
[文档] def generate_title(self) -> str: """ 生成文档标题部分的 reStructuredText 形式。 Generate reStructuredText format of the title part of the documentation. 标题最先出现,再是一些用于装饰的标点符号。 The title comes first, then punctuation characters for marking. :return: reStructuredText 格式的章节标记 """ width = 0 for char in self.title: eaw = unicodedata.east_asian_width(char) if eaw in ('F', 'W'): width += 2 else: width += 1 return self.title + '\n' + self.TITLE_SYMBOL * width
[文档] class Event(Simple): r""" 普通事件类型,也是所有 :term:`event type` 的基类。 General event type, also the base class of all :term:`event type`\ s. :arg description: 对于事件的描述,若不为空,则标题后会加上 `` --- {description}`` :arg name: 事件名称,默认使用 :data:`.DEFAULT_NAME` :arg date: 事件日期,若为空则调用 :func:`time.strftime`;若为字符串则直接使用,为 :class:`datetime.date` 类型时用 ``'{date.year:0>4}/{date.month:0>2}/{date.day:0>2}'`` 的格式转换,并放在标题的开头 """ #: 默认事件类型名称,作为 ``name`` 参数的默认值使用 #: #: default event format name, used as the default value of argument ``name`` DEFAULT_NAME: str = '事件' #: 默认内容,作为 ``content`` 参数的默认值使用 #: #: default content, used as the default value of argument ``content`` DEFAULT_CONTENT: str = '' def __init__(self, description: str | None = None, name: str | None = None, date: date_like = None, content: str | None = None): if description: addition = ' --- ' + description else: addition = '' if name is None: name = self.DEFAULT_NAME if date: try: date = f'{date.year:0>4}/{date.month:0>2}/{date.day:0>2}' except AttributeError: date = time.strftime('%Y/%m/%d') else: date = time.strftime('%Y/%m/%d') title = f'{date} {name}{addition}' if content is None: content = self.DEFAULT_CONTENT super().__init__(title, content)
[文档] class Homework(Event): DEFAULT_NAME = '作业' def __init__(self, date: date_like = None, date_limit: str | None = None, description: str | None = None, content: str | None = None, content_fmt: str | None = None): if date_limit: if content: content = f'*{date_limit.strip()}*\n\n{content}' else: content = date_limit if content_fmt is not None: content = content_fmt.format(content) super().__init__(description, date=date, content=content) self.content_fmt = content_fmt self.subjects: list['Subject'] = []
[文档] def dumps(self): return super().dumps()
def update_content(self): content = f'' for subject in self.subjects: content += subject.dumps()
class Subject(Simple): TITLE_SYMBOL = '-' def __init__(self, name: str, content: str | None = None): super().__init__(name, content) class Library: ... if __name__ == '__main__': print(Homework(date_limit='4.28~4.29', description='description', content='content', content_fmt='Content:\n{}'))