Merge pull request #1318 from ispyisail/feature/bom-skip-junctions-slaves
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 2m7s

Add options to leave junctions and contact blocks out of the parts list
This commit is contained in:
Laurent Trinques
2026-10-05 17:59:05 +02:00
committed by GitHub
18 changed files with 298 additions and 49 deletions
+6
View File
@@ -703,6 +703,12 @@ Python, plus the hang guard on `addConductor` and the database refresh in
`source_date_epoch` if given, else the server's own `SOURCE_DATE_EPOCH`,
else 0 (1 January 1970). The result's `"reproducible"` is false, with a
hint, when the QElectroTech build is too old to honour it.
- **`"no_slaves"` and `"no_junctions"` shorten a `bom` export.** The first
leaves out the contact blocks, which otherwise get a row of their own; the
second leaves out terminal-type elements with no label, designation,
manufacturer or manufacturer reference, such as the junction dots of
`114_connections`. They pass `--no-slaves` and `--no-junctions`; an older
QElectroTech ignores both and exports every row, so check the row count.
- **`qet_export` isolates its launch.** SingleApplication keys its socket
on `applicationFilePath()`, so a second launch of the same binary path
forwards its request to an already-running instance and returns *that*
+22 -4
View File
@@ -1061,10 +1061,13 @@ def _source_date_epoch(value) -> int:
def tool_export(binary: str, project: str, format: str, output: str,
timeout: int = 180, reproducible: bool = False,
source_date_epoch: int | None = None) -> dict:
source_date_epoch: int | None = None,
no_slaves: bool = False, no_junctions: bool = False) -> dict:
if format not in EXPORT_FORMATS:
raise ValueError(f"unknown format {format!r}; "
f"expected one of {', '.join(sorted(EXPORT_FORMATS))}")
if (no_slaves or no_junctions) and format != "bom":
raise ValueError("no_slaves and no_junctions only apply to format \"bom\"")
proj = Path(project).expanduser()
if not proj.is_file():
raise ValueError(f"no such project: {proj}")
@@ -1082,8 +1085,12 @@ def tool_export(binary: str, project: str, format: str, output: str,
if reproducible or source_date_epoch is not None:
epoch = _source_date_epoch(source_date_epoch)
extra_env = {"SOURCE_DATE_EPOCH": str(epoch)}
result = _run_qet(binary, [flag, str(proj), output], timeout,
extra_env=extra_env)
args = [flag, str(proj), output]
if no_slaves:
args.append("--no-slaves")
if no_junctions:
args.append("--no-junctions")
result = _run_qet(binary, args, timeout, extra_env=extra_env)
out = Path(output).expanduser()
result["output"] = str(out)
result["output_exists"] = out.exists()
@@ -4822,13 +4829,24 @@ TOOLS = [
"carries, in seconds since 1970 UTC. "
"Default: this server's own "
"SOURCE_DATE_EPOCH, else 0"},
"no_slaves": {"type": "boolean", "default": False,
"description": "bom: leave out the contact blocks (slave "
"elements), which otherwise get a row of "
"their own with their master's label"},
"no_junctions": {"type": "boolean", "default": False,
"description": "bom: leave out the junctions: "
"terminal-type elements with no label, "
"designation, manufacturer or "
"manufacturer reference"},
},
"required": ["project", "format", "output"],
},
"handler": lambda a: tool_export(a["binary"], a["project"], a["format"],
a["output"], a.get("timeout", 180),
a.get("reproducible", False),
a.get("source_date_epoch")),
a.get("source_date_epoch"),
a.get("no_slaves", False),
a.get("no_junctions", False)),
},
{
"name": "qet_edit",
+30
View File
@@ -4034,6 +4034,36 @@ class ProjectNewValidation(unittest.TestCase):
self.assertFalse(Path(new).exists())
class BomExportOptions(unittest.TestCase):
"""qet_export's no_slaves and no_junctions become --export-bom flags (#1178)."""
def run_export(self, format="bom", **kw):
seen = []
def fake(binary, args, timeout=180, **rest):
seen.extend(args)
return {"ok": True}
with tempfile.TemporaryDirectory() as tmp:
proj = Path(tmp) / "a.qet"
proj.write_text("<project/>")
with unittest.mock.patch.object(m, "_run_qet", fake):
m.tool_export("qet", str(proj), format, str(Path(tmp) / "o.csv"), **kw)
return seen
def test_off_by_default(self):
args = self.run_export()
self.assertNotIn("--no-slaves", args)
self.assertNotIn("--no-junctions", args)
def test_flags_after_the_output(self):
args = self.run_export(no_slaves=True, no_junctions=True)
self.assertEqual(args[0], "--export-bom")
self.assertEqual(args[3:], ["--no-slaves", "--no-junctions"])
def test_refused_for_other_formats(self):
with self.assertRaises(ValueError):
self.run_export(format="wiring", no_junctions=True)
class ReproducibleExport(unittest.TestCase):
"""qet_export's "reproducible" sets SOURCE_DATE_EPOCH for the run."""