fishertools 0.2.1__py3-none-any.whl → 0.4.0__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.
Files changed (69) hide show
  1. fishertools/__init__.py +16 -5
  2. fishertools/errors/__init__.py +11 -3
  3. fishertools/errors/exception_types.py +282 -0
  4. fishertools/errors/explainer.py +87 -1
  5. fishertools/errors/models.py +73 -1
  6. fishertools/errors/patterns.py +40 -0
  7. fishertools/examples/cli_example.py +156 -0
  8. fishertools/examples/learn_example.py +65 -0
  9. fishertools/examples/logger_example.py +176 -0
  10. fishertools/examples/menu_example.py +101 -0
  11. fishertools/examples/storage_example.py +175 -0
  12. fishertools/input_utils.py +185 -0
  13. fishertools/learn/__init__.py +19 -2
  14. fishertools/learn/examples.py +88 -1
  15. fishertools/learn/knowledge_engine.py +321 -0
  16. fishertools/learn/repl/__init__.py +19 -0
  17. fishertools/learn/repl/cli.py +31 -0
  18. fishertools/learn/repl/code_sandbox.py +229 -0
  19. fishertools/learn/repl/command_handler.py +544 -0
  20. fishertools/learn/repl/command_parser.py +165 -0
  21. fishertools/learn/repl/engine.py +479 -0
  22. fishertools/learn/repl/models.py +121 -0
  23. fishertools/learn/repl/session_manager.py +284 -0
  24. fishertools/learn/repl/test_code_sandbox.py +261 -0
  25. fishertools/learn/repl/test_code_sandbox_pbt.py +148 -0
  26. fishertools/learn/repl/test_command_handler.py +224 -0
  27. fishertools/learn/repl/test_command_handler_pbt.py +189 -0
  28. fishertools/learn/repl/test_command_parser.py +160 -0
  29. fishertools/learn/repl/test_command_parser_pbt.py +100 -0
  30. fishertools/learn/repl/test_engine.py +190 -0
  31. fishertools/learn/repl/test_session_manager.py +310 -0
  32. fishertools/learn/repl/test_session_manager_pbt.py +182 -0
  33. fishertools/learn/test_knowledge_engine.py +241 -0
  34. fishertools/learn/test_knowledge_engine_pbt.py +180 -0
  35. fishertools/patterns/__init__.py +46 -0
  36. fishertools/patterns/cli.py +175 -0
  37. fishertools/patterns/logger.py +140 -0
  38. fishertools/patterns/menu.py +99 -0
  39. fishertools/patterns/storage.py +127 -0
  40. fishertools/readme_transformer.py +631 -0
  41. fishertools/safe/__init__.py +6 -1
  42. fishertools/safe/files.py +329 -1
  43. fishertools/transform_readme.py +105 -0
  44. fishertools-0.4.0.dist-info/METADATA +104 -0
  45. fishertools-0.4.0.dist-info/RECORD +131 -0
  46. {fishertools-0.2.1.dist-info → fishertools-0.4.0.dist-info}/WHEEL +1 -1
  47. tests/test_documentation_properties.py +329 -0
  48. tests/test_documentation_structure.py +349 -0
  49. tests/test_errors/test_exception_types.py +446 -0
  50. tests/test_errors/test_exception_types_pbt.py +333 -0
  51. tests/test_errors/test_patterns.py +52 -0
  52. tests/test_input_utils/__init__.py +1 -0
  53. tests/test_input_utils/test_input_utils.py +65 -0
  54. tests/test_learn/test_examples.py +179 -1
  55. tests/test_learn/test_explain_properties.py +307 -0
  56. tests/test_patterns_cli.py +611 -0
  57. tests/test_patterns_docstrings.py +473 -0
  58. tests/test_patterns_logger.py +465 -0
  59. tests/test_patterns_menu.py +440 -0
  60. tests/test_patterns_storage.py +447 -0
  61. tests/test_readme_enhancements_v0_3_1.py +2036 -0
  62. tests/test_readme_transformer/__init__.py +1 -0
  63. tests/test_readme_transformer/test_readme_infrastructure.py +1023 -0
  64. tests/test_readme_transformer/test_transform_readme_integration.py +431 -0
  65. tests/test_safe/test_files.py +726 -1
  66. fishertools-0.2.1.dist-info/METADATA +0 -256
  67. fishertools-0.2.1.dist-info/RECORD +0 -81
  68. {fishertools-0.2.1.dist-info → fishertools-0.4.0.dist-info}/licenses/LICENSE +0 -0
  69. {fishertools-0.2.1.dist-info → fishertools-0.4.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,473 @@
1
+ """
2
+ Property-based tests for pattern docstrings in fishertools.patterns.
3
+
4
+ Tests the correctness property that all pattern classes and functions have
5
+ comprehensive docstrings explaining their purpose and usage.
6
+
7
+ **Validates: Requirements 7.3, 12.1**
8
+ """
9
+
10
+ import pytest
11
+ import inspect
12
+ from hypothesis import given, strategies as st
13
+
14
+ from fishertools.patterns.menu import simple_menu
15
+ from fishertools.patterns.storage import JSONStorage
16
+ from fishertools.patterns.logger import SimpleLogger
17
+ from fishertools.patterns.cli import SimpleCLI
18
+
19
+
20
+ class TestAllPatternsHaveDocstrings:
21
+ """
22
+ Property 10: All Patterns Have Docstrings
23
+
24
+ For all pattern classes and functions, they should have non-empty docstrings
25
+ explaining their purpose.
26
+
27
+ **Validates: Requirements 7.3, 12.1**
28
+ """
29
+
30
+ def test_simple_menu_has_docstring(self):
31
+ """Test that simple_menu() has a docstring."""
32
+ assert simple_menu.__doc__ is not None
33
+ assert len(simple_menu.__doc__) > 0
34
+ assert simple_menu.__doc__.strip() != ""
35
+
36
+ def test_simple_menu_docstring_is_meaningful(self):
37
+ """Test that simple_menu() docstring is meaningful."""
38
+ docstring = simple_menu.__doc__
39
+
40
+ # Should contain key information
41
+ assert "menu" in docstring.lower()
42
+ assert "options" in docstring.lower()
43
+
44
+ # Should be substantial
45
+ assert len(docstring) >= 100
46
+
47
+ def test_simple_menu_docstring_has_parameters(self):
48
+ """Test that simple_menu() docstring documents parameters."""
49
+ docstring = simple_menu.__doc__
50
+
51
+ # Should mention parameters
52
+ assert "Parameters" in docstring or "parameters" in docstring.lower()
53
+ assert "options" in docstring.lower()
54
+
55
+ def test_simple_menu_docstring_has_returns(self):
56
+ """Test that simple_menu() docstring documents return value."""
57
+ docstring = simple_menu.__doc__
58
+
59
+ # Should mention return value
60
+ assert "Returns" in docstring or "returns" in docstring.lower()
61
+
62
+ def test_simple_menu_docstring_has_example(self):
63
+ """Test that simple_menu() docstring includes an example."""
64
+ docstring = simple_menu.__doc__
65
+
66
+ # Should include example
67
+ assert "Example" in docstring or "example" in docstring.lower()
68
+
69
+ def test_jsonstorage_class_has_docstring(self):
70
+ """Test that JSONStorage class has a docstring."""
71
+ assert JSONStorage.__doc__ is not None
72
+ assert len(JSONStorage.__doc__) > 0
73
+ assert JSONStorage.__doc__.strip() != ""
74
+
75
+ def test_jsonstorage_class_docstring_is_meaningful(self):
76
+ """Test that JSONStorage class docstring is meaningful."""
77
+ docstring = JSONStorage.__doc__
78
+
79
+ # Should contain key information
80
+ assert "JSON" in docstring or "json" in docstring.lower()
81
+ assert "storage" in docstring.lower() or "save" in docstring.lower()
82
+
83
+ # Should be substantial
84
+ assert len(docstring) >= 100
85
+
86
+ def test_jsonstorage_init_has_docstring(self):
87
+ """Test that JSONStorage.__init__() has a docstring."""
88
+ assert JSONStorage.__init__.__doc__ is not None
89
+ assert len(JSONStorage.__init__.__doc__) > 0
90
+
91
+ def test_jsonstorage_save_has_docstring(self):
92
+ """Test that JSONStorage.save() has a docstring."""
93
+ assert JSONStorage.save.__doc__ is not None
94
+ assert len(JSONStorage.save.__doc__) > 0
95
+ assert "save" in JSONStorage.save.__doc__.lower()
96
+
97
+ def test_jsonstorage_load_has_docstring(self):
98
+ """Test that JSONStorage.load() has a docstring."""
99
+ assert JSONStorage.load.__doc__ is not None
100
+ assert len(JSONStorage.load.__doc__) > 0
101
+ assert "load" in JSONStorage.load.__doc__.lower()
102
+
103
+ def test_jsonstorage_exists_has_docstring(self):
104
+ """Test that JSONStorage.exists() has a docstring."""
105
+ assert JSONStorage.exists.__doc__ is not None
106
+ assert len(JSONStorage.exists.__doc__) > 0
107
+ assert "exist" in JSONStorage.exists.__doc__.lower()
108
+
109
+ def test_jsonstorage_class_docstring_has_parameters(self):
110
+ """Test that JSONStorage class docstring documents parameters."""
111
+ docstring = JSONStorage.__doc__
112
+
113
+ # Should mention parameters
114
+ assert "Parameters" in docstring or "parameters" in docstring.lower()
115
+ assert "file_path" in docstring.lower()
116
+
117
+ def test_jsonstorage_class_docstring_has_methods(self):
118
+ """Test that JSONStorage class docstring documents methods."""
119
+ docstring = JSONStorage.__doc__
120
+
121
+ # Should mention methods
122
+ assert "Methods" in docstring or "methods" in docstring.lower()
123
+ assert "save" in docstring.lower()
124
+ assert "load" in docstring.lower()
125
+
126
+ def test_jsonstorage_class_docstring_has_example(self):
127
+ """Test that JSONStorage class docstring includes an example."""
128
+ docstring = JSONStorage.__doc__
129
+
130
+ # Should include example
131
+ assert "Example" in docstring or "example" in docstring.lower()
132
+
133
+ def test_simplelogger_class_has_docstring(self):
134
+ """Test that SimpleLogger class has a docstring."""
135
+ assert SimpleLogger.__doc__ is not None
136
+ assert len(SimpleLogger.__doc__) > 0
137
+ assert SimpleLogger.__doc__.strip() != ""
138
+
139
+ def test_simplelogger_class_docstring_is_meaningful(self):
140
+ """Test that SimpleLogger class docstring is meaningful."""
141
+ docstring = SimpleLogger.__doc__
142
+
143
+ # Should contain key information
144
+ assert "log" in docstring.lower()
145
+ assert "file" in docstring.lower() or "message" in docstring.lower()
146
+
147
+ # Should be substantial
148
+ assert len(docstring) >= 100
149
+
150
+ def test_simplelogger_init_has_docstring(self):
151
+ """Test that SimpleLogger.__init__() has a docstring."""
152
+ assert SimpleLogger.__init__.__doc__ is not None
153
+ assert len(SimpleLogger.__init__.__doc__) > 0
154
+
155
+ def test_simplelogger_info_has_docstring(self):
156
+ """Test that SimpleLogger.info() has a docstring."""
157
+ assert SimpleLogger.info.__doc__ is not None
158
+ assert len(SimpleLogger.info.__doc__) > 0
159
+ assert "info" in SimpleLogger.info.__doc__.lower()
160
+
161
+ def test_simplelogger_warning_has_docstring(self):
162
+ """Test that SimpleLogger.warning() has a docstring."""
163
+ assert SimpleLogger.warning.__doc__ is not None
164
+ assert len(SimpleLogger.warning.__doc__) > 0
165
+ assert "warning" in SimpleLogger.warning.__doc__.lower()
166
+
167
+ def test_simplelogger_error_has_docstring(self):
168
+ """Test that SimpleLogger.error() has a docstring."""
169
+ assert SimpleLogger.error.__doc__ is not None
170
+ assert len(SimpleLogger.error.__doc__) > 0
171
+ assert "error" in SimpleLogger.error.__doc__.lower()
172
+
173
+ def test_simplelogger_class_docstring_has_parameters(self):
174
+ """Test that SimpleLogger class docstring documents parameters."""
175
+ docstring = SimpleLogger.__doc__
176
+
177
+ # Should mention parameters
178
+ assert "Parameters" in docstring or "parameters" in docstring.lower()
179
+ assert "file_path" in docstring.lower()
180
+
181
+ def test_simplelogger_class_docstring_has_methods(self):
182
+ """Test that SimpleLogger class docstring documents methods."""
183
+ docstring = SimpleLogger.__doc__
184
+
185
+ # Should mention methods
186
+ assert "Methods" in docstring or "methods" in docstring.lower()
187
+ assert "info" in docstring.lower()
188
+ assert "warning" in docstring.lower()
189
+ assert "error" in docstring.lower()
190
+
191
+ def test_simplelogger_class_docstring_has_example(self):
192
+ """Test that SimpleLogger class docstring includes an example."""
193
+ docstring = SimpleLogger.__doc__
194
+
195
+ # Should include example
196
+ assert "Example" in docstring or "example" in docstring.lower()
197
+
198
+ def test_simplecli_class_has_docstring(self):
199
+ """Test that SimpleCLI class has a docstring."""
200
+ assert SimpleCLI.__doc__ is not None
201
+ assert len(SimpleCLI.__doc__) > 0
202
+ assert SimpleCLI.__doc__.strip() != ""
203
+
204
+ def test_simplecli_class_docstring_is_meaningful(self):
205
+ """Test that SimpleCLI class docstring is meaningful."""
206
+ docstring = SimpleCLI.__doc__
207
+
208
+ # Should contain key information
209
+ assert "CLI" in docstring or "command" in docstring.lower()
210
+ assert "interface" in docstring.lower() or "command" in docstring.lower()
211
+
212
+ # Should be substantial
213
+ assert len(docstring) >= 100
214
+
215
+ def test_simplecli_init_has_docstring(self):
216
+ """Test that SimpleCLI.__init__() has a docstring."""
217
+ assert SimpleCLI.__init__.__doc__ is not None
218
+ assert len(SimpleCLI.__init__.__doc__) > 0
219
+
220
+ def test_simplecli_command_has_docstring(self):
221
+ """Test that SimpleCLI.command() has a docstring."""
222
+ assert SimpleCLI.command.__doc__ is not None
223
+ assert len(SimpleCLI.command.__doc__) > 0
224
+ assert "command" in SimpleCLI.command.__doc__.lower()
225
+
226
+ def test_simplecli_run_has_docstring(self):
227
+ """Test that SimpleCLI.run() has a docstring."""
228
+ assert SimpleCLI.run.__doc__ is not None
229
+ assert len(SimpleCLI.run.__doc__) > 0
230
+ assert "run" in SimpleCLI.run.__doc__.lower() or "execute" in SimpleCLI.run.__doc__.lower()
231
+
232
+ def test_simplecli_class_docstring_has_parameters(self):
233
+ """Test that SimpleCLI class docstring documents parameters."""
234
+ docstring = SimpleCLI.__doc__
235
+
236
+ # Should mention parameters
237
+ assert "Parameters" in docstring or "parameters" in docstring.lower()
238
+ assert "name" in docstring.lower()
239
+ assert "description" in docstring.lower()
240
+
241
+ def test_simplecli_class_docstring_has_methods(self):
242
+ """Test that SimpleCLI class docstring documents methods."""
243
+ docstring = SimpleCLI.__doc__
244
+
245
+ # Should mention methods
246
+ assert "Methods" in docstring or "methods" in docstring.lower()
247
+ assert "command" in docstring.lower()
248
+ assert "run" in docstring.lower()
249
+
250
+ def test_simplecli_class_docstring_has_example(self):
251
+ """Test that SimpleCLI class docstring includes an example."""
252
+ docstring = SimpleCLI.__doc__
253
+
254
+ # Should include example
255
+ assert "Example" in docstring or "example" in docstring.lower()
256
+
257
+ def test_all_pattern_classes_have_docstrings(self):
258
+ """Test that all pattern classes have docstrings."""
259
+ pattern_classes = [JSONStorage, SimpleLogger, SimpleCLI]
260
+
261
+ for cls in pattern_classes:
262
+ assert cls.__doc__ is not None, f"{cls.__name__} missing docstring"
263
+ assert len(cls.__doc__) > 0, f"{cls.__name__} has empty docstring"
264
+ assert cls.__doc__.strip() != "", f"{cls.__name__} has whitespace-only docstring"
265
+
266
+ def test_all_pattern_functions_have_docstrings(self):
267
+ """Test that all pattern functions have docstrings."""
268
+ pattern_functions = [simple_menu]
269
+
270
+ for func in pattern_functions:
271
+ assert func.__doc__ is not None, f"{func.__name__} missing docstring"
272
+ assert len(func.__doc__) > 0, f"{func.__name__} has empty docstring"
273
+ assert func.__doc__.strip() != "", f"{func.__name__} has whitespace-only docstring"
274
+
275
+ def test_all_pattern_public_methods_have_docstrings(self):
276
+ """Test that all public methods in pattern classes have docstrings."""
277
+ pattern_classes = [JSONStorage, SimpleLogger, SimpleCLI]
278
+
279
+ for cls in pattern_classes:
280
+ # Get all public methods
281
+ for name, method in inspect.getmembers(cls, predicate=inspect.isfunction):
282
+ if not name.startswith('_'):
283
+ assert method.__doc__ is not None, f"{cls.__name__}.{name} missing docstring"
284
+ assert len(method.__doc__) > 0, f"{cls.__name__}.{name} has empty docstring"
285
+
286
+ def test_docstrings_contain_meaningful_content(self):
287
+ """Test that docstrings contain meaningful content."""
288
+ pattern_items = [
289
+ (simple_menu, "simple_menu"),
290
+ (JSONStorage, "JSONStorage"),
291
+ (SimpleLogger, "SimpleLogger"),
292
+ (SimpleCLI, "SimpleCLI")
293
+ ]
294
+
295
+ for item, name in pattern_items:
296
+ docstring = item.__doc__
297
+
298
+ # Should have substantial content
299
+ assert len(docstring) >= 50, f"{name} docstring too short"
300
+
301
+ # Should contain alphabetic characters
302
+ assert any(c.isalpha() for c in docstring), f"{name} docstring has no text"
303
+
304
+ def test_docstrings_follow_format(self):
305
+ """Test that docstrings follow a consistent format."""
306
+ pattern_classes = [JSONStorage, SimpleLogger, SimpleCLI]
307
+
308
+ for cls in pattern_classes:
309
+ docstring = cls.__doc__
310
+
311
+ # Should have a summary line
312
+ lines = docstring.strip().split('\n')
313
+ assert len(lines) > 1, f"{cls.__name__} docstring too short"
314
+
315
+ # First line should be a summary
316
+ summary = lines[0].strip()
317
+ assert len(summary) > 10, f"{cls.__name__} summary too short"
318
+
319
+ def test_method_docstrings_document_parameters(self):
320
+ """Test that method docstrings document their parameters."""
321
+ # Check JSONStorage.save
322
+ save_doc = JSONStorage.save.__doc__
323
+ assert "Parameters" in save_doc or "parameters" in save_doc.lower()
324
+ assert "data" in save_doc.lower()
325
+
326
+ # Check SimpleLogger.info
327
+ info_doc = SimpleLogger.info.__doc__
328
+ assert "Parameters" in info_doc or "parameters" in info_doc.lower()
329
+ assert "message" in info_doc.lower()
330
+
331
+ # Check SimpleCLI.command
332
+ command_doc = SimpleCLI.command.__doc__
333
+ assert "Parameters" in command_doc or "parameters" in command_doc.lower()
334
+
335
+ def test_method_docstrings_document_returns(self):
336
+ """Test that method docstrings document return values."""
337
+ # Check JSONStorage.load
338
+ load_doc = JSONStorage.load.__doc__
339
+ assert "Returns" in load_doc or "returns" in load_doc.lower()
340
+
341
+ # Check JSONStorage.exists
342
+ exists_doc = JSONStorage.exists.__doc__
343
+ assert "Returns" in exists_doc or "returns" in exists_doc.lower()
344
+
345
+ def test_docstrings_are_not_just_pass_statements(self):
346
+ """Test that docstrings are actual documentation, not just pass."""
347
+ pattern_items = [
348
+ simple_menu,
349
+ JSONStorage,
350
+ SimpleLogger,
351
+ SimpleCLI
352
+ ]
353
+
354
+ for item in pattern_items:
355
+ docstring = item.__doc__
356
+
357
+ # Should not be just "pass" or similar
358
+ assert docstring.lower().strip() != "pass"
359
+ assert docstring.lower().strip() != "todo"
360
+ assert docstring.lower().strip() != "..."
361
+
362
+ def test_docstrings_have_examples(self):
363
+ """Test that main docstrings include usage examples."""
364
+ pattern_items = [
365
+ (simple_menu, "simple_menu"),
366
+ (JSONStorage, "JSONStorage"),
367
+ (SimpleLogger, "SimpleLogger"),
368
+ (SimpleCLI, "SimpleCLI")
369
+ ]
370
+
371
+ for item, name in pattern_items:
372
+ docstring = item.__doc__
373
+
374
+ # Should include example
375
+ assert "Example" in docstring or "example" in docstring.lower(), \
376
+ f"{name} docstring missing example"
377
+
378
+ def test_docstrings_have_notes_or_warnings(self):
379
+ """Test that docstrings include helpful notes."""
380
+ pattern_items = [
381
+ (simple_menu, "simple_menu"),
382
+ (JSONStorage, "JSONStorage"),
383
+ (SimpleLogger, "SimpleLogger"),
384
+ (SimpleCLI, "SimpleCLI")
385
+ ]
386
+
387
+ for item, name in pattern_items:
388
+ docstring = item.__doc__
389
+
390
+ # Should include note or important information
391
+ has_note = "Note" in docstring or "note" in docstring.lower()
392
+ has_important = "Important" in docstring or "important" in docstring.lower()
393
+
394
+ assert has_note or has_important, \
395
+ f"{name} docstring missing notes or important information"
396
+
397
+
398
+ class TestDocstringQuality:
399
+ """Test the quality and completeness of docstrings."""
400
+
401
+ def test_simple_menu_docstring_mentions_exit(self):
402
+ """Test that simple_menu docstring mentions exit behavior."""
403
+ docstring = simple_menu.__doc__
404
+
405
+ assert "quit" in docstring.lower() or "exit" in docstring.lower()
406
+
407
+ def test_jsonstorage_docstring_mentions_directory_creation(self):
408
+ """Test that JSONStorage docstring mentions directory creation."""
409
+ docstring = JSONStorage.__doc__
410
+
411
+ assert "director" in docstring.lower() or "create" in docstring.lower()
412
+
413
+ def test_simplelogger_docstring_mentions_timestamp(self):
414
+ """Test that SimpleLogger docstring mentions timestamp format."""
415
+ docstring = SimpleLogger.__doc__
416
+
417
+ assert "timestamp" in docstring.lower() or "time" in docstring.lower()
418
+
419
+ def test_simplecli_docstring_mentions_decorator(self):
420
+ """Test that SimpleCLI docstring mentions decorator usage."""
421
+ docstring = SimpleCLI.__doc__
422
+
423
+ assert "decorator" in docstring.lower() or "@" in docstring
424
+
425
+ def test_all_docstrings_are_accessible(self):
426
+ """Test that all docstrings are accessible via help()."""
427
+ pattern_items = [simple_menu, JSONStorage, SimpleLogger, SimpleCLI]
428
+
429
+ for item in pattern_items:
430
+ # Should be able to get help
431
+ help_text = inspect.getdoc(item)
432
+ assert help_text is not None
433
+ assert len(help_text) > 0
434
+
435
+
436
+ class TestDocstringConsistency:
437
+ """Test consistency across docstrings."""
438
+
439
+ def test_all_class_docstrings_have_similar_structure(self):
440
+ """Test that all class docstrings follow a similar structure."""
441
+ pattern_classes = [JSONStorage, SimpleLogger, SimpleCLI]
442
+
443
+ for cls in pattern_classes:
444
+ docstring = cls.__doc__
445
+
446
+ # Should have Parameters section
447
+ assert "Parameters" in docstring or "parameters" in docstring.lower()
448
+
449
+ # Should have Methods section (for classes)
450
+ assert "Methods" in docstring or "methods" in docstring.lower()
451
+
452
+ # Should have Example section
453
+ assert "Example" in docstring or "example" in docstring.lower()
454
+
455
+ def test_all_method_docstrings_have_parameters_section(self):
456
+ """Test that all methods with parameters document them."""
457
+ # JSONStorage.save has parameters
458
+ save_doc = JSONStorage.save.__doc__
459
+ assert "Parameters" in save_doc or "parameters" in save_doc.lower()
460
+
461
+ # SimpleLogger.info has parameters
462
+ info_doc = SimpleLogger.info.__doc__
463
+ assert "Parameters" in info_doc or "parameters" in info_doc.lower()
464
+
465
+ def test_all_method_docstrings_have_returns_section(self):
466
+ """Test that all methods document their return values."""
467
+ # JSONStorage.load returns data
468
+ load_doc = JSONStorage.load.__doc__
469
+ assert "Returns" in load_doc or "returns" in load_doc.lower()
470
+
471
+ # JSONStorage.exists returns bool
472
+ exists_doc = JSONStorage.exists.__doc__
473
+ assert "Returns" in exists_doc or "returns" in exists_doc.lower()