agent-first-data 0.6.0__tar.gz → 0.7.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-first-data
3
- Version: 0.6.0
3
+ Version: 0.7.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
@@ -188,6 +188,8 @@ Most users don't need this. Output functions automatically protect secrets.
188
188
  parse_size(s: str) -> int | None # Parse "10M" → bytes
189
189
  ```
190
190
 
191
+ Returns `None` for invalid, negative, or overflow input.
192
+
191
193
  **Example:**
192
194
  ```python
193
195
  from agent_first_data import *
@@ -179,6 +179,8 @@ Most users don't need this. Output functions automatically protect secrets.
179
179
  parse_size(s: str) -> int | None # Parse "10M" → bytes
180
180
  ```
181
181
 
182
+ Returns `None` for invalid, negative, or overflow input.
183
+
182
184
  **Example:**
183
185
  ```python
184
186
  from agent_first_data import *
@@ -118,6 +118,7 @@ def parse_size(s: str) -> int | None:
118
118
  Case-insensitive. Trims whitespace. Returns None for invalid input.
119
119
  """
120
120
  _multipliers = {"b": 1, "k": 1024, "m": 1024**2, "g": 1024**3, "t": 1024**4}
121
+ _max_u64 = (1 << 64) - 1
121
122
  s = s.strip()
122
123
  if not s:
123
124
  return None
@@ -136,14 +137,19 @@ def parse_size(s: str) -> int | None:
136
137
  n = int(num_str)
137
138
  if n < 0:
138
139
  return None
140
+ if n > _max_u64 // mult:
141
+ return None
139
142
  return n * mult
140
143
  except ValueError:
141
144
  pass
142
145
  try:
143
146
  f = float(num_str)
144
- if f < 0 or f != f: # NaN check
147
+ if f < 0 or not math.isfinite(f):
148
+ return None
149
+ result = f * mult
150
+ if not math.isfinite(result) or result > _max_u64:
145
151
  return None
146
- return int(f * mult)
152
+ return int(result)
147
153
  except (ValueError, OverflowError):
148
154
  return None
149
155
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-first-data
3
- Version: 0.6.0
3
+ Version: 0.7.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
@@ -188,6 +188,8 @@ Most users don't need this. Output functions automatically protect secrets.
188
188
  parse_size(s: str) -> int | None # Parse "10M" → bytes
189
189
  ```
190
190
 
191
+ Returns `None` for invalid, negative, or overflow input.
192
+
191
193
  **Example:**
192
194
  ```python
193
195
  from agent_first_data import *
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "agent-first-data"
3
- version = "0.6.0"
3
+ version = "0.7.0"
4
4
  description = "Agent-First Data (AFDATA) — suffix-driven output formatting and protocol templates for AI agents"
5
5
  license = "MIT"
6
6
  readme = "README.md"
@@ -11,6 +11,8 @@ from agent_first_data import (
11
11
  internal_redact_secrets,
12
12
  output_json,
13
13
  output_json_with,
14
+ output_yaml,
15
+ output_plain,
14
16
  )
15
17
  from agent_first_data.format import (
16
18
  _format_bytes_human,
@@ -92,6 +94,21 @@ def test_helper_fixtures():
92
94
  assert got == expected, f"[helpers/{name}({inp!r})] got {got!r}"
93
95
 
94
96
 
97
+ def test_output_format_fixtures():
98
+ for case in _load("output_formats.json"):
99
+ name = case["name"]
100
+ inp = json.loads(json.dumps(case["input"]))
101
+
102
+ got_json = json.loads(output_json(inp))
103
+ assert got_json == case["expected_json"], f"[output/{name}] json mismatch: {got_json}"
104
+
105
+ got_yaml = output_yaml(inp)
106
+ assert got_yaml == case["expected_yaml"], f"[output/{name}] yaml mismatch: {got_yaml!r}"
107
+
108
+ got_plain = output_plain(inp)
109
+ assert got_plain == case["expected_plain"], f"[output/{name}] plain mismatch: {got_plain!r}"
110
+
111
+
95
112
  def test_output_json_exception_field_is_readable():
96
113
  out = output_json({"error": Exception("timeout")})
97
114
  parsed = json.loads(out)