gcf-python 2.1.0__py3-none-any.whl → 2.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.
- gcf/decode_generic.py +91 -9
- gcf/generic.py +145 -5
- gcf/scalar.py +3 -0
- {gcf_python-2.1.0.dist-info → gcf_python-2.2.0.dist-info}/METADATA +21 -21
- {gcf_python-2.1.0.dist-info → gcf_python-2.2.0.dist-info}/RECORD +8 -8
- {gcf_python-2.1.0.dist-info → gcf_python-2.2.0.dist-info}/WHEEL +0 -0
- {gcf_python-2.1.0.dist-info → gcf_python-2.2.0.dist-info}/entry_points.txt +0 -0
- {gcf_python-2.1.0.dist-info → gcf_python-2.2.0.dist-info}/licenses/LICENSE +0 -0
gcf/decode_generic.py
CHANGED
|
@@ -151,6 +151,17 @@ def _parse_object_body(
|
|
|
151
151
|
i += consumed
|
|
152
152
|
continue
|
|
153
153
|
|
|
154
|
+
# Key=value. Check before inline array so bracket patterns in quoted
|
|
155
|
+
# values (e.g. text="ERR[404]: Not Found") are not misinterpreted.
|
|
156
|
+
eq_idx = _find_kv_split(content)
|
|
157
|
+
if eq_idx > 0:
|
|
158
|
+
name = _parse_key_from_header(content[:eq_idx])
|
|
159
|
+
_check_dup(out, name)
|
|
160
|
+
out[name] = parse_scalar(content[eq_idx + 1:])
|
|
161
|
+
i += 1
|
|
162
|
+
continue
|
|
163
|
+
|
|
164
|
+
# Inline array (e.g. items[3]: a,b,c). Only reached if no = found.
|
|
154
165
|
if not content.startswith("@") and not content.startswith("##"):
|
|
155
166
|
bracket_idx = content.find("[")
|
|
156
167
|
if bracket_idx > 0:
|
|
@@ -166,14 +177,6 @@ def _parse_object_body(
|
|
|
166
177
|
i += 1
|
|
167
178
|
continue
|
|
168
179
|
|
|
169
|
-
eq_idx = _find_kv_split(content)
|
|
170
|
-
if eq_idx > 0:
|
|
171
|
-
name = _parse_key_from_header(content[:eq_idx])
|
|
172
|
-
_check_dup(out, name)
|
|
173
|
-
out[name] = parse_scalar(content[eq_idx + 1:])
|
|
174
|
-
i += 1
|
|
175
|
-
continue
|
|
176
|
-
|
|
177
180
|
i += 1
|
|
178
181
|
return i - start
|
|
179
182
|
|
|
@@ -191,7 +194,13 @@ def _find_kv_split(s: str) -> int:
|
|
|
191
194
|
return i + 1 if i + 1 < len(s) and s[i + 1] == "=" else -1
|
|
192
195
|
i += 1
|
|
193
196
|
return -1
|
|
194
|
-
|
|
197
|
+
eq_idx = s.find("=")
|
|
198
|
+
if eq_idx < 0:
|
|
199
|
+
return -1
|
|
200
|
+
bracket_idx = s.find("[")
|
|
201
|
+
if bracket_idx >= 0 and bracket_idx < eq_idx:
|
|
202
|
+
return -1
|
|
203
|
+
return eq_idx
|
|
195
204
|
|
|
196
205
|
|
|
197
206
|
def _parse_key_from_header(s: str) -> str:
|
|
@@ -354,6 +363,55 @@ def _parse_attachment(
|
|
|
354
363
|
raise ValueError(f"invalid attachment form: {after_name}")
|
|
355
364
|
|
|
356
365
|
|
|
366
|
+
def _unflatten_paths(
|
|
367
|
+
path_columns: dict[str, list[str]],
|
|
368
|
+
flat_values: dict[str, Any],
|
|
369
|
+
flat_absent: set[str],
|
|
370
|
+
) -> dict[str, Any]:
|
|
371
|
+
"""Reconstruct nested objects from flat > path columns."""
|
|
372
|
+
groups: dict[str, list[str]] = {}
|
|
373
|
+
group_order: list[str] = []
|
|
374
|
+
for field_name, paths in path_columns.items():
|
|
375
|
+
if not paths:
|
|
376
|
+
continue
|
|
377
|
+
top = paths[0]
|
|
378
|
+
if top not in groups:
|
|
379
|
+
groups[top] = []
|
|
380
|
+
group_order.append(top)
|
|
381
|
+
groups[top].append(field_name)
|
|
382
|
+
|
|
383
|
+
result: dict[str, Any] = {}
|
|
384
|
+
|
|
385
|
+
for top in group_order:
|
|
386
|
+
field_names = groups[top]
|
|
387
|
+
all_absent = all(f in flat_absent for f in field_names)
|
|
388
|
+
all_null = all(
|
|
389
|
+
(f not in flat_absent and flat_values.get(f) is None)
|
|
390
|
+
for f in field_names
|
|
391
|
+
)
|
|
392
|
+
|
|
393
|
+
if all_absent:
|
|
394
|
+
continue
|
|
395
|
+
if all_null:
|
|
396
|
+
result[top] = None
|
|
397
|
+
continue
|
|
398
|
+
|
|
399
|
+
for field_name in field_names:
|
|
400
|
+
if field_name in flat_absent:
|
|
401
|
+
continue
|
|
402
|
+
paths = path_columns[field_name]
|
|
403
|
+
val = flat_values.get(field_name)
|
|
404
|
+
|
|
405
|
+
current = result
|
|
406
|
+
for k in paths[:-1]:
|
|
407
|
+
if k not in current:
|
|
408
|
+
current[k] = {}
|
|
409
|
+
current = current[k]
|
|
410
|
+
current[paths[-1]] = val
|
|
411
|
+
|
|
412
|
+
return result
|
|
413
|
+
|
|
414
|
+
|
|
357
415
|
def _parse_tabular_body(
|
|
358
416
|
lines: list[str], start: int, depth: int, fields: list[str], expected_count: int
|
|
359
417
|
) -> tuple[list[Any], int]:
|
|
@@ -361,6 +419,12 @@ def _parse_tabular_body(
|
|
|
361
419
|
rows: list[Any] = []
|
|
362
420
|
i = start
|
|
363
421
|
|
|
422
|
+
# Detect path columns: fields containing ">".
|
|
423
|
+
path_column_map: dict[str, list[str]] = {}
|
|
424
|
+
for f in fields:
|
|
425
|
+
if ">" in f:
|
|
426
|
+
path_column_map[f] = f.split(">")
|
|
427
|
+
|
|
364
428
|
# Track inline schemas and shared array schemas.
|
|
365
429
|
inline_schemas: dict[str, list[str]] = {}
|
|
366
430
|
shared_array_schemas: dict[str, list[str]] = {}
|
|
@@ -400,9 +464,22 @@ def _parse_tabular_body(
|
|
|
400
464
|
inline_att_order: list[str] = []
|
|
401
465
|
missing_fields: set[str] = set()
|
|
402
466
|
|
|
467
|
+
# Collect path column values for unflattening.
|
|
468
|
+
flat_values: dict[str, Any] = {}
|
|
469
|
+
flat_absent: set[str] = set()
|
|
470
|
+
|
|
403
471
|
for j, f in enumerate(fields):
|
|
404
472
|
cell_val = vals[j]
|
|
405
473
|
|
|
474
|
+
# Path columns: store values for later unflattening.
|
|
475
|
+
if f in path_column_map:
|
|
476
|
+
parsed = parse_scalar(cell_val, tabular_context=True)
|
|
477
|
+
if parsed is MISSING:
|
|
478
|
+
flat_absent.add(f)
|
|
479
|
+
else:
|
|
480
|
+
flat_values[f] = parsed
|
|
481
|
+
continue
|
|
482
|
+
|
|
406
483
|
# Check for ^{fields} inline schema declaration.
|
|
407
484
|
if cell_val.startswith("^{") and cell_val.endswith("}"):
|
|
408
485
|
schema_str = cell_val[1:]
|
|
@@ -539,6 +616,11 @@ def _parse_tabular_body(
|
|
|
539
616
|
row[f] = cell_values[f]
|
|
540
617
|
elif f in attachment_values:
|
|
541
618
|
row[f] = attachment_values[f]
|
|
619
|
+
# Unflatten path columns into nested objects.
|
|
620
|
+
if path_column_map:
|
|
621
|
+
nested = _unflatten_paths(path_column_map, flat_values, flat_absent)
|
|
622
|
+
row.update(nested)
|
|
623
|
+
|
|
542
624
|
rows.append(row)
|
|
543
625
|
|
|
544
626
|
if expected_count >= 0 and len(rows) >= expected_count:
|
gcf/generic.py
CHANGED
|
@@ -145,15 +145,136 @@ def _shared_array_schema(arr: list[dict], field_name: str) -> list[str] | None:
|
|
|
145
145
|
return canonical_fields
|
|
146
146
|
|
|
147
147
|
|
|
148
|
+
# ── Nested object flattening (v3.2) ──────────────────────────────────────
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _analyze_flattenable(
|
|
152
|
+
arr: list[dict], field_name: str, parent_path: str
|
|
153
|
+
) -> list[dict] | None:
|
|
154
|
+
"""Analyze whether a field can be flattened. Returns list of leaf descriptors or None."""
|
|
155
|
+
canonical_shape: dict[str, str] | None = None # key -> "scalar" | "nested"
|
|
156
|
+
|
|
157
|
+
for item in arr:
|
|
158
|
+
if field_name not in item or item[field_name] is None:
|
|
159
|
+
continue
|
|
160
|
+
v = item[field_name]
|
|
161
|
+
if not isinstance(v, dict):
|
|
162
|
+
return None
|
|
163
|
+
if isinstance(v, list):
|
|
164
|
+
return None
|
|
165
|
+
|
|
166
|
+
keys = list(v.keys())
|
|
167
|
+
|
|
168
|
+
if canonical_shape is None:
|
|
169
|
+
canonical_shape = {}
|
|
170
|
+
for k in keys:
|
|
171
|
+
if ">" in k:
|
|
172
|
+
return None
|
|
173
|
+
val = v[k]
|
|
174
|
+
if isinstance(val, list):
|
|
175
|
+
return None
|
|
176
|
+
elif isinstance(val, dict):
|
|
177
|
+
canonical_shape[k] = "nested"
|
|
178
|
+
else:
|
|
179
|
+
canonical_shape[k] = "scalar"
|
|
180
|
+
else:
|
|
181
|
+
if len(keys) != len(canonical_shape):
|
|
182
|
+
return None
|
|
183
|
+
for k in keys:
|
|
184
|
+
if k not in canonical_shape:
|
|
185
|
+
return None
|
|
186
|
+
val = v[k]
|
|
187
|
+
expected = canonical_shape[k]
|
|
188
|
+
if expected == "scalar":
|
|
189
|
+
if isinstance(val, (dict, list)):
|
|
190
|
+
return None
|
|
191
|
+
elif expected == "nested":
|
|
192
|
+
if isinstance(val, list):
|
|
193
|
+
return None
|
|
194
|
+
if val is not None and not isinstance(val, dict):
|
|
195
|
+
return None
|
|
196
|
+
|
|
197
|
+
if canonical_shape is None:
|
|
198
|
+
return None
|
|
199
|
+
|
|
200
|
+
current_path = f"{parent_path}>{field_name}" if parent_path else field_name
|
|
201
|
+
parent_keys = parent_path.split(">") + [field_name] if parent_path else [field_name]
|
|
202
|
+
|
|
203
|
+
leaves: list[dict] = []
|
|
204
|
+
for k in canonical_shape:
|
|
205
|
+
if canonical_shape[k] == "scalar":
|
|
206
|
+
leaves.append({"path": f"{current_path}>{k}", "keys": parent_keys + [k]})
|
|
207
|
+
else:
|
|
208
|
+
sub_arr = []
|
|
209
|
+
for item in arr:
|
|
210
|
+
if field_name not in item or item[field_name] is None:
|
|
211
|
+
sub_arr.append({})
|
|
212
|
+
else:
|
|
213
|
+
sub_arr.append(item[field_name])
|
|
214
|
+
sub_leaves = _analyze_flattenable(sub_arr, k, current_path)
|
|
215
|
+
if sub_leaves is None or len(sub_leaves) == 0:
|
|
216
|
+
return None
|
|
217
|
+
leaves.extend(sub_leaves)
|
|
218
|
+
|
|
219
|
+
# Guard: reject if any row has non-null object with all-null leaves.
|
|
220
|
+
if leaves:
|
|
221
|
+
for item in arr:
|
|
222
|
+
if field_name not in item or item[field_name] is None:
|
|
223
|
+
continue
|
|
224
|
+
all_null = all(
|
|
225
|
+
_resolve_key_chain(item, leaf["keys"])[0] is None
|
|
226
|
+
and _resolve_key_chain(item, leaf["keys"])[1]
|
|
227
|
+
for leaf in leaves
|
|
228
|
+
)
|
|
229
|
+
if all_null:
|
|
230
|
+
return None
|
|
231
|
+
|
|
232
|
+
return leaves
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def _resolve_key_chain(item: Any, keys: list[str]) -> tuple[Any, bool]:
|
|
236
|
+
"""Traverse an object by key chain. Returns (value, exists)."""
|
|
237
|
+
if not keys or not isinstance(item, dict):
|
|
238
|
+
return None, False
|
|
239
|
+
if keys[0] not in item:
|
|
240
|
+
return None, False
|
|
241
|
+
current = item[keys[0]]
|
|
242
|
+
if current is None:
|
|
243
|
+
return None, True
|
|
244
|
+
for k in keys[1:]:
|
|
245
|
+
if not isinstance(current, dict) or k not in current:
|
|
246
|
+
return None, False
|
|
247
|
+
current = current[k]
|
|
248
|
+
return current, True
|
|
249
|
+
|
|
250
|
+
|
|
148
251
|
def _encode_tabular(
|
|
149
252
|
header_prefix: str, arr: list[dict], fields: list[str], out: list[str], depth: int
|
|
150
253
|
) -> None:
|
|
151
254
|
prefix = _indent(depth)
|
|
152
255
|
|
|
153
|
-
#
|
|
256
|
+
# Phase 0: Analyze fields for flattening.
|
|
257
|
+
flatten_map: dict[str, list[dict]] = {}
|
|
258
|
+
for f in fields:
|
|
259
|
+
leaves = _analyze_flattenable(arr, f, "")
|
|
260
|
+
if leaves and len(leaves) > 0:
|
|
261
|
+
flatten_map[f] = leaves
|
|
262
|
+
|
|
263
|
+
# Build expanded column list.
|
|
264
|
+
columns: list[dict] = []
|
|
265
|
+
for f in fields:
|
|
266
|
+
if f in flatten_map:
|
|
267
|
+
for leaf in flatten_map[f]:
|
|
268
|
+
columns.append({"header": format_key(leaf["path"]), "type": "flat", "field": f, "keys": leaf["keys"]})
|
|
269
|
+
else:
|
|
270
|
+
columns.append({"header": format_key(f), "type": "original", "field": f, "keys": []})
|
|
271
|
+
|
|
272
|
+
# Pre-compute inline schemas and shared array schemas (skip flattened fields).
|
|
154
273
|
inline_schemas: dict[str, list[str]] = {}
|
|
155
274
|
shared_arr_schemas: dict[str, list[str]] = {}
|
|
156
275
|
for f in fields:
|
|
276
|
+
if f in flatten_map:
|
|
277
|
+
continue
|
|
157
278
|
ifs = _inline_schema_fields(arr, f)
|
|
158
279
|
if ifs is not None:
|
|
159
280
|
inline_schemas[f] = ifs
|
|
@@ -161,15 +282,34 @@ def _encode_tabular(
|
|
|
161
282
|
if sas is not None:
|
|
162
283
|
shared_arr_schemas[f] = sas
|
|
163
284
|
|
|
164
|
-
|
|
165
|
-
out.append(f"{header_prefix}[{len(arr)}]{{{
|
|
285
|
+
header_fields = ",".join(col["header"] for col in columns)
|
|
286
|
+
out.append(f"{header_prefix}[{len(arr)}]{{{header_fields}}}")
|
|
166
287
|
|
|
167
288
|
for i, item in enumerate(arr):
|
|
168
289
|
cells: list[str] = []
|
|
169
|
-
attachments: list[tuple[str, Any, bool, list[str] | None]] = []
|
|
290
|
+
attachments: list[tuple[str, Any, bool, list[str] | None]] = []
|
|
170
291
|
row_has_attachment = False
|
|
171
292
|
|
|
172
|
-
for
|
|
293
|
+
for col in columns:
|
|
294
|
+
if col["type"] == "flat":
|
|
295
|
+
keys = col["keys"]
|
|
296
|
+
if keys[0] not in item:
|
|
297
|
+
cells.append("~")
|
|
298
|
+
else:
|
|
299
|
+
top_val = item[keys[0]]
|
|
300
|
+
if top_val is None:
|
|
301
|
+
cells.append("-")
|
|
302
|
+
else:
|
|
303
|
+
val, exists = _resolve_key_chain(item, keys)
|
|
304
|
+
if not exists:
|
|
305
|
+
cells.append("~")
|
|
306
|
+
elif val is None:
|
|
307
|
+
cells.append("-")
|
|
308
|
+
else:
|
|
309
|
+
cells.append(format_scalar(val, "|"))
|
|
310
|
+
continue
|
|
311
|
+
|
|
312
|
+
f = col["field"]
|
|
173
313
|
if f not in item:
|
|
174
314
|
cells.append("~")
|
|
175
315
|
continue
|
gcf/scalar.py
CHANGED
|
@@ -8,6 +8,7 @@ from typing import Any
|
|
|
8
8
|
|
|
9
9
|
_JSON_NUMBER_RE = re.compile(r"^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$")
|
|
10
10
|
_NUMERIC_LIKE_RE = re.compile(r"^[+-]\.?\d|^\.\d|^0\d")
|
|
11
|
+
_INLINE_ARRAY_RE = re.compile(r"\[[^\]]*\]\s*:")
|
|
11
12
|
_BARE_KEY_RE = re.compile(r"^[a-zA-Z_][a-zA-Z0-9_]*$")
|
|
12
13
|
|
|
13
14
|
|
|
@@ -36,6 +37,8 @@ def needs_quote(s: str) -> bool:
|
|
|
36
37
|
return True
|
|
37
38
|
if s[0] in ("#", "@", "."):
|
|
38
39
|
return True
|
|
40
|
+
if _INLINE_ARRAY_RE.search(s):
|
|
41
|
+
return True
|
|
39
42
|
for c in s:
|
|
40
43
|
o = ord(c)
|
|
41
44
|
if c in ('"', "\\", "|", ",") or o < 0x20 or c in ("\n", "\r"):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gcf-python
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: Drop-in JSON replacement for AI pipelines. 79% fewer tokens. 90.7% comprehension across 10 models. Zero dependencies.
|
|
5
5
|
Project-URL: Homepage, https://github.com/blackwell-systems/gcf-python
|
|
6
6
|
Project-URL: Documentation, https://blackwell-systems.github.io/gcf/
|
|
@@ -217,26 +217,26 @@ Works on dicts, lists, and primitives. Lists of uniform dicts get tabular rows.
|
|
|
217
217
|
|
|
218
218
|
GCF wins 13/15 datasets on the expanded [token efficiency benchmark](https://github.com/blackwell-systems/toon/tree/gcf-comparison). Full results: [gcformat.com/guide/benchmarks](https://gcformat.com/guide/benchmarks.html)
|
|
219
219
|
|
|
220
|
-
##
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
- [
|
|
225
|
-
- [
|
|
226
|
-
- [
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
- [
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
220
|
+
## Implementations
|
|
221
|
+
|
|
222
|
+
| Language | Package | Repository |
|
|
223
|
+
|----------|---------|-----------|
|
|
224
|
+
| Go | `go get github.com/blackwell-systems/gcf-go` | [gcf-go](https://github.com/blackwell-systems/gcf-go) |
|
|
225
|
+
| TypeScript | `npm install @blackwell-systems/gcf` | [gcf-typescript](https://github.com/blackwell-systems/gcf-typescript) |
|
|
226
|
+
| Python | `pip install gcf-python` | [gcf-python](https://github.com/blackwell-systems/gcf-python) |
|
|
227
|
+
| Rust | `cargo add gcf` | [gcf-rust](https://github.com/blackwell-systems/gcf-rust) |
|
|
228
|
+
| Swift | Swift Package Manager | [gcf-swift](https://github.com/blackwell-systems/gcf-swift) |
|
|
229
|
+
| Kotlin | JitPack | [gcf-kotlin](https://github.com/blackwell-systems/gcf-kotlin) |
|
|
230
|
+
| MCP Proxy | `pip install gcf-proxy` | [gcf-proxy](https://github.com/blackwell-systems/gcf-proxy) (bidirectional, session dedup, HTTP frontend) |
|
|
231
|
+
| Claude Code Plugin | `/plugin install` | [gcf-claude-plugin](https://github.com/blackwell-systems/gcf-claude-plugin) (one-command install, session stats hook) |
|
|
232
|
+
| Codex Plugin | `codex plugin add` | [gcf-codex-plugin](https://github.com/blackwell-systems/gcf-codex-plugin) (one-command install, session stats hook) |
|
|
233
|
+
| VS Code | `ext install blackwell-systems.gcf-vscode` | [gcf-vscode](https://marketplace.visualstudio.com/items?itemName=blackwell-systems.gcf-vscode) (syntax highlighting) |
|
|
234
|
+
| n8n | `npm install n8n-nodes-gcf` | [gcf-n8n-nodes](https://github.com/blackwell-systems/gcf-n8n-nodes) (workflow encode/decode) |
|
|
235
|
+
| Tree-sitter | `npm install tree-sitter-gcf` | [tree-sitter-gcf](https://github.com/blackwell-systems/tree-sitter-gcf) |
|
|
236
|
+
|
|
237
|
+
**Zero runtime dependencies. Permanently.** All six implementations depend only on their language's standard library. No transitive dependencies. No supply chain risk. This is a permanent commitment: GCF will never take on external runtime dependencies. MIT licensed. All implementations support both generic profile (`encodeGeneric`) and graph profile (`encode`). CLI included in all 6 languages.
|
|
238
|
+
|
|
239
|
+
**Specification:** [SPEC v3.1 Stable](https://github.com/blackwell-systems/gcf/blob/main/SPEC.md) with 157 conformance fixtures, 33,000,000,000+ lossless round-trips verified across 5 formats and 6 languages. All implementations at v2.1.0+ (Go v1.2.0). Cross-language 6x6 matrix verified.
|
|
240
240
|
|
|
241
241
|
## License
|
|
242
242
|
|
|
@@ -3,17 +3,17 @@ gcf/__main__.py,sha256=EpvBz1yc8H0D5OJ1zy2tYke-kRzvudKa4DEbfeW14ao,71
|
|
|
3
3
|
gcf/cli.py,sha256=UEe1CAZn-rKGNIo_ap8-oez3ucl6DSRbsdv6RDnzygY,5256
|
|
4
4
|
gcf/constants.py,sha256=cmZ8YJSOB0im_eyfN8v4UvrLpBC6Fuf4cfcKZGbutxY,638
|
|
5
5
|
gcf/decode.py,sha256=nD8bXYhoeHQQ3LCeAJQOAgFuob-V_6us4mcBYtL_bBc,5978
|
|
6
|
-
gcf/decode_generic.py,sha256=
|
|
6
|
+
gcf/decode_generic.py,sha256=QdwXIPZhTTJsfaYInYKW0TKr8Ln5cufmRE2kl40_kpY,26034
|
|
7
7
|
gcf/delta.py,sha256=f90UC6zejXH-ujyU_OViWDCqnxLXk3i6Qion-RJGHY4,1670
|
|
8
8
|
gcf/encode.py,sha256=CcqMSNmojrQAAw2X3MNfw8YR6l4rNw9hWDqwmf846oA,2929
|
|
9
|
-
gcf/generic.py,sha256=
|
|
10
|
-
gcf/scalar.py,sha256=
|
|
9
|
+
gcf/generic.py,sha256=7cSwYT_U3ySTZy8yLY_GtQrzzGIRkhHOE1SEIGmhdrg,15458
|
|
10
|
+
gcf/scalar.py,sha256=MZay-KIROvaFHet-g2-pBghahT1bf_5bxZjG4yTZkSo,9329
|
|
11
11
|
gcf/session.py,sha256=6-wytNGaBkgqH7uTar7ojUFYNwIMeEVAZhuV-s-upZM,4704
|
|
12
12
|
gcf/stream.py,sha256=1Kt_a2daKpYHlWP1lnDJ4g549pUt9rc-U0xbARbXRKQ,5174
|
|
13
13
|
gcf/stream_generic.py,sha256=RnqqiPSu5joJa-7e58QbbzSGfvxBICA587A3aArjZvE,3250
|
|
14
14
|
gcf/types.py,sha256=AWm-LQoSqLHAYtEjcAxWQZqJ4JXqNreLUKO2mJFgNMA,1465
|
|
15
|
-
gcf_python-2.
|
|
16
|
-
gcf_python-2.
|
|
17
|
-
gcf_python-2.
|
|
18
|
-
gcf_python-2.
|
|
19
|
-
gcf_python-2.
|
|
15
|
+
gcf_python-2.2.0.dist-info/METADATA,sha256=Kc-fEX3jOtbvgBPwEiQL0gRf4hibJYlGJu4ea05kGfw,9781
|
|
16
|
+
gcf_python-2.2.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
17
|
+
gcf_python-2.2.0.dist-info/entry_points.txt,sha256=aFT6gqlkh8iGfM8cblE-LUMxHH08_v71IIoZtDdRIVA,37
|
|
18
|
+
gcf_python-2.2.0.dist-info/licenses/LICENSE,sha256=2Fit9wnaIe--RMSAgyQqxC5hfZTyZqn4fIdBtp9qPDw,1072
|
|
19
|
+
gcf_python-2.2.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|