pyegeria 5.3.9.3__py3-none-any.whl → 5.3.9.5__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.
- pyegeria/_globals.py +2 -1
- pyegeria/collection_manager_omvs.py +324 -61
- pyegeria/data_designer_omvs.py +4944 -0
- pyegeria/glossary_browser_omvs.py +2 -2
- pyegeria/md_processing/__init__.py +51 -0
- pyegeria/md_processing/commands/__init__.py +3 -0
- pyegeria/md_processing/commands/blueprint_commands.py +307 -0
- pyegeria/md_processing/commands/category_commands.py +242 -0
- pyegeria/md_processing/commands/glossary_commands.py +225 -0
- pyegeria/md_processing/commands/project_commands.py +169 -0
- pyegeria/md_processing/commands/term_commands.py +524 -0
- pyegeria/md_processing/utils/__init__.py +3 -0
- pyegeria/md_processing/utils/common_utils.py +101 -0
- pyegeria/md_processing/utils/display_utils.py +53 -0
- pyegeria/md_processing/utils/extraction_utils.py +177 -0
- pyegeria/md_processing/utils/validation_utils.py +208 -0
- pyegeria/mermaid_utilities.py +3 -2
- {pyegeria-5.3.9.3.dist-info → pyegeria-5.3.9.5.dist-info}/METADATA +1 -1
- {pyegeria-5.3.9.3.dist-info → pyegeria-5.3.9.5.dist-info}/RECORD +22 -9
- {pyegeria-5.3.9.3.dist-info → pyegeria-5.3.9.5.dist-info}/LICENSE +0 -0
- {pyegeria-5.3.9.3.dist-info → pyegeria-5.3.9.5.dist-info}/WHEEL +0 -0
- {pyegeria-5.3.9.3.dist-info → pyegeria-5.3.9.5.dist-info}/entry_points.txt +0 -0
@@ -52,7 +52,7 @@ class GlossaryBrowser(Client):
|
|
52
52
|
"""
|
53
53
|
Creates a preamble string and an elements action based on the given object type, search string,
|
54
54
|
and output format. The preamble provides a descriptive header based on the intent: To make a form,
|
55
|
-
a report, or unadorned
|
55
|
+
a report, or unadorned Markdown. The element action specifies the action to be taken on the object type.
|
56
56
|
|
57
57
|
Args:
|
58
58
|
obj_type: The type of object being updated or reported on (e.g., "Product", "Category").
|
@@ -2677,7 +2677,7 @@ class GlossaryBrowser(Client):
|
|
2677
2677
|
# Process each term element
|
2678
2678
|
for element in term_elements:
|
2679
2679
|
# Extract relationship type from the relationship header
|
2680
|
-
relationship_type = element['
|
2680
|
+
relationship_type = element['relatedBy']['relationshipHeader']['type']['typeName']
|
2681
2681
|
|
2682
2682
|
# Extract related term information
|
2683
2683
|
related_term = {
|
@@ -0,0 +1,51 @@
|
|
1
|
+
"""
|
2
|
+
This package contains functions to parse and process Egeria Markdown (Freddie)
|
3
|
+
"""
|
4
|
+
|
5
|
+
# Re-export all functions from the original md_processing_utils.py to maintain backward compatibility
|
6
|
+
from pyegeria.md_processing.utils.common_utils import (
|
7
|
+
render_markdown, is_valid_iso_date, set_debug_level, get_current_datetime_string, print_msg,
|
8
|
+
ALWAYS, ERROR, INFO, WARNING, pre_command, command_seperator, EXISTS_REQUIRED,
|
9
|
+
EGERIA_WIDTH, console, message_types, debug_level
|
10
|
+
)
|
11
|
+
|
12
|
+
from pyegeria.md_processing.utils.extraction_utils import (
|
13
|
+
extract_command_plus, extract_command, extract_attribute, process_simple_attribute, process_name_list
|
14
|
+
)
|
15
|
+
|
16
|
+
from pyegeria.md_processing.utils.validation_utils import (
|
17
|
+
process_element_identifiers, get_element_by_name, update_a_command
|
18
|
+
)
|
19
|
+
|
20
|
+
from pyegeria.md_processing.utils.display_utils import (
|
21
|
+
GLOSSARY_NAME_LABELS, CATEGORY_NAME_LABELS, PARENT_CATEGORY_LABELS, CHILD_CATEGORY_LABELS,
|
22
|
+
TERM_NAME_LABELS, PROJECT_NAME_LABELS, BLUEPRINT_NAME_LABELS, COMPONENT_NAME_LABELS,
|
23
|
+
SOLUTION_ROLE_LABELS, SOLUTION_ACTOR_ROLE_LABELS, SOLUTION_LINKING_ROLE_LABELS,
|
24
|
+
OUTPUT_LABELS, SEARCH_LABELS, GUID_LABELS, ELEMENT_OUTPUT_FORMATS, TERM_RELATIONSHPS,
|
25
|
+
command_list
|
26
|
+
)
|
27
|
+
|
28
|
+
from pyegeria.md_processing.commands.glossary_commands import (
|
29
|
+
process_glossary_upsert_command, process_glossary_list_command, process_glossary_structure_command
|
30
|
+
)
|
31
|
+
|
32
|
+
from pyegeria.md_processing.commands.category_commands import (
|
33
|
+
process_category_upsert_command, update_category_parent, process_category_list_command
|
34
|
+
)
|
35
|
+
|
36
|
+
from pyegeria.md_processing.commands.term_commands import (
|
37
|
+
update_term_categories, process_term_upsert_command, process_create_term_term_relationship_command,
|
38
|
+
process_term_list_command, process_term_details_command, process_term_history_command,
|
39
|
+
process_term_revision_history_command
|
40
|
+
)
|
41
|
+
|
42
|
+
from pyegeria.md_processing.commands.project_commands import (
|
43
|
+
process_per_proj_upsert_command
|
44
|
+
)
|
45
|
+
|
46
|
+
from pyegeria.md_processing.commands.blueprint_commands import (
|
47
|
+
process_blueprint_upsert_command, process_solution_component_upsert_command
|
48
|
+
)
|
49
|
+
|
50
|
+
# Also include process_provenance_command which doesn't fit neatly into any category
|
51
|
+
from pyegeria.md_processing.utils.common_utils import process_provenance_command
|
@@ -0,0 +1,307 @@
|
|
1
|
+
"""
|
2
|
+
This file contains blueprint/solution-related command functions for processing Egeria Markdown
|
3
|
+
"""
|
4
|
+
from typing import Optional
|
5
|
+
|
6
|
+
from rich.markdown import Markdown
|
7
|
+
|
8
|
+
from pyegeria.egeria_tech_client import EgeriaTech
|
9
|
+
from pyegeria.md_processing.utils.common_utils import (
|
10
|
+
debug_level, print_msg, ALWAYS, ERROR, INFO, WARNING, pre_command, command_seperator, EXISTS_REQUIRED
|
11
|
+
)
|
12
|
+
from pyegeria.md_processing.utils.extraction_utils import (
|
13
|
+
extract_command_plus, extract_command, process_simple_attribute, process_name_list
|
14
|
+
)
|
15
|
+
from pyegeria.md_processing.utils.validation_utils import (
|
16
|
+
process_element_identifiers, update_a_command
|
17
|
+
)
|
18
|
+
from pyegeria.md_processing.utils.display_utils import (
|
19
|
+
BLUEPRINT_NAME_LABELS, COMPONENT_NAME_LABELS, SOLUTION_ROLE_LABELS, SOLUTION_ACTOR_ROLE_LABELS,
|
20
|
+
SOLUTION_LINKING_ROLE_LABELS, OUTPUT_LABELS, ELEMENT_OUTPUT_FORMATS, SEARCH_LABELS
|
21
|
+
)
|
22
|
+
from pyegeria.dr_egeria_state import update_element_dictionary
|
23
|
+
|
24
|
+
def process_blueprint_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
|
25
|
+
"""
|
26
|
+
Processes a solution blueprint create or update command by extracting key attributes such as
|
27
|
+
blueprint name, description, and usage from the given text.
|
28
|
+
|
29
|
+
:param txt: A string representing the input cell to be processed for
|
30
|
+
extracting blueprint-related attributes.
|
31
|
+
:param directive: an optional string indicating the directive to be used - display, validate or execute
|
32
|
+
:return: A string summarizing the outcome of the processing.
|
33
|
+
"""
|
34
|
+
from pyegeria.md_processing.utils.common_utils import set_debug_level
|
35
|
+
|
36
|
+
command, object_type, object_action = extract_command_plus(txt)
|
37
|
+
set_debug_level(directive)
|
38
|
+
|
39
|
+
blueprint_name = process_simple_attribute(txt, BLUEPRINT_NAME_LABELS, ERROR)
|
40
|
+
print(Markdown(f"{pre_command} `{object_action}` `{object_type}` for blueprint: `\'{blueprint_name}\'` with directive: `{directive}` "))
|
41
|
+
description = process_simple_attribute(txt, ['Description'], INFO)
|
42
|
+
usage = process_simple_attribute(txt, ['Usage'], INFO)
|
43
|
+
q_name = process_simple_attribute(txt, ['Qualified Name'], INFO)
|
44
|
+
valid = True
|
45
|
+
|
46
|
+
if blueprint_name is None:
|
47
|
+
valid = False
|
48
|
+
known_q_name = None
|
49
|
+
known_guid = None
|
50
|
+
blueprint_exists = False
|
51
|
+
else:
|
52
|
+
element_labels = BLUEPRINT_NAME_LABELS
|
53
|
+
element_labels.append('Display Name')
|
54
|
+
known_q_name, known_guid, valid, blueprint_exists = process_element_identifiers(egeria_client, object_type,
|
55
|
+
element_labels, txt,
|
56
|
+
object_action, None)
|
57
|
+
|
58
|
+
blueprint_display = (f"\n* Command: `{command}`\n\t* Blueprint Name: {blueprint_name}\n\t"
|
59
|
+
f"* Description: {description}\n\t* Usage: {usage}\n")
|
60
|
+
|
61
|
+
if object_action == 'Update':
|
62
|
+
guid = process_simple_attribute(txt, ['GUID', 'guid', 'Guid'])
|
63
|
+
blueprint_display += f"* Qualified Name: `{q_name}`\n\t* GUID: {guid}\n\n"
|
64
|
+
if not blueprint_exists:
|
65
|
+
msg = f"Blueprint can't be updated; `{blueprint_name}` not found"
|
66
|
+
print_msg("ERROR", msg, debug_level)
|
67
|
+
valid = False
|
68
|
+
else:
|
69
|
+
msg = f"Blueprint can be updated; `{blueprint_name}` found"
|
70
|
+
print_msg(ALWAYS, msg, debug_level)
|
71
|
+
|
72
|
+
elif object_action == "Create":
|
73
|
+
if blueprint_exists:
|
74
|
+
msg = f"Blueprint `{blueprint_name}` can't be created because it already exists.\n"
|
75
|
+
print_msg("ERROR", msg, debug_level)
|
76
|
+
valid = False
|
77
|
+
elif valid:
|
78
|
+
msg = f"It is valid to create Blueprint `{blueprint_name}` with:\n"
|
79
|
+
print_msg("ALWAYS", msg, debug_level)
|
80
|
+
|
81
|
+
if directive == "display":
|
82
|
+
print(Markdown(blueprint_display))
|
83
|
+
return None
|
84
|
+
|
85
|
+
elif directive == "validate":
|
86
|
+
if valid:
|
87
|
+
print(Markdown(blueprint_display))
|
88
|
+
else:
|
89
|
+
msg = f"Validation failed for Blueprint `{blueprint_name}`\n"
|
90
|
+
print_msg(ERROR, msg, debug_level)
|
91
|
+
print(Markdown(blueprint_display))
|
92
|
+
|
93
|
+
return valid
|
94
|
+
|
95
|
+
elif directive == "process":
|
96
|
+
if valid:
|
97
|
+
print(Markdown(blueprint_display))
|
98
|
+
else:
|
99
|
+
if blueprint_exists and object_action == "Create":
|
100
|
+
msg = f"Create failed because blueprint `{blueprint_name}` exists - changing `Create` to `Update` in processed output \n"
|
101
|
+
print_msg(ERROR, msg, debug_level)
|
102
|
+
print(Markdown(blueprint_display))
|
103
|
+
return update_a_command(txt, command, object_type, known_q_name, known_guid)
|
104
|
+
else:
|
105
|
+
return None
|
106
|
+
|
107
|
+
if object_action == "Update":
|
108
|
+
if not blueprint_exists:
|
109
|
+
print(f"\n{ERROR}Blueprint `{blueprint_name}` does not exist! Updating result document with Create "
|
110
|
+
f"command\n")
|
111
|
+
return update_a_command(txt, command, object_type, known_q_name, known_guid)
|
112
|
+
|
113
|
+
body = {
|
114
|
+
"class": "ReferenceableRequestBody", "elementProperties": {
|
115
|
+
"class": "SolutionBlueprintProperties", "qualifiedName": known_q_name, "description": description,
|
116
|
+
"usage": usage
|
117
|
+
}
|
118
|
+
}
|
119
|
+
egeria_client.update_solution_blueprint(known_guid, body)
|
120
|
+
print_msg(ALWAYS, f"Updated Blueprint `{blueprint_name}` with GUID {known_guid}", debug_level)
|
121
|
+
update_element_dictionary(known_q_name, {
|
122
|
+
'guid': known_guid, 'display_name': blueprint_name
|
123
|
+
})
|
124
|
+
return egeria_client.get_solution_blueprint_by_guid(known_guid, output_format='MD')
|
125
|
+
|
126
|
+
elif object_action == "Create":
|
127
|
+
if blueprint_exists:
|
128
|
+
print(f"\nBlueprint `{blueprint_name}` already exists and result document updated\n")
|
129
|
+
return update_a_command(txt, command, object_type, known_q_name, known_guid)
|
130
|
+
else:
|
131
|
+
blueprint_guid = egeria_client.create_solution_blueprint(blueprint_name, description, usage)
|
132
|
+
if blueprint_guid:
|
133
|
+
print_msg(ALWAYS, f"Created Blueprint `{blueprint_name}` with GUID {blueprint_guid}", debug_level)
|
134
|
+
return egeria_client.get_solution_blueprint_by_guid(blueprint_guid, output_format='MD')
|
135
|
+
else:
|
136
|
+
print_msg(ERROR, f"Failed to create Blueprint `{blueprint_name}`", debug_level)
|
137
|
+
return None
|
138
|
+
|
139
|
+
|
140
|
+
def process_solution_component_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
|
141
|
+
"""
|
142
|
+
Processes a solution component create or update command by extracting key attributes such as
|
143
|
+
component name, description, and parent components from the given text.
|
144
|
+
|
145
|
+
:param txt: A string representing the input cell to be processed for
|
146
|
+
extracting component-related attributes.
|
147
|
+
:param directive: an optional string indicating the directive to be used - display, validate or execute
|
148
|
+
:return: A string summarizing the outcome of the processing.
|
149
|
+
"""
|
150
|
+
from pyegeria.md_processing.utils.common_utils import set_debug_level
|
151
|
+
|
152
|
+
command, object_type, object_action = extract_command_plus(txt)
|
153
|
+
set_debug_level(directive)
|
154
|
+
|
155
|
+
component_name = process_simple_attribute(txt, COMPONENT_NAME_LABELS, ERROR)
|
156
|
+
print(Markdown(f"{pre_command} `{object_action}` `{object_type}` for component: `\'{component_name}\'` with directive: `{directive}` "))
|
157
|
+
description = process_simple_attribute(txt, ['Description'], INFO)
|
158
|
+
q_name = process_simple_attribute(txt, ['Qualified Name'], INFO)
|
159
|
+
valid = True
|
160
|
+
|
161
|
+
if component_name is None:
|
162
|
+
valid = False
|
163
|
+
known_q_name = None
|
164
|
+
known_guid = None
|
165
|
+
component_exists = False
|
166
|
+
else:
|
167
|
+
element_labels = COMPONENT_NAME_LABELS
|
168
|
+
element_labels.append('Display Name')
|
169
|
+
known_q_name, known_guid, valid, component_exists = process_element_identifiers(egeria_client, object_type,
|
170
|
+
element_labels, txt,
|
171
|
+
object_action, None)
|
172
|
+
|
173
|
+
# Get the blueprint this component is in
|
174
|
+
blueprint_name = process_simple_attribute(txt, BLUEPRINT_NAME_LABELS)
|
175
|
+
if blueprint_name:
|
176
|
+
known_blueprint_q_name, known_blueprint_guid, blueprint_valid, blueprint_exists = process_element_identifiers(
|
177
|
+
egeria_client, "Solution Blueprint", BLUEPRINT_NAME_LABELS, txt, EXISTS_REQUIRED, None)
|
178
|
+
if not blueprint_exists:
|
179
|
+
valid = False
|
180
|
+
else:
|
181
|
+
known_blueprint_q_name = None
|
182
|
+
known_blueprint_guid = None
|
183
|
+
blueprint_valid = True
|
184
|
+
blueprint_exists = False
|
185
|
+
|
186
|
+
# Get the parent components if specified
|
187
|
+
parent_components = process_simple_attribute(txt, ['Parent Components', 'Parent Component'])
|
188
|
+
if parent_components:
|
189
|
+
parent_components_list, parent_q_name_list, parents_valid, parents_exist = process_name_list(
|
190
|
+
egeria_client, 'Solution Components', txt, COMPONENT_NAME_LABELS)
|
191
|
+
if not parents_exist:
|
192
|
+
valid = False
|
193
|
+
else:
|
194
|
+
parent_components_list = None
|
195
|
+
parent_q_name_list = None
|
196
|
+
parents_valid = True
|
197
|
+
parents_exist = False
|
198
|
+
|
199
|
+
component_display = (f"\n* Command: `{command}`\n\t* Component Name: {component_name}\n\t"
|
200
|
+
f"* Blueprint: {blueprint_name}\n\t* Parent Components: {parent_components}\n\t"
|
201
|
+
f"* Description: {description}\n")
|
202
|
+
|
203
|
+
if object_action == 'Update':
|
204
|
+
guid = process_simple_attribute(txt, ['GUID', 'guid', 'Guid'])
|
205
|
+
component_display += f"* Qualified Name: `{q_name}`\n\t* GUID: {guid}\n\n"
|
206
|
+
if not component_exists:
|
207
|
+
msg = f"Component can't be updated; `{component_name}` not found"
|
208
|
+
print_msg("ERROR", msg, debug_level)
|
209
|
+
valid = False
|
210
|
+
else:
|
211
|
+
msg = f"Component can be updated; `{component_name}` found"
|
212
|
+
print_msg(ALWAYS, msg, debug_level)
|
213
|
+
|
214
|
+
elif object_action == "Create":
|
215
|
+
if component_exists:
|
216
|
+
msg = f"Component `{component_name}` can't be created because it already exists.\n"
|
217
|
+
print_msg("ERROR", msg, debug_level)
|
218
|
+
valid = False
|
219
|
+
elif valid:
|
220
|
+
msg = f"It is valid to create Component `{component_name}` with:\n"
|
221
|
+
print_msg("ALWAYS", msg, debug_level)
|
222
|
+
|
223
|
+
if directive == "display":
|
224
|
+
print(Markdown(component_display))
|
225
|
+
return None
|
226
|
+
|
227
|
+
elif directive == "validate":
|
228
|
+
if valid:
|
229
|
+
print(Markdown(component_display))
|
230
|
+
else:
|
231
|
+
msg = f"Validation failed for Component `{component_name}`\n"
|
232
|
+
print_msg(ERROR, msg, debug_level)
|
233
|
+
print(Markdown(component_display))
|
234
|
+
|
235
|
+
return valid
|
236
|
+
|
237
|
+
elif directive == "process":
|
238
|
+
if valid:
|
239
|
+
print(Markdown(component_display))
|
240
|
+
else:
|
241
|
+
if component_exists and object_action == "Create":
|
242
|
+
msg = f"Create failed because component `{component_name}` exists - changing `Create` to `Update` in processed output \n"
|
243
|
+
print_msg(ERROR, msg, debug_level)
|
244
|
+
print(Markdown(component_display))
|
245
|
+
return update_a_command(txt, command, object_type, known_q_name, known_guid)
|
246
|
+
else:
|
247
|
+
return None
|
248
|
+
|
249
|
+
if object_action == "Update":
|
250
|
+
if not component_exists:
|
251
|
+
print(f"\n{ERROR}Component `{component_name}` does not exist! Updating result document with Create "
|
252
|
+
f"command\n")
|
253
|
+
return update_a_command(txt, command, object_type, known_q_name, known_guid)
|
254
|
+
|
255
|
+
body = {
|
256
|
+
"class": "ReferenceableRequestBody", "elementProperties": {
|
257
|
+
"class": "SolutionComponentProperties", "qualifiedName": known_q_name, "description": description
|
258
|
+
}
|
259
|
+
}
|
260
|
+
egeria_client.update_solution_component(known_guid, body)
|
261
|
+
print_msg(ALWAYS, f"Updated Component `{component_name}` with GUID {known_guid}", debug_level)
|
262
|
+
update_element_dictionary(known_q_name, {
|
263
|
+
'guid': known_guid, 'display_name': component_name
|
264
|
+
})
|
265
|
+
|
266
|
+
# Update parent components if specified
|
267
|
+
if parent_components and parents_exist and parents_valid:
|
268
|
+
# Get the current parent components
|
269
|
+
component_details = egeria_client.get_solution_component_by_guid(known_guid)
|
270
|
+
current_parents = []
|
271
|
+
if 'parentComponents' in component_details:
|
272
|
+
for parent in component_details['parentComponents']:
|
273
|
+
current_parents.append(parent.get('guid', None))
|
274
|
+
|
275
|
+
# Add new parent components
|
276
|
+
for parent in parent_q_name_list:
|
277
|
+
if parent not in current_parents:
|
278
|
+
egeria_client.add_parent_component(parent, known_guid)
|
279
|
+
print_msg(INFO, f"Added parent component to {component_name}", debug_level)
|
280
|
+
|
281
|
+
# Remove parent components that are not in the new list
|
282
|
+
for parent in current_parents:
|
283
|
+
if parent not in parent_q_name_list:
|
284
|
+
egeria_client.remove_parent_component(parent, known_guid)
|
285
|
+
print_msg(INFO, f"Removed parent component from {component_name}", debug_level)
|
286
|
+
|
287
|
+
return egeria_client.get_solution_component_by_guid(known_guid, output_format='MD')
|
288
|
+
|
289
|
+
elif object_action == "Create":
|
290
|
+
if component_exists:
|
291
|
+
print(f"\nComponent `{component_name}` already exists and result document updated\n")
|
292
|
+
return update_a_command(txt, command, object_type, known_q_name, known_guid)
|
293
|
+
else:
|
294
|
+
component_guid = egeria_client.create_solution_component(component_name, description, known_blueprint_guid)
|
295
|
+
if component_guid:
|
296
|
+
print_msg(ALWAYS, f"Created Component `{component_name}` with GUID {component_guid}", debug_level)
|
297
|
+
|
298
|
+
# Add parent components if specified
|
299
|
+
if parent_components and parents_exist and parents_valid:
|
300
|
+
for parent in parent_q_name_list:
|
301
|
+
egeria_client.add_parent_component(parent, component_guid)
|
302
|
+
print_msg(INFO, f"Added parent component to {component_name}", debug_level)
|
303
|
+
|
304
|
+
return egeria_client.get_solution_component_by_guid(component_guid, output_format='MD')
|
305
|
+
else:
|
306
|
+
print_msg(ERROR, f"Failed to create Component `{component_name}`", debug_level)
|
307
|
+
return None
|
@@ -0,0 +1,242 @@
|
|
1
|
+
"""
|
2
|
+
This file contains category-related command functions for processing Egeria Markdown
|
3
|
+
"""
|
4
|
+
from typing import Optional
|
5
|
+
|
6
|
+
from rich.markdown import Markdown
|
7
|
+
|
8
|
+
from pyegeria.egeria_tech_client import EgeriaTech
|
9
|
+
from pyegeria.md_processing.utils.common_utils import (
|
10
|
+
debug_level, print_msg, ALWAYS, ERROR, INFO, WARNING, pre_command, command_seperator, EXISTS_REQUIRED
|
11
|
+
)
|
12
|
+
from pyegeria.md_processing.utils.extraction_utils import (
|
13
|
+
extract_command_plus, extract_command, process_simple_attribute, process_name_list
|
14
|
+
)
|
15
|
+
from pyegeria.md_processing.utils.validation_utils import (
|
16
|
+
process_element_identifiers, update_a_command
|
17
|
+
)
|
18
|
+
from pyegeria.md_processing.utils.display_utils import (
|
19
|
+
GLOSSARY_NAME_LABELS, CATEGORY_NAME_LABELS, PARENT_CATEGORY_LABELS, OUTPUT_LABELS, ELEMENT_OUTPUT_FORMATS, SEARCH_LABELS
|
20
|
+
)
|
21
|
+
from pyegeria.dr_egeria_state import update_element_dictionary
|
22
|
+
|
23
|
+
def process_category_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
|
24
|
+
"""
|
25
|
+
Processes a category create or update command by extracting key attributes such as
|
26
|
+
category name, glossary name, description, and parent category from the given text.
|
27
|
+
|
28
|
+
:param txt: A string representing the input cell to be processed for
|
29
|
+
extracting category-related attributes.
|
30
|
+
:param directive: an optional string indicating the directive to be used - display, validate or execute
|
31
|
+
:return: A string summarizing the outcome of the processing.
|
32
|
+
"""
|
33
|
+
from pyegeria.md_processing.utils.common_utils import set_debug_level
|
34
|
+
|
35
|
+
command, object_type, object_action = extract_command_plus(txt)
|
36
|
+
set_debug_level(directive)
|
37
|
+
|
38
|
+
category_name = process_simple_attribute(txt, CATEGORY_NAME_LABELS, ERROR)
|
39
|
+
print(Markdown(f"{pre_command} `{object_action}` `{object_type}` for category: `\'{category_name}\'` with directive: `{directive}` "))
|
40
|
+
description = process_simple_attribute(txt, ['Description'], INFO)
|
41
|
+
q_name = process_simple_attribute(txt, ['Qualified Name'], INFO)
|
42
|
+
valid = True
|
43
|
+
|
44
|
+
if category_name is None:
|
45
|
+
valid = False
|
46
|
+
known_q_name = None
|
47
|
+
known_guid = None
|
48
|
+
category_exists = False
|
49
|
+
else:
|
50
|
+
element_labels = CATEGORY_NAME_LABELS
|
51
|
+
element_labels.append('Display Name')
|
52
|
+
known_q_name, known_guid, valid, category_exists = process_element_identifiers(egeria_client, object_type,
|
53
|
+
element_labels, txt,
|
54
|
+
object_action, None)
|
55
|
+
|
56
|
+
# Get the glossary this category is in
|
57
|
+
glossary_name = process_simple_attribute(txt, GLOSSARY_NAME_LABELS, ERROR)
|
58
|
+
if glossary_name is None:
|
59
|
+
valid = False
|
60
|
+
known_glossary_guid = None
|
61
|
+
known_glossary_q_name = None
|
62
|
+
glossary_valid = False
|
63
|
+
glossary_exists = False
|
64
|
+
else:
|
65
|
+
known_glossary_q_name, known_glossary_guid, glossary_valid, glossary_exists = process_element_identifiers(
|
66
|
+
egeria_client, "Glossary", GLOSSARY_NAME_LABELS, txt, EXISTS_REQUIRED, None)
|
67
|
+
|
68
|
+
# Get the parent category if specified
|
69
|
+
parent_category_name = process_simple_attribute(txt, PARENT_CATEGORY_LABELS)
|
70
|
+
if parent_category_name:
|
71
|
+
known_parent_q_name, known_parent_guid, parent_valid, parent_exists = process_element_identifiers(
|
72
|
+
egeria_client, "Category", PARENT_CATEGORY_LABELS, txt, EXISTS_REQUIRED, None)
|
73
|
+
if not parent_exists:
|
74
|
+
valid = False
|
75
|
+
else:
|
76
|
+
known_parent_q_name = None
|
77
|
+
known_parent_guid = None
|
78
|
+
parent_valid = True
|
79
|
+
parent_exists = False
|
80
|
+
|
81
|
+
category_display = (f"\n* Command: `{command}`\n\t* Glossary: {glossary_name}\n\t"
|
82
|
+
f"* Category Name: {category_name}\n\t* Parent Category: {parent_category_name}\n\t"
|
83
|
+
f"* Description: {description}\n")
|
84
|
+
|
85
|
+
if object_action == 'Update':
|
86
|
+
guid = process_simple_attribute(txt, ['GUID', 'guid', 'Guid'])
|
87
|
+
category_display += f"* Qualified Name: `{q_name}`\n\t* GUID: {guid}\n\n"
|
88
|
+
if not category_exists:
|
89
|
+
msg = f"Category can't be updated; `{category_name}` not found"
|
90
|
+
print_msg("ERROR", msg, debug_level)
|
91
|
+
valid = False
|
92
|
+
else:
|
93
|
+
msg = f"Category can be updated; `{category_name}` found"
|
94
|
+
print_msg(ALWAYS, msg, debug_level)
|
95
|
+
|
96
|
+
elif object_action == "Create":
|
97
|
+
if category_exists:
|
98
|
+
msg = f"Category `{category_name}` can't be created because it already exists.\n"
|
99
|
+
print_msg("ERROR", msg, debug_level)
|
100
|
+
valid = False
|
101
|
+
elif valid:
|
102
|
+
msg = f"It is valid to create Category `{category_name}` with:\n"
|
103
|
+
print_msg("ALWAYS", msg, debug_level)
|
104
|
+
|
105
|
+
if directive == "display":
|
106
|
+
print(Markdown(category_display))
|
107
|
+
return None
|
108
|
+
|
109
|
+
elif directive == "validate":
|
110
|
+
if valid:
|
111
|
+
print(Markdown(category_display))
|
112
|
+
else:
|
113
|
+
msg = f"Validation failed for Category `{category_name}`\n"
|
114
|
+
print_msg(ERROR, msg, debug_level)
|
115
|
+
print(Markdown(category_display))
|
116
|
+
|
117
|
+
return valid
|
118
|
+
|
119
|
+
elif directive == "process":
|
120
|
+
if valid:
|
121
|
+
print(Markdown(category_display))
|
122
|
+
else:
|
123
|
+
if category_exists and object_action == "Create":
|
124
|
+
msg = f"Create failed because category `{category_name}` exists - changing `Create` to `Update` in processed output \n"
|
125
|
+
print_msg(ERROR, msg, debug_level)
|
126
|
+
print(Markdown(category_display))
|
127
|
+
return update_a_command(txt, command, object_type, known_q_name, known_guid)
|
128
|
+
else:
|
129
|
+
return None
|
130
|
+
|
131
|
+
if object_action == "Update":
|
132
|
+
if not category_exists:
|
133
|
+
print(f"\n{ERROR}Category `{category_name}` does not exist! Updating result document with Create "
|
134
|
+
f"command\n")
|
135
|
+
return update_a_command(txt, command, object_type, known_q_name, known_guid)
|
136
|
+
|
137
|
+
body = {
|
138
|
+
"class": "ReferenceableRequestBody", "elementProperties": {
|
139
|
+
"class": "GlossaryCategoryProperties", "qualifiedName": known_q_name, "description": description
|
140
|
+
}
|
141
|
+
}
|
142
|
+
egeria_client.update_category(known_guid, body)
|
143
|
+
print_msg(ALWAYS, f"Updated Category `{category_name}` with GUID {known_guid}", debug_level)
|
144
|
+
update_element_dictionary(known_q_name, {
|
145
|
+
'guid': known_guid, 'display_name': category_name
|
146
|
+
})
|
147
|
+
|
148
|
+
# Update parent category if specified
|
149
|
+
if parent_category_name and parent_exists:
|
150
|
+
update_category_parent(egeria_client, known_guid, known_parent_guid, category_name, parent_category_name)
|
151
|
+
|
152
|
+
return egeria_client.get_category_by_guid(known_guid, output_format='MD')
|
153
|
+
|
154
|
+
elif object_action == "Create":
|
155
|
+
if category_exists:
|
156
|
+
print(f"\nCategory `{category_name}` already exists and result document updated\n")
|
157
|
+
return update_a_command(txt, command, object_type, known_q_name, known_guid)
|
158
|
+
else:
|
159
|
+
category_guid = egeria_client.create_category(category_name, description, known_glossary_guid, known_parent_guid)
|
160
|
+
if category_guid:
|
161
|
+
print_msg(ALWAYS, f"Created Category `{category_name}` with GUID {category_guid}", debug_level)
|
162
|
+
return egeria_client.get_category_by_guid(category_guid, output_format='MD')
|
163
|
+
else:
|
164
|
+
print_msg(ERROR, f"Failed to create Category `{category_name}`", debug_level)
|
165
|
+
return None
|
166
|
+
|
167
|
+
|
168
|
+
def update_category_parent(egeria_client: EgeriaTech, category_guid: str, parent_guid: str, category_name: str, parent_name: str) -> Optional[str]:
|
169
|
+
"""
|
170
|
+
Updates the parent category of a category.
|
171
|
+
|
172
|
+
:param egeria_client: The Egeria client to use for the update.
|
173
|
+
:param category_guid: The GUID of the category to update.
|
174
|
+
:param parent_guid: The GUID of the parent category.
|
175
|
+
:param category_name: The name of the category to update.
|
176
|
+
:param parent_name: The name of the parent category.
|
177
|
+
:return: A string summarizing the outcome of the processing.
|
178
|
+
"""
|
179
|
+
try:
|
180
|
+
# Get the current parent category
|
181
|
+
category = egeria_client.get_category_by_guid(category_guid)
|
182
|
+
if 'parentCategory' in category:
|
183
|
+
current_parent_guid = category['parentCategory'].get('guid', None)
|
184
|
+
if current_parent_guid and current_parent_guid != parent_guid:
|
185
|
+
# Remove the current parent
|
186
|
+
egeria_client.remove_parent_category(current_parent_guid, category_guid)
|
187
|
+
print_msg(INFO, f"Removed current parent category from {category_name}", debug_level)
|
188
|
+
|
189
|
+
# Add the new parent
|
190
|
+
egeria_client.add_parent_category(parent_guid, category_guid)
|
191
|
+
print_msg(ALWAYS, f"Added parent category {parent_name} to {category_name}", debug_level)
|
192
|
+
return f"Updated parent category of {category_name} to {parent_name}"
|
193
|
+
except Exception as e:
|
194
|
+
print_msg(ERROR, f"Error updating parent category: {e}", debug_level)
|
195
|
+
return None
|
196
|
+
|
197
|
+
|
198
|
+
def process_category_list_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
|
199
|
+
"""
|
200
|
+
Processes a category list command by extracting key attributes such as
|
201
|
+
glossary name, output format, and search string from the given text.
|
202
|
+
|
203
|
+
:param txt: A string representing the input cell to be processed for
|
204
|
+
extracting category-related attributes.
|
205
|
+
:param directive: an optional string indicating the directive to be used - display, validate or execute
|
206
|
+
:return: A string summarizing the outcome of the processing.
|
207
|
+
"""
|
208
|
+
from pyegeria.md_processing.utils.common_utils import set_debug_level
|
209
|
+
|
210
|
+
command = extract_command(txt)
|
211
|
+
set_debug_level(directive)
|
212
|
+
print(Markdown(f"{pre_command} `{command}` with directive: `{directive}`"))
|
213
|
+
|
214
|
+
glossary_name = process_simple_attribute(txt, GLOSSARY_NAME_LABELS)
|
215
|
+
output_format = process_simple_attribute(txt, OUTPUT_LABELS)
|
216
|
+
output_format = output_format.upper() if output_format else "MD"
|
217
|
+
if output_format not in ELEMENT_OUTPUT_FORMATS:
|
218
|
+
print_msg(WARNING, f"Output format {output_format} not recognized, using MD", debug_level)
|
219
|
+
output_format = "MD"
|
220
|
+
|
221
|
+
search_string = process_simple_attribute(txt, SEARCH_LABELS)
|
222
|
+
|
223
|
+
if glossary_name:
|
224
|
+
known_q_name, known_guid, valid, glossary_exists = process_element_identifiers(egeria_client, "Glossary",
|
225
|
+
GLOSSARY_NAME_LABELS, txt,
|
226
|
+
EXISTS_REQUIRED, None)
|
227
|
+
if not glossary_exists:
|
228
|
+
print_msg(ERROR, f"Glossary {glossary_name} not found", debug_level)
|
229
|
+
return None
|
230
|
+
|
231
|
+
if directive == "display":
|
232
|
+
print(Markdown(f"\n* Command: {command}\n\t* Glossary Name: {glossary_name}\n\t* Output Format: {output_format}\n\t* Search String: {search_string}"))
|
233
|
+
return None
|
234
|
+
elif directive == "validate":
|
235
|
+
print(Markdown(f"\n* Command: {command}\n\t* Glossary Name: {glossary_name}\n\t* Output Format: {output_format}\n\t* Search String: {search_string}"))
|
236
|
+
return True
|
237
|
+
elif directive == "process":
|
238
|
+
print(Markdown(f"\n* Command: {command}\n\t* Glossary Name: {glossary_name}\n\t* Output Format: {output_format}\n\t* Search String: {search_string}"))
|
239
|
+
if glossary_name and glossary_exists:
|
240
|
+
return egeria_client.list_categories_for_glossary(known_guid, output_format=output_format, search_string=search_string)
|
241
|
+
else:
|
242
|
+
return egeria_client.list_categories(output_format=output_format, search_string=search_string)
|