vis-agent 0.2.35.dev7414__tar.gz → 0.2.37.dev7442__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.
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/PKG-INFO +1 -1
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/schema/toggle.json +1 -1
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/pyproject.toml +1 -1
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/src/blockether/vis/_contracts.py +51 -5
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/src/blockether/vis/_outside.py +8 -1
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/src/blockether/vis/extension.py +19 -6
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_contracts.py +6 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_scoped_settings.py +26 -0
- vis_agent-0.2.37.dev7442/tests/test_text_list_arguments.py +89 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/.gitignore +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/LICENSE +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/README.md +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/fixtures/activity-arguments.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/fixtures/activity-cases.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/fixtures/activity-copy.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/fixtures/activity-execution.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/fixtures/activity-groups.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/fixtures/activity-read-session.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/fixtures/activity-reads.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/fixtures/activity-results.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/fixtures/activity-tables.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/fixtures/activity.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/fixtures/diff.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/fixtures/live-primitives.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/fixtures/session-health.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/fixtures/view.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/schema/activity.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/schema/agents.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/schema/automations.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/schema/common.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/schema/config.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/schema/content.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/schema/council.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/schema/diff.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/schema/gateway.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/schema/improve.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/schema/provider.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/schema/rooms.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/schema/symbol.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/schema/view.json +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/examples/greeter/tests/test_greeter.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/hatch_build.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/src/blockether/vis/__init__.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/src/blockether/vis/_wire.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/src/blockether/vis/activity.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/src/blockether/vis/engine/__init__.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/src/blockether/vis/engine/_agent.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/src/blockether/vis/engine/_agents.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/src/blockether/vis/engine/_client.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/src/blockether/vis/engine/_council.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/src/blockether/vis/engine/_extensions.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/src/blockether/vis/engine/_local.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/src/blockether/vis/extension_package.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/src/blockether/vis/py.typed +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/src/blockether/vis/rooms.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/src/blockether/vis/views.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/conftest.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_activity.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_agent.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_agent_extension_lifecycle.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_agent_extensions.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_agents.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_api_guides.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_authoring.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_catalog.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_catalog_recipe.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_ci_report_recipe.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_client.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_client_extensions_engine.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_code_quality_recipe.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_council.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_declarations.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_engine.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_engine_docstrings.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_extension_package.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_extension_reference.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_gateway_performance.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_goals.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_live_primitives.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_live_wait.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_local.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_method_typing.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_monitor_recipe.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_namespace.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_outside.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_providers.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_record_arguments.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_registration.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_repair_hooks.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_result_sequence.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_rooms.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_sdk_bootstrap.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_sdk_guide.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_sdk_typing.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_structured_live.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_symbol_contract.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_testing.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_tools.py +0 -0
- {vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_views.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: vis-agent
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.37.dev7442
|
|
4
4
|
Summary: The Vis Python SDK — author extensions and control local or remote engines.
|
|
5
5
|
Project-URL: Homepage, https://vis.blockether.com
|
|
6
6
|
Project-URL: Documentation, https://vis.blockether.com
|
|
@@ -8,7 +8,7 @@ build-backend = "hatchling.build"
|
|
|
8
8
|
|
|
9
9
|
[project]
|
|
10
10
|
name = "vis-agent"
|
|
11
|
-
version = "0.2.
|
|
11
|
+
version = "0.2.37.dev7442"
|
|
12
12
|
description = "The Vis Python SDK — author extensions and control local or remote engines."
|
|
13
13
|
readme = "README.md"
|
|
14
14
|
requires-python = ">=3.11"
|
|
@@ -74,16 +74,62 @@ def _json_value(item):
|
|
|
74
74
|
)
|
|
75
75
|
|
|
76
76
|
|
|
77
|
+
def _problem(error) -> str:
|
|
78
|
+
"""One readable line for a schema error: field, rule and limit, never the value."""
|
|
79
|
+
field = ".".join(str(part) for part in error.absolute_path) or "declaration"
|
|
80
|
+
rule, limit = error.validator, error.validator_value
|
|
81
|
+
if rule in ("maxLength", "minLength"):
|
|
82
|
+
bound = "maximum" if rule == "maxLength" else "minimum"
|
|
83
|
+
fix = f" Shorten the {field}." if rule == "maxLength" else ""
|
|
84
|
+
return (
|
|
85
|
+
f"{field} is {len(error.instance)} characters; {bound} is {limit} ({rule})."
|
|
86
|
+
+ fix
|
|
87
|
+
)
|
|
88
|
+
if rule == "required":
|
|
89
|
+
missing = ", ".join(key for key in limit if key not in error.instance)
|
|
90
|
+
return f"{missing} is missing (required)."
|
|
91
|
+
if rule == "enum":
|
|
92
|
+
return f"{field} must be one of: {', '.join(map(str, limit))} (enum)."
|
|
93
|
+
if rule == "pattern":
|
|
94
|
+
if (
|
|
95
|
+
limit
|
|
96
|
+
== definition("toggle", "contribution")["properties"]["description"][
|
|
97
|
+
"pattern"
|
|
98
|
+
]
|
|
99
|
+
):
|
|
100
|
+
return f"{field} must be one line without line breaks (pattern)."
|
|
101
|
+
return f"{field} does not match the pattern {limit} (pattern)."
|
|
102
|
+
return f"{field} breaks the {rule} rule."
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def problems(name: str, definition: str, value: Any) -> list[str]:
|
|
106
|
+
"""Readable rule failures of `value`, one line for each. Empty when it is valid.
|
|
107
|
+
|
|
108
|
+
Each line names the field, the rule and its limit. It never echoes the value.
|
|
109
|
+
"""
|
|
110
|
+
if not _json_value(value):
|
|
111
|
+
return ["the value is not JSON data."]
|
|
112
|
+
errors = _validator(name, definition).iter_errors(value)
|
|
113
|
+
return [
|
|
114
|
+
_problem(error)
|
|
115
|
+
for error in sorted(errors, key=lambda e: list(map(str, e.absolute_path)))
|
|
116
|
+
]
|
|
117
|
+
|
|
118
|
+
|
|
77
119
|
def validate(name: str, definition: str, value: Any) -> Any:
|
|
78
120
|
"""Validate portable JSON data, returning it or raising a payload-free ValueError.
|
|
79
121
|
|
|
80
|
-
|
|
122
|
+
The error names each failed field, rule and limit, never the value. Schemas
|
|
123
|
+
resolve only from the installed package. Runtime lifecycle, IO and
|
|
81
124
|
authorization belong to the engine, not JSON Schema.
|
|
82
125
|
"""
|
|
83
126
|
try:
|
|
84
|
-
|
|
127
|
+
found = problems(name, definition, value)
|
|
85
128
|
except (RecursionError, TypeError, ValueError):
|
|
86
|
-
|
|
87
|
-
if
|
|
88
|
-
|
|
129
|
+
found = [""]
|
|
130
|
+
if found:
|
|
131
|
+
detail = " ".join(problem for problem in found if problem)
|
|
132
|
+
raise ValueError(
|
|
133
|
+
f"invalid {name}.{definition} contract" + (f": {detail}" if detail else "")
|
|
134
|
+
)
|
|
89
135
|
return value
|
|
@@ -91,13 +91,20 @@ def workspace_root():
|
|
|
91
91
|
|
|
92
92
|
def setting_declaration(spec):
|
|
93
93
|
"""Use the package's own JSON Schemas for outside-host declarations."""
|
|
94
|
-
from ._contracts import definition, validate
|
|
94
|
+
from ._contracts import definition, problems, validate
|
|
95
95
|
|
|
96
96
|
spec = dict(spec)
|
|
97
97
|
spec.setdefault(
|
|
98
98
|
"scopes",
|
|
99
99
|
definition("toggle", "contribution")["properties"]["scopes"]["default"],
|
|
100
100
|
)
|
|
101
|
+
found = problems("toggle", "contribution", spec)
|
|
102
|
+
if found:
|
|
103
|
+
name = spec.get("id")
|
|
104
|
+
label = (
|
|
105
|
+
f"Invalid setting {name}" if isinstance(name, str) else "Invalid setting"
|
|
106
|
+
)
|
|
107
|
+
raise ValueError(f"{label}: {' '.join(found)}")
|
|
101
108
|
return validate("toggle", "contribution", spec)
|
|
102
109
|
|
|
103
110
|
|
|
@@ -1388,10 +1388,11 @@ def _call_arguments(fn, args, kwargs):
|
|
|
1388
1388
|
An argument crosses the host boundary as JSON, so a record arrives as a dict of its
|
|
1389
1389
|
public fields. A parameter annotated with a dataclass gets that dataclass back,
|
|
1390
1390
|
built through its constructor. This also works inside a union, list, tuple, set or
|
|
1391
|
-
dict annotation (Blockether/vis#289).
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
that
|
|
1391
|
+
dict annotation (Blockether/vis#289). One bare string for a sequence of strings
|
|
1392
|
+
becomes one item, not one item for each character (Blockether/vis#324).
|
|
1393
|
+
Annotations resolve statically, as for tool contracts. A value that does not fit
|
|
1394
|
+
its annotation stays as it arrived. So does every argument of a call that the
|
|
1395
|
+
signature cannot bind: the call itself reports that mistake.
|
|
1395
1396
|
"""
|
|
1396
1397
|
try:
|
|
1397
1398
|
# A wrapper around a bound method must not unwrap past the binding.
|
|
@@ -1561,9 +1562,10 @@ def _holds_record(shape):
|
|
|
1561
1562
|
def _rebuilt_value(shape, value):
|
|
1562
1563
|
"""Return `value` with the records that `shape` expects rebuilt.
|
|
1563
1564
|
|
|
1565
|
+
One bare string for a sequence of strings becomes that sequence with one item.
|
|
1564
1566
|
A value that does not fit stays as is.
|
|
1565
1567
|
"""
|
|
1566
|
-
if not _holds_record(shape):
|
|
1568
|
+
if not (_holds_record(shape) or isinstance(value, str)):
|
|
1567
1569
|
return value
|
|
1568
1570
|
result = _fitted_argument(shape, value)
|
|
1569
1571
|
return value if result is _UNFIT else result
|
|
@@ -1588,7 +1590,11 @@ def _fitted_argument(shape, value):
|
|
|
1588
1590
|
if kind == "record":
|
|
1589
1591
|
return _rebuilt_record(shape[1], value, shape[2])
|
|
1590
1592
|
if kind == "union":
|
|
1591
|
-
|
|
1593
|
+
members = shape[1]
|
|
1594
|
+
if isinstance(value, str):
|
|
1595
|
+
# A member that takes the string as it is wins over one that wraps it.
|
|
1596
|
+
members = sorted(members, key=lambda member: member[0] == "sequence")
|
|
1597
|
+
for member in members:
|
|
1592
1598
|
result = _fitted_argument(member, value)
|
|
1593
1599
|
if result is not _UNFIT:
|
|
1594
1600
|
return result
|
|
@@ -1599,6 +1605,13 @@ def _fitted_argument(shape, value):
|
|
|
1599
1605
|
if not _holds_record(shape):
|
|
1600
1606
|
return value
|
|
1601
1607
|
return {key: _rebuilt_value(shape[1], item) for key, item in value.items()}
|
|
1608
|
+
if kind == "sequence" and isinstance(value, str):
|
|
1609
|
+
# A string is a sequence of its characters; the caller named one item. An
|
|
1610
|
+
# item of any type also takes the whole string, so it stays as it is.
|
|
1611
|
+
if shape[2] in (("any",), ("plain", object)):
|
|
1612
|
+
return _UNFIT
|
|
1613
|
+
item = _fitted_argument(shape[2], value)
|
|
1614
|
+
return _UNFIT if item is _UNFIT else shape[1]((item,))
|
|
1602
1615
|
if not isinstance(value, (list, tuple)):
|
|
1603
1616
|
return _UNFIT
|
|
1604
1617
|
if kind == "fixed":
|
|
@@ -178,6 +178,12 @@ def test_payload_free_validation():
|
|
|
178
178
|
with pytest.raises(ValueError) as error:
|
|
179
179
|
_contracts.validate("activity", "declaration", bad)
|
|
180
180
|
assert "do-not-echo" not in str(error.value)
|
|
181
|
+
with pytest.raises(
|
|
182
|
+
ValueError, match=r": label does not match the pattern .* \(pattern\)"
|
|
183
|
+
):
|
|
184
|
+
_contracts.validate(
|
|
185
|
+
"activity", "declaration", {"presenter": "tests", "label": "one\ntwo"}
|
|
186
|
+
)
|
|
181
187
|
with pytest.raises(ValueError):
|
|
182
188
|
_contracts.validate("view", "missing-definition", {})
|
|
183
189
|
|
|
@@ -68,6 +68,32 @@ def test_parent_nests_a_setting():
|
|
|
68
68
|
vis.Setting(id="test_detail", label="Test detail", default=False, parent=" ")
|
|
69
69
|
|
|
70
70
|
|
|
71
|
+
# Regression for #322 and #323: a 300-character description is valid, and a
|
|
72
|
+
# longer one names the setting, the field, the rule and the limit.
|
|
73
|
+
def test_description_limit_and_actionable_error():
|
|
74
|
+
def mode(description):
|
|
75
|
+
return vis.Setting(
|
|
76
|
+
id="steering_mode",
|
|
77
|
+
label="Steering mode",
|
|
78
|
+
type="enum",
|
|
79
|
+
choices=["vibe", "control"],
|
|
80
|
+
default="vibe",
|
|
81
|
+
description=description,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
assert mode("x" * 300).description == "x" * 300
|
|
85
|
+
with pytest.raises(ValueError) as error:
|
|
86
|
+
mode("x" * 301)
|
|
87
|
+
assert str(error.value) == (
|
|
88
|
+
"Invalid setting steering_mode: description is 301 characters; "
|
|
89
|
+
"maximum is 300 (maxLength). Shorten the description."
|
|
90
|
+
)
|
|
91
|
+
with pytest.raises(ValueError, match="one line without line breaks"):
|
|
92
|
+
mode("two\nlines")
|
|
93
|
+
with pytest.raises(ValueError, match="minimum is 1"):
|
|
94
|
+
mode("")
|
|
95
|
+
|
|
96
|
+
|
|
71
97
|
def test_application_bridge_rejects_host_only_settings_before_connecting():
|
|
72
98
|
declaration = vis.Extension(
|
|
73
99
|
name="Settings test",
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""Regression coverage for #324: one bare string for a list of strings is one item."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Sequence
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Annotated, Literal, Optional
|
|
8
|
+
|
|
9
|
+
import blockether.vis.extension as vis
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Tools:
|
|
13
|
+
"""The parameter shapes of the `py.*` and `clj.*` language tools."""
|
|
14
|
+
|
|
15
|
+
def lint_code(
|
|
16
|
+
self,
|
|
17
|
+
paths: Annotated[Sequence[str], "Files or directories to lint."] = (),
|
|
18
|
+
*,
|
|
19
|
+
cwd: str = "",
|
|
20
|
+
namespaces: Annotated[Sequence[str], "Test namespaces to run."] = (),
|
|
21
|
+
) -> tuple:
|
|
22
|
+
return tuple(paths), tuple(namespaces)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def rebuilt(fn, *args, **kwargs):
|
|
26
|
+
return vis._call_arguments(fn, list(args), kwargs)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def test_bare_string_for_a_string_sequence_is_one_item():
|
|
30
|
+
# Regression for Blockether/vis#324: `py.lint_code("/src/app.py")` named one
|
|
31
|
+
# path for each character, and `/` made the lint walk the whole filesystem.
|
|
32
|
+
tools = Tools()
|
|
33
|
+
args, kwargs = rebuilt(tools.lint_code, "/src/app.py", namespaces="my.ns-test")
|
|
34
|
+
assert args == [["/src/app.py"]]
|
|
35
|
+
assert kwargs == {"namespaces": ["my.ns-test"]}
|
|
36
|
+
assert tools.lint_code(*args, **kwargs) == (("/src/app.py",), ("my.ns-test",))
|
|
37
|
+
assert rebuilt(tools.lint_code, paths="a.py")[1] == {"paths": ["a.py"]}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_lists_and_other_parameters_stay_as_they_arrived():
|
|
41
|
+
tools = Tools()
|
|
42
|
+
paths = ["a.py", "b.py"]
|
|
43
|
+
args, kwargs = rebuilt(tools.lint_code, paths, cwd="/src")
|
|
44
|
+
assert args[0] is paths
|
|
45
|
+
assert kwargs == {"cwd": "/src"}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def test_container_and_item_annotations_decide_the_shape():
|
|
49
|
+
def files(
|
|
50
|
+
paths: list[str], tags: set[str] = frozenset(), pair: tuple[str, ...] = ()
|
|
51
|
+
):
|
|
52
|
+
return paths, tags, pair
|
|
53
|
+
|
|
54
|
+
def optional(paths: Optional[list[str]] = None, more: list[str] | None = None): # noqa: UP045
|
|
55
|
+
return paths, more
|
|
56
|
+
|
|
57
|
+
def literal(modes: list[Literal["fast", "full"]] = ()):
|
|
58
|
+
return modes
|
|
59
|
+
|
|
60
|
+
assert rebuilt(files, "a.py", tags="x", pair="y") == (
|
|
61
|
+
[["a.py"]],
|
|
62
|
+
{"tags": {"x"}, "pair": ("y",)},
|
|
63
|
+
)
|
|
64
|
+
assert rebuilt(optional, "a.py", more="b.py") == ([["a.py"]], {"more": ["b.py"]})
|
|
65
|
+
assert rebuilt(literal, "fast") == ([["fast"]], {})
|
|
66
|
+
assert rebuilt(literal, "other") == (["other"], {})
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def test_a_member_that_takes_the_string_as_it_is_wins():
|
|
70
|
+
def either(paths: list[str] | str = (), path: str | list[str] = ""):
|
|
71
|
+
return paths, path
|
|
72
|
+
|
|
73
|
+
def anything(
|
|
74
|
+
values: list = (), items: Sequence[object] = (), raw: list[bytes] = ()
|
|
75
|
+
):
|
|
76
|
+
return values, items, raw
|
|
77
|
+
|
|
78
|
+
assert rebuilt(either, "a.py", path="b.py") == (["a.py"], {"path": "b.py"})
|
|
79
|
+
assert rebuilt(anything, "ab", items="cd", raw="ef") == (
|
|
80
|
+
["ab"],
|
|
81
|
+
{"items": "cd", "raw": "ef"},
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def test_path_items_take_a_bare_string_unchanged():
|
|
86
|
+
def walk(paths: list[str | Path] = ()):
|
|
87
|
+
return paths
|
|
88
|
+
|
|
89
|
+
assert rebuilt(walk, "src") == ([["src"]], {})
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/fixtures/activity-arguments.json
RENAMED
|
File without changes
|
{vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/fixtures/activity-cases.json
RENAMED
|
File without changes
|
|
File without changes
|
{vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/fixtures/activity-execution.json
RENAMED
|
File without changes
|
{vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/fixtures/activity-groups.json
RENAMED
|
File without changes
|
{vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/fixtures/activity-read-session.json
RENAMED
|
File without changes
|
{vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/fixtures/activity-reads.json
RENAMED
|
File without changes
|
{vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/fixtures/activity-results.json
RENAMED
|
File without changes
|
{vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/fixtures/activity-tables.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/fixtures/live-primitives.json
RENAMED
|
File without changes
|
{vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/contracts/fixtures/session-health.json
RENAMED
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/examples/greeter/tests/test_greeter.py
RENAMED
|
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
|
{vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/src/blockether/vis/engine/_extensions.py
RENAMED
|
File without changes
|
|
File without changes
|
{vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/src/blockether/vis/extension_package.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_agent_extension_lifecycle.py
RENAMED
|
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
|
{vis_agent-0.2.35.dev7414 → vis_agent-0.2.37.dev7442}/tests/test_client_extensions_engine.py
RENAMED
|
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
|
|
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
|
|
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
|
|
File without changes
|