gcf-python 0.5.0__py3-none-any.whl → 1.0.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.
- gcf/__init__.py +1 -1
- gcf/decode.py +17 -7
- gcf/decode_generic.py +399 -149
- gcf/delta.py +1 -1
- gcf/encode.py +1 -1
- gcf/generic.py +148 -125
- gcf/scalar.py +298 -0
- gcf/session.py +1 -1
- gcf/stream.py +9 -9
- gcf/stream_generic.py +7 -27
- {gcf_python-0.5.0.dist-info → gcf_python-1.0.0.dist-info}/METADATA +23 -28
- gcf_python-1.0.0.dist-info/RECORD +18 -0
- {gcf_python-0.5.0.dist-info → gcf_python-1.0.0.dist-info}/licenses/LICENSE +1 -1
- gcf_python-0.5.0.dist-info/RECORD +0 -17
- {gcf_python-0.5.0.dist-info → gcf_python-1.0.0.dist-info}/WHEEL +0 -0
- {gcf_python-0.5.0.dist-info → gcf_python-1.0.0.dist-info}/entry_points.txt +0 -0
gcf/__init__.py
CHANGED
gcf/decode.py
CHANGED
|
@@ -35,7 +35,11 @@ def decode(input_text: str) -> Payload:
|
|
|
35
35
|
_parse_header(header[4:], p)
|
|
36
36
|
|
|
37
37
|
if not p.tool:
|
|
38
|
-
raise DecodeError("header missing required 'tool' field")
|
|
38
|
+
raise DecodeError("missing_tool: header missing required 'tool' field")
|
|
39
|
+
|
|
40
|
+
# Detect delta mode.
|
|
41
|
+
is_delta = "delta=true" in header
|
|
42
|
+
valid_delta_sections = {"removed", "added", "edges_removed", "edges_added"}
|
|
39
43
|
|
|
40
44
|
# Parse body: symbols and edges.
|
|
41
45
|
symbols: list[Symbol] = []
|
|
@@ -48,6 +52,10 @@ def decode(input_text: str) -> Payload:
|
|
|
48
52
|
if not line:
|
|
49
53
|
continue
|
|
50
54
|
|
|
55
|
+
# Skip ##! summary trailer.
|
|
56
|
+
if line.startswith("##! "):
|
|
57
|
+
continue
|
|
58
|
+
|
|
51
59
|
# Group header.
|
|
52
60
|
if line.startswith("## "):
|
|
53
61
|
group = line[3:]
|
|
@@ -55,6 +63,8 @@ def decode(input_text: str) -> Payload:
|
|
|
55
63
|
bracket_idx = group.find(" [")
|
|
56
64
|
if bracket_idx >= 0:
|
|
57
65
|
group = group[:bracket_idx]
|
|
66
|
+
if is_delta and group not in valid_delta_sections:
|
|
67
|
+
raise DecodeError(f"malformed_delta: invalid delta section {group!r}")
|
|
58
68
|
in_edges = group == "edges"
|
|
59
69
|
if not in_edges:
|
|
60
70
|
if group == "targets":
|
|
@@ -113,19 +123,19 @@ def _parse_header(fields: str, p: Payload) -> None:
|
|
|
113
123
|
def _parse_symbol_line(line: str, distance: int) -> tuple[Symbol, int]:
|
|
114
124
|
"""Parse a symbol line into a Symbol and its local ID."""
|
|
115
125
|
if not line.startswith("@"):
|
|
116
|
-
raise DecodeError(f"expected symbol line starting with @, got {line!r}")
|
|
126
|
+
raise DecodeError(f"invalid_node_line: expected symbol line starting with @, got {line!r}")
|
|
117
127
|
|
|
118
128
|
parts = line.split()
|
|
119
129
|
if len(parts) < 5:
|
|
120
130
|
raise DecodeError(
|
|
121
|
-
f"symbol line needs at least 5 fields, got {len(parts)} in {line!r}"
|
|
131
|
+
f"invalid_node_line: symbol line needs at least 5 fields, got {len(parts)} in {line!r}"
|
|
122
132
|
)
|
|
123
133
|
|
|
124
134
|
id_str = parts[0][1:] # strip @
|
|
125
135
|
try:
|
|
126
136
|
sym_id = int(id_str)
|
|
127
137
|
except ValueError as e:
|
|
128
|
-
raise DecodeError(f"invalid symbol id {id_str!r}: {e}") from e
|
|
138
|
+
raise DecodeError(f"invalid_symbol_id: invalid symbol id {id_str!r}: {e}") from e
|
|
129
139
|
|
|
130
140
|
kind = parts[1]
|
|
131
141
|
kind = KIND_EXPAND.get(kind, kind)
|
|
@@ -135,7 +145,7 @@ def _parse_symbol_line(line: str, distance: int) -> tuple[Symbol, int]:
|
|
|
135
145
|
try:
|
|
136
146
|
score = float(parts[3])
|
|
137
147
|
except ValueError as e:
|
|
138
|
-
raise DecodeError(f"invalid score {parts[3]!r}: {e}") from e
|
|
148
|
+
raise DecodeError(f"invalid_score: invalid score {parts[3]!r}: {e}") from e
|
|
139
149
|
|
|
140
150
|
provenance = parts[4]
|
|
141
151
|
|
|
@@ -157,7 +167,7 @@ def _parse_edge_line(line: str, sym_by_id: dict[int, Symbol]) -> Edge:
|
|
|
157
167
|
ref = parts[0]
|
|
158
168
|
lt_idx = ref.find("<")
|
|
159
169
|
if lt_idx < 0:
|
|
160
|
-
raise DecodeError(f"edge line missing '<' separator in {ref!r}")
|
|
170
|
+
raise DecodeError(f"invalid_edge_syntax: edge line missing '<' separator in {ref!r}")
|
|
161
171
|
|
|
162
172
|
target_id_str = ref[1:lt_idx] # strip leading @
|
|
163
173
|
source_id_str = ref[lt_idx + 2:] # strip <@
|
|
@@ -176,7 +186,7 @@ def _parse_edge_line(line: str, sym_by_id: dict[int, Symbol]) -> Edge:
|
|
|
176
186
|
source_sym = sym_by_id.get(source_id)
|
|
177
187
|
if target_sym is None or source_sym is None:
|
|
178
188
|
raise DecodeError(
|
|
179
|
-
f"edge references unknown symbol id(s): target={target_id} source={source_id}"
|
|
189
|
+
f"unknown_edge_reference: edge references unknown symbol id(s): target={target_id} source={source_id}"
|
|
180
190
|
)
|
|
181
191
|
|
|
182
192
|
edge_type = parts[1]
|