pyegeria 5.4.3.4__py3-none-any.whl → 5.4.4__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.
- commands/cat/debug_log.2025-09-04_08-21-58_788009.log.zip +0 -0
- commands/cat/debug_log.2025-09-05_09-37-53_062579.log.zip +0 -0
- commands/cat/list_format_set.py +3 -1
- md_processing/__init__.py +9 -1
- md_processing/data/commands.json +7181 -1400
- md_processing/data/generated_format_sets.json +4137 -0
- md_processing/data/generated_format_sets.py +51 -0
- md_processing/dr_egeria.py +14 -2
- md_processing/md_commands/ext_ref_commands.py +543 -0
- md_processing/md_commands/old_solution_architect_commands.py +1139 -0
- md_processing/md_commands/solution_architect_commands.py +26 -59
- md_processing/md_processing_utils/debug_log +1 -3
- md_processing/md_processing_utils/dr-egeria-help-2025-09-09T11:10:03.md +3305 -0
- md_processing/md_processing_utils/gen_format_sets.py +422 -0
- md_processing/md_processing_utils/md_processing_constants.py +19 -1
- pyegeria/_output_formats.py +239 -85
- pyegeria/collection_manager.py +3 -3
- pyegeria/egeria_tech_client.py +3 -0
- pyegeria/external_references.py +1794 -0
- pyegeria/solution_architect.py +290 -485
- {pyegeria-5.4.3.4.dist-info → pyegeria-5.4.4.dist-info}/METADATA +1 -1
- {pyegeria-5.4.3.4.dist-info → pyegeria-5.4.4.dist-info}/RECORD +25 -199
- commands/.DS_Store +0 -0
- commands/cat/.DS_Store +0 -0
- commands/cat/.env +0 -8
- commands/cat/debug_log.2025-08-29_07-07-27_848189.log.zip +0 -0
- commands/cat/debug_log.2025-08-30_21-15-48_528443.log.zip +0 -0
- commands/cat/debug_log.log +0 -7276
- commands/cat/logs/pyegeria.log +0 -90
- commands/cli/debug_log.log +0 -0
- commands/doc/.DS_Store +0 -0
- commands/ops/logs/pyegeria.log +0 -0
- md_processing/.DS_Store +0 -0
- md_processing/.idea/.gitignore +0 -8
- md_processing/.idea/inspectionProfiles/Project_Default.xml +0 -59
- md_processing/.idea/md_processing.iml +0 -15
- md_processing/.idea/modules.xml +0 -8
- md_processing/.idea/sonarlint/issuestore/index.pb +0 -0
- md_processing/.idea/sonarlint/securityhotspotstore/index.pb +0 -0
- md_processing/.idea/vcs.xml +0 -6
- md_processing/.idea/workspace.xml +0 -107
- md_processing/dr_egeria_inbox/Derive-Dr-Gov-Defs.md +0 -8
- md_processing/dr_egeria_inbox/Dr.Egeria Templates.md +0 -873
- md_processing/dr_egeria_inbox/arch_test.md +0 -57
- md_processing/dr_egeria_inbox/archive/dr_egeria_intro.md +0 -254
- md_processing/dr_egeria_inbox/archive/dr_egeria_intro_more_terms.md +0 -696
- md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part1.md +0 -254
- md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part2.md +0 -298
- md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part3.md +0 -608
- md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part4.md +0 -94
- md_processing/dr_egeria_inbox/archive/freddie_intro.md +0 -284
- md_processing/dr_egeria_inbox/archive/freddie_intro_orig.md +0 -275
- md_processing/dr_egeria_inbox/archive/test-term.md +0 -110
- md_processing/dr_egeria_inbox/cat_test.md +0 -100
- md_processing/dr_egeria_inbox/collections.md +0 -39
- md_processing/dr_egeria_inbox/data_designer_debug.log +0 -6
- md_processing/dr_egeria_inbox/data_designer_out.md +0 -60
- md_processing/dr_egeria_inbox/data_designer_search_test.md +0 -11
- md_processing/dr_egeria_inbox/data_field.md +0 -54
- md_processing/dr_egeria_inbox/data_spec.md +0 -77
- md_processing/dr_egeria_inbox/data_spec_test.md +0 -2014
- md_processing/dr_egeria_inbox/data_test.md +0 -179
- md_processing/dr_egeria_inbox/data_test2.md +0 -429
- md_processing/dr_egeria_inbox/data_test3.md +0 -462
- md_processing/dr_egeria_inbox/dr_egeria_data_designer_1.md +0 -124
- md_processing/dr_egeria_inbox/dr_egeria_intro_categories.md +0 -168
- md_processing/dr_egeria_inbox/dr_egeria_intro_part1.md +0 -280
- md_processing/dr_egeria_inbox/dr_egeria_intro_part2.md +0 -318
- md_processing/dr_egeria_inbox/dr_egeria_intro_part3.md +0 -1073
- md_processing/dr_egeria_inbox/dr_egeria_isc1.md +0 -44
- md_processing/dr_egeria_inbox/generated_help_report.md +0 -9
- md_processing/dr_egeria_inbox/generated_help_terms.md +0 -842
- md_processing/dr_egeria_inbox/glossary_list.md +0 -5
- md_processing/dr_egeria_inbox/glossary_search_test.md +0 -40
- md_processing/dr_egeria_inbox/glossary_test1.md +0 -378
- md_processing/dr_egeria_inbox/gov_def.md +0 -718
- md_processing/dr_egeria_inbox/gov_def2.md +0 -447
- md_processing/dr_egeria_inbox/img.png +0 -0
- md_processing/dr_egeria_inbox/output_tests.md +0 -114
- md_processing/dr_egeria_inbox/product.md +0 -219
- md_processing/dr_egeria_inbox/rel.md +0 -8
- md_processing/dr_egeria_inbox/sb.md +0 -119
- md_processing/dr_egeria_inbox/solution-components.md +0 -136
- md_processing/dr_egeria_inbox/solution_blueprints.md +0 -118
- md_processing/dr_egeria_inbox/synonym_test.md +0 -42
- md_processing/dr_egeria_inbox/t2.md +0 -268
- md_processing/dr_egeria_outbox/.DS_Store +0 -0
- md_processing/dr_egeria_outbox/.obsidian/app.json +0 -1
- md_processing/dr_egeria_outbox/.obsidian/appearance.json +0 -1
- md_processing/dr_egeria_outbox/.obsidian/community-plugins.json +0 -7
- md_processing/dr_egeria_outbox/.obsidian/core-plugins.json +0 -33
- md_processing/dr_egeria_outbox/.obsidian/plugins/buttons/main.js +0 -5164
- md_processing/dr_egeria_outbox/.obsidian/plugins/buttons/manifest.json +0 -10
- md_processing/dr_egeria_outbox/.obsidian/plugins/buttons/styles.css +0 -624
- md_processing/dr_egeria_outbox/.obsidian/plugins/calendar/data.json +0 -10
- md_processing/dr_egeria_outbox/.obsidian/plugins/calendar/main.js +0 -4459
- md_processing/dr_egeria_outbox/.obsidian/plugins/calendar/manifest.json +0 -10
- md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-kanban/data.json +0 -3
- md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-kanban/main.js +0 -153
- md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-kanban/manifest.json +0 -11
- md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-kanban/styles.css +0 -1
- md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-tasks-plugin/main.js +0 -500
- md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-tasks-plugin/manifest.json +0 -12
- md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-tasks-plugin/styles.css +0 -1
- md_processing/dr_egeria_outbox/.obsidian/plugins/templater-obsidian/data.json +0 -38
- md_processing/dr_egeria_outbox/.obsidian/plugins/templater-obsidian/main.js +0 -37
- md_processing/dr_egeria_outbox/.obsidian/plugins/templater-obsidian/manifest.json +0 -11
- md_processing/dr_egeria_outbox/.obsidian/plugins/templater-obsidian/styles.css +0 -220
- md_processing/dr_egeria_outbox/.obsidian/types.json +0 -28
- md_processing/dr_egeria_outbox/.obsidian/workspace.json +0 -270
- md_processing/dr_egeria_outbox/Button Test.md +0 -11
- md_processing/dr_egeria_outbox/Scripts/.DS_Store +0 -0
- md_processing/dr_egeria_outbox/Scripts/sendRest.js +0 -24
- md_processing/dr_egeria_outbox/Templates/sendToApi.md.md +0 -17
- md_processing/dr_egeria_outbox/Untitled.canvas +0 -1
- md_processing/dr_egeria_outbox/monday/processed-2025-09-01 09:26-product.md +0 -210
- md_processing/dr_egeria_outbox/monday/processed-2025-09-01 14:03-product.md +0 -209
- md_processing/dr_egeria_outbox/monday/processed-2025-09-01 14:24-product.md +0 -263
- md_processing/dr_egeria_outbox/monday/processed-2025-09-01 16:03-data_spec_test.md +0 -2374
- md_processing/dr_egeria_outbox/monday/processed-2025-09-01 16:05-data_spec_test.md +0 -2374
- md_processing/dr_egeria_outbox/monday/processed-2025-09-02 08:28-data_spec_test.md +0 -2321
- md_processing/dr_egeria_outbox/monday/processed-2025-09-02 08:37-data_spec_test.md +0 -2304
- md_processing/dr_egeria_outbox/monday/processed-2025-09-02 08:56-data_spec_test.md +0 -2324
- md_processing/dr_egeria_outbox/monday/processed-2025-09-02 09:00-data_spec_test.md +0 -2324
- md_processing/dr_egeria_outbox/processed-2025-08-30 16:56-generated_help_terms.md +0 -795
- md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 15:00-Derive-Dr-Gov-Defs.md +0 -719
- md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 20:13-Derive-Dr-Gov-Defs.md +0 -41
- md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 20:14-Derive-Dr-Gov-Defs.md +0 -33
- md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 20:50-Derive-Dr-Gov-Defs.md +0 -192
- md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 22:08-gov_def2.md +0 -486
- md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 22:10-gov_def2.md +0 -486
- md_processing/dr_egeria_outbox/thursday/processed-2025-07-18 08:53-gov_def2.md +0 -486
- md_processing/dr_egeria_outbox/thursday/processed-2025-07-18 08:54-gov_def2.md +0 -486
- md_processing/dr_egeria_outbox/thursday/processed-2025-07-18 09:03-gov_def2.md +0 -486
- md_processing/dr_egeria_outbox/thursday/processed-2025-07-18 09:06-gov_def2.md +0 -486
- md_processing/dr_egeria_outbox/thursday/processed-2025-07-18 09:10-gov_def2.md +0 -486
- md_processing/family_docs/Data Designer/Create_Data_Class.md +0 -164
- md_processing/family_docs/Data Designer/Create_Data_Dictionary.md +0 -30
- md_processing/family_docs/Data Designer/Create_Data_Field.md +0 -162
- md_processing/family_docs/Data Designer/Create_Data_Specification.md +0 -36
- md_processing/family_docs/Data Designer/Create_Data_Structure.md +0 -38
- md_processing/family_docs/Data Designer/View_Data_Classes.md +0 -78
- md_processing/family_docs/Data Designer/View_Data_Dictionaries.md +0 -78
- md_processing/family_docs/Data Designer/View_Data_Fields.md +0 -78
- md_processing/family_docs/Data Designer/View_Data_Specifications.md +0 -78
- md_processing/family_docs/Data Designer/View_Data_Structures.md +0 -78
- md_processing/family_docs/Data Designer.md +0 -842
- md_processing/family_docs/Digital Product Manager/Add_Member->Collection.md +0 -42
- md_processing/family_docs/Digital Product Manager/Attach_Collection->Resource.md +0 -36
- md_processing/family_docs/Digital Product Manager/Create_Agreement.md +0 -96
- md_processing/family_docs/Digital Product Manager/Create_Data_Sharing_Agreement.md +0 -72
- md_processing/family_docs/Digital Product Manager/Create_DigitalSubscription.md +0 -102
- md_processing/family_docs/Digital Product Manager/Create_Digital_Product.md +0 -134
- md_processing/family_docs/Digital Product Manager/Link_Agreement_Items.md +0 -60
- md_processing/family_docs/Digital Product Manager/Link_Contracts.md +0 -26
- md_processing/family_docs/Digital Product Manager/Link_Digital_Product_-_Digital_Product.md +0 -30
- md_processing/family_docs/Digital Product Manager/Link_Subscribers.md +0 -48
- md_processing/family_docs/Digital Product Manager.md +0 -668
- md_processing/family_docs/Glossary/Attach_Category_Parent.md +0 -18
- md_processing/family_docs/Glossary/Attach_Term-Term_Relationship.md +0 -26
- md_processing/family_docs/Glossary/Create_Category.md +0 -38
- md_processing/family_docs/Glossary/Create_Glossary.md +0 -42
- md_processing/family_docs/Glossary/Create_Term.md +0 -70
- md_processing/family_docs/Glossary.md +0 -206
- md_processing/family_docs/Governance Officer/Create_Business_Imperative.md +0 -106
- md_processing/family_docs/Governance Officer/Create_Certification_Type.md +0 -112
- md_processing/family_docs/Governance Officer/Create_Governance_Approach.md +0 -114
- md_processing/family_docs/Governance Officer/Create_Governance_Obligation.md +0 -114
- md_processing/family_docs/Governance Officer/Create_Governance_Principle.md +0 -114
- md_processing/family_docs/Governance Officer/Create_Governance_Procedure.md +0 -128
- md_processing/family_docs/Governance Officer/Create_Governance_Process.md +0 -122
- md_processing/family_docs/Governance Officer/Create_Governance_Processing_Purpose.md +0 -106
- md_processing/family_docs/Governance Officer/Create_Governance_Responsibility.md +0 -122
- md_processing/family_docs/Governance Officer/Create_Governance_Rule.md +0 -122
- md_processing/family_docs/Governance Officer/Create_Governance_Strategy.md +0 -106
- md_processing/family_docs/Governance Officer/Create_License_Type.md +0 -112
- md_processing/family_docs/Governance Officer/Create_Naming_Standard_Rule.md +0 -122
- md_processing/family_docs/Governance Officer/Create_Regulation_Article.md +0 -106
- md_processing/family_docs/Governance Officer/Create_Regulation_Definition.md +0 -118
- md_processing/family_docs/Governance Officer/Create_Security_Access_Control.md +0 -114
- md_processing/family_docs/Governance Officer/Create_Security_Group.md +0 -120
- md_processing/family_docs/Governance Officer/Create_Service_Level_Objectives.md +0 -122
- md_processing/family_docs/Governance Officer/Create_Threat_Definition.md +0 -106
- md_processing/family_docs/Governance Officer/Link_Governance_Controls.md +0 -32
- md_processing/family_docs/Governance Officer/Link_Governance_Drivers.md +0 -32
- md_processing/family_docs/Governance Officer/Link_Governance_Policies.md +0 -32
- md_processing/family_docs/Governance Officer/View_Governance_Definitions.md +0 -82
- md_processing/family_docs/Governance Officer.md +0 -2412
- md_processing/family_docs/Solution Architect/Create_Information_Supply_Chain.md +0 -70
- md_processing/family_docs/Solution Architect/Create_Solution_Blueprint.md +0 -44
- md_processing/family_docs/Solution Architect/Create_Solution_Component.md +0 -96
- md_processing/family_docs/Solution Architect/Create_Solution_Role.md +0 -66
- md_processing/family_docs/Solution Architect/Link_Information_Supply_Chain_Peers.md +0 -32
- md_processing/family_docs/Solution Architect/Link_Solution_Component_Peers.md +0 -32
- md_processing/family_docs/Solution Architect/View_Information_Supply_Chains.md +0 -32
- md_processing/family_docs/Solution Architect/View_Solution_Blueprints.md +0 -32
- md_processing/family_docs/Solution Architect/View_Solution_Components.md +0 -32
- md_processing/family_docs/Solution Architect/View_Solution_Roles.md +0 -32
- md_processing/family_docs/Solution Architect.md +0 -490
- md_processing/md_commands/old_project_commands.py +0 -164
- md_processing/md_processing_utils/debug_log.log +0 -5580
- md_processing/md_processing_utils/generated_help_terms.md +0 -842
- md_processing/md_processing_utils/logs/pyegeria.log +0 -56
- pyegeria/.DS_Store +0 -0
- pyegeria/___external_references.py +0 -3255
- {pyegeria-5.4.3.4.dist-info → pyegeria-5.4.4.dist-info}/LICENSE +0 -0
- {pyegeria-5.4.3.4.dist-info → pyegeria-5.4.4.dist-info}/WHEEL +0 -0
- {pyegeria-5.4.3.4.dist-info → pyegeria-5.4.4.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,422 @@
|
|
1
|
+
import argparse
|
2
|
+
import json
|
3
|
+
import re
|
4
|
+
import argparse
|
5
|
+
from pathlib import Path
|
6
|
+
from typing import Iterable, List, Optional
|
7
|
+
|
8
|
+
from loguru import logger
|
9
|
+
from rich.prompt import Prompt
|
10
|
+
|
11
|
+
from pyegeria._output_format_models import Column, Format, ActionParameter, FormatSet, FormatSetDict
|
12
|
+
from pyegeria._output_formats import OPTIONAL_PARAMS # ["page_size","start_from","starts_with","ends_with","ignore_case"]
|
13
|
+
|
14
|
+
def _is_create_command(cmd_key: str, cmd_obj: dict) -> bool:
|
15
|
+
name = str(cmd_obj.get("display_name", "")).strip()
|
16
|
+
return (isinstance(cmd_key, str) and cmd_key.strip().lower().startswith("create")) or \
|
17
|
+
(name.lower().startswith("create"))
|
18
|
+
|
19
|
+
def _derive_set_name_from_display_name(display_name: str) -> str:
|
20
|
+
"""From 'Create Governance Strategy Definition' -> 'GovernanceStrategyDefinition'."""
|
21
|
+
if not display_name:
|
22
|
+
return ""
|
23
|
+
parts = display_name.strip().split()
|
24
|
+
if len(parts) <= 1:
|
25
|
+
return re.sub(r"\s+", "", display_name.strip())+"-DrE"
|
26
|
+
rest = " ".join(parts[1:]).strip()
|
27
|
+
rest = rest+"-DrE"
|
28
|
+
return re.sub(r"\s+", "", rest)
|
29
|
+
|
30
|
+
def _safe_parse_constraints(s) -> dict:
|
31
|
+
"""Parse find_constraints (often an escaped JSON string) into a dict."""
|
32
|
+
if not s:
|
33
|
+
return {}
|
34
|
+
if isinstance(s, dict):
|
35
|
+
return s
|
36
|
+
txt = str(s).strip()
|
37
|
+
# Attempt 1: direct JSON
|
38
|
+
try:
|
39
|
+
return json.loads(txt)
|
40
|
+
except Exception:
|
41
|
+
logger.error(f"Error parsing constraints: {s!r}")
|
42
|
+
pass
|
43
|
+
# Attempt 2: unwrap quotes
|
44
|
+
try:
|
45
|
+
txt2 = txt.strip('"').strip("'")
|
46
|
+
return json.loads(txt2)
|
47
|
+
except Exception:
|
48
|
+
pass
|
49
|
+
# Attempt 3: heuristic single->double quotes for dict-like strings
|
50
|
+
if ("{" in txt and "}" in txt) and ("'" in txt and '"' not in txt):
|
51
|
+
try:
|
52
|
+
return json.loads(txt.replace("'", '"'))
|
53
|
+
except Exception:
|
54
|
+
pass
|
55
|
+
logger.debug(f"Could not parse find_constraints: {s!r} -> {{}}")
|
56
|
+
return {}
|
57
|
+
|
58
|
+
def _extract_basic_columns_from_attributes(attributes: Iterable[dict]) -> List[Column]:
|
59
|
+
"""
|
60
|
+
attributes: list of single-key dicts, e.g.
|
61
|
+
{"Display Name": {"variable_name": "display_name", "level": "Basic", ...}}
|
62
|
+
"""
|
63
|
+
|
64
|
+
cols: List[Column] = []
|
65
|
+
seen: set[str] = set()
|
66
|
+
for entry in attributes or []:
|
67
|
+
if not isinstance(entry, dict) or not entry:
|
68
|
+
continue
|
69
|
+
# Some entries may contain more than one key; scan all items
|
70
|
+
for label, details in entry.items():
|
71
|
+
if not isinstance(details, dict):
|
72
|
+
continue
|
73
|
+
if details.get("level") != "Basic":
|
74
|
+
continue
|
75
|
+
key = details.get("variable_name")
|
76
|
+
if not key or key in seen:
|
77
|
+
continue
|
78
|
+
seen.add(key)
|
79
|
+
cols.append(Column(name=str(label), key=str(key)))
|
80
|
+
return cols
|
81
|
+
|
82
|
+
def build_format_sets_from_commands(
|
83
|
+
commands_json_path: str | Path,
|
84
|
+
*,
|
85
|
+
include_only_create: bool = True,
|
86
|
+
default_types: Optional[List[str]] = None
|
87
|
+
) -> FormatSetDict:
|
88
|
+
"""
|
89
|
+
Convert commands.json into a FormatSetDict following your mappings.
|
90
|
+
"""
|
91
|
+
path = Path(commands_json_path)
|
92
|
+
data = json.loads(path.read_text(encoding="utf-8"))
|
93
|
+
|
94
|
+
if isinstance(data, dict):
|
95
|
+
items_iter = data.items()
|
96
|
+
elif isinstance(data, list):
|
97
|
+
# If it’s a list of command objects, synthesize keys from display_name or index
|
98
|
+
def _key_for(idx, obj):
|
99
|
+
dn = str(obj.get("display_name", "")).strip()
|
100
|
+
return dn or f"cmd_{idx}"
|
101
|
+
|
102
|
+
items_iter = ((_key_for(i, obj), obj) for i, obj in enumerate(data))
|
103
|
+
else:
|
104
|
+
raise ValueError("commands.json root must be an object/dict or an array of command objects")
|
105
|
+
data = dict(items_iter).get("Command Specifications", {})
|
106
|
+
logger.info(
|
107
|
+
f"Loaded commands.json from {path} with {len(data)} commands"
|
108
|
+
)
|
109
|
+
|
110
|
+
|
111
|
+
results = FormatSetDict()
|
112
|
+
types = default_types or ["ALL"]
|
113
|
+
|
114
|
+
for cmd_key, cmd_obj in data.items():
|
115
|
+
if not isinstance(cmd_obj, dict):
|
116
|
+
continue
|
117
|
+
if include_only_create and not _is_create_command(cmd_key, cmd_obj):
|
118
|
+
continue
|
119
|
+
|
120
|
+
display_name = str(cmd_obj.get("display_name", "")).strip()
|
121
|
+
if not display_name:
|
122
|
+
logger.debug(f"Skip {cmd_key!r}: missing display_name")
|
123
|
+
continue
|
124
|
+
set_name = re.sub(r"\s+", "-", display_name)
|
125
|
+
set_name = set_name.strip() + "-DrE"
|
126
|
+
# set_name = _derive_set_name_from_display_name(display_name)
|
127
|
+
if not set_name:
|
128
|
+
logger.debug(f"Skip {cmd_key!r}: could not derive set name from display_name={display_name!r}")
|
129
|
+
continue
|
130
|
+
|
131
|
+
columns = _extract_basic_columns_from_attributes(cmd_obj.get("Attributes", []))
|
132
|
+
if not columns:
|
133
|
+
logger.debug(f"Skip {set_name}: no Basic attributes")
|
134
|
+
continue
|
135
|
+
|
136
|
+
find_method = cmd_obj.get("find_method") or ""
|
137
|
+
constraints = _safe_parse_constraints(cmd_obj.get("find_constraints"))
|
138
|
+
action = None
|
139
|
+
if find_method:
|
140
|
+
action = ActionParameter(
|
141
|
+
function=find_method,
|
142
|
+
required_params=["search_string"],
|
143
|
+
optional_params=OPTIONAL_PARAMS,
|
144
|
+
spec_params=constraints or {},
|
145
|
+
)
|
146
|
+
|
147
|
+
fs = FormatSet(
|
148
|
+
target_type=set_name,
|
149
|
+
heading=f"{set_name} Attributes",
|
150
|
+
description=f"Auto-generated format for {display_name} (Create).",
|
151
|
+
formats=[Format(types=types, columns=columns)],
|
152
|
+
action=action
|
153
|
+
)
|
154
|
+
results[set_name] = fs
|
155
|
+
|
156
|
+
return results
|
157
|
+
|
158
|
+
def save_generated_format_sets(
|
159
|
+
commands_json_path: str | Path,
|
160
|
+
out_file: str | Path,
|
161
|
+
*,
|
162
|
+
include_only_create: bool = True,
|
163
|
+
default_types: Optional[List[str]] = None
|
164
|
+
) -> Path:
|
165
|
+
"""Build and save to a JSON file loadable by _output_formats.load_output_format_sets."""
|
166
|
+
sets = build_format_sets_from_commands(
|
167
|
+
commands_json_path,
|
168
|
+
include_only_create=include_only_create,
|
169
|
+
default_types=default_types,
|
170
|
+
)
|
171
|
+
out = Path(out_file)
|
172
|
+
out.parent.mkdir(parents=True, exist_ok=True)
|
173
|
+
sets.save_to_json(str(out))
|
174
|
+
logger.info(f"Saved {len(sets)} generated format sets to {out}")
|
175
|
+
return out
|
176
|
+
|
177
|
+
# New: expose a simple alias that returns a FormatSetDict directly
|
178
|
+
# for callers that want the in-memory object rather than JSON.
|
179
|
+
def generate_format_sets(
|
180
|
+
commands_json_path: str | Path,
|
181
|
+
*,
|
182
|
+
include_only_create: bool = True,
|
183
|
+
default_types: Optional[List[str]] = None,
|
184
|
+
):
|
185
|
+
"""Return a FormatSetDict built from commands.json (no file I/O)."""
|
186
|
+
return build_format_sets_from_commands(
|
187
|
+
commands_json_path,
|
188
|
+
include_only_create=include_only_create,
|
189
|
+
default_types=default_types,
|
190
|
+
)
|
191
|
+
|
192
|
+
# New: merge generated sets into the builtin registry
|
193
|
+
|
194
|
+
def merge_generated_format_sets(
|
195
|
+
commands_json_path: str | Path,
|
196
|
+
*,
|
197
|
+
include_only_create: bool = True,
|
198
|
+
default_types: Optional[List[str]] = None,
|
199
|
+
) -> int:
|
200
|
+
"""Build a FormatSetDict and merge into pyegeria._output_formats.output_format_sets.
|
201
|
+
Returns the number of sets merged/added.
|
202
|
+
"""
|
203
|
+
from pyegeria._output_formats import output_format_sets # local import to avoid cycles on tooling
|
204
|
+
|
205
|
+
gen = build_format_sets_from_commands(
|
206
|
+
commands_json_path,
|
207
|
+
include_only_create=include_only_create,
|
208
|
+
default_types=default_types,
|
209
|
+
)
|
210
|
+
count = 0
|
211
|
+
for name, fs in gen.items():
|
212
|
+
output_format_sets[name] = fs
|
213
|
+
count += 1
|
214
|
+
logger.info(f"Merged {count} generated format sets into built-ins")
|
215
|
+
return count
|
216
|
+
|
217
|
+
|
218
|
+
def _py_literal(value):
|
219
|
+
"""Render a Python literal safely for strings, lists, dicts, bools, None, numbers."""
|
220
|
+
if isinstance(value, str):
|
221
|
+
return repr(value)
|
222
|
+
if isinstance(value, (int, float)):
|
223
|
+
return str(value)
|
224
|
+
if value is True:
|
225
|
+
return "True"
|
226
|
+
if value is False:
|
227
|
+
return "False"
|
228
|
+
if value is None:
|
229
|
+
return "None"
|
230
|
+
if isinstance(value, list):
|
231
|
+
return "[" + ", ".join(_py_literal(v) for v in value) + "]"
|
232
|
+
if isinstance(value, dict):
|
233
|
+
# Render dict with stable key ordering
|
234
|
+
items = ", ".join(f"{_py_literal(k)}: {_py_literal(v)}" for k, v in sorted(value.items(), key=lambda kv: str(kv[0]).lower()))
|
235
|
+
return "{" + items + "}"
|
236
|
+
# Fallback
|
237
|
+
return repr(value)
|
238
|
+
|
239
|
+
|
240
|
+
def _format_column(col: Column) -> str:
|
241
|
+
parts = [f"name={_py_literal(getattr(col, 'name', ''))}", f"key={_py_literal(getattr(col, 'key', ''))}"]
|
242
|
+
fmt = getattr(col, 'format', None)
|
243
|
+
if fmt not in (None, False):
|
244
|
+
parts.append(f"format={_py_literal(bool(fmt))}")
|
245
|
+
return "Column(" + ", ".join(parts) + ")"
|
246
|
+
|
247
|
+
|
248
|
+
def _format_action(ap: ActionParameter | None) -> str:
|
249
|
+
if not ap:
|
250
|
+
return "None"
|
251
|
+
parts = [
|
252
|
+
f"function={_py_literal(getattr(ap, 'function', ''))}",
|
253
|
+
]
|
254
|
+
req = getattr(ap, 'required_params', None)
|
255
|
+
if req:
|
256
|
+
parts.append(f"required_params={_py_literal(list(req))}")
|
257
|
+
opt = getattr(ap, 'optional_params', None)
|
258
|
+
if opt:
|
259
|
+
parts.append(f"optional_params={_py_literal(list(opt))}")
|
260
|
+
spec = getattr(ap, 'spec_params', None)
|
261
|
+
if spec:
|
262
|
+
parts.append(f"spec_params={_py_literal(dict(spec))}")
|
263
|
+
return "ActionParameter(" + ", ".join(parts) + ")"
|
264
|
+
|
265
|
+
|
266
|
+
def _format_format(fmt: Format) -> str:
|
267
|
+
cols = getattr(fmt, 'columns', []) or []
|
268
|
+
types = getattr(fmt, 'types', []) or []
|
269
|
+
col_code = ", ".join(_format_column(c) for c in cols)
|
270
|
+
parts = [f"types={_py_literal(list(types))}", f"columns=[{col_code}]"]
|
271
|
+
return "Format(" + ", ".join(parts) + ")"
|
272
|
+
|
273
|
+
|
274
|
+
def _format_formatset(fs: FormatSet) -> str:
|
275
|
+
parts = []
|
276
|
+
if getattr(fs, 'target_type', None):
|
277
|
+
parts.append(f"target_type={_py_literal(fs.target_type)}")
|
278
|
+
if getattr(fs, 'heading', None):
|
279
|
+
parts.append(f"heading={_py_literal(fs.heading)}")
|
280
|
+
if getattr(fs, 'description', None):
|
281
|
+
parts.append(f"description={_py_literal(fs.description)}")
|
282
|
+
aliases = getattr(fs, 'aliases', None)
|
283
|
+
if aliases:
|
284
|
+
parts.append(f"aliases={_py_literal(list(aliases))}")
|
285
|
+
ann = getattr(fs, 'annotations', None)
|
286
|
+
if ann:
|
287
|
+
parts.append(f"annotations={_py_literal(dict(ann))}")
|
288
|
+
# formats
|
289
|
+
fmts = getattr(fs, 'formats', []) or []
|
290
|
+
fmt_code = ", ".join(_format_format(f) for f in fmts)
|
291
|
+
parts.append(f"formats=[{fmt_code}]")
|
292
|
+
# actions
|
293
|
+
action = getattr(fs, 'action', None)
|
294
|
+
if action:
|
295
|
+
parts.append(f"action={_format_action(action)}")
|
296
|
+
get_add = getattr(fs, 'get_additional_props', None)
|
297
|
+
if get_add:
|
298
|
+
parts.append(f"get_additional_props={_format_action(get_add)}")
|
299
|
+
return "FormatSet(" + ", ".join(parts) + ")"
|
300
|
+
|
301
|
+
|
302
|
+
def format_sets_to_python_code(sets: FormatSetDict, var_name: str = "generated_format_sets") -> str:
|
303
|
+
"""Render a FormatSetDict into a Python module string defining `var_name`."""
|
304
|
+
header = (
|
305
|
+
"# Auto-generated by gen_format_sets.py\n"
|
306
|
+
"from pyegeria._output_format_models import Column, Format, ActionParameter, FormatSet, FormatSetDict\n\n"
|
307
|
+
)
|
308
|
+
# Stable ordering by key
|
309
|
+
entries = []
|
310
|
+
for name in sorted(sets.keys(), key=lambda s: s.lower()):
|
311
|
+
fs = sets[name]
|
312
|
+
entries.append(f" {_py_literal(name)}: {_format_formatset(fs)}")
|
313
|
+
body = f"{var_name} = FormatSetDict({{\n" + ",\n".join(entries) + "\n})\n"
|
314
|
+
return header + body
|
315
|
+
|
316
|
+
|
317
|
+
def save_generated_format_sets_code(
|
318
|
+
commands_json_path: str | Path,
|
319
|
+
out_file: str | Path,
|
320
|
+
*,
|
321
|
+
include_only_create: bool = True,
|
322
|
+
default_types: Optional[List[str]] = None,
|
323
|
+
var_name: str = "generated_format_sets",
|
324
|
+
) -> Path:
|
325
|
+
"""Build FormatSetDict and save as Python code to out_file."""
|
326
|
+
sets = build_format_sets_from_commands(
|
327
|
+
commands_json_path,
|
328
|
+
include_only_create=include_only_create,
|
329
|
+
default_types=default_types,
|
330
|
+
)
|
331
|
+
code = format_sets_to_python_code(sets, var_name=var_name)
|
332
|
+
out = Path(out_file)
|
333
|
+
out.parent.mkdir(parents=True, exist_ok=True)
|
334
|
+
out.write_text(code, encoding="utf-8")
|
335
|
+
logger.info(f"Saved Python code for {len(sets)} generated format sets to {out}")
|
336
|
+
return out
|
337
|
+
|
338
|
+
|
339
|
+
def main():
|
340
|
+
parser = argparse.ArgumentParser(description="Generate FormatSets from commands.json")
|
341
|
+
parser.add_argument("commands_json", nargs="?", help="Path to commands.json")
|
342
|
+
parser.add_argument("output_json", nargs="?", help="Path to output JSON file (when --emit json)")
|
343
|
+
parser.add_argument("--emit", choices=["json", "dict", "code"], default="json",
|
344
|
+
help="Choose output mode: save JSON file, write Python code, or work with in-memory FormatSetDict")
|
345
|
+
parser.add_argument("--merge", action="store_true",
|
346
|
+
help="Merge generated sets into built-in registry (output_format_sets)")
|
347
|
+
parser.add_argument("--list", action="store_true",
|
348
|
+
help="When emitting dict (and/or after merge), list set names to stdout")
|
349
|
+
args = parser.parse_args()
|
350
|
+
|
351
|
+
try:
|
352
|
+
input_file = args.commands_json or Prompt.ask(
|
353
|
+
"Enter commands.json:", default="md_processing/data/commands.json"
|
354
|
+
)
|
355
|
+
|
356
|
+
if args.emit == "json":
|
357
|
+
# JSON output path
|
358
|
+
output_file = args.output_json or Prompt.ask(
|
359
|
+
"Output File:", default="md_processing/data/generated_format_sets.json"
|
360
|
+
)
|
361
|
+
save_generated_format_sets(input_file, output_file)
|
362
|
+
if args.merge:
|
363
|
+
# Also load and merge saved JSON into registry for convenience
|
364
|
+
from pyegeria._output_formats import load_output_format_sets
|
365
|
+
load_output_format_sets(output_file, merge=True)
|
366
|
+
logger.info("Merged saved JSON into built-in registry")
|
367
|
+
elif args.emit == "code":
|
368
|
+
# Python code output path
|
369
|
+
output_file = args.output_json or Prompt.ask(
|
370
|
+
"Output Python File:", default="md_processing/data/generated_format_sets.py"
|
371
|
+
)
|
372
|
+
save_generated_format_sets_code(input_file, output_file)
|
373
|
+
if args.merge:
|
374
|
+
# Dynamically import and merge the generated variable
|
375
|
+
try:
|
376
|
+
import importlib.util
|
377
|
+
import sys as _sys
|
378
|
+
spec = importlib.util.spec_from_file_location("_gen_fs_module", output_file)
|
379
|
+
mod = importlib.util.module_from_spec(spec)
|
380
|
+
assert spec and spec.loader
|
381
|
+
spec.loader.exec_module(mod) # type: ignore
|
382
|
+
generated = getattr(mod, "generated_format_sets", None)
|
383
|
+
if generated:
|
384
|
+
from pyegeria._output_formats import output_format_sets
|
385
|
+
merged = 0
|
386
|
+
for name, fs in generated.items():
|
387
|
+
output_format_sets[name] = fs
|
388
|
+
merged += 1
|
389
|
+
logger.info(f"Merged {merged} generated format sets from code into built-ins")
|
390
|
+
else:
|
391
|
+
logger.warning("No 'generated_format_sets' found in generated code module")
|
392
|
+
except Exception as e:
|
393
|
+
logger.error(f"Failed to import and merge generated code: {e}")
|
394
|
+
else:
|
395
|
+
# Emit dict path: build in memory
|
396
|
+
sets = generate_format_sets(input_file)
|
397
|
+
logger.info(f"Generated {len(sets)} format sets (in-memory FormatSetDict)")
|
398
|
+
if args.merge:
|
399
|
+
from pyegeria._output_formats import output_format_sets
|
400
|
+
merged = 0
|
401
|
+
for name, fs in sets.items():
|
402
|
+
output_format_sets[name] = fs
|
403
|
+
merged += 1
|
404
|
+
logger.info(f"Merged {merged} generated format sets into built-ins")
|
405
|
+
if args.list:
|
406
|
+
# If merged, show names from the global registry that match the generated ones
|
407
|
+
names = sorted(list(sets.keys()))
|
408
|
+
print("Merged set names:")
|
409
|
+
for n in names:
|
410
|
+
print(f"- {n}")
|
411
|
+
else:
|
412
|
+
if args.list:
|
413
|
+
names = sorted(list(sets.keys()))
|
414
|
+
print(f"Generated set names ({len(names)}):")
|
415
|
+
for n in names:
|
416
|
+
print(f"- {n}")
|
417
|
+
except (KeyboardInterrupt, EOFError):
|
418
|
+
# Graceful exit when user cancels or stdin is not interactive
|
419
|
+
pass
|
420
|
+
|
421
|
+
if __name__ == "__main__":
|
422
|
+
main()
|
@@ -123,13 +123,30 @@ COLLECTIONS_LIST = ["List Collections", "View Collections", "List Digital Produc
|
|
123
123
|
"List Context Event Collections", "View Context Event Collections",
|
124
124
|
"List Name Space Collections", "View Name Space Collections",
|
125
125
|
"List Event Set Collections", "View Event Set Collections",
|
126
|
-
"List Naming Standard Rulesets", "View Naming Standard Rulesets",
|
126
|
+
"List Naming Standard Rulesets", "View Naming Standard Rulesets", "List External Reference",
|
127
|
+
"List Related Media", "List Cited Document", "List External Data Source", "List External Model Source",
|
127
128
|
]
|
128
129
|
|
129
130
|
PROJECT_COMMANDS = ["Create Project", "Update Project", "Create Campaign", "Update Campaign",
|
130
131
|
"Create Task", "Update Task", "Create Study Project", "Update Study Project",
|
131
132
|
"Create Personal Project", "Update Personal Project"]
|
132
133
|
|
134
|
+
LINK_EXT_REF = ["Link External Reference", "Link Referenceable->External Reference", "Attach External Reference",
|
135
|
+
"Detach External Reference", "Detach External Reference Link", "Link External Data Source",
|
136
|
+
"Link External Model Source", "Detach External Data Source", "Detach External Model Source",]
|
137
|
+
|
138
|
+
LINK_MEDIA = ["Link Related Media", "Link Referenceable->Related Media", "Attach Related Media", "Attach Media Reference Link",
|
139
|
+
"Detach Related Media", "Detach Related Media Link", "Detach Media Reference Link"]
|
140
|
+
|
141
|
+
LINK_CITED_DOC = ["Link Cited Document", "Link Referenceable->Cited Document", "Attach Cited Document", "Attach Cited Document Link",
|
142
|
+
"Detach Cited Document", "Detach Cited Document Link",]
|
143
|
+
|
144
|
+
EXT_REF_UPSERT = ["Create External Reference", "Update External Reference",
|
145
|
+
"Create Related Media", "Update Related Media",
|
146
|
+
"Create Cited Document", "Update Cited Document",
|
147
|
+
"Create External Data Source", "Update External Data Source", "Create External Model Source",
|
148
|
+
"Update External Model Source",]
|
149
|
+
EXT_REF_COMMANDS = EXT_REF_UPSERT + LINK_EXT_REF + LINK_MEDIA + LINK_CITED_DOC
|
133
150
|
command_list = ["Provenance", "Create Glossary", "Update Glossary", "Create Term", "Update Term", "List Terms",
|
134
151
|
"List Term Details", "List Glossary Terms", "List Term History", "List Term Revision History",
|
135
152
|
"List Term Update History", "List Glossary Structure", "List Glossaries", "List Categories",
|
@@ -198,6 +215,7 @@ command_list.extend(GOV_LINK_LIST)
|
|
198
215
|
command_list.extend(COLLECTIONS_LIST)
|
199
216
|
command_list.extend(SIMPLE_COLLECTIONS)
|
200
217
|
command_list.extend(PROJECT_COMMANDS)
|
218
|
+
command_list.extend(EXT_REF_COMMANDS)
|
201
219
|
command_list.extend(["Link Governance Response", "Detach Governance Response",
|
202
220
|
"Link Governance Mechanism", "Detach Governance Mechanism"])
|
203
221
|
|