Skip to content

Commit 1eef396

Browse files
committed
Add convert subcommand to CLI
1 parent e202016 commit 1eef396

2 files changed

Lines changed: 78 additions & 23 deletions

File tree

README.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,22 @@ This starts the PathView server with a local Python backend and opens your brows
3434
- `--no-browser` — don't auto-open the browser
3535
- `--debug` — debug mode with auto-reload
3636

37-
### Python API
37+
### Convert `.pvm` to Python
3838

39-
Convert `.pvm` model files to standalone PathSim Python scripts:
39+
Convert PathView model files to standalone PathSim scripts:
40+
41+
```bash
42+
pathview convert model.pvm # outputs model.py
43+
pathview convert model.pvm -o output.py # custom output path
44+
pathview convert model.pvm --stdout # print to stdout
45+
```
46+
47+
Or use the Python API directly:
4048

4149
```python
4250
from pathview import convert
4351

4452
python_code = convert("model.pvm")
45-
print(python_code)
4653
```
4754

4855
### Development setup

pathview/cli.py

Lines changed: 68 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,13 @@
55
import threading
66
import time
77
import webbrowser
8+
from pathlib import Path
89

910
from pathview import __version__
1011

1112

12-
def main():
13-
parser = argparse.ArgumentParser(
14-
prog="pathview",
15-
description="PathView — visual node editor for dynamic systems",
16-
)
17-
parser.add_argument("command", nargs="?", default="serve", choices=["serve"],
18-
help="Command to run (default: serve)")
19-
parser.add_argument("--port", type=int, default=5000,
20-
help="Port to run the server on (default: 5000)")
21-
parser.add_argument("--host", type=str, default="127.0.0.1",
22-
help="Host to bind to (default: 127.0.0.1)")
23-
parser.add_argument("--no-browser", action="store_true",
24-
help="Don't automatically open the browser")
25-
parser.add_argument("--debug", action="store_true",
26-
help="Run in debug mode")
27-
parser.add_argument("--version", action="version",
28-
version=f"pathview {__version__}")
29-
30-
args = parser.parse_args()
31-
13+
def _cmd_serve(args):
14+
"""Run the PathView server."""
3215
from pathview.app import create_app
3316

3417
app = create_app(serve_static=not args.debug)
@@ -70,5 +53,70 @@ def open_browser_when_ready():
7053
sys.exit(0)
7154

7255

56+
def _cmd_convert(args):
57+
"""Convert a .pvm file to a Python script."""
58+
from pathview.converter import convert
59+
60+
input_path = Path(args.input)
61+
if not input_path.exists():
62+
print(f"Error: Input file not found: {input_path}", file=sys.stderr)
63+
sys.exit(1)
64+
65+
registry_path = Path(args.registry) if args.registry else None
66+
python_code = convert(input_path, registry_path=registry_path)
67+
68+
if args.stdout:
69+
sys.stdout.buffer.write(python_code.encode("utf-8"))
70+
else:
71+
output_path = Path(args.output) if args.output else input_path.with_suffix(".py")
72+
output_path.write_text(python_code, encoding="utf-8")
73+
print(f"Converted: {input_path} -> {output_path}")
74+
75+
76+
def main():
77+
parser = argparse.ArgumentParser(
78+
prog="pathview",
79+
description="PathView — visual node editor for dynamic systems",
80+
)
81+
parser.add_argument("--version", action="version",
82+
version=f"pathview {__version__}")
83+
84+
subparsers = parser.add_subparsers(dest="command")
85+
86+
# --- serve ---
87+
serve_parser = subparsers.add_parser("serve", help="Start the PathView server")
88+
serve_parser.add_argument("--port", type=int, default=5000,
89+
help="Port to run the server on (default: 5000)")
90+
serve_parser.add_argument("--host", type=str, default="127.0.0.1",
91+
help="Host to bind to (default: 127.0.0.1)")
92+
serve_parser.add_argument("--no-browser", action="store_true",
93+
help="Don't automatically open the browser")
94+
serve_parser.add_argument("--debug", action="store_true",
95+
help="Run in debug mode")
96+
97+
# --- convert ---
98+
convert_parser = subparsers.add_parser(
99+
"convert",
100+
help="Convert a .pvm file to a Python script",
101+
)
102+
convert_parser.add_argument("input", help="Input .pvm or .json file")
103+
convert_parser.add_argument("-o", "--output",
104+
help="Output .py file (default: <input>.py)")
105+
convert_parser.add_argument("--stdout", action="store_true",
106+
help="Print to stdout instead of file")
107+
convert_parser.add_argument("--registry",
108+
help="Path to custom registry.json")
109+
110+
args = parser.parse_args()
111+
112+
if args.command is None or args.command == "serve":
113+
if args.command is None:
114+
# Re-parse with serve defaults when no subcommand given
115+
args = serve_parser.parse_args([])
116+
_cmd_serve(args)
117+
elif args.command == "convert":
118+
_cmd_convert(args)
119+
120+
73121
if __name__ == "__main__":
74122
main()

0 commit comments

Comments
 (0)