sphinx-mounts 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.
- sphinx_mounts-0.1.0/LICENSE +21 -0
- sphinx_mounts-0.1.0/PKG-INFO +133 -0
- sphinx_mounts-0.1.0/README.md +100 -0
- sphinx_mounts-0.1.0/pyproject.toml +123 -0
- sphinx_mounts-0.1.0/src/sphinx_mounts/__init__.py +10 -0
- sphinx_mounts-0.1.0/src/sphinx_mounts/config.py +513 -0
- sphinx_mounts-0.1.0/src/sphinx_mounts/extension.py +249 -0
- sphinx_mounts-0.1.0/src/sphinx_mounts/mounter.py +297 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 useblocks
|
|
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.
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sphinx-mounts
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Mount external sources into a Sphinx build without copying or symlinking
|
|
5
|
+
Keywords: sphinx,documentation,mount,bazel,monorepo
|
|
6
|
+
Author-email: team useblocks <info@useblocks.com>
|
|
7
|
+
Maintainer-email: Marco Heinemann <marco.heinemann@useblocks.com>
|
|
8
|
+
Requires-Python: >=3.12,<4
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Framework :: Sphinx :: Extension
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
21
|
+
Classifier: Topic :: Documentation
|
|
22
|
+
Classifier: Topic :: Documentation :: Sphinx
|
|
23
|
+
Classifier: Topic :: Software Development :: Documentation
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: sphinx>=7.4,<10
|
|
26
|
+
Requires-Dist: ignore-python>=0.3.3
|
|
27
|
+
Project-URL: Changelog, https://github.com/useblocks/sphinx-mounts/blob/main/docs/source/changelog.rst
|
|
28
|
+
Project-URL: Documentation, https://sphinx-mounts.useblocks.com
|
|
29
|
+
Project-URL: Homepage, https://sphinx-mounts.useblocks.com
|
|
30
|
+
Project-URL: Issues, https://github.com/useblocks/sphinx-mounts/issues
|
|
31
|
+
Project-URL: Repository, https://github.com/useblocks/sphinx-mounts
|
|
32
|
+
|
|
33
|
+
# Sphinx Mounts
|
|
34
|
+
|
|
35
|
+
Mount external source trees into a Sphinx build without copying or
|
|
36
|
+
symlinking. Sources stay where they live — for example, a Bazel `bazel-bin/`
|
|
37
|
+
output tree, a sibling repository, or a generated cache directory — and are
|
|
38
|
+
made visible to Sphinx at a configured docname prefix. RST works out of the
|
|
39
|
+
box; Markdown works as soon as `myst-parser` is loaded in the host project;
|
|
40
|
+
any other format a Sphinx parser extension registers is picked up the same
|
|
41
|
+
way.
|
|
42
|
+
|
|
43
|
+
## Features
|
|
44
|
+
|
|
45
|
+
- **No materialization**: sources are read directly from their original
|
|
46
|
+
location. No copy, no symlink, no staging step.
|
|
47
|
+
- **Declarative TOML config**: the mount mapping lives in `ubproject.toml`
|
|
48
|
+
(or any TOML file you name via `mounts_from_toml`). `conf.py` only
|
|
49
|
+
references it.
|
|
50
|
+
- **Language-agnostic & toolable**: because the config is static TOML, IDE
|
|
51
|
+
plugins, language servers, indexers, and build-system integrations
|
|
52
|
+
written in any language can read the same mount mapping that
|
|
53
|
+
`sphinx-build` reads — without having to evaluate `conf.py`.
|
|
54
|
+
- **Toctree auto-wiring**: an optional `attach_to` per mount injects the
|
|
55
|
+
bundle's entry doc into a host toctree at build time, so the host stays
|
|
56
|
+
buildable when a mount is absent (a developer hasn't run the upstream
|
|
57
|
+
build, CI hasn't fetched the bundle).
|
|
58
|
+
- **Self-contained bundles**: each mount is intended to be a
|
|
59
|
+
self-contained tree of `.rst` files with relative links only, so it can
|
|
60
|
+
be reused across host projects. A linter is on the roadmap; the
|
|
61
|
+
convention is not currently enforced.
|
|
62
|
+
|
|
63
|
+
## Quick Start
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
pip install sphinx-mounts
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Add to your `conf.py`:
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
extensions = ["sphinx_mounts"]
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Describe your mounts in `ubproject.toml` next to `conf.py`:
|
|
76
|
+
|
|
77
|
+
```toml
|
|
78
|
+
[[mounts]]
|
|
79
|
+
dir = "/abs/path/to/bazel-bin/docs/api-foo"
|
|
80
|
+
mount_at = "_generated/api-foo"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Reference mounted documents from your host project just like any other doc:
|
|
84
|
+
|
|
85
|
+
```rst
|
|
86
|
+
.. toctree::
|
|
87
|
+
|
|
88
|
+
_generated/api-foo/index
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Why TOML?
|
|
92
|
+
|
|
93
|
+
A `conf.py` is executable Python — only a Python interpreter can read it
|
|
94
|
+
correctly. A TOML file is static data, parseable by every common language.
|
|
95
|
+
Putting the mount mapping in `ubproject.toml` means that any external tool
|
|
96
|
+
(an IDE extension, a documentation indexer, a CI gate, a non-Python build
|
|
97
|
+
system) can resolve cross-references without running Sphinx. The same file
|
|
98
|
+
can also carry sections owned by sibling tools such as [Sphinx-Needs]
|
|
99
|
+
(`[needs]`) and [sphinx-codelinks] (`[codelinks]`), keeping the project's
|
|
100
|
+
documentation configuration in one place.
|
|
101
|
+
|
|
102
|
+
If TOML isn't an option for your setup, the legacy `mounts = [...]` list in
|
|
103
|
+
`conf.py` is still honored as a fallback — see the docs for details.
|
|
104
|
+
|
|
105
|
+
## Related projects
|
|
106
|
+
|
|
107
|
+
- [bazel-drives-sphinx] — a heavier take on Bazel-driven Sphinx
|
|
108
|
+
documentation: Bazel rules declare every RST file (and `needs.json`
|
|
109
|
+
artifact) as a label, and generated per-project targets invoke
|
|
110
|
+
`sphinx-build` on the assembled tree. `sphinx-mounts` is the lightweight
|
|
111
|
+
alternative — Bazel drops generated files under `bazel-bin/`, the
|
|
112
|
+
extension mounts that directory, and Sphinx reads in place. Pick the
|
|
113
|
+
former for fine-grained multi-project rule collection and tag-driven
|
|
114
|
+
variants; pick the latter when "Bazel build, then Sphinx" is enough.
|
|
115
|
+
See `docs/source/bazel.rst` for a side-by-side comparison.
|
|
116
|
+
|
|
117
|
+
## Documentation
|
|
118
|
+
|
|
119
|
+
See `docs/source/` for the full configuration reference and the Bazel
|
|
120
|
+
integration walkthrough. The "Related projects" section in
|
|
121
|
+
`docs/source/index.rst` lists sibling tools ([Sphinx-Needs],
|
|
122
|
+
[sphinx-codelinks], [ubCode], [bazel-drives-sphinx]) that share the
|
|
123
|
+
`ubproject.toml` convention.
|
|
124
|
+
|
|
125
|
+
## License
|
|
126
|
+
|
|
127
|
+
MIT — see [LICENSE](LICENSE).
|
|
128
|
+
|
|
129
|
+
[Sphinx-Needs]: https://sphinx-needs.readthedocs.io/
|
|
130
|
+
[sphinx-codelinks]: https://github.com/useblocks/sphinx-codelinks
|
|
131
|
+
[ubCode]: https://ubcode.useblocks.com/
|
|
132
|
+
[bazel-drives-sphinx]: https://github.com/useblocks/bazel-drives-sphinx
|
|
133
|
+
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Sphinx Mounts
|
|
2
|
+
|
|
3
|
+
Mount external source trees into a Sphinx build without copying or
|
|
4
|
+
symlinking. Sources stay where they live — for example, a Bazel `bazel-bin/`
|
|
5
|
+
output tree, a sibling repository, or a generated cache directory — and are
|
|
6
|
+
made visible to Sphinx at a configured docname prefix. RST works out of the
|
|
7
|
+
box; Markdown works as soon as `myst-parser` is loaded in the host project;
|
|
8
|
+
any other format a Sphinx parser extension registers is picked up the same
|
|
9
|
+
way.
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- **No materialization**: sources are read directly from their original
|
|
14
|
+
location. No copy, no symlink, no staging step.
|
|
15
|
+
- **Declarative TOML config**: the mount mapping lives in `ubproject.toml`
|
|
16
|
+
(or any TOML file you name via `mounts_from_toml`). `conf.py` only
|
|
17
|
+
references it.
|
|
18
|
+
- **Language-agnostic & toolable**: because the config is static TOML, IDE
|
|
19
|
+
plugins, language servers, indexers, and build-system integrations
|
|
20
|
+
written in any language can read the same mount mapping that
|
|
21
|
+
`sphinx-build` reads — without having to evaluate `conf.py`.
|
|
22
|
+
- **Toctree auto-wiring**: an optional `attach_to` per mount injects the
|
|
23
|
+
bundle's entry doc into a host toctree at build time, so the host stays
|
|
24
|
+
buildable when a mount is absent (a developer hasn't run the upstream
|
|
25
|
+
build, CI hasn't fetched the bundle).
|
|
26
|
+
- **Self-contained bundles**: each mount is intended to be a
|
|
27
|
+
self-contained tree of `.rst` files with relative links only, so it can
|
|
28
|
+
be reused across host projects. A linter is on the roadmap; the
|
|
29
|
+
convention is not currently enforced.
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install sphinx-mounts
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Add to your `conf.py`:
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
extensions = ["sphinx_mounts"]
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Describe your mounts in `ubproject.toml` next to `conf.py`:
|
|
44
|
+
|
|
45
|
+
```toml
|
|
46
|
+
[[mounts]]
|
|
47
|
+
dir = "/abs/path/to/bazel-bin/docs/api-foo"
|
|
48
|
+
mount_at = "_generated/api-foo"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Reference mounted documents from your host project just like any other doc:
|
|
52
|
+
|
|
53
|
+
```rst
|
|
54
|
+
.. toctree::
|
|
55
|
+
|
|
56
|
+
_generated/api-foo/index
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Why TOML?
|
|
60
|
+
|
|
61
|
+
A `conf.py` is executable Python — only a Python interpreter can read it
|
|
62
|
+
correctly. A TOML file is static data, parseable by every common language.
|
|
63
|
+
Putting the mount mapping in `ubproject.toml` means that any external tool
|
|
64
|
+
(an IDE extension, a documentation indexer, a CI gate, a non-Python build
|
|
65
|
+
system) can resolve cross-references without running Sphinx. The same file
|
|
66
|
+
can also carry sections owned by sibling tools such as [Sphinx-Needs]
|
|
67
|
+
(`[needs]`) and [sphinx-codelinks] (`[codelinks]`), keeping the project's
|
|
68
|
+
documentation configuration in one place.
|
|
69
|
+
|
|
70
|
+
If TOML isn't an option for your setup, the legacy `mounts = [...]` list in
|
|
71
|
+
`conf.py` is still honored as a fallback — see the docs for details.
|
|
72
|
+
|
|
73
|
+
## Related projects
|
|
74
|
+
|
|
75
|
+
- [bazel-drives-sphinx] — a heavier take on Bazel-driven Sphinx
|
|
76
|
+
documentation: Bazel rules declare every RST file (and `needs.json`
|
|
77
|
+
artifact) as a label, and generated per-project targets invoke
|
|
78
|
+
`sphinx-build` on the assembled tree. `sphinx-mounts` is the lightweight
|
|
79
|
+
alternative — Bazel drops generated files under `bazel-bin/`, the
|
|
80
|
+
extension mounts that directory, and Sphinx reads in place. Pick the
|
|
81
|
+
former for fine-grained multi-project rule collection and tag-driven
|
|
82
|
+
variants; pick the latter when "Bazel build, then Sphinx" is enough.
|
|
83
|
+
See `docs/source/bazel.rst` for a side-by-side comparison.
|
|
84
|
+
|
|
85
|
+
## Documentation
|
|
86
|
+
|
|
87
|
+
See `docs/source/` for the full configuration reference and the Bazel
|
|
88
|
+
integration walkthrough. The "Related projects" section in
|
|
89
|
+
`docs/source/index.rst` lists sibling tools ([Sphinx-Needs],
|
|
90
|
+
[sphinx-codelinks], [ubCode], [bazel-drives-sphinx]) that share the
|
|
91
|
+
`ubproject.toml` convention.
|
|
92
|
+
|
|
93
|
+
## License
|
|
94
|
+
|
|
95
|
+
MIT — see [LICENSE](LICENSE).
|
|
96
|
+
|
|
97
|
+
[Sphinx-Needs]: https://sphinx-needs.readthedocs.io/
|
|
98
|
+
[sphinx-codelinks]: https://github.com/useblocks/sphinx-codelinks
|
|
99
|
+
[ubCode]: https://ubcode.useblocks.com/
|
|
100
|
+
[bazel-drives-sphinx]: https://github.com/useblocks/bazel-drives-sphinx
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "sphinx-mounts"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Mount external sources into a Sphinx build without copying or symlinking"
|
|
5
|
+
authors = [{ name = "team useblocks", email = "info@useblocks.com" }]
|
|
6
|
+
maintainers = [
|
|
7
|
+
{ name = "Marco Heinemann", email = "marco.heinemann@useblocks.com" },
|
|
8
|
+
]
|
|
9
|
+
license = { file = "LICENSE" }
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
requires-python = ">=3.12,<4"
|
|
12
|
+
dependencies = ["sphinx>=7.4,<10", "ignore-python>=0.3.3"]
|
|
13
|
+
keywords = ["sphinx", "documentation", "mount", "bazel", "monorepo"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Framework :: Sphinx :: Extension",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Operating System :: OS Independent",
|
|
20
|
+
"Programming Language :: Python",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Programming Language :: Python :: 3.13",
|
|
25
|
+
"Programming Language :: Python :: 3.14",
|
|
26
|
+
"Topic :: Documentation",
|
|
27
|
+
"Topic :: Documentation :: Sphinx",
|
|
28
|
+
"Topic :: Software Development :: Documentation",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.urls]
|
|
32
|
+
Homepage = "https://sphinx-mounts.useblocks.com"
|
|
33
|
+
Documentation = "https://sphinx-mounts.useblocks.com"
|
|
34
|
+
Repository = "https://github.com/useblocks/sphinx-mounts"
|
|
35
|
+
Issues = "https://github.com/useblocks/sphinx-mounts/issues"
|
|
36
|
+
Changelog = "https://github.com/useblocks/sphinx-mounts/blob/main/docs/source/changelog.rst"
|
|
37
|
+
|
|
38
|
+
[build-system]
|
|
39
|
+
requires = ["flit_core >=3.4,<4"]
|
|
40
|
+
build-backend = "flit_core.buildapi"
|
|
41
|
+
|
|
42
|
+
[dependency-groups]
|
|
43
|
+
dev = ["prek>=0.3.3"]
|
|
44
|
+
testing = [
|
|
45
|
+
"pytest>=8.2.2",
|
|
46
|
+
"pytest-cov>=5.0.0",
|
|
47
|
+
"beautifulsoup4>=4.12",
|
|
48
|
+
# Exercised by the Markdown-mounting test; the extension supports any
|
|
49
|
+
# source suffix Sphinx knows about, so `.md` works whenever the host
|
|
50
|
+
# project loads `myst_parser`.
|
|
51
|
+
"myst-parser>=4.0.0",
|
|
52
|
+
]
|
|
53
|
+
docs = ["furo>=2024.5.6", "myst-parser>=4.0.0", "sphinx-design>=0.6.1"]
|
|
54
|
+
ty = ["ty>=0.0.37"]
|
|
55
|
+
ruff = ["ruff>=0.8.0"]
|
|
56
|
+
|
|
57
|
+
[tool.ruff.lint]
|
|
58
|
+
extend-select = [
|
|
59
|
+
"S",
|
|
60
|
+
"ARG",
|
|
61
|
+
"B", # flake8-bugbear
|
|
62
|
+
"C4", # flake8-comprehensions
|
|
63
|
+
"FURB", # refurb (modernising code)
|
|
64
|
+
"I", # isort
|
|
65
|
+
"ICN", # flake8-import-conventions
|
|
66
|
+
"ISC", # flake8-implicit-str-concat
|
|
67
|
+
"N", # pep8-naming
|
|
68
|
+
"PERF", # perflint (performance anti-patterns)
|
|
69
|
+
"PGH", # pygrep-hooks
|
|
70
|
+
"PIE", # flake8-pie
|
|
71
|
+
"PL", # pylint
|
|
72
|
+
"PTH", # flake8-use-pathlib
|
|
73
|
+
"RUF", # Ruff-specific rules
|
|
74
|
+
"SIM", # flake8-simplify
|
|
75
|
+
"SLF", # private member access
|
|
76
|
+
"UP", # pyupgrade
|
|
77
|
+
"T20", # flake8-print
|
|
78
|
+
]
|
|
79
|
+
extend-ignore = [
|
|
80
|
+
"ISC001", # implicit-str-concat
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
[tool.ruff.lint.isort]
|
|
84
|
+
split-on-trailing-comma = false
|
|
85
|
+
force-sort-within-sections = true
|
|
86
|
+
|
|
87
|
+
[tool.ruff.lint.per-file-ignores]
|
|
88
|
+
"**/tests/*" = [
|
|
89
|
+
"ARG001", # unused-function-argument - fixtures
|
|
90
|
+
"ARG005", # unused-lambda-argument - monkeypatches
|
|
91
|
+
"PLR2004", # magic-value-comparison - valuable for tests
|
|
92
|
+
"S101", # assert - needed for tests
|
|
93
|
+
"S603", # subprocess - bazel invocation in tests
|
|
94
|
+
"S607", # partial-executable-path - bazel by name
|
|
95
|
+
"SLF001", # private-member-access - inspecting Project._docname_to_path
|
|
96
|
+
]
|
|
97
|
+
"src/sphinx_mounts/mounter.py" = [
|
|
98
|
+
"SLF001", # private-member-access - we intentionally write to Project._docname_to_path
|
|
99
|
+
]
|
|
100
|
+
|
|
101
|
+
[tool.ty.src]
|
|
102
|
+
# Only the package source is type-checked. Tests, docs, and build artefacts
|
|
103
|
+
# are skipped — they are not part of the published API surface.
|
|
104
|
+
include = ["src"]
|
|
105
|
+
|
|
106
|
+
[tool.pytest.ini_options]
|
|
107
|
+
testpaths = ["tests"]
|
|
108
|
+
# ``bazel build`` materialises ``tests/example/bazel-*`` convenience symlinks
|
|
109
|
+
# that point into the Bazel execroot. Without this filter, pytest happily
|
|
110
|
+
# walks them and tries to collect ``test_*.py`` from ``bazel_tools`` external
|
|
111
|
+
# repositories — none of which can import in our environment.
|
|
112
|
+
norecursedirs = [
|
|
113
|
+
"bazel-*",
|
|
114
|
+
"*.egg-info",
|
|
115
|
+
".git",
|
|
116
|
+
".tox",
|
|
117
|
+
".venv",
|
|
118
|
+
"build",
|
|
119
|
+
"dist",
|
|
120
|
+
]
|
|
121
|
+
markers = [
|
|
122
|
+
"bazel: tests that require a Bazel installation on PATH (deselect with '-m \"not bazel\"')",
|
|
123
|
+
]
|