Skip to content
This repository was archived by the owner on Jan 27, 2025. It is now read-only.

Commit d0f318f

Browse files
committed
Manual update from ferrocene/ferrocene
mirrored-commit: 79cfbf8b352b0611672aefbbe877d9584fc11d6c
1 parent 52d3766 commit d0f318f

File tree

11 files changed

+414
-106
lines changed

11 files changed

+414
-106
lines changed

exts/ferrocene_domain_cli/domain.py

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
# SPDX-License-Identifier: MIT OR Apache-2.0
22
# SPDX-FileCopyrightText: The Ferrocene Developers
33

4+
5+
from dataclasses import dataclass
6+
import re
7+
import string
8+
49
from docutils import nodes
10+
from docutils.parsers.rst import directives
11+
512
from sphinx import addnodes
613
from sphinx.directives import SphinxDirective, ObjectDescription
714
from sphinx.domains import Domain, ObjType
815
from sphinx.roles import XRefRole
9-
import re
1016
import sphinx
11-
import string
1217

1318

1419
PROGRAM_STORAGE = "ferrocene_domain_cli:program"
@@ -18,17 +23,29 @@ class ProgramDirective(SphinxDirective):
1823
has_content = True
1924
required_arguments = 1
2025
final_argument_whitespace = True
26+
option_spec = {"no_traceability_matrix": directives.flag}
2127

2228
def run(self):
29+
# if there already is program data in storage, a ProgramDirective is
30+
# within a ProgramDirective, which isn't supported
2331
if PROGRAM_STORAGE in self.env.temp_data:
2432
warn("cli:program inside cli:program isn't supported", self.get_location())
2533
return []
26-
self.env.temp_data[PROGRAM_STORAGE] = self.arguments[0]
2734

35+
# store arguments, so they can be accessed by child `OptionDirective`s
36+
self.env.temp_data[PROGRAM_STORAGE] = ProgramStorage(
37+
self.arguments[0],
38+
"no_traceability_matrix" in self.options,
39+
)
40+
41+
# parse and process content of `ProgramDirective``
42+
# (one or more `OptionDirective`s)
2843
node = nodes.container()
2944
self.state.nested_parse(self.content, self.content_offset, node)
3045

46+
# clear program storage
3147
del self.env.temp_data[PROGRAM_STORAGE]
48+
3249
return [node]
3350

3451

@@ -43,11 +60,16 @@ def handle_signature(self, sig, signode):
4360
def add_target_and_index(self, name_cls, sig, signode):
4461
if PROGRAM_STORAGE not in self.env.temp_data:
4562
warn("cli:option outside cli:program isn't supported", self.get_location())
46-
program = "PLACEHOLDER"
63+
program_storage = ProgramStorage("PLACEHOLDER", False)
4764
else:
48-
program = self.env.temp_data[PROGRAM_STORAGE]
65+
program_storage: ProgramStorage = self.env.temp_data[PROGRAM_STORAGE]
4966

50-
option = Option(self.env.docname, program, sig)
67+
option = Option(
68+
self.env.docname,
69+
program_storage.program_name,
70+
sig,
71+
program_storage.no_traceability_matrix,
72+
)
5173

5274
signode["ids"].append(option.id())
5375

@@ -61,10 +83,11 @@ def add_target_and_index(self, name_cls, sig, signode):
6183

6284

6385
class Option:
64-
def __init__(self, document, program, option):
86+
def __init__(self, document, program, option, no_traceability_matrix):
6587
self.document = document
6688
self.program = program
6789
self.option = option
90+
self.no_traceability_matrix = no_traceability_matrix
6891

6992
def id(self):
7093
option = (
@@ -149,3 +172,9 @@ def warn(message, location):
149172

150173
def setup(app):
151174
app.add_domain(CliDomain)
175+
176+
177+
@dataclass
178+
class ProgramStorage:
179+
program_name: str
180+
no_traceability_matrix: bool

exts/ferrocene_domain_cli/traceability_ids.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ def write_traceability_ids(app):
1212

1313
options_by_document = defaultdict(list)
1414
for option in env.get_domain("cli").get_options().values():
15+
if option.no_traceability_matrix:
16+
continue
17+
1518
options_by_document[option.document].append(
1619
{
1720
"id": option.id(),

exts/ferrocene_qualification/__init__.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
# SPDX-License-Identifier: MIT OR Apache-2.0
22
# SPDX-FileCopyrightText: The Ferrocene Developers
33

4-
from . import substitutions, document_id, domain, signature_page, target
4+
from . import (
5+
document_id,
6+
domain,
7+
intersphinx_support,
8+
signature_page,
9+
sphinx_needs_support,
10+
substitutions,
11+
target,
12+
)
513
import string
614

715

@@ -11,16 +19,19 @@ def setup(app):
1119
domain.setup(app)
1220
signature_page.setup(app)
1321
target.setup(app)
22+
intersphinx_support.setup(app)
23+
sphinx_needs_support.setup(app)
1424

1525
app.connect("config-inited", validate_config)
26+
app.connect("config-inited", inject_version)
1627
app.add_config_value("ferrocene_id", None, "env", [str])
1728
app.add_config_value("ferrocene_substitutions_path", None, "env", [str])
1829
app.add_config_value("ferrocene_target_names_path", None, "env", [str])
1930
app.add_config_value("ferrocene_signature", None, "env", [str])
2031
app.add_config_value("ferrocene_private_signature_files_dir", None, "env", [str])
32+
app.add_config_value("rustfmt_version", None, "env", [str])
2133
app.add_config_value("ferrocene_version", None, "env", [str])
2234
app.add_config_value("rust_version", None, "env", [str])
23-
app.add_config_value("channel", None, "env", [str])
2435

2536
return {
2637
"version": "0",
@@ -40,3 +51,11 @@ def validate_config(app, config):
4051

4152
if any(c not in string.ascii_uppercase for c in config["ferrocene_id"]):
4253
raise ValueError("ferrocene_id can only be uppercase letters")
54+
55+
56+
def inject_version(app, config):
57+
# sphinx-needs requires the document version to be configured in order for
58+
# external needs to be loaded. Dynamically set it to the Ferrocene version
59+
# if there is no existing version.
60+
if not config.version and config.ferrocene_version:
61+
config.version = config.ferrocene_version

exts/ferrocene_intersphinx_support.py renamed to exts/ferrocene_qualification/intersphinx_support.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# SPDX-License-Identifier: MIT OR Apache-2.0
22
# SPDX-FileCopyrightText: The Ferrocene Developers
33

4-
# This extension adds some helpers needed to integrate Ferrocene's build system
4+
# This module adds some helpers needed to integrate Ferrocene's build system
55
# with InterSphinx. More specifically, the extension:
66
#
77
# - Defines the "ferrocene-intersphinx" Sphinx builder, which only produces the
@@ -18,6 +18,7 @@
1818
from sphinx.builders.html import StandaloneHTMLBuilder
1919
import json
2020
import sphinx
21+
import sphinx.ext.intersphinx
2122

2223

2324
class IntersphinxBuilder(Builder):
@@ -81,13 +82,11 @@ def inject_intersphinx_mappings(app, config):
8182

8283

8384
def setup(app):
85+
# Automatically enable the sphinx.ext.intersphinx extension without
86+
# requiring users to configure it in their conf.py.
87+
sphinx.ext.intersphinx.setup(app)
88+
8489
app.add_builder(IntersphinxBuilder)
8590

8691
app.add_config_value("ferrocene_intersphinx_mappings", None, "env", [str])
8792
app.connect("config-inited", inject_intersphinx_mappings, priority=1)
88-
89-
return {
90-
"version": "0",
91-
"parallel_read_safe": True,
92-
"parallel_write_safe": True,
93-
}

exts/ferrocene_qualification/signature_page.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def load_file(self, name, *, copy=False):
5858
self.loaded_files.append(path)
5959
if copy:
6060
self.copiable_files[name] = path
61-
with open(path) as f:
61+
with open(path, "r", encoding="utf-8") as f:
6262
return f.read()
6363

6464
def load_private_file(self, name, *, copy=False):
@@ -69,7 +69,7 @@ def load_private_file(self, name, *, copy=False):
6969
path = f"{self.app.config.ferrocene_private_signature_files_dir}/{uuid}"
7070
if copy:
7171
self.copiable_files[name] = path
72-
with open(path) as f:
72+
with open(path, "r", encoding="utf-8") as f:
7373
return f.read()
7474

7575

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# SPDX-License-Identifier: MIT OR Apache-2.0
2+
# SPDX-FileCopyrightText: The Ferrocene Developers
3+
4+
import sphinx_needs
5+
import json
6+
7+
8+
def configure_sphinx_needs(app, config):
9+
config.needs_types = [
10+
{
11+
"directive": "hazop-use",
12+
"title": "Use Case",
13+
"prefix": "USE_",
14+
"color": "",
15+
"style": "",
16+
},
17+
{
18+
"directive": "hazop-error",
19+
"title": "Potential error",
20+
"prefix": "ERR_",
21+
"color": "",
22+
"style": "",
23+
},
24+
{
25+
"directive": "constraint",
26+
"title": "Constraint",
27+
"prefix": "CONSTR_",
28+
"color": "",
29+
"style": "",
30+
},
31+
{
32+
"directive": "req",
33+
"title": "Requirement",
34+
"prefix": "REQ_",
35+
"color": "",
36+
"style": "",
37+
},
38+
]
39+
40+
config.needs_extra_links = [
41+
{
42+
"option": "caused_by",
43+
"incoming": "causes",
44+
"outgoing": "caused by",
45+
},
46+
{
47+
"option": "mitigates",
48+
"incoming": "mitigated by",
49+
"outgoing": "mitigates",
50+
},
51+
{
52+
"option": "implements",
53+
"incoming": "implemented by",
54+
"outgoing": "implements",
55+
},
56+
]
57+
58+
config.needs_default_layout = "ferrocene"
59+
config.needs_layouts = {
60+
# Forked from the builtin "clean" layout, but without the arrow to
61+
# collapse the meta information. That arrow generates HTML that
62+
# linkchecker doesn't like, unfortunately :(
63+
"ferrocene": {
64+
"grid": "simple",
65+
"layout": {
66+
"head": ['<<meta("type_name")>>: **<<meta("title")>>** <<meta_id()>>'],
67+
"meta": ["<<meta_all(no_links=True)>>", "<<meta_links_all()>>"],
68+
},
69+
},
70+
}
71+
72+
if config.ferrocene_external_needs is not None:
73+
config.needs_external_needs = json.loads(config.ferrocene_external_needs)
74+
75+
config.needs_title_optional = True
76+
config.needs_build_json = True
77+
config.needs_reproducible_json = True
78+
79+
80+
def setup(app):
81+
sphinx_needs.setup(app)
82+
83+
app.add_config_value("ferrocene_external_needs", None, "env", str)
84+
app.connect("config-inited", configure_sphinx_needs, priority=100)

exts/ferrocene_qualification/substitutions.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ def apply(self):
3131
# look at sphinx-substitutions.toml for the rest of the substitutions
3232
self.add_substitution("doc_title", self.app.config["html_short_title"])
3333
self.add_substitution("doc_short_title", self.app.config["ferrocene_id"])
34+
self.add_substitution("rustfmt_version", self.app.config["rustfmt_version"])
3435
self.add_substitution(
3536
"ferrocene_version",
3637
self.app.config["ferrocene_version"],
@@ -39,10 +40,6 @@ def apply(self):
3940
"rust_version",
4041
self.app.config["rust_version"],
4142
)
42-
self.add_substitution(
43-
"channel",
44-
self.app.config["channel"],
45-
)
4643

4744
def add_substitution(self, name, value):
4845
substitution = nodes.substitution_definition()

requirements.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
# SPDX-FileCopyrightText: The Ferrocene Developers
33

44
sphinx
5+
sphinx-needs
56
sphinx-autobuild
7+
sphinxcontrib-plantuml
68
tomli
79
myst_parser
810
pyyaml

0 commit comments

Comments
 (0)