Skip to content

Commit ebd16a4

Browse files
fix: Specifications from parents of Sphinx source directory (#264)
* fix: Specifications from parents of source dir If a spec is referenced with `../../../and-so-on/` to access a file from a parent of the Sphinx source directory, the resolved path can be a path that is a parent of the output HTML directory. By replacing the ".." with "dot-dot" in the output of the Sphinx relfn2path function, this fix ensures that the spec is copied correctly to a subdirectory of the output `_static` directory. For example, expect to see `_static/dot-dot/dot-dot/openapi.yaml`. That path would otherwise be a parent of the output HTML. Signed-off-by: Mike McKiernan <[email protected]> * chore: Update version for patch release Signed-off-by: Mike McKiernan <[email protected]> --------- Signed-off-by: Mike McKiernan <[email protected]>
1 parent c6c618e commit ebd16a4

File tree

4 files changed

+40
-3
lines changed

4 files changed

+40
-3
lines changed

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
11
# Changelog
22

3+
## 5.1.1
4+
5+
* Fixed a bug related to referencing a specification from a parent
6+
directory of the Sphinx source directory, such as when documentation
7+
is co-located with source code.
8+
9+
Before this fix, when a specification was several subdirectories
10+
from the documentation, the specification could be copied to
11+
a parent directory of the build HTML output and prevent the display
12+
of the specification.
13+
14+
With this fix, deeply nested specifications (`../../../../openapi.yaml`)
15+
have the `..` values that are parents of the Sphinx source directory
16+
replaced with the text `dot-dot`. This fix ensures that deeply
17+
nested specifications are copied to a subdirectory of the `_static`
18+
directory in the HTML output.
19+
320
## 5.1.0
421

522
* Refactored copying the specification to the HTML output and

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "swagger-plugin-for-sphinx"
7-
version = "5.1.0"
7+
version = "5.1.1"
88
description = "Sphinx plugin which renders a OpenAPI specification with Swagger"
99
authors = [{ name = "Kai Harder", email = "[email protected]" }]
1010
readme = "README.md"

swagger_plugin_for_sphinx/_plugin.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ def run(self) -> list[nodes.Node]:
5959
)
6060

6161
relpath, abspath = self.env.relfn2path(self.arguments[0])
62+
# Use dot-dot to address referencing specs from parents of the Sphinx source directory.
63+
# Otherwise, the spec is copied to a parent of the output directory.
64+
relpath = relpath.replace("..", "dot-dot")
6265
spec = Path(abspath).resolve()
6366
if not spec.exists():
6467
raise ExtensionError(

tests/test_plugin.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,8 @@ def test_custom_urls(
247247
@pytest.mark.parametrize("builder", ["html", "dirhtml"])
248248
def test_subdirs(tmp_path: Path, builder: str) -> None:
249249
docs = tmp_path / "docs"
250+
codedir = tmp_path / "code" # Imitate copying spec from source.
251+
codedir.mkdir(parents=True)
250252
subdir = docs / "subdir"
251253
subsubdir = subdir / "subdirtwo"
252254
subsubdir.mkdir(parents=True)
@@ -258,6 +260,7 @@ def test_subdirs(tmp_path: Path, builder: str) -> None:
258260
build.mkdir()
259261

260262
spec = Path(__file__).parent / "openapi.yml"
263+
shutil.copyfile(str(spec), str(codedir / "openapi.yaml"))
261264
shutil.copyfile(str(spec), str(speconedir / "openapi.yaml"))
262265
shutil.copyfile(str(spec), str(spectwodir / "openapi.yaml"))
263266

@@ -278,7 +281,18 @@ def test_subdirs(tmp_path: Path, builder: str) -> None:
278281
)
279282
two = subsubdir / "two.rst"
280283
two.write_text(
281-
"API Two\n=======\n\n.. swagger-plugin:: ../../api/two/yaml/openapi.yaml\n",
284+
dedent(
285+
"""
286+
API Two
287+
=======
288+
289+
.. swagger-plugin:: ../../api/two/yaml/openapi.yaml
290+
:id: from-docs
291+
292+
.. swagger-plugin:: ../../../code/openapi.yaml
293+
:id: from-code
294+
"""
295+
),
282296
encoding="utf-8",
283297
)
284298

@@ -303,8 +317,10 @@ def test_subdirs(tmp_path: Path, builder: str) -> None:
303317
build / "subdir" / "subdirtwo" / "two.html", encoding="utf-8"
304318
) as file:
305319
html = file.read()
306-
assert "#swagger-ui-container" in html
320+
assert "#from-docs" in html
321+
assert "#from-code" in html
307322
assert "../../_static/api/two/yaml/openapi.yaml" in html
323+
assert "../../_static/dot-dot/code/openapi.yaml" in html
308324

309325
if builder == "dirhtml":
310326
with open(build / "subdir" / "one" / "index.html", encoding="utf-8") as file:
@@ -316,3 +332,4 @@ def test_subdirs(tmp_path: Path, builder: str) -> None:
316332
) as file:
317333
html = file.read()
318334
assert "../../../_static/api/two/yaml/openapi.yaml" in html
335+
assert "../../../_static/dot-dot/code/openapi.yaml" in html

0 commit comments

Comments
 (0)