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.

Files changed (35) hide show
  1. ara_cli/__init__.py +15 -1
  2. ara_cli/ara_command_action.py +23 -43
  3. ara_cli/ara_command_parser.py +16 -1
  4. ara_cli/ara_config.py +17 -2
  5. ara_cli/artefact_autofix.py +40 -21
  6. ara_cli/artefact_creator.py +3 -1
  7. ara_cli/artefact_lister.py +29 -55
  8. ara_cli/artefact_models/artefact_data_retrieval.py +23 -0
  9. ara_cli/artefact_renamer.py +6 -2
  10. ara_cli/chat.py +80 -34
  11. ara_cli/commands/extract_command.py +4 -3
  12. ara_cli/commands/read_command.py +104 -0
  13. ara_cli/file_loaders/document_readers.py +233 -0
  14. ara_cli/file_loaders/file_loaders.py +123 -0
  15. ara_cli/file_loaders/image_processor.py +89 -0
  16. ara_cli/file_loaders/markdown_reader.py +75 -0
  17. ara_cli/file_loaders/text_file_loader.py +9 -11
  18. ara_cli/global_file_lister.py +61 -0
  19. ara_cli/prompt_extractor.py +21 -6
  20. ara_cli/prompt_handler.py +24 -4
  21. ara_cli/tag_extractor.py +21 -11
  22. ara_cli/template_manager.py +14 -4
  23. ara_cli/update_config_prompt.py +7 -1
  24. ara_cli/version.py +1 -1
  25. {ara_cli-0.1.9.93.dist-info → ara_cli-0.1.9.95.dist-info}/METADATA +18 -17
  26. {ara_cli-0.1.9.93.dist-info → ara_cli-0.1.9.95.dist-info}/RECORD +35 -27
  27. tests/test_ara_config.py +28 -0
  28. tests/test_artefact_lister.py +52 -132
  29. tests/test_chat.py +28 -40
  30. tests/test_global_file_lister.py +131 -0
  31. tests/test_prompt_handler.py +26 -1
  32. tests/test_template_manager.py +5 -4
  33. {ara_cli-0.1.9.93.dist-info → ara_cli-0.1.9.95.dist-info}/WHEEL +0 -0
  34. {ara_cli-0.1.9.93.dist-info → ara_cli-0.1.9.95.dist-info}/entry_points.txt +0 -0
  35. {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=0zl7IegxTid26EBGLav_fXZ4CCIV3H5TfAoFQiOHjvg,148
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=_LHE2V5hbJxN7ccYiptuPktRfbTnXmQEt_D_FxDBlBY,22456
4
- ara_cli/ara_command_parser.py,sha256=I-e9W-QwTIMKMzlHycSlCWCyBFQfiFYvGre1XsDbrFI,20573
5
- ara_cli/ara_config.py,sha256=5uBo_flNgZSk7B9lmyfvzWyxfIQzb13LbieCpJfdZJI,8765
6
- ara_cli/artefact_autofix.py,sha256=WVTiIR-jo4YKmmz4eS3qTFvl45W1YKwAk1XSuz9QX10,20015
7
- ara_cli/artefact_creator.py,sha256=0Ory6cB-Ahkw-BDNb8QHnTbp_OHGABdkb9bhwcEdcIc,6063
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=jhk4n4eqp7hDIq07q43QzS7-36BM3OfZ4EABxCeOGcw,4764
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=Hnz_3zD9xxnBa1FHyUE6mIktLk_9ttP2rFRvQIkmz-o,4061
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=mbpv5XQOcJSAUBJxCrfmyl7W5a0GhQU9cblxiTJNpP8,37841
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=Sk1aQkvn8W_YNcGhfChsbT19wUAWEJmOHTr3mveyQww,7754
28
- ara_cli/prompt_handler.py,sha256=6yfiMFNHGHANREAsjT8dv9jKxBKeazPkF7xQQI4l6vQ,22312
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=TGdaQOVnjy25R0zDsAifB67C5oom0Fwo24s0_fr5A_I,3151
32
- ara_cli/template_manager.py,sha256=YwrN6AYPpl6ZrW8BVQpVXx8yTRf-oNpJUIKeg4NAggs,6606
33
- ara_cli/update_config_prompt.py,sha256=Oy9vNTw6UhDohyTEfSKkqE5ifEMPlmWNYkKHgUrK_pY,4607
34
- ara_cli/version.py,sha256=UYGRHXHl4vgX5k6OLDjyffvrV4jDkHj_fVeKiGqQ8XU,146
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=TfKuOnKQzJ8JPpJyKDm7qhm5mvbZnHspCem8g6YgACo,835
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/text_file_loader.py,sha256=x_ZqnOUb2glpdxziceWCBX8oEBk7JZhAluLRRvBjuQs,6626
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=H5GwDbab0GMSa6IbHdruzmbsHy5Ia0xX0uteJdfZ9Rg,14277
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=VCEOCgDgnAOeUUgIoGAbWgz60hf9UT-tdHg18LGfB34,22656
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=-2vs3ORlym0yv05BLSCNX-6tNYXqoZiBFar8gswPuw8,57072
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=3-lYBvyHLQgD29MODkXB3YylUWXmRCYdAwrQrtlW8WU,30871
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=q-LMHRG4rHkD6ON6YW4cpZxUx9hul6Or8wVVRC2kb-8,4099
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.93.dist-info/METADATA,sha256=BEbyd6dizmW-wO3XCdsyU9t2FrgKvQdIPMhAcxm8__M,6739
157
- ara_cli-0.1.9.93.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
158
- ara_cli-0.1.9.93.dist-info/entry_points.txt,sha256=v4h7MzysTgSIDYfEo3oj4Kz_8lzsRa3hq-KJHEcLVX8,45
159
- ara_cli-0.1.9.93.dist-info/top_level.txt,sha256=WM4cLHT5DYUaWzLtRj-gu3yVNFpGQ6lLRI3FMmC-38I,14
160
- ara_cli-0.1.9.93.dist-info/RECORD,,
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:
@@ -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=ArtefactLister.artefact_content_retrieval,
125
- file_path_retrieval=ArtefactLister.artefact_path_retrieval,
126
- tag_retrieval=ArtefactLister.artefact_tags_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
- patch("ara_cli.artefact_lister.suggest_close_name_matches") as mock_suggest, \
485
- patch("ara_cli.artefact_lister.os") as mock_os, \
486
- patch("ara_cli.artefact_lister.list_files_in_directory") as mock_list_files:
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
- patch("ara_cli.artefact_lister.suggest_close_name_matches") as mock_suggest, \
519
- patch("ara_cli.artefact_lister.os") as mock_os, \
520
- patch("ara_cli.artefact_lister.list_files_in_directory") as mock_list_files:
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
- patch("ara_cli.artefact_lister.suggest_close_name_matches") as mock_suggest, \
553
- patch("ara_cli.artefact_lister.os") as mock_os, \
554
- patch("ara_cli.artefact_lister.list_files_in_directory") as mock_list_files:
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
- patch("ara_cli.artefact_lister.suggest_close_name_matches") as mock_suggest, \
587
- patch("ara_cli.artefact_lister.os") as mock_os, \
588
- patch("ara_cli.artefact_lister.list_files_in_directory") as mock_list_files:
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
- patch("ara_cli.artefact_lister.suggest_close_name_matches") as mock_suggest, \
616
- patch("ara_cli.artefact_lister.os") as mock_os, \
617
- patch("ara_cli.artefact_lister.list_files_in_directory") as mock_list_files:
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, file_content, prefix, suffix, block_delimiter, expected_content", [
475
- ("document.txt", "Hello World", "", "", "", "Hello World\n"),
476
- ("document.txt", "Hello World", "Prefix-", "-Suffix", "", "Prefix-Hello World-Suffix\n"),
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, file_content, prefix, suffix, block_delimiter, expected_content):
481
- mock_config = get_default_config()
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
- with patch.object(chat, 'determine_file_path', return_value=file_name):
486
- with patch("builtins.open", mock_open(read_data=file_content)) as mock_file:
487
- result = chat.load_text_file(file_name, prefix, suffix, block_delimiter)
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
- # assert result is False
492
+ # Check that the load method was called once
493
+ mock_load.assert_called_once()
508
494
 
509
- # mock_file.assert_not_called()
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="-s", block_delimiter="b", extract_images=False)
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="-s"
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="-s",
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="-s",
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, prefix="", suffix=""):
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, prefix="", suffix=""):
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="-s")
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="-s"
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
- # FIX: The `onecmd_plus_hooks` method requires the `orig_rl_history_length` argument.
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
- skip_queries=False,
1228
+ force=False,
1229
+ write=False,
1242
1230
  output=chat.poutput,
1243
1231
  error_output=chat.perror
1244
1232
  )