Implement the freeroute CLI (DSN in, SES out, JAR-flag-compatible)
The pyproject declared a freeroute script but freeroute.cli was missing, so the entry point was broken. Add it: reads a Specctra .dsn, routes (rip-up on by default), writes SES. Accepts FreeRouting-compatible -de/-do flags so it can be dropped in wherever 'java -jar freerouting.jar' was called.
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
"""freeroute command-line interface: Specctra DSN in, routed SES out.
|
||||
|
||||
Flag-compatible with the FreeRouting JAR (``-de`` / ``-do``) so it can be
|
||||
dropped in wherever ``java -jar freerouting.jar`` was invoked.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
from freeroute.dsn.reader import parse_dsn
|
||||
from freeroute.route.pipeline import build_routing_result
|
||||
from freeroute.ses import write_ses
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None) -> int:
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="freeroute",
|
||||
description="Native PCB autorouter — route a Specctra DSN and write an SES session file.",
|
||||
)
|
||||
parser.add_argument("dsn", nargs="?", help="input Specctra .dsn file")
|
||||
parser.add_argument(
|
||||
"-de", "--design", dest="design", help="input .dsn (FreeRouting-compatible alias)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"-do", "--output", dest="output", help="output .ses file (default: stdout)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"-mp",
|
||||
"--max-passes",
|
||||
type=int,
|
||||
default=None,
|
||||
help="accepted for FreeRouting CLI compatibility (advisory; freeroute self-bounds passes)",
|
||||
)
|
||||
parser.add_argument("--no-rip-up", action="store_true", help="disable rip-up-and-retry")
|
||||
parser.add_argument("--layers", help="comma-separated signal layer indices to route on")
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
dsn_path = args.design or args.dsn
|
||||
if not dsn_path:
|
||||
parser.error("no input DSN (pass a path, or -de <file>)")
|
||||
|
||||
layers = [int(x) for x in args.layers.split(",")] if args.layers else None
|
||||
|
||||
try:
|
||||
with open(dsn_path, encoding="utf-8") as f:
|
||||
dsn_text = f.read()
|
||||
except OSError as e:
|
||||
print(f"freeroute: cannot read {dsn_path}: {e}", file=sys.stderr)
|
||||
return 2
|
||||
|
||||
dsn = parse_dsn(dsn_text)
|
||||
result = build_routing_result(dsn, layers=layers, rip_up=not args.no_rip_up)
|
||||
ses_text = write_ses(dsn, result)
|
||||
|
||||
if args.output:
|
||||
with open(args.output, "w", encoding="utf-8") as f:
|
||||
f.write(ses_text)
|
||||
else:
|
||||
sys.stdout.write(ses_text)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user