Skip to content

Commit 776fd05

Browse files
authored
Merge pull request #226 from dwolfson/Dr.E-Refactoring
Dr.e refactoring
2 parents 4ab6e5f + 8e8f5e5 commit 776fd05

16 files changed

Lines changed: 177 additions & 34 deletions

‎md_processing/md_processing_utils/common_md_utils.py‎

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,18 @@
6161
global COMMAND_DEFINITIONS
6262

6363
def split_tb_string(input: str)-> [Any]:
64-
"""Split the string and trim the items"""
65-
l = [item.strip() for item in re.split(r'[;,\n]+',input)] if input is not None else None
66-
return l
64+
"""Split the string and trim the items, supporting markdown bullets"""
65+
if input is None:
66+
return None
67+
items = re.split(r'[;,\n]+', input)
68+
results = []
69+
for item in items:
70+
item = item.strip()
71+
if item:
72+
# Strip leading markdown bullet if present
73+
item = re.sub(r'^[\-\*\+]\s*', '', item)
74+
results.append(item)
75+
return results
6776

6877
def str_to_bool(value: str) -> bool:
6978
"""Converts a string to a boolean value."""
@@ -371,10 +380,13 @@ def set_element_prop_body(object_type: str, qualified_name: str, attributes: dic
371380
"class": prop_name + "Properties",
372381
"typeName": prop_name,
373382
"displayName": attributes.get('Display Name', {}).get('value', None),
383+
"name": attributes.get('Display Name', {}).get('value', None) if ("Project" in object_type or "Campaign" in object_type or "Task" in object_type or "StudyProject" in object_type) else None,
374384
"qualifiedName" : qualified_name,
375385
"description": attributes.get('Description', {}).get('value', None),
376386
"category": attributes.get('Category', {}).get('value', None),
377387
"identifier": attributes.get('Identifier', {}).get('value', None),
388+
"url": attributes.get('URL', {}).get('value', None),
389+
"authors": attributes.get('Authors', {}).get('value', []),
378390
"contentStatus": attributes.get('Content Status', {}).get('value', None) or attributes.get('Status', {}).get('value', None),
379391
"userDefinedContentStatus": attributes.get('User Defined Content Status', {}).get('value', None),
380392
"versionIdentifier": attributes.get('Version Identifier', {}).get('value', None),
@@ -409,6 +421,9 @@ def set_collection_manager_body(object_type: str, qualified_name: str, attribute
409421
prop_bod.update({
410422
"agreementType": attributes.get('Agreement Type', {}).get('value', None),
411423
"agreementStatus": attributes.get('Agreement Status', {}).get('value', None),
424+
"agreementIdentifier": attributes.get('Agreement Identifier', {}).get('value', None),
425+
"agreementStatusIdentifier": attributes.get('Agreement Status Identifier', {}).get('value', None),
426+
"agreementVersionIdentifier": attributes.get('Agreement Version Identifier', {}).get('value', None),
412427
})
413428
if "Subscription" in object_type:
414429
prop_bod.update({
@@ -485,9 +500,13 @@ def set_gov_prop_body(object_type: str, qualified_name: str, attributes: dict)->
485500

486501
prop_bod["scope"] = attributes.get('Scope', {}).get('value', None)
487502
prop_bod["importance"] = attributes.get('Importance', {}).get('value', None)
488-
prop_bod["implications"] = attributes.get('Implication', {}).get('value', [])
503+
prop_bod["implications"] = attributes.get('Implications', {}).get('value', [])
489504
prop_bod["outcomes"] = attributes.get('Outcomes', {}).get('value', [])
490505
prop_bod["results"] = attributes.get('Results', {}).get('value', []) or []
506+
prop_bod["entitlements"] = attributes.get('Entitlements', {}).get('value', [])
507+
prop_bod["obligations"] = attributes.get('Obligations', {}).get('value', [])
508+
prop_bod["restrictions"] = attributes.get('Restrictions', {}).get('value', [])
509+
prop_bod["usage"] = attributes.get('Usage', {}).get('value', None)
491510
prop_bod["effectiveFrom"] = attributes.get('Effective From', {}).get('value', None)
492511
prop_bod["effectiveTo"] = attributes.get('Effective To', {}).get('value', None)
493512
prop_bod["additionalProperties"] = attributes.get('Additional Properties', {}).get('value', None)

‎md_processing/v2/glossary.py‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,13 @@ async def apply_changes(self) -> str:
140140
prop_body["abbreviation"] = attributes.get('Abbreviation', {}).get('value', None)
141141
prop_body["usage"] = attributes.get('Usage', {}).get('value', None)
142142
prop_body["user_defined_status"] = attributes.get('UserDefinedStatus', {}).get('value', None)
143+
prop_body["contextDescription"] = attributes.get('Context Description', {}).get('value', None)
144+
prop_body["contextScope"] = attributes.get('Context Scope', {}).get('value', None)
145+
prop_body["isAbstractConcept"] = attributes.get('Is Abstract Concept', {}).get('value', False)
146+
prop_body["isActivityDescription"] = attributes.get('Is Activity Description', {}).get('value', False)
147+
prop_body["isContext"] = attributes.get('Is Context', {}).get('value', False)
148+
prop_body["isDataValue"] = attributes.get('Is Data Value', {}).get('value', False)
149+
prop_body["termActivityType"] = attributes.get('Term Activity Type', {}).get('value', None)
143150

144151
# 2. Extract collection GUIDs
145152
# We may have one or more collections listed (Glossary Name, Folders)

‎md_processing/v2/parsing.py‎

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,13 @@ async def parse(self) -> Dict[str, Any]:
3434
if not self.spec:
3535
logger.error(f"No specification found for command: {self.command.verb} {self.command.object_type}")
3636
self.errors.append(f"No specification found for command: {self.command.verb} {self.command.object_type}")
37-
return {}
37+
return {
38+
"attributes": {},
39+
"valid": False,
40+
"errors": self.errors,
41+
"warnings": self.warnings,
42+
"qualified_name": None
43+
}
3844

3945
# Spec can use "Attributes" or "attributes"
4046
spec_attrs = self.spec.get("Attributes", self.spec.get("attributes", []))
@@ -364,7 +370,15 @@ async def _process_attribute_value(self, value: str, details: dict) -> Any:
364370
return v
365371

366372
elif style in {"List", "NameList", "Simple List", "Reference Name List"}:
367-
return [v.strip() for v in re.split(r'[,\n]', value) if v.strip()]
373+
items = re.split(r'[;,\n]+', value)
374+
results = []
375+
for item in items:
376+
item = item.strip()
377+
if item:
378+
# Strip leading markdown bullet if present
379+
item = re.sub(r'^[\-\*\+]\s*', '', item)
380+
results.append(item)
381+
return results
368382

369383
return value
370384

‎md_processing/v2/processors.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from pyegeria import EgeriaTech, PyegeriaException, NO_ELEMENTS_FOUND, print_basic_exception
1313
from pyegeria.core.utils import make_format_set_name_from_type
1414
from pyegeria.view.base_report_formats import select_report_spec
15-
from pyegeria.view.output_formatter import generate_output, format_for_markdown_table
15+
from pyegeria.view.output_formatter import generate_output, format_for_markdown_table, populate_columns_from_properties
1616

1717
from md_processing.v2.extraction import DrECommand
1818
from md_processing.v2.parsing import AttributeFirstParser
@@ -723,7 +723,8 @@ async def render_result_markdown(self, guid: str) -> str:
723723
search_string=self.parsed_output.get("qualified_name", "Created/Updated Element"),
724724
entity_type=self.command.object_type,
725725
output_format="MD",
726-
columns_struct=columns_struct
726+
columns_struct=columns_struct,
727+
extract_properties_func=populate_columns_from_properties
727728
)
728729
return markdown
729730
except Exception as e:

‎md_processing/v2/project.py‎

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,8 @@ async def apply_changes(self) -> str:
4444
project_types = ["Campaign", "Task", "Personal Project", "Study Project"]
4545

4646
# 1. Properties
47-
# ProjectManager expects 'name' instead of 'displayName' and 'plannedEndDate' instead of 'endDate'
48-
prop_body = {
49-
"class": f"{base_type}Properties",
50-
# "typeName": self.command.object_type.replace(" ", ""),
51-
"qualifiedName": qualified_name,
52-
"displayName": display_name,
53-
"description": attributes.get('Description', {}).get('value'),
54-
"identifier": attributes.get('Identifier', {}).get('value'),
47+
prop_body = set_element_prop_body(base_type, qualified_name, attributes)
48+
prop_body.update({
5549
"projectStatus": attributes.get('Project Status', {}).get('value'),
5650
"projectPhase": attributes.get('Project Phase', {}).get('value'),
5751
"projectHealth": attributes.get('Project Health', {}).get('value'),
@@ -60,11 +54,16 @@ async def apply_changes(self) -> str:
6054
"actualStartDate": attributes.get('Actual Start Date', {}).get('value'),
6155
"actualCompletionDate": attributes.get('Actual Completion Date', {}).get('value'),
6256
"mission": attributes.get('Mission', {}).get('value'),
63-
"purposes": attributes.get('Purposes', {}).get('value'),
57+
"purposes": attributes.get('Purposes', {}).get('value', []),
6458
"priority": attributes.get('Priority', {}).get('value'),
6559
"successCriteria": attributes.get('Success Criteria', {}).get('value'),
66-
"contentStatus": attributes.get('Content Status', {}).get('value'),
67-
}
60+
"projectIdentifier": attributes.get('Project Identifier', {}).get('value'),
61+
"projectType": attributes.get('Project Type', {}).get('value'),
62+
"projectScope": attributes.get('Project Scope', {}).get('value'),
63+
"projectApproach": attributes.get('Project Approach', {}).get('value'),
64+
"projectManagementStyle": attributes.get('Project Management Style', {}).get('value'),
65+
"projectResultsUsage": attributes.get('Project Results Usage', {}).get('value'),
66+
})
6867

6968
if verb == "Update":
7069
guid = self.parsed_output.get("guid") or (self.as_is_element['elementHeader']['guid'] if self.as_is_element else None)

‎pyegeria/models/models.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,10 @@ class ReferenceableProperties(OpenMetadataRootProperties):
141141
version_identifier: str | None = None
142142
description: str | None = None
143143
category: str | None = None
144+
authors: list[str] | None = None
145+
usage: str | None = None
146+
url: str | None = None
147+
content_status: str | None = None
144148
additional_properties: dict | None = None
145149

146150

‎pyegeria/omvs/glossary_manager.py‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ class GlossaryTermProperties(ReferenceableProperties):
4242
usage: str = None
4343
user_defined_status: str = None
4444
publishVersionIdentifier: str = None
45+
contextDescription: str = None
46+
contextScope: str = None
47+
isAbstractConcept: bool = False
48+
isActivityDescription: bool = False
49+
isContext: bool = False
50+
isDataValue: bool = False
51+
termActivityType: str = None
4552

4653

4754
class GlossaryManager(CollectionManager):

‎pyegeria/omvs/governance_officer.py‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ class GovernanceDefinitionProperties(ReferenceableProperties):
6969
implications: list[str] | None = None
7070
outcomes: list[str] | None = None
7171
results: list[str] | None = None
72+
entitlements: list[str] | None = None
73+
obligations: list[str] | None = None
74+
restrictions: list[str] | None = None
7275
userDefinedStatus: str | None = None
7376

7477

‎pyegeria/omvs/security_officer.py‎

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,26 @@ async def __get_platform_guid__(self, platform_name: str) -> str:
6969
async def _async_set_user_account(
7070
self, platform_name: str, body: Union[dict, Any], platform_guid: str = None
7171
) -> None:
72-
"""Create or update a user account in the platform metadata security connector. Async version."""
72+
"""Create or update a user account in the platform metadata security connector. Async version.
73+
{
74+
"class": "UserAccountRequestBody",
75+
"userAccount": {
76+
"class": "OpenMetadataUserAccount",
77+
"userId": "{{accountUserId}}",
78+
"userName": "Freddie Mercury",
79+
"userAccountType": "EXTERNAL",
80+
"employeeNumber": "",
81+
"employeeType": "",
82+
"givenName": "Freddie",
83+
"surname": "Mercury",
84+
"email": "freddiemercury@queen.com",
85+
"securityRoles": ["serverOperator", "serverInvestigator"],
86+
"userAccountStatus": "CREDENTIALS_EXPIRED",
87+
"secrets": {
88+
"clearPassword": "itsakindofmagic"
89+
}
90+
}
91+
"""
7392
if not platform_guid:
7493
platform_guid = await self.__get_platform_guid__(platform_name)
7594
url = f"{self.security_officer_base_url}/platforms/{platform_guid}/user-accounts"

‎pyegeria/view.zip‎

400 KB
Binary file not shown.

0 commit comments

Comments
 (0)