agent-first-data 0.3.0__tar.gz → 0.4.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.
- {agent_first_data-0.3.0 → agent_first_data-0.4.0}/PKG-INFO +38 -2
- {agent_first_data-0.3.0 → agent_first_data-0.4.0}/README.md +37 -1
- {agent_first_data-0.3.0 → agent_first_data-0.4.0}/agent_first_data/__init__.py +13 -0
- agent_first_data-0.4.0/agent_first_data/cli.py +92 -0
- {agent_first_data-0.3.0 → agent_first_data-0.4.0}/agent_first_data.egg-info/PKG-INFO +38 -2
- {agent_first_data-0.3.0 → agent_first_data-0.4.0}/agent_first_data.egg-info/SOURCES.txt +4 -1
- {agent_first_data-0.3.0 → agent_first_data-0.4.0}/pyproject.toml +1 -1
- agent_first_data-0.4.0/tests/test_cli.py +98 -0
- agent_first_data-0.4.0/tests/test_no_stderr_policy.py +23 -0
- {agent_first_data-0.3.0 → agent_first_data-0.4.0}/agent_first_data/afdata_logging.py +0 -0
- {agent_first_data-0.3.0 → agent_first_data-0.4.0}/agent_first_data/format.py +0 -0
- {agent_first_data-0.3.0 → agent_first_data-0.4.0}/agent_first_data.egg-info/dependency_links.txt +0 -0
- {agent_first_data-0.3.0 → agent_first_data-0.4.0}/agent_first_data.egg-info/top_level.txt +0 -0
- {agent_first_data-0.3.0 → agent_first_data-0.4.0}/setup.cfg +0 -0
- {agent_first_data-0.3.0 → agent_first_data-0.4.0}/tests/test_afdata_logging.py +0 -0
- {agent_first_data-0.3.0 → agent_first_data-0.4.0}/tests/test_format.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-first-data
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Agent-First Data (AFDATA) — suffix-driven output formatting and protocol templates for AI agents
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Repository, https://github.com/cmnspore/agent-first-data
|
|
@@ -74,7 +74,7 @@ Plain: args.input_path=/data/backup.tar.gz code=log event=startup config.max_fil
|
|
|
74
74
|
|
|
75
75
|
## API Reference
|
|
76
76
|
|
|
77
|
-
Total: **
|
|
77
|
+
Total: **12 public APIs and 1 type** + **AFDATA logging** (3 protocol builders + 3 output functions + 1 internal + 1 utility + 4 CLI helpers + `OutputFormat`)
|
|
78
78
|
|
|
79
79
|
### Protocol Builders (returns dict)
|
|
80
80
|
|
|
@@ -187,6 +187,41 @@ assert parse_size("1.5K") == 1536
|
|
|
187
187
|
assert parse_size("512") == 512
|
|
188
188
|
```
|
|
189
189
|
|
|
190
|
+
### CLI Helpers (for tools built on AFDATA)
|
|
191
|
+
|
|
192
|
+
Shared helpers that prevent flag-parsing drift between CLI tools. Use these instead of reimplementing `--output` and `--log` handling in each tool.
|
|
193
|
+
|
|
194
|
+
```python
|
|
195
|
+
class OutputFormat(enum.Enum): # JSON="json", YAML="yaml", PLAIN="plain"
|
|
196
|
+
|
|
197
|
+
cli_parse_output(s: str) -> OutputFormat # Parse --output flag; raises ValueError on unknown
|
|
198
|
+
cli_parse_log_filters(entries: list[str]) -> list[str] # Normalize --log: trim, lowercase, dedup, remove empty
|
|
199
|
+
cli_output(value: Any, format: OutputFormat) -> str # Dispatch to output_json/yaml/plain
|
|
200
|
+
build_cli_error(message: str) -> dict # {code:"error", error_code:"invalid_request", retryable:False, trace:{duration_ms:0}}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**Canonical pattern** — parse all flags before doing work, emit JSONL errors to stdout:
|
|
204
|
+
|
|
205
|
+
```python
|
|
206
|
+
import sys
|
|
207
|
+
from agent_first_data import (
|
|
208
|
+
OutputFormat, cli_parse_output, cli_parse_log_filters,
|
|
209
|
+
cli_output, build_cli_error, output_json,
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
try:
|
|
213
|
+
fmt = cli_parse_output(args.output)
|
|
214
|
+
except ValueError as e:
|
|
215
|
+
print(output_json(build_cli_error(str(e))))
|
|
216
|
+
sys.exit(2)
|
|
217
|
+
|
|
218
|
+
log = cli_parse_log_filters(args.log.split(",") if args.log else [])
|
|
219
|
+
# ... do work ...
|
|
220
|
+
print(cli_output(result, fmt))
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
See `examples/agent_cli.py` for the complete working example (`pytest examples/agent_cli.py`).
|
|
224
|
+
|
|
190
225
|
## Usage Examples
|
|
191
226
|
|
|
192
227
|
### Example 1: REST API
|
|
@@ -276,6 +311,7 @@ result = build_json_ok(
|
|
|
276
311
|
)
|
|
277
312
|
|
|
278
313
|
# Print JSONL to stdout (secrets redacted, one JSON object per line)
|
|
314
|
+
# Channel policy: machine-readable protocol/log events must not use stderr.
|
|
279
315
|
print(output_json(result))
|
|
280
316
|
# {"code":"ok","result":{"status":"success"},"trace":{"api_key_secret":"***","duration_ms":250}}
|
|
281
317
|
```
|
|
@@ -65,7 +65,7 @@ Plain: args.input_path=/data/backup.tar.gz code=log event=startup config.max_fil
|
|
|
65
65
|
|
|
66
66
|
## API Reference
|
|
67
67
|
|
|
68
|
-
Total: **
|
|
68
|
+
Total: **12 public APIs and 1 type** + **AFDATA logging** (3 protocol builders + 3 output functions + 1 internal + 1 utility + 4 CLI helpers + `OutputFormat`)
|
|
69
69
|
|
|
70
70
|
### Protocol Builders (returns dict)
|
|
71
71
|
|
|
@@ -178,6 +178,41 @@ assert parse_size("1.5K") == 1536
|
|
|
178
178
|
assert parse_size("512") == 512
|
|
179
179
|
```
|
|
180
180
|
|
|
181
|
+
### CLI Helpers (for tools built on AFDATA)
|
|
182
|
+
|
|
183
|
+
Shared helpers that prevent flag-parsing drift between CLI tools. Use these instead of reimplementing `--output` and `--log` handling in each tool.
|
|
184
|
+
|
|
185
|
+
```python
|
|
186
|
+
class OutputFormat(enum.Enum): # JSON="json", YAML="yaml", PLAIN="plain"
|
|
187
|
+
|
|
188
|
+
cli_parse_output(s: str) -> OutputFormat # Parse --output flag; raises ValueError on unknown
|
|
189
|
+
cli_parse_log_filters(entries: list[str]) -> list[str] # Normalize --log: trim, lowercase, dedup, remove empty
|
|
190
|
+
cli_output(value: Any, format: OutputFormat) -> str # Dispatch to output_json/yaml/plain
|
|
191
|
+
build_cli_error(message: str) -> dict # {code:"error", error_code:"invalid_request", retryable:False, trace:{duration_ms:0}}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**Canonical pattern** — parse all flags before doing work, emit JSONL errors to stdout:
|
|
195
|
+
|
|
196
|
+
```python
|
|
197
|
+
import sys
|
|
198
|
+
from agent_first_data import (
|
|
199
|
+
OutputFormat, cli_parse_output, cli_parse_log_filters,
|
|
200
|
+
cli_output, build_cli_error, output_json,
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
try:
|
|
204
|
+
fmt = cli_parse_output(args.output)
|
|
205
|
+
except ValueError as e:
|
|
206
|
+
print(output_json(build_cli_error(str(e))))
|
|
207
|
+
sys.exit(2)
|
|
208
|
+
|
|
209
|
+
log = cli_parse_log_filters(args.log.split(",") if args.log else [])
|
|
210
|
+
# ... do work ...
|
|
211
|
+
print(cli_output(result, fmt))
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
See `examples/agent_cli.py` for the complete working example (`pytest examples/agent_cli.py`).
|
|
215
|
+
|
|
181
216
|
## Usage Examples
|
|
182
217
|
|
|
183
218
|
### Example 1: REST API
|
|
@@ -267,6 +302,7 @@ result = build_json_ok(
|
|
|
267
302
|
)
|
|
268
303
|
|
|
269
304
|
# Print JSONL to stdout (secrets redacted, one JSON object per line)
|
|
305
|
+
# Channel policy: machine-readable protocol/log events must not use stderr.
|
|
270
306
|
print(output_json(result))
|
|
271
307
|
# {"code":"ok","result":{"status":"success"},"trace":{"api_key_secret":"***","duration_ms":250}}
|
|
272
308
|
```
|
|
@@ -21,6 +21,14 @@ from agent_first_data.afdata_logging import (
|
|
|
21
21
|
span,
|
|
22
22
|
)
|
|
23
23
|
|
|
24
|
+
from agent_first_data.cli import (
|
|
25
|
+
OutputFormat,
|
|
26
|
+
cli_parse_output,
|
|
27
|
+
cli_parse_log_filters,
|
|
28
|
+
cli_output,
|
|
29
|
+
build_cli_error,
|
|
30
|
+
)
|
|
31
|
+
|
|
24
32
|
__all__ = [
|
|
25
33
|
"build_json_ok",
|
|
26
34
|
"build_json_error",
|
|
@@ -37,4 +45,9 @@ __all__ = [
|
|
|
37
45
|
"init_logging_yaml",
|
|
38
46
|
"get_logger",
|
|
39
47
|
"span",
|
|
48
|
+
"OutputFormat",
|
|
49
|
+
"cli_parse_output",
|
|
50
|
+
"cli_parse_log_filters",
|
|
51
|
+
"cli_output",
|
|
52
|
+
"build_cli_error",
|
|
40
53
|
]
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"""AFDATA CLI helpers — output format parsing, log filter normalization, error building."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import enum
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from agent_first_data.format import output_json, output_yaml, output_plain
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class OutputFormat(enum.Enum):
|
|
12
|
+
"""Output format for CLI and pipe/MCP modes."""
|
|
13
|
+
|
|
14
|
+
JSON = "json"
|
|
15
|
+
YAML = "yaml"
|
|
16
|
+
PLAIN = "plain"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def cli_parse_output(s: str) -> OutputFormat:
|
|
20
|
+
"""Parse the --output flag value into an OutputFormat.
|
|
21
|
+
|
|
22
|
+
Raises ValueError with a message suitable for build_cli_error on unknown values.
|
|
23
|
+
|
|
24
|
+
>>> cli_parse_output("json")
|
|
25
|
+
<OutputFormat.JSON: 'json'>
|
|
26
|
+
>>> cli_parse_output("xml")
|
|
27
|
+
Traceback (most recent call last):
|
|
28
|
+
...
|
|
29
|
+
ValueError: invalid --output format 'xml': expected json, yaml, or plain
|
|
30
|
+
"""
|
|
31
|
+
try:
|
|
32
|
+
return OutputFormat(s)
|
|
33
|
+
except ValueError:
|
|
34
|
+
raise ValueError(
|
|
35
|
+
f"invalid --output format {s!r}: expected json, yaml, or plain"
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def cli_parse_log_filters(entries: list[str]) -> list[str]:
|
|
40
|
+
"""Normalize --log flag entries: trim, lowercase, deduplicate, remove empty.
|
|
41
|
+
|
|
42
|
+
Accepts pre-split entries (e.g. after splitting on comma).
|
|
43
|
+
|
|
44
|
+
>>> cli_parse_log_filters(["Query", " error ", "query"])
|
|
45
|
+
['query', 'error']
|
|
46
|
+
"""
|
|
47
|
+
out: list[str] = []
|
|
48
|
+
for entry in entries:
|
|
49
|
+
s = entry.strip().lower()
|
|
50
|
+
if s and s not in out:
|
|
51
|
+
out.append(s)
|
|
52
|
+
return out
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def cli_output(value: Any, format: OutputFormat) -> str:
|
|
56
|
+
"""Dispatch output formatting by OutputFormat.
|
|
57
|
+
|
|
58
|
+
Equivalent to calling output_json, output_yaml, or output_plain directly.
|
|
59
|
+
|
|
60
|
+
>>> import json
|
|
61
|
+
>>> v = {"code": "ok"}
|
|
62
|
+
>>> cli_output(v, OutputFormat.JSON).startswith('{"code"')
|
|
63
|
+
True
|
|
64
|
+
"""
|
|
65
|
+
if format is OutputFormat.YAML:
|
|
66
|
+
return output_yaml(value)
|
|
67
|
+
if format is OutputFormat.PLAIN:
|
|
68
|
+
return output_plain(value)
|
|
69
|
+
return output_json(value)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def build_cli_error(message: str) -> dict:
|
|
73
|
+
"""Build a standard CLI parse error value.
|
|
74
|
+
|
|
75
|
+
Use when argument parsing fails or a flag value is invalid.
|
|
76
|
+
Print with output_json and exit with code 2.
|
|
77
|
+
|
|
78
|
+
>>> v = build_cli_error("--output: invalid value 'xml'")
|
|
79
|
+
>>> v["code"]
|
|
80
|
+
'error'
|
|
81
|
+
>>> v["error_code"]
|
|
82
|
+
'invalid_request'
|
|
83
|
+
>>> v["retryable"]
|
|
84
|
+
False
|
|
85
|
+
"""
|
|
86
|
+
return {
|
|
87
|
+
"code": "error",
|
|
88
|
+
"error_code": "invalid_request",
|
|
89
|
+
"error": message,
|
|
90
|
+
"retryable": False,
|
|
91
|
+
"trace": {"duration_ms": 0},
|
|
92
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-first-data
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Agent-First Data (AFDATA) — suffix-driven output formatting and protocol templates for AI agents
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Repository, https://github.com/cmnspore/agent-first-data
|
|
@@ -74,7 +74,7 @@ Plain: args.input_path=/data/backup.tar.gz code=log event=startup config.max_fil
|
|
|
74
74
|
|
|
75
75
|
## API Reference
|
|
76
76
|
|
|
77
|
-
Total: **
|
|
77
|
+
Total: **12 public APIs and 1 type** + **AFDATA logging** (3 protocol builders + 3 output functions + 1 internal + 1 utility + 4 CLI helpers + `OutputFormat`)
|
|
78
78
|
|
|
79
79
|
### Protocol Builders (returns dict)
|
|
80
80
|
|
|
@@ -187,6 +187,41 @@ assert parse_size("1.5K") == 1536
|
|
|
187
187
|
assert parse_size("512") == 512
|
|
188
188
|
```
|
|
189
189
|
|
|
190
|
+
### CLI Helpers (for tools built on AFDATA)
|
|
191
|
+
|
|
192
|
+
Shared helpers that prevent flag-parsing drift between CLI tools. Use these instead of reimplementing `--output` and `--log` handling in each tool.
|
|
193
|
+
|
|
194
|
+
```python
|
|
195
|
+
class OutputFormat(enum.Enum): # JSON="json", YAML="yaml", PLAIN="plain"
|
|
196
|
+
|
|
197
|
+
cli_parse_output(s: str) -> OutputFormat # Parse --output flag; raises ValueError on unknown
|
|
198
|
+
cli_parse_log_filters(entries: list[str]) -> list[str] # Normalize --log: trim, lowercase, dedup, remove empty
|
|
199
|
+
cli_output(value: Any, format: OutputFormat) -> str # Dispatch to output_json/yaml/plain
|
|
200
|
+
build_cli_error(message: str) -> dict # {code:"error", error_code:"invalid_request", retryable:False, trace:{duration_ms:0}}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**Canonical pattern** — parse all flags before doing work, emit JSONL errors to stdout:
|
|
204
|
+
|
|
205
|
+
```python
|
|
206
|
+
import sys
|
|
207
|
+
from agent_first_data import (
|
|
208
|
+
OutputFormat, cli_parse_output, cli_parse_log_filters,
|
|
209
|
+
cli_output, build_cli_error, output_json,
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
try:
|
|
213
|
+
fmt = cli_parse_output(args.output)
|
|
214
|
+
except ValueError as e:
|
|
215
|
+
print(output_json(build_cli_error(str(e))))
|
|
216
|
+
sys.exit(2)
|
|
217
|
+
|
|
218
|
+
log = cli_parse_log_filters(args.log.split(",") if args.log else [])
|
|
219
|
+
# ... do work ...
|
|
220
|
+
print(cli_output(result, fmt))
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
See `examples/agent_cli.py` for the complete working example (`pytest examples/agent_cli.py`).
|
|
224
|
+
|
|
190
225
|
## Usage Examples
|
|
191
226
|
|
|
192
227
|
### Example 1: REST API
|
|
@@ -276,6 +311,7 @@ result = build_json_ok(
|
|
|
276
311
|
)
|
|
277
312
|
|
|
278
313
|
# Print JSONL to stdout (secrets redacted, one JSON object per line)
|
|
314
|
+
# Channel policy: machine-readable protocol/log events must not use stderr.
|
|
279
315
|
print(output_json(result))
|
|
280
316
|
# {"code":"ok","result":{"status":"success"},"trace":{"api_key_secret":"***","duration_ms":250}}
|
|
281
317
|
```
|
|
@@ -2,10 +2,13 @@ README.md
|
|
|
2
2
|
pyproject.toml
|
|
3
3
|
agent_first_data/__init__.py
|
|
4
4
|
agent_first_data/afdata_logging.py
|
|
5
|
+
agent_first_data/cli.py
|
|
5
6
|
agent_first_data/format.py
|
|
6
7
|
agent_first_data.egg-info/PKG-INFO
|
|
7
8
|
agent_first_data.egg-info/SOURCES.txt
|
|
8
9
|
agent_first_data.egg-info/dependency_links.txt
|
|
9
10
|
agent_first_data.egg-info/top_level.txt
|
|
10
11
|
tests/test_afdata_logging.py
|
|
11
|
-
tests/
|
|
12
|
+
tests/test_cli.py
|
|
13
|
+
tests/test_format.py
|
|
14
|
+
tests/test_no_stderr_policy.py
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""Tests for agent_first_data CLI helpers."""
|
|
2
|
+
import pytest
|
|
3
|
+
from agent_first_data import (
|
|
4
|
+
OutputFormat,
|
|
5
|
+
cli_parse_output,
|
|
6
|
+
cli_parse_log_filters,
|
|
7
|
+
cli_output,
|
|
8
|
+
build_cli_error,
|
|
9
|
+
output_json,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# ── cli_parse_output ──────────────────────────────────────────────────────────
|
|
14
|
+
|
|
15
|
+
def test_parse_output_all_formats():
|
|
16
|
+
assert cli_parse_output("json") is OutputFormat.JSON
|
|
17
|
+
assert cli_parse_output("yaml") is OutputFormat.YAML
|
|
18
|
+
assert cli_parse_output("plain") is OutputFormat.PLAIN
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_parse_output_rejects_unknown():
|
|
22
|
+
with pytest.raises(ValueError):
|
|
23
|
+
cli_parse_output("xml")
|
|
24
|
+
with pytest.raises(ValueError):
|
|
25
|
+
cli_parse_output("JSON")
|
|
26
|
+
with pytest.raises(ValueError):
|
|
27
|
+
cli_parse_output("")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_parse_output_error_contains_value():
|
|
31
|
+
with pytest.raises(ValueError, match="toml"):
|
|
32
|
+
cli_parse_output("toml")
|
|
33
|
+
with pytest.raises(ValueError, match="json"):
|
|
34
|
+
cli_parse_output("toml")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# ── cli_parse_log_filters ─────────────────────────────────────────────────────
|
|
38
|
+
|
|
39
|
+
def test_parse_log_filters_trims_and_lowercases():
|
|
40
|
+
assert cli_parse_log_filters([" Query ", "ERROR"]) == ["query", "error"]
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def test_parse_log_filters_deduplicates():
|
|
44
|
+
assert cli_parse_log_filters(["query", "error", "Query", "query"]) == ["query", "error"]
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def test_parse_log_filters_removes_empty():
|
|
48
|
+
assert cli_parse_log_filters(["", "query", " "]) == ["query"]
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def test_parse_log_filters_empty_list():
|
|
52
|
+
assert cli_parse_log_filters([]) == []
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def test_parse_log_filters_preserves_order():
|
|
56
|
+
assert cli_parse_log_filters(["startup", "request", "retry"]) == ["startup", "request", "retry"]
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
# ── build_cli_error ───────────────────────────────────────────────────────────
|
|
60
|
+
|
|
61
|
+
def test_build_cli_error_required_fields():
|
|
62
|
+
v = build_cli_error("missing --sql")
|
|
63
|
+
assert v["code"] == "error"
|
|
64
|
+
assert v["error_code"] == "invalid_request"
|
|
65
|
+
assert v["error"] == "missing --sql"
|
|
66
|
+
assert v["retryable"] is False
|
|
67
|
+
assert v["trace"]["duration_ms"] == 0
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def test_build_cli_error_is_valid_json():
|
|
71
|
+
import json
|
|
72
|
+
v = build_cli_error("oops")
|
|
73
|
+
s = output_json(v)
|
|
74
|
+
parsed = json.loads(s)
|
|
75
|
+
assert parsed["code"] == "error"
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
# ── cli_output ────────────────────────────────────────────────────────────────
|
|
79
|
+
|
|
80
|
+
def test_cli_output_dispatches_json():
|
|
81
|
+
v = {"code": "ok", "size_bytes": 1024}
|
|
82
|
+
out = cli_output(v, OutputFormat.JSON)
|
|
83
|
+
assert "size_bytes" in out # json: raw keys, no suffix processing
|
|
84
|
+
assert "\n" not in out
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def test_cli_output_dispatches_yaml():
|
|
88
|
+
v = {"code": "ok", "size_bytes": 1024}
|
|
89
|
+
out = cli_output(v, OutputFormat.YAML)
|
|
90
|
+
assert out.startswith("---")
|
|
91
|
+
assert "size:" in out # yaml: suffix stripped
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def test_cli_output_dispatches_plain():
|
|
95
|
+
v = {"code": "ok"}
|
|
96
|
+
out = cli_output(v, OutputFormat.PLAIN)
|
|
97
|
+
assert "\n" not in out
|
|
98
|
+
assert "code=ok" in out
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Policy test: runtime library sources must not emit protocol/log events to stderr."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
import re
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
DISALLOWED = re.compile(
|
|
8
|
+
r"\bsys\.stderr\b|\bfile\s*=\s*sys\.stderr\b|\bstderr\.write\s*\(",
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_no_stderr_usage_in_runtime_sources() -> None:
|
|
13
|
+
root = Path(__file__).resolve().parents[1] / "agent_first_data"
|
|
14
|
+
files = sorted(root.glob("*.py"))
|
|
15
|
+
assert files, "no python source files found"
|
|
16
|
+
|
|
17
|
+
violations: list[str] = []
|
|
18
|
+
for path in files:
|
|
19
|
+
for lineno, line in enumerate(path.read_text(encoding="utf-8").splitlines(), start=1):
|
|
20
|
+
if DISALLOWED.search(line):
|
|
21
|
+
violations.append(f"{path.name}:{lineno}: {line.strip()}")
|
|
22
|
+
|
|
23
|
+
assert not violations, "stderr usage is disallowed:\n" + "\n".join(violations)
|
|
File without changes
|
|
File without changes
|
{agent_first_data-0.3.0 → agent_first_data-0.4.0}/agent_first_data.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|