rdc-cli 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rdc/__init__.py +4 -0
- rdc/adapter.py +61 -0
- rdc/cli.py +65 -0
- rdc/commands/capture.py +62 -0
- rdc/commands/completion.py +49 -0
- rdc/commands/counters.py +50 -0
- rdc/commands/doctor.py +98 -0
- rdc/commands/events.py +140 -0
- rdc/commands/export.py +57 -0
- rdc/commands/info.py +125 -0
- rdc/commands/pipeline.py +330 -0
- rdc/commands/resources.py +126 -0
- rdc/commands/search.py +67 -0
- rdc/commands/session.py +57 -0
- rdc/commands/unix_helpers.py +79 -0
- rdc/commands/usage.py +57 -0
- rdc/commands/vfs.py +206 -0
- rdc/daemon_client.py +32 -0
- rdc/daemon_server.py +2079 -0
- rdc/discover.py +84 -0
- rdc/formatters/json_fmt.py +20 -0
- rdc/formatters/tsv.py +60 -0
- rdc/protocol.py +61 -0
- rdc/services/__init__.py +1 -0
- rdc/services/query_service.py +512 -0
- rdc/services/session_service.py +174 -0
- rdc/session_state.py +86 -0
- rdc/vfs/__init__.py +0 -0
- rdc/vfs/formatter.py +62 -0
- rdc/vfs/router.py +191 -0
- rdc/vfs/tree_cache.py +308 -0
- rdc_cli-0.2.0.dist-info/METADATA +130 -0
- rdc_cli-0.2.0.dist-info/RECORD +37 -0
- rdc_cli-0.2.0.dist-info/WHEEL +5 -0
- rdc_cli-0.2.0.dist-info/entry_points.txt +2 -0
- rdc_cli-0.2.0.dist-info/licenses/LICENSE +21 -0
- rdc_cli-0.2.0.dist-info/top_level.txt +1 -0
rdc/discover.py
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""Renderdoc module discovery.
|
|
2
|
+
|
|
3
|
+
Searches for the renderdoc Python module in standard locations
|
|
4
|
+
and returns the imported module if found and ABI-compatible.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import importlib
|
|
10
|
+
import logging
|
|
11
|
+
import os
|
|
12
|
+
import shutil
|
|
13
|
+
import sys
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from types import ModuleType
|
|
16
|
+
|
|
17
|
+
log = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
_SYSTEM_PATHS = [
|
|
20
|
+
"/usr/lib/renderdoc",
|
|
21
|
+
"/usr/local/lib/renderdoc",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def find_renderdoc() -> ModuleType | None:
|
|
26
|
+
"""Discover and import the renderdoc module.
|
|
27
|
+
|
|
28
|
+
Search order:
|
|
29
|
+
1. ``RENDERDOC_PYTHON_PATH`` environment variable
|
|
30
|
+
2. System paths (``/usr/lib/renderdoc``, ``/usr/local/lib/renderdoc``)
|
|
31
|
+
3. Sibling directory of ``renderdoccmd`` on PATH
|
|
32
|
+
"""
|
|
33
|
+
candidates: list[str] = []
|
|
34
|
+
|
|
35
|
+
env_path = os.environ.get("RENDERDOC_PYTHON_PATH")
|
|
36
|
+
if env_path:
|
|
37
|
+
candidates.append(env_path)
|
|
38
|
+
|
|
39
|
+
candidates.extend(_SYSTEM_PATHS)
|
|
40
|
+
|
|
41
|
+
cmd = shutil.which("renderdoccmd")
|
|
42
|
+
if cmd:
|
|
43
|
+
candidates.append(str(Path(cmd).resolve().parent))
|
|
44
|
+
|
|
45
|
+
# Try already-importable module first (e.g. site-packages)
|
|
46
|
+
mod = _try_import()
|
|
47
|
+
if mod is not None:
|
|
48
|
+
return mod
|
|
49
|
+
|
|
50
|
+
for path in candidates:
|
|
51
|
+
if not Path(path).is_dir():
|
|
52
|
+
continue
|
|
53
|
+
mod = _try_import_from(path)
|
|
54
|
+
if mod is not None:
|
|
55
|
+
return mod
|
|
56
|
+
|
|
57
|
+
return None
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _try_import() -> ModuleType | None:
|
|
61
|
+
"""Try bare import without path manipulation."""
|
|
62
|
+
try:
|
|
63
|
+
return importlib.import_module("renderdoc")
|
|
64
|
+
except Exception: # noqa: BLE001
|
|
65
|
+
return None
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _try_import_from(directory: str) -> ModuleType | None:
|
|
69
|
+
"""Add *directory* to sys.path, attempt import, clean up on failure.
|
|
70
|
+
|
|
71
|
+
On success the directory stays in sys.path so that subsequent
|
|
72
|
+
``import renderdoc`` calls succeed. On failure it is removed.
|
|
73
|
+
"""
|
|
74
|
+
if directory in sys.path:
|
|
75
|
+
return _try_import()
|
|
76
|
+
|
|
77
|
+
sys.path.insert(0, directory)
|
|
78
|
+
try:
|
|
79
|
+
mod = importlib.import_module("renderdoc")
|
|
80
|
+
except Exception: # noqa: BLE001
|
|
81
|
+
sys.path.pop(0)
|
|
82
|
+
return None
|
|
83
|
+
log.debug("renderdoc found at %s", directory)
|
|
84
|
+
return mod
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""JSON and JSONL output formatters for rdc-cli."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import sys
|
|
7
|
+
from typing import Any, TextIO
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def write_json(data: Any, *, out: TextIO | None = None, indent: int = 2) -> None:
|
|
11
|
+
"""Write data as formatted JSON to the given output stream."""
|
|
12
|
+
dest = out or sys.stdout
|
|
13
|
+
dest.write(json.dumps(data, default=str, indent=indent) + "\n")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def write_jsonl(rows: list[dict[str, Any]], *, out: TextIO | None = None) -> None:
|
|
17
|
+
"""Write rows as JSONL (one JSON object per line)."""
|
|
18
|
+
dest = out or sys.stdout
|
|
19
|
+
for row in rows:
|
|
20
|
+
dest.write(json.dumps(row, default=str) + "\n")
|
rdc/formatters/tsv.py
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""TSV output formatter for rdc-cli.
|
|
2
|
+
|
|
3
|
+
All list commands output tab-separated values with optional header row.
|
|
4
|
+
Numbers are always raw (e.g. 1200000 not 1.2M). Empty fields are '-'.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import sys
|
|
10
|
+
from typing import Any, TextIO
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def escape_field(value: Any) -> str:
|
|
14
|
+
"""Escape a field value for TSV output.
|
|
15
|
+
|
|
16
|
+
Rules:
|
|
17
|
+
- None or empty string → '-'
|
|
18
|
+
- Tabs → '\\t'
|
|
19
|
+
- Newlines → '\\n'
|
|
20
|
+
- Everything else → str(value)
|
|
21
|
+
"""
|
|
22
|
+
if value is None:
|
|
23
|
+
return "-"
|
|
24
|
+
s = str(value)
|
|
25
|
+
if not s:
|
|
26
|
+
return "-"
|
|
27
|
+
return s.replace("\t", "\\t").replace("\n", "\\n")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def format_row(fields: list[Any]) -> str:
|
|
31
|
+
"""Format a single TSV row."""
|
|
32
|
+
return "\t".join(escape_field(f) for f in fields)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def write_tsv(
|
|
36
|
+
rows: list[list[Any]],
|
|
37
|
+
*,
|
|
38
|
+
header: list[str] | None = None,
|
|
39
|
+
no_header: bool = False,
|
|
40
|
+
out: TextIO | None = None,
|
|
41
|
+
) -> None:
|
|
42
|
+
"""Write rows as TSV to the given output stream.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
rows: List of rows, each row is a list of field values.
|
|
46
|
+
header: Column names for the header row.
|
|
47
|
+
no_header: If True, skip the header row even if provided.
|
|
48
|
+
out: Output stream. Defaults to sys.stdout.
|
|
49
|
+
"""
|
|
50
|
+
dest = out or sys.stdout
|
|
51
|
+
if header and not no_header:
|
|
52
|
+
dest.write(format_row(header) + "\n")
|
|
53
|
+
for row in rows:
|
|
54
|
+
dest.write(format_row(row) + "\n")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def write_footer(message: str, err: TextIO | None = None) -> None:
|
|
58
|
+
"""Write a footer/summary line to stderr."""
|
|
59
|
+
dest = err or sys.stderr
|
|
60
|
+
dest.write(message + "\n")
|
rdc/protocol.py
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass(frozen=True)
|
|
8
|
+
class JsonRpcRequest:
|
|
9
|
+
jsonrpc: str
|
|
10
|
+
method: str
|
|
11
|
+
id: int
|
|
12
|
+
params: dict[str, Any] | None = None
|
|
13
|
+
|
|
14
|
+
def to_dict(self) -> dict[str, Any]:
|
|
15
|
+
payload: dict[str, Any] = {
|
|
16
|
+
"jsonrpc": self.jsonrpc,
|
|
17
|
+
"method": self.method,
|
|
18
|
+
"id": self.id,
|
|
19
|
+
}
|
|
20
|
+
if self.params is not None:
|
|
21
|
+
payload["params"] = self.params
|
|
22
|
+
return payload
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _request(method: str, request_id: int, params: dict[str, Any] | None = None) -> JsonRpcRequest:
|
|
26
|
+
if request_id < 0:
|
|
27
|
+
raise ValueError("request id must be >= 0")
|
|
28
|
+
return JsonRpcRequest(jsonrpc="2.0", method=method, id=request_id, params=params)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def ping_request(token: str, request_id: int = 1) -> dict[str, Any]:
|
|
32
|
+
return _request("ping", request_id, {"_token": token}).to_dict()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def status_request(token: str, request_id: int = 1) -> dict[str, Any]:
|
|
36
|
+
return _request("status", request_id, {"_token": token}).to_dict()
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def goto_request(token: str, eid: int, request_id: int = 1) -> dict[str, Any]:
|
|
40
|
+
return _request("goto", request_id, {"_token": token, "eid": eid}).to_dict()
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def shutdown_request(token: str, request_id: int = 1) -> dict[str, Any]:
|
|
44
|
+
return _request("shutdown", request_id, {"_token": token}).to_dict()
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def count_request(
|
|
48
|
+
token: str,
|
|
49
|
+
what: str,
|
|
50
|
+
*,
|
|
51
|
+
pass_name: str | None = None,
|
|
52
|
+
request_id: int = 1,
|
|
53
|
+
) -> dict[str, Any]:
|
|
54
|
+
params: dict[str, Any] = {"_token": token, "what": what}
|
|
55
|
+
if pass_name is not None:
|
|
56
|
+
params["pass"] = pass_name
|
|
57
|
+
return _request("count", request_id, params).to_dict()
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def shader_map_request(token: str, request_id: int = 1) -> dict[str, Any]:
|
|
61
|
+
return _request("shader_map", request_id, {"_token": token}).to_dict()
|
rdc/services/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Service layer for rdc-cli."""
|