webifier 0.1.20__tar.gz → 1.0.2__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.
Files changed (67) hide show
  1. webifier-1.0.2/.github/workflows/python-publish.yml +49 -0
  2. webifier-1.0.2/.gitignore +168 -0
  3. webifier-1.0.2/PKG-INFO +129 -0
  4. webifier-1.0.2/README.md +98 -0
  5. webifier-1.0.2/action.yml +46 -0
  6. webifier-1.0.2/pyproject.toml +81 -0
  7. webifier-1.0.2/tests/test_extensions.py +374 -0
  8. webifier-1.0.2/webifier/__init__.py +21 -0
  9. webifier-1.0.2/webifier/_version.py +24 -0
  10. webifier-1.0.2/webifier/core/__init__.py +15 -0
  11. webifier-1.0.2/webifier/core/base.py +229 -0
  12. webifier-1.0.2/webifier/core/builder.py +642 -0
  13. webifier-1.0.2/webifier/core/extensions.py +440 -0
  14. webifier-1.0.2/webifier/core/frontmatter.py +25 -0
  15. webifier-1.0.2/webifier/core/html.py +130 -0
  16. webifier-1.0.2/webifier/core/loader.py +286 -0
  17. webifier-1.0.2/webifier/core/markdown.py +32 -0
  18. webifier-1.0.2/webifier/interface/__init__.py +27 -0
  19. webifier-1.0.2/webifier/interface/cli.py +78 -0
  20. webifier-1.0.2/webifier/interface/io.py +199 -0
  21. webifier-1.0.2/webifier/interface/resolvers/__init__.py +128 -0
  22. webifier-1.0.2/webifier/interface/resolvers/base.py +74 -0
  23. webifier-1.0.2/webifier/interface/resolvers/builtins.py +269 -0
  24. webifier-1.0.2/webifier/interface/resolvers/engine.py +127 -0
  25. webifier-1.0.2/webifier/interface/resolvers/utils.py +128 -0
  26. webifier-0.1.20/PKG-INFO +0 -130
  27. webifier-0.1.20/README.md +0 -114
  28. webifier-0.1.20/setup.cfg +0 -4
  29. webifier-0.1.20/setup.py +0 -39
  30. webifier-0.1.20/webifier/__init__.py +0 -0
  31. webifier-0.1.20/webifier/__version__.py +0 -1
  32. webifier-0.1.20/webifier/build/__init__.py +0 -1
  33. webifier-0.1.20/webifier/build/builder.py +0 -536
  34. webifier-0.1.20/webifier/build/content.py +0 -98
  35. webifier-0.1.20/webifier/build/html.py +0 -53
  36. webifier-0.1.20/webifier/build/io_utils.py +0 -225
  37. webifier-0.1.20/webifier/build/jekyll.py +0 -38
  38. webifier-0.1.20/webifier/build/md.py +0 -25
  39. webifier-0.1.20/webifier/build/notebook.py +0 -37
  40. webifier-0.1.20/webifier/jekyll/_includes/chapters.html +0 -36
  41. webifier-0.1.20/webifier/jekyll/_includes/comments.html +0 -12
  42. webifier-0.1.20/webifier/jekyll/_includes/footer.html +0 -25
  43. webifier-0.1.20/webifier/jekyll/_includes/head.html +0 -69
  44. webifier-0.1.20/webifier/jekyll/_includes/header.html +0 -29
  45. webifier-0.1.20/webifier/jekyll/_includes/link.html +0 -119
  46. webifier-0.1.20/webifier/jekyll/_includes/links.html +0 -16
  47. webifier-0.1.20/webifier/jekyll/_includes/meta.html +0 -9
  48. webifier-0.1.20/webifier/jekyll/_includes/nav.html +0 -77
  49. webifier-0.1.20/webifier/jekyll/_includes/people.html +0 -21
  50. webifier-0.1.20/webifier/jekyll/_includes/person.html +0 -96
  51. webifier-0.1.20/webifier/jekyll/_includes/search.html +0 -51
  52. webifier-0.1.20/webifier/jekyll/_includes/toc.html +0 -164
  53. webifier-0.1.20/webifier/jekyll/_layouts/content.html +0 -38
  54. webifier-0.1.20/webifier/jekyll/_layouts/home.html +0 -26
  55. webifier-0.1.20/webifier/jekyll/assets/css/codehilite.css +0 -74
  56. webifier-0.1.20/webifier/jekyll/assets/css/jupyter.css +0 -12181
  57. webifier-0.1.20/webifier/jekyll/assets/css/main.css +0 -62
  58. webifier-0.1.20/webifier/jekyll/assets/images/colab-badge.svg +0 -1
  59. webifier-0.1.20/webifier/jekyll/search.json +0 -13
  60. webifier-0.1.20/webifier/main.py +0 -43
  61. webifier-0.1.20/webifier.egg-info/PKG-INFO +0 -130
  62. webifier-0.1.20/webifier.egg-info/SOURCES.txt +0 -40
  63. webifier-0.1.20/webifier.egg-info/dependency_links.txt +0 -1
  64. webifier-0.1.20/webifier.egg-info/entry_points.txt +0 -3
  65. webifier-0.1.20/webifier.egg-info/requires.txt +0 -8
  66. webifier-0.1.20/webifier.egg-info/top_level.txt +0 -1
  67. {webifier-0.1.20 → webifier-1.0.2}/LICENSE +0 -0
@@ -0,0 +1,49 @@
1
+ name: Upload Python Package
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ release:
8
+ types: [created]
9
+ workflow_dispatch:
10
+
11
+ jobs:
12
+ deploy:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ with:
17
+ fetch-depth: 0
18
+
19
+ - name: Set up Python
20
+ uses: actions/setup-python@v5
21
+ with:
22
+ python-version: "3.12"
23
+
24
+ - name: Install dependencies
25
+ run: |
26
+ python -m pip install --upgrade pip
27
+ python -m pip install build twine
28
+
29
+ - name: Verify release tag
30
+ run: |
31
+ TAG="$(git describe --tags --exact-match)"
32
+ case "$TAG" in
33
+ v[0-9]*)
34
+ echo "Publishing $TAG"
35
+ ;;
36
+ *)
37
+ echo "Refusing to publish from non-release tag: $TAG"
38
+ exit 1
39
+ ;;
40
+ esac
41
+
42
+ - name: Build and publish
43
+ env:
44
+ TWINE_USERNAME: __token__
45
+ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
46
+ run: |
47
+ python -m build --sdist --wheel
48
+ python -m twine check dist/*
49
+ python -m twine upload dist/*
@@ -0,0 +1,168 @@
1
+ **/.DS_Store
2
+
3
+ # Generated by hatch-vcs at build time
4
+ webifier/_version.py
5
+
6
+
7
+ # Created by https://www.toptal.com/developers/gitignore/api/python,jupyternotebooks
8
+ # Edit at https://www.toptal.com/developers/gitignore?templates=python,jupyternotebooks
9
+
10
+ ### JupyterNotebooks ###
11
+ # gitignore template for Jupyter Notebooks
12
+ # website: http://jupyter.org/
13
+
14
+ .ipynb_checkpoints
15
+ */.ipynb_checkpoints/*
16
+
17
+ # IPython
18
+ profile_default/
19
+ ipython_config.py
20
+
21
+ # Remove previous ipynb_checkpoints
22
+ # git rm -r .ipynb_checkpoints/
23
+
24
+ ### Python ###
25
+ # Byte-compiled / optimized / DLL files
26
+ __pycache__/
27
+ *.py[cod]
28
+ *$py.class
29
+
30
+ # C extensions
31
+ *.so
32
+
33
+ # Distribution / packaging
34
+ .Python
35
+ develop-eggs/
36
+ dist/
37
+ downloads/
38
+ eggs/
39
+ .eggs/
40
+ parts/
41
+ sdist/
42
+ var/
43
+ wheels/
44
+ pip-wheel-metadata/
45
+ share/python-wheels/
46
+ *.egg-info/
47
+ .installed.cfg
48
+ *.egg
49
+ MANIFEST
50
+
51
+ # PyInstaller
52
+ # Usually these files are written by a python script from a template
53
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
54
+ *.manifest
55
+ *.spec
56
+
57
+ # Installer logs
58
+ pip-log.txt
59
+ pip-delete-this-directory.txt
60
+
61
+ # Unit test / coverage reports
62
+ htmlcov/
63
+ .tox/
64
+ .nox/
65
+ .coverage
66
+ .coverage.*
67
+ .cache
68
+ nosetests.xml
69
+ coverage.xml
70
+ *.cover
71
+ *.py,cover
72
+ .hypothesis/
73
+ .pytest_cache/
74
+ .ruff_cache/
75
+ pytestdebug.log
76
+
77
+ # Translations
78
+ *.mo
79
+ *.pot
80
+
81
+ # Django stuff:
82
+ *.log
83
+ local_settings.py
84
+ db.sqlite3
85
+ db.sqlite3-journal
86
+
87
+ # Flask stuff:
88
+ instance/
89
+ .webassets-cache
90
+
91
+ # Scrapy stuff:
92
+ .scrapy
93
+
94
+ # Sphinx documentation
95
+ docs/_build/
96
+ doc/_build/
97
+
98
+ # PyBuilder
99
+ target/
100
+
101
+ # Jupyter Notebook
102
+
103
+ # IPython
104
+
105
+ # pyenv
106
+ .python-version
107
+
108
+ # pipenv
109
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
110
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
111
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
112
+ # install all needed dependencies.
113
+ #Pipfile.lock
114
+
115
+ # poetry
116
+ #poetry.lock
117
+
118
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
119
+ __pypackages__/
120
+
121
+ # Celery stuff
122
+ celerybeat-schedule
123
+ celerybeat.pid
124
+
125
+ # SageMath parsed files
126
+ *.sage.py
127
+
128
+ # Environments
129
+ # .env
130
+ .env/
131
+ .venv/
132
+ env/
133
+ venv/
134
+ ENV/
135
+ env.bak/
136
+ venv.bak/
137
+ pythonenv*
138
+
139
+ # Spyder project settings
140
+ .spyderproject
141
+ .spyproject
142
+
143
+ # Rope project settings
144
+ .ropeproject
145
+
146
+ # mkdocs documentation
147
+ /site
148
+
149
+ # mypy
150
+ .mypy_cache/
151
+ .dmypy.json
152
+ dmypy.json
153
+
154
+ # Pyre type checker
155
+ .pyre/
156
+
157
+ # pytype static type analyzer
158
+ .pytype/
159
+
160
+ # operating system-related files
161
+ *.DS_Store #file properties cache/storage on macOS
162
+ Thumbs.db #thumbnail cache on Windows
163
+
164
+ # profiling data
165
+ .prof
166
+
167
+
168
+ # End of https://www.toptal.com/developers/gitignore/api/python,jupyternotebooks
@@ -0,0 +1,129 @@
1
+ Metadata-Version: 2.4
2
+ Name: webifier
3
+ Version: 1.0.2
4
+ Summary: Cook up a fully functional static website from YAML and Markdown.
5
+ Project-URL: Homepage, https://github.com/webifier/build
6
+ Project-URL: Repository, https://github.com/webifier/build
7
+ Project-URL: Issues, https://github.com/webifier/build/issues
8
+ Author-email: Vahid Zehtab <contact@vahidz.com>, Ahmad Salimi <ahsa9978@gmail.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: jinja2,jupyter notebook,markdown,static site,webifier
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Requires-Python: >=3.10
21
+ Requires-Dist: beautifulsoup4
22
+ Requires-Dist: jinja2<3.2,>=3.0
23
+ Requires-Dist: markdown
24
+ Requires-Dist: pygments
25
+ Requires-Dist: pyyaml
26
+ Requires-Dist: webifier-extensions>=1.0.4
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest; extra == 'dev'
29
+ Requires-Dist: ruff; extra == 'dev'
30
+ Description-Content-Type: text/markdown
31
+
32
+ # Webifier
33
+
34
+ [![Docs](https://img.shields.io/badge/docs-webifier.github.io-blue)](https://webifier.github.io/)
35
+ [![PyPI](https://img.shields.io/pypi/v/webifier.svg)](https://pypi.org/project/webifier/)
36
+ [![Python Package](https://github.com/webifier/build/actions/workflows/python-publish.yml/badge.svg)](https://github.com/webifier/build/actions/workflows/python-publish.yml)
37
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
38
+
39
+ Webifier turns YAML, Markdown, HTML, notebooks, and other static content into a
40
+ static website. It is meant to remove the publishing overhead from personal
41
+ projects, research notes, notebooks, reports, and evolving documentation: decide
42
+ what content goes where, commit it, and let Webifier build a navigable site.
43
+
44
+ The core package stays small: config loading, page discovery, rendering,
45
+ extension loading, hooks, template resolution, and asset copying. First-party
46
+ renderers, templates, themes, search, comments, notebooks, and resume sections
47
+ ship as the `webifier-extensions` package, which is installed automatically with
48
+ `webifier`.
49
+
50
+ ## Install
51
+
52
+ ```shell
53
+ pip install webifier
54
+ ```
55
+
56
+ Documentation and examples live at [webifier.github.io](https://webifier.github.io/).
57
+
58
+ ## Build Locally
59
+
60
+ ```shell
61
+ webify --index index.yml --output webified
62
+ ```
63
+
64
+ For project pages, pass a base URL:
65
+
66
+ ```shell
67
+ webify --baseurl my-repo --index index.yml --output webified
68
+ ```
69
+
70
+ For a root domain or `<user>.github.io` site, use an empty base URL:
71
+
72
+ ```shell
73
+ webify --baseurl "" --index index.yml --output webified
74
+ ```
75
+
76
+ ## Configure Extensions
77
+
78
+ Extensions are enabled explicitly in your site config. The instance name is local
79
+ to your site, and `uses` points to the installed extension implementation.
80
+
81
+ ```yaml
82
+ config:
83
+ webifier:
84
+ extensions:
85
+ site:
86
+ uses: webifier.standard
87
+ markdown:
88
+ uses: webifier.markdown
89
+ notebooks:
90
+ uses: webifier.notebook
91
+ search:
92
+ uses: webifier.search
93
+ theme:
94
+ uses: webifier.theme
95
+ default: system
96
+ comments:
97
+ uses: webifier.comments
98
+ ```
99
+
100
+ Extensions can register renderers, content renderers, templates, themes, assets,
101
+ resolvers, format loaders, hooks, and config defaults. Page-aware hooks can
102
+ inspect page config and page content before injecting assets into the head,
103
+ navigation, footer, or other extension areas.
104
+
105
+ ## GitHub Action
106
+
107
+ ```yaml
108
+ name: Webify
109
+ on:
110
+ push:
111
+ branches: [main]
112
+
113
+ jobs:
114
+ build:
115
+ runs-on: ubuntu-latest
116
+ steps:
117
+ - uses: actions/checkout@v4
118
+ - uses: webifier/build@v1.0.1
119
+ with:
120
+ baseurl: ""
121
+ index: index.yml
122
+ publish_dir: webified
123
+ ```
124
+
125
+ Deploy `webified/` with your preferred static hosting or GitHub Pages action.
126
+
127
+ ## License
128
+
129
+ MIT License.
@@ -0,0 +1,98 @@
1
+ # Webifier
2
+
3
+ [![Docs](https://img.shields.io/badge/docs-webifier.github.io-blue)](https://webifier.github.io/)
4
+ [![PyPI](https://img.shields.io/pypi/v/webifier.svg)](https://pypi.org/project/webifier/)
5
+ [![Python Package](https://github.com/webifier/build/actions/workflows/python-publish.yml/badge.svg)](https://github.com/webifier/build/actions/workflows/python-publish.yml)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
7
+
8
+ Webifier turns YAML, Markdown, HTML, notebooks, and other static content into a
9
+ static website. It is meant to remove the publishing overhead from personal
10
+ projects, research notes, notebooks, reports, and evolving documentation: decide
11
+ what content goes where, commit it, and let Webifier build a navigable site.
12
+
13
+ The core package stays small: config loading, page discovery, rendering,
14
+ extension loading, hooks, template resolution, and asset copying. First-party
15
+ renderers, templates, themes, search, comments, notebooks, and resume sections
16
+ ship as the `webifier-extensions` package, which is installed automatically with
17
+ `webifier`.
18
+
19
+ ## Install
20
+
21
+ ```shell
22
+ pip install webifier
23
+ ```
24
+
25
+ Documentation and examples live at [webifier.github.io](https://webifier.github.io/).
26
+
27
+ ## Build Locally
28
+
29
+ ```shell
30
+ webify --index index.yml --output webified
31
+ ```
32
+
33
+ For project pages, pass a base URL:
34
+
35
+ ```shell
36
+ webify --baseurl my-repo --index index.yml --output webified
37
+ ```
38
+
39
+ For a root domain or `<user>.github.io` site, use an empty base URL:
40
+
41
+ ```shell
42
+ webify --baseurl "" --index index.yml --output webified
43
+ ```
44
+
45
+ ## Configure Extensions
46
+
47
+ Extensions are enabled explicitly in your site config. The instance name is local
48
+ to your site, and `uses` points to the installed extension implementation.
49
+
50
+ ```yaml
51
+ config:
52
+ webifier:
53
+ extensions:
54
+ site:
55
+ uses: webifier.standard
56
+ markdown:
57
+ uses: webifier.markdown
58
+ notebooks:
59
+ uses: webifier.notebook
60
+ search:
61
+ uses: webifier.search
62
+ theme:
63
+ uses: webifier.theme
64
+ default: system
65
+ comments:
66
+ uses: webifier.comments
67
+ ```
68
+
69
+ Extensions can register renderers, content renderers, templates, themes, assets,
70
+ resolvers, format loaders, hooks, and config defaults. Page-aware hooks can
71
+ inspect page config and page content before injecting assets into the head,
72
+ navigation, footer, or other extension areas.
73
+
74
+ ## GitHub Action
75
+
76
+ ```yaml
77
+ name: Webify
78
+ on:
79
+ push:
80
+ branches: [main]
81
+
82
+ jobs:
83
+ build:
84
+ runs-on: ubuntu-latest
85
+ steps:
86
+ - uses: actions/checkout@v4
87
+ - uses: webifier/build@v1.0.1
88
+ with:
89
+ baseurl: ""
90
+ index: index.yml
91
+ publish_dir: webified
92
+ ```
93
+
94
+ Deploy `webified/` with your preferred static hosting or GitHub Pages action.
95
+
96
+ ## License
97
+
98
+ MIT License.
@@ -0,0 +1,46 @@
1
+ name: 'Webifier Build'
2
+ description: 'GitHub Action to build a static website and deploy on github pages'
3
+ author: 'webifier'
4
+ branding:
5
+ color: 'blue'
6
+ icon: 'cloud'
7
+
8
+ inputs:
9
+ repo:
10
+ description: 'GitHub repository of website material (default: $GITHUB_REPOSITORY)'
11
+ default: ${{ github.repository }}
12
+ required: false
13
+ baseurl:
14
+ description: >
15
+ Base URL (slug) of website (default: name of repository). You should set this field to "" if you are using
16
+ Webifier for building a github.io repository itself (in a `<username/organization>.github.io` repository ).
17
+ default: ${{ github.event.repository.name }}
18
+ required: false
19
+ index:
20
+ description: >
21
+ Entry index file (default: index.yml) change this if your entry index file is not named "index.yml" or is not
22
+ located in the root of your repository.
23
+ default: 'index.yml'
24
+ required: false
25
+ templates_dir:
26
+ description: >
27
+ Base directory to lookup custom jinja2 templates in (default: ".").
28
+ default: "."
29
+ required: false
30
+ publish_dir:
31
+ description: >
32
+ Where should the webified results end up (default: "./webified/")
33
+ default: "./webified/"
34
+ required: false
35
+ runs:
36
+ using: "composite"
37
+ steps:
38
+ - uses: actions/setup-python@v5
39
+ with:
40
+ python-version: "3.12"
41
+ - run: python -m pip install --upgrade pip
42
+ shell: bash
43
+ - run: python -m pip install --upgrade webifier webifier-extensions
44
+ shell: bash
45
+ - run: webify --repo-full-name "${{ inputs.repo }}" --baseurl "${{ inputs.baseurl }}" --index ${{ inputs.index }} --output="${{ inputs.publish_dir }}" --templates-dir="${{ inputs.templates_dir }}"
46
+ shell: bash
@@ -0,0 +1,81 @@
1
+ [build-system]
2
+ requires = ["hatchling", "hatch-vcs"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "webifier"
7
+ dynamic = ["version"]
8
+ description = "Cook up a fully functional static website from YAML and Markdown."
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.10"
12
+ authors = [
13
+ { name = "Vahid Zehtab", email = "contact@vahidz.com" },
14
+ { name = "Ahmad Salimi", email = "ahsa9978@gmail.com" },
15
+ ]
16
+ keywords = ["webifier", "jupyter notebook", "markdown", "jinja2", "static site"]
17
+ classifiers = [
18
+ "Development Status :: 3 - Alpha",
19
+ "Intended Audience :: Developers",
20
+ "License :: OSI Approved :: MIT License",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Programming Language :: Python :: 3.13",
26
+ ]
27
+ dependencies = [
28
+ "beautifulsoup4",
29
+ "jinja2>=3.0,<3.2",
30
+ "markdown",
31
+ "pygments",
32
+ "pyyaml",
33
+ "webifier-extensions>=1.0.4",
34
+ ]
35
+
36
+ [project.optional-dependencies]
37
+ dev = [
38
+ "pytest",
39
+ "ruff",
40
+ ]
41
+
42
+ [project.scripts]
43
+ webify = "webifier.interface.cli:main"
44
+
45
+ [project.urls]
46
+ Homepage = "https://github.com/webifier/build"
47
+ Repository = "https://github.com/webifier/build"
48
+ Issues = "https://github.com/webifier/build/issues"
49
+
50
+ # --- Version: single source of truth from git tags ---
51
+ [tool.hatch.version]
52
+ source = "vcs"
53
+
54
+ [tool.hatch.version.raw-options]
55
+ version_scheme = "no-guess-dev"
56
+
57
+ [tool.hatch.build.hooks.vcs]
58
+ version-file = "webifier/_version.py"
59
+
60
+ # --- Include non-Python assets in the wheel ---
61
+ [tool.hatch.build.targets.wheel]
62
+ packages = ["webifier"]
63
+
64
+ [tool.hatch.build.targets.wheel.force-include]
65
+ # Covered by package discovery, but explicit for clarity:
66
+ # all assets (templates, css, images) under webifier/ are included
67
+
68
+ # --- Ruff (replaces flake8 + isort + black) ---
69
+ [tool.ruff]
70
+ target-version = "py310"
71
+ line-length = 120
72
+
73
+ [tool.ruff.lint]
74
+ select = ["E", "F", "I", "UP", "B", "SIM"]
75
+
76
+ [tool.ruff.lint.isort]
77
+ known-first-party = ["webifier"]
78
+
79
+ # --- Pytest ---
80
+ [tool.pytest.ini_options]
81
+ testpaths = ["tests"]