ara-cli 0.1.9.95__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 +4 -1
- ara_cli/__main__.py +57 -11
- ara_cli/ara_command_action.py +31 -19
- ara_cli/artefact_autofix.py +131 -2
- ara_cli/artefact_creator.py +2 -7
- 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 +12 -13
- ara_cli/commands/extract_command.py +4 -11
- ara_cli/error_handler.py +134 -0
- ara_cli/file_classifier.py +3 -2
- ara_cli/prompt_extractor.py +1 -1
- ara_cli/version.py +1 -1
- {ara_cli-0.1.9.95.dist-info → ara_cli-0.1.9.96.dist-info}/METADATA +1 -1
- {ara_cli-0.1.9.95.dist-info → ara_cli-0.1.9.96.dist-info}/RECORD +26 -25
- tests/test_ara_command_action.py +66 -52
- tests/test_artefact_autofix.py +361 -5
- tests/test_chat.py +88 -6
- tests/test_file_classifier.py +23 -0
- tests/test_file_creator.py +3 -5
- {ara_cli-0.1.9.95.dist-info → ara_cli-0.1.9.96.dist-info}/WHEEL +0 -0
- {ara_cli-0.1.9.95.dist-info → ara_cli-0.1.9.96.dist-info}/entry_points.txt +0 -0
- {ara_cli-0.1.9.95.dist-info → ara_cli-0.1.9.96.dist-info}/top_level.txt +0 -0
ara_cli/artefact_reader.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from . import error_handler
|
|
1
2
|
from ara_cli.classifier import Classifier
|
|
2
3
|
from ara_cli.file_classifier import FileClassifier
|
|
3
4
|
from ara_cli.artefact_models.artefact_model import Artefact
|
|
@@ -12,8 +13,7 @@ class ArtefactReader:
|
|
|
12
13
|
@staticmethod
|
|
13
14
|
def read_artefact_data(artefact_name, classifier, classified_file_info = None) -> tuple[str, dict[str, str]]:
|
|
14
15
|
if not Classifier.is_valid_classifier(classifier):
|
|
15
|
-
|
|
16
|
-
return None, None
|
|
16
|
+
raise ValueError("Invalid classifier provided. Please provide a valid classifier.")
|
|
17
17
|
|
|
18
18
|
if not classified_file_info:
|
|
19
19
|
file_classifier = FileClassifier(os)
|
|
@@ -74,7 +74,6 @@ class ArtefactReader:
|
|
|
74
74
|
|
|
75
75
|
@staticmethod
|
|
76
76
|
def read_artefacts(classified_artefacts=None, file_system=os, tags=None) -> Dict[str, List[Artefact]]:
|
|
77
|
-
from ara_cli.artefact_models.artefact_load import artefact_from_content
|
|
78
77
|
|
|
79
78
|
if classified_artefacts is None:
|
|
80
79
|
file_classifier = FileClassifier(file_system)
|
|
@@ -89,7 +88,7 @@ class ArtefactReader:
|
|
|
89
88
|
artefact = ArtefactReader.read_artefact(title, artefact_type, classified_artefacts)
|
|
90
89
|
artefacts[artefact_type].append(artefact)
|
|
91
90
|
except Exception as e:
|
|
92
|
-
|
|
91
|
+
error_handler.report_error(e, f"reading {artefact_type} '{title}'")
|
|
93
92
|
continue
|
|
94
93
|
return artefacts
|
|
95
94
|
|
|
@@ -143,7 +142,7 @@ class ArtefactReader:
|
|
|
143
142
|
ArtefactReader._ensure_classifier_key(classifier, artefacts_by_classifier)
|
|
144
143
|
|
|
145
144
|
artefact = ArtefactReader._find_artefact_by_name(
|
|
146
|
-
artefact_name,
|
|
145
|
+
artefact_name,
|
|
147
146
|
classified_artefacts.get(classifier, [])
|
|
148
147
|
)
|
|
149
148
|
|
ara_cli/chat.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import argparse
|
|
3
3
|
import cmd2
|
|
4
|
+
from . import error_handler
|
|
4
5
|
from ara_cli.prompt_handler import send_prompt
|
|
5
|
-
from ara_cli.file_loaders.markdown_reader import MarkdownReader
|
|
6
6
|
|
|
7
7
|
from ara_cli.file_loaders.document_file_loader import DocumentFileLoader
|
|
8
8
|
from ara_cli.file_loaders.binary_file_loader import BinaryFileLoader
|
|
@@ -17,12 +17,6 @@ load_parser = argparse.ArgumentParser()
|
|
|
17
17
|
load_parser.add_argument('file_name', nargs='?', default='', help='File to load')
|
|
18
18
|
load_parser.add_argument('--load-images', action='store_true', help='Extract and describe images from documents')
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
from ara_cli.file_loaders.document_file_loader import DocumentFileLoader
|
|
22
|
-
from ara_cli.file_loaders.binary_file_loader import BinaryFileLoader
|
|
23
|
-
from ara_cli.file_loaders.text_file_loader import TextFileLoader
|
|
24
|
-
|
|
25
|
-
|
|
26
20
|
extract_parser = argparse.ArgumentParser()
|
|
27
21
|
extract_parser.add_argument('-f', '--force', action='store_true', help='Force extraction')
|
|
28
22
|
extract_parser.add_argument('-w','--write', action='store_true', help='Overwrite existing files without using LLM for merging.')
|
|
@@ -32,7 +26,6 @@ load_parser.add_argument('file_name', nargs='?', default='', help='File to load'
|
|
|
32
26
|
load_parser.add_argument('--load-images', action='store_true', help='Extract and describe images from documents')
|
|
33
27
|
|
|
34
28
|
|
|
35
|
-
|
|
36
29
|
class Chat(cmd2.Cmd):
|
|
37
30
|
CATEGORY_CHAT_CONTROL = "Chat control commands"
|
|
38
31
|
CATEGORY_LLM_CONTROL = "Language model controls"
|
|
@@ -64,7 +57,7 @@ Start chatting (type 'HELP'/'h' for available commands, 'QUIT'/'q' to exit chat
|
|
|
64
57
|
".jpg": "image/jpeg",
|
|
65
58
|
".jpeg": "image/jpeg",
|
|
66
59
|
}
|
|
67
|
-
|
|
60
|
+
|
|
68
61
|
DOCUMENT_TYPE_EXTENSIONS = [".docx", ".doc", ".odt", ".pdf"]
|
|
69
62
|
|
|
70
63
|
def __init__(
|
|
@@ -507,6 +500,13 @@ Start chatting (type 'HELP'/'h' for available commands, 'QUIT'/'q' to exit chat
|
|
|
507
500
|
self.last_result = True
|
|
508
501
|
return True
|
|
509
502
|
|
|
503
|
+
def onecmd(self, *args, **kwargs):
|
|
504
|
+
try:
|
|
505
|
+
return super().onecmd(*args, **kwargs)
|
|
506
|
+
except Exception as e:
|
|
507
|
+
error_handler.report_error(e)
|
|
508
|
+
return False
|
|
509
|
+
|
|
510
510
|
def onecmd_plus_hooks(self, line, orig_rl_history_length):
|
|
511
511
|
# store the full line for use with default()
|
|
512
512
|
self.full_input = line
|
|
@@ -832,8 +832,7 @@ Start chatting (type 'HELP'/'h' for available commands, 'QUIT'/'q' to exit chat
|
|
|
832
832
|
file_name=self.chat_name,
|
|
833
833
|
force=args.force,
|
|
834
834
|
write=args.write,
|
|
835
|
-
output=self.poutput
|
|
836
|
-
error_output=self.perror
|
|
835
|
+
output=self.poutput
|
|
837
836
|
)
|
|
838
837
|
command.execute()
|
|
839
838
|
|
|
@@ -919,7 +918,7 @@ Start chatting (type 'HELP'/'h' for available commands, 'QUIT'/'q' to exit chat
|
|
|
919
918
|
|
|
920
919
|
artefact = template_artefact_of_type(''.join(template_name))
|
|
921
920
|
if not artefact:
|
|
922
|
-
|
|
921
|
+
raise ValueError(f"No template for '{template_name}' found.")
|
|
923
922
|
write_content = artefact.serialize()
|
|
924
923
|
self.add_prompt_tag_if_needed(self.chat_name)
|
|
925
924
|
with open(self.chat_name, 'a', encoding='utf-8') as chat_file:
|
|
@@ -927,7 +926,7 @@ Start chatting (type 'HELP'/'h' for available commands, 'QUIT'/'q' to exit chat
|
|
|
927
926
|
print(f"Loaded {template_name} artefact template")
|
|
928
927
|
|
|
929
928
|
def complete_LOAD_TEMPLATE(self, text, line, begidx, endidx):
|
|
930
|
-
return self._complete_classifiers(
|
|
929
|
+
return self._complete_classifiers(text, line, begidx, endidx)
|
|
931
930
|
|
|
932
931
|
def _complete_classifiers(self, text, line, begidx, endidx):
|
|
933
932
|
from ara_cli.classifier import Classifier
|
|
@@ -3,20 +3,13 @@ from ara_cli.prompt_extractor import extract_responses
|
|
|
3
3
|
import os
|
|
4
4
|
|
|
5
5
|
class ExtractCommand(Command):
|
|
6
|
-
def __init__(self, file_name, force=False, write=False, output=None
|
|
6
|
+
def __init__(self, file_name, force=False, write=False, output=None):
|
|
7
7
|
self.file_name = file_name
|
|
8
8
|
self.force = force
|
|
9
9
|
self.write = write
|
|
10
10
|
self.output = output # Callable for standard output (optional)
|
|
11
|
-
self.error_output = error_output # Callable for errors (optional)
|
|
12
11
|
|
|
13
12
|
def execute(self, *args, **kwargs):
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
self.output("End of extraction")
|
|
18
|
-
except Exception as e:
|
|
19
|
-
if self.error_output:
|
|
20
|
-
self.error_output(f"Extraction failed: {e}")
|
|
21
|
-
else:
|
|
22
|
-
raise
|
|
13
|
+
extract_responses(self.file_name, True, force=self.force, write=self.write)
|
|
14
|
+
if self.output:
|
|
15
|
+
self.output("End of extraction")
|
ara_cli/error_handler.py
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import traceback
|
|
3
|
+
from typing import Optional
|
|
4
|
+
from enum import Enum
|
|
5
|
+
from functools import wraps
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
RED = '\033[91m'
|
|
9
|
+
RESET = '\033[0m'
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ErrorLevel(Enum):
|
|
13
|
+
INFO = "INFO"
|
|
14
|
+
WARNING = "WARNING"
|
|
15
|
+
ERROR = "ERROR"
|
|
16
|
+
CRITICAL = "CRITICAL"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class AraError(Exception):
|
|
20
|
+
"""Base exception class for ARA CLI errors"""
|
|
21
|
+
|
|
22
|
+
def __init__(
|
|
23
|
+
self, message: str, error_code: int = 1, level: ErrorLevel = ErrorLevel.ERROR
|
|
24
|
+
):
|
|
25
|
+
self.message = message
|
|
26
|
+
self.error_code = error_code
|
|
27
|
+
self.level = level
|
|
28
|
+
super().__init__(self.message)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class AraValidationError(AraError):
|
|
32
|
+
"""Raised when validation fails"""
|
|
33
|
+
|
|
34
|
+
def __init__(self, message: str):
|
|
35
|
+
super().__init__(message, error_code=2, level=ErrorLevel.ERROR)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class AraConfigurationError(AraError):
|
|
39
|
+
"""Raised when configuration is invalid"""
|
|
40
|
+
|
|
41
|
+
def __init__(self, message: str):
|
|
42
|
+
super().__init__(message, error_code=4, level=ErrorLevel.ERROR)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class ErrorHandler:
|
|
46
|
+
"""Centralized error handler for ARA CLI"""
|
|
47
|
+
|
|
48
|
+
def __init__(self, debug_mode: bool = False):
|
|
49
|
+
self.debug_mode = debug_mode
|
|
50
|
+
|
|
51
|
+
def handle_error(self, error: Exception, context: Optional[str] = None) -> None:
|
|
52
|
+
"""Handle any error with standardized output"""
|
|
53
|
+
if isinstance(error, AraError):
|
|
54
|
+
self._handle_ara_error(error, context)
|
|
55
|
+
else:
|
|
56
|
+
self._handle_generic_error(error, context)
|
|
57
|
+
|
|
58
|
+
def _handle_ara_error(self, error: AraError, context: Optional[str] = None) -> None:
|
|
59
|
+
"""Handle ARA-specific errors"""
|
|
60
|
+
self._report_ara_error(error, context)
|
|
61
|
+
|
|
62
|
+
sys.exit(error.error_code)
|
|
63
|
+
|
|
64
|
+
def _handle_generic_error(
|
|
65
|
+
self, error: Exception, context: Optional[str] = None
|
|
66
|
+
) -> None:
|
|
67
|
+
"""Handle generic Python errors"""
|
|
68
|
+
self._report_generic_error(error, context)
|
|
69
|
+
|
|
70
|
+
sys.exit(1)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def report_error(self, error: Exception, context: Optional[str] = None) -> None:
|
|
74
|
+
"""Report error with standardized formatting but don't exit"""
|
|
75
|
+
if isinstance(error, AraError):
|
|
76
|
+
self._report_ara_error(error, context)
|
|
77
|
+
else:
|
|
78
|
+
self._report_generic_error(error, context)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _report_ara_error(self, error: AraError, context: Optional[str] = None) -> None:
|
|
82
|
+
"""Report ARA-specific errors without exiting"""
|
|
83
|
+
error_prefix = f"[{error.level.value}]"
|
|
84
|
+
|
|
85
|
+
if context:
|
|
86
|
+
print(f"{RED}{error_prefix} {context}: {error.message}{RESET}", file=sys.stderr)
|
|
87
|
+
else:
|
|
88
|
+
print(f"{RED}{error_prefix} {error.message}{RESET}", file=sys.stderr)
|
|
89
|
+
|
|
90
|
+
if self.debug_mode:
|
|
91
|
+
traceback.print_exc()
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _report_generic_error(self, error: Exception, context: Optional[str] = None) -> None:
|
|
95
|
+
"""Report generic Python errors without exiting"""
|
|
96
|
+
error_type = type(error).__name__
|
|
97
|
+
|
|
98
|
+
if context:
|
|
99
|
+
print(f"{RED}[ERROR] {context}: {error_type}: {str(error)}{RESET}", file=sys.stderr)
|
|
100
|
+
else:
|
|
101
|
+
print(f"{RED}[ERROR] {error_type}: {str(error)}{RESET}", file=sys.stderr)
|
|
102
|
+
|
|
103
|
+
if self.debug_mode:
|
|
104
|
+
traceback.print_exc()
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def validate_and_exit(
|
|
108
|
+
self, condition: bool, message: str, error_code: int = 1
|
|
109
|
+
) -> None:
|
|
110
|
+
"""Validate condition and exit with error if false"""
|
|
111
|
+
if not condition:
|
|
112
|
+
raise AraValidationError(message)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def handle_errors(_func=None, context: Optional[str] = None, error_handler: Optional[ErrorHandler] = None):
|
|
116
|
+
"""Decorator to handle errors in action functions"""
|
|
117
|
+
|
|
118
|
+
def decorator(func):
|
|
119
|
+
@wraps(func)
|
|
120
|
+
def wrapper(*args, **kwargs):
|
|
121
|
+
nonlocal error_handler
|
|
122
|
+
if error_handler is None:
|
|
123
|
+
error_handler = ErrorHandler()
|
|
124
|
+
|
|
125
|
+
try:
|
|
126
|
+
return func(*args, **kwargs)
|
|
127
|
+
except Exception as e:
|
|
128
|
+
error_handler.handle_error(e, context or func.__name__)
|
|
129
|
+
|
|
130
|
+
return wrapper
|
|
131
|
+
|
|
132
|
+
if callable(_func):
|
|
133
|
+
return decorator(_func)
|
|
134
|
+
return decorator
|
ara_cli/file_classifier.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from . import error_handler
|
|
1
2
|
from ara_cli.classifier import Classifier
|
|
2
3
|
from ara_cli.artefact_models.artefact_model import Artefact
|
|
3
4
|
from ara_cli.artefact_fuzzy_search import find_closest_name_matches
|
|
@@ -33,8 +34,8 @@ class FileClassifier:
|
|
|
33
34
|
if byte > 127:
|
|
34
35
|
return True
|
|
35
36
|
except Exception as e:
|
|
36
|
-
|
|
37
|
-
print(f"Error while checking if file is binary: {e}")
|
|
37
|
+
error_handler.report_error(e, "checking if file is binary")
|
|
38
|
+
# print(f"Error while checking if file is binary: {e}")
|
|
38
39
|
return False
|
|
39
40
|
|
|
40
41
|
def read_file_with_fallback(self, file_path):
|
ara_cli/prompt_extractor.py
CHANGED
|
@@ -17,7 +17,7 @@ def extract_code_blocks_md(markdown_text):
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
def extract_responses(document_path, relative_to_ara_root=False, force=False, write=False):
|
|
20
|
-
print(f"
|
|
20
|
+
print(f"Starting extraction from '{document_path}'")
|
|
21
21
|
block_extraction_counter = 0
|
|
22
22
|
|
|
23
23
|
with open(document_path, 'r', encoding='utf-8', errors='replace') as file:
|
ara_cli/version.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# version.py
|
|
2
|
-
__version__ = "0.1.9.
|
|
2
|
+
__version__ = "0.1.9.96" # fith parameter like .0 for local install test purposes only. official numbers should be 4 digit numbers
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ara_cli
|
|
3
|
-
Version: 0.1.9.
|
|
3
|
+
Version: 0.1.9.96
|
|
4
4
|
Summary: Powerful, open source command-line tool for managing, structuring and automating software development artifacts in line with Business-Driven Development (BDD) and AI-assisted processes
|
|
5
5
|
Description-Content-Type: text/markdown
|
|
6
6
|
Requires-Dist: litellm
|
|
@@ -1,49 +1,50 @@
|
|
|
1
|
-
ara_cli/__init__.py,sha256=
|
|
2
|
-
ara_cli/__main__.py,sha256=
|
|
3
|
-
ara_cli/ara_command_action.py,sha256=
|
|
1
|
+
ara_cli/__init__.py,sha256=Kozfk9i2DfbDi8GTkXjbqIoIxWXmbDhxb_edRv73oUU,495
|
|
2
|
+
ara_cli/__main__.py,sha256=1GaJ2LJPOfAKZVPaKIkJ0x1L2p8yGMAgckzoRn_6JvA,3474
|
|
3
|
+
ara_cli/ara_command_action.py,sha256=iPDiIaN60TEpVCnOT6Esestu0fNJFzbyhNENQytbkEo,22822
|
|
4
4
|
ara_cli/ara_command_parser.py,sha256=A1lMc9Gc0EMJt-380PTcv3aKoxbXGfx5gGax-sZqV3I,21020
|
|
5
5
|
ara_cli/ara_config.py,sha256=VJeage_v-446OtSXIfpazUbetpH7kGNv8Un1lKYx5ZE,9321
|
|
6
|
-
ara_cli/artefact_autofix.py,sha256=
|
|
7
|
-
ara_cli/artefact_creator.py,sha256=
|
|
8
|
-
ara_cli/artefact_deleter.py,sha256=
|
|
9
|
-
ara_cli/artefact_fuzzy_search.py,sha256=
|
|
6
|
+
ara_cli/artefact_autofix.py,sha256=9j_bh0HGnN6HVT9OGKVp85VgDklpx3XpSc9MxBCldU4,25050
|
|
7
|
+
ara_cli/artefact_creator.py,sha256=fRrDaGZvOqJqDb_DLXqMTed2XfIvQMIHjLgOuHOi3Qg,5973
|
|
8
|
+
ara_cli/artefact_deleter.py,sha256=T1vS2s3k_BW86Sd8FExx8nC3BIL05xE9KZLkeZsZrKM,1891
|
|
9
|
+
ara_cli/artefact_fuzzy_search.py,sha256=XMzbMBOJ2YrgFi566jYNB3XeRAmJh7-zqV2QJYbhtlc,3006
|
|
10
10
|
ara_cli/artefact_link_updater.py,sha256=nKdxTpDKqWTOAMD8viKmUaklSFGWzJZ8S8E8xW_ADuM,3775
|
|
11
11
|
ara_cli/artefact_lister.py,sha256=M-ggazAgZ-OLeW9NB48r_sd6zPx0p4hEpeS63qHwI1A,4176
|
|
12
|
-
ara_cli/artefact_reader.py,sha256
|
|
12
|
+
ara_cli/artefact_reader.py,sha256=-6E1VhIlh2oJE1Rn8ARcHRc_E9N4uk8cEViKMoywm6E,7753
|
|
13
13
|
ara_cli/artefact_renamer.py,sha256=8S4QWD19_FGKsKlWojnu_RUOxx0u9rmLugydM4s4VDc,4219
|
|
14
14
|
ara_cli/artefact_scan.py,sha256=msPCm-vPWOAZ_e_z5GylXxq1MtNlmJ4zvKrsdOFCWF4,4813
|
|
15
|
-
ara_cli/chat.py,sha256=
|
|
15
|
+
ara_cli/chat.py,sha256=SCllSt821naybvF6K4afJEtZvFZq7UO52O4fOm0Ieic,39859
|
|
16
16
|
ara_cli/classifier.py,sha256=zWskj7rBYdqYBGjksBm46iTgVU5IIf2PZsJr4qeiwVU,1878
|
|
17
17
|
ara_cli/codefusionretriever.py,sha256=fCHgXdIBRzkVAnapX-KI2NQ44XbrrF4tEQmn5J6clUI,1980
|
|
18
18
|
ara_cli/codehierachieretriever.py,sha256=Xd3EgEWWhkSf1TmTWtf8X5_YvyE_4B66nRrqarwSiTU,1182
|
|
19
19
|
ara_cli/commandline_completer.py,sha256=b00Dqb5n7SecpxYIDLxAfYhp8X6e3c8a5qYz6ko0i3E,1192
|
|
20
20
|
ara_cli/directory_navigator.py,sha256=6QbSAjJrJ5a6Lutol9J4HFgVDMiAQ672ny9TATrh04U,3318
|
|
21
|
-
ara_cli/
|
|
21
|
+
ara_cli/error_handler.py,sha256=nNaJSq82f3xiz_QFRKPg5kX_-oI-UoFdRJ2OTj1AR18,4019
|
|
22
|
+
ara_cli/file_classifier.py,sha256=nUcNrhflUydCyCRbXHjEEXYwwwfUm65lYnNEvc86fpM,4026
|
|
22
23
|
ara_cli/file_lister.py,sha256=0C-j8IzajXo5qlvnuy5WFfe43ALwJ-0JFh2K6Xx2ccw,2332
|
|
23
24
|
ara_cli/filename_validator.py,sha256=Aw9PL8d5-Ymhp3EY6lDrUBk3cudaNqo1Uw5RzPpI1jA,118
|
|
24
25
|
ara_cli/global_file_lister.py,sha256=IIrtFoN5KYyJ3jVPanXZJ4UbYZfSdONRwxkZzvmq6-k,2806
|
|
25
26
|
ara_cli/list_filter.py,sha256=qKGwwQsrWe7L5FbdxEbBYD1bbbi8c-RMypjXqXvLbgs,5291
|
|
26
27
|
ara_cli/output_suppressor.py,sha256=nwiHaQLwabOjMoJOeUESBnZszGMxrQZfJ3N2OvahX7Y,389
|
|
27
28
|
ara_cli/prompt_chat.py,sha256=kd_OINDQFit6jN04bb7mzgY259JBbRaTaNp9F-webkc,1346
|
|
28
|
-
ara_cli/prompt_extractor.py,sha256
|
|
29
|
+
ara_cli/prompt_extractor.py,sha256=WloRgfcEdIVq37BpdWAd2X3EMu0bcNN_Wuws1T2YiUg,8418
|
|
29
30
|
ara_cli/prompt_handler.py,sha256=8a9fcMwE_C6ntbw7UeroNJeU5LxrxEppiUtvYNUTB2U,23292
|
|
30
31
|
ara_cli/prompt_rag.py,sha256=ydlhe4CUqz0jdzlY7jBbpKaf_5fjMrAZKnriKea3ZAg,7485
|
|
31
32
|
ara_cli/run_file_lister.py,sha256=XbrrDTJXp1LFGx9Lv91SNsEHZPP-PyEMBF_P4btjbDA,2360
|
|
32
33
|
ara_cli/tag_extractor.py,sha256=k2yRl7dAMZ4YTARzUke4wgY0oEIOmWkOHGet7nXB6uw,3317
|
|
33
34
|
ara_cli/template_manager.py,sha256=l2c785YHB7m0e2TjE0CX-nwXrS4v3EiT9qrS5KuatAc,7105
|
|
34
35
|
ara_cli/update_config_prompt.py,sha256=moqj2Kha7S7fEGzTReU0v2y8UjXC8QfnoiieOQr35C4,5157
|
|
35
|
-
ara_cli/version.py,sha256
|
|
36
|
+
ara_cli/version.py,sha256=-IPlzWGTvEOC2B1-l8hULGEXt1iWj3_npgirLamZr10,146
|
|
36
37
|
ara_cli/artefact_models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
37
38
|
ara_cli/artefact_models/artefact_data_retrieval.py,sha256=CooXOJBYWSyiViN2xkC8baS8OUaslry3YGVVUeDxRAU,527
|
|
38
39
|
ara_cli/artefact_models/artefact_load.py,sha256=IXzWxP-Q_j_oDGMno0m-OuXCQ7Vd5c_NctshGr4ROBw,621
|
|
39
40
|
ara_cli/artefact_models/artefact_mapping.py,sha256=8aD0spBjkJ8toMAmFawc6UTUxB6-tEEViZXv2I-r88Q,1874
|
|
40
41
|
ara_cli/artefact_models/artefact_model.py,sha256=qSbcrmFWAYgBqcNl9QARI1_uLQJm-TPVgP5q2AEFnjE,15983
|
|
41
|
-
ara_cli/artefact_models/artefact_templates.py,sha256=
|
|
42
|
+
ara_cli/artefact_models/artefact_templates.py,sha256=CFa_vIA-cnbZEHuACd24vNJB_7LueQi-8x7ga_AyLKI,9830
|
|
42
43
|
ara_cli/artefact_models/businessgoal_artefact_model.py,sha256=GYT5S2xEnQHwv-k-lEeX5NMSqA-UEfV3PhNjgPDUJpw,4698
|
|
43
44
|
ara_cli/artefact_models/capability_artefact_model.py,sha256=SZqHx4O2mj4urn77Stnj4_Jxtlq3-LgBBU9SMkByppI,3079
|
|
44
45
|
ara_cli/artefact_models/epic_artefact_model.py,sha256=h9pC00ZxCL-t_NMjwTCeOnIJZPa9hhB-R05wr110LXs,5619
|
|
45
46
|
ara_cli/artefact_models/example_artefact_model.py,sha256=UXrKbaPotg1jwcrVSdCeo-XH4tTD_-U1e3giaBn5_xg,1384
|
|
46
|
-
ara_cli/artefact_models/feature_artefact_model.py,sha256=
|
|
47
|
+
ara_cli/artefact_models/feature_artefact_model.py,sha256=iUCrdgH_VhRCBVyCQARpl9cWzavC310lKZHWLofsq9s,20256
|
|
47
48
|
ara_cli/artefact_models/issue_artefact_model.py,sha256=v6CpKnkqiUh6Wch2kkEmyyW49c8ysdy1qz8l1Ft9uJA,2552
|
|
48
49
|
ara_cli/artefact_models/keyfeature_artefact_model.py,sha256=J9oXLsCAo22AW31D5Z104y02ss0S0O4tPCcd09zYCD0,4066
|
|
49
50
|
ara_cli/artefact_models/serialize_helper.py,sha256=Wks30wy-UrwJURetydKykLgJkdGRgXFHkDT24vHe5tU,595
|
|
@@ -52,7 +53,7 @@ ara_cli/artefact_models/userstory_artefact_model.py,sha256=2awH31ROtm7j4T44Bv4cy
|
|
|
52
53
|
ara_cli/artefact_models/vision_artefact_model.py,sha256=frjaUJj-mmIlVHEhzAQztCGs-CtvNu_odSborgztfzo,5251
|
|
53
54
|
ara_cli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
54
55
|
ara_cli/commands/command.py,sha256=Y_2dNeuxRjbyI3ScXNv55lptSe8Hs_ya78L0nPYNZHA,154
|
|
55
|
-
ara_cli/commands/extract_command.py,sha256=
|
|
56
|
+
ara_cli/commands/extract_command.py,sha256=CzUOwDembG587PYbxg5rge4XSfdsuTyOPUvkobkXCIs,573
|
|
56
57
|
ara_cli/commands/load_command.py,sha256=H3CfeHIL-criDU5oi4BONTSpyzJ4m8DzJ0ZCIiAZFeI,2204
|
|
57
58
|
ara_cli/commands/load_image_command.py,sha256=g9-PXAYdqx5Ed1PdVo-FIb4CyJGEpRFbgQf9Dxg6DmM,886
|
|
58
59
|
ara_cli/commands/read_command.py,sha256=bo1BvRWuNKdFqBNN1EWORNrX_yuFAOyBruDUolHq1Vc,3791
|
|
@@ -140,20 +141,20 @@ ara_cli/templates/specification_breakdown_files/template.step.md,sha256=nzDRl9Xo
|
|
|
140
141
|
ara_cli/templates/specification_breakdown_files/template.technology.exploration.md,sha256=zQyiJcmbUfXdte-5uZwZUpT6ey0zwfZ00P4VwI97jQk,2274
|
|
141
142
|
ara_cli/templates/specification_breakdown_files/template.technology.md,sha256=bySiksz-8xtq0Nnj4svqe2MgUftWrVkbK9AcrDUE3KY,952
|
|
142
143
|
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
143
|
-
tests/test_ara_command_action.py,sha256=
|
|
144
|
+
tests/test_ara_command_action.py,sha256=gLXFAW6K0qCkNKvWvmbshfpJqczvdgBoNGT4rugF7JI,27181
|
|
144
145
|
tests/test_ara_config.py,sha256=RbVhS0SS1lr_SVopEMT1Fake5a-4rWN8MprgJtgI-FA,15883
|
|
145
|
-
tests/test_artefact_autofix.py,sha256=
|
|
146
|
+
tests/test_artefact_autofix.py,sha256=vcN11CY6XJq97N0php4OW-rPbEMEh_nYFISrg-pN1mE,38332
|
|
146
147
|
tests/test_artefact_fuzzy_search.py,sha256=5Sh3_l9QK8-WHn6JpGPU1b6h4QEnl2JoMq1Tdp2cj1U,1261
|
|
147
148
|
tests/test_artefact_link_updater.py,sha256=biqbEp2jCOz8giv72hu2P2hDfeJfJ9OrVGdAv5d9cK4,2191
|
|
148
149
|
tests/test_artefact_lister.py,sha256=35R13UU-YsX1HOsEN8M2-vIiCUA9RSBm6SwestDaFhE,20388
|
|
149
150
|
tests/test_artefact_reader.py,sha256=660K-d8ed-j8hulsUB_7baPD2-hhbg9TffUR5yVc4Uo,927
|
|
150
151
|
tests/test_artefact_renamer.py,sha256=lSnKCCfoFGgKhTdDZrEaeBq1xJAak1QoqH5aSeOe9Ro,3494
|
|
151
152
|
tests/test_artefact_scan.py,sha256=uNWgrt7ieZ4ogKACsPqzAsh59JF2BhTKSag31hpVrTQ,16887
|
|
152
|
-
tests/test_chat.py,sha256=
|
|
153
|
+
tests/test_chat.py,sha256=UK1566DikkeXKzslw8h1it3UXqJEGLpxy02_Pch0Tfs,59433
|
|
153
154
|
tests/test_classifier.py,sha256=grYGPksydNdPsaEBQxYHZTuTdcJWz7VQtikCKA6BNaQ,1920
|
|
154
155
|
tests/test_directory_navigator.py,sha256=7G0MVrBbtBvbrFUpL0zb_9EkEWi1dulWuHsrQxMJxDY,140
|
|
155
|
-
tests/test_file_classifier.py,sha256=
|
|
156
|
-
tests/test_file_creator.py,sha256=
|
|
156
|
+
tests/test_file_classifier.py,sha256=4O1C_iDpGGm35b7aI-HIJd5kkWxFUOrI2n4lEpiDNTM,11855
|
|
157
|
+
tests/test_file_creator.py,sha256=tgBCq6KPv-qMSDhj9AZvQIJABiAqgpFRnEg1fqbVrTI,2013
|
|
157
158
|
tests/test_file_lister.py,sha256=Q9HwhKKx540EPzTmfzOCnvtAgON0aMmpJE2eOe1J3EA,4324
|
|
158
159
|
tests/test_global_file_lister.py,sha256=ycvf2YL8q5QSEMwcnQfUdoWnQQ8xTSyEtccAeXwl6QU,5487
|
|
159
160
|
tests/test_list_filter.py,sha256=fJA3d_SdaOAUkE7jn68MOVS0THXGghy1fye_64Zvo1U,7964
|
|
@@ -161,8 +162,8 @@ tests/test_prompt_handler.py,sha256=kW8FU09ho4I5qC-f4G9r4ZgI-NlqdOkTmAazG7FaTrw,
|
|
|
161
162
|
tests/test_tag_extractor.py,sha256=nSiAYlTKZ7TLAOtcJpwK5zTWHhFYU0tI5xKnivLc1dU,2712
|
|
162
163
|
tests/test_template_manager.py,sha256=qliEeYgAEakn8JIqIHa8u0Ht6DY4L3T6DcHBXkjzR4I,4167
|
|
163
164
|
tests/test_update_config_prompt.py,sha256=xsqj1WTn4BsG5Q2t-sNPfu7EoMURFcS-hfb5VSXUnJc,6765
|
|
164
|
-
ara_cli-0.1.9.
|
|
165
|
-
ara_cli-0.1.9.
|
|
166
|
-
ara_cli-0.1.9.
|
|
167
|
-
ara_cli-0.1.9.
|
|
168
|
-
ara_cli-0.1.9.
|
|
165
|
+
ara_cli-0.1.9.96.dist-info/METADATA,sha256=rwUSTke0fhW8QCSyel4M0oASJkfy6AASVOkQMzdPBDo,6789
|
|
166
|
+
ara_cli-0.1.9.96.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
167
|
+
ara_cli-0.1.9.96.dist-info/entry_points.txt,sha256=v4h7MzysTgSIDYfEo3oj4Kz_8lzsRa3hq-KJHEcLVX8,45
|
|
168
|
+
ara_cli-0.1.9.96.dist-info/top_level.txt,sha256=WM4cLHT5DYUaWzLtRj-gu3yVNFpGQ6lLRI3FMmC-38I,14
|
|
169
|
+
ara_cli-0.1.9.96.dist-info/RECORD,,
|
tests/test_ara_command_action.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import pytest
|
|
2
2
|
from unittest.mock import patch, MagicMock, call, mock_open
|
|
3
|
+
from ara_cli.error_handler import AraValidationError
|
|
3
4
|
from ara_cli.ara_command_action import (
|
|
4
5
|
check_validity,
|
|
5
6
|
create_action,
|
|
@@ -16,6 +17,12 @@ from ara_cli.ara_command_action import (
|
|
|
16
17
|
)
|
|
17
18
|
|
|
18
19
|
|
|
20
|
+
@pytest.fixture
|
|
21
|
+
def mock_handle_errors():
|
|
22
|
+
with patch("ara_cli.ara_command_action.handle_errors", lambda context: (lambda f: f)):
|
|
23
|
+
yield
|
|
24
|
+
|
|
25
|
+
|
|
19
26
|
@pytest.fixture
|
|
20
27
|
def mock_dependencies():
|
|
21
28
|
with patch(
|
|
@@ -28,8 +35,10 @@ def mock_dependencies():
|
|
|
28
35
|
"ara_cli.template_manager.SpecificationBreakdownAspects"
|
|
29
36
|
) as MockSpecificationBreakdownAspects, patch(
|
|
30
37
|
"ara_cli.artefact_fuzzy_search.find_closest_rule"
|
|
31
|
-
) as mock_find_closest_rule
|
|
32
|
-
|
|
38
|
+
) as mock_find_closest_rule, patch(
|
|
39
|
+
"ara_cli.artefact_reader.ArtefactReader"
|
|
40
|
+
) as MockArtefactReader:
|
|
41
|
+
yield MockArtefactCreator, MockClassifier, mock_is_valid_filename, MockSpecificationBreakdownAspects, mock_find_closest_rule, MockArtefactReader
|
|
33
42
|
|
|
34
43
|
|
|
35
44
|
@pytest.fixture
|
|
@@ -102,65 +111,70 @@ def mock_suggest_close_name_matches():
|
|
|
102
111
|
yield mock_suggest_close_name_matches
|
|
103
112
|
|
|
104
113
|
|
|
105
|
-
|
|
106
|
-
"condition
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
)
|
|
110
|
-
def test_check_validity(condition, error_message):
|
|
111
|
-
with patch("sys.exit") as mock_exit, patch("builtins.print") as mock_print:
|
|
112
|
-
if condition:
|
|
113
|
-
check_validity(condition, error_message)
|
|
114
|
-
mock_exit.assert_not_called()
|
|
115
|
-
mock_print.assert_not_called()
|
|
116
|
-
else:
|
|
117
|
-
check_validity(condition, error_message)
|
|
118
|
-
mock_exit.assert_called_once_with(1)
|
|
119
|
-
mock_print.assert_called_once_with(error_message)
|
|
114
|
+
def test_check_validity_with_true_condition():
|
|
115
|
+
"""Test that check_validity does nothing when condition is True."""
|
|
116
|
+
# This should not raise any exception
|
|
117
|
+
check_validity(True, "This should not be printed")
|
|
120
118
|
|
|
121
119
|
|
|
122
|
-
|
|
123
|
-
"
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
120
|
+
def test_check_validity_with_false_condition():
|
|
121
|
+
"""Test that check_validity raises AraValidationError when condition is False."""
|
|
122
|
+
error_message = "This is a test error message"
|
|
123
|
+
|
|
124
|
+
with pytest.raises(AraValidationError, match=error_message):
|
|
125
|
+
check_validity(False, error_message)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def test_check_validity_error_message_content():
|
|
129
|
+
"""Test that the raised exception contains the correct error message."""
|
|
130
|
+
error_message = "Custom validation error"
|
|
131
|
+
|
|
132
|
+
with pytest.raises(AraValidationError) as exc_info:
|
|
133
|
+
check_validity(False, error_message)
|
|
134
|
+
|
|
135
|
+
assert str(exc_info.value) == error_message
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def setup_create_args_and_mocks(classifier_valid, filename_valid, mock_dependencies):
|
|
139
|
+
(MockArtefactCreator, MockClassifier, mock_is_valid_filename, _, _, MockArtefactReader) = mock_dependencies
|
|
136
140
|
MockClassifier.is_valid_classifier.return_value = classifier_valid
|
|
137
141
|
mock_is_valid_filename.return_value = filename_valid
|
|
138
|
-
|
|
142
|
+
MockArtefactReader.read_artefact.return_value = (None, None)
|
|
139
143
|
|
|
140
144
|
args = MagicMock()
|
|
141
145
|
args.classifier = "test_classifier"
|
|
142
146
|
args.parameter = "test_parameter"
|
|
147
|
+
return args
|
|
143
148
|
|
|
149
|
+
# Test for valid classifier and filename
|
|
150
|
+
def test_create_action_with_valid_params(mock_handle_errors, mock_dependencies):
|
|
151
|
+
args = setup_create_args_and_mocks(True, True, mock_dependencies)
|
|
144
152
|
with patch("ara_cli.ara_command_action.check_validity") as mock_check_validity:
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
153
|
+
create_action(args)
|
|
154
|
+
mock_check_validity.assert_any_call(True, "Invalid classifier provided. Please provide a valid classifier.")
|
|
155
|
+
mock_check_validity.assert_any_call(True, "Invalid filename provided. Please provide a valid filename.")
|
|
156
|
+
|
|
157
|
+
# Test for invalid classifier
|
|
158
|
+
def test_create_action_with_invalid_classifier(mock_handle_errors, mock_dependencies):
|
|
159
|
+
args = setup_create_args_and_mocks(False, True, mock_dependencies)
|
|
160
|
+
with patch("ara_cli.ara_command_action.check_validity") as mock_check_validity:
|
|
161
|
+
create_action(args)
|
|
162
|
+
mock_check_validity.assert_any_call(False, "Invalid classifier provided. Please provide a valid classifier.")
|
|
163
|
+
|
|
164
|
+
# Test for invalid filename
|
|
165
|
+
def test_create_action_with_invalid_filename(mock_handle_errors, mock_dependencies):
|
|
166
|
+
args = setup_create_args_and_mocks(True, False, mock_dependencies)
|
|
167
|
+
with patch("ara_cli.ara_command_action.check_validity") as mock_check_validity:
|
|
168
|
+
create_action(args)
|
|
169
|
+
mock_check_validity.assert_any_call(False, "Invalid filename provided. Please provide a valid filename.")
|
|
170
|
+
|
|
171
|
+
# Test for both invalid classifier and filename
|
|
172
|
+
def test_create_action_with_invalid_classifier_and_filename(mock_handle_errors, mock_dependencies):
|
|
173
|
+
args = setup_create_args_and_mocks(False, False, mock_dependencies)
|
|
174
|
+
with patch("ara_cli.ara_command_action.check_validity") as mock_check_validity:
|
|
175
|
+
create_action(args)
|
|
176
|
+
mock_check_validity.assert_any_call(False, "Invalid classifier provided. Please provide a valid classifier.")
|
|
177
|
+
mock_check_validity.assert_any_call(False, "Invalid filename provided. Please provide a valid filename.")
|
|
164
178
|
|
|
165
179
|
|
|
166
180
|
@pytest.mark.parametrize(
|
|
@@ -406,7 +420,7 @@ def test_read_status_action(classifier, artefact_name, artefact_exists, status,
|
|
|
406
420
|
# Verify behavior
|
|
407
421
|
if not artefact_exists:
|
|
408
422
|
# Should suggest close matches when artefact not found
|
|
409
|
-
mock_suggest_close_name_matches.assert_called_once_with(artefact_name, all_artefact_names)
|
|
423
|
+
mock_suggest_close_name_matches.assert_called_once_with(artefact_name, all_artefact_names, report_as_error=True)
|
|
410
424
|
mock_open.assert_not_called()
|
|
411
425
|
else:
|
|
412
426
|
# Should open the file and read content
|