ara-cli 0.1.9.94__py3-none-any.whl → 0.1.9.96__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.
- ara_cli/__init__.py +18 -1
- ara_cli/__main__.py +57 -11
- ara_cli/ara_command_action.py +31 -19
- ara_cli/ara_config.py +17 -2
- ara_cli/artefact_autofix.py +171 -23
- ara_cli/artefact_creator.py +5 -8
- ara_cli/artefact_deleter.py +2 -4
- ara_cli/artefact_fuzzy_search.py +13 -6
- ara_cli/artefact_models/artefact_templates.py +3 -3
- ara_cli/artefact_models/feature_artefact_model.py +25 -0
- ara_cli/artefact_reader.py +4 -5
- ara_cli/chat.py +79 -37
- ara_cli/commands/extract_command.py +4 -11
- ara_cli/error_handler.py +134 -0
- ara_cli/file_classifier.py +3 -2
- ara_cli/file_loaders/document_readers.py +233 -0
- ara_cli/file_loaders/file_loaders.py +123 -0
- ara_cli/file_loaders/image_processor.py +89 -0
- ara_cli/file_loaders/markdown_reader.py +75 -0
- ara_cli/file_loaders/text_file_loader.py +9 -11
- ara_cli/global_file_lister.py +61 -0
- ara_cli/prompt_extractor.py +1 -1
- ara_cli/prompt_handler.py +24 -4
- ara_cli/template_manager.py +14 -4
- ara_cli/update_config_prompt.py +7 -1
- ara_cli/version.py +1 -1
- {ara_cli-0.1.9.94.dist-info → ara_cli-0.1.9.96.dist-info}/METADATA +2 -1
- {ara_cli-0.1.9.94.dist-info → ara_cli-0.1.9.96.dist-info}/RECORD +40 -33
- tests/test_ara_command_action.py +66 -52
- tests/test_ara_config.py +28 -0
- tests/test_artefact_autofix.py +361 -5
- tests/test_chat.py +105 -36
- tests/test_file_classifier.py +23 -0
- tests/test_file_creator.py +3 -5
- tests/test_global_file_lister.py +131 -0
- tests/test_prompt_handler.py +26 -1
- tests/test_template_manager.py +5 -4
- {ara_cli-0.1.9.94.dist-info → ara_cli-0.1.9.96.dist-info}/WHEEL +0 -0
- {ara_cli-0.1.9.94.dist-info → ara_cli-0.1.9.96.dist-info}/entry_points.txt +0 -0
- {ara_cli-0.1.9.94.dist-info → ara_cli-0.1.9.96.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# tests/test_global_file_lister.py
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import pytest
|
|
5
|
+
from unittest.mock import patch
|
|
6
|
+
from io import StringIO
|
|
7
|
+
from ara_cli.global_file_lister import (
|
|
8
|
+
_build_tree,
|
|
9
|
+
_write_tree_to_markdown,
|
|
10
|
+
generate_global_markdown_listing,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
@pytest.fixture
|
|
14
|
+
def temp_dir_structure(tmp_path):
|
|
15
|
+
"""Create a temporary directory structure for comprehensive testing."""
|
|
16
|
+
root = tmp_path / "global_root"
|
|
17
|
+
root.mkdir()
|
|
18
|
+
(root / "src").mkdir()
|
|
19
|
+
(root / "src" / "main.py").touch()
|
|
20
|
+
(root / "src" / "utils.py").touch()
|
|
21
|
+
(root / "docs").mkdir()
|
|
22
|
+
(root / "docs" / "guide.md").touch()
|
|
23
|
+
(root / "docs" / "images").mkdir() # Empty dir, should be ignored
|
|
24
|
+
(root / "tests").mkdir()
|
|
25
|
+
(root / "tests" / "test_main.py").touch()
|
|
26
|
+
(root / "config.txt").touch() # Should be ignored by patterns
|
|
27
|
+
(root / "empty_dir").mkdir() # Should be ignored
|
|
28
|
+
return str(root)
|
|
29
|
+
|
|
30
|
+
class TestBuildTree:
|
|
31
|
+
"""Tests for the _build_tree function."""
|
|
32
|
+
def test_build_tree_with_matching_files(self, temp_dir_structure):
|
|
33
|
+
"""Tests building a tree, correctly filtering by patterns and excluding empty dirs."""
|
|
34
|
+
patterns = ["*.py", "*.md"]
|
|
35
|
+
tree = _build_tree(temp_dir_structure, patterns)
|
|
36
|
+
|
|
37
|
+
assert sorted(tree["dirs"]["src"]["files"]) == ["main.py", "utils.py"]
|
|
38
|
+
assert tree["dirs"]["docs"]["files"] == ["guide.md"]
|
|
39
|
+
assert tree["dirs"]["tests"]["files"] == ["test_main.py"]
|
|
40
|
+
assert "images" not in tree["dirs"]["docs"]["dirs"] # Empty dir excluded
|
|
41
|
+
assert "empty_dir" not in tree["dirs"] # Empty dir excluded
|
|
42
|
+
assert not tree["files"] # No files in root
|
|
43
|
+
|
|
44
|
+
def test_build_tree_no_matching_files(self, temp_dir_structure):
|
|
45
|
+
"""Tests building a tree where no files match the given patterns."""
|
|
46
|
+
patterns = ["*.json", "*.yml"]
|
|
47
|
+
tree = _build_tree(temp_dir_structure, patterns)
|
|
48
|
+
assert not tree["files"] and not tree["dirs"]
|
|
49
|
+
|
|
50
|
+
def test_build_tree_on_empty_directory(self, tmp_path):
|
|
51
|
+
"""Tests that an empty directory results in an empty tree."""
|
|
52
|
+
empty_dir = tmp_path / "empty"
|
|
53
|
+
empty_dir.mkdir()
|
|
54
|
+
tree = _build_tree(str(empty_dir), ["*.*"])
|
|
55
|
+
assert not tree["files"] and not tree["dirs"]
|
|
56
|
+
|
|
57
|
+
@patch('os.listdir')
|
|
58
|
+
@patch('sys.stdout', new_callable=StringIO)
|
|
59
|
+
def test_build_tree_handles_os_error(self, mock_stdout, mock_listdir):
|
|
60
|
+
"""Tests that an OSError during directory listing is caught and handled."""
|
|
61
|
+
mock_listdir.side_effect = OSError("Permission denied")
|
|
62
|
+
tree = _build_tree("/unreadable_dir", ["*.*"])
|
|
63
|
+
assert "Warning: Could not access path /unreadable_dir" in mock_stdout.getvalue()
|
|
64
|
+
assert not tree["files"] and not tree["dirs"]
|
|
65
|
+
|
|
66
|
+
class TestWriteTreeToMarkdown:
|
|
67
|
+
"""Tests for the _write_tree_to_markdown function."""
|
|
68
|
+
def test_write_tree_to_markdown_output_format(self):
|
|
69
|
+
"""Verifies that the markdown output is correctly formatted with proper indentation."""
|
|
70
|
+
tree = {
|
|
71
|
+
'files': ['root_file.md'],
|
|
72
|
+
'dirs': {
|
|
73
|
+
'dir1': {'files': ['a.py', 'b.py'], 'dirs': {}},
|
|
74
|
+
'dir2': {'files': [], 'dirs': {'subdir': {'files': ['c.md'], 'dirs': {}}}}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
md_file = StringIO()
|
|
79
|
+
_write_tree_to_markdown(md_file, tree, level=1)
|
|
80
|
+
output = md_file.getvalue()
|
|
81
|
+
|
|
82
|
+
# FIX: Added 4 spaces before "### subdir\n" to match the actual output.
|
|
83
|
+
expected = (
|
|
84
|
+
" - [] root_file.md\n"
|
|
85
|
+
"## dir1\n"
|
|
86
|
+
" - [] a.py\n"
|
|
87
|
+
" - [] b.py\n"
|
|
88
|
+
"## dir2\n"
|
|
89
|
+
" ### subdir\n"
|
|
90
|
+
" - [] c.md\n"
|
|
91
|
+
)
|
|
92
|
+
assert output == expected
|
|
93
|
+
|
|
94
|
+
class TestGenerateGlobalMarkdownListing:
|
|
95
|
+
"""Tests for the main generate_global_markdown_listing function."""
|
|
96
|
+
def test_generate_listing_with_valid_dirs(self, temp_dir_structure, tmp_path):
|
|
97
|
+
"""Tests the end-to-end generation of a markdown file from a valid directory."""
|
|
98
|
+
output_file = tmp_path / "output.md"
|
|
99
|
+
patterns = ["*.py"]
|
|
100
|
+
|
|
101
|
+
generate_global_markdown_listing([temp_dir_structure], patterns, str(output_file))
|
|
102
|
+
|
|
103
|
+
content = output_file.read_text()
|
|
104
|
+
abs_dir = os.path.abspath(temp_dir_structure)
|
|
105
|
+
|
|
106
|
+
assert f"# {abs_dir}\n" in content
|
|
107
|
+
assert "## src\n" in content
|
|
108
|
+
assert " - [] main.py\n" in content
|
|
109
|
+
assert "## tests\n" in content
|
|
110
|
+
assert "guide.md" not in content # Does not match pattern
|
|
111
|
+
|
|
112
|
+
def test_generate_listing_with_nonexistent_dir(self, tmp_path):
|
|
113
|
+
"""Tests that a warning is written to the file for a non-existent directory."""
|
|
114
|
+
output_file = tmp_path / "output.md"
|
|
115
|
+
non_existent_dir = "/path/to/nothing"
|
|
116
|
+
|
|
117
|
+
generate_global_markdown_listing([non_existent_dir], ["*.*"], str(output_file))
|
|
118
|
+
|
|
119
|
+
content = output_file.read_text()
|
|
120
|
+
abs_path = os.path.abspath(non_existent_dir)
|
|
121
|
+
|
|
122
|
+
assert f"# {non_existent_dir}\n" in content
|
|
123
|
+
assert f" - !! UYARI: Dizin bulunamadı: {abs_path}" in content
|
|
124
|
+
|
|
125
|
+
def test_generate_listing_with_no_matching_files(self, temp_dir_structure, tmp_path):
|
|
126
|
+
"""Tests that the output file is empty if no files match the patterns."""
|
|
127
|
+
output_file = tmp_path / "output.md"
|
|
128
|
+
|
|
129
|
+
generate_global_markdown_listing([temp_dir_structure], ["*.nonexistent"], str(output_file))
|
|
130
|
+
|
|
131
|
+
assert output_file.read_text() == ""
|
tests/test_prompt_handler.py
CHANGED
|
@@ -674,4 +674,29 @@ class TestArtefactAndTemplateHandling:
|
|
|
674
674
|
mock_send.assert_called_once_with(final_message_list)
|
|
675
675
|
|
|
676
676
|
log_file = self.root / "ara" / self.mock_classifier / f"{self.mock_param}.data" / f"{self.mock_classifier}.prompt_log.md"
|
|
677
|
-
assert "llm response" in log_file.read_text()
|
|
677
|
+
assert "llm response" in log_file.read_text()
|
|
678
|
+
|
|
679
|
+
@patch('ara_cli.global_file_lister.generate_global_markdown_listing')
|
|
680
|
+
def test_generate_config_prompt_global_givens_file(self, mock_global_lister, mock_config_manager, mock_config):
|
|
681
|
+
"""Tests that the global givens file is generated correctly when global_dirs are present."""
|
|
682
|
+
prompt_data_path = self.root / "prompt/data"
|
|
683
|
+
prompt_data_path.mkdir(parents=True)
|
|
684
|
+
|
|
685
|
+
# Scenario 1: No global_dirs are configured, should return early and do nothing.
|
|
686
|
+
mock_config.global_dirs = []
|
|
687
|
+
prompt_handler.generate_config_prompt_global_givens_file(str(prompt_data_path), "global.md")
|
|
688
|
+
mock_global_lister.assert_not_called()
|
|
689
|
+
|
|
690
|
+
# Scenario 2: With global_dirs, should call the global lister with correct arguments.
|
|
691
|
+
mock_config.global_dirs = [{"source_dir": "/global/src1"}, {"path": "/global/src2"}]
|
|
692
|
+
mock_config.ara_prompt_given_list_includes = ["*.py", "*.md"]
|
|
693
|
+
|
|
694
|
+
# Use patch to suppress print output during the test
|
|
695
|
+
with patch('builtins.print'):
|
|
696
|
+
prompt_handler.generate_config_prompt_global_givens_file(str(prompt_data_path), "global.md")
|
|
697
|
+
|
|
698
|
+
mock_global_lister.assert_called_once()
|
|
699
|
+
args, _ = mock_global_lister.call_args
|
|
700
|
+
assert args[0] == ["/global/src1", "/global/src2"]
|
|
701
|
+
assert args[1] == ["*.py", "*.md"]
|
|
702
|
+
assert args[2] == os.path.join(prompt_data_path, "global.md")
|
tests/test_template_manager.py
CHANGED
|
@@ -9,10 +9,11 @@ import os
|
|
|
9
9
|
|
|
10
10
|
@pytest.fixture(autouse=True)
|
|
11
11
|
def navigate_to_ara_directory():
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
with patch('builtins.input', return_value='y'):
|
|
13
|
+
navigator = DirectoryNavigator("ara")
|
|
14
|
+
original_directory = navigator.navigate_to_target()
|
|
15
|
+
yield
|
|
16
|
+
os.chdir(original_directory)
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
@pytest.mark.parametrize(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|