ara-cli 0.1.9.93__py3-none-any.whl → 0.1.9.95__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.
Potentially problematic release.
This version of ara-cli might be problematic. Click here for more details.
- ara_cli/__init__.py +15 -1
- ara_cli/ara_command_action.py +23 -43
- ara_cli/ara_command_parser.py +16 -1
- ara_cli/ara_config.py +17 -2
- ara_cli/artefact_autofix.py +40 -21
- ara_cli/artefact_creator.py +3 -1
- ara_cli/artefact_lister.py +29 -55
- ara_cli/artefact_models/artefact_data_retrieval.py +23 -0
- ara_cli/artefact_renamer.py +6 -2
- ara_cli/chat.py +80 -34
- ara_cli/commands/extract_command.py +4 -3
- ara_cli/commands/read_command.py +104 -0
- 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 +21 -6
- ara_cli/prompt_handler.py +24 -4
- ara_cli/tag_extractor.py +21 -11
- 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.93.dist-info → ara_cli-0.1.9.95.dist-info}/METADATA +18 -17
- {ara_cli-0.1.9.93.dist-info → ara_cli-0.1.9.95.dist-info}/RECORD +35 -27
- tests/test_ara_config.py +28 -0
- tests/test_artefact_lister.py +52 -132
- tests/test_chat.py +28 -40
- 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.93.dist-info → ara_cli-0.1.9.95.dist-info}/WHEEL +0 -0
- {ara_cli-0.1.9.93.dist-info → ara_cli-0.1.9.95.dist-info}/entry_points.txt +0 -0
- {ara_cli-0.1.9.93.dist-info → ara_cli-0.1.9.95.dist-info}/top_level.txt +0 -0
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
ara_cli/__init__.py,sha256=
|
|
1
|
+
ara_cli/__init__.py,sha256=CzGZUcf4WQP051xeNziNKQj8oNr-n_lZCW5_cR_WNVw,455
|
|
2
2
|
ara_cli/__main__.py,sha256=J5DCDLRZ6UcpYwM1-NkjaLo4PTetcSj2dB4HrrftkUw,2064
|
|
3
|
-
ara_cli/ara_command_action.py,sha256=
|
|
4
|
-
ara_cli/ara_command_parser.py,sha256=
|
|
5
|
-
ara_cli/ara_config.py,sha256=
|
|
6
|
-
ara_cli/artefact_autofix.py,sha256=
|
|
7
|
-
ara_cli/artefact_creator.py,sha256=
|
|
3
|
+
ara_cli/ara_command_action.py,sha256=uyMN05ZYffWqN9nwL53MmQ_yHpuxHVqZ_scAMEoD1jw,21516
|
|
4
|
+
ara_cli/ara_command_parser.py,sha256=A1lMc9Gc0EMJt-380PTcv3aKoxbXGfx5gGax-sZqV3I,21020
|
|
5
|
+
ara_cli/ara_config.py,sha256=VJeage_v-446OtSXIfpazUbetpH7kGNv8Un1lKYx5ZE,9321
|
|
6
|
+
ara_cli/artefact_autofix.py,sha256=w6erUYrpPiwtHToiZEfjkDgDDPPSA9zaNc7w2NqrZ2M,20730
|
|
7
|
+
ara_cli/artefact_creator.py,sha256=wchIq1w636ui_kRCfNWPffqiIiXqSb49pgTpQj3KzA0,6132
|
|
8
8
|
ara_cli/artefact_deleter.py,sha256=Co4wwCH3yW8H9NrOq7_2p5571EeHr0TsfE-H8KqoOfY,1900
|
|
9
9
|
ara_cli/artefact_fuzzy_search.py,sha256=iBlDqjZf-_D3VUjFf7ZwkiQbpQDcwRndIU7aG_sRTgE,2668
|
|
10
10
|
ara_cli/artefact_link_updater.py,sha256=nKdxTpDKqWTOAMD8viKmUaklSFGWzJZ8S8E8xW_ADuM,3775
|
|
11
|
-
ara_cli/artefact_lister.py,sha256=
|
|
11
|
+
ara_cli/artefact_lister.py,sha256=M-ggazAgZ-OLeW9NB48r_sd6zPx0p4hEpeS63qHwI1A,4176
|
|
12
12
|
ara_cli/artefact_reader.py,sha256=Pho0_Eqm7kD9CNbVMhKb6mkNM0I3iJiCJXbXmVp1DJU,7827
|
|
13
|
-
ara_cli/artefact_renamer.py,sha256=
|
|
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=i2v-Ctem66sgO-HUV3kvMbk4wfotsc2oNet_i1-wfAI,39901
|
|
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
|
|
@@ -21,18 +21,20 @@ ara_cli/directory_navigator.py,sha256=6QbSAjJrJ5a6Lutol9J4HFgVDMiAQ672ny9TATrh04
|
|
|
21
21
|
ara_cli/file_classifier.py,sha256=A7wilPtIFm81iMgvqD0PjkOVL_QMUc9TB2w2Z9UcPcM,4001
|
|
22
22
|
ara_cli/file_lister.py,sha256=0C-j8IzajXo5qlvnuy5WFfe43ALwJ-0JFh2K6Xx2ccw,2332
|
|
23
23
|
ara_cli/filename_validator.py,sha256=Aw9PL8d5-Ymhp3EY6lDrUBk3cudaNqo1Uw5RzPpI1jA,118
|
|
24
|
+
ara_cli/global_file_lister.py,sha256=IIrtFoN5KYyJ3jVPanXZJ4UbYZfSdONRwxkZzvmq6-k,2806
|
|
24
25
|
ara_cli/list_filter.py,sha256=qKGwwQsrWe7L5FbdxEbBYD1bbbi8c-RMypjXqXvLbgs,5291
|
|
25
26
|
ara_cli/output_suppressor.py,sha256=nwiHaQLwabOjMoJOeUESBnZszGMxrQZfJ3N2OvahX7Y,389
|
|
26
27
|
ara_cli/prompt_chat.py,sha256=kd_OINDQFit6jN04bb7mzgY259JBbRaTaNp9F-webkc,1346
|
|
27
|
-
ara_cli/prompt_extractor.py,sha256
|
|
28
|
-
ara_cli/prompt_handler.py,sha256=
|
|
28
|
+
ara_cli/prompt_extractor.py,sha256=-_17aVYXYH6kPX5FOSb9T8lbEkKPXE6nlHWq1pvO_Og,8423
|
|
29
|
+
ara_cli/prompt_handler.py,sha256=8a9fcMwE_C6ntbw7UeroNJeU5LxrxEppiUtvYNUTB2U,23292
|
|
29
30
|
ara_cli/prompt_rag.py,sha256=ydlhe4CUqz0jdzlY7jBbpKaf_5fjMrAZKnriKea3ZAg,7485
|
|
30
31
|
ara_cli/run_file_lister.py,sha256=XbrrDTJXp1LFGx9Lv91SNsEHZPP-PyEMBF_P4btjbDA,2360
|
|
31
|
-
ara_cli/tag_extractor.py,sha256=
|
|
32
|
-
ara_cli/template_manager.py,sha256=
|
|
33
|
-
ara_cli/update_config_prompt.py,sha256=
|
|
34
|
-
ara_cli/version.py,sha256=
|
|
32
|
+
ara_cli/tag_extractor.py,sha256=k2yRl7dAMZ4YTARzUke4wgY0oEIOmWkOHGet7nXB6uw,3317
|
|
33
|
+
ara_cli/template_manager.py,sha256=l2c785YHB7m0e2TjE0CX-nwXrS4v3EiT9qrS5KuatAc,7105
|
|
34
|
+
ara_cli/update_config_prompt.py,sha256=moqj2Kha7S7fEGzTReU0v2y8UjXC8QfnoiieOQr35C4,5157
|
|
35
|
+
ara_cli/version.py,sha256=rYDZfGIzWScBRjMjgeqPAsdSGThurJ7PgpedF2Ekr2U,146
|
|
35
36
|
ara_cli/artefact_models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
37
|
+
ara_cli/artefact_models/artefact_data_retrieval.py,sha256=CooXOJBYWSyiViN2xkC8baS8OUaslry3YGVVUeDxRAU,527
|
|
36
38
|
ara_cli/artefact_models/artefact_load.py,sha256=IXzWxP-Q_j_oDGMno0m-OuXCQ7Vd5c_NctshGr4ROBw,621
|
|
37
39
|
ara_cli/artefact_models/artefact_mapping.py,sha256=8aD0spBjkJ8toMAmFawc6UTUxB6-tEEViZXv2I-r88Q,1874
|
|
38
40
|
ara_cli/artefact_models/artefact_model.py,sha256=qSbcrmFWAYgBqcNl9QARI1_uLQJm-TPVgP5q2AEFnjE,15983
|
|
@@ -50,15 +52,20 @@ ara_cli/artefact_models/userstory_artefact_model.py,sha256=2awH31ROtm7j4T44Bv4cy
|
|
|
50
52
|
ara_cli/artefact_models/vision_artefact_model.py,sha256=frjaUJj-mmIlVHEhzAQztCGs-CtvNu_odSborgztfzo,5251
|
|
51
53
|
ara_cli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
52
54
|
ara_cli/commands/command.py,sha256=Y_2dNeuxRjbyI3ScXNv55lptSe8Hs_ya78L0nPYNZHA,154
|
|
53
|
-
ara_cli/commands/extract_command.py,sha256=
|
|
55
|
+
ara_cli/commands/extract_command.py,sha256=qpi2_ac3DyxS7FiOz4GsTtRR4xtpegckUmfXzDOwymM,858
|
|
54
56
|
ara_cli/commands/load_command.py,sha256=H3CfeHIL-criDU5oi4BONTSpyzJ4m8DzJ0ZCIiAZFeI,2204
|
|
55
57
|
ara_cli/commands/load_image_command.py,sha256=g9-PXAYdqx5Ed1PdVo-FIb4CyJGEpRFbgQf9Dxg6DmM,886
|
|
58
|
+
ara_cli/commands/read_command.py,sha256=bo1BvRWuNKdFqBNN1EWORNrX_yuFAOyBruDUolHq1Vc,3791
|
|
56
59
|
ara_cli/file_loaders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
57
60
|
ara_cli/file_loaders/binary_file_loader.py,sha256=1HHH1Nk4lEM83CTnf4z9wYz6rMLgpxydFoRcSgkBHmQ,940
|
|
58
61
|
ara_cli/file_loaders/document_file_loader.py,sha256=VxGFChYyM9K-e6eOCK3yk5jQuEXgz01Mh_NoA6CA_RM,1017
|
|
59
62
|
ara_cli/file_loaders/document_reader.py,sha256=SD9_5-XJ6homKUes6o8GWcG--X63UslfAosPbrJZQvo,7721
|
|
63
|
+
ara_cli/file_loaders/document_readers.py,sha256=aG7xrUJwLxWpuFTYlvxzDqoS00Idpvwzt865L0OuQcA,8124
|
|
60
64
|
ara_cli/file_loaders/file_loader.py,sha256=bc1BrMG4pEtwsZLm3Ct53YsMPgnbSaEvZEd8isRDYRY,1711
|
|
61
|
-
ara_cli/file_loaders/
|
|
65
|
+
ara_cli/file_loaders/file_loaders.py,sha256=9QqArTRDmcUUar58JEr-qnpiAtH9ySP-MV9bvooQNpI,4290
|
|
66
|
+
ara_cli/file_loaders/image_processor.py,sha256=laPThh-i0-obYyS_linQTMcTUwuxMxrSjedGRYb8cIA,3462
|
|
67
|
+
ara_cli/file_loaders/markdown_reader.py,sha256=R-hvvc9Sj9pWwENqJ0j6wrW0eN1tUqEKWcK2YUFsvsU,2542
|
|
68
|
+
ara_cli/file_loaders/text_file_loader.py,sha256=62U59RkWgAML0U0P-sUeFsK51mJM8Fu54gGlnmMwYpY,6804
|
|
62
69
|
ara_cli/templates/agile.artefacts,sha256=nTA8dp98HWKAD-0qhmNpVYIfkVGoJshZqMJGnphiOsE,7932
|
|
63
70
|
ara_cli/templates/template.businessgoal.prompt_log.md,sha256=xF6bkgj_GqAAqHxJWJiQNt11mEuSGemIqoZ2wOo6dI0,214
|
|
64
71
|
ara_cli/templates/template.capability.prompt_log.md,sha256=eO8EzrHgb2vYJ-DP1jGzAfDlMo8nY75hZDfhh0s40uQ,208
|
|
@@ -134,27 +141,28 @@ ara_cli/templates/specification_breakdown_files/template.technology.exploration.
|
|
|
134
141
|
ara_cli/templates/specification_breakdown_files/template.technology.md,sha256=bySiksz-8xtq0Nnj4svqe2MgUftWrVkbK9AcrDUE3KY,952
|
|
135
142
|
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
136
143
|
tests/test_ara_command_action.py,sha256=JTLqXM9BSMlU33OQgrk_sZnoowFJZKZAx8q-st-wa34,25821
|
|
137
|
-
tests/test_ara_config.py,sha256=
|
|
144
|
+
tests/test_ara_config.py,sha256=RbVhS0SS1lr_SVopEMT1Fake5a-4rWN8MprgJtgI-FA,15883
|
|
138
145
|
tests/test_artefact_autofix.py,sha256=pApZ-N0dW8Ujt-cNLbgvd4bhiIIK8oXb-saLf6QlA-8,25022
|
|
139
146
|
tests/test_artefact_fuzzy_search.py,sha256=5Sh3_l9QK8-WHn6JpGPU1b6h4QEnl2JoMq1Tdp2cj1U,1261
|
|
140
147
|
tests/test_artefact_link_updater.py,sha256=biqbEp2jCOz8giv72hu2P2hDfeJfJ9OrVGdAv5d9cK4,2191
|
|
141
|
-
tests/test_artefact_lister.py,sha256=
|
|
148
|
+
tests/test_artefact_lister.py,sha256=35R13UU-YsX1HOsEN8M2-vIiCUA9RSBm6SwestDaFhE,20388
|
|
142
149
|
tests/test_artefact_reader.py,sha256=660K-d8ed-j8hulsUB_7baPD2-hhbg9TffUR5yVc4Uo,927
|
|
143
150
|
tests/test_artefact_renamer.py,sha256=lSnKCCfoFGgKhTdDZrEaeBq1xJAak1QoqH5aSeOe9Ro,3494
|
|
144
151
|
tests/test_artefact_scan.py,sha256=uNWgrt7ieZ4ogKACsPqzAsh59JF2BhTKSag31hpVrTQ,16887
|
|
145
|
-
tests/test_chat.py,sha256
|
|
152
|
+
tests/test_chat.py,sha256=sf4mXmOjXZeaYPNSYXSyfz0b5pZA6Mq7_R3gWjQaJw4,56152
|
|
146
153
|
tests/test_classifier.py,sha256=grYGPksydNdPsaEBQxYHZTuTdcJWz7VQtikCKA6BNaQ,1920
|
|
147
154
|
tests/test_directory_navigator.py,sha256=7G0MVrBbtBvbrFUpL0zb_9EkEWi1dulWuHsrQxMJxDY,140
|
|
148
155
|
tests/test_file_classifier.py,sha256=kLWPiePu3F5mkVuI_lK_2QlLh2kXD_Mt2K8KZZ1fAnA,10940
|
|
149
156
|
tests/test_file_creator.py,sha256=D3G7MbgE0m8JmZihxnTryxLco6iZdbV--2CGc0L20FM,2109
|
|
150
157
|
tests/test_file_lister.py,sha256=Q9HwhKKx540EPzTmfzOCnvtAgON0aMmpJE2eOe1J3EA,4324
|
|
158
|
+
tests/test_global_file_lister.py,sha256=ycvf2YL8q5QSEMwcnQfUdoWnQQ8xTSyEtccAeXwl6QU,5487
|
|
151
159
|
tests/test_list_filter.py,sha256=fJA3d_SdaOAUkE7jn68MOVS0THXGghy1fye_64Zvo1U,7964
|
|
152
|
-
tests/test_prompt_handler.py,sha256=
|
|
160
|
+
tests/test_prompt_handler.py,sha256=kW8FU09ho4I5qC-f4G9r4ZgI-NlqdOkTmAazG7FaTrw,32299
|
|
153
161
|
tests/test_tag_extractor.py,sha256=nSiAYlTKZ7TLAOtcJpwK5zTWHhFYU0tI5xKnivLc1dU,2712
|
|
154
|
-
tests/test_template_manager.py,sha256=
|
|
162
|
+
tests/test_template_manager.py,sha256=qliEeYgAEakn8JIqIHa8u0Ht6DY4L3T6DcHBXkjzR4I,4167
|
|
155
163
|
tests/test_update_config_prompt.py,sha256=xsqj1WTn4BsG5Q2t-sNPfu7EoMURFcS-hfb5VSXUnJc,6765
|
|
156
|
-
ara_cli-0.1.9.
|
|
157
|
-
ara_cli-0.1.9.
|
|
158
|
-
ara_cli-0.1.9.
|
|
159
|
-
ara_cli-0.1.9.
|
|
160
|
-
ara_cli-0.1.9.
|
|
164
|
+
ara_cli-0.1.9.95.dist-info/METADATA,sha256=ZVJWS_s9Xmdeftrsy6337QTfO_BVESYERmL5r_2tT3s,6789
|
|
165
|
+
ara_cli-0.1.9.95.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
166
|
+
ara_cli-0.1.9.95.dist-info/entry_points.txt,sha256=v4h7MzysTgSIDYfEo3oj4Kz_8lzsRa3hq-KJHEcLVX8,45
|
|
167
|
+
ara_cli-0.1.9.95.dist-info/top_level.txt,sha256=WM4cLHT5DYUaWzLtRj-gu3yVNFpGQ6lLRI3FMmC-38I,14
|
|
168
|
+
ara_cli-0.1.9.95.dist-info/RECORD,,
|
tests/test_ara_config.py
CHANGED
|
@@ -115,6 +115,34 @@ class TestARAconfig:
|
|
|
115
115
|
assert config.glossary_dir == "./glossary"
|
|
116
116
|
assert "Warning: Value for 'glossary_dir' is missing or empty. Using default." in mock_stdout.getvalue()
|
|
117
117
|
|
|
118
|
+
@patch('sys.stdout', new_callable=StringIO)
|
|
119
|
+
def test_validator_with_empty_llm_config(self, mock_stdout):
|
|
120
|
+
"""Tests validator when llm_config is empty, setting default and extraction to None."""
|
|
121
|
+
config = ARAconfig(llm_config={})
|
|
122
|
+
assert config.llm_config == {}
|
|
123
|
+
assert config.default_llm is None
|
|
124
|
+
assert config.extraction_llm is None
|
|
125
|
+
assert "Warning: 'llm_config' is empty" in mock_stdout.getvalue()
|
|
126
|
+
|
|
127
|
+
@patch('sys.stdout', new_callable=StringIO)
|
|
128
|
+
def test_validator_with_invalid_default_llm(self, mock_stdout):
|
|
129
|
+
"""Tests that an invalid default_llm is reverted to the first available model."""
|
|
130
|
+
config = ARAconfig(default_llm="non_existent_model")
|
|
131
|
+
first_llm = next(iter(config.llm_config))
|
|
132
|
+
assert config.default_llm == first_llm
|
|
133
|
+
output = mock_stdout.getvalue()
|
|
134
|
+
assert "Warning: The configured 'default_llm' ('non_existent_model') does not exist" in output
|
|
135
|
+
assert f"-> Reverting to the first available model: '{first_llm}'" in output
|
|
136
|
+
|
|
137
|
+
@patch('sys.stdout', new_callable=StringIO)
|
|
138
|
+
def test_validator_with_invalid_extraction_llm(self, mock_stdout):
|
|
139
|
+
"""Tests that an invalid extraction_llm is reverted to the default_llm."""
|
|
140
|
+
config = ARAconfig(default_llm="gpt-4o", extraction_llm="non_existent_model")
|
|
141
|
+
assert config.extraction_llm == "gpt-4o"
|
|
142
|
+
output = mock_stdout.getvalue()
|
|
143
|
+
assert "Warning: The configured 'extraction_llm' ('non_existent_model') does not exist" in output
|
|
144
|
+
assert "-> Reverting to the 'default_llm' value: 'gpt-4o'" in output
|
|
145
|
+
|
|
118
146
|
# --- Test Helper Functions ---
|
|
119
147
|
|
|
120
148
|
class TestEnsureDirectoryExists:
|
tests/test_artefact_lister.py
CHANGED
|
@@ -2,6 +2,11 @@ import pytest
|
|
|
2
2
|
from unittest.mock import MagicMock, patch
|
|
3
3
|
from ara_cli.artefact_lister import ArtefactLister
|
|
4
4
|
from ara_cli.list_filter import ListFilter
|
|
5
|
+
from ara_cli.artefact_models.artefact_data_retrieval import (
|
|
6
|
+
artefact_content_retrieval,
|
|
7
|
+
artefact_path_retrieval,
|
|
8
|
+
artefact_tags_retrieval,
|
|
9
|
+
)
|
|
5
10
|
|
|
6
11
|
|
|
7
12
|
@pytest.fixture
|
|
@@ -9,66 +14,6 @@ def artefact_lister():
|
|
|
9
14
|
return ArtefactLister()
|
|
10
15
|
|
|
11
16
|
|
|
12
|
-
@pytest.mark.parametrize(
|
|
13
|
-
"users, status, tags, expected_tags",
|
|
14
|
-
[
|
|
15
|
-
# Normal case with all fields populated
|
|
16
|
-
(
|
|
17
|
-
["john", "alice"],
|
|
18
|
-
"in-progress",
|
|
19
|
-
["important", "urgent"],
|
|
20
|
-
["user_john", "user_alice", "in-progress", "important", "urgent"]
|
|
21
|
-
),
|
|
22
|
-
# Case with empty users
|
|
23
|
-
(
|
|
24
|
-
[],
|
|
25
|
-
"to-do",
|
|
26
|
-
["feature", "backend"],
|
|
27
|
-
["to-do", "feature", "backend"]
|
|
28
|
-
),
|
|
29
|
-
# Case with empty tags
|
|
30
|
-
(
|
|
31
|
-
["bob"],
|
|
32
|
-
"done",
|
|
33
|
-
[],
|
|
34
|
-
["user_bob", "done"]
|
|
35
|
-
),
|
|
36
|
-
# Case with all empty fields
|
|
37
|
-
(
|
|
38
|
-
[],
|
|
39
|
-
"",
|
|
40
|
-
[],
|
|
41
|
-
[""]
|
|
42
|
-
),
|
|
43
|
-
# Case with None values for tags (should handle gracefully)
|
|
44
|
-
(
|
|
45
|
-
["admin"],
|
|
46
|
-
"closed",
|
|
47
|
-
None,
|
|
48
|
-
["user_admin", "closed"]
|
|
49
|
-
),
|
|
50
|
-
]
|
|
51
|
-
)
|
|
52
|
-
def test_artefact_tags_retrieval(users, status, tags, expected_tags):
|
|
53
|
-
# Create a mock artefact with the specified attributes
|
|
54
|
-
artefact_mock = MagicMock()
|
|
55
|
-
artefact_mock.users = users
|
|
56
|
-
artefact_mock.status = status
|
|
57
|
-
artefact_mock.tags = tags if tags is not None else []
|
|
58
|
-
|
|
59
|
-
# Call the method under test
|
|
60
|
-
result = ArtefactLister.artefact_tags_retrieval(artefact_mock)
|
|
61
|
-
|
|
62
|
-
# Verify the result
|
|
63
|
-
assert result == expected_tags
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
def test_artefact_tags_retrieval_with_none():
|
|
67
|
-
# Test with None artefact
|
|
68
|
-
result = ArtefactLister.artefact_tags_retrieval(None)
|
|
69
|
-
assert result == []
|
|
70
|
-
|
|
71
|
-
|
|
72
17
|
@pytest.mark.parametrize(
|
|
73
18
|
"classified_files, list_filter, filter_result",
|
|
74
19
|
[
|
|
@@ -76,39 +21,36 @@ def test_artefact_tags_retrieval_with_none():
|
|
|
76
21
|
(
|
|
77
22
|
{"type1": [MagicMock(), MagicMock()]},
|
|
78
23
|
None,
|
|
79
|
-
{"type1": [MagicMock(), MagicMock()]}
|
|
24
|
+
{"type1": [MagicMock(), MagicMock()]},
|
|
80
25
|
),
|
|
81
26
|
# Case 2: Filter with include tags
|
|
82
27
|
(
|
|
83
28
|
{"type1": [MagicMock(), MagicMock()]},
|
|
84
29
|
ListFilter(include_tags=["tag1"]),
|
|
85
|
-
{"type1": [MagicMock()]}
|
|
30
|
+
{"type1": [MagicMock()]},
|
|
86
31
|
),
|
|
87
32
|
# Case 3: Filter with exclude tags
|
|
88
33
|
(
|
|
89
34
|
{"type1": [MagicMock(), MagicMock()], "type2": [MagicMock()]},
|
|
90
35
|
ListFilter(exclude_tags=["tag2"]),
|
|
91
|
-
{"type1": [MagicMock()], "type2": []}
|
|
36
|
+
{"type1": [MagicMock()], "type2": []},
|
|
92
37
|
),
|
|
93
38
|
# Case 4: Empty result after filtering
|
|
94
39
|
(
|
|
95
40
|
{"type1": [MagicMock(), MagicMock()]},
|
|
96
41
|
ListFilter(include_tags=["nonexistent"]),
|
|
97
|
-
{"type1": []}
|
|
42
|
+
{"type1": []},
|
|
98
43
|
),
|
|
99
44
|
# Case 5: Multiple artefact types
|
|
100
45
|
(
|
|
101
46
|
{"type1": [MagicMock()], "type2": [MagicMock(), MagicMock()]},
|
|
102
47
|
ListFilter(exclude_extension=[".txt"]),
|
|
103
|
-
{"type1": [], "type2": [MagicMock()]}
|
|
48
|
+
{"type1": [], "type2": [MagicMock()]},
|
|
104
49
|
),
|
|
105
50
|
],
|
|
106
51
|
)
|
|
107
52
|
def test_filter_artefacts(
|
|
108
|
-
artefact_lister,
|
|
109
|
-
classified_files,
|
|
110
|
-
list_filter,
|
|
111
|
-
filter_result
|
|
53
|
+
artefact_lister, classified_files, list_filter, filter_result
|
|
112
54
|
):
|
|
113
55
|
# Mock the filter_list function
|
|
114
56
|
with patch("ara_cli.artefact_lister.filter_list") as mock_filter_list:
|
|
@@ -121,9 +63,9 @@ def test_filter_artefacts(
|
|
|
121
63
|
mock_filter_list.assert_called_once_with(
|
|
122
64
|
list_to_filter=classified_files,
|
|
123
65
|
list_filter=list_filter,
|
|
124
|
-
content_retrieval_strategy=
|
|
125
|
-
file_path_retrieval=
|
|
126
|
-
tag_retrieval=
|
|
66
|
+
content_retrieval_strategy=artefact_content_retrieval,
|
|
67
|
+
file_path_retrieval=artefact_path_retrieval,
|
|
68
|
+
tag_retrieval=artefact_tags_retrieval,
|
|
127
69
|
)
|
|
128
70
|
|
|
129
71
|
# Verify the structure matches (don't compare the actual MagicMock objects)
|
|
@@ -132,30 +74,6 @@ def test_filter_artefacts(
|
|
|
132
74
|
assert len(result[key]) == len(filter_result[key])
|
|
133
75
|
|
|
134
76
|
|
|
135
|
-
@pytest.mark.parametrize("artefact_content", ["content1", "content2", "content3"])
|
|
136
|
-
def test_artefact_content_retrieval(artefact_content):
|
|
137
|
-
artefact_mock = MagicMock()
|
|
138
|
-
artefact_mock.serialize.return_value = artefact_content # Mock serialize()
|
|
139
|
-
|
|
140
|
-
content = ArtefactLister.artefact_content_retrieval(artefact_mock)
|
|
141
|
-
assert content == artefact_content
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
@pytest.mark.parametrize(
|
|
145
|
-
"file_path",
|
|
146
|
-
[
|
|
147
|
-
("./ara/userstories/test.userstory"),
|
|
148
|
-
("./ara/epics/test.epic"),
|
|
149
|
-
],
|
|
150
|
-
)
|
|
151
|
-
def test_artefact_path_retrieval(file_path):
|
|
152
|
-
artefact_mock = MagicMock()
|
|
153
|
-
artefact_mock.file_path = file_path
|
|
154
|
-
|
|
155
|
-
path = ArtefactLister.artefact_path_retrieval(artefact_mock)
|
|
156
|
-
assert path == file_path
|
|
157
|
-
|
|
158
|
-
|
|
159
77
|
@pytest.mark.parametrize(
|
|
160
78
|
"tags, navigate_to_target, list_filter, mock_artefacts, filtered_artefacts, expected_filtered",
|
|
161
79
|
[
|
|
@@ -476,20 +394,21 @@ def test_list_data_artefact_found_data_exists(artefact_lister):
|
|
|
476
394
|
classified_artefacts = {
|
|
477
395
|
"epic": [
|
|
478
396
|
{"title": "Epic1", "file_path": "path/to/Epic1.epic"},
|
|
479
|
-
{"title": "Epic2", "file_path": "path/to/Epic2.epic"}
|
|
397
|
+
{"title": "Epic2", "file_path": "path/to/Epic2.epic"},
|
|
480
398
|
]
|
|
481
399
|
}
|
|
482
|
-
|
|
483
|
-
with patch("ara_cli.artefact_lister.FileClassifier") as mock_file_classifier,
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
400
|
+
|
|
401
|
+
with patch("ara_cli.artefact_lister.FileClassifier") as mock_file_classifier, patch(
|
|
402
|
+
"ara_cli.artefact_lister.suggest_close_name_matches"
|
|
403
|
+
) as mock_suggest, patch("ara_cli.artefact_lister.os") as mock_os, patch(
|
|
404
|
+
"ara_cli.artefact_lister.list_files_in_directory"
|
|
405
|
+
) as mock_list_files:
|
|
487
406
|
|
|
488
407
|
# Configure mocks
|
|
489
408
|
mock_classifier_instance = MagicMock()
|
|
490
409
|
mock_file_classifier.return_value = mock_classifier_instance
|
|
491
410
|
mock_classifier_instance.classify_files.return_value = classified_artefacts
|
|
492
|
-
|
|
411
|
+
|
|
493
412
|
mock_os.path.splitext.return_value = ("path/to/Epic1", ".epic")
|
|
494
413
|
mock_os.path.exists.return_value = True
|
|
495
414
|
|
|
@@ -510,20 +429,21 @@ def test_list_data_artefact_found_data_not_exists(artefact_lister):
|
|
|
510
429
|
classified_artefacts = {
|
|
511
430
|
"epic": [
|
|
512
431
|
{"title": "Epic1", "file_path": "path/to/Epic1.epic"},
|
|
513
|
-
{"title": "Epic2", "file_path": "path/to/Epic2.epic"}
|
|
432
|
+
{"title": "Epic2", "file_path": "path/to/Epic2.epic"},
|
|
514
433
|
]
|
|
515
434
|
}
|
|
516
|
-
|
|
517
|
-
with patch("ara_cli.artefact_lister.FileClassifier") as mock_file_classifier,
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
435
|
+
|
|
436
|
+
with patch("ara_cli.artefact_lister.FileClassifier") as mock_file_classifier, patch(
|
|
437
|
+
"ara_cli.artefact_lister.suggest_close_name_matches"
|
|
438
|
+
) as mock_suggest, patch("ara_cli.artefact_lister.os") as mock_os, patch(
|
|
439
|
+
"ara_cli.artefact_lister.list_files_in_directory"
|
|
440
|
+
) as mock_list_files:
|
|
521
441
|
|
|
522
442
|
# Configure mocks
|
|
523
443
|
mock_classifier_instance = MagicMock()
|
|
524
444
|
mock_file_classifier.return_value = mock_classifier_instance
|
|
525
445
|
mock_classifier_instance.classify_files.return_value = classified_artefacts
|
|
526
|
-
|
|
446
|
+
|
|
527
447
|
mock_os.path.splitext.return_value = ("path/to/Epic1", ".epic")
|
|
528
448
|
mock_os.path.exists.return_value = False
|
|
529
449
|
|
|
@@ -544,14 +464,15 @@ def test_list_data_artefact_not_found(artefact_lister):
|
|
|
544
464
|
classified_artefacts = {
|
|
545
465
|
"epic": [
|
|
546
466
|
{"title": "Epic1", "file_path": "path/to/Epic1.epic"},
|
|
547
|
-
{"title": "Epic2", "file_path": "path/to/Epic2.epic"}
|
|
467
|
+
{"title": "Epic2", "file_path": "path/to/Epic2.epic"},
|
|
548
468
|
]
|
|
549
469
|
}
|
|
550
|
-
|
|
551
|
-
with patch("ara_cli.artefact_lister.FileClassifier") as mock_file_classifier,
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
470
|
+
|
|
471
|
+
with patch("ara_cli.artefact_lister.FileClassifier") as mock_file_classifier, patch(
|
|
472
|
+
"ara_cli.artefact_lister.suggest_close_name_matches"
|
|
473
|
+
) as mock_suggest, patch("ara_cli.artefact_lister.os") as mock_os, patch(
|
|
474
|
+
"ara_cli.artefact_lister.list_files_in_directory"
|
|
475
|
+
) as mock_list_files:
|
|
555
476
|
|
|
556
477
|
# Configure mocks
|
|
557
478
|
mock_classifier_instance = MagicMock()
|
|
@@ -562,10 +483,7 @@ def test_list_data_artefact_not_found(artefact_lister):
|
|
|
562
483
|
artefact_lister.list_data(classifier, artefact_name, list_filter)
|
|
563
484
|
|
|
564
485
|
# Verify interactions
|
|
565
|
-
mock_suggest.assert_called_once_with(
|
|
566
|
-
artefact_name,
|
|
567
|
-
["Epic1", "Epic2"]
|
|
568
|
-
)
|
|
486
|
+
mock_suggest.assert_called_once_with(artefact_name, ["Epic1", "Epic2"])
|
|
569
487
|
mock_os.path.splitext.assert_not_called()
|
|
570
488
|
mock_os.path.exists.assert_not_called()
|
|
571
489
|
mock_list_files.assert_not_called()
|
|
@@ -578,20 +496,21 @@ def test_list_data_with_filter(artefact_lister):
|
|
|
578
496
|
classified_artefacts = {
|
|
579
497
|
"userstory": [
|
|
580
498
|
{"title": "Story1", "file_path": "path/to/Story1.userstory"},
|
|
581
|
-
{"title": "Story2", "file_path": "path/to/Story2.userstory"}
|
|
499
|
+
{"title": "Story2", "file_path": "path/to/Story2.userstory"},
|
|
582
500
|
]
|
|
583
501
|
}
|
|
584
|
-
|
|
585
|
-
with patch("ara_cli.artefact_lister.FileClassifier") as mock_file_classifier,
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
502
|
+
|
|
503
|
+
with patch("ara_cli.artefact_lister.FileClassifier") as mock_file_classifier, patch(
|
|
504
|
+
"ara_cli.artefact_lister.suggest_close_name_matches"
|
|
505
|
+
) as mock_suggest, patch("ara_cli.artefact_lister.os") as mock_os, patch(
|
|
506
|
+
"ara_cli.artefact_lister.list_files_in_directory"
|
|
507
|
+
) as mock_list_files:
|
|
589
508
|
|
|
590
509
|
# Configure mocks
|
|
591
510
|
mock_classifier_instance = MagicMock()
|
|
592
511
|
mock_file_classifier.return_value = mock_classifier_instance
|
|
593
512
|
mock_classifier_instance.classify_files.return_value = classified_artefacts
|
|
594
|
-
|
|
513
|
+
|
|
595
514
|
mock_os.path.splitext.return_value = ("path/to/Story1", ".userstory")
|
|
596
515
|
mock_os.path.exists.return_value = True
|
|
597
516
|
|
|
@@ -610,11 +529,12 @@ def test_list_data_empty_artefact_list(artefact_lister):
|
|
|
610
529
|
artefact_name = "Epic1"
|
|
611
530
|
list_filter = None
|
|
612
531
|
classified_artefacts = {"epic": []}
|
|
613
|
-
|
|
614
|
-
with patch("ara_cli.artefact_lister.FileClassifier") as mock_file_classifier,
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
532
|
+
|
|
533
|
+
with patch("ara_cli.artefact_lister.FileClassifier") as mock_file_classifier, patch(
|
|
534
|
+
"ara_cli.artefact_lister.suggest_close_name_matches"
|
|
535
|
+
) as mock_suggest, patch("ara_cli.artefact_lister.os") as mock_os, patch(
|
|
536
|
+
"ara_cli.artefact_lister.list_files_in_directory"
|
|
537
|
+
) as mock_list_files:
|
|
618
538
|
|
|
619
539
|
# Configure mocks
|
|
620
540
|
mock_classifier_instance = MagicMock()
|
tests/test_chat.py
CHANGED
|
@@ -10,6 +10,7 @@ from types import SimpleNamespace
|
|
|
10
10
|
from ara_cli.chat import Chat
|
|
11
11
|
from ara_cli.template_manager import TemplatePathManager
|
|
12
12
|
from ara_cli.ara_config import ConfigManager
|
|
13
|
+
from ara_cli.file_loaders.text_file_loader import TextFileLoader
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
def get_default_config():
|
|
@@ -471,42 +472,28 @@ def test_determine_file_path(temp_chat_file):
|
|
|
471
472
|
mock_exists.reset_mock()
|
|
472
473
|
|
|
473
474
|
|
|
474
|
-
@pytest.mark.parametrize("file_name,
|
|
475
|
-
("document.txt", "Hello World
|
|
476
|
-
("
|
|
477
|
-
("document.txt", "Hello World", "", "", "---", "---\nHello World\n---\n"),
|
|
478
|
-
("document.txt", "Hello World", "Prefix", "Suffix", "---", "Prefix---\nHello World\n---Suffix\n"),
|
|
475
|
+
@pytest.mark.parametrize("file_name, expected_content", [
|
|
476
|
+
("document.txt", "Hello World\n"),
|
|
477
|
+
("another_document.txt", "Another World\n"),
|
|
479
478
|
])
|
|
480
|
-
def test_load_text_file(temp_chat_file, file_name,
|
|
481
|
-
|
|
479
|
+
def test_load_text_file(temp_chat_file, file_name, expected_content):
|
|
480
|
+
# Create a mock config
|
|
481
|
+
mock_config = MagicMock()
|
|
482
|
+
|
|
483
|
+
# Patch the get_config method to return the mock config
|
|
482
484
|
with patch('ara_cli.prompt_handler.ConfigManager.get_config', return_value=mock_config):
|
|
483
485
|
chat = Chat(temp_chat_file.name, reset=False)
|
|
484
486
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
assert result is True
|
|
490
|
-
|
|
491
|
-
mock_file.assert_any_call(file_name, 'r', encoding='utf-8', errors="replace")
|
|
492
|
-
|
|
493
|
-
mock_file.assert_any_call(chat.chat_name, 'a', encoding='utf-8')
|
|
494
|
-
|
|
495
|
-
mock_file().write.assert_called_once_with(expected_content)
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
# def test_load_text_file_file_not_found(temp_chat_file):
|
|
499
|
-
# mock_config = get_default_config()
|
|
500
|
-
# with patch('ara_cli.prompt_handler.ConfigManager.get_config', return_value=mock_config):
|
|
501
|
-
# chat = Chat(temp_chat_file.name, reset=False)
|
|
502
|
-
|
|
503
|
-
# with patch.object(chat, 'determine_file_path', return_value=None):
|
|
504
|
-
# with patch("builtins.open", mock_open()) as mock_file:
|
|
505
|
-
# result = chat.load_text_file("nonexistent.txt")
|
|
487
|
+
# Mock the TextFileLoader
|
|
488
|
+
with patch.object(TextFileLoader, 'load', return_value=True) as mock_load:
|
|
489
|
+
# Call the load_text_file method
|
|
490
|
+
result = chat.load_text_file(file_name)
|
|
506
491
|
|
|
507
|
-
#
|
|
492
|
+
# Check that the load method was called once
|
|
493
|
+
mock_load.assert_called_once()
|
|
508
494
|
|
|
509
|
-
#
|
|
495
|
+
# Check that the result is True
|
|
496
|
+
assert result is True
|
|
510
497
|
|
|
511
498
|
|
|
512
499
|
@pytest.mark.parametrize(
|
|
@@ -635,14 +622,14 @@ def test_load_file(temp_chat_file, file_name, file_type, mime_type):
|
|
|
635
622
|
patch.object(chat, 'load_text_file', return_value=True) as mock_load_text, \
|
|
636
623
|
patch.object(chat, 'load_document_file', return_value=True) as mock_load_document:
|
|
637
624
|
|
|
638
|
-
chat.load_file(file_name=file_name, prefix="p-", suffix="-
|
|
625
|
+
chat.load_file(file_name=file_name, prefix="p-", suffix="-f", block_delimiter="b", extract_images=False)
|
|
639
626
|
|
|
640
627
|
if file_type == "binary":
|
|
641
628
|
mock_load_binary.assert_called_once_with(
|
|
642
629
|
file_path=file_name,
|
|
643
630
|
mime_type=mime_type,
|
|
644
631
|
prefix="p-",
|
|
645
|
-
suffix="-
|
|
632
|
+
suffix="-f"
|
|
646
633
|
)
|
|
647
634
|
mock_load_text.assert_not_called()
|
|
648
635
|
mock_load_document.assert_not_called()
|
|
@@ -652,7 +639,7 @@ def test_load_file(temp_chat_file, file_name, file_type, mime_type):
|
|
|
652
639
|
mock_load_document.assert_called_once_with(
|
|
653
640
|
file_path=file_name,
|
|
654
641
|
prefix="p-",
|
|
655
|
-
suffix="-
|
|
642
|
+
suffix="-f",
|
|
656
643
|
block_delimiter="b",
|
|
657
644
|
extract_images=False
|
|
658
645
|
)
|
|
@@ -661,7 +648,7 @@ def test_load_file(temp_chat_file, file_name, file_type, mime_type):
|
|
|
661
648
|
mock_load_text.assert_called_once_with(
|
|
662
649
|
file_path=file_name,
|
|
663
650
|
prefix="p-",
|
|
664
|
-
suffix="-
|
|
651
|
+
suffix="-f",
|
|
665
652
|
block_delimiter="b",
|
|
666
653
|
extract_images=False
|
|
667
654
|
)
|
|
@@ -714,7 +701,7 @@ def test_load_helper(monkeypatch, capsys, temp_chat_file, directory, pattern, fi
|
|
|
714
701
|
def mock_input(prompt):
|
|
715
702
|
return user_input
|
|
716
703
|
|
|
717
|
-
def mock_load_file(self, file_path
|
|
704
|
+
def mock_load_file(self, file_path):
|
|
718
705
|
return True
|
|
719
706
|
|
|
720
707
|
monkeypatch.setattr(glob, 'glob', mock_glob)
|
|
@@ -750,7 +737,7 @@ def test_load_helper_with_exclude(monkeypatch, capsys, temp_chat_file, directory
|
|
|
750
737
|
def mock_input(prompt):
|
|
751
738
|
return user_input
|
|
752
739
|
|
|
753
|
-
def mock_load_file(self, file_path
|
|
740
|
+
def mock_load_file(self, file_path):
|
|
754
741
|
return True
|
|
755
742
|
|
|
756
743
|
monkeypatch.setattr(glob, 'glob', mock_glob)
|
|
@@ -907,7 +894,7 @@ def test_load_image(capsys, temp_chat_file, file_name, is_image, expected_mime):
|
|
|
907
894
|
chat = Chat(temp_chat_file.name, reset=False)
|
|
908
895
|
|
|
909
896
|
with patch.object(chat, 'load_binary_file', return_value=True) as mock_load_binary:
|
|
910
|
-
chat.load_image(file_name=file_name, prefix="p-", suffix="-
|
|
897
|
+
chat.load_image(file_name=file_name, prefix="p-", suffix="-f")
|
|
911
898
|
|
|
912
899
|
if is_image:
|
|
913
900
|
# FIX: The called method's parameter is `file_path`, not `file_name`.
|
|
@@ -915,7 +902,7 @@ def test_load_image(capsys, temp_chat_file, file_name, is_image, expected_mime):
|
|
|
915
902
|
file_path=file_name,
|
|
916
903
|
mime_type=expected_mime,
|
|
917
904
|
prefix="p-",
|
|
918
|
-
suffix="-
|
|
905
|
+
suffix="-f"
|
|
919
906
|
)
|
|
920
907
|
else:
|
|
921
908
|
mock_load_binary.assert_not_called()
|
|
@@ -1232,13 +1219,14 @@ def test_do_EXTRACT(MockExtractCommand, temp_chat_file):
|
|
|
1232
1219
|
with patch('ara_cli.prompt_handler.ConfigManager.get_config', return_value=mock_config):
|
|
1233
1220
|
chat = Chat(temp_chat_file.name, reset=False)
|
|
1234
1221
|
|
|
1235
|
-
#
|
|
1222
|
+
# The `onecmd_plus_hooks` method requires the `orig_rl_history_length` argument.
|
|
1236
1223
|
# We can pass a dummy value like 0 for the test.
|
|
1237
1224
|
chat.onecmd_plus_hooks("EXTRACT", orig_rl_history_length=0)
|
|
1238
1225
|
|
|
1239
1226
|
MockExtractCommand.assert_called_once_with(
|
|
1240
1227
|
file_name=chat.chat_name,
|
|
1241
|
-
|
|
1228
|
+
force=False,
|
|
1229
|
+
write=False,
|
|
1242
1230
|
output=chat.poutput,
|
|
1243
1231
|
error_output=chat.perror
|
|
1244
1232
|
)
|