pygeai 0.7.0b1__py3-none-any.whl → 0.7.0b4__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.
@@ -0,0 +1,419 @@
1
+ import unittest
2
+ import json
3
+ from json import JSONDecodeError
4
+
5
+
6
+ class TestCLIJsonParsing(unittest.TestCase):
7
+ """
8
+ Tests for JSON parsing patterns used in CLI commands.
9
+
10
+ These tests document the current behavior of json.loads() in CLI commands
11
+ to ensure optimizations don't break functionality.
12
+
13
+ Run with:
14
+ python -m unittest pygeai.tests.cli.commands.test_json_parsing.TestCLIJsonParsing
15
+ """
16
+
17
+ def test_parse_json_list_valid(self):
18
+ """Test parsing valid JSON list from CLI argument"""
19
+ json_str = '["input1", "input2", "input3"]'
20
+
21
+ result = json.loads(json_str)
22
+
23
+ self.assertIsInstance(result, list)
24
+ self.assertEqual(len(result), 3)
25
+ self.assertEqual(result, ["input1", "input2", "input3"])
26
+
27
+ def test_parse_json_dict_valid(self):
28
+ """Test parsing valid JSON dict from CLI argument"""
29
+ json_str = '{"key": "output_key", "description": "Output description"}'
30
+
31
+ result = json.loads(json_str)
32
+
33
+ self.assertIsInstance(result, dict)
34
+ self.assertEqual(result["key"], "output_key")
35
+ self.assertEqual(result["description"], "Output description")
36
+
37
+ def test_parse_json_list_of_dicts(self):
38
+ """Test parsing list of dictionaries (common CLI pattern)"""
39
+ json_str = '[{"key": "out1", "description": "First"}, {"key": "out2", "description": "Second"}]'
40
+
41
+ result = json.loads(json_str)
42
+
43
+ self.assertIsInstance(result, list)
44
+ self.assertEqual(len(result), 2)
45
+ self.assertEqual(result[0]["key"], "out1")
46
+ self.assertEqual(result[1]["key"], "out2")
47
+
48
+ def test_parse_json_invalid_raises_decode_error(self):
49
+ """Test that invalid JSON raises JSONDecodeError"""
50
+ invalid_json = 'not valid json'
51
+
52
+ with self.assertRaises(JSONDecodeError):
53
+ json.loads(invalid_json)
54
+
55
+ def test_parse_json_empty_string_raises_error(self):
56
+ """Test that empty string raises JSONDecodeError"""
57
+ with self.assertRaises(JSONDecodeError):
58
+ json.loads('')
59
+
60
+ def test_parse_json_single_quoted_invalid(self):
61
+ """Test that single quotes are invalid JSON (common CLI mistake)"""
62
+ # Common mistake: using single quotes instead of double quotes
63
+ invalid_json = "{'key': 'value'}"
64
+
65
+ with self.assertRaises(JSONDecodeError):
66
+ json.loads(invalid_json)
67
+
68
+ def test_parse_json_trailing_comma_invalid(self):
69
+ """Test that trailing commas are invalid JSON"""
70
+ invalid_json = '{"key": "value",}'
71
+
72
+ with self.assertRaises(JSONDecodeError):
73
+ json.loads(invalid_json)
74
+
75
+ def test_parse_json_unquoted_keys_invalid(self):
76
+ """Test that unquoted keys are invalid JSON"""
77
+ invalid_json = '{key: "value"}'
78
+
79
+ with self.assertRaises(JSONDecodeError):
80
+ json.loads(invalid_json)
81
+
82
+ def test_parse_json_with_escaped_quotes(self):
83
+ """Test parsing JSON with escaped quotes (common in CLI)"""
84
+ json_str = '{"text": "He said \\"hello\\""}'
85
+
86
+ result = json.loads(json_str)
87
+
88
+ self.assertEqual(result["text"], 'He said "hello"')
89
+
90
+ def test_parse_json_with_newlines(self):
91
+ """Test parsing JSON with newlines"""
92
+ json_str = '{\n "key": "value",\n "another": "test"\n}'
93
+
94
+ result = json.loads(json_str)
95
+
96
+ self.assertEqual(result["key"], "value")
97
+ self.assertEqual(result["another"], "test")
98
+
99
+ def test_parse_json_boolean_values(self):
100
+ """Test parsing JSON boolean values (lowercase only in JSON)"""
101
+ json_str = '{"enabled": true, "disabled": false}'
102
+
103
+ result = json.loads(json_str)
104
+
105
+ self.assertTrue(result["enabled"])
106
+ self.assertFalse(result["disabled"])
107
+
108
+ def test_parse_json_null_value(self):
109
+ """Test parsing JSON null value"""
110
+ json_str = '{"value": null}'
111
+
112
+ result = json.loads(json_str)
113
+
114
+ self.assertIsNone(result["value"])
115
+
116
+ def test_parse_json_numbers(self):
117
+ """Test parsing various number formats"""
118
+ json_str = '{"int": 42, "float": 3.14, "negative": -10, "scientific": 1e5}'
119
+
120
+ result = json.loads(json_str)
121
+
122
+ self.assertEqual(result["int"], 42)
123
+ self.assertAlmostEqual(result["float"], 3.14)
124
+ self.assertEqual(result["negative"], -10)
125
+ self.assertEqual(result["scientific"], 100000)
126
+
127
+ def test_parse_json_nested_structures(self):
128
+ """Test parsing nested JSON structures (common in complex CLI args)"""
129
+ json_str = '''
130
+ {
131
+ "agent": {
132
+ "name": "Test Agent",
133
+ "config": {
134
+ "inputs": ["input1", "input2"],
135
+ "outputs": [{"key": "out1", "type": "string"}]
136
+ }
137
+ }
138
+ }
139
+ '''
140
+
141
+ result = json.loads(json_str)
142
+
143
+ self.assertEqual(result["agent"]["name"], "Test Agent")
144
+ self.assertEqual(len(result["agent"]["config"]["inputs"]), 2)
145
+ self.assertEqual(result["agent"]["config"]["outputs"][0]["key"], "out1")
146
+
147
+ def test_parse_json_empty_structures(self):
148
+ """Test parsing empty JSON structures"""
149
+ # Empty list
150
+ result = json.loads('[]')
151
+ self.assertEqual(result, [])
152
+
153
+ # Empty dict
154
+ result = json.loads('{}')
155
+ self.assertEqual(result, {})
156
+
157
+ def test_parse_json_unicode_characters(self):
158
+ """Test parsing JSON with unicode characters"""
159
+ json_str = '{"text": "Hello 世界 🌍"}'
160
+
161
+ result = json.loads(json_str)
162
+
163
+ self.assertEqual(result["text"], "Hello 世界 🌍")
164
+
165
+ def test_parse_json_whitespace_handling(self):
166
+ """Test that JSON parsing handles various whitespace correctly"""
167
+ # Multiple spaces
168
+ result1 = json.loads(' { "key" : "value" } ')
169
+ self.assertEqual(result1, {"key": "value"})
170
+
171
+ # Tabs
172
+ result2 = json.loads('\t{\t"key"\t:\t"value"\t}\t')
173
+ self.assertEqual(result2, {"key": "value"})
174
+
175
+ def test_isinstance_check_list(self):
176
+ """Test isinstance check pattern used in CLI code"""
177
+ result = json.loads('["a", "b"]')
178
+
179
+ # This is the pattern used in CLI commands
180
+ if isinstance(result, list):
181
+ self.assertTrue(True)
182
+ else:
183
+ self.fail("Expected list type")
184
+
185
+ def test_isinstance_check_dict(self):
186
+ """Test isinstance check pattern for dict"""
187
+ result = json.loads('{"key": "value"}')
188
+
189
+ if isinstance(result, dict):
190
+ self.assertTrue(True)
191
+ else:
192
+ self.fail("Expected dict type")
193
+
194
+ def test_type_validation_pattern(self):
195
+ """Test the type validation pattern used in CLI commands"""
196
+ # Pattern: parse and validate type
197
+ json_str = '["input1", "input2"]'
198
+
199
+ try:
200
+ result = json.loads(json_str)
201
+ if not isinstance(result, list):
202
+ raise ValueError("Expected list")
203
+ # Success
204
+ self.assertEqual(len(result), 2)
205
+ except (JSONDecodeError, ValueError) as e:
206
+ self.fail(f"Unexpected error: {e}")
207
+
208
+ def test_dict_or_list_pattern(self):
209
+ """Test the pattern where both dict and list are accepted"""
210
+ # This pattern is common in CLI commands
211
+
212
+ # Test with dict
213
+ dict_str = '{"key": "value"}'
214
+ result1 = json.loads(dict_str)
215
+ self.assertTrue(isinstance(result1, (dict, list)))
216
+
217
+ # Test with list
218
+ list_str = '[{"key": "value"}]'
219
+ result2 = json.loads(list_str)
220
+ self.assertTrue(isinstance(result2, (dict, list)))
221
+
222
+
223
+ class TestCLIJsonParsingRealWorldCases(unittest.TestCase):
224
+ """
225
+ Real-world JSON parsing cases from CLI commands.
226
+
227
+ Run with:
228
+ python -m unittest pygeai.tests.cli.commands.test_json_parsing.TestCLIJsonParsingRealWorldCases
229
+ """
230
+
231
+ def test_agent_prompt_inputs_format(self):
232
+ """Test agent_data_prompt_input format"""
233
+ json_str = '["user_input", "context", "history"]'
234
+
235
+ result = json.loads(json_str)
236
+
237
+ self.assertIsInstance(result, list)
238
+ self.assertEqual(len(result), 3)
239
+ for item in result:
240
+ self.assertIsInstance(item, str)
241
+
242
+ def test_agent_prompt_outputs_format(self):
243
+ """Test agent_data_prompt_output format"""
244
+ json_str = '[{"key": "response", "description": "Agent response"}, {"key": "confidence", "description": "Confidence score"}]'
245
+
246
+ result = json.loads(json_str)
247
+
248
+ self.assertIsInstance(result, list)
249
+ for item in result:
250
+ self.assertIn("key", item)
251
+ self.assertIn("description", item)
252
+
253
+ def test_agent_examples_format(self):
254
+ """Test agent_data_prompt_example format"""
255
+ json_str = '''
256
+ [
257
+ {
258
+ "inputs": {"user_input": "Hello"},
259
+ "output": {"response": "Hi there!"}
260
+ }
261
+ ]
262
+ '''
263
+
264
+ result = json.loads(json_str)
265
+
266
+ self.assertIsInstance(result, list)
267
+ self.assertIn("inputs", result[0])
268
+ self.assertIn("output", result[0])
269
+
270
+ def test_localized_description_format(self):
271
+ """Test localized_description format"""
272
+ json_str = '{"language": "en", "description": "Test description"}'
273
+
274
+ result = json.loads(json_str)
275
+
276
+ self.assertIsInstance(result, dict)
277
+ self.assertIn("language", result)
278
+ self.assertIn("description", result)
279
+
280
+ def test_json_schema_format(self):
281
+ """Test JSON schema format used in CLI"""
282
+ json_str = '''
283
+ {
284
+ "type": "object",
285
+ "properties": {
286
+ "name": {"type": "string"},
287
+ "age": {"type": "integer"}
288
+ },
289
+ "required": ["name"]
290
+ }
291
+ '''
292
+
293
+ result = json.loads(json_str)
294
+
295
+ self.assertEqual(result["type"], "object")
296
+ self.assertIn("properties", result)
297
+ self.assertIn("required", result)
298
+
299
+ def test_tool_parameters_format(self):
300
+ """Test tool parameters JSON format"""
301
+ json_str = '''
302
+ {
303
+ "type": "object",
304
+ "properties": {
305
+ "location": {
306
+ "type": "string",
307
+ "description": "City name"
308
+ },
309
+ "unit": {
310
+ "type": "string",
311
+ "enum": ["celsius", "fahrenheit"]
312
+ }
313
+ }
314
+ }
315
+ '''
316
+
317
+ result = json.loads(json_str)
318
+
319
+ self.assertEqual(result["type"], "object")
320
+ self.assertIn("enum", result["properties"]["unit"])
321
+
322
+ def test_metadata_format(self):
323
+ """Test metadata JSON format"""
324
+ json_str = '{"version": "1.0", "tags": ["prod", "critical"], "owner": "team-a"}'
325
+
326
+ result = json.loads(json_str)
327
+
328
+ self.assertEqual(result["version"], "1.0")
329
+ self.assertIsInstance(result["tags"], list)
330
+
331
+ def test_files_argument_format(self):
332
+ """Test files argument JSON format from chat commands"""
333
+ json_str = '[{"id": "file-1", "name": "doc.pdf"}, {"id": "file-2", "name": "image.png"}]'
334
+
335
+ result = json.loads(json_str)
336
+
337
+ self.assertIsInstance(result, list)
338
+ for file_obj in result:
339
+ self.assertIn("id", file_obj)
340
+ self.assertIn("name", file_obj)
341
+
342
+ def test_evaluation_dataset_format(self):
343
+ """Test evaluation dataset JSON format"""
344
+ json_str = '''
345
+ {
346
+ "test_cases": [
347
+ {"input": "test1", "expected": "output1"},
348
+ {"input": "test2", "expected": "output2"}
349
+ ]
350
+ }
351
+ '''
352
+
353
+ result = json.loads(json_str)
354
+
355
+ self.assertIn("test_cases", result)
356
+ self.assertEqual(len(result["test_cases"]), 2)
357
+
358
+
359
+ class TestCLIJsonParsingErrorHandling(unittest.TestCase):
360
+ """
361
+ Test error handling patterns in CLI JSON parsing.
362
+
363
+ Run with:
364
+ python -m unittest pygeai.tests.cli.commands.test_json_parsing.TestCLIJsonParsingErrorHandling
365
+ """
366
+
367
+ def test_catch_json_decode_error(self):
368
+ """Test catching JSONDecodeError"""
369
+ invalid_json = 'invalid'
370
+
371
+ try:
372
+ json.loads(invalid_json)
373
+ self.fail("Should have raised JSONDecodeError")
374
+ except JSONDecodeError as e:
375
+ # This is expected
376
+ self.assertIsInstance(e, JSONDecodeError)
377
+
378
+ def test_catch_value_error_for_type_check(self):
379
+ """Test catching ValueError for type validation"""
380
+ json_str = '{"key": "value"}'
381
+
382
+ try:
383
+ result = json.loads(json_str)
384
+ if not isinstance(result, list):
385
+ raise ValueError("Expected list")
386
+ self.fail("Should have raised ValueError")
387
+ except ValueError as e:
388
+ self.assertIn("Expected list", str(e))
389
+
390
+ def test_catch_combined_exceptions(self):
391
+ """Test catching both JSONDecodeError and ValueError"""
392
+ test_cases = [
393
+ ('invalid json', JSONDecodeError),
394
+ ('{"valid": "json"}', ValueError) # Wrong type
395
+ ]
396
+
397
+ for json_str, expected_error in test_cases:
398
+ with self.subTest(json_str=json_str):
399
+ try:
400
+ result = json.loads(json_str)
401
+ if not isinstance(result, list):
402
+ raise ValueError("Expected list")
403
+ except (JSONDecodeError, ValueError) as e:
404
+ self.assertIsInstance(e, (JSONDecodeError, ValueError))
405
+
406
+ def test_error_with_generic_exception(self):
407
+ """Test catching generic Exception (pattern used in some CLI commands)"""
408
+ invalid_json = 'invalid'
409
+
410
+ try:
411
+ json.loads(invalid_json)
412
+ self.fail("Should have raised exception")
413
+ except Exception as e:
414
+ # Generic exception catch (less specific but used in CLI code)
415
+ self.assertIsInstance(e, JSONDecodeError)
416
+
417
+
418
+ if __name__ == '__main__':
419
+ unittest.main()