rtfc 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rtfc-0.1.0/.github/workflows/ci.yml +130 -0
- rtfc-0.1.0/.github/workflows/lint.yml +83 -0
- rtfc-0.1.0/.gitignore +220 -0
- rtfc-0.1.0/.readthedocs.yml +31 -0
- rtfc-0.1.0/DESIGN.md +188 -0
- rtfc-0.1.0/LICENSE +21 -0
- rtfc-0.1.0/PKG-INFO +122 -0
- rtfc-0.1.0/PLAN.md +16 -0
- rtfc-0.1.0/README.rst +98 -0
- rtfc-0.1.0/changelog/aa9e0244.feature.rtfc +6 -0
- rtfc-0.1.0/changelog/entry.rst.jinja +4 -0
- rtfc-0.1.0/docs/Makefile +23 -0
- rtfc-0.1.0/docs/make.bat +35 -0
- rtfc-0.1.0/docs/source/changelog.rst +8 -0
- rtfc-0.1.0/docs/source/cli.rst +12 -0
- rtfc-0.1.0/docs/source/conf.py +93 -0
- rtfc-0.1.0/docs/source/configuration.rst +185 -0
- rtfc-0.1.0/docs/source/index.rst +19 -0
- rtfc-0.1.0/docs/source/sphinx.rst +54 -0
- rtfc-0.1.0/docs/source/usage.rst +89 -0
- rtfc-0.1.0/prek.toml +20 -0
- rtfc-0.1.0/pyproject.toml +132 -0
- rtfc-0.1.0/src/rtfc/__init__.py +5 -0
- rtfc-0.1.0/src/rtfc/__main__.py +6 -0
- rtfc-0.1.0/src/rtfc/_changelog.py +46 -0
- rtfc-0.1.0/src/rtfc/_cli.py +227 -0
- rtfc-0.1.0/src/rtfc/_config.py +298 -0
- rtfc-0.1.0/src/rtfc/_entry.py +256 -0
- rtfc-0.1.0/src/rtfc/_format/__init__.py +39 -0
- rtfc-0.1.0/src/rtfc/_format/base.py +59 -0
- rtfc-0.1.0/src/rtfc/_format/rst.py +22 -0
- rtfc-0.1.0/src/rtfc/_render/__init__.py +15 -0
- rtfc-0.1.0/src/rtfc/_render/base.py +98 -0
- rtfc-0.1.0/src/rtfc/_render/jinja.py +78 -0
- rtfc-0.1.0/src/rtfc/_validation.py +529 -0
- rtfc-0.1.0/src/rtfc/py.typed +0 -0
- rtfc-0.1.0/src/rtfc/sphinx.py +105 -0
- rtfc-0.1.0/tests/test_changelog.py +65 -0
- rtfc-0.1.0/tests/test_cli.py +231 -0
- rtfc-0.1.0/tests/test_config.py +399 -0
- rtfc-0.1.0/tests/test_entry.py +255 -0
- rtfc-0.1.0/tests/test_format.py +64 -0
- rtfc-0.1.0/tests/test_render.py +259 -0
- rtfc-0.1.0/tests/test_sphinx.py +90 -0
- rtfc-0.1.0/tests/test_validation.py +397 -0
- rtfc-0.1.0/uv.lock +1638 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
name: ci
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
tags:
|
|
8
|
+
- '**'
|
|
9
|
+
pull_request: {}
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
tests:
|
|
16
|
+
name: Run tests with pytest
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
strategy:
|
|
19
|
+
matrix:
|
|
20
|
+
python-version: ['3.11', '3.11', '3.12', '3.13', '3.14', '3.15']
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
23
|
+
with:
|
|
24
|
+
persist-credentials: false
|
|
25
|
+
|
|
26
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
27
|
+
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
28
|
+
with:
|
|
29
|
+
python-version: ${{ matrix.python-version }}
|
|
30
|
+
enable-cache: true # zizmor: ignore[cache-poisoning] (Job does not produce release artifacts and does not have sensitive permissions)
|
|
31
|
+
|
|
32
|
+
- name: Install tox
|
|
33
|
+
run: uv tool install --managed-python --python 3.13 tox --with tox-uv --with tox-gh
|
|
34
|
+
|
|
35
|
+
- name: Install Python ${{ matrix.python-version }}
|
|
36
|
+
run: uv python install --managed-python ${{ matrix.python-version }}
|
|
37
|
+
|
|
38
|
+
- name: Test with tox
|
|
39
|
+
run: tox run
|
|
40
|
+
env:
|
|
41
|
+
TOX_GH_MAJOR_MINOR: ${{ matrix.python-version }}
|
|
42
|
+
UV_PYTHON_DOWNLOADS: never
|
|
43
|
+
|
|
44
|
+
docs:
|
|
45
|
+
name: Build and check documentation
|
|
46
|
+
runs-on: ubuntu-latest
|
|
47
|
+
steps:
|
|
48
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
49
|
+
with:
|
|
50
|
+
persist-credentials: false
|
|
51
|
+
|
|
52
|
+
- name: Set up Python 3.14
|
|
53
|
+
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
54
|
+
with:
|
|
55
|
+
python-version: '3.14'
|
|
56
|
+
|
|
57
|
+
- name: Install dependencies
|
|
58
|
+
run: uv sync --group docs
|
|
59
|
+
|
|
60
|
+
- name: Lint docs with sphinx-lint
|
|
61
|
+
run: |
|
|
62
|
+
uv run sphinx-lint docs
|
|
63
|
+
|
|
64
|
+
- name: Build docs and check the integrity of external links
|
|
65
|
+
run: |
|
|
66
|
+
uv run sphinx-build --builder linkcheck --fail-on-warning "source" "build"
|
|
67
|
+
uv run sphinx-build --builder html --fail-on-warning "source" "build"
|
|
68
|
+
working-directory:
|
|
69
|
+
./docs
|
|
70
|
+
|
|
71
|
+
build:
|
|
72
|
+
name: Build project
|
|
73
|
+
runs-on: ubuntu-latest
|
|
74
|
+
steps:
|
|
75
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
76
|
+
with:
|
|
77
|
+
persist-credentials: false
|
|
78
|
+
|
|
79
|
+
- uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
80
|
+
with:
|
|
81
|
+
enable-cache: false
|
|
82
|
+
|
|
83
|
+
- run: uv sync --no-install-project --only-group build
|
|
84
|
+
|
|
85
|
+
- name: Build library
|
|
86
|
+
run: uv run --no-sync python -m build --installer uv
|
|
87
|
+
|
|
88
|
+
- run: ls -lh dist/
|
|
89
|
+
|
|
90
|
+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
91
|
+
with:
|
|
92
|
+
name: pypi_files
|
|
93
|
+
path: dist
|
|
94
|
+
|
|
95
|
+
release:
|
|
96
|
+
needs: [tests, docs, build]
|
|
97
|
+
runs-on: ubuntu-latest
|
|
98
|
+
if: startsWith(github.ref, 'refs/tags/')
|
|
99
|
+
environment: release
|
|
100
|
+
|
|
101
|
+
permissions:
|
|
102
|
+
id-token: write
|
|
103
|
+
contents: write
|
|
104
|
+
|
|
105
|
+
steps:
|
|
106
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
107
|
+
with:
|
|
108
|
+
persist-credentials: false
|
|
109
|
+
|
|
110
|
+
- uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
111
|
+
with:
|
|
112
|
+
enable-cache: false
|
|
113
|
+
|
|
114
|
+
- run: uv sync --no-install-project --only-group build
|
|
115
|
+
|
|
116
|
+
- name: Get pydantic dist artifacts
|
|
117
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
118
|
+
with:
|
|
119
|
+
name: pypi_files
|
|
120
|
+
path: dist
|
|
121
|
+
|
|
122
|
+
- name: Test artifacts integrity
|
|
123
|
+
run: |
|
|
124
|
+
for whl in dist/*.whl; do unzip -qt "$whl"; done
|
|
125
|
+
uv run --no-sync twine check --strict dist/*
|
|
126
|
+
|
|
127
|
+
- name: Upload package to PyPI
|
|
128
|
+
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
|
|
129
|
+
with:
|
|
130
|
+
packages-dir: dist/
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
name: lint
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
tags:
|
|
8
|
+
- '**'
|
|
9
|
+
pull_request: {}
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
prek:
|
|
16
|
+
name: Run prek pre-commit hooks
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
20
|
+
with:
|
|
21
|
+
persist-credentials: false
|
|
22
|
+
|
|
23
|
+
- uses: j178/prek-action@4e14d07f9231acabce116ccfca13b13dd9755ece # v3.0.0
|
|
24
|
+
|
|
25
|
+
ruff-format:
|
|
26
|
+
name: Check code formatting with Ruff
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
30
|
+
with:
|
|
31
|
+
persist-credentials: false
|
|
32
|
+
|
|
33
|
+
- name: Set up Python 3.14
|
|
34
|
+
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
35
|
+
with:
|
|
36
|
+
python-version: '3.14'
|
|
37
|
+
enable-cache: true # zizmor: ignore[cache-poisoning] (Job does not produce release artifacts and does not have sensitive permissions)
|
|
38
|
+
|
|
39
|
+
- name: Install dependencies
|
|
40
|
+
run: uv sync --group dev
|
|
41
|
+
|
|
42
|
+
- name: Run Ruff formatter
|
|
43
|
+
run: uv run ruff format --diff
|
|
44
|
+
|
|
45
|
+
ruff-check:
|
|
46
|
+
name: Check code linting with Ruff
|
|
47
|
+
runs-on: ubuntu-latest
|
|
48
|
+
steps:
|
|
49
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
50
|
+
with:
|
|
51
|
+
persist-credentials: false
|
|
52
|
+
|
|
53
|
+
- name: Set up Python 3.14
|
|
54
|
+
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
55
|
+
with:
|
|
56
|
+
python-version: '3.14'
|
|
57
|
+
enable-cache: true # zizmor: ignore[cache-poisoning] (Job does not produce release artifacts and does not have sensitive permissions)
|
|
58
|
+
|
|
59
|
+
- name: Install dependencies
|
|
60
|
+
run: uv sync --group dev
|
|
61
|
+
|
|
62
|
+
- name: Run Ruff formatter
|
|
63
|
+
run: uv run ruff check --output-format=github
|
|
64
|
+
|
|
65
|
+
typecheck:
|
|
66
|
+
name: Run typechecking with pyright
|
|
67
|
+
runs-on: ubuntu-latest
|
|
68
|
+
steps:
|
|
69
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
70
|
+
with:
|
|
71
|
+
persist-credentials: false
|
|
72
|
+
|
|
73
|
+
- name: Set up Python 3.14
|
|
74
|
+
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
75
|
+
with:
|
|
76
|
+
python-version: '3.14'
|
|
77
|
+
enable-cache: true # zizmor: ignore[cache-poisoning] (Job does not produce release artifacts and does not have sensitive permissions)
|
|
78
|
+
|
|
79
|
+
- name: Install dependencies
|
|
80
|
+
run: uv sync --group dev
|
|
81
|
+
|
|
82
|
+
- name: Run pyright
|
|
83
|
+
run: uv run pyright
|
rtfc-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[codz]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py.cover
|
|
50
|
+
*.lcov
|
|
51
|
+
.hypothesis/
|
|
52
|
+
.pytest_cache/
|
|
53
|
+
cover/
|
|
54
|
+
|
|
55
|
+
# Translations
|
|
56
|
+
*.mo
|
|
57
|
+
*.pot
|
|
58
|
+
|
|
59
|
+
# Django stuff:
|
|
60
|
+
*.log
|
|
61
|
+
local_settings.py
|
|
62
|
+
db.sqlite3
|
|
63
|
+
db.sqlite3-journal
|
|
64
|
+
|
|
65
|
+
# Flask stuff:
|
|
66
|
+
instance/
|
|
67
|
+
.webassets-cache
|
|
68
|
+
|
|
69
|
+
# Scrapy stuff:
|
|
70
|
+
.scrapy
|
|
71
|
+
|
|
72
|
+
# Sphinx documentation
|
|
73
|
+
docs/_build/
|
|
74
|
+
|
|
75
|
+
# PyBuilder
|
|
76
|
+
.pybuilder/
|
|
77
|
+
target/
|
|
78
|
+
|
|
79
|
+
# Jupyter Notebook
|
|
80
|
+
.ipynb_checkpoints
|
|
81
|
+
|
|
82
|
+
# IPython
|
|
83
|
+
profile_default/
|
|
84
|
+
ipython_config.py
|
|
85
|
+
|
|
86
|
+
# pyenv
|
|
87
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
88
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
89
|
+
# .python-version
|
|
90
|
+
|
|
91
|
+
# pipenv
|
|
92
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
93
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
94
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
95
|
+
# install all needed dependencies.
|
|
96
|
+
# Pipfile.lock
|
|
97
|
+
|
|
98
|
+
# UV
|
|
99
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
100
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
101
|
+
# commonly ignored for libraries.
|
|
102
|
+
# uv.lock
|
|
103
|
+
|
|
104
|
+
# poetry
|
|
105
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
106
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
107
|
+
# commonly ignored for libraries.
|
|
108
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
109
|
+
# poetry.lock
|
|
110
|
+
# poetry.toml
|
|
111
|
+
|
|
112
|
+
# pdm
|
|
113
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
114
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
115
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
116
|
+
# pdm.lock
|
|
117
|
+
# pdm.toml
|
|
118
|
+
.pdm-python
|
|
119
|
+
.pdm-build/
|
|
120
|
+
|
|
121
|
+
# pixi
|
|
122
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
123
|
+
# pixi.lock
|
|
124
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
125
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
126
|
+
.pixi/*
|
|
127
|
+
!.pixi/config.toml
|
|
128
|
+
|
|
129
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
130
|
+
__pypackages__/
|
|
131
|
+
|
|
132
|
+
# Celery stuff
|
|
133
|
+
celerybeat-schedule*
|
|
134
|
+
celerybeat.pid
|
|
135
|
+
|
|
136
|
+
# Redis
|
|
137
|
+
*.rdb
|
|
138
|
+
*.aof
|
|
139
|
+
*.pid
|
|
140
|
+
|
|
141
|
+
# RabbitMQ
|
|
142
|
+
mnesia/
|
|
143
|
+
rabbitmq/
|
|
144
|
+
rabbitmq-data/
|
|
145
|
+
|
|
146
|
+
# ActiveMQ
|
|
147
|
+
activemq-data/
|
|
148
|
+
|
|
149
|
+
# SageMath parsed files
|
|
150
|
+
*.sage.py
|
|
151
|
+
|
|
152
|
+
# Environments
|
|
153
|
+
.env
|
|
154
|
+
.envrc
|
|
155
|
+
.venv
|
|
156
|
+
env/
|
|
157
|
+
venv/
|
|
158
|
+
ENV/
|
|
159
|
+
env.bak/
|
|
160
|
+
venv.bak/
|
|
161
|
+
|
|
162
|
+
# Spyder project settings
|
|
163
|
+
.spyderproject
|
|
164
|
+
.spyproject
|
|
165
|
+
|
|
166
|
+
# Rope project settings
|
|
167
|
+
.ropeproject
|
|
168
|
+
|
|
169
|
+
# mkdocs documentation
|
|
170
|
+
/site
|
|
171
|
+
|
|
172
|
+
# mypy
|
|
173
|
+
.mypy_cache/
|
|
174
|
+
.dmypy.json
|
|
175
|
+
dmypy.json
|
|
176
|
+
|
|
177
|
+
# Pyre type checker
|
|
178
|
+
.pyre/
|
|
179
|
+
|
|
180
|
+
# pytype static type analyzer
|
|
181
|
+
.pytype/
|
|
182
|
+
|
|
183
|
+
# Cython debug symbols
|
|
184
|
+
cython_debug/
|
|
185
|
+
|
|
186
|
+
# PyCharm
|
|
187
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
188
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
189
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
190
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
191
|
+
# .idea/
|
|
192
|
+
|
|
193
|
+
# Abstra
|
|
194
|
+
# Abstra is an AI-powered process automation framework.
|
|
195
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
196
|
+
# Learn more at https://abstra.io/docs
|
|
197
|
+
.abstra/
|
|
198
|
+
|
|
199
|
+
# Visual Studio Code
|
|
200
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
|
201
|
+
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
202
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
|
203
|
+
# you could uncomment the following to ignore the entire vscode folder
|
|
204
|
+
# .vscode/
|
|
205
|
+
# Temporary file for partial code execution
|
|
206
|
+
tempCodeRunnerFile.py
|
|
207
|
+
|
|
208
|
+
# Ruff stuff:
|
|
209
|
+
.ruff_cache/
|
|
210
|
+
|
|
211
|
+
# PyPI configuration file
|
|
212
|
+
.pypirc
|
|
213
|
+
|
|
214
|
+
# Marimo
|
|
215
|
+
marimo/_static/
|
|
216
|
+
marimo/_lsp/
|
|
217
|
+
__marimo__/
|
|
218
|
+
|
|
219
|
+
# Streamlit
|
|
220
|
+
.streamlit/secrets.toml
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# .readthedocs.yaml
|
|
2
|
+
# Read the Docs configuration file
|
|
3
|
+
# See https://docs.readthedocs.com/platform/stable/config-file/v2.html for details
|
|
4
|
+
|
|
5
|
+
# Required
|
|
6
|
+
version: 2
|
|
7
|
+
|
|
8
|
+
# Set the OS, Python version and other tools you might need
|
|
9
|
+
build:
|
|
10
|
+
os: ubuntu-24.04
|
|
11
|
+
tools:
|
|
12
|
+
python: "3.14"
|
|
13
|
+
# https://docs.readthedocs.com/platform/stable/build-customization.html#install-dependencies-with-uv
|
|
14
|
+
jobs:
|
|
15
|
+
pre_create_environment:
|
|
16
|
+
- asdf plugin add uv
|
|
17
|
+
- asdf install uv latest
|
|
18
|
+
- asdf global uv latest
|
|
19
|
+
create_environment:
|
|
20
|
+
- uv venv "${READTHEDOCS_VIRTUALENV_PATH}"
|
|
21
|
+
install:
|
|
22
|
+
- UV_PROJECT_ENVIRONMENT="${READTHEDOCS_VIRTUALENV_PATH}" uv sync --frozen --group docs
|
|
23
|
+
|
|
24
|
+
# Build documentation in the "docs/" directory with Sphinx
|
|
25
|
+
sphinx:
|
|
26
|
+
configuration: docs/source/conf.py
|
|
27
|
+
|
|
28
|
+
# Optionally build your docs in additional formats such as PDF and ePub
|
|
29
|
+
formats:
|
|
30
|
+
- pdf
|
|
31
|
+
- epub
|
rtfc-0.1.0/DESIGN.md
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# rtfc — design plan
|
|
2
|
+
|
|
3
|
+
rtfc ("read the freaking changelog") is a Python tool to manage changelogs and versioning,
|
|
4
|
+
similar in spirit to towncrier. Changelog entries live as individual files in a
|
|
5
|
+
configurable directory and are combined into a changelog document on release.
|
|
6
|
+
Primarily targets Python documentation (sphinx/rst first), but designed to be
|
|
7
|
+
extensible to other formats (e.g. mkdocs markdown).
|
|
8
|
+
|
|
9
|
+
Status: draft — iterating.
|
|
10
|
+
|
|
11
|
+
## 1. Entry file format
|
|
12
|
+
|
|
13
|
+
**Decision: TOML frontmatter + raw body.** One file per entry, structured header and
|
|
14
|
+
an **opaque** body, separated by a `+++` delimiter:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
+++
|
|
18
|
+
date = 2025-08-01
|
|
19
|
+
nonce = "k3jf9a"
|
|
20
|
+
section = "bugfix" # optional, may be absent (null)
|
|
21
|
+
|
|
22
|
+
[metadata] # optional, free-form
|
|
23
|
+
gh_issue = 123
|
|
24
|
+
is_backport = true
|
|
25
|
+
+++
|
|
26
|
+
Fix a bug where :meth:`~pydantic.BaseModel.model_dump` would crash on
|
|
27
|
+
recursive references. Multi-line, arbitrary rst — never parsed by rtfc.
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Rationale, vs the alternatives considered:
|
|
31
|
+
|
|
32
|
+
- **Pure TOML/JSON/YAML**: multiline content in TOML (`"""..."""` escaping) or YAML
|
|
33
|
+
(indentation-sensitive block scalars) is annoying to write and review in PRs.
|
|
34
|
+
JSON is a non-starter for humans.
|
|
35
|
+
- **Native `.rst` with docinfo field lists**: bare docutils on a body containing
|
|
36
|
+
sphinx-specific syntax doesn't hard-crash, but emits "Unknown interpreted text
|
|
37
|
+
role" / "Unknown directive type" system messages and mangles the parse. Also
|
|
38
|
+
needs a different metadata convention per docs format, and nested `metadata`
|
|
39
|
+
doesn't map onto rst field lists. Dead end.
|
|
40
|
+
- **TOML frontmatter** gives: real nested mappings for `metadata`, real date types,
|
|
41
|
+
trivial parsing (split on delimiter, `tomllib` the header, keep the rest
|
|
42
|
+
verbatim), and the body stays raw text in the target docs format. The body is
|
|
43
|
+
only ever interpreted by sphinx itself, after assembly into `changelog.rst`.
|
|
44
|
+
|
|
45
|
+
Parsing: split on the delimiter, parse header with `tomllib`, body kept verbatim.
|
|
46
|
+
|
|
47
|
+
Filename: `{nonce}.rtfc` — the nonce (generated by `rtfc new`) guarantees filenames
|
|
48
|
+
can't collide across concurrent PRs. Extension TBD (see open questions); cost of a
|
|
49
|
+
dedicated extension is no editor highlighting for the body.
|
|
50
|
+
|
|
51
|
+
Note: `tomllib` is stdlib from 3.11 — either bump `requires-python` to `>=3.11`
|
|
52
|
+
(recommended for a new tool) or depend on `tomli` for 3.10.
|
|
53
|
+
|
|
54
|
+
## 2. Core data model
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
@dataclass
|
|
58
|
+
class Entry:
|
|
59
|
+
date: date
|
|
60
|
+
nonce: str
|
|
61
|
+
section: str | None # must be a key of configured sections, or None
|
|
62
|
+
metadata: dict[str, Any] # free-form
|
|
63
|
+
content: str # raw body, never parsed
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Validation at load time: mandatory fields present (`date`, `nonce`), `section`
|
|
67
|
+
(if set) exists in config, dates parseable. `rtfc check` runs this in CI.
|
|
68
|
+
|
|
69
|
+
Terminology note: "section" here is what the original brief also called "type"
|
|
70
|
+
(the entry's category: feature, bugfix, ...). Naming TBD.
|
|
71
|
+
|
|
72
|
+
## 3. Configuration
|
|
73
|
+
|
|
74
|
+
Discovery: `rtfc.toml` if present (takes priority), else `[tool.rtfc]` in
|
|
75
|
+
`pyproject.toml`. Loaded into frozen dataclasses (no pydantic dependency needed
|
|
76
|
+
for a tool this size).
|
|
77
|
+
|
|
78
|
+
```toml
|
|
79
|
+
[tool.rtfc]
|
|
80
|
+
directory = "changelog.d"
|
|
81
|
+
changelog = "docs/changelog.rst"
|
|
82
|
+
format = "rst" # entry point name of the format plugin
|
|
83
|
+
|
|
84
|
+
# defaults if omitted; declaration order = output order
|
|
85
|
+
[tool.rtfc.sections.feature]
|
|
86
|
+
label = "Features"
|
|
87
|
+
|
|
88
|
+
[tool.rtfc.sections.bugfix]
|
|
89
|
+
label = "Bug fixes"
|
|
90
|
+
|
|
91
|
+
[tool.rtfc.render]
|
|
92
|
+
sort = ["date", "metadata.gh_issue"] # sort key within a section
|
|
93
|
+
flat = false # true: ignore sections, one flat list
|
|
94
|
+
entry_template = "{{ content }}{% if metadata.gh_issue %} (:gh:`{{ metadata.gh_issue }}`){% endif %}"
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Templating: **Jinja2**, per-entry only. Standard, known from towncrier; inventing a
|
|
98
|
+
mini-language would be worse. The template receives `content`, `date`, `section`,
|
|
99
|
+
`metadata`. Section headers and version headers are produced by the format plugin,
|
|
100
|
+
not templates (version header non-configurable for now: just the version number
|
|
101
|
+
provided on the command line).
|
|
102
|
+
|
|
103
|
+
Entries with `section = None` in sectioned mode: rendered in an unlabeled group
|
|
104
|
+
before the first section (could become configurable later).
|
|
105
|
+
|
|
106
|
+
## 4. Format plugins
|
|
107
|
+
|
|
108
|
+
Small protocol; rst implementation built in; third parties register via the
|
|
109
|
+
`rtfc.formats` entry-point group:
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
class Format(Protocol):
|
|
113
|
+
name: str
|
|
114
|
+
def version_header(self, version: str, date: date) -> str: ... # underlined title for rst
|
|
115
|
+
def section_header(self, label: str) -> str: ...
|
|
116
|
+
def render_entry(self, rendered_text: str) -> str: ... # "- " bullet + indent continuation lines
|
|
117
|
+
def markers(self) -> tuple[str, str]: ... # comment syntax for insertion/unreleased markers
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The plugin never parses entry bodies — it only wraps already-rendered text in
|
|
121
|
+
format-level structure. Keeps a future mkdocs/markdown implementation trivial.
|
|
122
|
+
|
|
123
|
+
## 5. Assembly into the changelog file
|
|
124
|
+
|
|
125
|
+
The changelog file contains an insertion marker (rst comment):
|
|
126
|
+
|
|
127
|
+
```rst
|
|
128
|
+
Changelog
|
|
129
|
+
=========
|
|
130
|
+
|
|
131
|
+
.. rtfc-insert
|
|
132
|
+
|
|
133
|
+
v1.2.0 (2025-07-01)
|
|
134
|
+
-------------------
|
|
135
|
+
...
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
- `rtfc build --version 1.3.0` — collects entries, renders the version block,
|
|
139
|
+
inserts it right after the marker, **deletes** the entry files.
|
|
140
|
+
- `rtfc build --unreleased` — renders the same block titled "Unreleased", wrapped
|
|
141
|
+
in begin/end markers (`.. rtfc-unreleased-start` / `-end`) so re-running
|
|
142
|
+
**replaces** the previous unreleased block idempotently; deletes nothing.
|
|
143
|
+
A release build first removes any existing unreleased block.
|
|
144
|
+
- `--draft` — print to stdout instead of writing (useful in CI and for release
|
|
145
|
+
PR/GitHub-release descriptions).
|
|
146
|
+
|
|
147
|
+
## 6. CLI
|
|
148
|
+
|
|
149
|
+
- `rtfc new [--section bugfix] [--meta gh_issue=123]` — generates nonce + today's
|
|
150
|
+
date, opens `$EDITOR` or takes `--content`.
|
|
151
|
+
- `rtfc build [--version X.Y.Z | --unreleased] [--draft]`
|
|
152
|
+
- `rtfc check` — validate all entries (CI-friendly).
|
|
153
|
+
|
|
154
|
+
Library: argparse, keeping runtime deps at just `jinja2` (+ `tomli` on 3.10).
|
|
155
|
+
Switch to click only if subcommand UX outgrows it.
|
|
156
|
+
|
|
157
|
+
## 7. Future exports (design awareness only)
|
|
158
|
+
|
|
159
|
+
Faithful markdown export (e.g. for GitHub releases) requires sphinx, since
|
|
160
|
+
`` :gh:`123` `` can expand to a link, a section, a table, anything. The
|
|
161
|
+
architecture keeps this open in two ways:
|
|
162
|
+
|
|
163
|
+
- Entries stay structured until the final render, so an exporter can re-render
|
|
164
|
+
from `Entry` objects rather than scraping `changelog.rst`.
|
|
165
|
+
- A future sphinx-based export path can build just the changelog doc through
|
|
166
|
+
sphinx with a text/markdown builder to resolve roles.
|
|
167
|
+
|
|
168
|
+
Nothing in the core needs to change for either — the renderer produces a
|
|
169
|
+
version-block string; writing it into the changelog file is a separate step, so
|
|
170
|
+
"changelog file is the only output" is not baked into the renderer API.
|
|
171
|
+
|
|
172
|
+
## 8. Milestones
|
|
173
|
+
|
|
174
|
+
1. Config loading (`rtfc.toml` / `pyproject.toml`) + entry parser + `Entry`
|
|
175
|
+
model + `check` — pure, easily tested.
|
|
176
|
+
2. rst format plugin + renderer (sections, sorting, Jinja entry template).
|
|
177
|
+
3. File assembly (markers, unreleased replacement, entry deletion) + `build` CLI.
|
|
178
|
+
4. `rtfc new`, docs, polish; entry-point plugin loading.
|
|
179
|
+
|
|
180
|
+
## Open questions
|
|
181
|
+
|
|
182
|
+
1. `section` vs `type` naming for the entry category field.
|
|
183
|
+
2. `.rtfc` extension vs something else for entry files?
|
|
184
|
+
3. Bump to Python ≥3.11 for `tomllib`?
|
|
185
|
+
4. `--unreleased` as a flag on `build` vs a separate command — leaning flag
|
|
186
|
+
(same logic, one code path).
|
|
187
|
+
5. Delimiter: `+++` (Hugo-style, signals TOML) vs `---` (usually implies YAML) —
|
|
188
|
+
leaning `+++`.
|
rtfc-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Victorien
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|