pyegeria 5.3.5.1__py3-none-any.whl → 5.3.5.2__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/asset_catalog_omvs.py +67 -11
- pyegeria/commands/cat/freddie_jupyter.py +124 -0
- pyegeria/commands/cat/freddie_md.py +158 -0
- pyegeria/commands/cat/freddie_utils.py +530 -0
- pyegeria/commands/cat/glossary_actions.py +112 -12
- pyegeria/commands/cli/egeria.py +4 -4
- pyegeria/commands/cli/egeria_cat.py +4 -4
- pyegeria/glossary_browser_omvs.py +2 -2
- pyegeria/glossary_manager_omvs.py +779 -570
- {pyegeria-5.3.5.1.dist-info → pyegeria-5.3.5.2.dist-info}/METADATA +2 -1
- {pyegeria-5.3.5.1.dist-info → pyegeria-5.3.5.2.dist-info}/RECORD +14 -11
- {pyegeria-5.3.5.1.dist-info → pyegeria-5.3.5.2.dist-info}/entry_points.txt +5 -2
- {pyegeria-5.3.5.1.dist-info → pyegeria-5.3.5.2.dist-info}/LICENSE +0 -0
- {pyegeria-5.3.5.1.dist-info → pyegeria-5.3.5.2.dist-info}/WHEEL +0 -0
@@ -0,0 +1,530 @@
|
|
1
|
+
"""
|
2
|
+
|
3
|
+
This file contains functions to parse and process Egeria Markdown (Freddie)
|
4
|
+
|
5
|
+
|
6
|
+
"""
|
7
|
+
|
8
|
+
import json
|
9
|
+
from jupyter_notebook_parser import JupyterNotebookParser
|
10
|
+
import nbformat
|
11
|
+
import os
|
12
|
+
import re
|
13
|
+
from pyegeria import EgeriaTech
|
14
|
+
from rich import box, print
|
15
|
+
from rich.console import Console
|
16
|
+
from rich.markdown import Markdown
|
17
|
+
from rich.prompt import Prompt
|
18
|
+
from rich.table import Table
|
19
|
+
import click
|
20
|
+
from pyegeria import EgeriaTech, body_slimmer, NO_GLOSSARIES_FOUND, NO_TERMS_FOUND, NO_ELEMENTS_FOUND, NO_PROJECTS_FOUND
|
21
|
+
from pyegeria._exceptions import (
|
22
|
+
InvalidParameterException,
|
23
|
+
PropertyServerException,
|
24
|
+
print_exception_response,
|
25
|
+
)
|
26
|
+
import datetime
|
27
|
+
commands = ["Create Glossary", "Update Glossary",
|
28
|
+
"Create Term", "Update Term",
|
29
|
+
"Create Personal Project", "Update Personal Project"]
|
30
|
+
ERROR = "ERROR-> "
|
31
|
+
INFO = "INFO- "
|
32
|
+
WARNING = "WARNING-> "
|
33
|
+
|
34
|
+
def is_valid_iso_date(date_text) -> bool:
|
35
|
+
"""Checks if the given string is a valid ISO date."""
|
36
|
+
try:
|
37
|
+
datetime.datetime.strptime(date_text, '%Y-%m-%d')
|
38
|
+
return True
|
39
|
+
except ValueError:
|
40
|
+
return False
|
41
|
+
|
42
|
+
def get_current_datetime_string():
|
43
|
+
"""Returns the current date and time as a human-readable string."""
|
44
|
+
now = datetime.datetime.now()
|
45
|
+
return now.strftime("%Y%m%d%H%M%S")
|
46
|
+
|
47
|
+
|
48
|
+
def extract_command(block: str) -> str | None:
|
49
|
+
match = re.search(r"#(.*?)(?:##|\n|$)", block) # Using a non capturing group
|
50
|
+
if match:
|
51
|
+
return match.group(1).strip()
|
52
|
+
return None
|
53
|
+
|
54
|
+
|
55
|
+
def extract_attribute (text: str, label: str) -> str | None:
|
56
|
+
"""
|
57
|
+
Extracts the glossary name from a string.
|
58
|
+
|
59
|
+
Args:
|
60
|
+
text: The input string.
|
61
|
+
label: The label to search for.
|
62
|
+
|
63
|
+
Returns:
|
64
|
+
The glossary name, or None if not found.
|
65
|
+
"""
|
66
|
+
pattern = r"## " + re.escape(label) + r"\n(.*?)(?:##|$)" # Construct pattern
|
67
|
+
match = re.search(pattern, text, re.DOTALL)
|
68
|
+
if match:
|
69
|
+
return match.group(1).strip()
|
70
|
+
return None
|
71
|
+
|
72
|
+
def update_a_command(txt: str, command: str, obj_type: str, q_name: str, u_guid: str)->str:
|
73
|
+
u_guid = u_guid if u_guid else " "
|
74
|
+
txt = txt.replace(f"{command}", f'**Update {obj_type}**\n') # update the command
|
75
|
+
txt = txt.replace('<GUID>', f'**GUID**\n{u_guid}') # update with GUID
|
76
|
+
txt = txt.replace('<Qualified Name>', f"**Qualified Name**\n{q_name}")
|
77
|
+
# if command == "Update Term":
|
78
|
+
# txt = txt.replace('Update Description', f"**Update Description**\n")
|
79
|
+
return txt
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
def process_glossary_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display" ) -> str | None:
|
84
|
+
"""
|
85
|
+
Processes a glossary create or update command by extracting key attributes such as
|
86
|
+
glossary name, language, description, and usage from the given cell.
|
87
|
+
|
88
|
+
:param txt: A string representing the input cell to be processed for
|
89
|
+
extracting glossary-related attributes.
|
90
|
+
:param directive: an optional string indicating the directive to be used - display, validate or execute
|
91
|
+
:return: A string summarizing the outcome of the processing.
|
92
|
+
"""
|
93
|
+
command = extract_command(txt)
|
94
|
+
object_type = command.split(' ')[1].strip()
|
95
|
+
object_action = command.split(' ')[0].strip()
|
96
|
+
|
97
|
+
glossary_name = extract_attribute(txt, 'Glossary Name')
|
98
|
+
print(f"\n==> Processing command: {command} for glossary: {glossary_name} with directive: {directive} ")
|
99
|
+
language = extract_attribute(txt, 'Language')
|
100
|
+
description = extract_attribute(txt, 'Description')
|
101
|
+
usage = extract_attribute(txt, 'Usage')
|
102
|
+
glossary_display = (f"\n* Command: {command}\n\t* Glossary: {glossary_name}\n\t"
|
103
|
+
f"* Language: {language}\n\t* Description: {description}\n\t"
|
104
|
+
f"* Usage: {usage}")
|
105
|
+
|
106
|
+
def validate_glossary(obj_action: str) -> tuple[bool, bool, str]:
|
107
|
+
valid = True
|
108
|
+
msg = ""
|
109
|
+
known_glossary_guid = None
|
110
|
+
known_q_name = None
|
111
|
+
|
112
|
+
glossary_details = egeria_client.get_glossaries_by_name(glossary_name)
|
113
|
+
if glossary_details == NO_GLOSSARIES_FOUND:
|
114
|
+
glossary_exists = False
|
115
|
+
else:
|
116
|
+
glossary_exists = True
|
117
|
+
|
118
|
+
if glossary_name is None:
|
119
|
+
msg = f"* {ERROR}Glossary name is missing\n"
|
120
|
+
valid = False
|
121
|
+
if language is None:
|
122
|
+
msg += f"* {ERROR}Language is missing\n"
|
123
|
+
valid = False
|
124
|
+
if description is None:
|
125
|
+
msg += f"* {INFO}Description is missing\n"
|
126
|
+
|
127
|
+
if obj_action == "Update":
|
128
|
+
q_name = extract_attribute(txt, 'Qualified Name')
|
129
|
+
|
130
|
+
if not glossary_exists:
|
131
|
+
msg += f"* {ERROR}Glossary {glossary_name} does not exist\n"
|
132
|
+
valid = False
|
133
|
+
if len(glossary_details) > 1 and glossary_exists:
|
134
|
+
msg += f"* {ERROR}More than one glossary with name {glossary_name} found\n"
|
135
|
+
valid = False
|
136
|
+
if len(glossary_details) == 1:
|
137
|
+
known_glossary_guid = glossary_details[0]['elementHeader'].get('guid', None)
|
138
|
+
known_q_name = glossary_details[0]['glossaryProperties'].get('qualifiedName',None)
|
139
|
+
if q_name is None:
|
140
|
+
msg += f"* {INFO}Qualified Name is missing => can use known qualified name of {known_q_name}\n"
|
141
|
+
valid = True
|
142
|
+
elif q_name != known_q_name:
|
143
|
+
msg += (f"* {ERROR}Glossary {glossary_name} qualifiedName mismatch between {q_name} and {known_q_name}\n")
|
144
|
+
valid = False
|
145
|
+
if valid:
|
146
|
+
msg += glossary_display
|
147
|
+
msg += f"* -->Glossary {glossary_name} exists and can be updated\n"
|
148
|
+
else:
|
149
|
+
msg += f"* --> validation failed\n"
|
150
|
+
msg+='---'
|
151
|
+
print(Markdown(msg))
|
152
|
+
return valid, glossary_exists, known_glossary_guid, known_q_name
|
153
|
+
|
154
|
+
elif obj_action == "Create":
|
155
|
+
if glossary_exists:
|
156
|
+
msg += f"{ERROR}Glossary {glossary_name} already exists"
|
157
|
+
valid = False
|
158
|
+
else:
|
159
|
+
msg += f"-->It is valid to create Glossary \'{glossary_name}\' with:\n"
|
160
|
+
print(Markdown(msg))
|
161
|
+
return valid, glossary_exists, known_glossary_guid, known_q_name
|
162
|
+
|
163
|
+
if directive == "display":
|
164
|
+
print(Markdown(glossary_display))
|
165
|
+
return None
|
166
|
+
|
167
|
+
elif directive == "validate":
|
168
|
+
is_valid, exists, known_guid, known_q_name = validate_glossary(object_action)
|
169
|
+
valid = is_valid if is_valid else None
|
170
|
+
return valid
|
171
|
+
|
172
|
+
elif directive == "process":
|
173
|
+
is_valid, exists, known_guid, known_q_name = validate_glossary(object_action)
|
174
|
+
if not is_valid:
|
175
|
+
return None
|
176
|
+
if object_action == "Update":
|
177
|
+
if not exists:
|
178
|
+
print(f"\n-->Glossary {glossary_name} does not exist")
|
179
|
+
return None
|
180
|
+
body = {
|
181
|
+
"class": "ReferenceableRequestBody",
|
182
|
+
"elementProperties":
|
183
|
+
{
|
184
|
+
"class": "GlossaryProperties",
|
185
|
+
"qualifiedName": known_q_name,
|
186
|
+
"description": description,
|
187
|
+
"language": language,
|
188
|
+
"usage": usage
|
189
|
+
}
|
190
|
+
}
|
191
|
+
egeria_client.update_glossary(known_guid, body)
|
192
|
+
print(f"\n-->Updated Glossary {glossary_name} with GUID {known_guid}")
|
193
|
+
return update_a_command(txt, command, object_type, known_q_name, known_guid)
|
194
|
+
elif object_action == "Create" :
|
195
|
+
guid = None
|
196
|
+
q_name = f"Glossary:{glossary_name}:{get_current_datetime_string()}"
|
197
|
+
|
198
|
+
if exists:
|
199
|
+
print(f"Glossary {glossary_name} already exists")
|
200
|
+
return update_a_command(txt, command, object_type, known_q_name, known_guid)
|
201
|
+
else:
|
202
|
+
guid = egeria_client.create_glossary(glossary_name, description,
|
203
|
+
language, usage)
|
204
|
+
glossary = egeria_client.get_glossary_by_guid(guid)
|
205
|
+
if glossary == NO_GLOSSARIES_FOUND:
|
206
|
+
print(f"Just created with GUID {guid} but Glossary not found")
|
207
|
+
return None
|
208
|
+
q_name = glossary['glossaryProperties']["qualifiedName"]
|
209
|
+
return update_a_command(txt, command, object_type, q_name, guid)
|
210
|
+
|
211
|
+
|
212
|
+
def process_term_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display" ) -> str | None:
|
213
|
+
"""
|
214
|
+
Processes a term create or update command by extracting key attributes such as
|
215
|
+
term name, summary, description, abbreviation, examples, usage, version, and status from the given cell.
|
216
|
+
|
217
|
+
:param txt: A string representing the input cell to be processed for
|
218
|
+
extracting glossary-related attributes.
|
219
|
+
:param directive: an optional string indicating the directive to be used - display, validate or execute
|
220
|
+
:return: A string summarizing the outcome of the processing.
|
221
|
+
"""
|
222
|
+
|
223
|
+
command = extract_command(txt)
|
224
|
+
object_type = command.split(' ')[1].strip()
|
225
|
+
object_action = command.split(' ')[0].strip()
|
226
|
+
|
227
|
+
term_name = extract_attribute(txt, 'Term Name')
|
228
|
+
summary = extract_attribute(txt, 'Summary')
|
229
|
+
description = extract_attribute(txt, 'Description')
|
230
|
+
abbreviation = extract_attribute(txt, 'Abbreviation')
|
231
|
+
examples = extract_attribute(txt, 'Examples')
|
232
|
+
usage = extract_attribute(txt, 'Usage')
|
233
|
+
version = extract_attribute(txt, 'Version')
|
234
|
+
status = extract_attribute(txt, 'Status')
|
235
|
+
glossary_name = extract_attribute(txt, 'Glossary Name')
|
236
|
+
|
237
|
+
print(f"\n==> Processing command: {command} for Term {term_name} with directive: {directive}")
|
238
|
+
|
239
|
+
def validate_term(obj_action: str) -> tuple[bool, bool, str]:
|
240
|
+
valid = True
|
241
|
+
msg = ""
|
242
|
+
known_term_guid = None
|
243
|
+
known_q_name = None
|
244
|
+
|
245
|
+
term_details = egeria_client.get_terms_by_name(term_name)
|
246
|
+
if term_details == NO_TERMS_FOUND:
|
247
|
+
term_exists = False
|
248
|
+
else:
|
249
|
+
term_exists = True
|
250
|
+
|
251
|
+
if term_name is None:
|
252
|
+
msg = f"* {ERROR}Term name is missing\n"
|
253
|
+
valid = False
|
254
|
+
if glossary_name is None:
|
255
|
+
msg += f"* {ERROR}Glossary name is missing\n"
|
256
|
+
valid = False
|
257
|
+
if status is None:
|
258
|
+
msg += f"* {INFO}Term status is missing - will default to DRAFT"
|
259
|
+
if obj_action == "Update": # check to see if provided information exists and is consistent with existing info
|
260
|
+
|
261
|
+
if not term_exists:
|
262
|
+
msg += f"* {ERROR}Term {term_name} does not exist\n"
|
263
|
+
valid = False
|
264
|
+
|
265
|
+
if len(term_details) > 1 and term_exists:
|
266
|
+
msg += f"* {ERROR}More than one term with name {term_name} found\n"
|
267
|
+
valid = False
|
268
|
+
elif len(term_details) == 1:
|
269
|
+
known_term_guid = term_details[0]['elementHeader'].get('guid', None)
|
270
|
+
known_q_name = term_details[0]['glossaryTermProperties'].get('qualifiedName', None)
|
271
|
+
if q_name != known_q_name:
|
272
|
+
msg += (f"* {ERROR}Term {term_name} qualifiedName mismatch between {q_name} and {known_q_name}\n")
|
273
|
+
valid = False
|
274
|
+
else:
|
275
|
+
msg += f"--> * Term {term_name} exists and can be updated\n"
|
276
|
+
msg += term_display
|
277
|
+
msg += '\n---\n'
|
278
|
+
print(Markdown(msg))
|
279
|
+
return valid, term_exists, known_term_guid
|
280
|
+
|
281
|
+
elif obj_action == 'Create': # if the command is create, check that it doesn't already exist
|
282
|
+
if term_exists:
|
283
|
+
msg += f"{WARNING}Term \'{term_name}\' already exists\n"
|
284
|
+
|
285
|
+
else:
|
286
|
+
msg += f"-->It is valid to create Term \'{term_name}\' with: {term_display}\n"
|
287
|
+
msg += '\n---\n'
|
288
|
+
print(Markdown(msg))
|
289
|
+
return valid, term_exists, known_term_guid
|
290
|
+
|
291
|
+
if object_action == "Update":
|
292
|
+
term_guid = extract_attribute(txt, 'GUID')
|
293
|
+
term_guid = term_guid if term_guid else " "
|
294
|
+
q_name = extract_attribute(txt, 'Qualified Name')
|
295
|
+
q_name = q_name if q_name else " "
|
296
|
+
update_description = extract_attribute(txt, 'Update Description')
|
297
|
+
update_description = update_description if update_description else " "
|
298
|
+
term_display = (f"\n* Command: {command}\n\t* Glossary: {glossary_name}\n\t"
|
299
|
+
f"* Term Name: {term_name}\n\t* Summary: {summary}\n\t* Description: {description}\n\t"
|
300
|
+
f"* Abbreviation: {abbreviation}\n\t* Examples: {examples}\n\t* Usage: {usage}\n\t"
|
301
|
+
f"* Version: {version}\n\t* Status: {status}\n\t* GUID: {term_guid}\n\t* Qualified Name: {q_name}"
|
302
|
+
f"\n\t* Update Description: {update_description}\n")
|
303
|
+
else:
|
304
|
+
term_display = (f"\n* Command: {command}\n\t* Glossary: {glossary_name}\n\t"
|
305
|
+
f"* Term Name: {term_name}\n\t* Summary: {summary}\n\t* Description: {description}\n\t"
|
306
|
+
f"* Abbreviation: {abbreviation}\n\t* Examples: {examples}\n\t* Usage: {usage}\n\t"
|
307
|
+
f"* Version: {version}\n\t* Status: {status}\n")
|
308
|
+
|
309
|
+
|
310
|
+
if directive == "display":
|
311
|
+
print(Markdown(term_display))
|
312
|
+
return None
|
313
|
+
elif directive == "validate":
|
314
|
+
is_valid, exists, known_guid = validate_term(object_action)
|
315
|
+
valid = is_valid if is_valid else None
|
316
|
+
return valid
|
317
|
+
elif directive == "process":
|
318
|
+
is_valid, exists, known_guid = validate_term(object_action)
|
319
|
+
if not is_valid: # First validate the term before we process it
|
320
|
+
return None
|
321
|
+
|
322
|
+
if object_action == "Update":
|
323
|
+
if not exists:
|
324
|
+
print(f"\n-->Term {term_name} does not exist")
|
325
|
+
return None
|
326
|
+
body = {
|
327
|
+
"class": "ReferenceableRequestBody",
|
328
|
+
"elementProperties":
|
329
|
+
{
|
330
|
+
"class": "GlossaryTermProperties",
|
331
|
+
"qualifiedName": q_name,
|
332
|
+
"summary": summary,
|
333
|
+
"description": description,
|
334
|
+
"abbreviation": abbreviation,
|
335
|
+
"examples": examples,
|
336
|
+
"usage": usage,
|
337
|
+
"publishVersionIdentifier": version,
|
338
|
+
"status": status
|
339
|
+
},
|
340
|
+
"updateDescription": update_description
|
341
|
+
}
|
342
|
+
egeria_client.update_term(known_guid, body)
|
343
|
+
print(f"\n-->Updated Term {term_name} with GUID {known_guid}")
|
344
|
+
return update_a_command(txt, command, object_type, q_name, known_guid)
|
345
|
+
|
346
|
+
elif object_action == "Create" :
|
347
|
+
guid = None
|
348
|
+
q_name = f"GlossaryTerm:{term_name}:{get_current_datetime_string()}"
|
349
|
+
if exists:
|
350
|
+
print(f"\n-->Term {term_name} exists and document updated")
|
351
|
+
return update_a_command(txt, command, object_type, q_name, guid)
|
352
|
+
else:
|
353
|
+
## get the guid for the glossary from the name
|
354
|
+
glossary_guid = egeria_client.__get_guid__(property_name="displayName", display_name=glossary_name)
|
355
|
+
if glossary_guid == NO_ELEMENTS_FOUND:
|
356
|
+
print(f"Glossary {glossary_name} not found")
|
357
|
+
return None
|
358
|
+
term_body = {
|
359
|
+
"class": "ReferenceableRequestBody",
|
360
|
+
"elementProperties":
|
361
|
+
{
|
362
|
+
"class": "GlossaryTermProperties",
|
363
|
+
"qualifiedName":q_name,
|
364
|
+
"displayName": term_name,
|
365
|
+
"summary": summary,
|
366
|
+
"description": description,
|
367
|
+
"abbreviation": abbreviation,
|
368
|
+
"examples": examples,
|
369
|
+
"usage": usage,
|
370
|
+
"publishVersionIdentifier": version
|
371
|
+
# "additionalProperties":
|
372
|
+
# {
|
373
|
+
# "propertyName1": "xxxx",
|
374
|
+
# "propertyName2": "xxxx"
|
375
|
+
# }
|
376
|
+
},
|
377
|
+
"initialStatus": status
|
378
|
+
}
|
379
|
+
term_guid = egeria_client.create_controlled_glossary_term(glossary_guid, term_body)
|
380
|
+
print(f"\n-->Created Term {term_name} with GUID {term_guid}")
|
381
|
+
return update_a_command(txt, command, object_type, q_name, term_guid)
|
382
|
+
|
383
|
+
def process_per_proj_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display" ) -> str | None:
|
384
|
+
"""
|
385
|
+
Processes a personal project create or update command by extracting key attributes such as
|
386
|
+
glossary name, language, description, and usage from the given cell.
|
387
|
+
|
388
|
+
:param txt: A string representing the input cell to be processed for
|
389
|
+
extracting glossary-related attributes.
|
390
|
+
:param directive: an optional string indicating the directive to be used - display, validate or execute
|
391
|
+
:return: A string summarizing the outcome of the processing.
|
392
|
+
"""
|
393
|
+
command = extract_command(txt)
|
394
|
+
object = command.split()
|
395
|
+
object_type = f"{object[1]} {object[2]}"
|
396
|
+
object_action = object[0]
|
397
|
+
|
398
|
+
project_name = extract_attribute(txt, 'Project Name')
|
399
|
+
description = extract_attribute(txt, 'Description')
|
400
|
+
project_identifier = extract_attribute(txt, 'Project Identifier')
|
401
|
+
project_status = extract_attribute(txt, 'Project Status')
|
402
|
+
project_phase = extract_attribute(txt, 'Project Phase')
|
403
|
+
project_health = extract_attribute(txt, 'Project Health')
|
404
|
+
start_date = extract_attribute(txt, 'Start Date')
|
405
|
+
planned_end_date = extract_attribute(txt, 'Planned End Date')
|
406
|
+
print(f"\n==> Processing command: {command} for project: {project_name} with directive: {directive} ")
|
407
|
+
|
408
|
+
project_display = (f"\n* Command: {command}\n\t* Project: {project_name}\n\t"
|
409
|
+
f"* Status: {project_status}\n\t* Description: {description}\n\t"
|
410
|
+
f"* Phase: {project_phase}\n\t* Health: {project_health}\n\t"
|
411
|
+
f"* Start Date: {start_date}\n\t* Planned End Date: {planned_end_date}\n")
|
412
|
+
|
413
|
+
def validate_project(obj_action: str) -> tuple[bool, bool, str, str]:
|
414
|
+
valid = True
|
415
|
+
msg = ""
|
416
|
+
known_guid = None
|
417
|
+
known_q_name = None
|
418
|
+
|
419
|
+
project_details = egeria_client.get_projects_by_name(project_name)
|
420
|
+
if project_details == NO_PROJECTS_FOUND:
|
421
|
+
project_exists = False
|
422
|
+
else:
|
423
|
+
project_exists = True
|
424
|
+
|
425
|
+
if project_name is None:
|
426
|
+
msg = f"* {ERROR}Project name is missing\n"
|
427
|
+
valid = False
|
428
|
+
if project_status is None:
|
429
|
+
msg += f"* {INFO}No Project status found\n"
|
430
|
+
|
431
|
+
if description is None:
|
432
|
+
msg += f"* {INFO}No Description found\n"
|
433
|
+
|
434
|
+
if project_identifier is None:
|
435
|
+
msg += f"* {INFO}No Project Identifier found\n"
|
436
|
+
|
437
|
+
if project_phase is None:
|
438
|
+
msg += f"* {INFO}No Project Phase found\n"
|
439
|
+
|
440
|
+
if project_health is None:
|
441
|
+
msg += f"* {INFO}No Project Health found\n"
|
442
|
+
|
443
|
+
if start_date is None:
|
444
|
+
msg += f"* {INFO}No Start Date found\n"
|
445
|
+
elif not is_valid_iso_date(start_date):
|
446
|
+
msg += f"* {ERROR}Start Date is not a valid ISO date of form YYYY-MM-DD\n"
|
447
|
+
valid = False
|
448
|
+
|
449
|
+
if planned_end_date is None:
|
450
|
+
msg += f"* {INFO} No Planned End Date found\n"
|
451
|
+
elif not is_valid_iso_date(planned_end_date):
|
452
|
+
msg += f"* {ERROR}Planned End Date is not a valid ISO date of form YYYY-MM-DD\n"
|
453
|
+
valid = False
|
454
|
+
|
455
|
+
if obj_action == "Update":
|
456
|
+
q_name = extract_attribute(txt, 'Qualified Name')
|
457
|
+
|
458
|
+
if not project_exists:
|
459
|
+
msg += f"* {ERROR}Project {project_name} does not exist\n"
|
460
|
+
valid = False
|
461
|
+
if len(project_details) > 1 and project_exists:
|
462
|
+
msg += f"* {ERROR}More than one projecty with name {project_name} found\n"
|
463
|
+
valid = False
|
464
|
+
if len(project_details) == 1:
|
465
|
+
known_guid = project_details[0]['elementHeader'].get('guid', None)
|
466
|
+
known_q_name = project_details[0]['glossaryProperties'].get('qualifiedName',None)
|
467
|
+
if q_name is None:
|
468
|
+
msg += f"* {INFO}Qualified Name is missing => can use known qualified name of {known_q_name}\n"
|
469
|
+
valid = True
|
470
|
+
elif q_name != known_q_name:
|
471
|
+
msg += (f"* {ERROR}Project {project_name} qualifiedName mismatch between {q_name} and {known_q_name}\n")
|
472
|
+
valid = False
|
473
|
+
if valid:
|
474
|
+
msg += project_display
|
475
|
+
msg += f"* -->Project {project_name} exists and can be updated\n"
|
476
|
+
else:
|
477
|
+
msg += f"* --> validation failed\n"
|
478
|
+
msg+='---'
|
479
|
+
print(Markdown(msg))
|
480
|
+
return valid, project_exists, known_guid, known_q_name
|
481
|
+
|
482
|
+
elif obj_action == "Create":
|
483
|
+
if project_exists:
|
484
|
+
msg += f"\n{ERROR}Project {project_name} already exists"
|
485
|
+
else:
|
486
|
+
msg += f"\n-->It is valid to create Project \'{project_name}\' with:\n"
|
487
|
+
print(Markdown(msg))
|
488
|
+
return valid, project_exists, known_guid, known_q_name
|
489
|
+
|
490
|
+
if directive == "display":
|
491
|
+
print(Markdown(project_display))
|
492
|
+
return None
|
493
|
+
|
494
|
+
elif directive == "validate":
|
495
|
+
is_valid, exists, known_guid, known_q_name = validate_project(object_action)
|
496
|
+
valid = is_valid if is_valid else None
|
497
|
+
return valid
|
498
|
+
|
499
|
+
elif directive == "process":
|
500
|
+
is_valid, exists, known_guid, known_q_name = validate_project(object_action)
|
501
|
+
if not is_valid:
|
502
|
+
return None
|
503
|
+
if object_action == "Update":
|
504
|
+
if not exists:
|
505
|
+
print(f"\n\n-->Project {project_name} does not exist")
|
506
|
+
return None
|
507
|
+
|
508
|
+
egeria_client.update_project(known_guid, known_q_name, project_identifier, project_name,
|
509
|
+
description,project_status,project_phase,project_health,
|
510
|
+
start_date, planned_end_date,False)
|
511
|
+
print(f"\n-->Updated Project {project_name} with GUID {known_guid}")
|
512
|
+
return update_a_command(txt, command, object_type, known_q_name, known_guid)
|
513
|
+
elif object_action == "Create" :
|
514
|
+
guid = None
|
515
|
+
|
516
|
+
if exists:
|
517
|
+
print(f"Project {project_name} already exists and")
|
518
|
+
return update_a_command(txt, command, object_type, known_q_name, known_guid)
|
519
|
+
else:
|
520
|
+
guid = egeria_client.create_project(None,None, None, False,
|
521
|
+
project_name, description,
|
522
|
+
"PersonalProject",project_identifier, True,
|
523
|
+
project_status, project_phase, project_health,
|
524
|
+
start_date, planned_end_date)
|
525
|
+
project_g = egeria_client.get_project(guid)
|
526
|
+
if project_g == NO_GLOSSARIES_FOUND:
|
527
|
+
print(f"Just created with GUID {guid} but Project not found")
|
528
|
+
return None
|
529
|
+
q_name = project_g['prjectProperties']["qualifiedName"]
|
530
|
+
return update_a_command(txt, command, object_type, q_name, guid)
|