pyegeria 5.3.7.7__py3-none-any.whl → 5.3.7.8__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/__init__.py +2 -1
- pyegeria/_client.py +4 -1
- pyegeria/commands/cat/dr_egeria_md.py +16 -12
- pyegeria/commands/cat/get_project_dependencies.py +1 -1
- pyegeria/commands/cat/get_project_structure.py +1 -1
- pyegeria/glossary_manager_omvs.py +1 -1
- pyegeria/md_processing_helpers.py +58 -68
- pyegeria/md_processing_utils.py +253 -161
- pyegeria/md_processing_utils_orig.py +1 -1
- pyegeria/project_manager_omvs.py +79 -3
- pyegeria/shared_state.py +35 -0
- {pyegeria-5.3.7.7.dist-info → pyegeria-5.3.7.8.dist-info}/METADATA +1 -1
- {pyegeria-5.3.7.7.dist-info → pyegeria-5.3.7.8.dist-info}/RECORD +16 -15
- {pyegeria-5.3.7.7.dist-info → pyegeria-5.3.7.8.dist-info}/LICENSE +0 -0
- {pyegeria-5.3.7.7.dist-info → pyegeria-5.3.7.8.dist-info}/WHEEL +0 -0
- {pyegeria-5.3.7.7.dist-info → pyegeria-5.3.7.8.dist-info}/entry_points.txt +0 -0
pyegeria/__init__.py
CHANGED
@@ -93,7 +93,8 @@ from .x_action_author_omvs import ActionAuthor
|
|
93
93
|
from .md_processing_utils import (extract_command, process_glossary_upsert_command, process_term_upsert_command,
|
94
94
|
process_categories_upsert_command,
|
95
95
|
get_current_datetime_string, process_per_proj_upsert_command, command_list,
|
96
|
-
render_markdown, process_provenance_command, process_blueprint_upsert_command
|
96
|
+
render_markdown, process_provenance_command, process_blueprint_upsert_command,
|
97
|
+
process_solution_component_upsert_command)
|
97
98
|
|
98
99
|
#
|
99
100
|
# The following assignments were generated by the `create_tech_guid_lists.py` utility that uses the pyegeria functions
|
pyegeria/_client.py
CHANGED
@@ -770,7 +770,8 @@ class Client:
|
|
770
770
|
)
|
771
771
|
return result
|
772
772
|
|
773
|
-
def __create_qualified_name__(self, type: str, display_name: str, local_qualifier: str = None
|
773
|
+
def __create_qualified_name__(self, type: str, display_name: str, local_qualifier: str = None,
|
774
|
+
version_identifier: str = None) -> str:
|
774
775
|
"""Helper function to create a qualified name for a given type and display name.
|
775
776
|
If present, the local qualifier will be prepended to the qualified name."""
|
776
777
|
EGERIA_LOCAL_QUALIFIER = os.environ.get("EGERIA_LOCAL_QUALIFIER", local_qualifier)
|
@@ -778,6 +779,8 @@ class Client:
|
|
778
779
|
q_name = f"{type}:{display_name}"
|
779
780
|
if EGERIA_LOCAL_QUALIFIER:
|
780
781
|
q_name = f"{EGERIA_LOCAL_QUALIFIER}:{q_name}"
|
782
|
+
if version_identifier:
|
783
|
+
q_name = f"{q_name}:{version_identifier}"
|
781
784
|
return q_name
|
782
785
|
|
783
786
|
if __name__ == "__main__":
|
@@ -13,11 +13,11 @@ import click
|
|
13
13
|
from pyegeria import (extract_command, process_glossary_upsert_command, process_term_upsert_command,
|
14
14
|
process_categories_upsert_command, process_provenance_command,
|
15
15
|
get_current_datetime_string, process_per_proj_upsert_command, command_list,EgeriaTech,
|
16
|
-
process_blueprint_upsert_command
|
16
|
+
process_blueprint_upsert_command, process_solution_component_upsert_command,
|
17
|
+
shared_state
|
17
18
|
)
|
18
19
|
from datetime import datetime
|
19
20
|
|
20
|
-
|
21
21
|
EGERIA_METADATA_STORE = os.environ.get("EGERIA_METADATA_STORE", "active-metadata-store")
|
22
22
|
EGERIA_KAFKA_ENDPOINT = os.environ.get("KAFKA_ENDPOINT", "localhost:9092")
|
23
23
|
EGERIA_PLATFORM_URL = os.environ.get("EGERIA_PLATFORM_URL", "https://localhost:9443")
|
@@ -86,11 +86,11 @@ def process_markdown_file(
|
|
86
86
|
h1_blocks = []
|
87
87
|
current_block = ""
|
88
88
|
in_h1_block = False
|
89
|
-
|
89
|
+
|
90
90
|
|
91
91
|
# Helper function to process the current block
|
92
92
|
def process_current_block(current_block):
|
93
|
-
nonlocal updated, final_output, prov_found, prov_output, h1_blocks, in_h1_block
|
93
|
+
nonlocal updated, final_output, prov_found, prov_output, h1_blocks, in_h1_block
|
94
94
|
|
95
95
|
if not current_block:
|
96
96
|
return # No block to process
|
@@ -103,26 +103,30 @@ def process_markdown_file(
|
|
103
103
|
prov_found = True
|
104
104
|
|
105
105
|
elif potential_command in ["Create Glossary", "Update Glossary"]:
|
106
|
-
result = process_glossary_upsert_command(client,
|
106
|
+
result = process_glossary_upsert_command(client, shared_state.get_element_dictionary(), current_block, directive)
|
107
107
|
elif potential_command in ["Create Category", "Update Category"]:
|
108
|
-
result = process_categories_upsert_command(client,
|
108
|
+
result = process_categories_upsert_command(client, shared_state.get_element_dictionary(), current_block, directive)
|
109
109
|
elif potential_command in ["Create Term", "Update Term"]:
|
110
|
-
result = process_term_upsert_command(client,
|
110
|
+
result = process_term_upsert_command(client, shared_state.get_element_dictionary(), current_block, directive)
|
111
111
|
elif potential_command in ["Create Personal Project", "Update Personal Project"]:
|
112
|
-
result = process_per_proj_upsert_command(client,
|
112
|
+
result = process_per_proj_upsert_command(client, shared_state.get_element_dictionary(), current_block, directive)
|
113
113
|
elif potential_command in ["Create Blueprint", "Update Blueprint", "Create Solution Blueprint", "Update Solution Blueprint"]:
|
114
|
-
result = process_blueprint_upsert_command(client,
|
114
|
+
result = process_blueprint_upsert_command(client, shared_state.get_element_dictionary(), current_block, directive)
|
115
|
+
elif potential_command in ["Create Solution Component", "Update Solution Component"]:
|
116
|
+
result = process_solution_component_upsert_command(client, shared_state.get_element_dictionary(), current_block, directive)
|
117
|
+
|
118
|
+
|
115
119
|
else:
|
116
120
|
# If command is not recognized, keep the block as-is
|
117
121
|
result = None
|
118
|
-
|
122
|
+
print(json.dumps(shared_state.get_element_dictionary(), indent=4))
|
119
123
|
if result:
|
120
124
|
if directive == "process":
|
121
125
|
updated = True
|
122
126
|
final_output.append(result)
|
123
|
-
|
127
|
+
print(json.dumps(shared_state.get_element_dictionary(), indent=4))
|
124
128
|
elif directive == "validate":
|
125
|
-
print(json.dumps(
|
129
|
+
print(json.dumps(shared_state.get_element_dictionary(), indent=4))
|
126
130
|
elif directive == "process":
|
127
131
|
# Handle errors (skip this block but notify the user)
|
128
132
|
print(f"\n==>\tErrors found while processing command: \'{potential_command}\'\n"
|
@@ -109,7 +109,7 @@ def project_dependency_viewer(
|
|
109
109
|
child_md = ""
|
110
110
|
child_guid = proj["elementHeader"]["guid"]
|
111
111
|
child_name = proj["properties"]["name"]
|
112
|
-
relationship = proj["
|
112
|
+
relationship = proj["startingElement"]["relationshipHeader"]["type"][
|
113
113
|
"typeName"
|
114
114
|
]
|
115
115
|
if relationship != "ProjectDependency":
|
@@ -109,7 +109,7 @@ def project_structure_viewer(
|
|
109
109
|
child_md = ""
|
110
110
|
child_guid = proj["elementHeader"]["guid"]
|
111
111
|
child_name = proj["properties"]["name"]
|
112
|
-
relationship = proj["
|
112
|
+
relationship = proj["startingElement"]["relationshipHeader"]["type"][
|
113
113
|
"typeName"
|
114
114
|
]
|
115
115
|
if relationship != "ProjectHierarchy":
|
@@ -936,7 +936,7 @@ class GlossaryManager(GlossaryBrowser):
|
|
936
936
|
continue
|
937
937
|
|
938
938
|
# Add the term
|
939
|
-
term_qualified_name = self.__create_qualified_name__("Term",
|
939
|
+
term_qualified_name = self.__create_qualified_name__("Term", term_name)
|
940
940
|
|
941
941
|
body = {
|
942
942
|
"class": "ReferenceableRequestBody",
|
@@ -1,68 +1,58 @@
|
|
1
|
-
|
2
|
-
from typing import List, Optional
|
3
|
-
|
4
|
-
import os
|
5
|
-
import re
|
6
|
-
|
7
|
-
from rich import box, print
|
8
|
-
from rich.console import Console
|
9
|
-
from rich.markdown import Markdown
|
10
|
-
|
11
|
-
from pyegeria import body_slimmer
|
12
|
-
from pyegeria._globals import NO_TERMS_FOUND, NO_GLOSSARIES_FOUND, NO_TERMS_FOUND, NO_ELEMENTS_FOUND, NO_PROJECTS_FOUND, NO_CATEGORIES_FOUND
|
13
|
-
from pyegeria.egeria_tech_client import EgeriaTech
|
14
|
-
from pyegeria.md_processing_utils import extract_attribute
|
15
|
-
from pyegeria.project_manager_omvs import ProjectManager
|
16
|
-
from pyegeria.glossary_manager_omvs import GlossaryManager
|
17
|
-
ERROR = "ERROR-> "
|
18
|
-
INFO = "INFO- "
|
19
|
-
WARNING = "WARNING-> "
|
20
|
-
pre_command = "\n---\n==> Processing command:"
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
def process_q_name_list(egeria_client: EgeriaTech, element_type:str, txt:str )-> tuple[str,
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
'guid': el_guid,
|
60
|
-
'displayName': el_display_name
|
61
|
-
}
|
62
|
-
elements = f"{el_qname}, {elements}"
|
63
|
-
new_element_list.append(el_qname)
|
64
|
-
if el_exist:
|
65
|
-
elements += '\n'
|
66
|
-
element_list = new_element_list
|
67
|
-
else:
|
68
|
-
elements = None
|
1
|
+
#
|
2
|
+
# from typing import List, Optional
|
3
|
+
#
|
4
|
+
# import os
|
5
|
+
# import re
|
6
|
+
#
|
7
|
+
# from rich import box, print
|
8
|
+
# from rich.console import Console
|
9
|
+
# from rich.markdown import Markdown
|
10
|
+
#
|
11
|
+
# from pyegeria import body_slimmer
|
12
|
+
# from pyegeria._globals import NO_TERMS_FOUND, NO_GLOSSARIES_FOUND, NO_TERMS_FOUND, NO_ELEMENTS_FOUND, NO_PROJECTS_FOUND, NO_CATEGORIES_FOUND
|
13
|
+
# from pyegeria.egeria_tech_client import EgeriaTech
|
14
|
+
# from pyegeria.md_processing_utils import extract_attribute, get_element_by_name, process_element_identifiers
|
15
|
+
# from pyegeria.project_manager_omvs import ProjectManager
|
16
|
+
# from pyegeria.glossary_manager_omvs import GlossaryManager
|
17
|
+
# ERROR = "ERROR-> "
|
18
|
+
# INFO = "INFO- "
|
19
|
+
# WARNING = "WARNING-> "
|
20
|
+
# pre_command = "\n---\n==> Processing command:"
|
21
|
+
#
|
22
|
+
#
|
23
|
+
#
|
24
|
+
# def process_q_name_list(egeria_client: EgeriaTech, element_type:str, txt:str )-> tuple[str | None,list | None,str | None,bool,bool]:
|
25
|
+
# msg = ""
|
26
|
+
# known_guid = None
|
27
|
+
# valid = True
|
28
|
+
# exists = False
|
29
|
+
# elements = ""
|
30
|
+
# new_element_list = []
|
31
|
+
#
|
32
|
+
# elements_txt = extract_attribute(txt, [element_type])
|
33
|
+
#
|
34
|
+
# if elements_txt is None:
|
35
|
+
# msg += f"* {INFO}No {element_type}s found\n"
|
36
|
+
#
|
37
|
+
# else:
|
38
|
+
# element_list = re.split(r'[,\n]+', elements_txt)
|
39
|
+
#
|
40
|
+
# for element in element_list:
|
41
|
+
# element_el = element.strip()
|
42
|
+
#
|
43
|
+
# # Get the element using the generalized function
|
44
|
+
# known_q_name, known_guid, status_msg, el_valid, el_exists = get_element_by_name(
|
45
|
+
# egeria_client, element_type,txt)
|
46
|
+
# msg += status_msg
|
47
|
+
# if exists and valid:
|
48
|
+
# elements = f"{element_el}, {elements}" # list of the input names
|
49
|
+
# new_element_list.append(known_q_name) # list of qualified names
|
50
|
+
# valid = valid and el_valid
|
51
|
+
# exists = exists and el_exists
|
52
|
+
#
|
53
|
+
# if elements:
|
54
|
+
# elements += "\n"
|
55
|
+
# msg += f"* {INFO}Found {element_type}s: {elements}"
|
56
|
+
# else:
|
57
|
+
# msg += f"* {INFO}List contains one or more invalid elements.\n"
|
58
|
+
# return elements,new_element_list, msg, valid, exists
|
pyegeria/md_processing_utils.py
CHANGED
@@ -20,11 +20,13 @@ from rich.markdown import Markdown
|
|
20
20
|
from pyegeria import body_slimmer
|
21
21
|
from pyegeria._globals import NO_TERMS_FOUND, NO_GLOSSARIES_FOUND, NO_TERMS_FOUND, NO_ELEMENTS_FOUND, NO_PROJECTS_FOUND, NO_CATEGORIES_FOUND
|
22
22
|
from pyegeria.egeria_tech_client import EgeriaTech
|
23
|
+
# from pyegeria.md_processing_helpers import process_q_name_list
|
23
24
|
from pyegeria.project_manager_omvs import ProjectManager
|
24
25
|
from pyegeria.glossary_manager_omvs import GlossaryManager
|
26
|
+
from pyegeria.shared_state import get_element_dictionary, update_element_dictionary
|
25
27
|
|
26
28
|
from datetime import datetime
|
27
|
-
EGERIA_WIDTH = int(os.environ.get("EGERIA_WIDTH", "
|
29
|
+
EGERIA_WIDTH = int(os.environ.get("EGERIA_WIDTH", "170"))
|
28
30
|
console = Console(width=EGERIA_WIDTH)
|
29
31
|
|
30
32
|
command_list = ["Provenance",
|
@@ -32,14 +34,15 @@ command_list = ["Provenance",
|
|
32
34
|
"Create Term", "Update Term",
|
33
35
|
"Create Personal Project", "Update Personal Project",
|
34
36
|
"Create Category", "Update Category",
|
35
|
-
"Create Solution Blueprint", "Update Solution Blueprint"
|
37
|
+
"Create Solution Blueprint", "Update Solution Blueprint",
|
38
|
+
"Create Solution Component", "Update Solution Component",]
|
36
39
|
|
37
40
|
ERROR = "ERROR-> "
|
38
41
|
INFO = "INFO- "
|
39
42
|
WARNING = "WARNING-> "
|
40
43
|
pre_command = "\n---\n==> Processing command:"
|
41
44
|
|
42
|
-
|
45
|
+
|
43
46
|
|
44
47
|
def render_markdown(markdown_text: str) -> None:
|
45
48
|
"""Renders the given markdown text in the console."""
|
@@ -67,8 +70,9 @@ def add_term_to_categories(egeria_client: GlossaryManager, term_guid: str, categ
|
|
67
70
|
for category in categories_list:
|
68
71
|
cat_guid = None
|
69
72
|
cat_el = category.strip()
|
70
|
-
|
71
|
-
|
73
|
+
element_dict = get_element_dictionary()
|
74
|
+
if cat_el in element_dict:
|
75
|
+
cat = element_dict.get(cat_el, None)
|
72
76
|
cat_guid = cat.get('guid', None) if cat else None
|
73
77
|
if cat_guid is None:
|
74
78
|
cat_guid = egeria_client.__get_guid__(qualified_name=cat_el)
|
@@ -160,7 +164,8 @@ def process_provenance_command(file_path: str, txt: [str]) -> str:
|
|
160
164
|
existing_prov = existing_prov if existing_prov else " "
|
161
165
|
return f"\n# Provenance:\n{existing_prov}\n{output}\n"
|
162
166
|
|
163
|
-
def process_element_identifiers(egeria_client: EgeriaTech, element_type:str, txt: str
|
167
|
+
def process_element_identifiers(egeria_client: EgeriaTech, element_type:str, txt: str, action: str, version: str=None) \
|
168
|
+
-> tuple[str, str, str, bool, bool]:
|
164
169
|
"""
|
165
170
|
Processes element identifiers by extracting display name and qualified name from the input text,
|
166
171
|
checking if the element exists in Egeria, and validating the information.
|
@@ -172,6 +177,10 @@ def process_element_identifiers(egeria_client: EgeriaTech, element_type:str, txt
|
|
172
177
|
type of element to process (e.g., 'blueprint', 'category', 'term')
|
173
178
|
txt: str
|
174
179
|
A string representing the input text to be processed for extracting element identifiers.
|
180
|
+
action: str
|
181
|
+
The action command to be executed (e.g., 'Create', 'Update', 'Display', ...)
|
182
|
+
version: str, optional = None
|
183
|
+
An optional version identifier used if we need to construct the qualified name
|
175
184
|
|
176
185
|
Returns: tuple[str, str, str, bool, bool]
|
177
186
|
A tuple containing:
|
@@ -181,44 +190,42 @@ def process_element_identifiers(egeria_client: EgeriaTech, element_type:str, txt
|
|
181
190
|
- Valid: Boolean indicating if the element information is valid
|
182
191
|
- Exists: Boolean indicating if the element exists in Egeria
|
183
192
|
"""
|
184
|
-
|
185
193
|
msg = ""
|
186
|
-
|
194
|
+
guid = None
|
187
195
|
valid = True
|
188
196
|
exists = False
|
197
|
+
unique: bool | None = None
|
189
198
|
display_name = extract_attribute(txt, ["Display Name"])
|
190
|
-
|
191
|
-
msg = f"* {ERROR}Display name is missing\n"
|
192
|
-
valid = False
|
193
|
-
return "","", msg, valid, exists
|
199
|
+
|
194
200
|
qualified_name = extract_attribute(txt, ["Qualified Name"])
|
195
201
|
if qualified_name:
|
196
|
-
|
202
|
+
q_name, guid, msg, unique, exists = get_element_by_name(egeria_client,element_type,qualified_name)
|
203
|
+
# Qualified name could be different if it is being updated
|
197
204
|
else:
|
198
|
-
|
205
|
+
q_name, guid, msg, unique, exists = get_element_by_name(egeria_client,element_type,display_name)
|
206
|
+
if unique is False:
|
207
|
+
msg += f"{ERROR} Multiple elements named {display_name} found\n"
|
208
|
+
valid = False
|
209
|
+
if action == "Update" and not exists:
|
210
|
+
msg += f"* {ERROR}Element {display_name} does not exist\n"
|
211
|
+
valid = False
|
212
|
+
elif action == "Update" and exists:
|
213
|
+
msg += f"* {INFO}Element {display_name} exists\n"
|
214
|
+
elif action == "Create" and exists:
|
215
|
+
msg += f"* {ERROR}Element {display_name} already exists\n"
|
216
|
+
valid = False
|
217
|
+
elif action == "Create" and not exists:
|
218
|
+
msg += f"* {INFO}Element {display_name} does not exist and can be created\n"
|
219
|
+
if q_name is None:
|
220
|
+
q_name = egeria_client.__create_qualified_name__(element_type, display_name,
|
221
|
+
version_identifier=version)
|
222
|
+
update_element_dictionary(q_name, {'display_name': display_name})
|
199
223
|
|
200
|
-
|
201
|
-
exists = False
|
202
|
-
else:
|
203
|
-
exists = True
|
224
|
+
return q_name, guid, msg, valid, exists
|
204
225
|
|
205
|
-
if len(element_details) > 1 and exists:
|
206
|
-
msg += (f"* {ERROR}More than one element with name {display_name} found, please specify a "
|
207
|
-
f"**Qualified Name**\n")
|
208
|
-
valid = False
|
209
|
-
elif len(element_details) == 1:
|
210
|
-
known_guid = element_details[0]['elementHeader'].get('guid', None)
|
211
|
-
known_q_name = element_details[0]['glossaryTermProperties'].get('qualifiedName', None)
|
212
|
-
if qualified_name != known_q_name:
|
213
|
-
msg += (f"* {ERROR}Element {display_name} qualifiedName mismatch between {qualified_name} and {known_q_name}\n")
|
214
|
-
valid = False
|
215
|
-
else:
|
216
|
-
msg += f"\n--> * Element {display_name} exists and can be updated\n"
|
217
|
-
# msg += term_display
|
218
|
-
# element_dictionary[known_q_name] = {'display_name': display_name, 'guid': known_guid}
|
219
|
-
return qualified_name, known_guid, msg, valid, exists
|
220
226
|
|
221
|
-
def get_element_by_name(egeria_client, element_type: str, element_name: str)
|
227
|
+
def get_element_by_name(egeria_client, element_type: str, element_name: str)\
|
228
|
+
->tuple[str | None, str | None, str, bool | None, bool | None]:
|
222
229
|
"""
|
223
230
|
Generalized function to retrieve an element by name based on its type.
|
224
231
|
|
@@ -231,28 +238,119 @@ def get_element_by_name(egeria_client, element_type: str, element_name: str):
|
|
231
238
|
The name of the element to retrieve.
|
232
239
|
|
233
240
|
Returns:
|
234
|
-
|
241
|
+
tuple of qualified_name, guid, msg, uniqye, exists
|
235
242
|
"""
|
243
|
+
unique = None
|
244
|
+
element_dict = get_element_dictionary()
|
245
|
+
if element_name in element_dict: # use information from element_dictionary
|
246
|
+
guid = element_dict[element_name].get('guid',None)
|
247
|
+
unique = True
|
248
|
+
exists = False
|
249
|
+
if guid is not None: # Found complete entry in element_dictionary
|
250
|
+
return element_name, guid, 'Found qualified name', unique, exists
|
251
|
+
else: # Missing guid from element_dictionary
|
252
|
+
guid = egeria_client.get_element_guid_by_unique_name(element_name)
|
253
|
+
if guid == NO_ELEMENTS_FOUND:
|
254
|
+
exists = False
|
255
|
+
msg = f"{INFO}No {element_type} guid found with name {element_name}\n"
|
256
|
+
return element_name, None, msg, unique, exists
|
257
|
+
else:
|
258
|
+
exists = True
|
259
|
+
update_element_dictionary(element_name, {'guid': guid})
|
260
|
+
return element_name, guid, 'Found qualified name', unique, exists
|
261
|
+
|
262
|
+
# Haven't seen this element before
|
263
|
+
property_names = ['qualifiedName', 'name', 'displayName']
|
264
|
+
open_metadata_type_name = None
|
265
|
+
details = egeria_client.get_elements_by_property_value(
|
266
|
+
element_name, property_names, open_metadata_type_name
|
267
|
+
)
|
268
|
+
if isinstance(details, str):
|
269
|
+
msg = f"{INFO}{element_type} `{element_name}` not found\n"
|
270
|
+
exists = False
|
271
|
+
return element_name, None, msg, unique, exists
|
272
|
+
if len(details) > 1:
|
273
|
+
msg = (f"{ERROR}More than one element with name {element_name} found, please specify a "
|
274
|
+
f"**Qualified Name**\n")
|
275
|
+
unique= False
|
276
|
+
exists = None
|
277
|
+
return element_name, None, msg, unique, exists
|
278
|
+
|
279
|
+
el_qname = details[0]["properties"].get('qualifiedName', None)
|
280
|
+
el_guid = details[0]['elementHeader']['guid']
|
281
|
+
el_display_name = details[0]["properties"].get('displayName', None)
|
282
|
+
update_element_dictionary(el_qname, {
|
283
|
+
'guid': el_guid,
|
284
|
+
'displayName': el_display_name
|
285
|
+
})
|
286
|
+
msg = f"{INFO}Found {element_type} `{element_name}`\n"
|
287
|
+
exists = True
|
288
|
+
unique = True
|
289
|
+
return el_qname, el_guid, msg, unique, exists
|
290
|
+
|
236
291
|
# Convert element_type to plural form for method name construction
|
237
|
-
if element_type.endswith('y'):
|
238
|
-
|
239
|
-
elif element_type.endswith('s'):
|
240
|
-
|
241
|
-
else:
|
242
|
-
|
292
|
+
# if element_type.endswith('y'):
|
293
|
+
# plural_type = f"{element_type[:-1]}ies"
|
294
|
+
# elif element_type.endswith('s'):
|
295
|
+
# plural_type = f"{element_type}es"
|
296
|
+
# else:
|
297
|
+
# plural_type = f"{element_type}s"
|
298
|
+
#
|
299
|
+
# # Construct method name
|
300
|
+
# method_name = f"get_{plural_type}_by_name"
|
301
|
+
#
|
302
|
+
# # Check if the method exists on the client
|
303
|
+
# if hasattr(egeria_client, method_name):
|
304
|
+
# # Call the method
|
305
|
+
# method = getattr(egeria_client, method_name)
|
306
|
+
# result = method(element_name)
|
307
|
+
# return result
|
308
|
+
# else:
|
309
|
+
# # Method doesn't exist
|
310
|
+
# return f"Method {method_name} not found on client"
|
311
|
+
|
312
|
+
|
313
|
+
|
314
|
+
def process_q_name_list(egeria_client: EgeriaTech, element_type: str, txt: str) -> tuple[
|
315
|
+
str | None, list | None, str | None, bool, bool]:
|
316
|
+
msg = ""
|
317
|
+
known_guid = None
|
318
|
+
valid = True
|
319
|
+
exists = False
|
320
|
+
elements = ""
|
321
|
+
new_element_list = []
|
322
|
+
|
323
|
+
elements_txt = extract_attribute(txt, [element_type])
|
243
324
|
|
244
|
-
|
245
|
-
|
325
|
+
if elements_txt is None:
|
326
|
+
msg += f"* {INFO}No {element_type}s found\n"
|
246
327
|
|
247
|
-
# Check if the method exists on the client
|
248
|
-
if hasattr(egeria_client, method_name):
|
249
|
-
# Call the method
|
250
|
-
method = getattr(egeria_client, method_name)
|
251
|
-
result = method(element_name)
|
252
|
-
return result
|
253
328
|
else:
|
254
|
-
|
255
|
-
|
329
|
+
element_list = re.split(r'[,\n]+', elements_txt)
|
330
|
+
|
331
|
+
for element in element_list:
|
332
|
+
element_el = element.strip()
|
333
|
+
|
334
|
+
# Get the element using the generalized function
|
335
|
+
known_q_name, known_guid, status_msg, el_valid, el_exists = get_element_by_name(
|
336
|
+
egeria_client, element_type, element_el)
|
337
|
+
msg += status_msg
|
338
|
+
if el_exists and el_valid:
|
339
|
+
elements = f"{element_el}, {elements}" # list of the input names
|
340
|
+
new_element_list.append(known_q_name) # list of qualified names
|
341
|
+
elif not el_exists:
|
342
|
+
msg += f"* {INFO}No {element_type} `{element_el}` found\n"
|
343
|
+
valid = False
|
344
|
+
valid = valid if el_valid is None else valid and el_valid
|
345
|
+
exists = exists and el_exists
|
346
|
+
|
347
|
+
if elements:
|
348
|
+
elements += "\n"
|
349
|
+
msg += f"* {INFO}Found {element_type}s: {elements}"
|
350
|
+
else:
|
351
|
+
msg += f"* {INFO}List contains one or more invalid elements.\n"
|
352
|
+
return elements, new_element_list, msg, valid, exists
|
353
|
+
|
256
354
|
|
257
355
|
|
258
356
|
|
@@ -274,16 +372,23 @@ def process_blueprint_upsert_command(egeria_client: EgeriaTech, element_dictiona
|
|
274
372
|
Returns: str
|
275
373
|
A string summarizing the outcome of the processing.
|
276
374
|
"""
|
277
|
-
|
278
375
|
object_type, object_action = extract_command_plus(txt)
|
279
376
|
element_display = ""
|
377
|
+
valid = True
|
378
|
+
msg =""
|
379
|
+
|
280
380
|
display_name = extract_attribute(txt, ['Display Name','Blueprint Name'])
|
281
381
|
description = extract_attribute(txt, ['Description'])
|
282
382
|
version = extract_attribute(txt, ['Version', "Version Identifier", "Published Version"])
|
283
383
|
|
284
|
-
print(Markdown(f"{pre_command} `{object_type}
|
285
|
-
|
286
|
-
|
384
|
+
print(Markdown(f"{pre_command} {object_action} `{object_type}` for Blueprint: `\'{display_name}\'` with directive: `{directive}`\n"))
|
385
|
+
if display_name is None:
|
386
|
+
msg += f"* {ERROR}Display name is missing\n"
|
387
|
+
valid = False
|
388
|
+
q_name, known_guid, exists = None
|
389
|
+
else:
|
390
|
+
q_name, known_guid, status_msg, valid, exists = process_element_identifiers(egeria_client, object_type,txt, object_action)
|
391
|
+
msg+= status_msg
|
287
392
|
|
288
393
|
if description is None:
|
289
394
|
msg += f"* {INFO}Description is missing\n"
|
@@ -298,32 +403,33 @@ def process_blueprint_upsert_command(egeria_client: EgeriaTech, element_dictiona
|
|
298
403
|
|
299
404
|
element_display = (f"\n* Command: {object_action} {object_type}\n\t* Blueprint: {display_name}\n\t"
|
300
405
|
f"* Description: {description}\n\t"
|
301
|
-
f"* Version: {version}\n\t* Qualified Name:{
|
406
|
+
f"* Version: {version}\n\t* Qualified Name:{q_name}\n\t* GUID: {known_guid} "
|
302
407
|
f"\n\t* Update Description: {update_description}\n")
|
303
408
|
|
304
|
-
if object_action == "Update": # check to see if provided information exists and is consistent with existing info
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
409
|
+
# if object_action == "Update": # check to see if provided information exists and is consistent with existing info
|
410
|
+
# if not exists:
|
411
|
+
# msg += f"* {ERROR}Element {display_name} does not exist\n"
|
412
|
+
# valid = False
|
413
|
+
|
414
|
+
# elif object_action == 'Create': # if the command is create, check that it doesn't already exist
|
415
|
+
# if exists:
|
416
|
+
# msg += f"\n{WARNING}Element \'{display_name}\' already exists.\n"
|
417
|
+
# elif not valid:
|
418
|
+
# msg += f"\n-->Validation checks failed in creating element \'{display_name}\' with: {element_display}\n"
|
419
|
+
# else: # valid to create - update element_dictionary
|
420
|
+
# msg += f"\n-->It is valid to create element \'{display_name}\' with: {element_display}\n"
|
421
|
+
# if known_q_name is None:
|
422
|
+
# known_q_name = egeria_client.__create_qualified_name__(object_type, display_name)
|
423
|
+
# element_dictionary[known_q_name] = {'display_name': display_name}
|
424
|
+
if valid:
|
425
|
+
msg += f"\n-->It is valid to create element \'{display_name}\' with: {element_display}\n"
|
321
426
|
|
322
427
|
if directive == "display":
|
323
428
|
print(Markdown(element_display))
|
324
429
|
return None
|
325
430
|
elif directive == "validate":
|
326
431
|
print(Markdown(msg))
|
432
|
+
print(Markdown(element_display))
|
327
433
|
return valid
|
328
434
|
|
329
435
|
elif directive == "process":
|
@@ -350,16 +456,16 @@ def process_blueprint_upsert_command(egeria_client: EgeriaTech, element_dictiona
|
|
350
456
|
if exists:
|
351
457
|
print(f"\n{WARNING}Blueprint {display_name} exists and result document updated")
|
352
458
|
return update_a_command(txt, f"{object_type}{object_action}",
|
353
|
-
object_type,
|
459
|
+
object_type, q_name, known_guid)
|
354
460
|
else:
|
355
461
|
# create the blueprint
|
356
462
|
#term_guid = egeria_client.create_controlled_glossary_term(glossary_guid, term_body)
|
357
463
|
# if term_guid == NO_ELEMENTS_FOUND:
|
358
464
|
# print(f"{ERROR}Term {term_name} not created")
|
359
465
|
# return None
|
360
|
-
|
361
|
-
print(f"\n-->Created Blueprint {display_name} with GUID {
|
362
|
-
|
466
|
+
new_guid= f"guid:{get_current_datetime_string()}"
|
467
|
+
print(f"\n-->Created Blueprint {display_name} with GUID {new_guid}")
|
468
|
+
update_element_dictionary(q_name, {'guid': new_guid, 'display_name': display_name})
|
363
469
|
return 'Would return get blueprint by guid results as md' #egeria_client.get_terms_by_guid(term_guid, 'MD')
|
364
470
|
|
365
471
|
except Exception as e:
|
@@ -387,10 +493,12 @@ def process_solution_component_upsert_command(egeria_client: EgeriaTech, element
|
|
387
493
|
Returns: str
|
388
494
|
A string summarizing the outcome of the processing.
|
389
495
|
"""
|
390
|
-
|
391
496
|
object_type, object_action = extract_command_plus(txt)
|
392
497
|
element_display = ""
|
393
498
|
bp_exist = True
|
499
|
+
bp_qname_list = []
|
500
|
+
parent_qname_list = []
|
501
|
+
|
394
502
|
display_name = extract_attribute(txt, ['Display Name', 'Solution Component Name'])
|
395
503
|
description = extract_attribute(txt, ['Description'])
|
396
504
|
version = extract_attribute(txt, ['Version', "Version Identifier", "Published Version"])
|
@@ -400,9 +508,9 @@ def process_solution_component_upsert_command(egeria_client: EgeriaTech, element
|
|
400
508
|
parent_components = extract_attribute(txt, ['Parent Components'])
|
401
509
|
|
402
510
|
print(Markdown(
|
403
|
-
f"{pre_command} `{object_type}
|
511
|
+
f"{pre_command} {object_action} `{object_type}` for Solution Component: `\'{display_name}\'` with directive: `{directive}`\n"))
|
404
512
|
|
405
|
-
known_q_name, known_guid, msg, valid, exists = process_element_identifiers(egeria_client, object_type,txt)
|
513
|
+
known_q_name, known_guid, msg, valid, exists = process_element_identifiers(egeria_client, object_type,txt, object_action)
|
406
514
|
|
407
515
|
if description is None:
|
408
516
|
msg += f"* {INFO}Description is missing\n"
|
@@ -424,54 +532,31 @@ def process_solution_component_upsert_command(egeria_client: EgeriaTech, element
|
|
424
532
|
if solution_blueprints is None:
|
425
533
|
msg += f"* {INFO}No Solution Blueprints found\n"
|
426
534
|
|
427
|
-
else:
|
428
|
-
|
429
|
-
|
430
|
-
new_blueprint_list = []
|
431
|
-
for blueprint in blueprint_list:
|
432
|
-
blueprint_el = blueprint.strip()
|
433
|
-
if blueprint_el not in element_dictionary:
|
434
|
-
# Get the blueprint using the generalized function
|
435
|
-
element_type = 'blueprint'
|
436
|
-
bp = get_element_by_name(egeria_client, element_type, blueprint_el)
|
437
|
-
if isinstance(bp, str):
|
438
|
-
msg += (f"* {WARNING}Blueprint `{blueprint_el}` not found -> "
|
439
|
-
f"Blueprints for this Solution Component won't be processed!\n")
|
440
|
-
bp_exist = False
|
441
|
-
break
|
442
|
-
|
443
|
-
# Extract properties using the element type name to construct property access
|
444
|
-
properties_key = f"{element_type}Properties"
|
445
|
-
bp_qname = bp[0][properties_key].get('qualifiedName', None)
|
446
|
-
|
447
|
-
if bp_qname not in element_dictionary:
|
448
|
-
bp_guid = bp[0]['elementHeader']['guid']
|
449
|
-
bp_display_name = bp[0][properties_key].get('displayName', None)
|
450
|
-
element_dictionary[bp_qname] = {
|
451
|
-
'guid': bp_guid,
|
452
|
-
'displayName': bp_display_name
|
453
|
-
}
|
454
|
-
blueprints = f"{bp_qname}, {blueprints}"
|
455
|
-
new_blueprint_list.append(bp_qname)
|
456
|
-
if bp_exist:
|
457
|
-
blueprints += '\n'
|
458
|
-
blueprint_list = new_blueprint_list
|
459
|
-
else:
|
460
|
-
blueprints = None
|
535
|
+
else: # Find information about blueprints that include this component
|
536
|
+
solution_blueprints, bp_qname_list, msg, valid, exists = process_q_name_list(egeria_client,
|
537
|
+
'Solution Blueprints', txt)
|
461
538
|
|
462
539
|
if parent_components is None:
|
463
540
|
msg += f"* {INFO}Parent Components are missing\n"
|
541
|
+
else:
|
542
|
+
parent_components, parent_qname_list, msg, valid, exists = process_q_name_list(egeria_client,
|
543
|
+
'Solution Component', parent_components)
|
464
544
|
|
465
|
-
element_display = (f"\n* Command: {object_action} {object_type}\n\t*
|
545
|
+
element_display = (f"\n* Command: {object_action} {object_type}\n\t* Display Name: {display_name}\n\t"
|
466
546
|
f"* Description: {description}\n\t"
|
467
|
-
f"* Version: {version}\n\t
|
547
|
+
f"* Version Identifier: {version}\n\t"
|
548
|
+
f"* Solution Component Type {solution_component_type}\n\t"
|
549
|
+
f"* Planned Deployment Implementation Type {planned_deployed_implementation_type}\n\t"
|
550
|
+
f"* Solution_Blueprints: {solution_blueprints}\n\t"
|
551
|
+
f"* Parent Components: {parent_components}\n\t"
|
552
|
+
f"* Qualified Name:{known_q_name}\n\t* GUID: {known_guid} "
|
468
553
|
f"\n\t* Update Description: {update_description}\n")
|
469
554
|
|
470
555
|
if object_action == "Update": # check to see if provided information exists and is consistent with existing info
|
471
556
|
if not exists:
|
472
557
|
msg += f"* {ERROR}Element {display_name} does not exist\n"
|
473
558
|
valid = False
|
474
|
-
element_dictionary[known_q_name] = {'display_name': display_name, 'guid': known_guid}
|
559
|
+
# element_dictionary[known_q_name] = {'display_name': display_name, 'guid': known_guid}
|
475
560
|
|
476
561
|
elif object_action == 'Create': # if the command is create, check that it doesn't already exist
|
477
562
|
if exists:
|
@@ -481,14 +566,16 @@ def process_solution_component_upsert_command(egeria_client: EgeriaTech, element
|
|
481
566
|
else: # valid to create - update element_dictionary
|
482
567
|
msg += f"\n-->It is valid to create element \'{display_name}\' with: {element_display}\n"
|
483
568
|
if known_q_name is None:
|
484
|
-
known_q_name = egeria_client.__create_qualified_name__(object_type, display_name
|
485
|
-
|
569
|
+
known_q_name = egeria_client.__create_qualified_name__(object_type, display_name,
|
570
|
+
version_identifier=version)
|
571
|
+
update_element_dictionary(known_q_name, {'display_name': display_name})
|
486
572
|
|
487
573
|
if directive == "display":
|
488
574
|
print(Markdown(element_display))
|
489
575
|
return None
|
490
576
|
elif directive == "validate":
|
491
577
|
print(Markdown(msg))
|
578
|
+
print(Markdown(element_display))
|
492
579
|
return valid
|
493
580
|
|
494
581
|
elif directive == "process":
|
@@ -499,14 +586,14 @@ def process_solution_component_upsert_command(egeria_client: EgeriaTech, element
|
|
499
586
|
|
500
587
|
if object_action == "Update" and directive == "process":
|
501
588
|
if not exists:
|
502
|
-
print(f"\n-->
|
589
|
+
print(f"\n-->Solution Component {display_name} does not exist")
|
503
590
|
return None
|
504
591
|
|
505
|
-
# call update
|
592
|
+
# call update solution component here
|
506
593
|
|
507
|
-
print(f"\n-->Updated
|
508
|
-
# update with get
|
509
|
-
return 'Would return get
|
594
|
+
print(f"\n-->Updated Solution Component {display_name} with GUID {known_guid}")
|
595
|
+
# update with get solution component by guid
|
596
|
+
return 'Would return get Solution Component by guid and return md' # egeria_client.get_terms_by_guid(known_guid, 'md')
|
510
597
|
|
511
598
|
elif object_action == "Update" and directive == "validate":
|
512
599
|
return 'Would call get_blueprint_by_guid and return md' # egeria_client.get_terms_by_guid(known_guid, 'md')
|
@@ -523,9 +610,9 @@ def process_solution_component_upsert_command(egeria_client: EgeriaTech, element
|
|
523
610
|
# print(f"{ERROR}Term {term_name} not created")
|
524
611
|
# return None
|
525
612
|
|
526
|
-
print(f"\n-->Created
|
527
|
-
|
528
|
-
return 'Would return get
|
613
|
+
print(f"\n-->Created Solution Component {display_name} with GUID {known_guid}")
|
614
|
+
update_element_dictionary(known_q_name, {'guid': known_guid, 'display_name': display_name})
|
615
|
+
return 'Would return get solution component by guid results as md' # egeria_client.get_terms_by_guid(term_guid, 'MD')
|
529
616
|
|
530
617
|
except Exception as e:
|
531
618
|
print(f"{ERROR}Error creating term {display_name}: {e}")
|
@@ -568,7 +655,7 @@ def process_glossary_upsert_command(egeria_client: GlossaryManager, element_dict
|
|
568
655
|
valid = True
|
569
656
|
msg = ""
|
570
657
|
|
571
|
-
known_q_name, known_guid, msg, valid, glossary_exists = process_element_identifiers(egeria_client, object_type,txt)
|
658
|
+
known_q_name, known_guid, msg, valid, glossary_exists = process_element_identifiers(egeria_client, object_type,txt, object_action)
|
572
659
|
|
573
660
|
if glossary_name is None:
|
574
661
|
msg = f"* {ERROR}Glossary name is missing\n"
|
@@ -595,7 +682,7 @@ def process_glossary_upsert_command(egeria_client: GlossaryManager, element_dict
|
|
595
682
|
if valid:
|
596
683
|
msg += glossary_display
|
597
684
|
msg += f"* -->Glossary `{glossary_name}` exists and can be updated\n"
|
598
|
-
|
685
|
+
update_element_dictionary(known_q_name, {'display_name': glossary_name, 'guid': known_guid})
|
599
686
|
else:
|
600
687
|
msg += f"* --> validation failed\n"
|
601
688
|
|
@@ -610,7 +697,7 @@ def process_glossary_upsert_command(egeria_client: GlossaryManager, element_dict
|
|
610
697
|
msg += f"-->It is valid to create Glossary \'{glossary_name}\' with:\n"
|
611
698
|
msg += glossary_display
|
612
699
|
expected_q_name = egeria_client.__create_qualified_name__('Glossary', glossary_name)
|
613
|
-
|
700
|
+
update_element_dictionary(expected_q_name, {'display_name': glossary_name})
|
614
701
|
|
615
702
|
print(Markdown(msg))
|
616
703
|
return valid, glossary_exists, known_guid, known_q_name
|
@@ -642,9 +729,9 @@ def process_glossary_upsert_command(egeria_client: GlossaryManager, element_dict
|
|
642
729
|
}
|
643
730
|
egeria_client.update_glossary(known_guid, body)
|
644
731
|
print(f"\n-->Updated Glossary {glossary_name} with GUID {known_guid}")
|
645
|
-
|
732
|
+
update_element_dictionary(known_q_name, {
|
646
733
|
'guid': known_guid, 'display_name': glossary_name
|
647
|
-
}
|
734
|
+
})
|
648
735
|
# return update_a_command(txt, command, object_type, known_q_name, known_guid)
|
649
736
|
return egeria_client.get_glossary_by_guid(known_guid, output_format='MD')
|
650
737
|
elif object_action == "Create":
|
@@ -660,9 +747,9 @@ def process_glossary_upsert_command(egeria_client: GlossaryManager, element_dict
|
|
660
747
|
print(f"{ERROR}Just created with GUID {glossary_guid} but Glossary not found\n")
|
661
748
|
return None
|
662
749
|
qualified_name = glossary['glossaryProperties']["qualifiedName"]
|
663
|
-
|
750
|
+
update_element_dictionary(qualified_name, {
|
664
751
|
'guid': glossary_guid, 'display_name': glossary_name
|
665
|
-
}
|
752
|
+
})
|
666
753
|
# return update_a_command(txt, command, object_type, qualified_name, glossary_guid)
|
667
754
|
return egeria_client.get_glossary_by_guid(glossary_guid, output_format = 'MD')
|
668
755
|
|
@@ -715,9 +802,10 @@ def process_categories_upsert_command(egeria_client: GlossaryManager, element_di
|
|
715
802
|
msg += f"* {ERROR}Owning Glossary Qualified Name is missing\n"
|
716
803
|
valid = False
|
717
804
|
|
718
|
-
elif owning_glossary_qn in
|
719
|
-
|
720
|
-
|
805
|
+
elif owning_glossary_qn in get_element_dictionary(): # Check to see if we already know about this glossary
|
806
|
+
element_dict = get_element_dictionary()
|
807
|
+
glossary_name = element_dict[owning_glossary_qn].get('display_name', None)
|
808
|
+
glossary_guid = element_dict[owning_glossary_qn].get('guid', None)
|
721
809
|
|
722
810
|
else:
|
723
811
|
# need to ask Egeria if it knows the Glossary Name
|
@@ -734,9 +822,9 @@ def process_categories_upsert_command(egeria_client: GlossaryManager, element_di
|
|
734
822
|
msg += f"* {ERROR}Glossary `{owning_glossary_qn}` is known by qualifiedName `{glossary_qn}`\n\n"
|
735
823
|
valid = False
|
736
824
|
else:
|
737
|
-
|
825
|
+
update_element_dictionary(owning_glossary_qn, {
|
738
826
|
'guid': glossary_guid, 'display_name': glossary_name
|
739
|
-
}
|
827
|
+
})
|
740
828
|
|
741
829
|
if category_name is None:
|
742
830
|
msg = f"* {ERROR}Category name is missing\n"
|
@@ -766,7 +854,7 @@ def process_categories_upsert_command(egeria_client: GlossaryManager, element_di
|
|
766
854
|
if valid:
|
767
855
|
msg += category_display
|
768
856
|
msg += f"* -->category `{category_name}` exists and can be updated\n"
|
769
|
-
|
857
|
+
update_element_dictionary(known_q_name, {'display_name': glossary_name, 'guid': known_category_guid})
|
770
858
|
else:
|
771
859
|
msg += f"* --> validation failed\n"
|
772
860
|
|
@@ -781,7 +869,7 @@ def process_categories_upsert_command(egeria_client: GlossaryManager, element_di
|
|
781
869
|
msg += f"-->It is valid to create category `{category_name}` with:\n"
|
782
870
|
msg += category_display
|
783
871
|
expected_q_name = egeria_client.__create_qualified_name__('Category', category_name)
|
784
|
-
|
872
|
+
update_element_dictionary(expected_q_name, {'display_name': category_name})
|
785
873
|
|
786
874
|
print(Markdown(msg))
|
787
875
|
return valid, category_exists, known_category_guid, known_q_name, glossary_guid
|
@@ -811,9 +899,9 @@ def process_categories_upsert_command(egeria_client: GlossaryManager, element_di
|
|
811
899
|
egeria_client.update_category(glossary_guid, category_name, description, known_q_name, None,
|
812
900
|
update_description)
|
813
901
|
print(f"\n-->Updated category `{category_name}`with GUID {known_guid}")
|
814
|
-
|
902
|
+
update_element_dictionary(known_q_name, {
|
815
903
|
'guid': known_guid, 'display_name': category_name
|
816
|
-
}
|
904
|
+
})
|
817
905
|
# return update_a_command(txt, command, object_type, known_q_name, known_guid)
|
818
906
|
return egeria_client.get_categories_by_guid(known_guid, output_format='FORM')
|
819
907
|
|
@@ -831,9 +919,9 @@ def process_categories_upsert_command(egeria_client: GlossaryManager, element_di
|
|
831
919
|
print(f"{ERROR}Just created with GUID {category_guid} but category not found\n")
|
832
920
|
return None
|
833
921
|
qualified_name = category['glossaryCategoryProperties']["qualifiedName"]
|
834
|
-
|
922
|
+
update_element_dictionary(qualified_name, {
|
835
923
|
'guid': category_guid, 'display_name': category_name
|
836
|
-
}
|
924
|
+
})
|
837
925
|
# return update_a_command(txt, command, object_type, qualified_name, category_guid)
|
838
926
|
return egeria_client.get_categories_by_guid(category_guid, output_format='MD')
|
839
927
|
|
@@ -905,7 +993,8 @@ def process_term_upsert_command(egeria_client: GlossaryManager, element_dictiona
|
|
905
993
|
valid = False
|
906
994
|
else:
|
907
995
|
print(f"* {INFO}Glossary qualified name is `{glossary_qn}`")
|
908
|
-
|
996
|
+
element_dict = get_element_dictionary()
|
997
|
+
if glossary_qn not in element_dict:
|
909
998
|
glossary = egeria_client.get_glossaries_by_name(glossary_qn) #assuming q_name?
|
910
999
|
if isinstance(glossary,str):
|
911
1000
|
msg += f"* {ERROR}Glossary `{glossary_qn}` is unknown\n "
|
@@ -919,10 +1008,10 @@ def process_term_upsert_command(egeria_client: GlossaryManager, element_dictiona
|
|
919
1008
|
msg += f"* {ERROR}Glossary `{glossary_qn}` has no qualifiedName\n "
|
920
1009
|
valid = False
|
921
1010
|
else:
|
922
|
-
|
1011
|
+
update_element_dictionary(glossary_qn, {
|
923
1012
|
'guid': glossary[0]['elementHeader'].get('guid', None),
|
924
1013
|
'display_name': glossary[0]['glossaryProperties'].get('displayName', None)
|
925
|
-
}
|
1014
|
+
})
|
926
1015
|
|
927
1016
|
|
928
1017
|
if categories is None:
|
@@ -933,7 +1022,8 @@ def process_term_upsert_command(egeria_client: GlossaryManager, element_dictiona
|
|
933
1022
|
new_cat_list = []
|
934
1023
|
for category in categories_list:
|
935
1024
|
category_el = category.strip()
|
936
|
-
|
1025
|
+
element_dict = get_element_dictionary()
|
1026
|
+
if category_el not in element_dict:
|
937
1027
|
cat = egeria_client.get_categories_by_name(category_el) # assuming qualified name?
|
938
1028
|
if isinstance(cat,str):
|
939
1029
|
msg += (f"* {WARNING}Category `{category_el}` not found -> "
|
@@ -942,13 +1032,13 @@ def process_term_upsert_command(egeria_client: GlossaryManager, element_dictiona
|
|
942
1032
|
break
|
943
1033
|
cat_qname = cat[0]['glossaryCategoryProperties'].get('qualifiedName', None)
|
944
1034
|
category = cat_qname # use the qualified name if found
|
945
|
-
if cat_qname not in
|
1035
|
+
if cat_qname not in element_dict:
|
946
1036
|
cat_guid = cat[0]['elementHeader']['guid']
|
947
1037
|
cat_display_name = cat[0]['glossaryCategoryProperties'].get('displayName', None)
|
948
|
-
|
1038
|
+
update_element_dictionary(cat_qname, {
|
949
1039
|
'guid' : cat_guid,
|
950
1040
|
'displayName': cat_display_name
|
951
|
-
}
|
1041
|
+
})
|
952
1042
|
categories = f"{category}, {categories}"
|
953
1043
|
new_cat_list.append(category)
|
954
1044
|
if cats_exist:
|
@@ -993,7 +1083,7 @@ def process_term_upsert_command(egeria_client: GlossaryManager, element_dictiona
|
|
993
1083
|
else:
|
994
1084
|
msg += f"\n--> * Term {term_name} exists and can be updated\n"
|
995
1085
|
msg += term_display
|
996
|
-
|
1086
|
+
update_element_dictionary(known_q_name, {'display_name': term_name, 'guid': known_term_guid})
|
997
1087
|
|
998
1088
|
print(Markdown(msg))
|
999
1089
|
return valid, term_exists, known_term_guid, known_q_name
|
@@ -1006,10 +1096,11 @@ def process_term_upsert_command(egeria_client: GlossaryManager, element_dictiona
|
|
1006
1096
|
else:
|
1007
1097
|
msg += f"\n-->It is valid to create Term \'{term_name}\' with: {term_display}\n"
|
1008
1098
|
if q_name is None:
|
1009
|
-
expected_q_name = egeria_client.__create_qualified_name__('Term',
|
1010
|
-
|
1099
|
+
expected_q_name = egeria_client.__create_qualified_name__('Term',
|
1100
|
+
term_name, version_identifier=version)
|
1101
|
+
update_element_dictionary(expected_q_name, {'display_name': term_name})
|
1011
1102
|
else:
|
1012
|
-
|
1103
|
+
update_element_dictionary(q_name, {'display_name': term_name})
|
1013
1104
|
print(Markdown(msg))
|
1014
1105
|
return valid, term_exists, known_term_guid, known_q_name
|
1015
1106
|
|
@@ -1086,13 +1177,14 @@ def process_term_upsert_command(egeria_client: GlossaryManager, element_dictiona
|
|
1086
1177
|
elif object_action == "Create":
|
1087
1178
|
guid = None
|
1088
1179
|
if q_name is None:
|
1089
|
-
q_name = egeria_client.__create_qualified_name__("Term",term_name
|
1180
|
+
q_name = egeria_client.__create_qualified_name__("Term",term_name,
|
1181
|
+
version_identifier=version)
|
1090
1182
|
if exists:
|
1091
1183
|
print(f"\n{WARNING}Term {term_name} exists and result document updated")
|
1092
1184
|
return update_a_command(txt, command, object_type, q_name, known_guid)
|
1093
1185
|
else:
|
1094
1186
|
## get the guid for the glossary from the name - first look locally
|
1095
|
-
glossary =
|
1187
|
+
glossary = get_element_dictionary().get(glossary_qn, None)
|
1096
1188
|
|
1097
1189
|
if glossary is not None:
|
1098
1190
|
glossary_guid = glossary.get('guid', None)
|
@@ -1131,7 +1223,7 @@ def process_term_upsert_command(egeria_client: GlossaryManager, element_dictiona
|
|
1131
1223
|
egeria_client, term_guid, cats_exist, categories_list,
|
1132
1224
|
element_dictionary)
|
1133
1225
|
print(f"\n-->Created Term {term_name} with GUID {term_guid}")
|
1134
|
-
|
1226
|
+
update_element_dictionary(q_name, {'guid': term_guid, 'display_name': term_name})
|
1135
1227
|
return egeria_client.get_terms_by_guid(term_guid, 'MD')
|
1136
1228
|
# return update_a_command(txt, command, object_type, q_name, term_guid)
|
1137
1229
|
except Exception as e:
|
@@ -1279,11 +1371,11 @@ def process_per_proj_upsert_command(egeria_client: ProjectManager, element_dicti
|
|
1279
1371
|
guid = egeria_client.create_project(None, None, None, False, project_name, description,
|
1280
1372
|
"PersonalProject", project_identifier, True, project_status,
|
1281
1373
|
project_phase, project_health, start_date, planned_end_date)
|
1282
|
-
project_g = egeria_client.
|
1374
|
+
project_g = egeria_client.get_project_by_guid(guid)
|
1283
1375
|
if project_g == NO_GLOSSARIES_FOUND:
|
1284
1376
|
print(f"Just created with GUID {guid} but Project not found")
|
1285
1377
|
return None
|
1286
1378
|
|
1287
1379
|
q_name = project_g['projectProperties']["qualifiedName"]
|
1288
|
-
|
1380
|
+
update_element_dictionary(q_name, {'guid': guid, 'display_name': project_name})
|
1289
1381
|
return update_a_command(txt, command, object_type, q_name, guid)
|
@@ -1093,7 +1093,7 @@ def process_per_proj_upsert_command(egeria_client: ProjectManager, element_dicti
|
|
1093
1093
|
guid = egeria_client.create_project(None, None, None, False, project_name, description,
|
1094
1094
|
"PersonalProject", project_identifier, True, project_status,
|
1095
1095
|
project_phase, project_health, start_date, planned_end_date)
|
1096
|
-
project_g = egeria_client.
|
1096
|
+
project_g = egeria_client.get_project_by_guid(guid)
|
1097
1097
|
if project_g == NO_GLOSSARIES_FOUND:
|
1098
1098
|
print(f"Just created with GUID {guid} but Project not found")
|
1099
1099
|
return None
|
pyegeria/project_manager_omvs.py
CHANGED
@@ -635,7 +635,7 @@ class ProjectManager(Client):
|
|
635
635
|
|
636
636
|
return resp
|
637
637
|
|
638
|
-
async def
|
638
|
+
async def _async_get_project_by_guid(
|
639
639
|
self,
|
640
640
|
project_guid: str,
|
641
641
|
effective_time: str = None,
|
@@ -677,7 +677,7 @@ class ProjectManager(Client):
|
|
677
677
|
resp = await self._async_make_request("GET", url, body)
|
678
678
|
return resp.json()
|
679
679
|
|
680
|
-
def
|
680
|
+
def get_project_by_guid(self, project_guid: str, effective_time: str = None) -> dict | str:
|
681
681
|
"""Return the properties of a specific project.
|
682
682
|
|
683
683
|
Parameters
|
@@ -707,11 +707,87 @@ class ProjectManager(Client):
|
|
707
707
|
"""
|
708
708
|
loop = asyncio.get_event_loop()
|
709
709
|
resp = loop.run_until_complete(
|
710
|
-
self.
|
710
|
+
self._async_get_project_by_guid(project_guid, effective_time)
|
711
711
|
)
|
712
712
|
|
713
713
|
return resp
|
714
714
|
|
715
|
+
async def _async_get_project_graph(
|
716
|
+
self,
|
717
|
+
project_guid: str,
|
718
|
+
effective_time: str = None,
|
719
|
+
) -> dict | str:
|
720
|
+
"""Return the mermaid graph of a specific project. Async version.
|
721
|
+
|
722
|
+
Parameters
|
723
|
+
----------
|
724
|
+
project_guid: str,
|
725
|
+
unique identifier of the project.
|
726
|
+
effective_time: str, [default=None], optional
|
727
|
+
Effective time of the query. If not specified will default to any time. Time in ISO8601 format is assumed.
|
728
|
+
|
729
|
+
|
730
|
+
Returns
|
731
|
+
-------
|
732
|
+
str
|
733
|
+
|
734
|
+
A mermaid markdown string representing the graph of the project.
|
735
|
+
Raises
|
736
|
+
------
|
737
|
+
|
738
|
+
InvalidParameterException
|
739
|
+
If the client passes incorrect parameters on the request - such as bad URLs or invalid values
|
740
|
+
PropertyServerException
|
741
|
+
Raised by the server when an issue arises in processing a valid request
|
742
|
+
NotAuthorizedException
|
743
|
+
The principle specified by the user_id does not have authorization for the requested action
|
744
|
+
|
745
|
+
"""
|
746
|
+
|
747
|
+
validate_guid(project_guid)
|
748
|
+
body = {
|
749
|
+
"effective_time": effective_time,
|
750
|
+
}
|
751
|
+
url = f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/projects/{project_guid}/graph"
|
752
|
+
|
753
|
+
resp = await self._async_make_request("GET", url, body)
|
754
|
+
return resp.json().get('element',NO_ELEMENTS_FOUND)
|
755
|
+
|
756
|
+
def get_project_graph(self, project_guid: str, effective_time: str = None) -> dict | str:
|
757
|
+
"""Return the mermaid graph of a specific project.
|
758
|
+
|
759
|
+
Parameters
|
760
|
+
----------
|
761
|
+
project_guid: str,
|
762
|
+
unique identifier of the project.
|
763
|
+
effective_time: str, [default=None], optional
|
764
|
+
Effective time of the query. If not specified will default to any time. Time in ISO8601 format is assumed.
|
765
|
+
|
766
|
+
|
767
|
+
Returns
|
768
|
+
-------
|
769
|
+
str
|
770
|
+
|
771
|
+
A mermaid markdown string representing the graph of the project.
|
772
|
+
Raises
|
773
|
+
------
|
774
|
+
|
775
|
+
InvalidParameterException
|
776
|
+
If the client passes incorrect parameters on the request - such as bad URLs or invalid values
|
777
|
+
PropertyServerException
|
778
|
+
Raised by the server when an issue arises in processing a valid request
|
779
|
+
NotAuthorizedException
|
780
|
+
The principle specified by the user_id does not have authorization for the requested action
|
781
|
+
|
782
|
+
"""
|
783
|
+
loop = asyncio.get_event_loop()
|
784
|
+
resp = loop.run_until_complete(
|
785
|
+
self._async_get_project_graph(project_guid, effective_time)
|
786
|
+
)
|
787
|
+
|
788
|
+
return resp
|
789
|
+
|
790
|
+
|
715
791
|
#
|
716
792
|
# Create project methods
|
717
793
|
#
|
pyegeria/shared_state.py
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
"""
|
2
|
+
This module provides shared state for the pyegeria package.
|
3
|
+
It contains variables that need to be accessed and modified by multiple modules.
|
4
|
+
"""
|
5
|
+
|
6
|
+
# Dictionary to store element information to avoid redundant API calls
|
7
|
+
element_dictionary = {}
|
8
|
+
|
9
|
+
def get_element_dictionary():
|
10
|
+
"""
|
11
|
+
Get the shared element dictionary.
|
12
|
+
|
13
|
+
Returns:
|
14
|
+
dict: The shared element dictionary
|
15
|
+
"""
|
16
|
+
global element_dictionary
|
17
|
+
return element_dictionary
|
18
|
+
|
19
|
+
def update_element_dictionary(key, value):
|
20
|
+
"""
|
21
|
+
Update the shared element dictionary with a new key-value pair.
|
22
|
+
|
23
|
+
Args:
|
24
|
+
key (str): The key to update
|
25
|
+
value (dict): The value to associate with the key
|
26
|
+
"""
|
27
|
+
global element_dictionary
|
28
|
+
element_dictionary[key] = value
|
29
|
+
|
30
|
+
def clear_element_dictionary():
|
31
|
+
"""
|
32
|
+
Clear the shared element dictionary.
|
33
|
+
"""
|
34
|
+
global element_dictionary
|
35
|
+
element_dictionary.clear()
|
@@ -1,6 +1,6 @@
|
|
1
1
|
pyegeria/README.md,sha256=PwX5OC7-YSZUCIsoyHh1O-WBM2hE84sm3Bd4O353NOk,1464
|
2
|
-
pyegeria/__init__.py,sha256=
|
3
|
-
pyegeria/_client.py,sha256=
|
2
|
+
pyegeria/__init__.py,sha256=_ajfbBLCVW8RnSWYK4tGXLqjHEdnzCW2q815GENuFS0,30383
|
3
|
+
pyegeria/_client.py,sha256=IAX6y11zqX3Dz1XwbYXQqHNdi7HmKQClI0Li5cjUSUA,31884
|
4
4
|
pyegeria/_deprecated_gov_engine.py,sha256=dWNcwVsE5__dF2u4QiIyQrssozzzOjBbLld8MdpmVCQ,17264
|
5
5
|
pyegeria/_exceptions.py,sha256=1SrnV194V4_YJNnNAU0myTHQ3dhLn4GF2B2gZcj1u90,18153
|
6
6
|
pyegeria/_globals.py,sha256=a_irI6oGuBLks2LzQHkSdK6xWbPdJCPRjqxK7PKxwgw,991
|
@@ -17,12 +17,12 @@ pyegeria/commands/cat/__init__.py,sha256=5OCy4m_yZsnSxdy_gvkCyP_OkjvuWKimqUGHYCJ
|
|
17
17
|
pyegeria/commands/cat/dr_egeria_inbox/glossary_creation_experiment.ipynb,sha256=dbzNu90fCKNohOWVSRBOB1GLyd95x8Qw51I5AkaPtso,11552
|
18
18
|
pyegeria/commands/cat/dr_egeria_inbox/glossary_exp.md,sha256=KsUeTzDe5QkrTmIfIAXR74qZ29oSfRW-NAEn0RYIRqM,2534
|
19
19
|
pyegeria/commands/cat/dr_egeria_jupyter.py,sha256=U-3m9BMoCXj2fvuawr3PTc2HQWAXThqQ3sIXjyCWv6s,5912
|
20
|
-
pyegeria/commands/cat/dr_egeria_md.py,sha256
|
20
|
+
pyegeria/commands/cat/dr_egeria_md.py,sha256=-WCnNL3_1hjsYgVy5Z3eixg7MED7O1K0ldfkX7tFpWQ,10378
|
21
21
|
pyegeria/commands/cat/exp_list_glossaries.py,sha256=dC6Bnfm3YSMTKPP146qeslIFRiZnGu5b7iDYE07p4iU,5817
|
22
22
|
pyegeria/commands/cat/get_asset_graph.py,sha256=xnXJfpDTVH1TJ2TwE3dtjaXU36Di6-N6JAyhothzz2o,12461
|
23
23
|
pyegeria/commands/cat/get_collection.py,sha256=kXPcP8u-SMWfrVyyBhNoxG8mcgB7EV_5i9N9w_IBU7o,5379
|
24
|
-
pyegeria/commands/cat/get_project_dependencies.py,sha256=
|
25
|
-
pyegeria/commands/cat/get_project_structure.py,sha256=
|
24
|
+
pyegeria/commands/cat/get_project_dependencies.py,sha256=XwstxuDxDDuP2uN1oJi0PTDZVLbqgcc_3lxh_prBZvY,5987
|
25
|
+
pyegeria/commands/cat/get_project_structure.py,sha256=5uxWMqNve592OT73GRCO2KoBkgLWRNuQv_emWpS-Fw8,5975
|
26
26
|
pyegeria/commands/cat/get_tech_type_elements.py,sha256=IznytHXwDOFriGM6mypV9wuEeM-vT2s66cUzf-IROog,6147
|
27
27
|
pyegeria/commands/cat/glossary_actions.py,sha256=SO0PH_Zy34Sbv31FEwCnZalNcxjGVeMT3T352BxSY34,19590
|
28
28
|
pyegeria/commands/cat/list_assets.py,sha256=CdJ2coKvvQv2VwJO0Sp9Eg9Fu_uvpC21tgjrdtT9Yz4,6315
|
@@ -227,26 +227,27 @@ pyegeria/egeria_tech_client.py,sha256=uycgYfCpb4jzFfaQ7I5JxbZ5PKsWdaWxLOJjbw6C2Z
|
|
227
227
|
pyegeria/feedback_manager_omvs.py,sha256=0xBs0p54vmdfVYYgQ8pOanLC4fxfgTk1Z61Y6D1U7_I,152978
|
228
228
|
pyegeria/full_omag_server_config.py,sha256=CQqLCy_3DZFvJZEOcGf50HWdFaWpiAIs6z-kKyjvpDA,47464
|
229
229
|
pyegeria/glossary_browser_omvs.py,sha256=hkYa5xGV_WXTUAMLx4VjsGhnC7PkVpmVFVcwfUTKDGE,109582
|
230
|
-
pyegeria/glossary_manager_omvs.py,sha256=
|
230
|
+
pyegeria/glossary_manager_omvs.py,sha256=ZJrRUwx3Z1ebbjy60_9PLYh7gAtInE94cPtsPRM7FtM,70273
|
231
231
|
pyegeria/m_test.py,sha256=M5-M2ZczsAJLXWfSeqTTADHdx6Ku-y4PbQ4M21JthAE,7778
|
232
|
-
pyegeria/md_processing_helpers.py,sha256=
|
233
|
-
pyegeria/md_processing_utils.py,sha256=
|
234
|
-
pyegeria/md_processing_utils_orig.py,sha256=
|
232
|
+
pyegeria/md_processing_helpers.py,sha256=sV-ciVg_xOGVGTH_CMpH2B5k3V5jzdFp_XvnQQ5xafw,2131
|
233
|
+
pyegeria/md_processing_utils.py,sha256=n7PT3wsnv6eLhgnRo_1N3C-HTrHK6459FTsJ1hqgbTU,65055
|
234
|
+
pyegeria/md_processing_utils_orig.py,sha256=WGoVpsV03wwgv9YwDDHZ0EO4-opN8BdoISt4ZhkYGuQ,52492
|
235
235
|
pyegeria/mermaid_utilities.py,sha256=sQqdFUWdNpHu9d3Tk9UVe80M-5bOzses0XcFYX5FF-E,54254
|
236
236
|
pyegeria/metadata_explorer_omvs.py,sha256=xHnZTQKbd6XwOhYia-RiIisrvZcqHi0SL1l6OCf04Gk,86911
|
237
237
|
pyegeria/my_profile_omvs.py,sha256=d0oJYCJG7pS9BINPuGciVa00ac0jwPHNANXDCLginEc,34720
|
238
238
|
pyegeria/platform_services.py,sha256=YEpZsGGsbSdesN8ceyFhV0OMzKG6znTZrREMTRimLps,41701
|
239
|
-
pyegeria/project_manager_omvs.py,sha256=
|
239
|
+
pyegeria/project_manager_omvs.py,sha256=UA-HcLTJ0rAYQXv-l5xLN7hTUinBTsrbwT_MmC8lx0U,70165
|
240
240
|
pyegeria/registered_info.py,sha256=y0-LgDIQXpph0lEWxIOG3_HsqX_Z2iAIb3xu4Aa4B70,6344
|
241
241
|
pyegeria/runtime_manager_omvs.py,sha256=Z5wY9ignNjil8O6yjihZftxkGoh9A4PQDcXhoIsOIT8,79698
|
242
242
|
pyegeria/server_operations.py,sha256=5k0KVz3u8qRLwtz16zT3J86LZY3pkUrMDcps8srmq1A,16831
|
243
|
+
pyegeria/shared_state.py,sha256=KqmvWAvct1o6Bte9accfAbI-qAZu-UtCUZiYi7eYYM8,907
|
243
244
|
pyegeria/solution_architect_omvs.py,sha256=x6CfPTyn1l2DFYVEFP0t_rT9uVjoFr596hBBeuVaMRg,22093
|
244
245
|
pyegeria/template_manager_omvs.py,sha256=PfJ9dOfmBvf59DgRdZ9Dl1Kl_UYqjF-JncXVnbCqLZU,42408
|
245
246
|
pyegeria/utils.py,sha256=GCt1C0bp0Xng1ahzbZhzV9qQwH7Dj93IaCt2dvWb-sg,5417
|
246
247
|
pyegeria/valid_metadata_omvs.py,sha256=Xq9DqBQvBFFJzaFIRKcVZ2k4gJvSh9yeXs_j-O3vn1w,65050
|
247
248
|
pyegeria/x_action_author_omvs.py,sha256=RcqSzahUKCtvb_3u_wyintAlc9WFkC_2v0E12TZs8lQ,6433
|
248
|
-
pyegeria-5.3.7.
|
249
|
-
pyegeria-5.3.7.
|
250
|
-
pyegeria-5.3.7.
|
251
|
-
pyegeria-5.3.7.
|
252
|
-
pyegeria-5.3.7.
|
249
|
+
pyegeria-5.3.7.8.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
250
|
+
pyegeria-5.3.7.8.dist-info/METADATA,sha256=4Pjg58x9foW-W7Uq0AbbwL4G2vdRvogrPtjP0ewZHs0,2740
|
251
|
+
pyegeria-5.3.7.8.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
|
252
|
+
pyegeria-5.3.7.8.dist-info/entry_points.txt,sha256=eAvQ_vkejlF3JzMzEc5VD93ymLA_hSFV0HM8fntG-d8,6791
|
253
|
+
pyegeria-5.3.7.8.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|