diff options
author | alyx <alyx@aleteoryx.me> | 2023-12-24 18:52:17 -0500 |
---|---|---|
committer | alyx <alyx@aleteoryx.me> | 2023-12-24 18:52:17 -0500 |
commit | 8786ac439b00772235f107b2f98456e2dffc69de (patch) | |
tree | 4c509ed54db4b0f9ad213621121eb714edbfd7b9 | |
parent | defde6070677e806c40d5891543848fcb2001ef5 (diff) | |
download | bbss.py-8786ac439b00772235f107b2f98456e2dffc69de.tar.gz bbss.py-8786ac439b00772235f107b2f98456e2dffc69de.tar.bz2 bbss.py-8786ac439b00772235f107b2f98456e2dffc69de.zip |
-rw-r--r-- | docs/conf.py | 9 | ||||
-rw-r--r-- | docs/index.rst | 205 | ||||
-rw-r--r-- | src/bbss/site.py | 2 | ||||
-rw-r--r-- | src/bbss/sizes.py | 7 |
4 files changed, 209 insertions, 14 deletions
diff --git a/docs/conf.py b/docs/conf.py index 760ad19..0ac5971 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -29,11 +29,18 @@ exclude_patterns = ['*~'] # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output html_theme = 'sphinxdoc' +html_theme_options = { + 'sidebarwidth': 300 +} + html_static_path = ['_static'] python_display_short_literal_types = True -intersphinx_mapping = {'python': ('https://docs.python.org/3', None)} +intersphinx_mapping = { + 'python': ('https://docs.python.org/3', None), + 'requests': ('https://requests.readthedocs.io/en/latest/', None) +} doctest_global_setup = """ import bbss diff --git a/docs/index.rst b/docs/index.rst index 963c702..8e82f55 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -35,6 +35,11 @@ bbss.site Whether the site was generated from a default directory, or a user-supplied one + .. py:attribute:: root + :type: str + + The base URL of the BBSS directory + .. py:attribute:: has_sizes_txt :type: bool @@ -50,6 +55,21 @@ bbss.site A list of friend sites found at the site + .. doctest:: + + >>> site = bbss.site.Site('aleteoryx.me') + >>> for size in site.sizes: + ... print(f"{size.entry} @ {size.url()}") + ... if size.exists(): + ... for button in size.get(): + ... print(f"===> {button.entry} @ {button.url()}") + ... else: + ... print("...doesn't seem to exist!") + ... + 88x31 @ https://aleteoryx.me/BBSS/88x31/list.txt + ===> ame.gif @ https://aleteoryx.me/BBSS/88x31/ame.gif + ===> amev2.gif @ https://aleteoryx.me/BBSS/88x31/amev2.gif + bbss.lists ========== @@ -81,7 +101,7 @@ bbss.lists .. py:class:: ListFileEntry(entry, comment) - The base class for all listfile entries. + The base class for all listfile entries :param str entry: The main content of the entry :param comment: The comment, if present @@ -89,7 +109,7 @@ bbss.lists .. py:class:: BaseListFile(contents) - The base class for all listfile representations. + 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. @@ -105,20 +125,12 @@ bbss.lists .. py:class:: ListFile(contents) - A representation of an arbitrary listfile. + 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 = """ @@ -140,6 +152,177 @@ bbss.lists ``this is a comment on entry two'' > entry 3 + .. 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 + +bbss.buttons +============ + +.. py:module:: bbss.buttons + + .. py:class:: ButtonListFileEntry(entry, comment, root) + + A representation of a button image + + :param str entry: The button's filename + :param comment: The comment for this button + :type comment: str or None + :param str root: The URL that this button is a child of + + .. py:method:: url() + + :return: The URL of the button file + :rtype: str + + .. py:method:: exists() + + :return: Whether the button actually exists on the server + :rtype: bool + + .. py:method:: get() + + :return: The HTTP response from trying to ``GET`` the button + :rtype: requests.Response + + .. py:class:: ButtonListFile(contents) + + A representation of a list of buttons + + 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 button list, if available + :rtype: ButtonListFile | None + + .. doctest:: + + >>> buttons = bbss.buttons.ButtonListFile \ + ... .from_url("https://aleteoryx.me/BBSS/88x31/list.txt") + >>> for button in buttons: + ... print(button.url()) + ... + https://aleteoryx.me/BBSS/88x31/ame.gif + https://aleteoryx.me/BBSS/88x31/amev2.gif + +bbss.sizes +============ + +.. py:module:: bbss.sizes + + .. py:class:: SizeListFileEntry(entry, comment, root) + + A representation of a given size for buttons + + :param str entry: The actual size + :param comment: The comment for this size + :type comment: str or None + :param str root: The BBSS directory that this size is within + + .. py:method:: url() + + :return: The URL of the size's button list + :rtype: str + + .. py:method:: exists() + + :return: Whether the size's button list file exists + :rtype: bool + + .. py:method:: get() + + :return: The actual button list, if available + :rtype: bbss.buttons.ButtonListFile + + .. py:method:: dims() + + :return: The dimensions of the size, ``(x, y)``, if they can be parsed from the name + :rtype: (int, int) or None + + .. py:class:: SizeListFile(contents) + + A representation of a list of button sizes + + 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 size list, if available + :rtype: ButtonListFile | None + +bbss.friends +============ + +.. py:module:: bbss.friends + + .. py:class:: FriendListFileEntry(entry, comment) + + A representation of a friend site + + :param str entry: The actual size + :param comment: The comment for this size + :type comment: str or None + + .. py:attribute:: url + :type: str + + The URL of the size's button list + + .. py:attribute:: domain + :type: str + + The domain of the friend site + + .. py:attribute:: scheme + :type: str + + The scheme of the friend site + + .. py:attribute:: path + :type: str + + The optional path of the remote BBSS directory + + .. py:method:: exists() + + :return: Whether the size's button list file exists + :rtype: bool + + .. py:method:: get() + + :return: The remote site + :rtype: bbss.site.Size + + .. py:class:: FriendListFile(contents) + + A representation of a list of friend sites + + 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 friend list, if available + :rtype: ButtonListFile | None ================== Indices and tables diff --git a/src/bbss/site.py b/src/bbss/site.py index 134ee8b..3829ae9 100644 --- a/src/bbss/site.py +++ b/src/bbss/site.py @@ -6,7 +6,7 @@ from collections.abc import Sequence import requests class Site: - def __init__(self, domain: str, path: Optional[str], *, scheme: Optional[str]): + def __init__(self, domain: str, path: Optional[str] = None, *, scheme: Optional[str] = None): base = (scheme if scheme is not None else "https") + "://" + domain hit_sizefile = False diff --git a/src/bbss/sizes.py b/src/bbss/sizes.py index f71a94c..c1d58f5 100644 --- a/src/bbss/sizes.py +++ b/src/bbss/sizes.py @@ -1,9 +1,10 @@ from bbss.lists import BaseListFile, ListFileEntry, parse_listfile from bbss.buttons import ButtonListFile from dataclasses import dataclass -from typing import Optional, Self +from typing import Optional, Self, Tuple from collections.abc import Sequence import requests +import re @dataclass(frozen=True) class SizeListFileEntry(ListFileEntry): @@ -18,6 +19,10 @@ class SizeListFileEntry(ListFileEntry): def get(self) -> Optional[ButtonListFile]: return ButtonListFile.from_url(self.url()) + def dims(self) -> Optional[Tuple[int, int]]: + matches = re.match("^([0-9]+)x([0-9]+)$", self.entry) + return (matches[1], matches[2]) if matches is not None else None + class SizeListFile(BaseListFile[SizeListFileEntry]): def __init__(self, contents: str, root: str): super().__init__(contents) |