pyegeria 5.3.9.9.3__py3-none-any.whl → 5.5.3.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.

Files changed (272) hide show
  1. commands/__init__.py +24 -0
  2. commands/cat/Dr-Egeria_md-orig.py +2 -2
  3. commands/cat/__init__.py +1 -17
  4. commands/cat/collection_actions.py +197 -0
  5. commands/cat/dr_egeria_command_help.py +372 -0
  6. commands/cat/dr_egeria_jupyter.py +7 -7
  7. commands/cat/dr_egeria_md.py +27 -182
  8. commands/cat/exp_list_glossaries.py +11 -14
  9. commands/cat/get_asset_graph.py +37 -267
  10. commands/cat/{get_collection.py → get_collection_tree.py} +10 -18
  11. commands/cat/get_project_dependencies.py +14 -14
  12. commands/cat/get_project_structure.py +15 -14
  13. commands/cat/get_tech_type_elements.py +16 -116
  14. commands/cat/glossary_actions.py +145 -298
  15. commands/cat/list_assets.py +3 -11
  16. commands/cat/list_cert_types.py +17 -63
  17. commands/cat/list_collections.py +46 -138
  18. commands/cat/list_deployed_catalogs.py +15 -27
  19. commands/cat/list_deployed_database_schemas.py +27 -43
  20. commands/cat/list_deployed_databases.py +16 -31
  21. commands/cat/list_deployed_servers.py +35 -54
  22. commands/cat/list_glossaries.py +18 -17
  23. commands/cat/list_projects.py +10 -12
  24. commands/cat/list_tech_type_elements.py +21 -37
  25. commands/cat/list_tech_types.py +13 -25
  26. commands/cat/list_terms.py +38 -79
  27. commands/cat/list_todos.py +4 -11
  28. commands/cat/list_user_ids.py +3 -10
  29. commands/cat/my_reports.py +559 -0
  30. commands/cat/run_report.py +394 -0
  31. commands/cat/run_report_orig.py +528 -0
  32. commands/cli/egeria.py +222 -247
  33. commands/cli/egeria_cat.py +68 -81
  34. commands/cli/egeria_my.py +13 -0
  35. commands/cli/egeria_ops.py +69 -74
  36. commands/cli/egeria_tech.py +17 -93
  37. commands/cli/ops_config.py +3 -6
  38. commands/{cat/list_categories.py → deprecated/list_data_designer.py} +53 -64
  39. commands/{cat/list_data_structures.py → deprecated/list_data_structures_full.py} +3 -6
  40. commands/deprecated/old_get_asset_graph.py +315 -0
  41. commands/my/__init__.py +0 -2
  42. commands/my/list_my_profile.py +27 -34
  43. commands/my/list_my_roles.py +1 -7
  44. commands/my/monitor_my_todos.py +1 -7
  45. commands/my/monitor_open_todos.py +6 -7
  46. commands/my/todo_actions.py +4 -5
  47. commands/ops/__init__.py +0 -2
  48. commands/ops/gov_server_actions.py +17 -21
  49. commands/ops/list_archives.py +17 -38
  50. commands/ops/list_catalog_targets.py +33 -40
  51. commands/ops/load_archive.py +35 -26
  52. commands/ops/{monitor_engine_activity_c.py → monitor_active_engine_activity.py} +51 -82
  53. commands/ops/{monitor_integ_daemon_status.py → monitor_daemon_status.py} +35 -55
  54. commands/ops/monitor_engine_activity.py +79 -77
  55. commands/ops/{monitor_gov_eng_status.py → monitor_engine_status.py} +10 -7
  56. commands/ops/monitor_platform_status.py +38 -50
  57. commands/ops/monitor_server_startup.py +6 -11
  58. commands/ops/monitor_server_status.py +7 -11
  59. commands/ops/orig_monitor_server_list.py +8 -8
  60. commands/ops/orig_monitor_server_status.py +1 -5
  61. commands/ops/refresh_integration_daemon.py +5 -5
  62. commands/ops/restart_integration_daemon.py +5 -5
  63. commands/ops/table_integ_daemon_status.py +6 -6
  64. commands/ops/x_engine_actions.py +7 -7
  65. commands/tech/__init__.py +0 -2
  66. commands/tech/{generic_actions.py → element_actions.py} +6 -11
  67. commands/tech/get_element_info.py +20 -29
  68. commands/tech/get_guid_info.py +23 -42
  69. commands/tech/get_tech_details.py +20 -35
  70. commands/tech/get_tech_type_template.py +28 -39
  71. commands/tech/list_all_om_type_elements.py +24 -30
  72. commands/tech/list_all_om_type_elements_x.py +22 -28
  73. commands/tech/list_all_related_elements.py +19 -28
  74. commands/tech/list_anchored_elements.py +22 -30
  75. commands/tech/list_asset_types.py +19 -24
  76. commands/tech/list_elements_by_classification_by_property_value.py +26 -32
  77. commands/tech/list_elements_by_property_value.py +19 -25
  78. commands/tech/list_elements_by_property_value_x.py +20 -28
  79. commands/tech/list_elements_for_classification.py +28 -41
  80. commands/tech/list_gov_action_processes.py +16 -27
  81. commands/tech/list_information_supply_chains.py +22 -30
  82. commands/tech/list_registered_services.py +14 -26
  83. commands/tech/list_related_elements_with_prop_value.py +15 -25
  84. commands/tech/list_related_specification.py +1 -4
  85. commands/tech/list_relationship_types.py +15 -25
  86. commands/tech/list_relationships.py +20 -36
  87. commands/tech/list_solution_blueprints.py +28 -33
  88. commands/tech/list_solution_components.py +23 -29
  89. commands/tech/list_solution_roles.py +21 -32
  90. commands/tech/list_tech_templates.py +51 -54
  91. commands/tech/list_valid_metadata_values.py +5 -9
  92. commands/tech/table_tech_templates.py +2 -6
  93. commands/tech/x_list_related_elements.py +1 -4
  94. examples/GeoSpatial Products Example.py +524 -0
  95. examples/Jupyter Notebooks/P-egeria-server-config.ipynb +2137 -0
  96. examples/Jupyter Notebooks/README.md +2 -0
  97. examples/Jupyter Notebooks/common/P-environment-check.ipynb +115 -0
  98. examples/Jupyter Notebooks/common/__init__.py +14 -0
  99. examples/Jupyter Notebooks/common/common-functions.ipynb +4694 -0
  100. examples/Jupyter Notebooks/common/environment-check.ipynb +52 -0
  101. examples/Jupyter Notebooks/common/globals.ipynb +184 -0
  102. examples/Jupyter Notebooks/common/globals.py +154 -0
  103. examples/Jupyter Notebooks/common/orig_globals.py +152 -0
  104. examples/format_sets/all_format_sets.json +910 -0
  105. examples/format_sets/custom_format_sets.json +268 -0
  106. examples/format_sets/subset_format_sets.json +187 -0
  107. examples/format_sets_save_load_example.py +291 -0
  108. examples/jacquard_data_sets.py +129 -0
  109. examples/output_formats_example.py +193 -0
  110. examples/test_jacquard_data_sets.py +54 -0
  111. examples/test_jacquard_data_sets_scenarios.py +94 -0
  112. md_processing/__init__.py +90 -0
  113. md_processing/command_dispatcher.py +33 -0
  114. md_processing/command_mapping.py +221 -0
  115. md_processing/data/commands/commands_data_designer.json +537 -0
  116. md_processing/data/commands/commands_external_reference.json +733 -0
  117. md_processing/data/commands/commands_feedback.json +155 -0
  118. md_processing/data/commands/commands_general.json +204 -0
  119. md_processing/data/commands/commands_glossary.json +218 -0
  120. md_processing/data/commands/commands_governance.json +3678 -0
  121. md_processing/data/commands/commands_product_manager.json +865 -0
  122. md_processing/data/commands/commands_project.json +642 -0
  123. md_processing/data/commands/commands_solution_architect.json +366 -0
  124. md_processing/data/commands.json +17568 -0
  125. md_processing/data/commands_working.json +30641 -0
  126. md_processing/data/gened_report_specs.py +6584 -0
  127. md_processing/data/generated_format_sets.json +6533 -0
  128. md_processing/data/generated_format_sets_old.json +4137 -0
  129. md_processing/data/generated_format_sets_old.py +45 -0
  130. md_processing/dr_egeria.py +182 -0
  131. md_processing/md_commands/__init__.py +3 -0
  132. md_processing/md_commands/data_designer_commands.py +1276 -0
  133. md_processing/md_commands/ext_ref_commands.py +530 -0
  134. md_processing/md_commands/feedback_commands.py +726 -0
  135. md_processing/md_commands/glossary_commands.py +684 -0
  136. md_processing/md_commands/governance_officer_commands.py +600 -0
  137. md_processing/md_commands/product_manager_commands.py +1266 -0
  138. md_processing/md_commands/project_commands.py +383 -0
  139. md_processing/md_commands/solution_architect_commands.py +1184 -0
  140. md_processing/md_commands/view_commands.py +295 -0
  141. md_processing/md_processing_utils/__init__.py +4 -0
  142. md_processing/md_processing_utils/common_md_proc_utils.py +1249 -0
  143. md_processing/md_processing_utils/common_md_utils.py +578 -0
  144. md_processing/md_processing_utils/determine_width.py +103 -0
  145. md_processing/md_processing_utils/extraction_utils.py +547 -0
  146. md_processing/md_processing_utils/gen_report_specs.py +643 -0
  147. md_processing/md_processing_utils/generate_dr_help.py +193 -0
  148. md_processing/md_processing_utils/generate_md_cmd_templates.py +144 -0
  149. md_processing/md_processing_utils/generate_md_templates.py +83 -0
  150. md_processing/md_processing_utils/md_processing_constants.py +1228 -0
  151. md_processing/md_processing_utils/message_constants.py +19 -0
  152. pyegeria/__init__.py +201 -443
  153. pyegeria/core/__init__.py +40 -0
  154. pyegeria/core/_base_platform_client.py +574 -0
  155. pyegeria/core/_base_server_client.py +573 -0
  156. pyegeria/core/_exceptions.py +457 -0
  157. pyegeria/core/_globals.py +60 -0
  158. pyegeria/core/_server_client.py +6073 -0
  159. pyegeria/core/_validators.py +257 -0
  160. pyegeria/core/config.py +654 -0
  161. pyegeria/{create_tech_guid_lists.py → core/create_tech_guid_lists.py} +0 -1
  162. pyegeria/core/load_config.py +37 -0
  163. pyegeria/core/logging_configuration.py +207 -0
  164. pyegeria/core/mcp_adapter.py +144 -0
  165. pyegeria/core/mcp_server.py +212 -0
  166. pyegeria/core/utils.py +405 -0
  167. pyegeria/deprecated/__init__.py +0 -0
  168. pyegeria/{_client.py → deprecated/_client.py} +62 -24
  169. pyegeria/{_deprecated_gov_engine.py → deprecated/_deprecated_gov_engine.py} +16 -16
  170. pyegeria/{classification_manager_omvs.py → deprecated/classification_manager_omvs.py} +1988 -1878
  171. pyegeria/deprecated/output_formatter_with_machine_keys.py +1127 -0
  172. pyegeria/{runtime_manager_omvs.py → deprecated/runtime_manager_omvs.py} +216 -229
  173. pyegeria/{valid_metadata_omvs.py → deprecated/valid_metadata_omvs.py} +93 -93
  174. pyegeria/{x_action_author_omvs.py → deprecated/x_action_author_omvs.py} +2 -3
  175. pyegeria/egeria_cat_client.py +25 -51
  176. pyegeria/egeria_client.py +140 -98
  177. pyegeria/egeria_config_client.py +48 -24
  178. pyegeria/egeria_tech_client.py +170 -83
  179. pyegeria/models/__init__.py +150 -0
  180. pyegeria/models/collection_models.py +168 -0
  181. pyegeria/models/models.py +654 -0
  182. pyegeria/omvs/__init__.py +84 -0
  183. pyegeria/omvs/action_author.py +342 -0
  184. pyegeria/omvs/actor_manager.py +5980 -0
  185. pyegeria/omvs/asset_catalog.py +842 -0
  186. pyegeria/omvs/asset_maker.py +2736 -0
  187. pyegeria/omvs/automated_curation.py +4403 -0
  188. pyegeria/omvs/classification_manager.py +11213 -0
  189. pyegeria/omvs/collection_manager.py +5780 -0
  190. pyegeria/omvs/community_matters_omvs.py +468 -0
  191. pyegeria/{core_omag_server_config.py → omvs/core_omag_server_config.py} +157 -157
  192. pyegeria/{data_designer_omvs.py → omvs/data_designer.py} +1991 -1691
  193. pyegeria/omvs/data_discovery.py +869 -0
  194. pyegeria/omvs/data_engineer.py +372 -0
  195. pyegeria/omvs/digital_business.py +1133 -0
  196. pyegeria/omvs/external_links.py +1752 -0
  197. pyegeria/omvs/feedback_manager.py +834 -0
  198. pyegeria/{full_omag_server_config.py → omvs/full_omag_server_config.py} +73 -69
  199. pyegeria/omvs/glossary_manager.py +3231 -0
  200. pyegeria/omvs/governance_officer.py +3009 -0
  201. pyegeria/omvs/lineage_linker.py +314 -0
  202. pyegeria/omvs/location_arena.py +1525 -0
  203. pyegeria/omvs/metadata_expert.py +668 -0
  204. pyegeria/omvs/metadata_explorer_omvs.py +2943 -0
  205. pyegeria/omvs/my_profile.py +1042 -0
  206. pyegeria/omvs/notification_manager.py +358 -0
  207. pyegeria/omvs/people_organizer.py +394 -0
  208. pyegeria/{platform_services.py → omvs/platform_services.py} +113 -193
  209. pyegeria/omvs/product_manager.py +1825 -0
  210. pyegeria/omvs/project_manager.py +1907 -0
  211. pyegeria/omvs/reference_data.py +1140 -0
  212. pyegeria/omvs/registered_info.py +334 -0
  213. pyegeria/omvs/runtime_manager.py +2817 -0
  214. pyegeria/omvs/schema_maker.py +446 -0
  215. pyegeria/{server_operations.py → omvs/server_operations.py} +27 -26
  216. pyegeria/omvs/solution_architect.py +6490 -0
  217. pyegeria/omvs/specification_properties.py +37 -0
  218. pyegeria/omvs/subject_area.py +1042 -0
  219. pyegeria/omvs/template_manager_omvs.py +236 -0
  220. pyegeria/omvs/time_keeper.py +1761 -0
  221. pyegeria/omvs/valid_metadata.py +3221 -0
  222. pyegeria/omvs/valid_metadata_lists.py +37 -0
  223. pyegeria/omvs/valid_type_lists.py +37 -0
  224. pyegeria/view/__init__.py +28 -0
  225. pyegeria/view/_output_format_models.py +514 -0
  226. pyegeria/view/_output_formats.py +14 -0
  227. pyegeria/view/base_report_formats.py +2719 -0
  228. pyegeria/view/dr_egeria_reports.py +56 -0
  229. pyegeria/view/format_set_executor.py +397 -0
  230. pyegeria/{md_processing_utils.py → view/md_processing_utils.py} +5 -5
  231. pyegeria/{mermaid_utilities.py → view/mermaid_utilities.py} +2 -154
  232. pyegeria/view/output_formatter.py +1297 -0
  233. pyegeria-5.5.3.3.dist-info/METADATA +218 -0
  234. pyegeria-5.5.3.3.dist-info/RECORD +241 -0
  235. {pyegeria-5.3.9.9.3.dist-info → pyegeria-5.5.3.3.dist-info}/WHEEL +2 -1
  236. pyegeria-5.5.3.3.dist-info/entry_points.txt +103 -0
  237. pyegeria-5.5.3.3.dist-info/top_level.txt +4 -0
  238. commands/cat/.DS_Store +0 -0
  239. commands/cat/README.md +0 -16
  240. commands/cli/txt_custom_v2.tcss +0 -19
  241. commands/my/README.md +0 -17
  242. commands/ops/README.md +0 -24
  243. commands/ops/monitor_asset_events.py +0 -108
  244. commands/tech/README.md +0 -24
  245. pyegeria/.DS_Store +0 -0
  246. pyegeria/README.md +0 -35
  247. pyegeria/_globals.py +0 -47
  248. pyegeria/_validators.py +0 -385
  249. pyegeria/asset_catalog_omvs.py +0 -864
  250. pyegeria/automated_curation_omvs.py +0 -3765
  251. pyegeria/collection_manager_omvs.py +0 -2744
  252. pyegeria/dr.egeria spec.md +0 -9
  253. pyegeria/egeria_my_client.py +0 -56
  254. pyegeria/feedback_manager_omvs.py +0 -4573
  255. pyegeria/glossary_browser_omvs.py +0 -3728
  256. pyegeria/glossary_manager_omvs.py +0 -2440
  257. pyegeria/m_test.py +0 -118
  258. pyegeria/md_processing_helpers.py +0 -58
  259. pyegeria/md_processing_utils_orig.py +0 -1103
  260. pyegeria/metadata_explorer_omvs.py +0 -2326
  261. pyegeria/my_profile_omvs.py +0 -1022
  262. pyegeria/output_formatter.py +0 -389
  263. pyegeria/project_manager_omvs.py +0 -1933
  264. pyegeria/registered_info.py +0 -167
  265. pyegeria/solution_architect_omvs.py +0 -2156
  266. pyegeria/template_manager_omvs.py +0 -1414
  267. pyegeria/utils.py +0 -197
  268. pyegeria-5.3.9.9.3.dist-info/METADATA +0 -72
  269. pyegeria-5.3.9.9.3.dist-info/RECORD +0 -143
  270. pyegeria-5.3.9.9.3.dist-info/entry_points.txt +0 -99
  271. /pyegeria/{_exceptions.py → deprecated/_exceptions.py} +0 -0
  272. {pyegeria-5.3.9.9.3.dist-info → pyegeria-5.5.3.3.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,524 @@
1
+ """SPDX-License-Identifier: Apache-2.0
2
+ Copyright Contributors to the ODPi Egeria project.
3
+
4
+ This module provides a simple example for building out some GeoSpatial Digital Products.
5
+
6
+
7
+ """
8
+ import os
9
+ import time
10
+
11
+ from loguru import logger
12
+ from rich.console import Console
13
+
14
+ from pyegeria.core.config import get_app_config
15
+ from pyegeria.core.logging_configuration import config_logging
16
+ from pyegeria.core._exceptions import (PyegeriaException, print_validation_error,
17
+ PyegeriaInvalidParameterException, PyegeriaConnectionException,
18
+ PyegeriaAPIException, PyegeriaUnknownException, print_exception_table
19
+ )
20
+ from pydantic import ValidationError
21
+ from pyegeria import EgeriaTech
22
+
23
+ EGERIA_USER = os.environ.get("EGERIA_USER", "erinoverview")
24
+ EGERIA_USER_PASSWORD = os.environ.get("EGERIA_USER_PASSWORD", "secret")
25
+
26
+ app_settings = get_app_config()
27
+ app_config = app_settings.Environment
28
+ config_logging()
29
+ logger.enable("pyegeria")
30
+ logger.info(f"Console width is {app_config.console_width}")
31
+
32
+ view_server = app_config.egeria_view_server
33
+ view_url = app_config.egeria_view_server_url
34
+ user = EGERIA_USER
35
+ user_pass = EGERIA_USER_PASSWORD
36
+
37
+
38
+ console = Console(
39
+ style="bold bright_white on black",
40
+ width=app_config.console_width,
41
+ force_terminal=not app_config.egeria_jupyter,
42
+ )
43
+
44
+
45
+
46
+
47
+ try:
48
+ client = EgeriaTech(view_server, view_url, user, user_pass)
49
+
50
+ token = client.create_egeria_bearer_token()
51
+ start_time = time.perf_counter()
52
+ logger.info("Starting to create GeoSpatial Products")
53
+ display_name = "GeoSpatial Root"
54
+ description = "This is the root of the GeoSpatial work"
55
+ category = "GeoSpatial"
56
+
57
+
58
+ print("First we'll set up a number of folders to support the work.")
59
+ #
60
+ # Root Folder
61
+ #
62
+ root = client.get_collections_by_name(display_name)
63
+ if isinstance(root, dict | list):
64
+ root_guid = root[0]['elementHeader']['guid']
65
+ print(f"Found root guid of {root_guid}")
66
+ else:
67
+ root_guid = client.create_root_collection(
68
+ display_name=display_name,
69
+ description=description,
70
+ category=category
71
+ )
72
+ logger.success(f"Created root collection {root_guid}")
73
+ #
74
+ # Digital Products Marketplace
75
+ #
76
+ display_name = "Digital Products MarketPlace"
77
+ description = "This is the digital products marketplace"
78
+ category = "GeoSpatial"
79
+ qualified_name = client.__create_qualified_name__("Marketplace", display_name)
80
+
81
+ props_body = {
82
+ "class": "DigitalProductCatalogProperties",
83
+ "qualifiedName": qualified_name,
84
+ "displayName": display_name,
85
+ "description": description,
86
+ "category": category
87
+ }
88
+
89
+ request_body = {
90
+
91
+ "class": "NewElementRequestBody",
92
+ "isOwnAnchor": False,
93
+ "anchorGUID": root_guid,
94
+ "parentGUID": root_guid,
95
+ "parentRelationshipTypeName": "CollectionMembership",
96
+ "parentAtEnd1": True,
97
+ "properties": props_body,
98
+ }
99
+ marketplace = client.get_collections_by_name(qualified_name)
100
+ if isinstance(marketplace, dict | list):
101
+ marketplace_guid = marketplace[0]['elementHeader']['guid']
102
+ print(f"Found marketplace guid of {marketplace_guid}")
103
+ else:
104
+ marketplace_guid = client.create_digital_product_catalog(body=request_body)
105
+ logger.success(f"Created folder collection for marketplace: {marketplace_guid}")
106
+ #
107
+ # GeoSpatial Products folder
108
+ #
109
+ display_name = "GeoSpatial Products"
110
+ description = "GeoSpatial product offerings"
111
+ category = "GeoSpatial"
112
+ qualified_name = client.__create_qualified_name__("Folder", display_name)
113
+
114
+ props_body = {
115
+ "class": "DigitalProductCatalogProperties",
116
+ "qualifiedName": qualified_name,
117
+ "displayName": display_name,
118
+ "description": description,
119
+ "category": category
120
+ }
121
+
122
+ request_body = {
123
+ "class": "NewElementRequestBody",
124
+ "isOwnAnchor": False,
125
+ "anchorGUID": marketplace_guid,
126
+ "parentGUID": marketplace_guid,
127
+ "parentRelationshipTypeName": "CollectionMembership",
128
+ "parentAtEnd1": True,
129
+ "properties": props_body,
130
+ }
131
+ geo_prods = client.get_collections_by_name(qualified_name)
132
+ if isinstance(geo_prods, dict | list):
133
+ geo_prods_guid = geo_prods[0]['elementHeader']['guid']
134
+ print(f"Found geo_prods guid of {geo_prods_guid}")
135
+ else:
136
+ geo_prods_guid = client.create_digital_product_catalog(body=request_body)
137
+ logger.success(f"Created folder collection for geoprods: {geo_prods_guid}")
138
+ #
139
+ # Agricultural Products Folder
140
+ #
141
+ display_name = "Agricultural Products"
142
+ description = "Agricultural product offerings"
143
+ category = "GeoSpatial"
144
+ qualified_name = client.__create_qualified_name__("Folder", display_name)
145
+
146
+ props_body = {
147
+
148
+ "class": "DigitalProductCatalogProperties",
149
+ "qualifiedName": qualified_name,
150
+ "displayName": display_name,
151
+ "description": description,
152
+ "category": category
153
+ }
154
+
155
+ request_body = {
156
+
157
+ "class": "NewElementRequestBody",
158
+ "isOwnAnchor": False,
159
+ "anchorGUID": marketplace_guid,
160
+ "parentGUID": marketplace_guid,
161
+ "parentRelationshipTypeName": "CollectionMembership",
162
+ "parentAtEnd1": True,
163
+ "properties": props_body, }
164
+ ag_prods = client.get_collections_by_name(qualified_name)
165
+ if isinstance(ag_prods, dict | list):
166
+ ag_prods_guid = ag_prods[0]['elementHeader']['guid']
167
+ print(f"Found ag_prods guid of {ag_prods_guid}")
168
+ else:
169
+ ag_prods_guid = client.create_digital_product_catalog(body=request_body)
170
+ logger.success(f"Created folder collection for ag products: {ag_prods_guid}")
171
+ #
172
+ # Folder to hold Prepared Imagery Products
173
+ #
174
+ display_name = "Prepared Imagery Products"
175
+ description = "Imagery products that are ready for consumption"
176
+ category = "GeoSpatial"
177
+ qualified_name = client.__create_qualified_name__("Folder", display_name)
178
+
179
+ props_body = {
180
+ "class": "DigitalProductCatalogProperties",
181
+ "qualifiedName": qualified_name,
182
+ "displayName": display_name,
183
+ "description": description,
184
+ "category": category
185
+ }
186
+
187
+ request_body = {
188
+ "class": "NewElementRequestBody",
189
+ "isOwnAnchor": False,
190
+ "anchorGUID": root_guid,
191
+ "parentGUID": root_guid,
192
+ "parentRelationshipTypeName": "CollectionMembership",
193
+ "parentAtEnd1": True,
194
+ "properties": props_body,
195
+ }
196
+ prepared_imagery = client.get_collections_by_name(qualified_name)
197
+ if isinstance(prepared_imagery, dict | list):
198
+ prepared_imagery_guid = prepared_imagery[0]['elementHeader']['guid']
199
+ print(f"Found prepared_imagery guid of {prepared_imagery_guid}")
200
+ else:
201
+ prepared_imagery_guid = client.create_digital_product_catalog(body=request_body)
202
+ logger.success(f"Created folder for prepared imagery products: {prepared_imagery_guid}")
203
+ #
204
+ # A digital product covering NDVI - derived from Sentinel 2
205
+ #
206
+ display_name = "NDVI - Sentinel 2 derived"
207
+ description = "NDVI vegetation index calculated from Sentinel 2 imagery"
208
+ category = "GeoSpatial"
209
+ qualified_name = client.__create_qualified_name__("DigitalProduct", display_name)
210
+
211
+ props_body = {
212
+ "class": "DigitalProductProperties",
213
+ "qualifiedName": qualified_name,
214
+ "displayName": display_name,
215
+ "description": description,
216
+ "category": category,
217
+ "productType": "Periodic Extended",
218
+ "identifier": "NDVI-S",
219
+ "productName": "NDVI - Sentinel 2",
220
+ "serviceLife": "Until interest and budget wane",
221
+ "maturity": "Nascent"
222
+ }
223
+
224
+ request_body = {
225
+ "class": "NewElementRequestBody",
226
+ "isOwnAnchor": False,
227
+ "anchorGUID": prepared_imagery_guid,
228
+ "parentGUID": prepared_imagery_guid,
229
+ "parentRelationshipTypeName": "CollectionMembership",
230
+ "parentAtEnd1": True,
231
+ "properties": props_body,
232
+ }
233
+
234
+ ndvi = client.get_collections_by_name(qualified_name)
235
+ if isinstance(ndvi, dict | list):
236
+ ndvi_guid = ndvi[0]['elementHeader']['guid']
237
+ print(f"Found ndvi guid of {ndvi_guid}")
238
+ else:
239
+ ndvi_guid = client.create_digital_product(body=request_body)
240
+ logger.success(f"Created NDVI product: {ndvi_guid}")
241
+ #
242
+ # A folder to hold Raw Satellite Imagery Products
243
+ #
244
+ display_name = "Raw Satellite Imagery Products"
245
+ description = "Raw satellite imagery imported from or referenced from satellite data providers"
246
+ category = "GeoSpatial"
247
+ qualified_name = client.__create_qualified_name__("Folder", display_name)
248
+
249
+ props_body = {
250
+ "class": "DigitalProductCatalogProperties",
251
+ "qualifiedName": qualified_name,
252
+ "displayName": display_name,
253
+ "description": description,
254
+ "category": category
255
+ }
256
+
257
+ request_body = {
258
+ "class": "NewElementRequestBody",
259
+ "isOwnAnchor": False,
260
+ "anchorGUID": root_guid,
261
+ "parentGUID": root_guid,
262
+ "parentRelationshipTypeName": "CollectionMembership",
263
+ "parentAtEnd1": True,
264
+ "properties": props_body,
265
+ }
266
+ raw_imagery = client.get_collections_by_name(qualified_name)
267
+ if isinstance(raw_imagery, dict | list):
268
+ raw_imagery_guid = raw_imagery[0]['elementHeader']['guid']
269
+ print(f"Found raw_imagery guid of {raw_imagery_guid}")
270
+ else:
271
+ raw_imagery_guid = client.create_digital_product_catalog(body=request_body)
272
+ logger.success(f"Created folder for raw imagery products: {raw_imagery_guid}")
273
+ #
274
+ # A digital product providing Sentinel-2a imagery
275
+ #
276
+ display_name = "Sentinel-2a"
277
+ description = "Level 2a (surface level) imagery"
278
+ category = "GeoSpatial"
279
+ qualified_name = client.__create_qualified_name__("DigitalProduct", display_name)
280
+
281
+ props_body = {
282
+ "class": "DigitalProductProperties",
283
+ "qualifiedName": qualified_name,
284
+ "displayName": display_name,
285
+ "description": description,
286
+ "category": category,
287
+ "productType": "Periodic Extended",
288
+ "identifier": "sentinel-2a",
289
+ "productName": "Sentinel Level 2A",
290
+ "serviceLife": "Until interest and budget wane",
291
+ "maturity": "Nascent"
292
+ }
293
+
294
+ request_body = {
295
+ "class": "NewElementRequestBody",
296
+ "isOwnAnchor": False,
297
+ "anchorGUID": raw_imagery_guid,
298
+ "parentGUID": raw_imagery_guid,
299
+ "parentRelationshipTypeName": "CollectionMembership",
300
+ "parentAtEnd1": True,
301
+ "properties": props_body,
302
+ }
303
+ sentinel2a = client.get_collections_by_name(qualified_name)
304
+ if isinstance(sentinel2a, dict | list):
305
+ sentinel2a_guid = sentinel2a[0]['elementHeader']['guid']
306
+ print(f"Found sentinel2a guid of {sentinel2a_guid}")
307
+ else:
308
+ sentinel2a_guid = client.create_digital_product(body=request_body)
309
+ logger.success(f"Created Sentinel-2a product: {sentinel2a_guid}")
310
+
311
+ # NDVI uses Sentinel 2A data so Add a dependency between ndvi dependent on sentinel2a
312
+ client.link_digital_product_dependency(sentinel2a_guid, ndvi_guid)
313
+
314
+ #
315
+ # Now lets create some standard subscriptions (a form of agreement)
316
+ #
317
+ # Create a folder for standard agreements
318
+ display_name = "Standard Subscription Agreements Folder"
319
+ description = "A folder collection for digital product subscriptions"
320
+ category = "GeoSpatial"
321
+ qualified_name = client.__create_qualified_name__("Folder", display_name)
322
+
323
+ props_body = {
324
+ "class": "CollectionProperties",
325
+ "qualifiedName": qualified_name,
326
+ "displayName": display_name,
327
+ "description": description,
328
+ "category": category
329
+ }
330
+
331
+ request_body = {
332
+ "class": "NewElementRequestBody",
333
+ "isOwnAnchor": False,
334
+ "anchorGUID": root_guid,
335
+ "parentGUID": root_guid,
336
+ "parentRelationshipTypeName": "CollectionMembership",
337
+ "parentAtEnd1": True,
338
+ "properties": props_body,
339
+ }
340
+ subscriptions_folder = client.get_collections_by_name(qualified_name)
341
+ if isinstance(subscriptions_folder, dict | list):
342
+ subscriptions_folder_guid = subscriptions_folder[0]['elementHeader']['guid']
343
+ print(f"Found Standard Subscription Agreements Folder {subscriptions_folder_guid}")
344
+ else:
345
+ subscriptions_folder_guid = client.create_folder_collection(body=request_body)
346
+ logger.success(f"Created folder for standard subscriptions: {subscriptions_folder_guid}")
347
+ #
348
+ # Add a Digital Subscription to this folder
349
+ #
350
+ anchor_guid = subscriptions_folder_guid
351
+ parent_guid = subscriptions_folder_guid
352
+ parent_relationship_type_name = "CollectionMembership"
353
+ parent_at_end1 = True
354
+ display_name = "GeoSpatial Data Products Subscription"
355
+ description = "A generic subscription agreement for GeoSpatial Data Products"
356
+ identifier = "GeoSpatial-0"
357
+ category = "GeoSpatial"
358
+ is_own_anchor = False
359
+
360
+ qualified_name = client.__create_qualified_name__("DigitalSubscription", display_name)
361
+
362
+ body = {
363
+ "class": "NewElementRequestBody",
364
+ "anchorGUID": anchor_guid,
365
+ "isOwnAnchor": is_own_anchor,
366
+ "parentGUID": parent_guid,
367
+ # "initialClassification": {classification: {"class": {}}},
368
+ "parentRelationshipTypeName": parent_relationship_type_name,
369
+ "parentAtEnd1": parent_at_end1,
370
+ "properties": {
371
+ "class": "DigitalSubscriptionProperties",
372
+ "displayName": display_name,
373
+ "qualifiedName": qualified_name,
374
+ "description": description,
375
+ "identifier": identifier,
376
+ "category": category,
377
+ "supportLevel": "Best Effort"
378
+ },
379
+ }
380
+ geo_subscriptions = client.get_collections_by_name(qualified_name)
381
+ if isinstance(geo_subscriptions, dict | list):
382
+ geo_subscriptions_guid = geo_subscriptions[0]['elementHeader']['guid']
383
+ print(f"Found GeoSpatial Subscriptions guid of {geo_subscriptions_guid}")
384
+ else:
385
+ geo_subscriptions_guid = client.create_digital_subscription(body)
386
+ print(f"Created Digital Subscription, GeoSpatial Data Products Subscription: {geo_subscriptions_guid}")
387
+ logger.success(f"Created subscription : {geo_subscriptions_guid}")
388
+ #
389
+ # Add agreement items to the agreement - the sentinel data
390
+ #
391
+ body = {
392
+ "class": "NewRelationshipRequestBody",
393
+ "properties": {
394
+ "class": "AgreementItemProperties",
395
+ "agreementItemId": "Sentinel-2a-Subscription",
396
+ "agreementStart": "2025-08-01",
397
+ "agreementEnd": "2025-12-31",
398
+ "entitlements": {"Data Download": "Allowed", "Data Sharing": "Allowed"}
399
+ }
400
+ }
401
+ client.link_agreement_item(geo_subscriptions_guid, sentinel2a_guid, body)
402
+ msg = f"Linked agreement item sentinel2a to geo_subscriptions"
403
+ logger.success(msg)
404
+ print(msg)
405
+
406
+ #
407
+ # Licensing
408
+ #
409
+ # First a folder to hold license types - we will anchor it to the GeoSpatial root
410
+ #
411
+ display_name = "GeoSpatial Data Products License Types"
412
+ description = "A folder collection containing license types governing GeoSpatial Data Products"
413
+ category = "GeoSpatial"
414
+ qualified_name = client.__create_qualified_name__("Folder", display_name)
415
+
416
+ props_body = {
417
+ "class": "CollectionProperties",
418
+ "qualifiedName": qualified_name,
419
+ "displayName": display_name,
420
+ "description": description,
421
+ "category": category
422
+ }
423
+
424
+ request_body = {
425
+ "class": "NewElementRequestBody",
426
+ "isOwnAnchor": False,
427
+ "anchorGUID": root_guid,
428
+ "parentGUID": root_guid,
429
+ "parentRelationshipTypeName": "CollectionMembership",
430
+ "parentAtEnd1": True,
431
+ "properties": props_body,
432
+ }
433
+ license_type_folder = client.get_collections_by_name(qualified_name)
434
+ if not isinstance(license_type_folder, dict | list):
435
+ license_type_folder_guid = client.create_folder_collection(body=request_body)
436
+ logger.success(f"Created folder for GeoSpatial Data Products License Types: {license_type_folder_guid}")
437
+ else:
438
+ license_type_folder_guid = license_type_folder[0]['elementHeader']['guid']
439
+ print(f"Found license_type_folder guid of {license_type_folder_guid}")
440
+
441
+ #
442
+ # Now lets create a few license types:
443
+ # - one for importing sentinel 2 data from ESA
444
+ # - one for offering the sentinel 2 data as a digital product
445
+ # - one for offering our derived product (NDVI) as a digital product
446
+ #
447
+ display_name = "ESA License Type"
448
+ description = "A folder collection containing license types governing GeoSpatial Data Products"
449
+ summary = "Free and Open Data - Requires Attribution"
450
+ category = "GeoSpatial"
451
+ details = "https://www.copernicus.eu/en/access-data/copyright-and-licences"
452
+ qualified_name = client.__create_qualified_name__("LicenseType", display_name)
453
+
454
+
455
+ props_body = {
456
+ "class": "LicenseTypeProperties",
457
+ "typeName": "LicenseType",
458
+ "domainIdentifier": 0,
459
+ "qualifiedName": qualified_name,
460
+ "display_name": display_name,
461
+ "summary": summary,
462
+ "description": description,
463
+ "scope": "World-Wide",
464
+ "importance": "Foundational",
465
+ # "details": details,
466
+ # "entitlements": {"Data Download": "True", "Data Sharing": "True", "Data Access": "True",
467
+ # "Data Usage": "True", "Data Analysis": "True"},
468
+ # "restrictions": {},
469
+ # "obligations": {"Attribution Required": "True"},
470
+ "implications": ["Open Use"],
471
+ "outcomes": ["Data Available"]
472
+ # "results": [],
473
+ }
474
+
475
+
476
+ request_body = {
477
+ "class": "NewElementRequestBody",
478
+ "anchorGUID": license_type_folder_guid,
479
+ "isOwnAnchor": False,
480
+ "parentGUID": license_type_folder_guid,
481
+ "parentRelationshipTypeName": "CollectionMembership",
482
+ "parentAtEnd1": True,
483
+ "properties": {
484
+ "class": "LicenseTypeProperties",
485
+ "typeName": "LicenseType",
486
+ "domainIdentifier": 0,
487
+ "qualifiedName": qualified_name,
488
+ "display_name": display_name,
489
+ "summary": summary,
490
+ "description": description,
491
+ "scope": "World-Wide",
492
+ "importance": "Foundational",
493
+ # "details": details,
494
+ "entitlements": {"Data Download": "True", "Data Sharing": "True", "Data Access": "True",
495
+ "Data Usage": "True", "Data Analysis": "True"},
496
+ "restrictions": {},
497
+ "obligations": {"Attribution Required": "True"},
498
+ "implications": ["Open Use"],
499
+ "outcomes": ["Data Available"],
500
+ "results": []
501
+ },
502
+ "initialStatus": "ACTIVE"
503
+ }
504
+
505
+ esa_license_type = client.get_governance_definitions_by_name(qualified_name)
506
+ if not isinstance(esa_license_type, dict | list):
507
+ esa_license_type_guid = client.create_governance_definition(body=request_body)
508
+ logger.success(f"Created license type for ESA License Type: {esa_license_type_guid}")
509
+ else:
510
+ esa_license_type_guid = esa_license_type[0]['elementHeader']['guid']
511
+ print(f"Found license_type_guid for esa license type {esa_license_type_guid}")
512
+
513
+
514
+
515
+ except (PyegeriaInvalidParameterException, PyegeriaConnectionException, PyegeriaAPIException,
516
+ PyegeriaUnknownException, PyegeriaException) as e:
517
+ print_exception_table(e)
518
+ except ValidationError as e:
519
+ print_validation_error(e)
520
+ except Exception as e:
521
+ print(e)
522
+
523
+ finally:
524
+ client.close_session()