Skip to content

Commit 49bc9ca

Browse files
author
Arnaud Riess
committed
feat: refactor TOML generation functions to return strings and use tempfile for merging
1 parent 8e8c30a commit 49bc9ca

2 files changed

Lines changed: 30 additions & 60 deletions

File tree

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ user.bazelrc
1212
/_build*
1313
docs/ubproject.toml
1414
docs/schemas.json
15-
docs/*_generated.toml
1615

1716
# Vale - editorial style guide
1817
.vale.ini

src/extensions/score_sync_toml/__init__.py

Lines changed: 30 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@
1010
#
1111
# SPDX-License-Identifier: Apache-2.0
1212
# *******************************************************************************
13+
import tempfile
1314
from pathlib import Path
1415

1516
from sphinx.application import Sphinx
1617

1718
from src.helper_lib import config_setdefault
1819

1920

20-
def _write_needs_fields_toml(app: Sphinx) -> Path:
21+
def _generate_needs_fields_toml(app: Sphinx) -> str:
2122
"""Serialize ``app.config.needs_fields`` as ``[needs.fields.*]`` TOML entries.
2223
2324
``needs_config_writer`` cannot serialize the nested dicts that make up
@@ -26,31 +27,24 @@ def _write_needs_fields_toml(app: Sphinx) -> Path:
2627
from ``ubproject.toml``. Without them, ubCode does not know these are valid
2728
options and will report them as unknown fields.
2829
29-
This function writes only the ``default`` value for each field, which is
30-
sufficient for ubCode to recognise the field as valid.
30+
Returns only the ``default`` value for each field, which is sufficient for
31+
ubCode to recognise the field as valid.
3132
3233
Must be called *after* ``score_metamodel.setup()`` has run (i.e. after
3334
``app.config.needs_fields`` has been extended with the metamodel fields).
3435
"""
35-
lines: list[str] = [
36-
"# Auto-generated – do not edit manually.\n",
37-
"# Contains [needs.fields.*] entries derived from metamodel.yaml.\n",
38-
"# Required for the ubCode language server to recognise custom need fields.\n\n",
39-
]
36+
lines: list[str] = []
4037
for field_name, field_config in sorted(app.config.needs_fields.items()):
4138
default = field_config.get("default", "")
4239
# TOML-escape the default value (handle quotes)
4340
escaped = str(default).replace("\\", "\\\\").replace('"', '\\"')
4441
lines.append(f"[needs.fields.{field_name}]\n")
4542
lines.append(f'default = "{escaped}"\n')
4643
lines.append("\n")
47-
48-
output_path = Path(app.confdir) / "needs_fields_generated.toml"
49-
output_path.write_text("".join(lines), encoding="utf-8")
50-
return output_path
44+
return "".join(lines)
5145

5246

53-
def _write_needs_links_toml(app: Sphinx) -> Path:
47+
def _generate_needs_links_toml(app: Sphinx) -> str:
5448
"""Serialize ``app.config.needs_links`` as ``[needs.links.*]`` TOML entries.
5549
5650
``needs_config_writer`` cannot serialize the ``needs_links`` dict of dicts
@@ -62,11 +56,7 @@ def _write_needs_links_toml(app: Sphinx) -> Path:
6256
Must be called *after* ``score_metamodel.setup()`` has run (i.e. after
6357
``app.config.needs_links`` has been updated with the metamodel links).
6458
"""
65-
lines: list[str] = [
66-
"# Auto-generated – do not edit manually.\n",
67-
"# Contains [needs.links.*] entries derived from metamodel.yaml.\n",
68-
"# Required for the ubCode language server to recognise custom link types.\n\n",
69-
]
59+
lines: list[str] = []
7060
for link_name, link_config in sorted(app.config.needs_links.items()):
7161
incoming = (
7262
str(link_config.get("incoming", ""))
@@ -82,13 +72,10 @@ def _write_needs_links_toml(app: Sphinx) -> Path:
8272
lines.append(f'incoming = "{incoming}"\n')
8373
lines.append(f'outgoing = "{outgoing}"\n')
8474
lines.append("\n")
85-
86-
output_path = Path(app.confdir) / "needs_links_generated.toml"
87-
output_path.write_text("".join(lines), encoding="utf-8")
88-
return output_path
75+
return "".join(lines)
8976

9077

91-
def _write_needs_types_toml(app: Sphinx) -> Path:
78+
def _generate_needs_types_toml(app: Sphinx) -> str:
9279
"""Serialize ``app.config.needs_types`` as ``[[needs.types]]`` TOML entries.
9380
9481
``needs_config_writer`` cannot serialize the complex ``ScoreNeedType``
@@ -97,19 +84,13 @@ def _write_needs_types_toml(app: Sphinx) -> Path:
9784
the ubCode language server does not recognise any RST directives as needs
9885
and indexes nothing.
9986
100-
This function writes only the fields that ubCode requires to identify
101-
need directives (``directive``, ``title``, ``prefix``, and optionally
102-
``color``/``style``) to a separate TOML file that is then merged into
103-
``ubproject.toml`` by ``needs_config_writer``.
87+
Returns only the fields that ubCode requires to identify need directives
88+
(``directive``, ``title``, ``prefix``, and optionally ``color``/``style``).
10489
10590
Must be called *after* ``score_metamodel.setup()`` has run (i.e. after
10691
``app.config.needs_types`` has been extended with the metamodel types).
10792
"""
108-
lines: list[str] = [
109-
"# Auto-generated – do not edit manually.\n",
110-
"# Contains [[needs.types]] entries derived from metamodel.yaml.\n",
111-
"# Required for the ubCode language server to recognise need directives.\n\n",
112-
]
93+
lines: list[str] = []
11394
for nt in app.config.needs_types:
11495
lines.append("[[needs.types]]\n")
11596
lines.append(f'directive = "{nt["directive"]}"\n')
@@ -120,10 +101,7 @@ def _write_needs_types_toml(app: Sphinx) -> Path:
120101
if style := nt.get("style"):
121102
lines.append(f'style = "{style}"\n')
122103
lines.append("\n")
123-
124-
output_path = Path(app.confdir) / "needs_types_generated.toml"
125-
output_path.write_text("".join(lines), encoding="utf-8")
126-
return output_path
104+
return "".join(lines)
127105

128106

129107
def setup(app: Sphinx) -> dict[str, str | bool]:
@@ -171,29 +149,22 @@ def setup(app: Sphinx) -> dict[str, str | bool]:
171149
)
172150
"""Merge the static TOML file into the generated configuration."""
173151

174-
# Write [[needs.types]] from the metamodel into a separate TOML fragment and
175-
# merge it. needs_config_writer cannot serialise the complex ScoreNeedType
176-
# dicts itself (unsupported_type), so ubproject.toml would otherwise contain
177-
# no type definitions and the ubCode language server would index nothing.
178-
needs_types_toml = _write_needs_types_toml(app)
179-
app.config.needscfg_merge_toml_files.append(str(needs_types_toml))
180-
"""Merge the generated [[needs.types]] TOML into the final ubproject.toml."""
181-
182-
# Write [needs.fields.*] from the metamodel into a separate TOML fragment and
183-
# merge it. needs_config_writer cannot serialise the nested field dicts, so
184-
# custom fields like 'safety', 'security', 'reqtype' etc. would be absent from
185-
# ubproject.toml and ubCode would flag them as unknown.
186-
needs_fields_toml = _write_needs_fields_toml(app)
187-
app.config.needscfg_merge_toml_files.append(str(needs_fields_toml))
188-
"""Merge the generated [needs.fields.*] TOML into the final ubproject.toml."""
189-
190-
# Write [needs.links.*] from the metamodel into a separate TOML fragment and
191-
# merge it. needs_config_writer cannot serialise the nested link dicts, so
192-
# custom link types like 'satisfies', 'fulfils', 'belongs_to' etc. would be
193-
# absent from ubproject.toml and ubCode would not recognise them.
194-
needs_links_toml = _write_needs_links_toml(app)
195-
app.config.needscfg_merge_toml_files.append(str(needs_links_toml))
196-
"""Merge the generated [needs.links.*] TOML into the final ubproject.toml."""
152+
# Generate TOML fragments for types, fields, and links from the metamodel.
153+
# needs_config_writer cannot serialise these structures itself, so we combine
154+
# them into a single temporary file and register it for merging.
155+
# A NamedTemporaryFile with delete=False is used so the path remains valid
156+
# when needs_config_writer reads it later during the write phase.
157+
metamodel_toml = (
158+
_generate_needs_types_toml(app)
159+
+ _generate_needs_fields_toml(app)
160+
+ _generate_needs_links_toml(app)
161+
)
162+
with tempfile.NamedTemporaryFile(
163+
mode="w", suffix=".toml", delete=False, encoding="utf-8"
164+
) as tmp:
165+
tmp.write(metamodel_toml)
166+
app.config.needscfg_merge_toml_files.append(tmp.name)
167+
"""Merge the generated metamodel TOML (types, fields, links) into the final ubproject.toml."""
197168

198169
app.config.needscfg_relative_path_fields.extend(
199170
[

0 commit comments

Comments
 (0)