mirror of
https://github.com/drewcassidy/yaclog.git
synced 2024-09-01 14:58:58 +00:00
Add API documentation
This commit is contained in:
parent
5cc815d8b6
commit
f085f318b3
12
docs/_templates/layout.html
vendored
12
docs/_templates/layout.html
vendored
@ -1,10 +1,10 @@
|
||||
{% extends "!layout.html" %}
|
||||
{% block extrahead %}
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="_static/icon-16.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="_static/icon-32.png">
|
||||
<link rel="icon" type="image/png" sizes="48x48" href="_static/icon-48.png">
|
||||
<link rel="icon" type="image/png" sizes="64x64" href="_static/icon-64.png">
|
||||
<link rel="icon" type="image/png" sizes="128x128" href="_static/icon-128.png">
|
||||
<link rel="icon" type="image/png" sizes="256x256" href="_static/icon-256.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/_static/icon-16.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/_static/icon-32.png">
|
||||
<link rel="icon" type="image/png" sizes="48x48" href="/_static/icon-48.png">
|
||||
<link rel="icon" type="image/png" sizes="64x64" href="/_static/icon-64.png">
|
||||
<link rel="icon" type="image/png" sizes="128x128" href="/_static/icon-128.png">
|
||||
<link rel="icon" type="image/png" sizes="256x256" href="/_static/icon-256.png">
|
||||
{{ super() }}
|
||||
{% endblock %}
|
38
docs/conf.py
38
docs/conf.py
@ -4,16 +4,18 @@
|
||||
# list see the documentation:
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
|
||||
from pkg_resources import get_distribution
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
from pkg_resources import get_distribution
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.abspath('..'))
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
@ -29,7 +31,10 @@ version = '.'.join(release.split('.')[:3])
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'myst_parser', 'sphinx_rtd_theme'
|
||||
'myst_parser',
|
||||
'sphinx_rtd_theme',
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.intersphinx',
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
@ -40,6 +45,8 @@ templates_path = ['_templates']
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
|
||||
default_role = 'py:obj'
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
@ -54,3 +61,24 @@ html_favicon = 'favicon.ico'
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
html_css_files = ['css/custom.css']
|
||||
|
||||
# -- Options for Autodoc -----------------------------------------------------
|
||||
|
||||
add_module_names = False
|
||||
autodoc_docstring_signature = True
|
||||
autoclass_content = 'both'
|
||||
|
||||
autodoc_default_options = {
|
||||
'member-order': 'bysource',
|
||||
'undoc-members': True,
|
||||
}
|
||||
|
||||
# -- Options for Intersphinx -------------------------------------------------
|
||||
|
||||
# This config value contains the locations and names of other projects that
|
||||
# should be linked to in this documentation.
|
||||
|
||||
intersphinx_mapping = {
|
||||
'python': ('https://docs.python.org/3', None),
|
||||
'packaging': ('https://packaging.pypa.io/en/latest/', None),
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ Welcome to Yaclog's documentation!
|
||||
:includehidden:
|
||||
:caption: Contents:
|
||||
|
||||
Changelog <changelog>
|
||||
API Reference <reference/index.rst>
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
5
docs/reference/changelog.rst
Normal file
5
docs/reference/changelog.rst
Normal file
@ -0,0 +1,5 @@
|
||||
Changelog Module
|
||||
================
|
||||
|
||||
.. automodule:: yaclog.changelog
|
||||
:members:
|
8
docs/reference/index.rst
Normal file
8
docs/reference/index.rst
Normal file
@ -0,0 +1,8 @@
|
||||
API Reference
|
||||
=============
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:glob:
|
||||
|
||||
*
|
5
docs/reference/markdown.rst
Normal file
5
docs/reference/markdown.rst
Normal file
@ -0,0 +1,5 @@
|
||||
Markdown Module
|
||||
==============
|
||||
|
||||
.. automodule:: yaclog.markdown
|
||||
:members:
|
5
docs/reference/version.rst
Normal file
5
docs/reference/version.rst
Normal file
@ -0,0 +1,5 @@
|
||||
Version Module
|
||||
==============
|
||||
|
||||
.. automodule:: yaclog.version
|
||||
:members:
|
@ -1,3 +1,8 @@
|
||||
"""
|
||||
Contains the `Changelog` class that represents a parsed changelog file that can be read from and written to
|
||||
disk as markdown, as well as the `VersionEntry` class that represents a single version within that changelog
|
||||
"""
|
||||
|
||||
# yaclog: yet another changelog tool
|
||||
# Copyright (c) 2021. Andrew Cassidy
|
||||
#
|
||||
@ -32,23 +37,21 @@ default_header = '# Changelog\n\nAll notable changes to this project will be doc
|
||||
class VersionEntry:
|
||||
"""Holds a single version entry in a :py:class:`Changelog`"""
|
||||
|
||||
header_regex = re.compile( # THE LANGUAGE OF THE GODS
|
||||
_header_regex = re.compile( # THE LANGUAGE OF THE GODS
|
||||
r"##\s+(?P<name>.*?)(?:\s+-)?(?:\s+(?P<date>\d{4}-\d{2}-\d{2}))?(?P<tags>(?:\s+\[[^]]*?])*)\s*$")
|
||||
|
||||
tag_regex = re.compile(r'\[(?P<tag>[^]]*?)]')
|
||||
_tag_regex = re.compile(r'\[(?P<tag>[^]]*?)]')
|
||||
|
||||
def __init__(self, name: str = 'Unreleased',
|
||||
date: Optional[datetime.date] = None, tags: Optional[List[str]] = None,
|
||||
link: Optional[str] = None, link_id: Optional[str] = None, line_no: Optional[int] = None):
|
||||
"""
|
||||
Create a new version entry
|
||||
|
||||
:param str name: The version's name
|
||||
:param date: When the version was released
|
||||
:param Optional[datetime.date] date: When the version was released
|
||||
:param tags: The version's tags
|
||||
:param link: The version's URL
|
||||
:param link_id: The version's link ID
|
||||
:param line_no What line in the original file the version starts on
|
||||
:param line_no: What line in the original file the version starts on
|
||||
"""
|
||||
|
||||
self.name: str = name
|
||||
@ -67,7 +70,7 @@ class VersionEntry:
|
||||
"""The version's link ID, uses the version name by default when writing"""
|
||||
|
||||
self.line_no: Optional[int] = line_no
|
||||
"""What line the version occurs at in the file, or None if the version was not read from a file.
|
||||
"""What line the version occurs at in the file, or `None` if the version was not read from a file.
|
||||
This is not guaranteed to be correct after the changelog has been modified,
|
||||
and it has no effect on the written file"""
|
||||
|
||||
@ -86,7 +89,7 @@ class VersionEntry:
|
||||
"""
|
||||
version = cls(line_no=line_no)
|
||||
|
||||
match = cls.header_regex.match(header)
|
||||
match = cls._header_regex.match(header)
|
||||
assert match, f'failed to parse version header: "{header}"'
|
||||
|
||||
version.name, version.link, version.link_id = markdown.strip_link(match['name'])
|
||||
@ -98,7 +101,7 @@ class VersionEntry:
|
||||
return cls(name=header.lstrip('#').strip(), line_no=line_no)
|
||||
|
||||
if match['tags']:
|
||||
version.tags = [m['tag'].upper() for m in cls.tag_regex.finditer(match['tags'])]
|
||||
version.tags = [m['tag'].upper() for m in cls._tag_regex.finditer(match['tags'])]
|
||||
|
||||
return version
|
||||
|
||||
@ -200,11 +203,13 @@ class VersionEntry:
|
||||
return contents
|
||||
|
||||
@property
|
||||
def released(self):
|
||||
def released(self) -> bool:
|
||||
"""Returns true if a PEP440 version number is present in the version name, and has no prerelease segments"""
|
||||
return yaclog.version.is_release(self.name)
|
||||
|
||||
@property
|
||||
def version(self):
|
||||
"""Returns the PEP440 version number from the version name, or `None` if none is found"""
|
||||
return yaclog.version.extract_version(self.name)[0]
|
||||
|
||||
def __str__(self) -> str:
|
||||
@ -216,7 +221,7 @@ class Changelog:
|
||||
|
||||
def __init__(self, path=None, header: str = default_header):
|
||||
"""
|
||||
Create a new changelog object. Contents will be automatically read from disk if the file exists
|
||||
Contents will be automatically read from disk if the file exists
|
||||
|
||||
:param path: The changelog's path on disk
|
||||
:param header: The header at the top of the changelog to use if the file does not exist
|
||||
@ -230,7 +235,7 @@ class Changelog:
|
||||
self.versions: List[VersionEntry] = []
|
||||
"""A list of versions in the changelog"""
|
||||
|
||||
self.links = {}
|
||||
self.links: Dict[str, str] = {}
|
||||
"""Link IDs at the end of the changelog"""
|
||||
|
||||
if path and os.path.exists(path):
|
||||
@ -339,12 +344,12 @@ class Changelog:
|
||||
Get the current version from the changelog
|
||||
|
||||
:param released: if the returned version should be a released version,
|
||||
an unreleased version, or ``None`` to return the most recent
|
||||
an unreleased version, or `None` to return the most recent
|
||||
:param new_version: if a new version should be created if none exist.
|
||||
:param new_version_name: The name of the version to create if there
|
||||
are no matches and ``new_version`` is True.
|
||||
:return: The current version matching the criteria,
|
||||
or None if ``new_version`` is disabled and none are found.
|
||||
or `None` if ``new_version`` is disabled and none are found.
|
||||
"""
|
||||
|
||||
# return the first version that matches `released`
|
||||
@ -365,7 +370,7 @@ class Changelog:
|
||||
"""
|
||||
Get a version from the changelog
|
||||
|
||||
:param name: The name of the version to get, or ``None`` to return the most recent
|
||||
:param name: The name of the version to get, or `None` to return the most recent
|
||||
:return: The first version with the selected name
|
||||
"""
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
"""
|
||||
Tools for parsing and manipulating markdown, including a very basic tokenizer.
|
||||
"""
|
||||
|
||||
# yaclog: yet another changelog tool
|
||||
# Copyright (c) 2021. Andrew Cassidy
|
||||
#
|
||||
@ -13,6 +17,7 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import re
|
||||
from typing import List
|
||||
|
||||
@ -31,23 +36,23 @@ setext_h1_replace_regex = re.compile(r'(?<=\n)(?P<header>[^\n]+?)\n=+[ \t]*(?=\n
|
||||
setext_h2_replace_regex = re.compile(r'(?<=\n)(?P<header>[^\n]+?)\n-+[ \t]*(?=\n)')
|
||||
|
||||
|
||||
def strip_link(token):
|
||||
def strip_link(text):
|
||||
"""
|
||||
Parses and removes any links from the token
|
||||
Parses and removes any links from the input string
|
||||
|
||||
:param token: An input token which may be a markdown link, either literal or an ID
|
||||
:return: A tuple of (name, url, id)
|
||||
:param text: An input string which may be a markdown link, either literal or an ID
|
||||
:return: A tuple of (name, url, id). If the input is not a link, it is returned verbatim as the name.
|
||||
"""
|
||||
|
||||
if link_lit := link_lit_regex.fullmatch(token):
|
||||
if link_lit := link_lit_regex.fullmatch(text):
|
||||
# in the form [name](link)
|
||||
return link_lit['text'], link_lit['link'], None
|
||||
|
||||
if link_def := link_def_regex.fullmatch(token):
|
||||
if link_def := link_def_regex.fullmatch(text):
|
||||
# in the form [name][id] where id is hopefully linked somewhere else in the document
|
||||
return link_def['text'], None, link_def['link_id'].lower()
|
||||
|
||||
return token, None, None
|
||||
return text, None, None
|
||||
|
||||
|
||||
def join(segments: List[str]) -> str:
|
||||
@ -76,10 +81,17 @@ def join(segments: List[str]) -> str:
|
||||
|
||||
|
||||
class Token:
|
||||
"""A single tokenized block of markdown, consisting of one or more lines of text."""
|
||||
|
||||
def __init__(self, line_no: int, lines: List[str], kind: str):
|
||||
self.line_no = line_no
|
||||
"""Which line this block appears on in the original file"""
|
||||
|
||||
self.lines = lines
|
||||
"""The lines of text making up this block"""
|
||||
|
||||
self.kind = kind
|
||||
"""What kind of token this is. One of ``h[1-6]``, ``p``, ``li`` or ``code``"""
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.kind}: {self.lines}'
|
||||
@ -93,7 +105,7 @@ def tokenize(text: str):
|
||||
(Headers, top-level list items, links, code blocks, paragraphs).
|
||||
|
||||
:param text: input text to tokenize
|
||||
:return: A list of tokens
|
||||
:return: A list of tokens and a dictionary of links
|
||||
"""
|
||||
|
||||
# convert setext-style headers
|
||||
|
@ -1,3 +1,8 @@
|
||||
"""
|
||||
Various helper functions for analyzing and manipulating PEP440 version numbers,
|
||||
meant to augment the `packaging.version` module.
|
||||
"""
|
||||
|
||||
# yaclog: yet another changelog tool
|
||||
# Copyright (c) 2021. Andrew Cassidy
|
||||
#
|
||||
|
Loading…
Reference in New Issue
Block a user