Skip to content

Commit eb9da37

Browse files
committed
Merge branch 'mh-bump-sphinx-py' into mh-schema-validation
2 parents bfaad13 + 087501b commit eb9da37

File tree

11 files changed

+195
-93
lines changed

11 files changed

+195
-93
lines changed

.github/workflows/ci.yaml

+17-10
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,25 @@ jobs:
2323
fail-fast: false # Set on "false" to get the results of ALL builds
2424
matrix:
2525
os: ["ubuntu-latest"]
26-
python-version: ["3.10", "3.12"]
27-
sphinx-version: ["7.0", "8.0"]
26+
python-version: ["3.9", "3.12", "3.13"]
27+
sphinx-version: ["7.4", "8.2"]
2828
include:
29-
- os: "ubuntu-latest"
30-
python-version: "3.9"
31-
sphinx-version: "7.0"
29+
# corner cases for Windows
3230
- os: "windows-latest"
3331
python-version: "3.9"
34-
sphinx-version: "7.0"
32+
sphinx-version: "7.4"
3533
- os: "windows-latest"
3634
python-version: "3.12"
37-
sphinx-version: "8.0"
35+
sphinx-version: "8.2"
36+
- os: "windows-latest"
37+
python-version: "3.13"
38+
sphinx-version: "8.2"
39+
exclude:
40+
# Sphinx 8.2 only supports py3.11+
41+
- os: "ubuntu-latest"
42+
python-version: "3.9"
43+
sphinx-version: "8.2"
44+
3845
steps:
3946
- uses: actions/checkout@v4
4047
- name: Install graphviz (linux)
@@ -75,10 +82,10 @@ jobs:
7582
include:
7683
- os: "ubuntu-latest"
7784
python-version: "3.9"
78-
sphinx-version: "7.0"
85+
sphinx-version: "7.4"
7986
- os: "ubuntu-latest"
80-
python-version: "3.12"
81-
sphinx-version: "8.0"
87+
python-version: "3.13"
88+
sphinx-version: "8.2"
8289
steps:
8390
- uses: actions/checkout@v4
8491
- name: Use Node.js

docs/directives/needimport.rst

+14-6
Original file line numberDiff line numberDiff line change
@@ -26,26 +26,34 @@ The directive argument can be one of the following formats:
2626
- A remote URL from which to download the ``needs.json``:
2727

2828
.. code-block:: rst
29-
29+
3030
.. needimport:: https://my_company.com/docs/remote-needs.json
3131
3232
- A local path relative to the containing document:
3333

3434
.. code-block:: rst
35-
35+
3636
.. needimport:: needs.json
3737
3838
- A local path starting with ``/`` is relative to the Sphinx source directory:
3939

4040
.. code-block:: rst
41-
41+
4242
.. needimport:: /path/to/needs.json
4343
44-
- For an absolute path, make sure to start with two ``//`` (on Linux/OSX):
44+
- For an absolute path on Linux/OSX, make sure to start with two ``//``:
4545

4646
.. code-block:: rst
47-
48-
.. needimport:: //absoulte/path/to/needs.json
47+
48+
.. needimport:: //absolute/path/to/needs.json
49+
50+
- For an absolute path on Windows, just use the normal drive letters with either forward or backward slashes:
51+
52+
.. code-block:: rst
53+
54+
.. needimport:: c:/absolute/path/to/needs.json
55+
56+
.. needimport:: c:\absolute\path\to\needs.json
4957
5058
Options
5159
-------

pyproject.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,14 @@ classifiers = [
2121
'Programming Language :: Python :: 3.10',
2222
'Programming Language :: Python :: 3.11',
2323
'Programming Language :: Python :: 3.12',
24+
'Programming Language :: Python :: 3.13',
2425
'Topic :: Documentation',
2526
'Topic :: Utilities',
2627
'Framework :: Sphinx :: Extension',
2728
]
2829
requires-python = ">=3.9,<4"
2930
dependencies = [
30-
"sphinx>=7.0,<9",
31+
"sphinx>=7.4,<9",
3132
"requests-file~=2.1", # external links
3233
"requests~=2.32", # external links
3334
"jsonschema>=3.2.0", # needsimport schema validation

sphinx_needs/directives/needimport.py

+3-28
Original file line numberDiff line numberDiff line change
@@ -90,34 +90,9 @@ def run(self) -> Sequence[nodes.Node]:
9090
else:
9191
logger.info(f"Importing needs from {need_import_path}")
9292

93-
if not os.path.isabs(need_import_path):
94-
# Relative path should start from current rst file directory
95-
curr_dir = os.path.dirname(self.docname)
96-
new_need_import_path = os.path.join(
97-
self.env.app.srcdir, curr_dir, need_import_path
98-
)
99-
100-
correct_need_import_path = new_need_import_path
101-
if not os.path.exists(new_need_import_path):
102-
# Check the old way that calculates relative path starting from conf.py directory
103-
old_need_import_path = os.path.join(
104-
self.env.app.srcdir, need_import_path
105-
)
106-
if os.path.exists(old_need_import_path):
107-
correct_need_import_path = old_need_import_path
108-
log_warning(
109-
logger,
110-
"Deprecation warning: Relative path must be relative to the current document in future, "
111-
"not to the conf.py location. Use a starting '/', like '/needs.json', to make the path "
112-
"relative to conf.py.",
113-
"deprecated",
114-
location=(self.env.docname, self.lineno),
115-
)
116-
else:
117-
# Absolute path starts with /, based on the source directory. The / need to be striped
118-
correct_need_import_path = os.path.join(
119-
self.env.app.srcdir, need_import_path[1:]
120-
)
93+
correct_need_import_path = self.env.relfn2path(
94+
need_import_path, self.env.docname
95+
)[1]
12196

12297
if not os.path.exists(correct_need_import_path):
12398
raise ReferenceError(

sphinx_needs/directives/needuml.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import os
55
import time
66
from collections.abc import Sequence
7+
from pathlib import PurePosixPath
78
from typing import TYPE_CHECKING, Any, Callable, TypedDict
89

910
from docutils import nodes
@@ -116,9 +117,9 @@ def run(self) -> Sequence[nodes.Node]:
116117
save_path = self.options.get("save")
117118
plantuml_code_out_path = None
118119
if save_path:
119-
if os.path.isabs(save_path):
120+
if PurePosixPath(save_path).is_absolute():
120121
raise NeedumlException(
121-
f"Given save path: {save_path}, is not a relative path."
122+
f"Given save path: {save_path}, is not a relative posix path."
122123
)
123124
else:
124125
plantuml_code_out_path = save_path

tests/__snapshots__/test_needimport.ambr

+3-18
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
'external_css': 'external_link',
7979
'id': 'REQ_1',
8080
'layout': '',
81-
'lineno': 48,
81+
'lineno': 47,
8282
'section_name': 'FILTERED',
8383
'sections': list([
8484
'FILTERED',
@@ -193,7 +193,7 @@
193193
'external_css': 'external_link',
194194
'id': 'SPEC_1',
195195
'layout': '',
196-
'lineno': 51,
196+
'lineno': 50,
197197
'section_name': 'FILTERED',
198198
'sections': list([
199199
'FILTERED',
@@ -1250,21 +1250,6 @@
12501250
'type': 'req',
12511251
'type_name': 'Requirement',
12521252
}),
1253-
'small_depr_rel_path_TEST_01': dict({
1254-
'content': 'small_depr_rel_path_TEST_01',
1255-
'docname': 'subdoc/deprecated_rel_path_import',
1256-
'external_css': 'external_link',
1257-
'id': 'small_depr_rel_path_TEST_01',
1258-
'is_import': True,
1259-
'lineno': 6,
1260-
'section_name': 'Deprecated Relative path import test',
1261-
'sections': list([
1262-
'Deprecated Relative path import test',
1263-
]),
1264-
'title': 'TEST_01 DESCRIPTION',
1265-
'type': 'impl',
1266-
'type_name': 'Implementation',
1267-
}),
12681253
'small_rel_path_TEST_01': dict({
12691254
'content': 'small_rel_path_TEST_01',
12701255
'docname': 'subdoc/rel_path_import',
@@ -1635,7 +1620,7 @@
16351620
'type_name': 'Test Case',
16361621
}),
16371622
}),
1638-
'needs_amount': 66,
1623+
'needs_amount': 65,
16391624
'needs_defaults_removed': True,
16401625
'needs_schema': dict({
16411626
'$schema': 'http://json-schema.org/draft-07/schema#',

tests/conftest.py

+24-2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,19 @@ def copy_srcdir_to_tmpdir(srcdir: path, tmp: path) -> path:
5656
return tmproot
5757

5858

59+
def create_src_files_in_tmpdir(files: list[tuple[Path, str]], tmp: path) -> path:
60+
"""Create source files in a temporary directory under the subdir src."""
61+
subdir = path("src")
62+
tmproot = tmp.joinpath(generate_random_string()) / subdir
63+
tmproot.makedirs(exist_ok=True)
64+
for file in files:
65+
file_path, content = file
66+
file_abs = tmproot.joinpath(str(file_path))
67+
file_abs.parent.makedirs(exist_ok=True)
68+
file_abs.write_text(content)
69+
return tmproot
70+
71+
5972
def get_abspath(relpath: str) -> str:
6073
"""
6174
Get the absolute path from a relative path.
@@ -266,9 +279,18 @@ def test_app(make_app, sphinx_test_tempdir, request):
266279
)
267280
sphinx_conf_overrides.update(plantuml=plantuml)
268281

269-
# copy test srcdir to test temporary directory sphinx_test_tempdir
270282
srcdir = builder_params.get("srcdir")
271-
src_dir = copy_srcdir_to_tmpdir(srcdir, sphinx_test_tempdir)
283+
files = builder_params.get("files")
284+
if (srcdir is None) == (files is None):
285+
raise ValueError("Exactly one of srcdir, files must not be None")
286+
287+
if srcdir is not None:
288+
# copy test srcdir to test temporary directory sphinx_test_tempdir
289+
src_dir = copy_srcdir_to_tmpdir(srcdir, sphinx_test_tempdir)
290+
else:
291+
# create given files in tmpdir
292+
src_dir = create_src_files_in_tmpdir(files, sphinx_test_tempdir)
293+
272294
parent_path = Path(str(src_dir.parent.abspath()))
273295

274296
if version_info >= (7, 2):

tests/doc_test/import_doc/index.rst

-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ FILTERED
4343
subdoc/filter
4444
subdoc/abs_path_import
4545
subdoc/rel_path_import
46-
subdoc/deprecated_rel_path_import
4746

4847
.. req:: Test requirement 1
4948
:id: REQ_1

tests/doc_test/import_doc/subdoc/deprecated_rel_path_import.rst

-8
This file was deleted.

0 commit comments

Comments
 (0)