Spaces:
Running on Zero
Running on Zero
Download sysml_check.py from cmuchancel/patent2sysml: direct link, hf CLI and curl.
- Browser
- Download file 4.6 kB
-
https://huggingface.co/spaces/cmuchancel/patent2sysml/resolve/main/sysml_check.py
- Command line
-
hf download hf://spaces/cmuchancel/patent2sysml/sysml_check.py
-
curl -L -o sysml_check.py https://huggingface.co/spaces/cmuchancel/patent2sysml/resolve/main/sysml_check.py
4.6 kB
| """Run the pinned SysIDE Legacy parser with its matching standard library.""" | |
| import json | |
| import os | |
| import queue | |
| import shutil | |
| import subprocess | |
| import threading | |
| import time | |
| import tempfile | |
| from pathlib import Path | |
| DEFAULT_PARSER = (Path(__file__).parent / 'assets/sysml-parser' if os.getenv('SPACE_ID') | |
| else Path.home() / '.cache/patent2sysml/sysml-parser') | |
| PARSER = Path(os.getenv('SYSML_PARSER_DIR', str(DEFAULT_PARSER))) | |
| def check_sysml(source): | |
| started = time.monotonic() | |
| source = Path(source).resolve() | |
| server_file = PARSER / 'syside-languageserver.js' | |
| base = {'validator': 'SysIDE Legacy 0.9.1', 'specification': '2024-12', | |
| 'note': 'Parser/semantic diagnostics are not certification against the final SysML 2.0 specification.'} | |
| if not shutil.which('node') or not server_file.exists(): | |
| return {**base, 'status': 'unavailable', 'error': 'Install Node.js and run python setup_parser.py.'} | |
| messages = queue.Queue() | |
| with tempfile.TemporaryDirectory(prefix='patent-sysml-check-') as directory, source.with_suffix('.parser.log').open('w') as log: | |
| document = Path(directory) / source.name | |
| document.write_text(source.read_text()) | |
| server = subprocess.Popen(['node', str(server_file), '--stdio'], stdin=subprocess.PIPE, | |
| stdout=subprocess.PIPE, stderr=log, cwd=directory) | |
| def send(value): | |
| body = json.dumps(value).encode() | |
| server.stdin.write(f'Content-Length: {len(body)}\r\n\r\n'.encode() + body) | |
| server.stdin.flush() | |
| def read(): | |
| while True: | |
| line = server.stdout.readline() | |
| if not line: | |
| return | |
| if not line.lower().startswith(b'content-length:'): | |
| continue | |
| size = int(line.split(b':', 1)[1]) | |
| while server.stdout.readline().strip(): | |
| pass | |
| try: messages.put(json.loads(server.stdout.read(size))) | |
| except (ValueError, OSError): return | |
| threading.Thread(target=read, daemon=True).start() | |
| settings = {'standardLibrary': True, 'standardLibraryPath': str(PARSER / 'stdlib'), | |
| 'skipWorkspaceInit': False, 'defaultBuildOptions': {'standardLibrary': 'standard'}} | |
| last, activity, diagnostics, protocol = None, time.monotonic(), [], [] | |
| try: | |
| send({'jsonrpc': '2.0', 'id': 1, 'method': 'initialize', 'params': { | |
| 'processId': None, 'rootUri': None, 'workspaceFolders': [], | |
| 'capabilities': {'workspace': {'configuration': True}}}}) | |
| deadline = time.monotonic() + 90 | |
| while time.monotonic() < deadline: | |
| try: message = messages.get(timeout=.3) | |
| except queue.Empty: | |
| if last and time.monotonic() - activity > 3: break | |
| continue | |
| activity = time.monotonic() | |
| protocol.append(message) | |
| if 'id' in message and 'method' in message: | |
| result = [settings for _ in message['params']['items']] if message['method'] == 'workspace/configuration' else None | |
| send({'jsonrpc': '2.0', 'id': message['id'], 'result': result}) | |
| elif message.get('id') == 1: | |
| send({'jsonrpc': '2.0', 'method': 'initialized', 'params': {}}) | |
| send({'jsonrpc': '2.0', 'method': 'workspace/didChangeConfiguration', 'params': {'settings': {'syside': settings}}}) | |
| send({'jsonrpc': '2.0', 'method': 'textDocument/didOpen', 'params': {'textDocument': { | |
| 'uri': document.as_uri(), 'languageId': 'sysml', 'version': 1, 'text': document.read_text()}}}) | |
| elif message.get('method') == 'textDocument/publishDiagnostics' and message['params']['uri'] == document.as_uri(): | |
| last, diagnostics = time.monotonic(), message['params']['diagnostics'] | |
| status = 'unavailable' if last is None else ('failed' if any(d.get('severity') == 1 for d in diagnostics) else 'passed') | |
| return {**base, 'status': status, 'diagnostics': diagnostics, 'protocol': protocol, | |
| 'server_exit_code': server.poll(), 'duration_seconds': time.monotonic() - started} | |
| finally: | |
| server.terminate() | |
| try: server.wait(timeout=5) | |
| except subprocess.TimeoutExpired: | |
| server.kill(); server.wait() | |
| server.stdin.close(); server.stdout.close() | |