pyegeria 5.4.4.1__py3-none-any.whl → 5.4.4.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyegeria might be problematic. Click here for more details.
- commands/cat/list_format_set.py +6 -2
- md_processing/.obsidian/plugins/obsidian-sample-plugin/.git/index +0 -0
- md_processing/md_commands/data_designer_commands.py +17 -11
- md_processing/md_commands/ext_ref_commands.py +9 -6
- md_processing/md_commands/glossary_commands.py +6 -2
- md_processing/md_commands/governance_officer_commands.py +8 -3
- md_processing/md_commands/product_manager_commands.py +9 -6
- md_processing/md_commands/project_commands.py +5 -2
- md_processing/md_processing_utils/common_md_proc_utils.py +159 -127
- md_processing/md_processing_utils/common_md_utils.py +7 -4
- md_processing/md_processing_utils/extraction_utils.py +75 -36
- pyegeria/__init__.py +1 -1
- pyegeria/_client_new.py +469 -44
- pyegeria/_output_formats.py +1338 -141
- pyegeria/external_references.py +100 -209
- pyegeria/glossary_manager.py +2 -1
- pyegeria/governance_officer.py +1 -4
- pyegeria/output_formatter.py +4 -0
- pyegeria/utils.py +115 -64
- {pyegeria-5.4.4.1.dist-info → pyegeria-5.4.4.3.dist-info}/METADATA +1 -1
- {pyegeria-5.4.4.1.dist-info → pyegeria-5.4.4.3.dist-info}/RECORD +24 -25
- md_processing/md_commands/old_solution_architect_commands.py +0 -1139
- {pyegeria-5.4.4.1.dist-info → pyegeria-5.4.4.3.dist-info}/LICENSE +0 -0
- {pyegeria-5.4.4.1.dist-info → pyegeria-5.4.4.3.dist-info}/WHEEL +0 -0
- {pyegeria-5.4.4.1.dist-info → pyegeria-5.4.4.3.dist-info}/entry_points.txt +0 -0
|
@@ -8,9 +8,11 @@ import re
|
|
|
8
8
|
from typing import List, Optional
|
|
9
9
|
|
|
10
10
|
from loguru import logger
|
|
11
|
+
from pydantic import ValidationError
|
|
11
12
|
from rich import print
|
|
12
13
|
from rich.markdown import Markdown
|
|
13
14
|
from rich.console import Console
|
|
15
|
+
from pyegeria.utils import parse_to_dict
|
|
14
16
|
|
|
15
17
|
from md_processing.md_processing_utils.common_md_utils import (get_current_datetime_string, get_element_dictionary,
|
|
16
18
|
update_element_dictionary,
|
|
@@ -26,7 +28,8 @@ from md_processing.md_processing_utils.common_md_utils import (update_element_di
|
|
|
26
28
|
from md_processing.md_processing_utils.extraction_utils import (extract_command_plus, update_a_command)
|
|
27
29
|
from md_processing.md_processing_utils.md_processing_constants import (get_command_spec)
|
|
28
30
|
from md_processing.md_processing_utils.message_constants import (ERROR, INFO, WARNING, ALWAYS, EXISTS_REQUIRED)
|
|
29
|
-
from pyegeria import EgeriaTech, select_output_format_set
|
|
31
|
+
from pyegeria import EgeriaTech, select_output_format_set, PyegeriaException, print_basic_exception, \
|
|
32
|
+
print_validation_error
|
|
30
33
|
|
|
31
34
|
from pyegeria._globals import DEBUG_LEVEL
|
|
32
35
|
|
|
@@ -93,131 +96,157 @@ def parse_upsert_command(egeria_client: EgeriaTech, object_type: str, object_act
|
|
|
93
96
|
|
|
94
97
|
for attr in attributes:
|
|
95
98
|
for key in attr:
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
if attr[key].get('input_required', False) is True:
|
|
120
|
-
if_missing = ERROR
|
|
121
|
-
else:
|
|
122
|
-
if_missing = INFO
|
|
123
|
-
|
|
124
|
-
# lab = [item.strip() for item in re.split(r'[;,\n]+',attr[key]['attr_labels'])]
|
|
125
|
-
lab = split_tb_string(attr[key]['attr_labels'])
|
|
126
|
-
labels: set = set()
|
|
127
|
-
labels.add(key.strip())
|
|
128
|
-
if key == 'Display Name':
|
|
129
|
-
labels.add(object_type.strip())
|
|
130
|
-
if lab is not None and lab != [""]:
|
|
131
|
-
labels.update(lab)
|
|
132
|
-
|
|
133
|
-
default_value = attr[key].get('default_value', None)
|
|
134
|
-
|
|
135
|
-
style = attr[key]['style']
|
|
136
|
-
if style in ['Simple', 'Comment']:
|
|
137
|
-
parsed_attributes[key] = proc_simple_attribute(txt, object_action, labels, if_missing, default_value)
|
|
138
|
-
elif style == 'Dictionary':
|
|
139
|
-
parsed_attributes[key] = proc_dictionary_attribute(txt, object_action, labels, if_missing, default_value)
|
|
140
|
-
parsed_attributes[key]['name_list'] = json.dumps(parsed_attributes[key]['value'], indent=2)
|
|
141
|
-
|
|
142
|
-
elif style == 'Valid Value':
|
|
143
|
-
parsed_attributes[key] = proc_valid_value(txt, object_action, labels,
|
|
144
|
-
attr[key].get('valid_values', None), if_missing,
|
|
145
|
-
default_value)
|
|
146
|
-
elif style == 'QN':
|
|
147
|
-
parsed_attributes[key] = proc_el_id(egeria_client, command_display_name, command_qn_prefix, labels, txt,
|
|
148
|
-
object_action, version, if_missing)
|
|
149
|
-
if key == 'Qualified Name' and parsed_attributes[key]['value'] and parsed_attributes[key][
|
|
150
|
-
'exists'] is False:
|
|
151
|
-
parsed_output['exists'] = False
|
|
152
|
-
elif style == 'ID':
|
|
153
|
-
parsed_attributes[key] = proc_el_id(egeria_client, command_display_name, command_qn_prefix, labels, txt,
|
|
154
|
-
object_action, version, if_missing)
|
|
155
|
-
|
|
156
|
-
parsed_output['guid'] = parsed_attributes[key].get('guid', None)
|
|
157
|
-
parsed_output['qualified_name'] = parsed_attributes[key].get('qualified_name', None)
|
|
158
|
-
parsed_output['exists'] = parsed_attributes[key]['exists']
|
|
159
|
-
if parsed_attributes[key]['valid'] is False:
|
|
160
|
-
parsed_output['valid'] = False
|
|
161
|
-
parsed_output['reason'] += parsed_attributes[key]['reason']
|
|
162
|
-
|
|
163
|
-
elif style == 'Reference Name':
|
|
164
|
-
parsed_attributes[key] = proc_ids(egeria_client, key, labels, txt, object_action, if_missing)
|
|
165
|
-
if ((if_missing == ERROR) and parsed_attributes[key].get("value", None) and parsed_attributes[key][
|
|
166
|
-
'exists'] is False):
|
|
167
|
-
msg = f"Reference Name `{parsed_attributes[key]['value']}` is specified but does not exist"
|
|
168
|
-
logger.error(msg)
|
|
169
|
-
parsed_output['valid'] = False
|
|
170
|
-
parsed_output['reason'] += msg
|
|
171
|
-
elif parsed_attributes[key]['valid'] is False:
|
|
172
|
-
parsed_output['valid'] = False
|
|
173
|
-
parsed_output['reason'] += parsed_attributes[key]['reason']
|
|
174
|
-
|
|
175
|
-
elif style == 'GUID':
|
|
176
|
-
parsed_attributes[key] = proc_simple_attribute(txt, object_action, labels, if_missing)
|
|
177
|
-
elif style == 'Ordered Int':
|
|
178
|
-
parsed_attributes[key] = proc_simple_attribute(txt, object_action, labels, if_missing)
|
|
179
|
-
elif style == 'Simple Int':
|
|
180
|
-
parsed_attributes[key] = proc_simple_attribute(txt, object_action, labels, if_missing, default_value, "int")
|
|
181
|
-
elif style == 'Simple List':
|
|
182
|
-
parsed_attributes[key] = proc_simple_attribute(txt, object_action, labels, if_missing, default_value)
|
|
183
|
-
name_list = parsed_attributes[key]['value']
|
|
184
|
-
# attribute = re.split(r'[;,\n]+', name_list) if name_list is not None else None
|
|
185
|
-
attribute = split_tb_string(name_list)
|
|
186
|
-
parsed_attributes[key]['value'] = attribute
|
|
187
|
-
parsed_attributes[key]['name_list'] = name_list
|
|
188
|
-
elif style == 'Parent':
|
|
189
|
-
parsed_attributes[key] = proc_simple_attribute(txt, object_action, labels, if_missing, default_value)
|
|
190
|
-
elif style == 'Bool':
|
|
191
|
-
parsed_attributes[key] = proc_bool_attribute(txt, object_action, labels, if_missing, default_value)
|
|
192
|
-
elif style == "Dictionary List":
|
|
193
|
-
parsed_attributes[key] = proc_simple_attribute(txt, object_action, labels, if_missing, default_value)
|
|
194
|
-
parsed_attributes[key]['list'] = json.loads(parsed_attributes[key]['value'])
|
|
195
|
-
|
|
99
|
+
try:
|
|
100
|
+
# Run some checks to see if the attribute is appropriate to the operation and usage level
|
|
101
|
+
for_update = attr[key].get('inUpdate', True)
|
|
102
|
+
level = attr[key].get('level', 'Basic')
|
|
103
|
+
msg = (f"___\nProcessing `{key}` in `{object_action}` on a `{object_type}` "
|
|
104
|
+
f"\n\twith usage level: `{EGERIA_USAGE_LEVEL}` and attribute level `{level}` and for_update `"
|
|
105
|
+
f"{for_update}`\n")
|
|
106
|
+
logger.trace(msg)
|
|
107
|
+
if for_update is False and object_action == "Update":
|
|
108
|
+
logger.trace(f"Attribute `{key}`is not allowed for `Update`", highlight=True)
|
|
109
|
+
continue
|
|
110
|
+
if EGERIA_USAGE_LEVEL == "Basic" and level != "Basic":
|
|
111
|
+
logger.trace(f"Attribute `{key}` is not supported for `{EGERIA_USAGE_LEVEL}` usage level. Skipping.",
|
|
112
|
+
highlight=True)
|
|
113
|
+
continue
|
|
114
|
+
if EGERIA_USAGE_LEVEL == "Advanced" and level in ["Expert", "Invisible"]:
|
|
115
|
+
logger.trace(f"Attribute `{key}` is not supported for `{EGERIA_USAGE_LEVEL}` usage level. Skipping.",
|
|
116
|
+
highlight=True)
|
|
117
|
+
continue
|
|
118
|
+
if EGERIA_USAGE_LEVEL == "Expert" and level == "Invisible":
|
|
119
|
+
logger.trace(f"Attribute `{key}` is not supported for `{EGERIA_USAGE_LEVEL}` usage level. Skipping.",
|
|
120
|
+
highlight=True)
|
|
121
|
+
continue
|
|
196
122
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
123
|
+
if attr[key].get('input_required', False) is True:
|
|
124
|
+
if_missing = ERROR
|
|
125
|
+
else:
|
|
126
|
+
if_missing = INFO
|
|
127
|
+
|
|
128
|
+
# lab = [item.strip() for item in re.split(r'[;,\n]+',attr[key]['attr_labels'])]
|
|
129
|
+
lab = split_tb_string(attr[key]['attr_labels'])
|
|
130
|
+
labels: set = set()
|
|
131
|
+
labels.add(key.strip())
|
|
132
|
+
if key == 'Display Name':
|
|
133
|
+
labels.add(object_type.strip())
|
|
134
|
+
if lab is not None and lab != [""]:
|
|
135
|
+
labels.update(lab)
|
|
136
|
+
|
|
137
|
+
default_value = attr[key].get('default_value', None)
|
|
138
|
+
|
|
139
|
+
style = attr[key]['style']
|
|
140
|
+
if style in ['Simple', 'Comment']:
|
|
141
|
+
parsed_attributes[key] = proc_simple_attribute(txt, object_action, labels, if_missing, default_value)
|
|
142
|
+
elif style == 'Dictionary':
|
|
143
|
+
parsed_attributes[key] = proc_dictionary_attribute(txt, object_action, labels, if_missing, default_value)
|
|
144
|
+
if key in parsed_attributes and parsed_attributes[key] is not None:
|
|
145
|
+
if parsed_attributes[key].get('value', None) is not None:
|
|
146
|
+
if isinstance(parsed_attributes[key]['value'], dict):
|
|
147
|
+
parsed_attributes[key]['dict'] = json.dumps(parsed_attributes[key]['value'], indent=2)
|
|
148
|
+
else:
|
|
149
|
+
continue
|
|
150
|
+
else:
|
|
151
|
+
continue
|
|
152
|
+
|
|
153
|
+
elif style == 'Valid Value':
|
|
154
|
+
parsed_attributes[key] = proc_valid_value(txt, object_action, labels,
|
|
155
|
+
attr[key].get('valid_values', None), if_missing,
|
|
156
|
+
default_value)
|
|
157
|
+
elif style == 'QN':
|
|
158
|
+
parsed_attributes[key] = proc_el_id(egeria_client, command_display_name, command_qn_prefix, labels, txt,
|
|
159
|
+
object_action, version, if_missing)
|
|
160
|
+
if key == 'Qualified Name' and parsed_attributes[key]['value'] and parsed_attributes[key][
|
|
161
|
+
'exists'] is False:
|
|
162
|
+
parsed_output['exists'] = False
|
|
163
|
+
elif style == 'ID':
|
|
164
|
+
parsed_attributes[key] = proc_el_id(egeria_client, command_display_name, command_qn_prefix, labels, txt,
|
|
165
|
+
object_action, version, if_missing)
|
|
166
|
+
|
|
167
|
+
parsed_output['guid'] = parsed_attributes[key].get('guid', None)
|
|
168
|
+
parsed_output['qualified_name'] = parsed_attributes[key].get('qualified_name', None)
|
|
169
|
+
parsed_output['exists'] = parsed_attributes[key]['exists']
|
|
170
|
+
if parsed_attributes[key]['valid'] is False:
|
|
171
|
+
parsed_output['valid'] = False
|
|
172
|
+
parsed_output['reason'] += parsed_attributes[key]['reason']
|
|
173
|
+
|
|
174
|
+
elif style == 'Reference Name':
|
|
175
|
+
parsed_attributes[key] = proc_ids(egeria_client, key, labels, txt, object_action, if_missing)
|
|
176
|
+
if ((if_missing == ERROR) and parsed_attributes[key].get("value", None) and parsed_attributes[key][
|
|
177
|
+
'exists'] is False):
|
|
178
|
+
msg = f"Reference Name `{parsed_attributes[key]['value']}` is specified but does not exist"
|
|
179
|
+
logger.error(msg)
|
|
180
|
+
parsed_output['valid'] = False
|
|
181
|
+
parsed_output['reason'] += msg
|
|
182
|
+
elif parsed_attributes[key]['valid'] is False:
|
|
183
|
+
parsed_output['valid'] = False
|
|
184
|
+
parsed_output['reason'] += parsed_attributes[key]['reason']
|
|
185
|
+
|
|
186
|
+
elif style == 'GUID':
|
|
187
|
+
parsed_attributes[key] = proc_simple_attribute(txt, object_action, labels, if_missing)
|
|
188
|
+
elif style == 'Ordered Int':
|
|
189
|
+
parsed_attributes[key] = proc_simple_attribute(txt, object_action, labels, if_missing)
|
|
190
|
+
elif style == 'Simple Int':
|
|
191
|
+
parsed_attributes[key] = proc_simple_attribute(txt, object_action, labels, if_missing, default_value, "int")
|
|
192
|
+
elif style == 'Simple List':
|
|
193
|
+
parsed_attributes[key] = proc_simple_attribute(txt, object_action, labels, if_missing, default_value, "list")
|
|
194
|
+
name_list = parsed_attributes[key]['value']
|
|
195
|
+
# attribute = re.split(r'[;,\n]+', name_list) if name_list is not None else None
|
|
196
|
+
attribute = split_tb_string(name_list)
|
|
197
|
+
parsed_attributes[key]['value'] = attribute
|
|
198
|
+
parsed_attributes[key]['name_list'] = name_list
|
|
199
|
+
elif style == 'Parent':
|
|
200
|
+
parsed_attributes[key] = proc_simple_attribute(txt, object_action, labels, if_missing, default_value)
|
|
201
|
+
elif style == 'Bool':
|
|
202
|
+
parsed_attributes[key] = proc_bool_attribute(txt, object_action, labels, if_missing, default_value)
|
|
203
|
+
elif style == "Dictionary List":
|
|
204
|
+
parsed_attributes[key] = proc_simple_attribute(txt, object_action, labels, if_missing, default_value)
|
|
205
|
+
parsed_attributes[key]['list'] = json.loads(parsed_attributes[key]['value'])
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
elif style == 'Reference Name List':
|
|
209
|
+
parsed_attributes[key] = proc_name_list(egeria_client, key, txt, labels, if_missing)
|
|
210
|
+
if (parsed_attributes[key].get("value", None) and (
|
|
211
|
+
parsed_attributes[key]['exists'] is False or parsed_attributes[key]['valid'] is False)):
|
|
212
|
+
msg = (f"A Reference Name in `{parsed_attributes[key].get('name_list', None)}` is specified but "
|
|
213
|
+
f"does not exist")
|
|
214
|
+
logger.error(msg)
|
|
215
|
+
parsed_output['valid'] = False
|
|
216
|
+
parsed_output['reason'] += msg
|
|
217
|
+
else:
|
|
218
|
+
msg = f"Unknown attribute style: {style} for key `{key}`"
|
|
203
219
|
logger.error(msg)
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
220
|
+
sys.exit(1)
|
|
221
|
+
parsed_attributes[key]['valid'] = False
|
|
222
|
+
parsed_attributes[key]['value'] = None
|
|
223
|
+
if key == "Display Name":
|
|
224
|
+
display_name = parsed_attributes[key]['value']
|
|
225
|
+
|
|
226
|
+
value = parsed_attributes[key].get('value', None)
|
|
227
|
+
|
|
228
|
+
if value is not None:
|
|
229
|
+
if isinstance(value, list):
|
|
230
|
+
list_out = f"\n\t* {key}:\n\n"
|
|
231
|
+
for item in value:
|
|
232
|
+
list_out += f"\t{item}\n"
|
|
233
|
+
parsed_output['display'] += list_out
|
|
234
|
+
elif isinstance(value, dict):
|
|
235
|
+
list_out = f"\n\t* {key}:\n\n"
|
|
236
|
+
for k, v in value.items():
|
|
237
|
+
list_out += f"\t{k}: \n\t\t{v}\n"
|
|
238
|
+
parsed_output['display'] += list_out
|
|
239
|
+
else:
|
|
240
|
+
parsed_output['display'] += f"\n\t* {key}: \n`{value}`\n\t"
|
|
241
|
+
except PyegeriaException as e:
|
|
242
|
+
logger.error(f"PyegeriaException occurred: {e}")
|
|
243
|
+
|
|
244
|
+
print_basic_exception(e)
|
|
245
|
+
|
|
246
|
+
except ValidationError as e:
|
|
210
247
|
parsed_attributes[key]['valid'] = False
|
|
211
248
|
parsed_attributes[key]['value'] = None
|
|
212
|
-
|
|
213
|
-
display_name = parsed_attributes[key]['value']
|
|
214
|
-
|
|
215
|
-
value = parsed_attributes[key].get('value', None)
|
|
216
|
-
|
|
217
|
-
if value is not None:
|
|
218
|
-
# if the value is a dict, get the flattened name list
|
|
219
|
-
value = parsed_attributes[key].get('name_list', None) if isinstance(value, (dict, list)) else value
|
|
220
|
-
parsed_output['display'] += f"\n\t* {key}: `{value}`\n\t"
|
|
249
|
+
print_validation_error(e)
|
|
221
250
|
|
|
222
251
|
|
|
223
252
|
parsed_output['attributes'] = parsed_attributes
|
|
@@ -504,7 +533,8 @@ def proc_simple_attribute(txt: str, action: str, labels: set, if_missing: str =
|
|
|
504
533
|
|
|
505
534
|
attribute = extract_attribute(txt, labels)
|
|
506
535
|
|
|
507
|
-
attribute = default_value if attribute is None else attribute.replace('\n', '')
|
|
536
|
+
# attribute = default_value if attribute is None else attribute.replace('\n', '')
|
|
537
|
+
attribute = default_value if attribute is None else attribute
|
|
508
538
|
|
|
509
539
|
if attribute is None:
|
|
510
540
|
if if_missing == INFO or if_missing == WARNING:
|
|
@@ -519,8 +549,10 @@ def proc_simple_attribute(txt: str, action: str, labels: set, if_missing: str =
|
|
|
519
549
|
|
|
520
550
|
if attribute and simp_type == "int" :
|
|
521
551
|
attribute = int(attribute)
|
|
522
|
-
elif attribute and simp_type == "list":
|
|
523
|
-
|
|
552
|
+
# elif attribute and simp_type == "list":
|
|
553
|
+
# if isinstance(attribute, str):
|
|
554
|
+
# attribute = [piece.strip() for piece in re.split(r'[,\n]', attribute) if piece.strip()]
|
|
555
|
+
|
|
524
556
|
|
|
525
557
|
|
|
526
558
|
return {"status": INFO, "OK": None, "value": attribute, "valid": valid, "exists": True}
|
|
@@ -554,8 +586,8 @@ def proc_dictionary_attribute(txt: str, action: str, labels: set, if_missing: st
|
|
|
554
586
|
default_value = None
|
|
555
587
|
|
|
556
588
|
attr = extract_attribute(txt, labels)
|
|
557
|
-
attribute = json.loads(attr) if attr is not None else default_value
|
|
558
|
-
|
|
589
|
+
# attribute = json.loads(attr) if attr is not None else default_value
|
|
590
|
+
attribute = parse_to_dict(attr)
|
|
559
591
|
|
|
560
592
|
if attribute is None:
|
|
561
593
|
if if_missing == INFO or if_missing == WARNING:
|
|
@@ -387,7 +387,7 @@ def set_gov_prop_body(object_type: str, qualified_name: str, attributes: dict)->
|
|
|
387
387
|
prop_bod["importance"] = attributes.get('Importance', {}).get('value', None)
|
|
388
388
|
prop_bod["implications"] = attributes.get('Implication', {}).get('value', [])
|
|
389
389
|
prop_bod["outcomes"] = attributes.get('Outcomes', {}).get('value', [])
|
|
390
|
-
prop_bod["results"] = attributes.get('Results', {}).get('value', [])
|
|
390
|
+
prop_bod["results"] = attributes.get('Results', {}).get('value', []) or []
|
|
391
391
|
prop_bod["effectiveFrom"] = attributes.get('Effective From', {}).get('value', None),
|
|
392
392
|
prop_bod["effectiveTo"] = attributes.get('Effective To', {}).get('value', None),
|
|
393
393
|
prop_bod["additionalProperties"] = attributes.get('Additional Properties', {}).get('value', None),
|
|
@@ -425,9 +425,12 @@ def update_gov_body_for_type(object_type: str, body: dict, attributes: dict) ->
|
|
|
425
425
|
body['namePatterns'] = attributes.get('Name Patterns', {}).get('value', [])
|
|
426
426
|
return body
|
|
427
427
|
elif object_type in ["TermsAndConditions", "Certification Type", "License Type"]:
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
428
|
+
entitlements = attributes.get('Entitlementss', {}).get('value', {}) if attributes.get('Entitlementss',None) else None
|
|
429
|
+
restrictions = attributes.get('Restrictions', {}).get('value', {}) if attributes.get('Restrictions',None) else None
|
|
430
|
+
obligations = attributes.get('Obligations', {}).get('value', {}) if attributes.get('Obligations',None) else None
|
|
431
|
+
body['entitlements'] = entitlements
|
|
432
|
+
body['restrictions'] = restrictions
|
|
433
|
+
body['obligations'] = obligations
|
|
431
434
|
|
|
432
435
|
return body
|
|
433
436
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
This file contains functions for extracting data from text for Egeria Markdown processing
|
|
3
3
|
"""
|
|
4
4
|
import re
|
|
5
|
+
import json
|
|
5
6
|
from typing import Any
|
|
6
7
|
|
|
7
8
|
from md_processing.md_processing_utils.common_md_utils import (print_msg, find_key_with_value, get_element_dictionary,
|
|
@@ -74,56 +75,94 @@ def extract_command(block: str) -> str | None:
|
|
|
74
75
|
return None
|
|
75
76
|
|
|
76
77
|
|
|
77
|
-
def extract_attribute(text: str, labels: set) -> str | None:
|
|
78
|
+
# def extract_attribute(text: str, labels: set) -> str | None:
|
|
79
|
+
# """
|
|
80
|
+
# Extracts the attribute value from a string.
|
|
81
|
+
#
|
|
82
|
+
# Args:
|
|
83
|
+
# text: The input string.
|
|
84
|
+
# labels: List of equivalent labels to search for
|
|
85
|
+
#
|
|
86
|
+
# Returns:
|
|
87
|
+
# The value of the attribute, or None if not found.
|
|
88
|
+
#
|
|
89
|
+
# Note:
|
|
90
|
+
# Lines beginning with '>' are ignored.
|
|
91
|
+
# """
|
|
92
|
+
# # Iterate over the list of labels
|
|
93
|
+
# for label in labels:
|
|
94
|
+
# # Construct pattern for the current label
|
|
95
|
+
# # text = re.sub(r'\s+', ' ', text).strip() # just added
|
|
96
|
+
# # text = re.sub(r'\n\n+', '\n\n', text).strip()
|
|
97
|
+
#
|
|
98
|
+
# # Replace multiple spaces or tabs with a single space
|
|
99
|
+
# normalized = re.sub(r'\s+', ' ', text)
|
|
100
|
+
# # Collapse multiple blank lines into a single one
|
|
101
|
+
# normalized = re.sub(r'\n\s*\n', '\n', normalized).strip()
|
|
102
|
+
#
|
|
103
|
+
# # label = label.strip()
|
|
104
|
+
# # pattern = rf"##\s*{re.escape(label)}\s*\n(?:\s*\n)*?(.*?)(?:#|___|$)"
|
|
105
|
+
# # Normalize the label
|
|
106
|
+
# normalized_label = re.sub(r'\s+', ' ', label.strip())
|
|
107
|
+
#
|
|
108
|
+
# # Construct the regex pattern
|
|
109
|
+
# pattern = rf"##\s*{re.escape(normalized_label)}\s*\n(?:\s*\n)*?(.*?)(?:#|___|$)"
|
|
110
|
+
# # pattern = rf"##\s+{re.escape(label)}\n(.*?)(?:#|___|$)" # modified from --- to enable embedded tables
|
|
111
|
+
# match = re.search(pattern, text, re.DOTALL)
|
|
112
|
+
# if match:
|
|
113
|
+
# # Extract matched text
|
|
114
|
+
# matched_text = match.group(1)
|
|
115
|
+
#
|
|
116
|
+
# # Filter out lines beginning with '>'
|
|
117
|
+
# filtered_lines = [line for line in matched_text.split('\n') if not line.strip().startswith('>')]
|
|
118
|
+
# filtered_text = '\n'.join(filtered_lines)
|
|
119
|
+
#
|
|
120
|
+
# # Replace consecutive \n with a single \n
|
|
121
|
+
# extracted_text = re.sub(r'\n+', '\n', filtered_text)
|
|
122
|
+
# if not extracted_text.isspace() and extracted_text:
|
|
123
|
+
# return extracted_text.strip() # Return the cleaned text - I removed the title casing
|
|
124
|
+
#
|
|
125
|
+
# return None
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
from typing import Optional, List
|
|
129
|
+
|
|
130
|
+
def extract_attribute(text: str, labels: List[str]) -> Optional[str]:
|
|
78
131
|
"""
|
|
79
|
-
|
|
132
|
+
def extract_attribute(text: str, labels: List[str]) -> Optional[str]:
|
|
80
133
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
134
|
+
Extracts the attribute value from a string while:
|
|
135
|
+
- Preserving single newlines within the matched text.
|
|
136
|
+
- Removing lines starting with '>'.
|
|
84
137
|
|
|
85
|
-
|
|
86
|
-
|
|
138
|
+
Args:
|
|
139
|
+
text: The input string containing labeled sections.
|
|
140
|
+
labels: List of equivalent labels to search for.
|
|
87
141
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
# Iterate over the list of labels
|
|
142
|
+
Returns:
|
|
143
|
+
The cleaned value of the attribute, or None if not found.
|
|
144
|
+
"""
|
|
92
145
|
for label in labels:
|
|
93
146
|
# Construct pattern for the current label
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
# Replace multiple spaces or tabs with a single space
|
|
98
|
-
normalized = re.sub(r'\s+', ' ', text)
|
|
99
|
-
# Collapse multiple blank lines into a single one
|
|
100
|
-
normalized = re.sub(r'\n\s*\n', '\n', normalized).strip()
|
|
101
|
-
|
|
102
|
-
# label = label.strip()
|
|
103
|
-
# pattern = rf"##\s*{re.escape(label)}\s*\n(?:\s*\n)*?(.*?)(?:#|___|$)"
|
|
104
|
-
# Normalize the label
|
|
105
|
-
normalized_label = re.sub(r'\s+', ' ', label.strip())
|
|
106
|
-
|
|
107
|
-
# Construct the regex pattern
|
|
108
|
-
pattern = rf"##\s*{re.escape(normalized_label)}\s*\n(?:\s*\n)*?(.*?)(?:#|___|$)"
|
|
109
|
-
# pattern = rf"##\s+{re.escape(label)}\n(.*?)(?:#|___|$)" # modified from --- to enable embedded tables
|
|
110
|
-
match = re.search(pattern, text, re.DOTALL)
|
|
147
|
+
pattern = rf"## {re.escape(label)}\n(.*?)(?=^##|\Z)" # Captures content until the next '##' or end of text
|
|
148
|
+
match = re.search(pattern, text, re.DOTALL | re.MULTILINE)
|
|
111
149
|
if match:
|
|
112
150
|
# Extract matched text
|
|
113
|
-
|
|
151
|
+
extracted_text = match.group(1)
|
|
114
152
|
|
|
115
|
-
#
|
|
116
|
-
filtered_lines = [line for line in
|
|
117
|
-
filtered_text = '\n'.join(filtered_lines)
|
|
153
|
+
# Remove lines starting with '>'
|
|
154
|
+
filtered_lines = [line for line in extracted_text.splitlines() if not line.lstrip().startswith(">")]
|
|
118
155
|
|
|
119
|
-
#
|
|
120
|
-
|
|
121
|
-
if not extracted_text.isspace() and extracted_text:
|
|
122
|
-
return extracted_text.strip() # Return the cleaned text - I removed the title casing
|
|
156
|
+
# Join the lines back, preserving single newlines
|
|
157
|
+
cleaned_text = "\n".join(filtered_lines).strip()
|
|
123
158
|
|
|
159
|
+
if cleaned_text:
|
|
160
|
+
return cleaned_text # Return the cleaned and formatted text
|
|
124
161
|
return None
|
|
125
162
|
|
|
126
163
|
|
|
164
|
+
|
|
165
|
+
|
|
127
166
|
def process_simple_attribute(txt: str, labels: set, if_missing: str = INFO) -> str | None:
|
|
128
167
|
"""Process a simple attribute based on the provided labels and if_missing value.
|
|
129
168
|
Extract the attribute value from the text and return it if it exists.
|
pyegeria/__init__.py
CHANGED
|
@@ -62,7 +62,7 @@ from .registered_info import RegisteredInfo
|
|
|
62
62
|
from .runtime_manager_omvs import RuntimeManager
|
|
63
63
|
from .server_operations import ServerOps
|
|
64
64
|
from .solution_architect import SolutionArchitect
|
|
65
|
-
from .utils import body_slimmer,
|
|
65
|
+
from .utils import body_slimmer,to_pascal_case, to_camel_case, camel_to_title_case
|
|
66
66
|
from .valid_metadata_omvs import ValidMetadataManager
|
|
67
67
|
from .x_action_author_omvs import ActionAuthor
|
|
68
68
|
from .template_manager_omvs import TemplateManager
|