a25593a9c6
Group all 69 projects into category subfolders under src/ and tests/ so the Rider Solution Explorer mirrors the module structure. Folders: Core, Server, Drivers (with a nested Driver CLIs subfolder), Client, Tooling. - Move every project folder on disk with git mv (history preserved as renames). - Recompute relative paths in 57 .csproj files: cross-category ProjectReferences, the lib/ HintPath+None refs in Driver.Historian.Wonderware, and the external mxaccessgw refs in Driver.Galaxy and its test project. - Rebuild ZB.MOM.WW.OtOpcUa.slnx with nested solution folders. - Re-prefix project paths in functional scripts (e2e, compliance, smoke SQL, integration, install). Build green (0 errors); unit tests pass. Docs left for a separate pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
81 lines
2.5 KiB
Python
81 lines
2.5 KiB
Python
from __future__ import annotations
|
|
|
|
import argparse
|
|
import asyncio
|
|
import json
|
|
from pathlib import Path
|
|
|
|
from .data_store import MockDataStore
|
|
from .export_introspection import write_profiles
|
|
from .profiles import list_profiles, load_profile
|
|
from .server import FocasMockServer
|
|
|
|
|
|
def _default_root() -> Path:
|
|
return Path(__file__).resolve().parents[2]
|
|
|
|
|
|
def build_parser() -> argparse.ArgumentParser:
|
|
root = _default_root()
|
|
parser = argparse.ArgumentParser(prog="focas-mock")
|
|
sub = parser.add_subparsers(dest="command", required=True)
|
|
|
|
serve = sub.add_parser("serve", help="Start the mock server.")
|
|
serve.add_argument("--host", default="127.0.0.1")
|
|
serve.add_argument("--port", type=int, default=8193)
|
|
serve.add_argument("--profile", default="fwlib30i64")
|
|
serve.add_argument("--data", help="Optional JSON patch file.")
|
|
|
|
sub.add_parser("list-profiles", help="List built-in profiles.")
|
|
|
|
dump_profile = sub.add_parser("dump-profile", help="Print one built-in profile as JSON.")
|
|
dump_profile.add_argument("profile")
|
|
|
|
extract = sub.add_parser("extract-profiles", help="Regenerate JSON profiles from vendored DLLs.")
|
|
extract.add_argument("--dll-dir", default=str(root / "vendor" / "fanuc-cnc-api" / "64bit"))
|
|
extract.add_argument("--fwlib", default=str(root / "upstream" / "fwlib.cs"))
|
|
extract.add_argument("--out-dir", default=str(root / "src" / "focas_mock" / "builtin_profiles"))
|
|
return parser
|
|
|
|
|
|
async def _run_server(args: argparse.Namespace) -> None:
|
|
profile = load_profile(args.profile)
|
|
store = MockDataStore(profile)
|
|
if args.data:
|
|
store.load_patch_file(args.data)
|
|
server = FocasMockServer(args.host, args.port, profile, store)
|
|
await server.start()
|
|
print(f"focas-mock listening on {server.host}:{server.port} with profile {profile['profile_name']}")
|
|
try:
|
|
await server.serve_forever()
|
|
finally:
|
|
await server.close()
|
|
|
|
|
|
def main(argv: list[str] | None = None) -> None:
|
|
parser = build_parser()
|
|
args = parser.parse_args(argv)
|
|
|
|
if args.command == "list-profiles":
|
|
for profile in list_profiles():
|
|
print(profile)
|
|
return
|
|
|
|
if args.command == "dump-profile":
|
|
print(json.dumps(load_profile(args.profile), indent=2))
|
|
return
|
|
|
|
if args.command == "extract-profiles":
|
|
written = write_profiles(args.dll_dir, args.fwlib, args.out_dir)
|
|
for path in written:
|
|
print(path)
|
|
return
|
|
|
|
if args.command == "serve":
|
|
asyncio.run(_run_server(args))
|
|
return
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|