Skip to content

Commit

Permalink
Merge pull request #46 from ferrocene/hoverbear/manually-update
Browse files Browse the repository at this point in the history
Manual update from ferrocene/ferrocene
  • Loading branch information
amanjeev authored Nov 26, 2024
2 parents 52d3766 + 7de064b commit 20befa7
Show file tree
Hide file tree
Showing 11 changed files with 408 additions and 111 deletions.
43 changes: 36 additions & 7 deletions exts/ferrocene_domain_cli/domain.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
# SPDX-License-Identifier: MIT OR Apache-2.0
# SPDX-FileCopyrightText: The Ferrocene Developers


from dataclasses import dataclass
import re
import string

from docutils import nodes
from docutils.parsers.rst import directives

from sphinx import addnodes
from sphinx.directives import SphinxDirective, ObjectDescription
from sphinx.domains import Domain, ObjType
from sphinx.roles import XRefRole
import re
import sphinx
import string


PROGRAM_STORAGE = "ferrocene_domain_cli:program"
Expand All @@ -18,17 +23,29 @@ class ProgramDirective(SphinxDirective):
has_content = True
required_arguments = 1
final_argument_whitespace = True
option_spec = {"no_traceability_matrix": directives.flag}

def run(self):
# if there already is program data in storage, a ProgramDirective is
# within a ProgramDirective, which isn't supported
if PROGRAM_STORAGE in self.env.temp_data:
warn("cli:program inside cli:program isn't supported", self.get_location())
return []
self.env.temp_data[PROGRAM_STORAGE] = self.arguments[0]

# store arguments, so they can be accessed by child `OptionDirective`s
self.env.temp_data[PROGRAM_STORAGE] = ProgramStorage(
self.arguments[0],
"no_traceability_matrix" in self.options,
)

# parse and process content of `ProgramDirective``
# (one or more `OptionDirective`s)
node = nodes.container()
self.state.nested_parse(self.content, self.content_offset, node)

# clear program storage
del self.env.temp_data[PROGRAM_STORAGE]

return [node]


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

option = Option(self.env.docname, program, sig)
option = Option(
self.env.docname,
program_storage.program_name,
sig,
program_storage.no_traceability_matrix,
)

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

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


class Option:
def __init__(self, document, program, option):
def __init__(self, document, program, option, no_traceability_matrix):
self.document = document
self.program = program
self.option = option
self.no_traceability_matrix = no_traceability_matrix

def id(self):
option = (
Expand Down Expand Up @@ -149,3 +172,9 @@ def warn(message, location):

def setup(app):
app.add_domain(CliDomain)


@dataclass
class ProgramStorage:
program_name: str
no_traceability_matrix: bool
3 changes: 3 additions & 0 deletions exts/ferrocene_domain_cli/traceability_ids.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ def write_traceability_ids(app):

options_by_document = defaultdict(list)
for option in env.get_domain("cli").get_options().values():
if option.no_traceability_matrix:
continue

options_by_document[option.document].append(
{
"id": option.id(),
Expand Down
23 changes: 21 additions & 2 deletions exts/ferrocene_qualification/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
# SPDX-License-Identifier: MIT OR Apache-2.0
# SPDX-FileCopyrightText: The Ferrocene Developers

from . import substitutions, document_id, domain, signature_page, target
from . import (
document_id,
domain,
intersphinx_support,
signature_page,
sphinx_needs_support,
substitutions,
target,
)
import string


Expand All @@ -11,16 +19,19 @@ def setup(app):
domain.setup(app)
signature_page.setup(app)
target.setup(app)
intersphinx_support.setup(app)
sphinx_needs_support.setup(app)

app.connect("config-inited", validate_config)
app.connect("config-inited", inject_version)
app.add_config_value("ferrocene_id", None, "env", [str])
app.add_config_value("ferrocene_substitutions_path", None, "env", [str])
app.add_config_value("ferrocene_target_names_path", None, "env", [str])
app.add_config_value("ferrocene_signature", None, "env", [str])
app.add_config_value("ferrocene_private_signature_files_dir", None, "env", [str])
app.add_config_value("rustfmt_version", None, "env", [str])
app.add_config_value("ferrocene_version", None, "env", [str])
app.add_config_value("rust_version", None, "env", [str])
app.add_config_value("channel", None, "env", [str])

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

if any(c not in string.ascii_uppercase for c in config["ferrocene_id"]):
raise ValueError("ferrocene_id can only be uppercase letters")


def inject_version(app, config):
# sphinx-needs requires the document version to be configured in order for
# external needs to be loaded. Dynamically set it to the Ferrocene version
# if there is no existing version.
if not config.version and config.ferrocene_version:
config.version = config.ferrocene_version
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: MIT OR Apache-2.0
# SPDX-FileCopyrightText: The Ferrocene Developers

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


class IntersphinxBuilder(Builder):
Expand Down Expand Up @@ -81,13 +82,11 @@ def inject_intersphinx_mappings(app, config):


def setup(app):
# Automatically enable the sphinx.ext.intersphinx extension without
# requiring users to configure it in their conf.py.
sphinx.ext.intersphinx.setup(app)

app.add_builder(IntersphinxBuilder)

app.add_config_value("ferrocene_intersphinx_mappings", None, "env", [str])
app.connect("config-inited", inject_intersphinx_mappings, priority=1)

return {
"version": "0",
"parallel_read_safe": True,
"parallel_write_safe": True,
}
4 changes: 2 additions & 2 deletions exts/ferrocene_qualification/signature_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def load_file(self, name, *, copy=False):
self.loaded_files.append(path)
if copy:
self.copiable_files[name] = path
with open(path) as f:
with open(path, "r", encoding="utf-8") as f:
return f.read()

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


Expand Down
84 changes: 84 additions & 0 deletions exts/ferrocene_qualification/sphinx_needs_support.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# SPDX-License-Identifier: MIT OR Apache-2.0
# SPDX-FileCopyrightText: The Ferrocene Developers

import sphinx_needs
import json


def configure_sphinx_needs(app, config):
config.needs_types = [
{
"directive": "hazop-use",
"title": "Use Case",
"prefix": "USE_",
"color": "",
"style": "",
},
{
"directive": "hazop-error",
"title": "Potential error",
"prefix": "ERR_",
"color": "",
"style": "",
},
{
"directive": "constraint",
"title": "Constraint",
"prefix": "CONSTR_",
"color": "",
"style": "",
},
{
"directive": "req",
"title": "Requirement",
"prefix": "REQ_",
"color": "",
"style": "",
},
]

config.needs_extra_links = [
{
"option": "caused_by",
"incoming": "causes",
"outgoing": "caused by",
},
{
"option": "mitigates",
"incoming": "mitigated by",
"outgoing": "mitigates",
},
{
"option": "implements",
"incoming": "implemented by",
"outgoing": "implements",
},
]

config.needs_default_layout = "ferrocene"
config.needs_layouts = {
# Forked from the builtin "clean" layout, but without the arrow to
# collapse the meta information. That arrow generates HTML that
# linkchecker doesn't like, unfortunately :(
"ferrocene": {
"grid": "simple",
"layout": {
"head": ['<<meta("type_name")>>: **<<meta("title")>>** <<meta_id()>>'],
"meta": ["<<meta_all(no_links=True)>>", "<<meta_links_all()>>"],
},
},
}

if config.ferrocene_external_needs is not None:
config.needs_external_needs = json.loads(config.ferrocene_external_needs)

config.needs_title_optional = True
config.needs_build_json = True
config.needs_reproducible_json = True


def setup(app):
sphinx_needs.setup(app)

app.add_config_value("ferrocene_external_needs", None, "env", str)
app.connect("config-inited", configure_sphinx_needs, priority=100)
5 changes: 1 addition & 4 deletions exts/ferrocene_qualification/substitutions.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def apply(self):
# look at sphinx-substitutions.toml for the rest of the substitutions
self.add_substitution("doc_title", self.app.config["html_short_title"])
self.add_substitution("doc_short_title", self.app.config["ferrocene_id"])
self.add_substitution("rustfmt_version", self.app.config["rustfmt_version"])
self.add_substitution(
"ferrocene_version",
self.app.config["ferrocene_version"],
Expand All @@ -39,10 +40,6 @@ def apply(self):
"rust_version",
self.app.config["rust_version"],
)
self.add_substitution(
"channel",
self.app.config["channel"],
)

def add_substitution(self, name, value):
substitution = nodes.substitution_definition()
Expand Down
2 changes: 2 additions & 0 deletions requirements.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
# SPDX-FileCopyrightText: The Ferrocene Developers

sphinx
sphinx-needs
sphinx-autobuild
sphinxcontrib-plantuml
tomli
myst_parser
pyyaml
Expand Down
Loading

0 comments on commit 20befa7

Please sign in to comment.