caxton 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.
- caxton-0.1.0/.gitignore +55 -0
- caxton-0.1.0/CHANGELOG.md +27 -0
- caxton-0.1.0/LICENSE +21 -0
- caxton-0.1.0/PKG-INFO +145 -0
- caxton-0.1.0/README.md +119 -0
- caxton-0.1.0/changelog.d/README.md +35 -0
- caxton-0.1.0/pyproject.toml +239 -0
- caxton-0.1.0/scripts/bump_version.py +102 -0
- caxton-0.1.0/scripts/check_api_compatibility.py +55 -0
- caxton-0.1.0/scripts/validate_commits.py +136 -0
- caxton-0.1.0/scripts/validate_files.py +75 -0
- caxton-0.1.0/setup.cfg +56 -0
- caxton-0.1.0/src/caxton/__init__.py +215 -0
- caxton-0.1.0/src/caxton/__version__.py +1 -0
- caxton-0.1.0/src/caxton/_internal/__init__.py +0 -0
- caxton-0.1.0/src/caxton/_internal/aggregation/__init__.py +11 -0
- caxton-0.1.0/src/caxton/_internal/aggregation/execution.py +315 -0
- caxton-0.1.0/src/caxton/_internal/aggregation/keys.py +80 -0
- caxton-0.1.0/src/caxton/_internal/aggregation/matrices.py +308 -0
- caxton-0.1.0/src/caxton/_internal/aggregation/models.py +69 -0
- caxton-0.1.0/src/caxton/_internal/aggregation/tables.py +233 -0
- caxton-0.1.0/src/caxton/_internal/backends/__init__.py +5 -0
- caxton-0.1.0/src/caxton/_internal/backends/_common.py +27 -0
- caxton-0.1.0/src/caxton/_internal/backends/_xlsx_formats.py +112 -0
- caxton-0.1.0/src/caxton/_internal/backends/openpyxl/__init__.py +25 -0
- caxton-0.1.0/src/caxton/_internal/backends/openpyxl/conditional_formats.py +42 -0
- caxton-0.1.0/src/caxton/_internal/backends/openpyxl/extensions.py +105 -0
- caxton-0.1.0/src/caxton/_internal/backends/openpyxl/footers.py +51 -0
- caxton-0.1.0/src/caxton/_internal/backends/openpyxl/native_tables.py +65 -0
- caxton-0.1.0/src/caxton/_internal/backends/openpyxl/package.py +223 -0
- caxton-0.1.0/src/caxton/_internal/backends/openpyxl/renderer.py +98 -0
- caxton-0.1.0/src/caxton/_internal/backends/openpyxl/rows.py +111 -0
- caxton-0.1.0/src/caxton/_internal/backends/openpyxl/styles.py +118 -0
- caxton-0.1.0/src/caxton/_internal/backends/openpyxl/tables.py +32 -0
- caxton-0.1.0/src/caxton/_internal/backends/openpyxl/template_renderer.py +108 -0
- caxton-0.1.0/src/caxton/_internal/backends/openpyxl/template_workbook.py +479 -0
- caxton-0.1.0/src/caxton/_internal/backends/openpyxl/workbook.py +74 -0
- caxton-0.1.0/src/caxton/_internal/backends/xlsxwriter/__init__.py +8 -0
- caxton-0.1.0/src/caxton/_internal/backends/xlsxwriter/conditional_formats.py +41 -0
- caxton-0.1.0/src/caxton/_internal/backends/xlsxwriter/destination.py +81 -0
- caxton-0.1.0/src/caxton/_internal/backends/xlsxwriter/drawings.py +118 -0
- caxton-0.1.0/src/caxton/_internal/backends/xlsxwriter/execution.py +93 -0
- caxton-0.1.0/src/caxton/_internal/backends/xlsxwriter/footers.py +67 -0
- caxton-0.1.0/src/caxton/_internal/backends/xlsxwriter/native_tables.py +67 -0
- caxton-0.1.0/src/caxton/_internal/backends/xlsxwriter/renderer.py +118 -0
- caxton-0.1.0/src/caxton/_internal/backends/xlsxwriter/rows.py +220 -0
- caxton-0.1.0/src/caxton/_internal/backends/xlsxwriter/styles.py +121 -0
- caxton-0.1.0/src/caxton/_internal/backends/xlsxwriter/tables.py +63 -0
- caxton-0.1.0/src/caxton/_internal/backends/xlsxwriter/workbook.py +45 -0
- caxton-0.1.0/src/caxton/_internal/block_paths.py +24 -0
- caxton-0.1.0/src/caxton/_internal/compiler/__init__.py +5 -0
- caxton-0.1.0/src/caxton/_internal/compiler/formula_resolution.py +246 -0
- caxton-0.1.0/src/caxton/_internal/compiler/spreadsheet.py +690 -0
- caxton-0.1.0/src/caxton/_internal/const.py +144 -0
- caxton-0.1.0/src/caxton/_internal/data/__init__.py +9 -0
- caxton-0.1.0/src/caxton/_internal/data/accessors.py +72 -0
- caxton-0.1.0/src/caxton/_internal/data/sources.py +187 -0
- caxton-0.1.0/src/caxton/_internal/formulas.py +140 -0
- caxton-0.1.0/src/caxton/_internal/layout/__init__.py +21 -0
- caxton-0.1.0/src/caxton/_internal/layout/spreadsheet.py +392 -0
- caxton-0.1.0/src/caxton/_internal/normalization/__init__.py +3 -0
- caxton-0.1.0/src/caxton/_internal/normalization/coordinates.py +56 -0
- caxton-0.1.0/src/caxton/_internal/operations.py +204 -0
- caxton-0.1.0/src/caxton/_internal/rendering.py +35 -0
- caxton-0.1.0/src/caxton/_internal/requirements.py +252 -0
- caxton-0.1.0/src/caxton/_internal/resolver.py +248 -0
- caxton-0.1.0/src/caxton/_internal/semantic/__init__.py +3 -0
- caxton-0.1.0/src/caxton/_internal/semantic/evaluator.py +413 -0
- caxton-0.1.0/src/caxton/_internal/shape.py +14 -0
- caxton-0.1.0/src/caxton/_internal/sinks.py +177 -0
- caxton-0.1.0/src/caxton/_internal/templates/__init__.py +17 -0
- caxton-0.1.0/src/caxton/_internal/templates/xlsx.py +406 -0
- caxton-0.1.0/src/caxton/_internal/validation/__init__.py +5 -0
- caxton-0.1.0/src/caxton/_internal/validation/expressions.py +179 -0
- caxton-0.1.0/src/caxton/_internal/validation/features.py +316 -0
- caxton-0.1.0/src/caxton/_internal/validation/formulas.py +303 -0
- caxton-0.1.0/src/caxton/_internal/validation/spreadsheet.py +31 -0
- caxton-0.1.0/src/caxton/_internal/validation/structure.py +183 -0
- caxton-0.1.0/src/caxton/api/__init__.py +155 -0
- caxton-0.1.0/src/caxton/api/columns.py +145 -0
- caxton-0.1.0/src/caxton/api/operations.py +62 -0
- caxton-0.1.0/src/caxton/api/spreadsheet.py +307 -0
- caxton-0.1.0/src/caxton/api/templates.py +76 -0
- caxton-0.1.0/src/caxton/api/xlsx/__init__.py +19 -0
- caxton-0.1.0/src/caxton/core/__init__.py +11 -0
- caxton-0.1.0/src/caxton/core/_values.py +211 -0
- caxton-0.1.0/src/caxton/core/errors/__init__.py +87 -0
- caxton-0.1.0/src/caxton/core/errors/base.py +42 -0
- caxton-0.1.0/src/caxton/core/errors/data.py +136 -0
- caxton-0.1.0/src/caxton/core/errors/rendering.py +58 -0
- caxton-0.1.0/src/caxton/core/errors/validation.py +171 -0
- caxton-0.1.0/src/caxton/core/errors/warnings.py +14 -0
- caxton-0.1.0/src/caxton/core/formatting/__init__.py +59 -0
- caxton-0.1.0/src/caxton/core/formatting/alignment.py +14 -0
- caxton-0.1.0/src/caxton/core/formatting/display.py +160 -0
- caxton-0.1.0/src/caxton/core/formatting/styles.py +364 -0
- caxton-0.1.0/src/caxton/core/ir/__init__.py +51 -0
- caxton-0.1.0/src/caxton/core/ir/base.py +22 -0
- caxton-0.1.0/src/caxton/core/ir/spreadsheet.py +329 -0
- caxton-0.1.0/src/caxton/core/models/__init__.py +140 -0
- caxton-0.1.0/src/caxton/core/models/_operators.py +98 -0
- caxton-0.1.0/src/caxton/core/models/_validation.py +64 -0
- caxton-0.1.0/src/caxton/core/models/columns.py +233 -0
- caxton-0.1.0/src/caxton/core/models/common.py +38 -0
- caxton-0.1.0/src/caxton/core/models/expressions.py +282 -0
- caxton-0.1.0/src/caxton/core/models/formulas.py +302 -0
- caxton-0.1.0/src/caxton/core/models/spreadsheet.py +527 -0
- caxton-0.1.0/src/caxton/core/models/templates.py +115 -0
- caxton-0.1.0/src/caxton/core/protocols/__init__.py +55 -0
- caxton-0.1.0/src/caxton/core/protocols/data.py +49 -0
- caxton-0.1.0/src/caxton/core/protocols/rendering.py +64 -0
- caxton-0.1.0/src/caxton/core/protocols/templates.py +40 -0
- caxton-0.1.0/src/caxton/core/rendering.py +201 -0
- caxton-0.1.0/src/caxton/core/types/__init__.py +27 -0
- caxton-0.1.0/src/caxton/core/types/base.py +37 -0
- caxton-0.1.0/src/caxton/core/types/boolean.py +11 -0
- caxton-0.1.0/src/caxton/core/types/date.py +11 -0
- caxton-0.1.0/src/caxton/core/types/datetime.py +11 -0
- caxton-0.1.0/src/caxton/core/types/decimal.py +11 -0
- caxton-0.1.0/src/caxton/core/types/duration.py +11 -0
- caxton-0.1.0/src/caxton/core/types/integer.py +11 -0
- caxton-0.1.0/src/caxton/core/types/link.py +11 -0
- caxton-0.1.0/src/caxton/core/types/money.py +22 -0
- caxton-0.1.0/src/caxton/core/types/percentage.py +13 -0
- caxton-0.1.0/src/caxton/core/types/text.py +11 -0
- caxton-0.1.0/src/caxton/core/types/time.py +11 -0
- caxton-0.1.0/src/caxton/core/values.py +22 -0
- caxton-0.1.0/src/caxton/errors.py +63 -0
- caxton-0.1.0/src/caxton/py.typed +0 -0
- caxton-0.1.0/src/caxton/testing/__init__.py +102 -0
- caxton-0.1.0/src/caxton/testing/_artifact.py +297 -0
- caxton-0.1.0/src/caxton/testing/_assertions.py +394 -0
- caxton-0.1.0/src/caxton/testing/_diff.py +40 -0
- caxton-0.1.0/src/caxton/testing/_errors.py +13 -0
- caxton-0.1.0/src/caxton/testing/_layout.py +669 -0
- caxton-0.1.0/src/caxton/testing/_snapshots.py +173 -0
- caxton-0.1.0/src/caxton/testing/_spec.py +631 -0
- caxton-0.1.0/src/caxton/testing/_xlsx.py +186 -0
- caxton-0.1.0/src/caxton/testing/strategies.py +160 -0
- caxton-0.1.0/tests/test_benchmark_data_sources.py +78 -0
- caxton-0.1.0/tests/test_benchmark_grouping.py +160 -0
- caxton-0.1.0/tests/test_benchmark_grouping_scaling.py +184 -0
- caxton-0.1.0/tests/test_benchmark_openpyxl.py +191 -0
- caxton-0.1.0/tests/test_coordinates.py +17 -0
- caxton-0.1.0/tests/test_data_sources.py +218 -0
- caxton-0.1.0/tests/test_errors.py +127 -0
- caxton-0.1.0/tests/test_formulas.py +374 -0
- caxton-0.1.0/tests/test_grouping.py +736 -0
- caxton-0.1.0/tests/test_grouping_coverage.py +72 -0
- caxton-0.1.0/tests/test_grouping_regressions.py +318 -0
- caxton-0.1.0/tests/test_package.py +87 -0
- caxton-0.1.0/tests/test_rendering.py +455 -0
- caxton-0.1.0/tests/test_semantic_evaluator.py +305 -0
- caxton-0.1.0/tests/test_semantic_model.py +196 -0
- caxton-0.1.0/tests/test_semantic_types.py +82 -0
- caxton-0.1.0/tests/test_snapshots.py +87 -0
- caxton-0.1.0/tests/test_spreadsheet_blocks.py +294 -0
- caxton-0.1.0/tests/test_spreadsheet_compiler.py +213 -0
- caxton-0.1.0/tests/test_spreadsheet_features.py +498 -0
- caxton-0.1.0/tests/test_strategies.py +17 -0
- caxton-0.1.0/tests/test_streaming.py +251 -0
- caxton-0.1.0/tests/test_templates.py +359 -0
- caxton-0.1.0/tests/test_testing_api.py +429 -0
- caxton-0.1.0/tests/test_xlsx_template_package.py +85 -0
- caxton-0.1.0/tests/types/data_source.py +31 -0
- caxton-0.1.0/tests/types/formulas.py +23 -0
- caxton-0.1.0/tests/types/grouping.py +16 -0
- caxton-0.1.0/tests/types/row_accessor.py +13 -0
- caxton-0.1.0/tests/types/spreadsheet_features.py +37 -0
- caxton-0.1.0/tests/types/templates.py +20 -0
caxton-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Byte-compiled files and caches
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
.pytest_cache/
|
|
5
|
+
.mypy_cache/
|
|
6
|
+
.ruff_cache/
|
|
7
|
+
.tox/
|
|
8
|
+
|
|
9
|
+
# Environments
|
|
10
|
+
.venv/
|
|
11
|
+
venv/
|
|
12
|
+
|
|
13
|
+
# Distribution / packaging
|
|
14
|
+
.Python
|
|
15
|
+
build/
|
|
16
|
+
develop-eggs/
|
|
17
|
+
dist/
|
|
18
|
+
downloads/
|
|
19
|
+
eggs/
|
|
20
|
+
.eggs/
|
|
21
|
+
lib/
|
|
22
|
+
lib64/
|
|
23
|
+
parts/
|
|
24
|
+
sdist/
|
|
25
|
+
var/
|
|
26
|
+
wheels/
|
|
27
|
+
share/python-wheels/
|
|
28
|
+
*.egg-info/
|
|
29
|
+
.installed.cfg
|
|
30
|
+
*.egg
|
|
31
|
+
MANIFEST
|
|
32
|
+
|
|
33
|
+
# PyInstaller
|
|
34
|
+
# Usually these files are written by a python script from a template
|
|
35
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
36
|
+
*.manifest
|
|
37
|
+
*.spec
|
|
38
|
+
|
|
39
|
+
# Documentation
|
|
40
|
+
site/
|
|
41
|
+
.cache/
|
|
42
|
+
|
|
43
|
+
# Coverage
|
|
44
|
+
.coverage
|
|
45
|
+
coverage/
|
|
46
|
+
coverage.xml
|
|
47
|
+
htmlcov/
|
|
48
|
+
|
|
49
|
+
# IDE and operating system files
|
|
50
|
+
.idea/
|
|
51
|
+
.vscode/
|
|
52
|
+
.DS_Store
|
|
53
|
+
|
|
54
|
+
backend/stations.sqlite3
|
|
55
|
+
**/output/**
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
<!-- towncrier release notes start -->
|
|
4
|
+
|
|
5
|
+
## [0.1.0] - 2026-08-19
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
- Add public spreadsheet API with data-source ingestion, semantic types, references, validation, styles, formulas,
|
|
10
|
+
streaming, and direct XLSX output ([#2](https://github.com/dzhalaevd/caxton/issues/2))
|
|
11
|
+
- Add declarative spreadsheet blocks: `title`, `spacer`, `image`, `chart` and the `stack` flow container.
|
|
12
|
+
A sheet now places its blocks sequentially without manual `start_row` arithmetic, explicit `anchor` stays
|
|
13
|
+
available as a layout escape hatch, overlapping placed blocks are rejected during validation, and the
|
|
14
|
+
XlsxWriter backend lowers titles, images and the supported chart
|
|
15
|
+
kinds. ([#3](https://github.com/dzhalaevd/caxton/issues/3))
|
|
16
|
+
- Add grouped reports and pivot matrices with flexible aggregates, typed keys,
|
|
17
|
+
and single-pass buffering. Enforce XLSX bounds and avoid dense sparse
|
|
18
|
+
materialization. ([#4](https://github.com/dzhalaevd/caxton/issues/4))
|
|
19
|
+
- Add a format-independent template specification and a dedicated XLSX template
|
|
20
|
+
route with named-range table targets, styled block repetition, OpenPyXL hooks,
|
|
21
|
+
and pivot package post-processing. ([#5](https://github.com/dzhalaevd/caxton/issues/5))
|
|
22
|
+
|
|
23
|
+
### Documentation
|
|
24
|
+
|
|
25
|
+
- Added a MkDocs documentation site with a Material theme and a mkdocstrings API
|
|
26
|
+
reference, a `docs` dependency group, `docs` and `docs-serve` tox environments, and a
|
|
27
|
+
GitHub Pages deployment workflow that builds with `--strict`. ([#6](https://github.com/dzhalaevd/caxton/issues/6))
|
caxton-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 David Dzhalaev
|
|
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.
|
caxton-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: caxton
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A declarative way to describe files in Python
|
|
5
|
+
Project-URL: Homepage, https://github.com/dzhalaevd/caxton
|
|
6
|
+
Project-URL: Repository, https://github.com/dzhalaevd/caxton
|
|
7
|
+
Project-URL: Issues, https://github.com/dzhalaevd/caxton/issues
|
|
8
|
+
Author: David Dzhalaev
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: declarative,files,validation
|
|
12
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Classifier: Typing :: Typed
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Requires-Dist: openpyxl<4.0,>=3.1.5
|
|
22
|
+
Requires-Dist: xlsxwriter<4.0,>=3.2.9
|
|
23
|
+
Provides-Extra: hypothesis
|
|
24
|
+
Requires-Dist: hypothesis<7.0,>=6.165; extra == 'hypothesis'
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
<div align="center">
|
|
28
|
+
|
|
29
|
+
# Caxton
|
|
30
|
+
|
|
31
|
+
**Declarative document generation for Python**
|
|
32
|
+
|
|
33
|
+
[![Contributors][contributors-shield]][contributors-url]
|
|
34
|
+
[![Forks][forks-shield]][forks-url]
|
|
35
|
+
[![Stars][stars-shield]][stars-url]
|
|
36
|
+
[![Issues][issues-shield]][issues-url]
|
|
37
|
+
|
|
38
|
+
</div>
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
| 🏗️ This project is currently under development and is **not ready for production use**. |
|
|
43
|
+
|------------------------------------------------------------------------------------------|
|
|
44
|
+
|
|
45
|
+
## :mag: About
|
|
46
|
+
|
|
47
|
+
Declarative Python library for describing and generating documents
|
|
48
|
+
from application data. Users define the document structure and semantics, while
|
|
49
|
+
renderers handle output formats and backend-specific details.
|
|
50
|
+
|
|
51
|
+
## :alembic: Built With
|
|
52
|
+
|
|
53
|
+
![Python][python-shield]
|
|
54
|
+
![Excel][excel-shield]
|
|
55
|
+
![uv][uv-shield]
|
|
56
|
+
![wps][wemake-shield]
|
|
57
|
+
|
|
58
|
+
## Quick start
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from caxton import render, sheet, spreadsheet, table, text, write
|
|
62
|
+
|
|
63
|
+
rows = [{"name": "Ada Lovelace"}, {"name": "Grace Hopper"}]
|
|
64
|
+
|
|
65
|
+
report = spreadsheet(
|
|
66
|
+
sheet(
|
|
67
|
+
"People",
|
|
68
|
+
table(
|
|
69
|
+
rows,
|
|
70
|
+
text("name").titled("Name"),
|
|
71
|
+
),
|
|
72
|
+
),
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
result = render(report)
|
|
76
|
+
|
|
77
|
+
write(report, "people.xlsx")
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
More examples are available in the [example projects](example).
|
|
81
|
+
|
|
82
|
+
## :books: Documentation
|
|
83
|
+
|
|
84
|
+
Full documentation is at [dzhalaevd.github.io/caxton](https://dzhalaevd.github.io/caxton/).
|
|
85
|
+
|
|
86
|
+
## :scroll: Licensing
|
|
87
|
+
|
|
88
|
+
- The project is licensed under the [MIT](LICENSE)
|
|
89
|
+
|
|
90
|
+
<div align="center">
|
|
91
|
+
|
|
92
|
+
### Works on Open-Source
|
|
93
|
+
|
|
94
|
+
If you find this project interesting, consider giving it a ⭐
|
|
95
|
+
|
|
96
|
+
</div>
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
[contributors-shield]: https://img.shields.io/github/contributors/dzhalaevd/caxton.svg?style=for-the-badge
|
|
100
|
+
|
|
101
|
+
[contributors-url]: https://github.com/dzhalaevd/caxton/graphs/contributors
|
|
102
|
+
|
|
103
|
+
[forks-shield]: https://img.shields.io/github/forks/dzhalaevd/caxton.svg?style=for-the-badge
|
|
104
|
+
|
|
105
|
+
[forks-url]: https://github.com/dzhalaevd/caxton/network/members
|
|
106
|
+
|
|
107
|
+
[stars-shield]: https://img.shields.io/github/stars/dzhalaevd/caxton.svg?style=for-the-badge
|
|
108
|
+
|
|
109
|
+
[stars-url]: https://github.com/dzhalaevd/caxton/stargazers
|
|
110
|
+
|
|
111
|
+
[issues-shield]: https://img.shields.io/github/issues/dzhalaevd/caxton.svg?style=for-the-badge
|
|
112
|
+
|
|
113
|
+
[issues-url]: https://github.com/dzhalaevd/caxton/issues
|
|
114
|
+
|
|
115
|
+
[python-shield]: https://img.shields.io/badge/python-3670A0?style=for-the-badge&logo=python&logoColor=ffdd54
|
|
116
|
+
|
|
117
|
+
[uv-shield]: https://img.shields.io/badge/uv-%23DE5FE9.svg?style=for-the-badge&logo=uv&logoColor=white
|
|
118
|
+
|
|
119
|
+
[fastapi-shield]: https://img.shields.io/badge/FastAPI-005571.svg?style=for-the-badge&logo=fastapi
|
|
120
|
+
|
|
121
|
+
[sqlalchemy-shield]: https://img.shields.io/badge/sqlalchemy-%23D71F00.svg?style=for-the-badge&logo=sqlalchemy&logoColor=white
|
|
122
|
+
|
|
123
|
+
[pytest-shield]: https://img.shields.io/badge/pytest-%23ffffff.svg?style=for-the-badge&logo=pytest&logoColor=2f9fe3
|
|
124
|
+
|
|
125
|
+
[telegram-shield]: https://img.shields.io/badge/Telegram-2CA5E0?style=for-the-badge&logo=telegram&logoColor=white
|
|
126
|
+
|
|
127
|
+
[react-shield]: https://img.shields.io/badge/react-%2320232a.svg?style=for-the-badge&logo=react&logoColor=%2361DAFB
|
|
128
|
+
|
|
129
|
+
[typescript-shield]: https://img.shields.io/badge/typescript-%23007ACC.svg?style=for-the-badge&logo=typescript&logoColor=white
|
|
130
|
+
|
|
131
|
+
[vite-shield]: https://img.shields.io/badge/vite-%23646CFF.svg?style=for-the-badge&logo=vite&logoColor=white
|
|
132
|
+
|
|
133
|
+
[postgres-shield]: https://img.shields.io/badge/postgres-%23316192.svg?style=for-the-badge&logo=postgresql&logoColor=white
|
|
134
|
+
|
|
135
|
+
[otel-shield]: https://img.shields.io/badge/OpenTelemetry-FFFFFF?style=for-the-badge&logo=opentelemetry&logoColor=black
|
|
136
|
+
|
|
137
|
+
[grafana-shield]: https://img.shields.io/badge/grafana-%23F46800.svg?style=for-the-badge&logo=grafana&logoColor=white
|
|
138
|
+
|
|
139
|
+
[prometheus-shield]: https://img.shields.io/badge/Prometheus-E6522C?style=for-the-badge&logo=Prometheus&logoColor=white
|
|
140
|
+
|
|
141
|
+
[docker-shield]: https://img.shields.io/badge/docker-%230db7ed.svg?style=for-the-badge&logo=docker&logoColor=white
|
|
142
|
+
|
|
143
|
+
[wemake-shield]: https://img.shields.io/badge/Style_WPS-%23000000.svg?style=for-the-badge&logo=python&logoColor=white
|
|
144
|
+
|
|
145
|
+
[excel-shield]: https://img.shields.io/badge/Microsoft_Excel-217346?style=for-the-badge&logo=microsoft-excel&logoColor=white
|
caxton-0.1.0/README.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# Caxton
|
|
4
|
+
|
|
5
|
+
**Declarative document generation for Python**
|
|
6
|
+
|
|
7
|
+
[![Contributors][contributors-shield]][contributors-url]
|
|
8
|
+
[![Forks][forks-shield]][forks-url]
|
|
9
|
+
[![Stars][stars-shield]][stars-url]
|
|
10
|
+
[![Issues][issues-shield]][issues-url]
|
|
11
|
+
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
| 🏗️ This project is currently under development and is **not ready for production use**. |
|
|
17
|
+
|------------------------------------------------------------------------------------------|
|
|
18
|
+
|
|
19
|
+
## :mag: About
|
|
20
|
+
|
|
21
|
+
Declarative Python library for describing and generating documents
|
|
22
|
+
from application data. Users define the document structure and semantics, while
|
|
23
|
+
renderers handle output formats and backend-specific details.
|
|
24
|
+
|
|
25
|
+
## :alembic: Built With
|
|
26
|
+
|
|
27
|
+
![Python][python-shield]
|
|
28
|
+
![Excel][excel-shield]
|
|
29
|
+
![uv][uv-shield]
|
|
30
|
+
![wps][wemake-shield]
|
|
31
|
+
|
|
32
|
+
## Quick start
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from caxton import render, sheet, spreadsheet, table, text, write
|
|
36
|
+
|
|
37
|
+
rows = [{"name": "Ada Lovelace"}, {"name": "Grace Hopper"}]
|
|
38
|
+
|
|
39
|
+
report = spreadsheet(
|
|
40
|
+
sheet(
|
|
41
|
+
"People",
|
|
42
|
+
table(
|
|
43
|
+
rows,
|
|
44
|
+
text("name").titled("Name"),
|
|
45
|
+
),
|
|
46
|
+
),
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
result = render(report)
|
|
50
|
+
|
|
51
|
+
write(report, "people.xlsx")
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
More examples are available in the [example projects](example).
|
|
55
|
+
|
|
56
|
+
## :books: Documentation
|
|
57
|
+
|
|
58
|
+
Full documentation is at [dzhalaevd.github.io/caxton](https://dzhalaevd.github.io/caxton/).
|
|
59
|
+
|
|
60
|
+
## :scroll: Licensing
|
|
61
|
+
|
|
62
|
+
- The project is licensed under the [MIT](LICENSE)
|
|
63
|
+
|
|
64
|
+
<div align="center">
|
|
65
|
+
|
|
66
|
+
### Works on Open-Source
|
|
67
|
+
|
|
68
|
+
If you find this project interesting, consider giving it a ⭐
|
|
69
|
+
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
[contributors-shield]: https://img.shields.io/github/contributors/dzhalaevd/caxton.svg?style=for-the-badge
|
|
74
|
+
|
|
75
|
+
[contributors-url]: https://github.com/dzhalaevd/caxton/graphs/contributors
|
|
76
|
+
|
|
77
|
+
[forks-shield]: https://img.shields.io/github/forks/dzhalaevd/caxton.svg?style=for-the-badge
|
|
78
|
+
|
|
79
|
+
[forks-url]: https://github.com/dzhalaevd/caxton/network/members
|
|
80
|
+
|
|
81
|
+
[stars-shield]: https://img.shields.io/github/stars/dzhalaevd/caxton.svg?style=for-the-badge
|
|
82
|
+
|
|
83
|
+
[stars-url]: https://github.com/dzhalaevd/caxton/stargazers
|
|
84
|
+
|
|
85
|
+
[issues-shield]: https://img.shields.io/github/issues/dzhalaevd/caxton.svg?style=for-the-badge
|
|
86
|
+
|
|
87
|
+
[issues-url]: https://github.com/dzhalaevd/caxton/issues
|
|
88
|
+
|
|
89
|
+
[python-shield]: https://img.shields.io/badge/python-3670A0?style=for-the-badge&logo=python&logoColor=ffdd54
|
|
90
|
+
|
|
91
|
+
[uv-shield]: https://img.shields.io/badge/uv-%23DE5FE9.svg?style=for-the-badge&logo=uv&logoColor=white
|
|
92
|
+
|
|
93
|
+
[fastapi-shield]: https://img.shields.io/badge/FastAPI-005571.svg?style=for-the-badge&logo=fastapi
|
|
94
|
+
|
|
95
|
+
[sqlalchemy-shield]: https://img.shields.io/badge/sqlalchemy-%23D71F00.svg?style=for-the-badge&logo=sqlalchemy&logoColor=white
|
|
96
|
+
|
|
97
|
+
[pytest-shield]: https://img.shields.io/badge/pytest-%23ffffff.svg?style=for-the-badge&logo=pytest&logoColor=2f9fe3
|
|
98
|
+
|
|
99
|
+
[telegram-shield]: https://img.shields.io/badge/Telegram-2CA5E0?style=for-the-badge&logo=telegram&logoColor=white
|
|
100
|
+
|
|
101
|
+
[react-shield]: https://img.shields.io/badge/react-%2320232a.svg?style=for-the-badge&logo=react&logoColor=%2361DAFB
|
|
102
|
+
|
|
103
|
+
[typescript-shield]: https://img.shields.io/badge/typescript-%23007ACC.svg?style=for-the-badge&logo=typescript&logoColor=white
|
|
104
|
+
|
|
105
|
+
[vite-shield]: https://img.shields.io/badge/vite-%23646CFF.svg?style=for-the-badge&logo=vite&logoColor=white
|
|
106
|
+
|
|
107
|
+
[postgres-shield]: https://img.shields.io/badge/postgres-%23316192.svg?style=for-the-badge&logo=postgresql&logoColor=white
|
|
108
|
+
|
|
109
|
+
[otel-shield]: https://img.shields.io/badge/OpenTelemetry-FFFFFF?style=for-the-badge&logo=opentelemetry&logoColor=black
|
|
110
|
+
|
|
111
|
+
[grafana-shield]: https://img.shields.io/badge/grafana-%23F46800.svg?style=for-the-badge&logo=grafana&logoColor=white
|
|
112
|
+
|
|
113
|
+
[prometheus-shield]: https://img.shields.io/badge/Prometheus-E6522C?style=for-the-badge&logo=Prometheus&logoColor=white
|
|
114
|
+
|
|
115
|
+
[docker-shield]: https://img.shields.io/badge/docker-%230db7ed.svg?style=for-the-badge&logo=docker&logoColor=white
|
|
116
|
+
|
|
117
|
+
[wemake-shield]: https://img.shields.io/badge/Style_WPS-%23000000.svg?style=for-the-badge&logo=python&logoColor=white
|
|
118
|
+
|
|
119
|
+
[excel-shield]: https://img.shields.io/badge/Microsoft_Excel-217346?style=for-the-badge&logo=microsoft-excel&logoColor=white
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Changelog fragments
|
|
2
|
+
|
|
3
|
+
Towncrier reads release notes from this directory and renders them into
|
|
4
|
+
`CHANGELOG.md`.
|
|
5
|
+
|
|
6
|
+
Create one fragment per change:
|
|
7
|
+
|
|
8
|
+
```text
|
|
9
|
+
<issue-id>.<type>.md
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Supported types are `breaking`, `feature`, `bugfix`, `doc`, `generation` and
|
|
13
|
+
`ci`. For example: `123.feature.md`.
|
|
14
|
+
|
|
15
|
+
Create a fragment with Towncrier:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
hatch run towncrier create --content "Describe the user-visible change." 123.feature.md
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Use a GitHub issue or pull request number when one exists. Otherwise, prefix a
|
|
22
|
+
short unique identifier with `+`, for example `+typing.bugfix.md`.
|
|
23
|
+
|
|
24
|
+
Preview the next changelog entry without modifying files:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
hatch run changelog-draft
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Build the changelog during a release, using the version from
|
|
31
|
+
`src/caxton/__version__.py`:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
hatch run changelog-build "$(hatch version)"
|
|
35
|
+
```
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling>=1.31,<2.0"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "caxton"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "A declarative way to describe files in Python"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "David Dzhalaev" },
|
|
14
|
+
]
|
|
15
|
+
keywords = ["files", "declarative", "validation"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 2 - Pre-Alpha",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Programming Language :: Python :: 3.13",
|
|
23
|
+
"Programming Language :: Python :: 3.14",
|
|
24
|
+
"Typing :: Typed",
|
|
25
|
+
]
|
|
26
|
+
dependencies = [
|
|
27
|
+
"xlsxwriter>=3.2.9,<4.0",
|
|
28
|
+
"openpyxl>=3.1.5,<4.0",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.optional-dependencies]
|
|
32
|
+
hypothesis = ["hypothesis>=6.165,<7.0"]
|
|
33
|
+
|
|
34
|
+
[project.urls]
|
|
35
|
+
Homepage = "https://github.com/dzhalaevd/caxton"
|
|
36
|
+
Repository = "https://github.com/dzhalaevd/caxton"
|
|
37
|
+
Issues = "https://github.com/dzhalaevd/caxton/issues"
|
|
38
|
+
|
|
39
|
+
[tool.hatch.version]
|
|
40
|
+
path = "src/caxton/__version__.py"
|
|
41
|
+
|
|
42
|
+
[tool.hatch.build.targets.wheel]
|
|
43
|
+
packages = ["src/caxton"]
|
|
44
|
+
|
|
45
|
+
[tool.hatch.build.targets.sdist]
|
|
46
|
+
include = [
|
|
47
|
+
"/LICENSE",
|
|
48
|
+
"/CHANGELOG.md",
|
|
49
|
+
"/README.md",
|
|
50
|
+
"/changelog.d",
|
|
51
|
+
"/pyproject.toml",
|
|
52
|
+
"/setup.cfg",
|
|
53
|
+
"/scripts",
|
|
54
|
+
"/src",
|
|
55
|
+
"/tests",
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
[tool.hatch.envs.default]
|
|
59
|
+
dependency-groups = ["dev"]
|
|
60
|
+
|
|
61
|
+
[tool.hatch.envs.default.scripts]
|
|
62
|
+
lint = "flake8 ."
|
|
63
|
+
typecheck = "mypy"
|
|
64
|
+
test = "pytest {args:tests}"
|
|
65
|
+
docs = "mkdocs build --strict"
|
|
66
|
+
docs-serve = "mkdocs serve {args}"
|
|
67
|
+
api-compatibility = "griffe check --search src caxton {args}"
|
|
68
|
+
check = [
|
|
69
|
+
"flake8 .",
|
|
70
|
+
"mypy",
|
|
71
|
+
"pytest",
|
|
72
|
+
"towncrier build --draft",
|
|
73
|
+
]
|
|
74
|
+
changelog-draft = "towncrier build --draft"
|
|
75
|
+
changelog-build = "towncrier build --yes --version {args}"
|
|
76
|
+
validate-changelog = "python scripts/validate_files.py {args}"
|
|
77
|
+
bump-version = "python scripts/bump_version.py {args}"
|
|
78
|
+
|
|
79
|
+
[tool.pytest.ini_options]
|
|
80
|
+
addopts = "-ra"
|
|
81
|
+
testpaths = ["tests"]
|
|
82
|
+
|
|
83
|
+
[tool.coverage.run]
|
|
84
|
+
branch = true
|
|
85
|
+
source = ["caxton"]
|
|
86
|
+
|
|
87
|
+
[tool.coverage.paths]
|
|
88
|
+
source = [
|
|
89
|
+
"src/caxton",
|
|
90
|
+
"*/.tox/*/lib/python*/site-packages/caxton",
|
|
91
|
+
"*/.tox/*/Lib/site-packages/caxton",
|
|
92
|
+
"*\\.tox\\*\\Lib\\site-packages\\caxton",
|
|
93
|
+
]
|
|
94
|
+
|
|
95
|
+
[tool.coverage.report]
|
|
96
|
+
fail_under = 85
|
|
97
|
+
show_missing = true
|
|
98
|
+
|
|
99
|
+
[tool.deptry]
|
|
100
|
+
known_first_party = ["caxton"]
|
|
101
|
+
|
|
102
|
+
[tool.importlinter]
|
|
103
|
+
root_packages = ["caxton"]
|
|
104
|
+
|
|
105
|
+
[[tool.importlinter.contracts]]
|
|
106
|
+
name = "Core does not depend on orchestration"
|
|
107
|
+
type = "forbidden"
|
|
108
|
+
source_modules = ["caxton.core"]
|
|
109
|
+
forbidden_modules = [
|
|
110
|
+
"caxton.api",
|
|
111
|
+
"caxton._internal",
|
|
112
|
+
"caxton.testing",
|
|
113
|
+
]
|
|
114
|
+
|
|
115
|
+
[[tool.importlinter.contracts]]
|
|
116
|
+
name = "Internal implementation does not depend on public API"
|
|
117
|
+
type = "forbidden"
|
|
118
|
+
source_modules = ["caxton._internal"]
|
|
119
|
+
forbidden_modules = ["caxton.api"]
|
|
120
|
+
|
|
121
|
+
[[tool.importlinter.contracts]]
|
|
122
|
+
name = "Internal spreadsheet pipeline is layered"
|
|
123
|
+
type = "layers"
|
|
124
|
+
layers = [
|
|
125
|
+
"caxton._internal.compiler",
|
|
126
|
+
"caxton._internal.validation",
|
|
127
|
+
"caxton._internal.layout",
|
|
128
|
+
"caxton._internal.aggregation",
|
|
129
|
+
"caxton._internal.semantic",
|
|
130
|
+
"caxton._internal.data",
|
|
131
|
+
]
|
|
132
|
+
|
|
133
|
+
[[tool.importlinter.contracts]]
|
|
134
|
+
name = "Bundled XLSX backends are independent"
|
|
135
|
+
type = "independence"
|
|
136
|
+
modules = [
|
|
137
|
+
"caxton._internal.backends.openpyxl",
|
|
138
|
+
"caxton._internal.backends.xlsxwriter",
|
|
139
|
+
]
|
|
140
|
+
|
|
141
|
+
[dependency-groups]
|
|
142
|
+
build = [
|
|
143
|
+
"twine>=7.0,<8.0",
|
|
144
|
+
]
|
|
145
|
+
coverage = [
|
|
146
|
+
"coverage>=7.15,<8.0",
|
|
147
|
+
]
|
|
148
|
+
dependencies = [
|
|
149
|
+
"deptry>=0.25.1,<0.26",
|
|
150
|
+
]
|
|
151
|
+
docs = [
|
|
152
|
+
"hypothesis>=6.165,<7.0",
|
|
153
|
+
"mkdocs>=1.6,<2.0",
|
|
154
|
+
"mkdocs-material>=9.7,<10.0",
|
|
155
|
+
"mkdocstrings[python]>=1.0,<2.0",
|
|
156
|
+
]
|
|
157
|
+
imports = [
|
|
158
|
+
"import-linter>=2.13,<3.0",
|
|
159
|
+
]
|
|
160
|
+
lint = [
|
|
161
|
+
"flake8>=7.3,<8.0",
|
|
162
|
+
"ruff>=0.16,<0.17",
|
|
163
|
+
"wemake-python-styleguide>=1.7,<2.0",
|
|
164
|
+
]
|
|
165
|
+
maintenance = [
|
|
166
|
+
"griffe>=2.1,<3.0",
|
|
167
|
+
"hatch>=1.17,<2.0",
|
|
168
|
+
"pip>=25,<27",
|
|
169
|
+
"towncrier>=25.8,<26.0",
|
|
170
|
+
]
|
|
171
|
+
pre-commit = [
|
|
172
|
+
"pre-commit>=4.6.1,<5.0",
|
|
173
|
+
]
|
|
174
|
+
test = [
|
|
175
|
+
"hypothesis>=6.165,<7.0",
|
|
176
|
+
"pytest>=9.1,<10.0",
|
|
177
|
+
"pytest-benchmark>=5.2,<6.0",
|
|
178
|
+
"pytest-cov>=7.1,<8.0",
|
|
179
|
+
]
|
|
180
|
+
tox = [
|
|
181
|
+
"tox>=4.52.1,<5.0",
|
|
182
|
+
"tox-uv>=1.29,<2.0",
|
|
183
|
+
]
|
|
184
|
+
typecheck = [
|
|
185
|
+
"mypy>=2.3,<3.0",
|
|
186
|
+
"types-openpyxl>=3.1.5.20260518,<3.2",
|
|
187
|
+
]
|
|
188
|
+
dev = [
|
|
189
|
+
{ include-group = "build" },
|
|
190
|
+
{ include-group = "coverage" },
|
|
191
|
+
{ include-group = "dependencies" },
|
|
192
|
+
{ include-group = "docs" },
|
|
193
|
+
{ include-group = "imports" },
|
|
194
|
+
{ include-group = "lint" },
|
|
195
|
+
{ include-group = "maintenance" },
|
|
196
|
+
{ include-group = "pre-commit" },
|
|
197
|
+
{ include-group = "test" },
|
|
198
|
+
{ include-group = "tox" },
|
|
199
|
+
{ include-group = "typecheck" },
|
|
200
|
+
]
|
|
201
|
+
|
|
202
|
+
[tool.towncrier]
|
|
203
|
+
directory = "changelog.d"
|
|
204
|
+
filename = "CHANGELOG.md"
|
|
205
|
+
issue_format = "[#{issue}](https://github.com/dzhalaevd/caxton/issues/{issue})"
|
|
206
|
+
orphan_prefix = "+"
|
|
207
|
+
start_string = "<!-- towncrier release notes start -->\n"
|
|
208
|
+
title_format = "## [{version}] - {project_date}"
|
|
209
|
+
underlines = ["", "", ""]
|
|
210
|
+
|
|
211
|
+
[[tool.towncrier.type]]
|
|
212
|
+
directory = "breaking"
|
|
213
|
+
name = "Breaking changes"
|
|
214
|
+
showcontent = true
|
|
215
|
+
|
|
216
|
+
[[tool.towncrier.type]]
|
|
217
|
+
directory = "feature"
|
|
218
|
+
name = "Features"
|
|
219
|
+
showcontent = true
|
|
220
|
+
|
|
221
|
+
[[tool.towncrier.type]]
|
|
222
|
+
directory = "bugfix"
|
|
223
|
+
name = "Bug fixes"
|
|
224
|
+
showcontent = true
|
|
225
|
+
|
|
226
|
+
[[tool.towncrier.type]]
|
|
227
|
+
directory = "doc"
|
|
228
|
+
name = "Documentation"
|
|
229
|
+
showcontent = true
|
|
230
|
+
|
|
231
|
+
[[tool.towncrier.type]]
|
|
232
|
+
directory = "generation"
|
|
233
|
+
name = "Code generation"
|
|
234
|
+
showcontent = true
|
|
235
|
+
|
|
236
|
+
[[tool.towncrier.type]]
|
|
237
|
+
directory = "ci"
|
|
238
|
+
name = "CI and tooling"
|
|
239
|
+
showcontent = true
|