fishertools 0.2.1__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 (81) hide show
  1. fishertools/__init__.py +82 -0
  2. fishertools/config/__init__.py +24 -0
  3. fishertools/config/manager.py +247 -0
  4. fishertools/config/models.py +96 -0
  5. fishertools/config/parser.py +265 -0
  6. fishertools/decorators.py +93 -0
  7. fishertools/documentation/__init__.py +38 -0
  8. fishertools/documentation/api.py +242 -0
  9. fishertools/documentation/generator.py +502 -0
  10. fishertools/documentation/models.py +126 -0
  11. fishertools/documentation/visual.py +583 -0
  12. fishertools/errors/__init__.py +29 -0
  13. fishertools/errors/exceptions.py +191 -0
  14. fishertools/errors/explainer.py +303 -0
  15. fishertools/errors/formatters.py +386 -0
  16. fishertools/errors/models.py +228 -0
  17. fishertools/errors/patterns.py +119 -0
  18. fishertools/errors/recovery.py +467 -0
  19. fishertools/examples/__init__.py +22 -0
  20. fishertools/examples/models.py +118 -0
  21. fishertools/examples/repository.py +770 -0
  22. fishertools/helpers.py +116 -0
  23. fishertools/integration.py +451 -0
  24. fishertools/learn/__init__.py +18 -0
  25. fishertools/learn/examples.py +550 -0
  26. fishertools/learn/tips.py +281 -0
  27. fishertools/learning/__init__.py +32 -0
  28. fishertools/learning/core.py +349 -0
  29. fishertools/learning/models.py +112 -0
  30. fishertools/learning/progress.py +314 -0
  31. fishertools/learning/session.py +500 -0
  32. fishertools/learning/tutorial.py +626 -0
  33. fishertools/legacy/__init__.py +76 -0
  34. fishertools/legacy/deprecated.py +261 -0
  35. fishertools/legacy/deprecation.py +149 -0
  36. fishertools/safe/__init__.py +16 -0
  37. fishertools/safe/collections.py +242 -0
  38. fishertools/safe/files.py +240 -0
  39. fishertools/safe/strings.py +15 -0
  40. fishertools/utils.py +57 -0
  41. fishertools-0.2.1.dist-info/METADATA +256 -0
  42. fishertools-0.2.1.dist-info/RECORD +81 -0
  43. fishertools-0.2.1.dist-info/WHEEL +5 -0
  44. fishertools-0.2.1.dist-info/licenses/LICENSE +21 -0
  45. fishertools-0.2.1.dist-info/top_level.txt +2 -0
  46. tests/__init__.py +6 -0
  47. tests/conftest.py +25 -0
  48. tests/test_config/__init__.py +3 -0
  49. tests/test_config/test_basic_config.py +57 -0
  50. tests/test_config/test_config_error_handling.py +287 -0
  51. tests/test_config/test_config_properties.py +435 -0
  52. tests/test_documentation/__init__.py +3 -0
  53. tests/test_documentation/test_documentation_properties.py +253 -0
  54. tests/test_documentation/test_visual_documentation_properties.py +444 -0
  55. tests/test_errors/__init__.py +3 -0
  56. tests/test_errors/test_api.py +301 -0
  57. tests/test_errors/test_error_handling.py +354 -0
  58. tests/test_errors/test_explainer.py +173 -0
  59. tests/test_errors/test_formatters.py +338 -0
  60. tests/test_errors/test_models.py +248 -0
  61. tests/test_errors/test_patterns.py +270 -0
  62. tests/test_examples/__init__.py +3 -0
  63. tests/test_examples/test_example_repository_properties.py +204 -0
  64. tests/test_examples/test_specific_examples.py +303 -0
  65. tests/test_integration.py +298 -0
  66. tests/test_integration_enhancements.py +462 -0
  67. tests/test_learn/__init__.py +3 -0
  68. tests/test_learn/test_examples.py +221 -0
  69. tests/test_learn/test_tips.py +285 -0
  70. tests/test_learning/__init__.py +3 -0
  71. tests/test_learning/test_interactive_learning_properties.py +337 -0
  72. tests/test_learning/test_learning_system_properties.py +194 -0
  73. tests/test_learning/test_progress_tracking_properties.py +279 -0
  74. tests/test_legacy/__init__.py +3 -0
  75. tests/test_legacy/test_backward_compatibility.py +236 -0
  76. tests/test_legacy/test_deprecation_warnings.py +208 -0
  77. tests/test_safe/__init__.py +3 -0
  78. tests/test_safe/test_collections_properties.py +189 -0
  79. tests/test_safe/test_files.py +104 -0
  80. tests/test_structure.py +58 -0
  81. tests/test_structure_enhancements.py +115 -0
@@ -0,0 +1,104 @@
1
+ """
2
+ Unit tests for safe file operations.
3
+ """
4
+
5
+ import pytest
6
+ import tempfile
7
+ import os
8
+ from pathlib import Path
9
+ from fishertools.safe.files import (
10
+ safe_read_file, safe_write_file, safe_file_exists,
11
+ safe_get_file_size, safe_list_files
12
+ )
13
+
14
+
15
+ class TestSafeFileOperations:
16
+ """Unit tests for safe file operations."""
17
+
18
+ def test_safe_read_file_existing_file(self):
19
+ """Test reading an existing file."""
20
+ with tempfile.NamedTemporaryFile(mode='w', delete=False, encoding='utf-8') as f:
21
+ f.write("Test content")
22
+ temp_path = f.name
23
+
24
+ try:
25
+ result = safe_read_file(temp_path)
26
+ assert result == "Test content"
27
+ finally:
28
+ os.unlink(temp_path)
29
+
30
+ def test_safe_read_file_nonexistent_file(self):
31
+ """Test reading a non-existent file returns default."""
32
+ result = safe_read_file("nonexistent_file.txt", default="default content")
33
+ assert result == "default content"
34
+
35
+ def test_safe_write_file_success(self):
36
+ """Test writing to a file successfully."""
37
+ with tempfile.TemporaryDirectory() as temp_dir:
38
+ file_path = Path(temp_dir) / "test_file.txt"
39
+ result = safe_write_file(file_path, "Hello World")
40
+ assert result is True
41
+ assert file_path.exists()
42
+ assert file_path.read_text(encoding='utf-8') == "Hello World"
43
+
44
+ def test_safe_file_exists_existing_file(self):
45
+ """Test checking existence of an existing file."""
46
+ with tempfile.NamedTemporaryFile(delete=False) as f:
47
+ temp_path = f.name
48
+
49
+ try:
50
+ assert safe_file_exists(temp_path) is True
51
+ finally:
52
+ os.unlink(temp_path)
53
+
54
+ def test_safe_file_exists_nonexistent_file(self):
55
+ """Test checking existence of a non-existent file."""
56
+ assert safe_file_exists("nonexistent_file.txt") is False
57
+
58
+ def test_safe_get_file_size_existing_file(self):
59
+ """Test getting size of an existing file."""
60
+ with tempfile.NamedTemporaryFile(mode='w', delete=False, encoding='utf-8') as f:
61
+ f.write("12345") # 5 bytes
62
+ temp_path = f.name
63
+
64
+ try:
65
+ size = safe_get_file_size(temp_path)
66
+ assert size == 5
67
+ finally:
68
+ os.unlink(temp_path)
69
+
70
+ def test_safe_get_file_size_nonexistent_file(self):
71
+ """Test getting size of a non-existent file returns default."""
72
+ size = safe_get_file_size("nonexistent_file.txt", default=100)
73
+ assert size == 100
74
+
75
+ def test_safe_list_files_existing_directory(self):
76
+ """Test listing files in an existing directory."""
77
+ with tempfile.TemporaryDirectory() as temp_dir:
78
+ # Create some test files
79
+ (Path(temp_dir) / "file1.txt").write_text("content1")
80
+ (Path(temp_dir) / "file2.py").write_text("content2")
81
+ (Path(temp_dir) / "subdir").mkdir()
82
+
83
+ files = safe_list_files(temp_dir)
84
+ assert "file1.txt" in files
85
+ assert "file2.py" in files
86
+ assert len(files) == 2 # Should not include subdirectory
87
+
88
+ def test_safe_list_files_nonexistent_directory(self):
89
+ """Test listing files in a non-existent directory returns default."""
90
+ files = safe_list_files("nonexistent_directory", default=["default"])
91
+ assert files == ["default"]
92
+
93
+ def test_input_validation_errors(self):
94
+ """Test that functions raise appropriate errors for invalid inputs."""
95
+ from fishertools.errors.exceptions import SafeUtilityError
96
+
97
+ with pytest.raises(SafeUtilityError, match="не может быть None"):
98
+ safe_read_file(None)
99
+
100
+ with pytest.raises(SafeUtilityError, match="должна быть строкой"):
101
+ safe_read_file("test.txt", encoding=123)
102
+
103
+ with pytest.raises(SafeUtilityError, match="должно быть строкой"):
104
+ safe_write_file("test.txt", 123)
@@ -0,0 +1,58 @@
1
+ """
2
+ Tests for project structure and imports.
3
+ """
4
+
5
+ import pytest
6
+
7
+
8
+ class TestProjectStructure:
9
+ """Tests to verify the new project structure works correctly."""
10
+
11
+ def test_main_imports(self):
12
+ """Test that main fishertools imports work."""
13
+ import fishertools
14
+
15
+ # Test that main API is available
16
+ assert hasattr(fishertools, 'explain_error')
17
+
18
+ # Test that modules are available
19
+ assert hasattr(fishertools, 'errors')
20
+ assert hasattr(fishertools, 'safe')
21
+ assert hasattr(fishertools, 'learn')
22
+ assert hasattr(fishertools, 'legacy')
23
+
24
+ def test_errors_module_imports(self):
25
+ """Test that errors module imports work."""
26
+ from fishertools.errors import ErrorExplainer, explain_error, ErrorPattern
27
+ from fishertools.errors.models import ErrorExplanation, ExplainerConfig
28
+
29
+ # Test that classes can be instantiated
30
+ explainer = ErrorExplainer()
31
+ assert explainer is not None
32
+
33
+ config = ExplainerConfig()
34
+ assert config is not None
35
+
36
+ def test_safe_module_imports(self):
37
+ """Test that safe module imports work."""
38
+ from fishertools.safe import safe_get, safe_divide, safe_read_file
39
+
40
+ # Test that functions are callable
41
+ assert callable(safe_get)
42
+ assert callable(safe_divide)
43
+ assert callable(safe_read_file)
44
+
45
+ def test_learn_module_imports(self):
46
+ """Test that learn module imports work."""
47
+ from fishertools.learn import generate_example, show_best_practice
48
+
49
+ # Test that functions are callable
50
+ assert callable(generate_example)
51
+ assert callable(show_best_practice)
52
+
53
+ def test_legacy_module_imports(self):
54
+ """Test that legacy module imports work."""
55
+ import fishertools.legacy
56
+
57
+ # Module should be importable
58
+ assert fishertools.legacy is not None
@@ -0,0 +1,115 @@
1
+ """
2
+ Test the basic structure of fishertools enhancements.
3
+
4
+ This test verifies that all new modules can be imported correctly
5
+ and that the basic interfaces are properly defined.
6
+ """
7
+
8
+ import pytest
9
+ from hypothesis import given, strategies as st
10
+
11
+
12
+ class TestEnhancementStructure:
13
+ """Test the basic structure of enhancement modules."""
14
+
15
+ def test_learning_module_imports(self):
16
+ """Test that learning module components can be imported."""
17
+ from fishertools.learning import (
18
+ LearningSystem, TutorialEngine, ProgressSystem,
19
+ InteractiveSessionManager
20
+ )
21
+ from fishertools.learning.models import (
22
+ StepExplanation, InteractiveExercise, LearningProgress,
23
+ TutorialSession, ValidationResult, CodeContext
24
+ )
25
+
26
+ # Verify classes can be instantiated (basic structure test)
27
+ assert LearningSystem is not None
28
+ assert TutorialEngine is not None
29
+ assert ProgressSystem is not None
30
+ assert InteractiveSessionManager is not None
31
+
32
+ def test_documentation_module_imports(self):
33
+ """Test that documentation module components can be imported."""
34
+ from fishertools.documentation import (
35
+ DocumentationGenerator, VisualDocumentation, APIGenerator
36
+ )
37
+ from fishertools.documentation.models import (
38
+ APIInfo, FunctionInfo, SphinxDocuments, NavigationTree
39
+ )
40
+
41
+ # Verify classes can be instantiated (basic structure test)
42
+ assert DocumentationGenerator is not None
43
+ assert VisualDocumentation is not None
44
+ assert APIGenerator is not None
45
+
46
+ def test_examples_module_imports(self):
47
+ """Test that examples module components can be imported."""
48
+ from fishertools.examples import ExampleRepository
49
+ from fishertools.examples.models import (
50
+ CodeExample, Scenario, ProjectTemplate, LineByLineExplanation
51
+ )
52
+
53
+ # Verify classes can be instantiated (basic structure test)
54
+ assert ExampleRepository is not None
55
+
56
+ def test_config_module_imports(self):
57
+ """Test that config module components can be imported."""
58
+ from fishertools.config import ConfigurationManager, ConfigurationParser
59
+ from fishertools.config.models import (
60
+ LearningConfig, ValidationResult, RecoveryAction, ConfigError
61
+ )
62
+
63
+ # Verify classes can be instantiated (basic structure test)
64
+ assert ConfigurationManager is not None
65
+ assert ConfigurationParser is not None
66
+
67
+ def test_main_package_imports(self):
68
+ """Test that new modules are accessible from main package."""
69
+ import fishertools
70
+
71
+ # Verify new modules are available
72
+ assert hasattr(fishertools, 'learning')
73
+ assert hasattr(fishertools, 'documentation')
74
+ assert hasattr(fishertools, 'examples')
75
+ assert hasattr(fishertools, 'config')
76
+
77
+ def test_data_models_structure(self):
78
+ """Test that data models have expected attributes."""
79
+ from fishertools.learning.models import StepExplanation, DifficultyLevel
80
+ from fishertools.config.models import LearningConfig
81
+
82
+ # Test enum values
83
+ assert DifficultyLevel.BEGINNER.value == "beginner"
84
+ assert DifficultyLevel.INTERMEDIATE.value == "intermediate"
85
+ assert DifficultyLevel.ADVANCED.value == "advanced"
86
+
87
+ # Test default config creation
88
+ config = LearningConfig()
89
+ assert config.default_level == "beginner"
90
+ assert config.visual_aids_enabled is True
91
+ assert config.progress_tracking_enabled is True
92
+
93
+
94
+ class TestHypothesisConfiguration:
95
+ """Test that Hypothesis is properly configured for property-based testing."""
96
+
97
+ @given(st.text())
98
+ def test_hypothesis_basic_functionality(self, text_input):
99
+ """Basic test to verify Hypothesis is working."""
100
+ # This is a trivial property test to verify Hypothesis setup
101
+ assert isinstance(text_input, str)
102
+
103
+ @given(st.integers(min_value=1, max_value=100))
104
+ def test_hypothesis_integer_generation(self, number):
105
+ """Test integer generation for future property tests."""
106
+ assert 1 <= number <= 100
107
+ assert isinstance(number, int)
108
+
109
+ @given(st.lists(st.text(), min_size=0, max_size=10))
110
+ def test_hypothesis_list_generation(self, text_list):
111
+ """Test list generation for future property tests."""
112
+ assert isinstance(text_list, list)
113
+ assert len(text_list) <= 10
114
+ for item in text_list:
115
+ assert isinstance(item, str)