behavior-contracts 0.7.2__tar.gz → 0.8.0__tar.gz
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.
- {behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/PKG-INFO +3 -3
- {behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/README.md +2 -2
- {behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/pyproject.toml +1 -1
- {behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/src/behavior_contracts/__init__.py +5 -2
- {behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/src/behavior_contracts/behavior.py +70 -2
- {behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/src/behavior_contracts/conformance.py +41 -1
- {behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/src/behavior_contracts.egg-info/PKG-INFO +3 -3
- {behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/tests/test_codegen_generated.py +1 -1
- {behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/tests/test_conformance.py +1 -1
- {behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/tests/test_public_api.py +3 -2
- {behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/setup.cfg +0 -0
- {behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/src/behavior_contracts/canonical.py +0 -0
- {behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/src/behavior_contracts/codec.py +0 -0
- {behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/src/behavior_contracts/envelope.py +0 -0
- {behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/src/behavior_contracts/expr_eval.py +0 -0
- {behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/src/behavior_contracts/fingerprint.py +0 -0
- {behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/src/behavior_contracts/guard.py +0 -0
- {behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/src/behavior_contracts/plan.py +0 -0
- {behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/src/behavior_contracts/primitives.py +0 -0
- {behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/src/behavior_contracts/template.py +0 -0
- {behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/src/behavior_contracts.egg-info/SOURCES.txt +0 -0
- {behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/src/behavior_contracts.egg-info/dependency_links.txt +0 -0
- {behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/src/behavior_contracts.egg-info/entry_points.txt +0 -0
- {behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/src/behavior_contracts.egg-info/requires.txt +0 -0
- {behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/src/behavior_contracts.egg-info/top_level.txt +0 -0
- {behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/tests/test_plan_parallel.py +0 -0
- {behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/tests/test_primitives.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: behavior-contracts
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.0
|
|
4
4
|
Summary: Multi-language IR-Runtime common core (Python port). The COMMON 'thin core' primitives from dsl-contracts runtime-boundary.md — validate_envelope / evaluate_expression / render_template / run_plan / canonical_value / canonical_json / py_float_repr / assert_portable — with zero backend (DynamoDB/graphddb) dependencies.
|
|
5
5
|
Author: foo-log
|
|
6
6
|
License: MIT
|
|
@@ -60,12 +60,12 @@ string matching the conformance protocol's failure-code set.
|
|
|
60
60
|
|
|
61
61
|
## Conformance
|
|
62
62
|
|
|
63
|
-
Runs the
|
|
63
|
+
Runs the 8 shared suites (173 vectors) from `../conformance/vectors/*.json`
|
|
64
64
|
through this package per [`../conformance/PROTOCOL.md`](../conformance/PROTOCOL.md),
|
|
65
65
|
including the pre-flight version fail-closed sweep.
|
|
66
66
|
|
|
67
67
|
```bash
|
|
68
|
-
python -m behavior_contracts.conformance # → "
|
|
68
|
+
python -m behavior_contracts.conformance # → "173 passed, 0 failed / 173 vectors across 8 suites"
|
|
69
69
|
# or the console script:
|
|
70
70
|
behavior-contracts-conformance
|
|
71
71
|
```
|
|
@@ -48,12 +48,12 @@ string matching the conformance protocol's failure-code set.
|
|
|
48
48
|
|
|
49
49
|
## Conformance
|
|
50
50
|
|
|
51
|
-
Runs the
|
|
51
|
+
Runs the 8 shared suites (173 vectors) from `../conformance/vectors/*.json`
|
|
52
52
|
through this package per [`../conformance/PROTOCOL.md`](../conformance/PROTOCOL.md),
|
|
53
53
|
including the pre-flight version fail-closed sweep.
|
|
54
54
|
|
|
55
55
|
```bash
|
|
56
|
-
python -m behavior_contracts.conformance # → "
|
|
56
|
+
python -m behavior_contracts.conformance # → "173 passed, 0 failed / 173 vectors across 8 suites"
|
|
57
57
|
# or the console script:
|
|
58
58
|
behavior-contracts-conformance
|
|
59
59
|
```
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "behavior-contracts"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.8.0"
|
|
8
8
|
description = "Multi-language IR-Runtime common core (Python port). The COMMON 'thin core' primitives from dsl-contracts runtime-boundary.md — validate_envelope / evaluate_expression / render_template / run_plan / canonical_value / canonical_json / py_float_repr / assert_portable — with zero backend (DynamoDB/graphddb) dependencies."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -22,9 +22,10 @@ SPEC_VERSIONS = {
|
|
|
22
22
|
"template": 1,
|
|
23
23
|
"plan": 1,
|
|
24
24
|
"canonical": 2, # v2: obj 値の __proto__ own key を FORBIDDEN_KEY に(fail-closed)
|
|
25
|
-
"behavior":
|
|
26
|
-
"guard":
|
|
25
|
+
"behavior": 4, # v4(#128/A6・SCP-only): provenance token + 全ノード型確定を serialized-IR 不変条件へ格上げ(released 3=fanout を retire)。v1–v3 意味論は不変だが旧 runtime(behavior≤3)は新 IR を loud reject する(機構 = 生成モジュールの baked-spec-skew ゲート[EXPECTED_SPEC_VERSIONS.behavior vs runtime] + conformance pre-flight version fail-closed。validate_envelope は envelope の specVersion「major.minor」文字列を見るのであって behaviorVersion 整数ではない)
|
|
26
|
+
"guard": 2, # v2(#128/A6): assert_compiled + UNTYPED_NODE + operator 型シグネチャ SSoT の accept/reject を vector-pin(v1 は bc#25 の可搬性 pin のみ)
|
|
27
27
|
"c2": 1, # 初版(bc#28: c2-catalog-swap — catalog-swap 実行 + IR 構造一致の 5 言語 pin)
|
|
28
|
+
"provenance": 1, # 初版(#128/A6): シリアライズ境界の canonical fingerprint 照合(改竄/stale の 5 言語 loud reject)+ 非空虚性(CONFORMANCE_MUTATE)
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
# validate_envelope に渡す graphddb 形式の既定 supported 版(``"<major>.<minor>"``)。
|
|
@@ -80,6 +81,7 @@ from .guard import ( # noqa: E402
|
|
|
80
81
|
# ── behavior(component-graph IR + run_behavior) ──────────────────────────────
|
|
81
82
|
from .behavior import ( # noqa: E402
|
|
82
83
|
BehaviorFailure,
|
|
84
|
+
fanout_dedup_drop,
|
|
83
85
|
run_behavior,
|
|
84
86
|
)
|
|
85
87
|
|
|
@@ -143,6 +145,7 @@ __all__ = [
|
|
|
143
145
|
"PortabilityError",
|
|
144
146
|
# behavior
|
|
145
147
|
"run_behavior",
|
|
148
|
+
"fanout_dedup_drop",
|
|
146
149
|
"BehaviorFailure",
|
|
147
150
|
# codec
|
|
148
151
|
"decode_value",
|
|
@@ -52,16 +52,20 @@ def _bfail(code: str, message: str) -> "None":
|
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
def _node_kind(n: Mapping[str, Any]) -> str:
|
|
55
|
+
if "fanout" in n:
|
|
56
|
+
return "fanout"
|
|
55
57
|
if "map" in n:
|
|
56
58
|
return "map"
|
|
57
59
|
if "cond" in n:
|
|
58
60
|
return "cond"
|
|
59
61
|
if "component" in n:
|
|
60
62
|
return "componentRef"
|
|
61
|
-
_bfail("UNKNOWN_NODE_KIND", f"body node '{n.get('id', '?')}' is not componentRef/map/cond")
|
|
63
|
+
_bfail("UNKNOWN_NODE_KIND", f"body node '{n.get('id', '?')}' is not componentRef/map/cond/fanout")
|
|
62
64
|
|
|
63
65
|
|
|
64
66
|
def _node_parent(n: Mapping[str, Any]) -> Optional[str]:
|
|
67
|
+
if "fanout" in n:
|
|
68
|
+
return n["fanout"].get("parent")
|
|
65
69
|
if "map" in n:
|
|
66
70
|
return n["map"].get("parent")
|
|
67
71
|
if "cond" in n:
|
|
@@ -70,12 +74,14 @@ def _node_parent(n: Mapping[str, Any]) -> Optional[str]:
|
|
|
70
74
|
|
|
71
75
|
|
|
72
76
|
def _node_bind_field(n: Mapping[str, Any]) -> Optional[str]:
|
|
73
|
-
if "map" in n or "cond" in n:
|
|
77
|
+
if "map" in n or "cond" in n or "fanout" in n:
|
|
74
78
|
return None
|
|
75
79
|
return n.get("bindField")
|
|
76
80
|
|
|
77
81
|
|
|
78
82
|
def _node_policy(n: Mapping[str, Any]) -> Optional[str]:
|
|
83
|
+
if "fanout" in n:
|
|
84
|
+
return n["fanout"].get("policy")
|
|
79
85
|
if "map" in n:
|
|
80
86
|
return n["map"].get("policy")
|
|
81
87
|
if "cond" in n:
|
|
@@ -84,6 +90,8 @@ def _node_policy(n: Mapping[str, Any]) -> Optional[str]:
|
|
|
84
90
|
|
|
85
91
|
|
|
86
92
|
def _node_relation_kind(n: Mapping[str, Any]) -> Optional[str]:
|
|
93
|
+
if "fanout" in n:
|
|
94
|
+
return n["fanout"].get("relationKind")
|
|
87
95
|
if "map" in n:
|
|
88
96
|
return n["map"].get("relationKind")
|
|
89
97
|
if "cond" in n:
|
|
@@ -91,6 +99,37 @@ def _node_relation_kind(n: Mapping[str, Any]) -> Optional[str]:
|
|
|
91
99
|
return n.get("relationKind")
|
|
92
100
|
|
|
93
101
|
|
|
102
|
+
def fanout_dedup_drop(aligned_bodies: List[Value], dedupe_key: str, drop: str,
|
|
103
|
+
implicit_source: Optional[str]) -> List[Value]:
|
|
104
|
+
"""THE ONE dedup/drop definition (behaviorVersion 3) — Python twin of behavior.ts fanoutDedupDrop.
|
|
105
|
+
|
|
106
|
+
Applies first-seen dedupe (by the body's ``dedupe_key`` field) + dangling drop (null/non-object/
|
|
107
|
+
absent-key body when ``drop=='dangling'``) + implicitSource strip to the aligned raw list; returns
|
|
108
|
+
the connection ``items`` (the wrap is done by the caller). MUST stay byte-equal to the TS/native defs.
|
|
109
|
+
"""
|
|
110
|
+
items: List[Value] = []
|
|
111
|
+
seen: set = set()
|
|
112
|
+
for body in aligned_bodies:
|
|
113
|
+
rec = body if isinstance(body, dict) else None
|
|
114
|
+
key_val = rec.get(dedupe_key) if rec is not None else None
|
|
115
|
+
has_key = key_val is not None
|
|
116
|
+
if not has_key:
|
|
117
|
+
if drop == "dangling":
|
|
118
|
+
continue
|
|
119
|
+
items.append(body)
|
|
120
|
+
continue
|
|
121
|
+
seen_key = ("s:" + key_val) if isinstance(key_val, str) else ("j:" + repr(key_val))
|
|
122
|
+
if seen_key in seen:
|
|
123
|
+
continue
|
|
124
|
+
seen.add(seen_key)
|
|
125
|
+
if implicit_source is not None and rec is not None and implicit_source in rec:
|
|
126
|
+
copy = {k: v for k, v in rec.items() if k != implicit_source}
|
|
127
|
+
items.append(copy)
|
|
128
|
+
else:
|
|
129
|
+
items.append(body)
|
|
130
|
+
return items
|
|
131
|
+
|
|
132
|
+
|
|
94
133
|
def _eval_ports(ports: Mapping[str, Any], scope: Dict[str, Value]) -> Dict[str, Value]:
|
|
95
134
|
# key はソートせず宣言順のまま。FORBIDDEN_KEY 等は evaluate が投げる(fail-closed)。
|
|
96
135
|
return {k: evaluate_expression(v, scope) for k, v in ports.items()}
|
|
@@ -235,6 +274,35 @@ def run_behavior(
|
|
|
235
274
|
augmented.append(el)
|
|
236
275
|
return {"ok": augmented}
|
|
237
276
|
|
|
277
|
+
if kind == "fanout":
|
|
278
|
+
# fanout(v3): over(id-list)→ dedup 済み 1 回の batched handler → dedupe/drop/strip →
|
|
279
|
+
# connection {items, cursor:None}。整列制約(MAP_BATCH_RESULT_MISMATCH)は適用されない。
|
|
280
|
+
f = node["fanout"]
|
|
281
|
+
over = evaluate_expression(f["over"], base_scope())
|
|
282
|
+
if not isinstance(over, list):
|
|
283
|
+
_bfail("FANOUT_OVER_NOT_ARRAY", f"fanout '{op['id']}': 'over' did not evaluate to an array")
|
|
284
|
+
handler = handlers.get(f["component"])
|
|
285
|
+
if handler is None:
|
|
286
|
+
_bfail("UNKNOWN_COMPONENT", f"component '{f['component']}' has no handler (fail-closed)")
|
|
287
|
+
items_ports: List[Value] = []
|
|
288
|
+
for el in over:
|
|
289
|
+
scope = {**base_scope(), f["as"]: el}
|
|
290
|
+
items_ports.append(_eval_ports(f["ports"], scope))
|
|
291
|
+
if not items_ports:
|
|
292
|
+
return {"ok": {"items": [], "cursor": None}}
|
|
293
|
+
outcome = handler({"items": items_ports}, {"nodeId": op["id"], "component": f["component"]})
|
|
294
|
+
if "error" in outcome:
|
|
295
|
+
return outcome
|
|
296
|
+
r = outcome["ok"]
|
|
297
|
+
if not isinstance(r, list) or len(r) != len(items_ports):
|
|
298
|
+
_bfail(
|
|
299
|
+
"FANOUT_BATCH_RESULT_MISMATCH",
|
|
300
|
+
f"fanout '{op['id']}': batched handler must return a list aligned to the deduped id list "
|
|
301
|
+
f"(want {len(items_ports)}, got {len(r) if isinstance(r, list) else type(r).__name__})",
|
|
302
|
+
)
|
|
303
|
+
items_out = fanout_dedup_drop(r, f["dedupeKey"], f["drop"], f.get("implicitSource"))
|
|
304
|
+
return {"ok": {"items": items_out, "cursor": None}}
|
|
305
|
+
|
|
238
306
|
# componentRef
|
|
239
307
|
handler = handlers.get(node["component"])
|
|
240
308
|
if handler is None:
|
|
@@ -39,6 +39,7 @@ from . import (
|
|
|
39
39
|
encode_value,
|
|
40
40
|
evaluate_expression,
|
|
41
41
|
final_tree,
|
|
42
|
+
fingerprint_component_graph,
|
|
42
43
|
py_float_repr,
|
|
43
44
|
render_template,
|
|
44
45
|
run_behavior,
|
|
@@ -93,6 +94,7 @@ def _preflight(vectors_dir: Path) -> Dict[str, Any]:
|
|
|
93
94
|
("behavior.json", "behavior", "behaviorVersion", SPEC_VERSIONS["behavior"]),
|
|
94
95
|
("guard.json", "guard", "guardVersion", SPEC_VERSIONS["guard"]),
|
|
95
96
|
("c2-catalog-swap.json", "c2", "c2Version", SPEC_VERSIONS["c2"]),
|
|
97
|
+
("provenance.json", "provenance", "provenanceVersion", SPEC_VERSIONS["provenance"]),
|
|
96
98
|
]
|
|
97
99
|
loaded = [(f, suite, vk, want, _load_json(vectors_dir, f)) for (f, suite, vk, want) in specs]
|
|
98
100
|
mismatches = [(suite, doc.get(vk), want) for (_, suite, vk, want, doc) in loaded if doc.get(vk) != want]
|
|
@@ -356,6 +358,43 @@ def _run_guard(t: _Tally, doc: Any) -> None:
|
|
|
356
358
|
_bump(t, ok)
|
|
357
359
|
|
|
358
360
|
|
|
361
|
+
# ── provenance suite(シリアライズ境界の canonical fingerprint 照合, #128/A6)──────
|
|
362
|
+
def _run_provenance(t: _Tally, doc: Any) -> None:
|
|
363
|
+
"""シリアライズ境界の provenance ゲート(PROTOCOL.md §3.8 / scp-only-authoring-contract §3 SA3・§5)。
|
|
364
|
+
|
|
365
|
+
token はプロセス内 capability ゆえ JSON 境界を越えない。境界のゲートは canonical fingerprint:
|
|
366
|
+
runner は `ir`(RAW JSON)から `fingerprint_component_graph` を **再計算** し、宣言 `fingerprint` と
|
|
367
|
+
照合する。一致 = accept、不一致(改竄/stale)= 固定コード ``NON_COMPILED_IR`` で reject。
|
|
368
|
+
key 順・int/整数 float の綴りは fingerprint を変えない(canonical 不変性)。非空虚性
|
|
369
|
+
(CONFORMANCE_MUTATE): 1 nibble 崩した fingerprint の vector が必ず reject になることで、
|
|
370
|
+
runner が実際に再計算+照合していることを証明する。
|
|
371
|
+
"""
|
|
372
|
+
print(f"\nprovenance.json (v{doc['provenanceVersion']}) — {len(doc['vectors'])} vectors")
|
|
373
|
+
for v in doc["vectors"]:
|
|
374
|
+
ok = False
|
|
375
|
+
detail = ""
|
|
376
|
+
recomputed = fingerprint_component_graph(v["ir"])
|
|
377
|
+
matched = recomputed == v["fingerprint"]
|
|
378
|
+
if matched:
|
|
379
|
+
if "ok" in v["expect"]:
|
|
380
|
+
ok = True
|
|
381
|
+
else:
|
|
382
|
+
detail = f"expected Failure({v['expect']['failure']}), fingerprint matched"
|
|
383
|
+
else:
|
|
384
|
+
# 不一致 = 境界 loader の NON_COMPILED_IR reject に相当。
|
|
385
|
+
if "failure" in v["expect"]:
|
|
386
|
+
ok = v["expect"]["failure"] == "NON_COMPILED_IR"
|
|
387
|
+
if not ok:
|
|
388
|
+
detail = f"expected Failure({v['expect']['failure']}), got NON_COMPILED_IR"
|
|
389
|
+
else:
|
|
390
|
+
detail = (
|
|
391
|
+
f"expected accept, got NON_COMPILED_IR "
|
|
392
|
+
f"(declared {v['fingerprint']}, recomputed {recomputed})"
|
|
393
|
+
)
|
|
394
|
+
_line(ok, v["name"], detail)
|
|
395
|
+
_bump(t, ok)
|
|
396
|
+
|
|
397
|
+
|
|
359
398
|
# ── c2 suite(c2-catalog-swap: catalog-swap 実行 + IR 構造一致, bc#28)──────────
|
|
360
399
|
def _c2_normalize(decoded_ir: Any, role_by_name: Dict[str, str]) -> Any:
|
|
361
400
|
"""component leaf 名を role に置換(構造は不変)。unmapped は ValueError。"""
|
|
@@ -453,9 +492,10 @@ def run(vectors_dir: Optional[Path] = None) -> int:
|
|
|
453
492
|
_run_behavior(t, docs["behavior"])
|
|
454
493
|
_run_guard(t, docs["guard"])
|
|
455
494
|
_run_c2(t, docs["c2"])
|
|
495
|
+
_run_provenance(t, docs["provenance"])
|
|
456
496
|
|
|
457
497
|
total = t.passed + t.failed
|
|
458
|
-
print(f"\n{t.passed} passed, {t.failed} failed / {total} vectors across
|
|
498
|
+
print(f"\n{t.passed} passed, {t.failed} failed / {total} vectors across 8 suites")
|
|
459
499
|
return t.failed
|
|
460
500
|
|
|
461
501
|
|
{behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/src/behavior_contracts.egg-info/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: behavior-contracts
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.0
|
|
4
4
|
Summary: Multi-language IR-Runtime common core (Python port). The COMMON 'thin core' primitives from dsl-contracts runtime-boundary.md — validate_envelope / evaluate_expression / render_template / run_plan / canonical_value / canonical_json / py_float_repr / assert_portable — with zero backend (DynamoDB/graphddb) dependencies.
|
|
5
5
|
Author: foo-log
|
|
6
6
|
License: MIT
|
|
@@ -60,12 +60,12 @@ string matching the conformance protocol's failure-code set.
|
|
|
60
60
|
|
|
61
61
|
## Conformance
|
|
62
62
|
|
|
63
|
-
Runs the
|
|
63
|
+
Runs the 8 shared suites (173 vectors) from `../conformance/vectors/*.json`
|
|
64
64
|
through this package per [`../conformance/PROTOCOL.md`](../conformance/PROTOCOL.md),
|
|
65
65
|
including the pre-flight version fail-closed sweep.
|
|
66
66
|
|
|
67
67
|
```bash
|
|
68
|
-
python -m behavior_contracts.conformance # → "
|
|
68
|
+
python -m behavior_contracts.conformance # → "173 passed, 0 failed / 173 vectors across 8 suites"
|
|
69
69
|
# or the console script:
|
|
70
70
|
behavior-contracts-conformance
|
|
71
71
|
```
|
|
@@ -110,7 +110,7 @@ def test_tampered_generated_module_is_loudly_rejected(tmp_path):
|
|
|
110
110
|
code = f.read()
|
|
111
111
|
|
|
112
112
|
# spec-version skew(焼き込み定数の改変)→ ロード時 RuntimeError。
|
|
113
|
-
skew = code.replace('"behavior":
|
|
113
|
+
skew = code.replace('"behavior": 4', '"behavior": 99')
|
|
114
114
|
assert skew != code
|
|
115
115
|
p = tmp_path / "skew.py"
|
|
116
116
|
p.write_text(skew, encoding="utf-8")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/src/behavior_contracts.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/src/behavior_contracts.egg-info/requires.txt
RENAMED
|
File without changes
|
{behavior_contracts-0.7.2 → behavior_contracts-0.8.0}/src/behavior_contracts.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|