From defde6070677e806c40d5891543848fcb2001ef5 Mon Sep 17 00:00:00 2001 From: alyx Date: Sun, 24 Dec 2023 17:12:56 -0500 Subject: bbss.lists documented, doctests setup --- docs/conf.py | 18 ++++++-- docs/index.rst | 131 +++++++++++++++++++++++++++++++++++++++++++++--------- src/bbss/lists.py | 5 ++- 3 files changed, 128 insertions(+), 26 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index a851995..760ad19 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -2,7 +2,6 @@ import sys import pathlib sys.path.append(str(pathlib.PurePath(__file__).parent.parent.joinpath('src'))) -print(sys.path) # Configuration file for the Sphinx documentation builder. @@ -21,15 +20,26 @@ release = '0.1.0' # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration -extensions = ['sphinx.ext.autodoc'] +extensions = ['sphinx.ext.doctest', 'sphinx.ext.intersphinx'] templates_path = ['_templates'] exclude_patterns = ['*~'] -autodoc_default_options = { "members": None } - # -- Options for HTML output ------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output html_theme = 'sphinxdoc' html_static_path = ['_static'] + +python_display_short_literal_types = True + +intersphinx_mapping = {'python': ('https://docs.python.org/3', None)} + +doctest_global_setup = """ +import bbss +import bbss.lists +import bbss.buttons +import bbss.friends +import bbss.site +import bbss.sizes +""" diff --git a/docs/index.rst b/docs/index.rst index ec56a5d..963c702 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -18,39 +18,128 @@ bbss.site .. py:module:: bbss.site -.. py:class:: Site(domain: str[, path: str[, *, scheme: str = 'https']]) + .. py:class:: Site(domain, path, *, scheme = 'https') - `domain` - The domain to check for BBSS files + A representation of some BBSS directory. On construction, all information about an individual site + is downloaded. - `path` - An optional subdirectory to treat as the root of the BBSS directory + :param str domain: The domain to check for BBSS files - `scheme` - What protocol to download over; can be either :python:`'http'` or :python:`'https'` + :param path: An optional subdirectory to treat as the root of the BBSS directory + :type path: str or None + :param scheme: What protocol to download over + :type scheme: 'http' | 'https' - A representation of some BBSS directory. On construction, all information about an individual site - is downloaded. + .. py:attribute:: default_path + :type: bool - .. py:attribute:: default_path - :type: bool + Whether the site was generated from a default directory, or a user-supplied one - Whether the site was generated from a default directory, or a user-supplied one + .. py:attribute:: has_sizes_txt + :type: bool - .. py:attribute:: has_sizes_txt - :type: bool + Whether the BBSS directory contains a ``sizes.txt`` file - Whether the BBSS directory contains a :code:`sizes.txt` file + .. py:attribute:: sizes + :type: bbss.sizes.SizeListFile - .. py:attribute:: sizes - :type: bbss.sizes.SizeListFile + A list of the sizes found at the site - A list of the sizes found at the site + .. py:attribute:: friends + :type: Optional[bbss.friends.FriendListFile] - .. py:attribute:: friends - :type: Optional[bbss.friends.FriendListFile] + A list of friend sites found at the site + +bbss.lists +========== + +.. py:module:: bbss.lists + + .. py:function:: parse_listfile[T](contents, ctor) + + Parses in the text of a listfile, and calls the passed constructor + function repeatedly to generate datastructures. + + :param str contents: The contents of the listfile + :param ctor: The constructor for the internal datastructures + :type ctor: (str, str or None) -> T + :return: A list of T, containing the contents of the file + :rtype: list[T] + + .. doctest:: + + >>> listfile = """ + ... entry 1 + ... ## this is a comment on entry two + ... entry 2 + ... # omitted + ... entry 3 + ... ## trailing comments are ignored + ... """ + >>> bbss.lists.parse_listfile(listfile, lambda x, y: (x, y)) + [('entry 1', None), ('entry 2', 'this is a comment on entry two'), ('entry 3', None)] + + .. py:class:: ListFileEntry(entry, comment) + + The base class for all listfile entries. + + :param str entry: The main content of the entry + :param comment: The comment, if present + :type comment: str or None + + .. py:class:: BaseListFile(contents) + + The base class for all listfile representations. + + It supports all the :py:class:`collections.abc.Sequence` operations, meaning it can be used like a list in most cases. + + :param str contents: The contents of the source listfile + + .. py:classmethod:: from_url(url) + + Alternate constructor, which will attempt to download the listfile at ``url``. + + :param str url: The URL to download from. + :return: A representation of the remote file, if available + :rtype: BaseListFile | None + + .. py:class:: ListFile(contents) + + A representation of an arbitrary listfile. + + It supports all the :py:class:`collections.abc.Sequence` operations, meaning it can be used like a list in most cases. + + :param str contents: The contents of the source listfile + + .. py:classmethod:: from_url(url) + + Alternate constructor, which will attempt to download the listfile at ``url``. + + :param str url: The URL to download from. + :return: A representation of the remote file, if available + :rtype: BaseListFile | None + + .. doctest:: + + >>> contents = """ + ... entry 1 + ... ## this is a comment on entry two + ... entry 2 + ... # omitted + ... entry 3 + ... ## trailing comments are ignored + ... """ + >>> listfile = bbss.lists.ListFile(contents) + >>> for entry in listfile: + ... print(">", entry.entry) + ... if entry.comment is not None: + ... print(f" ``{entry.comment}''") + ... + > entry 1 + > entry 2 + ``this is a comment on entry two'' + > entry 3 - A list of friend sites found at the site ================== Indices and tables diff --git a/src/bbss/lists.py b/src/bbss/lists.py index 5bcdddf..6fa757f 100644 --- a/src/bbss/lists.py +++ b/src/bbss/lists.py @@ -8,12 +8,15 @@ def parse_listfile(contents: str, ctor: Callable[[str, Optional[str]], T]) -> Li acc = [] comment_acc = [] for line in contents.splitlines(): - if line.startswith("#"): + if not len(line): continue elif line.startswith("##"): comment_acc.append(line[2:].strip()) + elif line.startswith("#"): + continue else: acc.append(ctor(line, " ".join(comment_acc) if len(comment_acc) else None)) + comment_acc = [] return acc @dataclass(frozen=True) -- cgit v1.2.3-70-g09d2