ara-cli 0.1.9.50__py3-none-any.whl → 0.1.9.52__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.
@@ -1,45 +1,46 @@
1
1
  ara_cli/__init__.py,sha256=0zl7IegxTid26EBGLav_fXZ4CCIV3H5TfAoFQiOHjvg,148
2
- ara_cli/__main__.py,sha256=MCFmW28F03tdci98CNPKeyHyksf8rrD4zkcj8Y9GBx4,1761
3
- ara_cli/ara_command_action.py,sha256=IHf5v_7CXwtFJXFwY6G-DsVFDho3hjudlocosJXA2gY,18735
4
- ara_cli/ara_command_parser.py,sha256=VCjvPw_lgVjC06mjtsx6Wh1OJTjpBzdS4ghNE1pzjUs,16627
5
- ara_cli/ara_config.py,sha256=opSHjITVKz7M1gz1RKyYLMHeqBIbpdGSuNc9eQr4pw8,4080
6
- ara_cli/artefact.py,sha256=Hgtsj2LKBm93mWbw08c7FKDaH6Z6HOJ6UkTbIh5yLxQ,6083
7
- ara_cli/artefact_creator.py,sha256=psFVpP_YQpCUwCf5WkzY5yiCslzcFcBPWKLGYbz7iU0,6046
2
+ ara_cli/__main__.py,sha256=3fYaQUcudgjqtJa2gj2LoYnhy-Wy1OfZIfXEYQf4m0U,1806
3
+ ara_cli/analyse_artefacts.py,sha256=JwA2zxkCy8vNOHoU9f3TICJesXRRXndHi2hT5m_uQ8Q,4965
4
+ ara_cli/ara_command_action.py,sha256=5V5QnOYoLgvayym6CW2e0jJFc2HhKTZihHiysw9ZM48,18459
5
+ ara_cli/ara_command_parser.py,sha256=wbuPElD9GSDpaxHRH3yoyKaLAYsk6n9lE78jERD2zXg,16770
6
+ ara_cli/ara_config.py,sha256=3sbTY-NzLAL6augf06wLTh_5-exwM0dHVxqS_7dxWcg,4571
7
+ ara_cli/artefact_creator.py,sha256=s0hY8-X0EAwEfZvIRK1F67bW55tB-EvgnvH2gYNTGpY,6022
8
8
  ara_cli/artefact_deleter.py,sha256=Co4wwCH3yW8H9NrOq7_2p5571EeHr0TsfE-H8KqoOfY,1900
9
9
  ara_cli/artefact_fuzzy_search.py,sha256=sDxHKfg6P5TIiwznFgrMuMMhDp6EKElCbZsfflmkCww,1339
10
10
  ara_cli/artefact_link_updater.py,sha256=itMS_Z64jE8bBly9WA01z8PqkBeNW6ntTO7ryMeCTRg,3703
11
- ara_cli/artefact_lister.py,sha256=FxehJ8PCA8umEAKL_sBNbg0ezhftkhuMlz9tLn2OXUo,4625
12
- ara_cli/artefact_reader.py,sha256=FsP0Kfn_1MmVYW-9AEIoI6cA29ioFpp6SkOtcO7bvSg,4961
13
- ara_cli/artefact_renamer.py,sha256=u1DUu_VxpVZLUTZGFYHCA7JcQBd6j_JOCxpa8Qnjawk,4043
11
+ ara_cli/artefact_lister.py,sha256=jhk4n4eqp7hDIq07q43QzS7-36BM3OfZ4EABxCeOGcw,4764
12
+ ara_cli/artefact_reader.py,sha256=qNaMPWShmWtDU5LLdh9efFB27djI4NAoq6zEFwdTd38,6983
13
+ ara_cli/artefact_renamer.py,sha256=U0cwkR6j1KVjz1LRqiHa11sqFCSyi_GaG5AWJHoLOx0,4009
14
+ ara_cli/artefact_scan.py,sha256=DgFGv4hnbCjYdIgPA2PbAuGDWg1q2fCjtIqxGs57b9w,1762
14
15
  ara_cli/chat.py,sha256=MOJHRszQTUtBmGkOC96cIiXfkyGvrDkEirRagJEvm8U,28522
15
16
  ara_cli/classifier.py,sha256=zWskj7rBYdqYBGjksBm46iTgVU5IIf2PZsJr4qeiwVU,1878
16
17
  ara_cli/codefusionretriever.py,sha256=fCHgXdIBRzkVAnapX-KI2NQ44XbrrF4tEQmn5J6clUI,1980
17
18
  ara_cli/codehierachieretriever.py,sha256=Xd3EgEWWhkSf1TmTWtf8X5_YvyE_4B66nRrqarwSiTU,1182
18
19
  ara_cli/commandline_completer.py,sha256=b00Dqb5n7SecpxYIDLxAfYhp8X6e3c8a5qYz6ko0i3E,1192
19
20
  ara_cli/directory_navigator.py,sha256=6QbSAjJrJ5a6Lutol9J4HFgVDMiAQ672ny9TATrh04U,3318
20
- ara_cli/file_classifier.py,sha256=CkEMqvDOq0eEK5oKgN5ixro_AckmeUVR8CZ1crjP8M0,4874
21
+ ara_cli/file_classifier.py,sha256=rKgF2_tyxHUlpr_vclaZN1CKzidErRXzOng3SbSYR6Q,3903
21
22
  ara_cli/file_lister.py,sha256=VFpUmHU1d6sQvJWSeuFqkZZ0Ci3ZYCUtAUfvgWypaYU,2314
22
23
  ara_cli/filename_validator.py,sha256=Aw9PL8d5-Ymhp3EY6lDrUBk3cudaNqo1Uw5RzPpI1jA,118
23
24
  ara_cli/list_filter.py,sha256=Not17hIngI37gZsLtIKxopB-BmyWoOGlBzSqBwh-Zpc,5273
24
25
  ara_cli/output_suppressor.py,sha256=ZByUwLH2DxOb-eJ31KQbtIziBKdykoyxvwxZ0tSammA,371
25
26
  ara_cli/prompt_chat.py,sha256=kd_OINDQFit6jN04bb7mzgY259JBbRaTaNp9F-webkc,1346
26
- ara_cli/prompt_extractor.py,sha256=l5tvrl0RgirFzbrtCdMamkOudRnb1dqEiDaQYGZk-o8,7151
27
+ ara_cli/prompt_extractor.py,sha256=gidrCI8wTLfPL0ktqiXyPeGdQEB0S0sZegSOiF1Nn0Y,7358
27
28
  ara_cli/prompt_handler.py,sha256=PzHoIPTAWtRleOMtprhyYlFfo59S5T_kzHHkrwL-cNU,17155
28
29
  ara_cli/prompt_rag.py,sha256=vmlt4-rSboWibwgO_KUF79TK99YXT5KXjmbD9FeWdZY,7449
29
30
  ara_cli/run_file_lister.py,sha256=XbrrDTJXp1LFGx9Lv91SNsEHZPP-PyEMBF_P4btjbDA,2360
30
- ara_cli/tag_extractor.py,sha256=uKZnaxs85iYJ8litsw_sQSP60WorHKTX9_LyfGLv-dg,1428
31
+ ara_cli/tag_extractor.py,sha256=IlFOeWRhuojXc4qVgBlfU0SXqfL_UW_q_iBrC8pdL1U,948
31
32
  ara_cli/template_manager.py,sha256=YXPj2jGNDb-diIHFEK_vGJ-ZucodnXSGAPofKTnOofI,6633
32
33
  ara_cli/update_config_prompt.py,sha256=PZgNIN3dTw6p80GyX8Sp5apkAhSoykwnkEbHo3IOkUo,4571
33
- ara_cli/version.py,sha256=zJ9SWtTh14y7kCEXdMwGWiQs7lI5SKSZ9kxy02KbEnE,146
34
+ ara_cli/version.py,sha256=pkOflZPbtrSLZdm4j5Ws2p77G9Jo5_lAqkuvQ6g5RGs,146
34
35
  ara_cli/artefact_models/artefact_load.py,sha256=dNcwZDW2Dk0bts9YnPZ0ESmWD2NbsLIvl4Z-qQeGmTQ,401
35
36
  ara_cli/artefact_models/artefact_mapping.py,sha256=8aD0spBjkJ8toMAmFawc6UTUxB6-tEEViZXv2I-r88Q,1874
36
- ara_cli/artefact_models/artefact_model.py,sha256=QGHpw-nPMoW3gFrwWkdj5FNyZhd9JkJc4VLm0Fjb1vI,13934
37
+ ara_cli/artefact_models/artefact_model.py,sha256=ORnG8xKtK_hXuhfUXpiRBUV0QUUZNfR3wFSQU7oJiDo,14454
37
38
  ara_cli/artefact_models/artefact_templates.py,sha256=Vd7SwoRVKNGKZmxBKS6f9FE1ThUOCqZLScu0ClPfIu8,8321
38
39
  ara_cli/artefact_models/businessgoal_artefact_model.py,sha256=u9-Rr7VDYoNP6Vy2iKE64yAxDPOnrJJFozO6Ji9s8pI,4570
39
40
  ara_cli/artefact_models/capability_artefact_model.py,sha256=SZqHx4O2mj4urn77Stnj4_Jxtlq3-LgBBU9SMkByppI,3079
40
41
  ara_cli/artefact_models/epic_artefact_model.py,sha256=MuK6n0Tl0TM3364pH_j5R8XvwJZFyNwrZGCYaaqzxvs,5490
41
42
  ara_cli/artefact_models/example_artefact_model.py,sha256=UXrKbaPotg1jwcrVSdCeo-XH4tTD_-U1e3giaBn5_xg,1384
42
- ara_cli/artefact_models/feature_artefact_model.py,sha256=DkkFifgQIUyXnf5LK8vl9Id4cKm3mFMiShsP2EZHqy8,12816
43
+ ara_cli/artefact_models/feature_artefact_model.py,sha256=HuHLPZW4HptHhKaDHekobB29ZDWXqU4LXMHUP7gMIS8,12979
43
44
  ara_cli/artefact_models/issue_artefact_model.py,sha256=v6CpKnkqiUh6Wch2kkEmyyW49c8ysdy1qz8l1Ft9uJA,2552
44
45
  ara_cli/artefact_models/keyfeature_artefact_model.py,sha256=nkRNQyoJrDqmRxmqJZBQId6fNv6gI3EoKtXsI7BPqdY,3968
45
46
  ara_cli/artefact_models/task_artefact_model.py,sha256=kHMw_Tr-Ud3EeHWpRWy4jI0xFnPzGZ-FT52c5rSrT1k,3558
@@ -119,7 +120,7 @@ ara_cli/templates/prompt-modules/rules/product_owner.rules.md,sha256=NQYZ0JHOlss
119
120
  ara_cli/templates/prompt-modules/rules/python_behave.rules.md,sha256=0CG8S6W-lkLEu0zz2dFwxWCIgZM8QERlk4PCWybTMwA,1257
120
121
  ara_cli/templates/prompt-modules/rules/python_developer.rules.md,sha256=XkteyHS8wNdg4Kxtu45ca8q0kXUSBVEpDzqwNdis3fk,600
121
122
  ara_cli/templates/specification_breakdown_files/template.concept.exploration.md,sha256=Snti9j5CXMQb0799CQe-4MlLWTcathUVQQJWlvwPXBA,2117
122
- ara_cli/templates/specification_breakdown_files/template.concept.md,sha256=EfP2KnGmDL8LegrmocTEkAEkdHT7bNGL069b_A4rJ5A,893
123
+ ara_cli/templates/specification_breakdown_files/template.concept.md,sha256=tyAZojoQF0Xn4BEOtEsT1PZlpPsQSUGsojnvjTqbxks,587
123
124
  ara_cli/templates/specification_breakdown_files/template.customer.exploration.md,sha256=mMd66EPkoCzpJH24CfOD5xBrovsdDX6OA_zQi0u8P_g,2273
124
125
  ara_cli/templates/specification_breakdown_files/template.customer.md,sha256=gaIhWIfk41e8P5Gpi1PeyIw9MzhiWB7YUgrA5vq4v-w,1460
125
126
  ara_cli/templates/specification_breakdown_files/template.persona.exploration.md,sha256=CAJ195w07xWSkNvssgAa_c3ub2f_XCBW0bi_dTns0r8,4183
@@ -129,26 +130,26 @@ ara_cli/templates/specification_breakdown_files/template.step.md,sha256=nzDRl9Xo
129
130
  ara_cli/templates/specification_breakdown_files/template.technology.exploration.md,sha256=zQyiJcmbUfXdte-5uZwZUpT6ey0zwfZ00P4VwI97jQk,2274
130
131
  ara_cli/templates/specification_breakdown_files/template.technology.md,sha256=bySiksz-8xtq0Nnj4svqe2MgUftWrVkbK9AcrDUE3KY,952
131
132
  ara_cli/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
132
- ara_cli/tests/test_ara_command_action.py,sha256=1U3U8XY81k5rLOxnCE8Ty2Kh2ttOq07GQbZoz9VkJj8,20550
133
+ ara_cli/tests/test_ara_command_action.py,sha256=N7712HbmN86ziGBKI5GoHQPp75OSyD0kHsHRxna8d9w,25446
133
134
  ara_cli/tests/test_ara_config.py,sha256=1LWby_iSestTIIqK-1clggL8kmbGGbtlYfsxAHaMMF8,2232
134
- ara_cli/tests/test_artefact.py,sha256=xMouG-yf2PQoqt_9atdRtMS1t8QsVXj549G78ZCeFu8,12718
135
135
  ara_cli/tests/test_artefact_fuzzy_search.py,sha256=5Sh3_l9QK8-WHn6JpGPU1b6h4QEnl2JoMq1Tdp2cj1U,1261
136
136
  ara_cli/tests/test_artefact_link_updater.py,sha256=gN5KFF1uY7OoBh8Mr5jWpqXp02YCU5OSIpSU76Rm4Gs,2137
137
- ara_cli/tests/test_artefact_lister.py,sha256=LJu6DnmyOuLZev1Ej1NfnLM5xSoc3OmNNsZvdHeErSU,9142
138
- ara_cli/tests/test_artefact_reader.py,sha256=C3Vu6-NXO7p_z-_TbUwofJtFviJ6Jri34tNIfyWHsOg,4274
137
+ ara_cli/tests/test_artefact_lister.py,sha256=VCEOCgDgnAOeUUgIoGAbWgz60hf9UT-tdHg18LGfB34,22656
138
+ ara_cli/tests/test_artefact_reader.py,sha256=660K-d8ed-j8hulsUB_7baPD2-hhbg9TffUR5yVc4Uo,927
139
139
  ara_cli/tests/test_artefact_renamer.py,sha256=Dls9Z65h3HiG55Irki7aPOxoIxx8mfZTOqy5k2_Jbls,6155
140
+ ara_cli/tests/test_artefact_scan.py,sha256=m0V3HMLJtrOBXpJIRUI0D6MbHssgxDU_c935Wc3jatQ,4696
140
141
  ara_cli/tests/test_chat.py,sha256=VLQYsniaQI663xy8XFeoqczrVAoiln7tUm0yDjR1oGY,45727
141
142
  ara_cli/tests/test_classifier.py,sha256=grYGPksydNdPsaEBQxYHZTuTdcJWz7VQtikCKA6BNaQ,1920
142
143
  ara_cli/tests/test_directory_navigator.py,sha256=7G0MVrBbtBvbrFUpL0zb_9EkEWi1dulWuHsrQxMJxDY,140
143
- ara_cli/tests/test_file_classifier.py,sha256=C1sCcAIivENQrlxoYPq2_SZ806pgcQeIb8wOvyaAaow,8154
144
+ ara_cli/tests/test_file_classifier.py,sha256=6OYM-lYVYjxq4Qwl8U1btv_FYJhc5t3rKjYr2CXZ4uI,10069
144
145
  ara_cli/tests/test_file_creator.py,sha256=ssrl7gfU13H4ogrrX1BXx4WO4bQ7OG1R2tXZC1MP8EY,2004
145
146
  ara_cli/tests/test_file_lister.py,sha256=f6B_vIv-wAulKH2ZGgNg4SG79XqGGbfwoIvZlbEnYyM,4306
146
147
  ara_cli/tests/test_list_filter.py,sha256=gSRKirTtFuhRS3QlFHqWl89WvCvAdVEnFsCWTYmgB2o,7928
147
- ara_cli/tests/test_tag_extractor.py,sha256=zFSSBHOV9g4DkxCpC6RWHydEBm3BGF1EoV91ERRhSyU,2364
148
+ ara_cli/tests/test_tag_extractor.py,sha256=A4Usip4DrCS5iOGo8wYcTvIHJfN9V_yepYDjdCUyQNk,1729
148
149
  ara_cli/tests/test_template_manager.py,sha256=bRxka6cxHsCAOvXjfG8MrVO8qSZXhxW01tnph80UtNk,3143
149
150
  ara_cli/tests/test_update_config_prompt.py,sha256=vSsLvc18HZdVjVM93qXWVbJt752xTLL6VGjSVCrPufk,6729
150
- ara_cli-0.1.9.50.dist-info/METADATA,sha256=220dJeeM5TVPTFKMew7Mdno6oa1gCBy4CGr2pqfCn4Q,367
151
- ara_cli-0.1.9.50.dist-info/WHEEL,sha256=5sUXSg9e4bi7lTLOHcm6QEYwO5TIF1TNbTSVFVjcJcc,92
152
- ara_cli-0.1.9.50.dist-info/entry_points.txt,sha256=v4h7MzysTgSIDYfEo3oj4Kz_8lzsRa3hq-KJHEcLVX8,45
153
- ara_cli-0.1.9.50.dist-info/top_level.txt,sha256=zzee_PwFmKqfBi9XgIunP6xy2S4TIt593CLLxenNaAE,8
154
- ara_cli-0.1.9.50.dist-info/RECORD,,
151
+ ara_cli-0.1.9.52.dist-info/METADATA,sha256=LPiTn-w5P0D8PN2cLtTCMzBNK16r6yTHyyUUCIn7W3E,367
152
+ ara_cli-0.1.9.52.dist-info/WHEEL,sha256=5sUXSg9e4bi7lTLOHcm6QEYwO5TIF1TNbTSVFVjcJcc,92
153
+ ara_cli-0.1.9.52.dist-info/entry_points.txt,sha256=v4h7MzysTgSIDYfEo3oj4Kz_8lzsRa3hq-KJHEcLVX8,45
154
+ ara_cli-0.1.9.52.dist-info/top_level.txt,sha256=zzee_PwFmKqfBi9XgIunP6xy2S4TIt593CLLxenNaAE,8
155
+ ara_cli-0.1.9.52.dist-info/RECORD,,
ara_cli/artefact.py DELETED
@@ -1,172 +0,0 @@
1
- from __future__ import annotations
2
- from dataclasses import dataclass, field
3
- from typing import Literal, Optional
4
- from ara_cli.classifier import Classifier
5
- import re
6
- import os
7
-
8
- @dataclass
9
- class Artefact:
10
- classifier: Literal(Classifier.ordered_classifiers())
11
- name: str
12
- _content: str | None = None
13
- _parent: Artefact | None = field(init=False, default=None)
14
- _file_path: Optional[str] = None
15
- _tags: set[str] | None = None
16
-
17
- def assemble_content(self):
18
- def replace_parent(content):
19
- parent = self.parent
20
- if parent is None:
21
- return content
22
- parent_name = parent.name
23
- parent_classifier = parent.classifier
24
- parent_title = Classifier.get_artefact_title(parent_classifier)
25
- parent_string = f"{parent_name} {parent_title}"
26
-
27
- contribute_string = "Contributes to"
28
- illustrate_string = "Illustrates"
29
-
30
- regex_pattern = f'(?m)^(.*(?:{contribute_string}|{illustrate_string}))(.*)$'
31
-
32
- def replacement_function(match):
33
- return f"{match.group(1)} {parent_string}"
34
-
35
- def create_contributes(content):
36
- own_classifier_title = Classifier.get_artefact_title(self.classifier)
37
- own_title_line = f"{own_classifier_title}: {self.name}"
38
- contribution = contribute_string
39
- if self.classifier == 'example':
40
- contribution = illustrate_string
41
- parent_line = f"{contribution} {parent_string}"
42
- lines = content.splitlines()
43
- for i, line in enumerate(lines):
44
- if line.startswith(own_title_line):
45
- lines.insert(i + 1, "")
46
- lines.insert(i + 2, parent_line)
47
- break
48
- content = '\n'.join(lines)
49
- return content
50
-
51
- if not re.search(regex_pattern, content):
52
- return create_contributes(content)
53
-
54
- return re.sub(regex_pattern, replacement_function, content, count=1)
55
-
56
- def replace_tags(content):
57
- tag_set = self.tags
58
- if tag_set is None or not tag_set:
59
- return content
60
- tags = ' '.join(sorted([f'@{tag}' for tag in tag_set]))
61
-
62
- lines = content.splitlines()
63
- if lines and lines[0].startswith('@'):
64
- lines[0] = tags
65
- return '\n'.join(lines)
66
- lines.insert(0, tags)
67
- return '\n'.join(lines)
68
-
69
- content = self.content
70
- content = replace_tags(content)
71
- content = replace_parent(content)
72
- self._content = content
73
-
74
- @property
75
- def file_name(self) -> str:
76
- basename = os.path.basename(self.file_path)
77
- return os.path.splitext(basename)[0]
78
-
79
- @property
80
- def content(self) -> str:
81
- if self._content is not None:
82
- return self._content
83
- with open(self.file_path, 'r') as file:
84
- self._content = file.read()
85
- return self._content
86
-
87
- @property
88
- def parent(self) -> Artefact | None:
89
- if self._parent is not None:
90
- return self._parent
91
-
92
- if self.content is None:
93
- with open(self.file_path, 'r') as file:
94
- self.content = file.read()
95
-
96
- artefact_titles = Classifier.artefact_titles()
97
- title_segment = '|'.join(artefact_titles)
98
-
99
- regex_pattern = rf'(?:Contributes to|Illustrates)\s*:*\s*(.*)\s+({title_segment}).*'
100
- regex = re.compile(regex_pattern)
101
- match = re.search(regex, self.content)
102
-
103
- if match:
104
- parent_name = match.group(1).strip()
105
- parent_name = parent_name.replace(' ', '_')
106
- parent_title = match.group(2).strip()
107
- parent_type = Classifier.get_artefact_classifier(parent_title)
108
- self._parent = Artefact(classifier=parent_type, name=parent_name)
109
-
110
- return self._parent
111
-
112
- @property
113
- def file_path(self) -> str:
114
- if self._file_path is None:
115
- sub_directory = Classifier.get_sub_directory(self.classifier)
116
- underscore_name = self.name.replace(' ', '_')
117
- self._file_path = f"{sub_directory}/{underscore_name}.{self.classifier}"
118
- return self._file_path
119
-
120
- @property
121
- def tags(self) -> set[str]:
122
- if self._tags is not None:
123
- return self._tags
124
-
125
- if self.content is None:
126
- return set()
127
-
128
- lines = self.content.splitlines()
129
- first_line = lines[0].strip() if lines else ""
130
-
131
- if not first_line.startswith('@'):
132
- self._tags = set()
133
- return self._tags
134
-
135
- self._tags = {tag[1:] for tag in first_line.split() if tag.startswith('@')}
136
- return self._tags
137
-
138
- @classmethod
139
- def from_content(cls, content: str, file_path: str | None = None) -> Artefact:
140
- """
141
- Create an Artefact object from the given content.
142
- """
143
- error_message = "Content does not contain valid artefact information"
144
-
145
- if content is None:
146
- raise ValueError(error_message)
147
-
148
- artefact_titles = Classifier.artefact_titles()
149
- title_segment = '|'.join(artefact_titles)
150
-
151
- regex_pattern = rf'({title_segment})\s*:*\s*(.*)\s*'
152
- regex = re.compile(regex_pattern)
153
- match = re.search(regex, content)
154
-
155
- if not match:
156
- raise ValueError(error_message)
157
-
158
- title = match.group(1).strip()
159
- classifier = Classifier.get_artefact_classifier(title)
160
- name = match.group(2).strip()
161
-
162
- return cls(classifier=classifier, name=name, _content=content, _file_path=file_path)
163
-
164
- def write_to_file(self):
165
- if self.content is None:
166
- raise ValueError("Artefact object does not contain content information")
167
- self.assemble_content()
168
- file_path = self.file_path
169
- data_directory = f"{os.path.splitext(file_path)[0]}.data"
170
- os.makedirs(data_directory, exist_ok=True)
171
- with open(self.file_path, 'w') as file:
172
- file.write(self.content)
@@ -1,304 +0,0 @@
1
- import pytest
2
- import os
3
- from unittest.mock import patch, MagicMock, mock_open
4
- from ara_cli.artefact import Artefact
5
-
6
- mock_artefact_titles = ['Document', 'Report']
7
- mock_ordered_classifiers = ['Document', 'Report']
8
- mock_sub_directories = {
9
- 'Document': 'documents',
10
- 'Report': 'reports'
11
- }
12
-
13
-
14
- @pytest.fixture
15
- def mock_classifier():
16
- with patch('ara_cli.artefact.Classifier') as MockClassifier:
17
- MockClassifier.artefact_titles.return_value = mock_artefact_titles
18
- MockClassifier.ordered_classifiers.return_value = mock_ordered_classifiers
19
- MockClassifier.get_artefact_classifier.side_effect = lambda x: 'Type1' if x == 'Document' else 'Type2'
20
- MockClassifier.get_sub_directory.side_effect = lambda x: mock_sub_directories[x]
21
- yield MockClassifier
22
-
23
-
24
- @pytest.mark.parametrize(
25
- "classifier, name, content, expected_content",
26
- [
27
- ('Document', 'Test Artefact', 'Document: Test Artefact\nSome content',
28
- 'Document: Test Artefact\n\nContributes to Parent_Artefact Document\nSome content'),
29
-
30
- ('Document', 'Test Artefact', '@a_tag\nDocument: Test Artefact\nSome content',
31
- '@a_tag\nDocument: Test Artefact\n\nContributes to Parent_Artefact Document\nSome content'),
32
-
33
- ('example', 'Test Artefact', 'Example: Test Artefact\nSome content',
34
- 'Example: Test Artefact\n\nIllustrates Parent_Artefact Document\nSome content'),
35
-
36
- ('Document', 'Test Artefact', 'Some content without title line',
37
- 'Some content without title line'),
38
- ]
39
- )
40
- def test_create_contributes(mock_classifier, classifier, name, content, expected_content):
41
- artefact = Artefact(classifier=classifier, name=name, _content=content)
42
-
43
- with patch.object(Artefact, 'parent', new_callable=MagicMock(return_value=Artefact('Document', 'Parent_Artefact'))), \
44
- patch('ara_cli.artefact.Classifier.get_artefact_title', side_effect=lambda x: 'Document' if x == 'Document' else 'Example'):
45
-
46
- artefact.assemble_content()
47
- assert artefact._content == expected_content
48
-
49
-
50
- @pytest.mark.parametrize(
51
- "initial_content, parent, expected_content",
52
- [
53
- ("Contributes to Child Artefact", Artefact('Type1', 'Parent_Artefact'), "Contributes to Parent_Artefact Document"),
54
- ("Contributes to: Child Artefact", Artefact('Type1', 'Parent_Artefact'), "Contributes to Parent_Artefact Document"),
55
- ("Illustrates Child Artefact", Artefact('Type1', 'Parent_Artefact'), "Illustrates Parent_Artefact Document"),
56
- ("Illustrates: Child Artefact", Artefact('Type1', 'Parent_Artefact'), "Illustrates Parent_Artefact Document"),
57
- ("Contributes to Child Artefact", None, "Contributes to Child Artefact"),
58
- ("Illustrates Child Artefact", None, "Illustrates Child Artefact")
59
- ]
60
- )
61
- def test_assemble_content_replace_parent(mock_classifier, initial_content, parent, expected_content):
62
- artefact = Artefact(classifier='Document', name='Test Artefact', _content=initial_content)
63
-
64
- with patch.object(Artefact, 'parent', new_callable=MagicMock(return_value=parent)), \
65
- patch('ara_cli.artefact.Classifier.get_artefact_title', return_value='Document'):
66
- artefact.assemble_content()
67
- assert artefact._content == expected_content
68
-
69
-
70
- @pytest.mark.parametrize(
71
- "initial_content, initial_tags, expected_content",
72
- [
73
- ("Some content", {'tag1', 'tag2'}, "@tag1 @tag2\nSome content"),
74
- ("@oldtag\nContent", {'newtag'}, "@newtag\nContent"),
75
- ("Content without tags", set(), "Content without tags"),
76
- ]
77
- )
78
- def test_assemble_content_replace_tags(mock_classifier, initial_content, initial_tags, expected_content):
79
- artefact = Artefact(classifier='Document', name='Test Artefact', _content=initial_content)
80
- artefact._tags = initial_tags
81
-
82
- with patch.object(Artefact, 'parent', new_callable=MagicMock(return_value=None)):
83
- artefact.assemble_content()
84
- assert artefact._content == expected_content
85
-
86
- @pytest.mark.parametrize(
87
- "initial_content, parent, initial_tags, expected_content",
88
- [
89
- ("Contributes to Child Artefact", Artefact('Type1', 'Parent_Artefact'), {'tag1'}, "@tag1\nContributes to Parent_Artefact Document"),
90
- ("@oldtag\nIllustrates Child Artefact", Artefact('Type1', 'Parent_Artefact'), {'newtag'}, "@newtag\nIllustrates Parent_Artefact Document"),
91
- ("Content without parent", None, {'tag1', 'tag2'}, "@tag1 @tag2\nContent without parent"),
92
- ]
93
- )
94
- def test_assemble_content_full(mock_classifier, initial_content, parent, initial_tags, expected_content):
95
- artefact = Artefact(classifier='Document', name='Test Artefact', _content=initial_content)
96
- artefact._tags = initial_tags
97
-
98
- with patch.object(Artefact, 'parent', new_callable=MagicMock(return_value=parent)), \
99
- patch('ara_cli.artefact.Classifier.get_artefact_title', return_value='Document'):
100
- artefact.assemble_content()
101
- assert artefact._content == expected_content
102
-
103
-
104
- @pytest.mark.parametrize(
105
- "content, expected_parent",
106
- [
107
- ("Contributes to: Parent Artefact Document", Artefact('Type1', 'Parent_Artefact')),
108
- ("Contributes to Parent Report", Artefact('Type2', 'Parent')),
109
- ("No parent defined here", None),
110
- ("", None),
111
- ]
112
- )
113
- def test_parent_property(mock_classifier, content, expected_parent):
114
- artefact = Artefact(classifier='Document', name='Test Artefact', _content=content)
115
-
116
- parent = artefact.parent
117
-
118
- if expected_parent is None:
119
- assert parent is None
120
- else:
121
- assert parent is not None
122
- assert parent.name == expected_parent.name
123
- assert parent.classifier == expected_parent.classifier
124
-
125
-
126
- @pytest.mark.parametrize(
127
- "initial_parent, expected_parent",
128
- [
129
- (Artefact('Document', 'Existing Parent'), Artefact('Document', 'Existing Parent')),
130
- ]
131
- )
132
- def test_parent_property_initial_parent(mock_classifier, initial_parent, expected_parent):
133
- artefact = Artefact(classifier='Document', name='Test Artefact', _content="Contributes to: New Parent Document")
134
- artefact._parent = initial_parent # Directly set _parent to simulate pre-existing condition
135
-
136
- parent = artefact.parent
137
-
138
- assert parent is not None
139
- assert parent.name == expected_parent.name
140
- assert parent.classifier == expected_parent.classifier
141
-
142
-
143
- @pytest.mark.parametrize(
144
- "classifier, name, expected_file_path",
145
- [
146
- ('Document', 'Test Artefact', 'documents/Test_Artefact.Document'),
147
- ('Report', 'Another Report', 'reports/Another_Report.Report'),
148
- ('Document', 'Report with spaces', 'documents/Report_with_spaces.Document'),
149
- ]
150
- )
151
- def test_file_path_property(mock_classifier, classifier, name, expected_file_path):
152
- artefact = Artefact(classifier=classifier, name=name)
153
- file_path = artefact.file_path
154
- assert file_path == expected_file_path
155
-
156
-
157
- @pytest.mark.parametrize(
158
- "content, expected_tags",
159
- [
160
- ("@tag1 @tag2 Some content here", {'tag1', 'tag2'}),
161
- ("@singleTag Content follows", {'singleTag'}),
162
- ("No tags in this content", set()),
163
- ("", set()),
164
- ("@mixedCase @AnotherTag @123numeric", {'mixedCase', 'AnotherTag', '123numeric'}),
165
- (" @leadingSpaceTag @another ", {'leadingSpaceTag', 'another'}),
166
- ("Not a tag @notatag", set()),
167
- ]
168
- )
169
- def test_tags_property(mock_classifier, content, expected_tags):
170
- artefact = Artefact(classifier='Document', name='Test Artefact', _content=content)
171
- tags = artefact.tags
172
- assert tags == expected_tags
173
-
174
-
175
- @pytest.mark.parametrize(
176
- "initial_tags, content, expected_tags",
177
- [
178
- ({'preExistingTag'}, "@tag1 @tag2", {'preExistingTag'}),
179
- (None, "@tag1 @tag2", {'tag1', 'tag2'}),
180
- ({'anotherTag'}, "", {'anotherTag'}),
181
- (set(), "No tags in this content", set()),
182
- ]
183
- )
184
- def test_tags_property_when_tags_pre_set(mock_classifier, initial_tags, content, expected_tags):
185
- artefact = Artefact(classifier='Document', name='Test Artefact', _content=content)
186
- artefact._tags = initial_tags # Directly set _tags to simulate pre-existing condition
187
-
188
- tags = artefact.tags
189
-
190
- assert tags == expected_tags
191
-
192
-
193
- def test_content_property_reads_file(mock_classifier):
194
- artefact = Artefact(classifier='Document', name='Test Artefact')
195
- mock_file_content = "This is the file content."
196
-
197
- # Mock the open function within the specific context
198
- with patch("builtins.open", mock_open(read_data=mock_file_content)):
199
- content = artefact.content
200
-
201
- assert content == mock_file_content
202
-
203
- def test_content_property_caches_content(mock_classifier):
204
- artefact = Artefact(classifier='Document', name='Test Artefact')
205
- mock_file_content = "This is the file content."
206
-
207
- # Mock the open function within the specific context
208
- with patch("builtins.open", mock_open(read_data=mock_file_content)) as mocked_open:
209
- content_first_call = artefact.content
210
- content_second_call = artefact.content
211
-
212
- # Ensure the file is only read once
213
- mocked_open.assert_called_once_with(artefact.file_path, 'r')
214
- assert content_first_call == mock_file_content
215
- assert content_second_call == mock_file_content
216
-
217
- def test_content_property_with_existing_content(mock_classifier):
218
- existing_content = "Existing content should be returned."
219
- artefact = Artefact(classifier='Document', name='Test Artefact', _content=existing_content)
220
-
221
- with patch("builtins.open", mock_open()) as mocked_open:
222
- content = artefact.content
223
-
224
- # Ensure that the file is never opened because _content is already set
225
- mocked_open.assert_not_called()
226
- assert content == existing_content
227
-
228
-
229
- @pytest.mark.parametrize(
230
- "content, expected_classifier, expected_name",
231
- [
232
- ("Document: Parent Artefact", 'Type1', 'Parent Artefact'),
233
- ("Report: Another Report", 'Type2', 'Another Report')
234
- ]
235
- )
236
- def test_from_content_valid(mock_classifier, content, expected_classifier, expected_name):
237
- artefact = Artefact.from_content(content)
238
- assert artefact.classifier == expected_classifier
239
- assert artefact.name == expected_name
240
- assert artefact.content == content
241
-
242
-
243
- @pytest.mark.parametrize(
244
- "content",
245
- [
246
- "Invalid content without proper structure",
247
- "Classifier: Name: Missing title",
248
- "",
249
- None,
250
- ]
251
- )
252
- def test_from_content_invalid(mock_classifier, content):
253
- with pytest.raises(ValueError, match="Content does not contain valid artefact information"):
254
- Artefact.from_content(content)
255
-
256
-
257
- @pytest.mark.parametrize(
258
- "content, should_raise_error",
259
- [
260
- ("Some valid content", False), # Content is valid, should not raise
261
- ]
262
- )
263
- def test_write_to_file_content_check(mock_classifier, content, should_raise_error):
264
- artefact = Artefact(classifier='Document', name='Test Artefact', _content=content)
265
- if should_raise_error:
266
- with pytest.raises(ValueError, match="Artefact object does not contain content information"):
267
- artefact.write_to_file()
268
- else:
269
- with patch('builtins.open', mock_open()) as mocked_file, \
270
- patch('os.makedirs') as mocked_makedirs, \
271
- patch.object(artefact, 'assemble_content') as mocked_assemble_content:
272
- artefact.write_to_file()
273
- mocked_assemble_content.assert_called_once()
274
- mocked_makedirs.assert_called_once_with('documents/Test_Artefact.data', exist_ok=True)
275
- mocked_file.assert_called_once_with('documents/Test_Artefact.Document', 'w')
276
- mocked_file().write.assert_called_once_with(content)
277
-
278
-
279
- @pytest.mark.parametrize(
280
- "file_path",
281
- [
282
- ('documents/Test_Artefact.Document'),
283
- ('reports/Another_Report.Report')
284
- ]
285
- )
286
- def test_write_to_file_directory_creation(mock_classifier, file_path):
287
- artefact = Artefact(classifier='Document', name='Test Artefact', _content="Some content")
288
- artefact._file_path = file_path # Directly set file path for testing
289
- with patch('os.makedirs') as mocked_makedirs, \
290
- patch('builtins.open', mock_open()):
291
- artefact.write_to_file()
292
- data_directory = f"{os.path.splitext(file_path)[0]}.data"
293
- mocked_makedirs.assert_called_once_with(data_directory, exist_ok=True)
294
-
295
-
296
- def test_write_to_file_writes_content(mock_classifier):
297
- content = "Some valid content"
298
- artefact = Artefact(classifier='Document', name='Test Artefact', _content=content)
299
- with patch('builtins.open', mock_open()) as mocked_file, \
300
- patch('os.makedirs'), \
301
- patch.object(Artefact, 'assemble_content'):
302
- artefact.write_to_file()
303
- mocked_file.assert_called_once_with('documents/Test_Artefact.Document', 'w')
304
- mocked_file().write.assert_called_once_with(content)