pyegeria 5.4.0.26__py3-none-any.whl → 5.4.0.27__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.
Files changed (46) hide show
  1. commands/cat/debug_log +868 -7794
  2. commands/cat/debug_log.2025-08-18_11-34-38_088636.zip +0 -0
  3. commands/cat/list_collections.py +1 -1
  4. commands/cat/list_format_set.py +6 -8
  5. commands/cli/egeria.py +2 -2
  6. commands/cli/egeria_cat.py +3 -2
  7. commands/ops/load_archive.py +2 -2
  8. md_processing/data/commands.json +7 -7
  9. md_processing/dr_egeria_inbox/dr_egeria_intro_part1.md +7 -7
  10. md_processing/dr_egeria_inbox/dr_egeria_intro_part2.md +36 -31
  11. md_processing/dr_egeria_outbox/friday/processed-2025-08-22 21:22-dr_egeria_intro_part1.md +312 -0
  12. md_processing/dr_egeria_outbox/friday/processed-2025-08-22 21:23-dr_egeria_intro_part1.md +265 -0
  13. md_processing/dr_egeria_outbox/friday/processed-2025-08-23 15:06-dr_egeria_intro_part1.md +230 -0
  14. md_processing/dr_egeria_outbox/friday/processed-2025-08-23 15:30-dr_egeria_intro_part1.md +296 -0
  15. md_processing/dr_egeria_outbox/friday/processed-2025-08-23 15:31-dr_egeria_intro_part1.md +253 -0
  16. md_processing/dr_egeria_outbox/friday/processed-2025-08-23 16:08-dr_egeria_intro_part2.md +343 -0
  17. md_processing/dr_egeria_outbox/friday/processed-2025-08-23 16:12-dr_egeria_intro_part2.md +343 -0
  18. md_processing/md_commands/glossary_commands.py +888 -951
  19. md_processing/md_commands/product_manager_commands.py +8 -270
  20. md_processing/md_commands/project_commands.py +1 -1
  21. md_processing/md_processing_utils/common_md_proc_utils.py +138 -64
  22. md_processing/md_processing_utils/common_md_utils.py +2 -1
  23. pyegeria/__init__.py +2 -3
  24. pyegeria/_client_new.py +4 -3
  25. pyegeria/_output_formats.py +5 -3
  26. pyegeria/collection_manager.py +31 -28
  27. pyegeria/{load_config.py → config.py} +7 -2
  28. pyegeria/data_designer.py +154 -194
  29. pyegeria/egeria_cat_client.py +46 -28
  30. pyegeria/egeria_client.py +71 -72
  31. pyegeria/egeria_config_client.py +37 -7
  32. pyegeria/egeria_my_client.py +45 -10
  33. pyegeria/egeria_tech_client.py +68 -57
  34. pyegeria/glossary_manager.py +494 -122
  35. pyegeria/governance_officer.py +2 -2
  36. pyegeria/logging_configuration.py +1 -4
  37. pyegeria/models.py +1 -1
  38. pyegeria/project_manager.py +358 -509
  39. pyegeria/utils.py +1 -3
  40. {pyegeria-5.4.0.26.dist-info → pyegeria-5.4.0.27.dist-info}/METADATA +1 -1
  41. {pyegeria-5.4.0.26.dist-info → pyegeria-5.4.0.27.dist-info}/RECORD +44 -38
  42. md_processing/md_processing_utils/solution_architect_log.log +0 -0
  43. pyegeria/glossary_browser.py +0 -1259
  44. {pyegeria-5.4.0.26.dist-info → pyegeria-5.4.0.27.dist-info}/LICENSE +0 -0
  45. {pyegeria-5.4.0.26.dist-info → pyegeria-5.4.0.27.dist-info}/WHEEL +0 -0
  46. {pyegeria-5.4.0.26.dist-info → pyegeria-5.4.0.27.dist-info}/entry_points.txt +0 -0
@@ -9,27 +9,17 @@ Copyright Contributors to the ODPi Egeria project.
9
9
 
10
10
  import asyncio
11
11
 
12
- from loguru import logger
13
-
14
12
  from pyegeria._client_new import Client2
15
13
  from pyegeria.load_config import get_app_config
16
14
  from pyegeria.models import (SearchStringRequestBody, FilterRequestBody, GetRequestBody, NewElementRequestBody,
17
- TemplateRequestBody, UpdateElementRequestBody, DeleteRequestBody,
18
- NewRelationshipRequestBody)
15
+ TemplateRequestBody)
19
16
  from pyegeria.utils import body_slimmer, dynamic_catch
20
- from pyegeria._output_formats import select_output_format_set, get_output_format_type_match
21
- from pyegeria.output_formatter import (generate_output,
22
- _extract_referenceable_properties,
23
- populate_columns_from_properties,
24
- get_required_relationships)
25
17
 
26
18
  app_settings = get_app_config()
27
19
  EGERIA_LOCAL_QUALIFIER = app_settings.User_Profile.egeria_local_qualifier
28
20
  from pyegeria._globals import NO_ELEMENTS_FOUND, NO_PROJECTS_FOUND
29
21
 
30
22
  PROJECT_TYPES = ["Project", "Campaign", "StudyProject", "Task", "PersonalProject"]
31
- PROJECT_PROPERTIES_LIST = ["ProjectProperties", "CampaignProperties", "StudyProjectProperties", "TaskProperties",
32
- "PersonalProjectProperties"]
33
23
 
34
24
  class ProjectManager(Client2):
35
25
  """
@@ -67,93 +57,18 @@ class ProjectManager(Client2):
67
57
  Client2.__init__(self, view_server, platform_url, user_id, user_pwd, token)
68
58
 
69
59
 
70
- def _extract_project_properties(self, element: dict, columns_struct: dict) -> dict:
71
- """
72
- Populate columns_struct values for a Project element using the standardized approach from collection_manager.
73
- - Populate from element.properties
74
- - Overlay header-derived values
75
- - Derive classifications list
76
- - Populate relationship-based columns generically
77
- - Include mermaid graph if requested
78
- """
79
- col_data = populate_columns_from_properties(element, columns_struct)
80
- columns_list = col_data.get("formats", {}).get("columns", [])
81
-
82
- # Header-derived values
83
- header_props = _extract_referenceable_properties(element)
84
- for column in columns_list:
85
- key = column.get('key')
86
- if key in header_props:
87
- column['value'] = header_props.get(key)
88
- elif isinstance(key, str) and key.lower() == 'guid':
89
- column['value'] = header_props.get('GUID')
90
-
91
- # Classifications
92
- cl_names = []
93
- for c in element.get('elementHeader', {}).get('classifications', []) or []:
94
- nm = c.get('classificationName')
95
- if nm:
96
- cl_names.append(nm)
97
- if cl_names:
98
- for column in columns_list:
99
- if column.get('key') == 'classifications':
100
- column['value'] = ", ".join(cl_names)
101
- break
102
-
103
- # Relationships
104
- col_data = get_required_relationships(element, col_data)
105
-
106
- # Mermaid
107
- mermaid_val = element.get('mermaidGraph', "") or ""
108
- for column in columns_list:
109
- if column.get('key') == 'mermaid':
110
- column['value'] = mermaid_val
111
- break
112
-
113
- return col_data
114
-
115
- def _generate_project_output(self, elements: dict | list[dict], filter: str = None,
116
- element_type_name: str | None = None,
117
- output_format: str = 'DICT',
118
- output_format_set: str | dict = None) -> str | list[dict]:
119
- """
120
- Generate output for projects using selectable output format sets.
121
- """
122
- entity_type = element_type_name or 'Project'
123
-
124
- # Resolve output formats
125
- if output_format_set:
126
- if isinstance(output_format_set, str):
127
- output_formats = select_output_format_set(output_format_set, output_format)
128
- elif isinstance(output_format_set, dict):
129
- output_formats = get_output_format_type_match(output_format_set, output_format)
130
- elif element_type_name:
131
- output_formats = select_output_format_set(element_type_name, output_format)
132
- else:
133
- output_formats = select_output_format_set(entity_type, output_format)
134
- if output_formats is None:
135
- output_formats = select_output_format_set('Default', output_format)
136
-
137
- return generate_output(
138
- elements,
139
- filter,
140
- entity_type,
141
- output_format,
142
- self._extract_project_properties,
143
- None,
144
- output_formats,
145
- )
60
+ def _generate_project_output(self):
61
+ pass
146
62
  #
147
63
  # Retrieving Projects= Information - https://egeria-project.org/concepts/project
148
64
  #
149
65
  async def _async_get_linked_projects(
150
66
  self,
151
67
  parent_guid: str,
152
- filter_string: str = None,
153
- classification_names: list[str] = None,
154
- body: dict | FilterRequestBody = None,
155
- start_from: int = 0, page_size: int = None,
156
- output_format: str = "json", output_format_set: str | dict = None,
68
+ project_status: str = None,
69
+ effective_time: str = None,
70
+ start_from: int = 0,
71
+ page_size: int = None,
157
72
  ) -> list | str:
158
73
  """Returns the list of projects that are linked off of the supplied element. Any relationship will do.
159
74
  The request body is optional, but if supplied acts as a filter on project status. Async version.
@@ -190,51 +105,82 @@ class ProjectManager(Client2):
190
105
 
191
106
  """
192
107
 
108
+ if page_size is None:
109
+ page_size = self.page_size
110
+
111
+ body = {
112
+ "filter": project_status,
113
+ "effectiveTime": effective_time,
114
+ }
115
+ body_s = body_slimmer(body)
193
116
  url = (
194
117
  f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/"
195
- f"metadata-elements/{parent_guid}/projects"
118
+ f"metadata-elements/{parent_guid}/projects?startFrom={start_from}&pageSize={page_size}"
196
119
  )
197
120
 
198
- response = await self._async_get_name_request(url, _type="Project",
199
- _gen_output=self._generate_project_output,
200
- filter_string=filter_string,
201
- classification_names=classification_names,
202
- start_from=start_from, page_size=page_size,
203
- output_format=output_format, output_format_set=output_format_set,
204
- body=body)
205
-
206
- return response
121
+ resp = await self._async_make_request("POST", url, body_s)
122
+ return resp.json().get("elements", "No linked projects found")
207
123
 
208
124
  def get_linked_projects(
209
125
  self,
210
126
  parent_guid: str,
211
- filter_string: str = None,
212
- classification_names: list[str] = None,
213
- body: dict | FilterRequestBody = None,
214
- start_from: int = 0, page_size: int = None,
215
- output_format: str = "json", output_format_set: str | dict = None,
127
+ project_status: str = None,
128
+ effective_time: str = None,
129
+ start_from: int = 0,
130
+ page_size: int = None,
216
131
  ) -> list | str:
217
- loop = asyncio.get_event_loop()
218
- resp = loop.run_until_complete(
219
- self._async_get_linked_projects(parent_guid, filter_string, classification_names,
220
- body, start_from,page_size,output_format, output_format_set)
221
- )
132
+ """Returns the list of projects that are linked off of the supplied element. Any relationship will do.
133
+ The request body is optional, but if supplied acts as a filter on project status.
222
134
 
223
- return resp
135
+ Parameters
136
+ ----------
137
+ parent_guid: str
138
+ The identity of the parent to find linked projects from
139
+ project_status: str, optional
140
+ Optionally, filter results by project status.
141
+ effective_time: str, optional
142
+ Time at which to query for projects. Time format is "YYYY-MM-DDTHH:MM:SS" (ISO 8601).
224
143
 
144
+ start_from: int, [default=0], optional
145
+ When multiple pages of results are available, the page number to start from.
146
+ page_size: int, [default=None]
147
+ The number of items to return in a single page. If not specified, the default will be taken from
148
+ the class instance.
149
+ Returns
150
+ -------
151
+ List | str
225
152
 
153
+ A list of projects linked off of the supplied element filtered by project status and effective time.
226
154
 
155
+ Raises
156
+ ------
227
157
 
158
+ InvalidParameterException
159
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
160
+ PropertyServerException
161
+ Raised by the server when an issue arises in processing a valid request
162
+ NotAuthorizedException
163
+ The principle specified by the user_id does not have authorization for the requested action
228
164
 
165
+ """
166
+ loop = asyncio.get_event_loop()
167
+ resp = loop.run_until_complete(
168
+ self._async_get_linked_projects(
169
+ parent_guid,
170
+ project_status,
171
+ effective_time,
172
+ start_from,
173
+ page_size,
174
+ )
175
+ )
176
+ return resp
229
177
 
230
178
  async def _async_get_classified_projects(
231
179
  self,
232
180
  project_classification: str,
233
- classification_names: list[str] = None,
234
- body: dict | FilterRequestBody = None,
235
- start_from: int = 0, page_size: int = 0,
236
- output_format: str = "json", output_format_set: str | dict = None,
237
-
181
+ effective_time: str = None,
182
+ start_from: int = 0,
183
+ page_size: int = None,
238
184
  ) -> list | str:
239
185
  """Returns the list of projects with a particular classification. The name of the classification is
240
186
  supplied in the request body. Examples of these classifications include StudyProject, PersonalProject,
@@ -270,30 +216,28 @@ class ProjectManager(Client2):
270
216
 
271
217
  """
272
218
 
219
+ if page_size is None:
220
+ page_size = self.page_size
273
221
 
222
+ body = {
223
+ "filter": project_classification,
224
+ "effectiveTime": effective_time,
225
+ }
226
+ body_s = body_slimmer(body)
274
227
  url = (
275
228
  f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/"
276
- f"projects/by-classifications"
229
+ f"projects/by-classifications?startFrom={start_from}&pageSize={page_size}"
277
230
  )
278
- response = await self._async_get_name_request(url, _type="Project",
279
- _gen_output=self._generate_project_output,
280
- filter_string=project_classification,
281
- classification_names=classification_names,
282
- start_from=start_from, page_size=page_size,
283
- output_format=output_format, output_format_set=output_format_set,
284
- body=body)
285
-
286
- return response
287
231
 
232
+ resp = await self._async_make_request("POST", url, body_s)
233
+ return resp.json()
288
234
 
289
235
  def get_classified_projects(
290
236
  self,
291
237
  project_classification: str,
292
- classification_names: list[str] = None,
293
- body: dict | FilterRequestBody = None,
294
- start_from: int = 0, page_size: int = 0,
295
- output_format: str = "json", output_format_set: str | dict = None,
296
-
238
+ effective_time: str = None,
239
+ start_from: int = 0,
240
+ page_size: int = None,
297
241
  ) -> list | str:
298
242
  """Returns the list of projects with a particular classification. The name of the classification is
299
243
  supplied in the request body. Examples of these classifications include StudyProject, PersonalProject,
@@ -332,11 +276,9 @@ class ProjectManager(Client2):
332
276
  resp = loop.run_until_complete(
333
277
  self._async_get_classified_projects(
334
278
  project_classification,
335
- classification_names,
336
- body, start_from,
279
+ effective_time,
280
+ start_from,
337
281
  page_size,
338
- output_format,
339
- output_format_set,
340
282
  )
341
283
  )
342
284
  return resp
@@ -345,10 +287,9 @@ class ProjectManager(Client2):
345
287
  self,
346
288
  project_guid: str,
347
289
  team_role: str = None,
348
- classification_names: list[str] = None,
349
- body: dict | FilterRequestBody = None,
350
- start_from: int = 0, page_size: int = None,
351
- output_format: str = "json", output_format_set: str | dict = None,
290
+ effective_time: str = None,
291
+ start_from: int = 0,
292
+ page_size: int = None,
352
293
  ) -> list | str:
353
294
  """Returns the list of actors that are linked off of the project. This includes the project managers.
354
295
  The optional request body allows a teamRole to be specified as a filter. To filter out the project managers,
@@ -387,29 +328,28 @@ class ProjectManager(Client2):
387
328
  -----
388
329
  """
389
330
 
331
+ if page_size is None:
332
+ page_size = self.page_size
390
333
 
334
+ body = {effective_time: effective_time, "filter": team_role}
335
+ body_s = body_slimmer(body)
391
336
  url = (
392
337
  f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/projects/"
393
- f"{project_guid}/team"
338
+ f"{project_guid}/team?startFrom={start_from}&pageSize={page_size}"
394
339
  )
395
- response = await self._async_get_name_request(url, _type="Project",
396
- _gen_output=self._generate_project_output,
397
- filter_string=team_role,
398
- classification_names=classification_names,
399
- start_from=start_from, page_size=page_size,
400
- output_format=output_format, output_format_set=output_format_set,
401
- body=body)
402
340
 
403
- return response
341
+ resp = await self._async_make_request("POST", url, body_s)
342
+
343
+ result = resp.json().get("elements", NO_ELEMENTS_FOUND)
344
+ return result
404
345
 
405
346
  def get_project_team(
406
347
  self,
407
348
  project_guid: str,
408
349
  team_role: str = None,
409
- classification_names: list[str] = None,
410
- body: dict | FilterRequestBody = None,
411
- start_from: int = 0, page_size: int = None,
412
- output_format: str = "json", output_format_set: str | dict = None,
350
+ effective_time: str = None,
351
+ start_from: int = 0,
352
+ page_size: int = None,
413
353
  ) -> list | str:
414
354
  """Returns the list of actors that are linked off of the project. This includes the project managers.
415
355
  The optional request body allows a teamRole to be specified as a filter. To filter out the project managers,
@@ -452,11 +392,9 @@ class ProjectManager(Client2):
452
392
  self._async_get_project_team(
453
393
  project_guid,
454
394
  team_role,
455
- classification_names,
456
- body, start_from,
395
+ effective_time,
396
+ start_from,
457
397
  page_size,
458
- output_format,
459
- output_format_set,
460
398
  )
461
399
  )
462
400
  return resp
@@ -611,8 +549,8 @@ class ProjectManager(Client2):
611
549
  output_format_set: str | dict = None) -> list | str:
612
550
  url = f"{self.project_command_base}/by-name"
613
551
 
614
- response = await self._async_get_name_request(url, _type="Project",
615
- _gen_output=self._generate_project_output,
552
+ response = await self._async_get_name_request(url, _type="Projects",
553
+ _gen_output=self._generate_projects_output,
616
554
  filter_string=filter_string,
617
555
  classification_names=classification_names,
618
556
  start_from=start_from, page_size=page_size,
@@ -652,34 +590,35 @@ class ProjectManager(Client2):
652
590
 
653
591
  Parameters
654
592
  ----------
655
- project_guid: str
656
- Unique identifier of the project to retrieve.
657
- element_type: str, optional, default = None
658
- Metadata element type name to guide output formatting (defaults to "Project").
593
+ project_guid: str,
594
+ unique identifier of the collection.
595
+ element_type: str, default = None, optional
596
+ type of collection - Collection, DataSpec, Agreement, etc.
659
597
  body: dict | GetRequestBody, optional, default = None
660
- Full request body for advanced options (effective time, lineage, etc.).
661
- output_format: str, optional, default = "JSON"
662
- One of "DICT", "LIST", "MD", "FORM", "REPORT", "MERMAID" or "JSON".
598
+ full request body.
599
+ output_format: str, default = "JSON"
600
+ - one of "DICT", "MERMAID" or "JSON"
663
601
  output_format_set: str | dict, optional, default = None
664
- The desired output columns/fields definition or a label referring to a predefined set.
602
+ The desired output columns/fields to include.
665
603
 
666
604
  Returns
667
605
  -------
668
606
  dict | str
669
- JSON dict representing the specified project when output_format == "JSON";
670
- otherwise a formatted string (or list) according to output_format.
607
+
608
+ A JSON dict representing the specified collection. Returns a string if none found.
671
609
 
672
610
  Raises
673
611
  ------
612
+
674
613
  InvalidParameterException
675
- If the client passes incorrect parameters on the request (bad URLs/values)
614
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
676
615
  PropertyServerException
677
- Raised by the server when an issue arises in processing a valid request
616
+ Raised by the server when an issue arises in processing a valid request
678
617
  NotAuthorizedException
679
- The requesting user is not authorized to issue this request
618
+ The principle specified by the user_id does not have authorization for the requested action
680
619
 
681
620
  Notes
682
- -----
621
+ ----
683
622
  Body sample:
684
623
  {
685
624
  "class": "GetRequestBody",
@@ -692,10 +631,10 @@ class ProjectManager(Client2):
692
631
 
693
632
  url = (f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/projects/"
694
633
  f"{project_guid}")
695
- type = element_type if element_type else "Project"
634
+ type = element_type if element_type else "Collection"
696
635
 
697
636
  response = await self._async_get_guid_request(url, _type=type,
698
- _gen_output=self._generate_project_output,
637
+ _gen_output=self._generate_collection_output,
699
638
  output_format=output_format, output_format_set=output_format_set,
700
639
  body=body)
701
640
 
@@ -710,34 +649,35 @@ class ProjectManager(Client2):
710
649
 
711
650
  Parameters
712
651
  ----------
713
- project_guid: str
714
- Unique identifier of the project to retrieve.
715
- element_type: str, optional, default = None
716
- Metadata element type name to guide output formatting (defaults to "Project").
652
+ project_guid: str,
653
+ unique identifier of the collection.
654
+ element_type: str, default = None, optional
655
+ type of collection - Collection, DataSpec, Agreement, etc.
717
656
  body: dict | GetRequestBody, optional, default = None
718
- Full request body for advanced options (effective time, lineage, etc.).
719
- output_format: str, optional, default = "JSON"
720
- One of "DICT", "LIST", "MD", "FORM", "REPORT", "MERMAID" or "JSON".
657
+ full request body.
658
+ output_format: str, default = "JSON"
659
+ - one of "DICT", "MERMAID" or "JSON"
721
660
  output_format_set: str | dict, optional, default = None
722
- The desired output columns/fields definition or a label referring to a predefined set.
661
+ The desired output columns/fields to include.
723
662
 
724
663
  Returns
725
664
  -------
726
665
  dict | str
727
- JSON dict representing the specified project when output_format == "JSON";
728
- otherwise a formatted string (or list) according to output_format.
666
+
667
+ A JSON dict representing the specified collection. Returns a string if none found.
729
668
 
730
669
  Raises
731
670
  ------
671
+
732
672
  InvalidParameterException
733
- If the client passes incorrect parameters on the request (bad URLs/values)
673
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
734
674
  PropertyServerException
735
- Raised by the server when an issue arises in processing a valid request
675
+ Raised by the server when an issue arises in processing a valid request
736
676
  NotAuthorizedException
737
- The requesting user is not authorized to issue this request
677
+ The principle specified by the user_id does not have authorization for the requested action
738
678
 
739
679
  Notes
740
- -----
680
+ ----
741
681
  Body sample:
742
682
  {
743
683
  "class": "GetRequestBody",
@@ -763,35 +703,29 @@ class ProjectManager(Client2):
763
703
  output_format: str = 'JSON',
764
704
  output_format_set: str | dict = None,
765
705
  ) -> dict | str:
766
- """Return the mermaid graph or formatted details of a specific project. Async version.
706
+ """Return the mermaid graph of a specific project. Async version.
767
707
 
768
708
  Parameters
769
709
  ----------
770
- project_guid: str
771
- Unique identifier of the project.
772
- element_type: str, optional, default = None
773
- Metadata element type name to guide output formatting (defaults to "Project").
710
+ project_guid: str,
711
+ unique identifier of the project.
774
712
  body: dict | GetRequestBody, optional, default = None
775
- Full request body for advanced options (effective time, lineage, etc.).
776
- output_format: str, optional, default = "JSON"
777
- One of "DICT", "LIST", "MD", "FORM", "REPORT", "MERMAID" or "JSON".
778
- output_format_set: str | dict, optional, default = None
779
- The desired output columns/fields definition or a label referring to a predefined set.
713
+ full request body.
780
714
 
781
715
  Returns
782
716
  -------
783
- dict | str
784
- JSON dict when output_format == "JSON"; otherwise a formatted string according to output_format
785
- (for example, a Mermaid markdown string when output_format == "MERMAID").
717
+ str
786
718
 
719
+ A mermaid markdown string representing the graph of the project.
787
720
  Raises
788
721
  ------
722
+
789
723
  InvalidParameterException
790
- If the client passes incorrect parameters on the request (bad URLs/values)
724
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
791
725
  PropertyServerException
792
- Raised by the server when an issue arises in processing a valid request
726
+ Raised by the server when an issue arises in processing a valid request
793
727
  NotAuthorizedException
794
- The requesting user is not authorized to issue this request
728
+ The principle specified by the user_id does not have authorization for the requested action
795
729
 
796
730
  """
797
731
 
@@ -799,7 +733,7 @@ class ProjectManager(Client2):
799
733
  url = (f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/pr"
800
734
  f"ojects/{project_guid}/graph")
801
735
 
802
- response = await self._async_get_guid_request(url, _type=element_type or 'Project',
736
+ response = await self._async_get_guid_request(url, _type=element_type,
803
737
  _gen_output=self._generate_project_output,
804
738
  output_format=output_format, output_format_set=output_format_set,
805
739
  body=body)
@@ -815,35 +749,29 @@ class ProjectManager(Client2):
815
749
  output_format: str = 'JSON',
816
750
  output_format_set: str | dict = None,
817
751
  ) -> dict | str:
818
- """Return the mermaid graph or formatted details of a specific project.
752
+ """Return the mermaid graph of a specific project. Async version.
819
753
 
820
754
  Parameters
821
755
  ----------
822
- project_guid: str
823
- Unique identifier of the project.
824
- element_type: str, optional, default = None
825
- Metadata element type name to guide output formatting (defaults to "Project").
756
+ project_guid: str,
757
+ unique identifier of the project.
826
758
  body: dict | GetRequestBody, optional, default = None
827
- Full request body for advanced options (effective time, lineage, etc.).
828
- output_format: str, optional, default = "JSON"
829
- One of "DICT", "LIST", "MD", "FORM", "REPORT", "MERMAID" or "JSON".
830
- output_format_set: str | dict, optional, default = None
831
- The desired output columns/fields definition or a label referring to a predefined set.
759
+ full request body.
832
760
 
833
761
  Returns
834
762
  -------
835
- dict | str
836
- JSON dict when output_format == "JSON"; otherwise a formatted string according to output_format
837
- (for example, a Mermaid markdown string when output_format == "MERMAID").
763
+ str
838
764
 
765
+ A mermaid markdown string representing the graph of the project.
839
766
  Raises
840
767
  ------
768
+
841
769
  InvalidParameterException
842
- If the client passes incorrect parameters on the request (bad URLs/values)
770
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
843
771
  PropertyServerException
844
- Raised by the server when an issue arises in processing a valid request
772
+ Raised by the server when an issue arises in processing a valid request
845
773
  NotAuthorizedException
846
- The requesting user is not authorized to issue this request
774
+ The principle specified by the user_id does not have authorization for the requested action
847
775
 
848
776
  """
849
777
  loop = asyncio.get_event_loop()
@@ -927,14 +855,13 @@ class ProjectManager(Client2):
927
855
  """Create project: https://egeria-project.org/concepts/project
928
856
 
929
857
  Parameters
930
- ----------
931
- body: dict | NewElementRequestBody
932
- A dict or NewElementRequestBody representing the details of the project to create.
858
+ ----------.
859
+ body: dict
860
+ A dict representing the details of the project to create.
933
861
 
934
862
  Returns
935
863
  -------
936
- str
937
- The GUID of the created project.
864
+ str - the guid of the created collection
938
865
 
939
866
  Raises
940
867
  ------
@@ -1098,7 +1025,6 @@ class ProjectManager(Client2):
1098
1025
  resp = loop.run_until_complete(self._async_create_project_from_template(body))
1099
1026
  return resp
1100
1027
 
1101
-
1102
1028
  #
1103
1029
  #
1104
1030
  #
@@ -1106,20 +1032,47 @@ class ProjectManager(Client2):
1106
1032
  async def _async_update_project(
1107
1033
  self,
1108
1034
  project_guid: str,
1109
- body: dict | UpdateElementRequestBody,
1035
+ qualified_name: str = None,
1036
+ identifier: str = None,
1037
+ display_name: str = None,
1038
+ description: str = None,
1039
+ project_status: str = None,
1040
+ project_phase: str = None,
1041
+ project_health: str = None,
1042
+ start_date: str = None,
1043
+ planned_end_date: str = None,
1044
+ replace_all_props: bool = False,
1110
1045
  ) -> None:
1111
- """Update the properties of a project. Async version.
1046
+ """Update the properties of a project. Async Version.
1112
1047
 
1113
1048
  Parameters
1114
1049
  ----------
1115
1050
  project_guid: str
1116
- Unique identifier of the project to update.
1117
- body: dict | UpdateElementRequestBody
1118
- The update payload specifying properties to change.
1051
+ Unique identifier for the project.
1052
+ qualified_name: str, optional, defaults to None
1053
+ The unique identifier of the project.
1054
+ identifier: str
1055
+ A project identifier.
1056
+ display_name: str
1057
+ The display name of the element. Will also be used as the basis of the qualified_name.
1058
+ description: str
1059
+ A description of the collection.
1060
+ project_status: str, optional
1061
+ The project status
1062
+ project_phase: str, optional
1063
+ Project phase as defined in valid values
1064
+ project_health: str, optional
1065
+ Project health as defined in valid values
1066
+ start_date: str, optional, defaults to None
1067
+ Start date of the project in ISO 8601 string format.
1068
+ planned_end_date: str, optional, defaults to None
1069
+ Planned completion date in ISO 8601 string format.
1070
+ replace_all_props: bool, optional, defaults to False
1071
+ If True, then all the properties of the project will be replaced with the specified properties.
1119
1072
 
1120
1073
  Returns
1121
1074
  -------
1122
- None
1075
+ str - the guid of the created project task
1123
1076
 
1124
1077
  Raises
1125
1078
  ------
@@ -1131,28 +1084,72 @@ class ProjectManager(Client2):
1131
1084
  The principle specified by the user_id does not have authorization for the requested action
1132
1085
  """
1133
1086
 
1087
+ replace_all_props_s = str(replace_all_props).lower()
1134
1088
  url = (
1135
- f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/projects/{project_guid}/update"
1089
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/projects/{project_guid}/"
1090
+ f"update?replaceAllProperties={replace_all_props_s}"
1136
1091
  )
1137
1092
 
1138
- await self._async_update_element_body_request(url, PROJECT_PROPERTIES_LIST, body)
1093
+ body = {
1094
+ "class": "ProjectProperties",
1095
+ "qualifiedName": qualified_name,
1096
+ "identifier": identifier,
1097
+ "name": display_name,
1098
+ "description": description,
1099
+ "projectStatus": project_status,
1100
+ "projectPhase": project_phase,
1101
+ "projectHealth": project_health,
1102
+ "startDate": start_date,
1103
+ "plannedEndDate": planned_end_date,
1104
+ }
1105
+ body_s = body_slimmer(body)
1106
+ await self._async_make_request("POST", url, body_s)
1107
+ return
1139
1108
 
1140
1109
  def update_project(
1141
1110
  self,
1142
1111
  project_guid: str,
1143
- body: dict | UpdateElementRequestBody ) -> None:
1112
+ qualified_name: str = None,
1113
+ identifier: str = None,
1114
+ display_name: str = None,
1115
+ description: str = None,
1116
+ project_status: str = None,
1117
+ project_phase: str = None,
1118
+ project_health: str = None,
1119
+ start_date: str = None,
1120
+ planned_end_date: str = None,
1121
+ replace_all_props: bool = False,
1122
+ ) -> None:
1144
1123
  """Update the properties of a project.
1145
1124
 
1146
1125
  Parameters
1147
1126
  ----------
1148
1127
  project_guid: str
1149
- Unique identifier of the project to update.
1150
- body: dict | UpdateElementRequestBody
1151
- The update payload specifying properties to change.
1128
+ Unique identifier for the project.
1129
+ qualified_name: str, optional, defaults to None
1130
+ The unique identifier of the project.
1131
+ identifier: str
1132
+ A project identifier.
1133
+ display_name: str
1134
+ The display name of the element. Will also be used as the basis of the qualified_name.
1135
+ description: str
1136
+ A description of the collection.
1137
+ project_status: str, optional
1138
+ The project status
1139
+ project_phase: str, optional
1140
+ Project phase as defined in valid values
1141
+ project_health: str, optional
1142
+ Project health as defined in valid values
1143
+ start_date: str, optional, defaults to None
1144
+ Start date of the project in ISO 8601 string format.
1145
+ planned_end_date: str, optional, defaults to None
1146
+ Planned completion date in ISO 8601 string format.
1147
+ replace_all_props: bool, optional, defaults to False
1148
+ If True, then all the properties of the project will be replaced with the specified properties.
1152
1149
 
1153
1150
  Returns
1154
1151
  -------
1155
- None
1152
+ str - the guid of the created project task
1156
1153
 
1157
1154
  Raises
1158
1155
  ------
@@ -1167,30 +1164,36 @@ class ProjectManager(Client2):
1167
1164
  loop.run_until_complete(
1168
1165
  self._async_update_project(
1169
1166
  project_guid,
1170
- body
1167
+ qualified_name,
1168
+ identifier,
1169
+ display_name,
1170
+ description,
1171
+ project_status,
1172
+ project_phase,
1173
+ project_health,
1174
+ start_date,
1175
+ planned_end_date,
1176
+ replace_all_props,
1171
1177
  )
1172
1178
  )
1173
1179
  return
1174
1180
 
1175
1181
  async def _async_delete_project(
1176
1182
  self,
1177
- project_guid: str, cascade_delete: bool = False,
1178
- body: dict | DeleteRequestBody = None
1183
+ project_guid: str, cascade: bool = False
1179
1184
  ) -> None:
1180
- """Delete a project. Async version.
1185
+ """Delete a project. It is detected from all parent elements. Async version
1181
1186
 
1182
1187
  Parameters
1183
1188
  ----------
1184
1189
  project_guid: str
1185
- The GUID of the project to delete.
1186
- cascade_delete: bool, optional, default = False
1187
- If True, then all anchored elements will be deleted.
1188
- body: dict | DeleteRequestBody, optional, default = None
1189
- Request body for additional options.
1190
+ The guid of the project to update.
1191
+ cascade: bool, optional, defaults to False
1192
+ If true, then all anchored elements will be deleted.
1190
1193
 
1191
1194
  Returns
1192
1195
  -------
1193
- None
1196
+ Nothing
1194
1197
 
1195
1198
  Raises
1196
1199
  ------
@@ -1202,33 +1205,36 @@ class ProjectManager(Client2):
1202
1205
  The principle specified by the user_id does not have authorization for the requested action
1203
1206
 
1204
1207
  """
1205
-
1208
+ cascade_s = str(cascade).lower()
1206
1209
  url = (
1207
1210
  f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/projects/"
1208
- f"{project_guid}/delete"
1211
+ f"{project_guid}/delete?cascadedDelete={cascade_s}"
1209
1212
  )
1210
- await self._async_delete_request(url, body, cascade_delete)
1211
- logger.info(f"Deleted project {project_guid} with cascade {cascade_delete}")
1213
+
1214
+ body = {"class": "NullRequestBody"}
1215
+
1216
+ await self._async_make_request("POST", url, body)
1217
+ return
1212
1218
 
1213
1219
  def delete_project(
1214
1220
  self,
1215
- project_guid: str, cascade_delete: bool = False,
1216
- body: dict |DeleteRequestBody = None
1221
+ project_guid: str, cascade: bool = False
1217
1222
  ) -> None:
1218
- """Delete a project.
1223
+ """Delete a project. It is detected from all parent elements.
1219
1224
 
1220
1225
  Parameters
1221
1226
  ----------
1222
1227
  project_guid: str
1223
- The GUID of the project to delete.
1224
- cascade_delete: bool, optional, default = False
1225
- If True, then all anchored elements will be deleted.
1226
- body: dict | DeleteRequestBody, optional, default = None
1227
- Request body for additional options.
1228
+ The guid of the collection to update.
1229
+ cascade: bool, optional, defaults to False
1230
+ If true, then all anchored elements will be deleted.
1231
+
1228
1232
 
1233
+ cascade: bool, optional, defaults to False
1234
+ If true, then all anchored elements will be deleted.
1229
1235
  Returns
1230
1236
  -------
1231
- None
1237
+ Nothing
1232
1238
 
1233
1239
  Raises
1234
1240
  ------
@@ -1242,25 +1248,32 @@ class ProjectManager(Client2):
1242
1248
 
1243
1249
  """
1244
1250
  loop = asyncio.get_event_loop()
1245
- loop.run_until_complete(self._async_delete_project(project_guid, cascade_delete, body))
1246
-
1251
+ loop.run_until_complete(self._async_delete_project(project_guid, cascade))
1252
+ return
1247
1253
 
1248
1254
  async def _async_add_to_project_team(
1249
1255
  self,
1250
1256
  project_guid: str,
1251
1257
  actor_guid: str,
1252
- body: dict | NewRelationshipRequestBody = None,
1258
+ team_role: str = None,
1259
+ effective_from: str = None,
1260
+ effective_to: str = None,
1253
1261
  ) -> None:
1254
- """Add an actor to a project. Async version.
1262
+ """Add an actor to a project. The request body is optional. If supplied, it contains the name of the role that
1263
+ the actor plays in the project. Async version.
1255
1264
 
1256
1265
  Parameters
1257
1266
  ----------
1258
1267
  project_guid: str
1259
- Identity of the project to update.
1268
+ identity of the project to update.
1260
1269
  actor_guid: str
1261
- Identity of the actor to add.
1262
- body: dict | NewRelationshipRequestBody, optional, default = None
1263
- Optional relationship properties (for example, role name, effective times).
1270
+ identity of the actor to add.
1271
+ team_role: str, optional, defaults to None
1272
+ Name of the role the actor plays in the project.
1273
+ effective_from: str, optional, defaults to None
1274
+ Date at which the actor becomes active in the project. Date format is ISO 8601 string format.
1275
+ effective_to: str, optional, defaults to None
1276
+ Date at which the actor is no longer active in the project. Date format is ISO 8601 string format.
1264
1277
 
1265
1278
  Returns
1266
1279
  -------
@@ -1282,25 +1295,42 @@ class ProjectManager(Client2):
1282
1295
  f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/projects/{project_guid}/"
1283
1296
  f"members/{actor_guid}/attach"
1284
1297
  )
1285
- await self._async_new_relationship_request(url, "AssignmentScopeProperties", body)
1286
- logger.info(f"Added actor {actor_guid} to project {project_guid}")
1298
+ body = {
1299
+ "class": "ProjectTeamProperties",
1300
+ "teamRole": team_role,
1301
+ "effectiveFrom": effective_from,
1302
+ "effectiveTo": effective_to,
1303
+ }
1304
+ body_s = body_slimmer(body)
1305
+ if body_s is None:
1306
+ await self._async_make_request("POST", url)
1307
+ else:
1308
+ await self._async_make_request("POST", url, body_s)
1309
+ return
1287
1310
 
1288
1311
  def add_to_project_team(
1289
1312
  self,
1290
1313
  project_guid: str,
1291
1314
  actor_guid: str,
1292
- body: dict | NewRelationshipRequestBody = None,
1315
+ team_role: str = None,
1316
+ effective_from: str = None,
1317
+ effective_to: str = None,
1293
1318
  ) -> None:
1294
- """Add an actor to a project.
1319
+ """Add an actor to a project. The request body is optional. If supplied, it contains the name of the role that
1320
+ the actor plays in the project.
1295
1321
 
1296
1322
  Parameters
1297
1323
  ----------
1298
1324
  project_guid: str
1299
- Identity of the project to update.
1325
+ identity of the project to update.
1300
1326
  actor_guid: str
1301
- Identity of the actor to add.
1302
- body: dict | NewRelationshipRequestBody, optional, default = None
1303
- Optional relationship properties (for example, role name, effective times).
1327
+ identity of the actor to add.
1328
+ team_role: str, optional, defaults to None
1329
+ Name of the role the actor plays in the project.
1330
+ effective_from: str, optional, defaults to None
1331
+ Date at which the actor becomes active in the project. Date format is ISO 8601 string format.
1332
+ effective_to: str, optional, defaults to None
1333
+ Date at which the actor is no longer active in the project. Date format is ISO 8601 string format.
1304
1334
 
1305
1335
  Returns
1306
1336
  -------
@@ -1322,30 +1352,26 @@ class ProjectManager(Client2):
1322
1352
  self._async_add_to_project_team(
1323
1353
  project_guid,
1324
1354
  actor_guid,
1325
- body
1355
+ team_role,
1356
+ effective_from,
1357
+ effective_to,
1326
1358
  )
1327
1359
  )
1328
-
1360
+ return
1329
1361
 
1330
1362
  async def _async_remove_from_project_team(
1331
1363
  self,
1332
1364
  project_guid: str,
1333
1365
  actor_guid: str,
1334
- body: dict | DeleteRequestBody = None,
1335
- cascade_delete: bool = False,
1336
1366
  ) -> None:
1337
1367
  """Remove an actor from a project. Async version.
1338
1368
 
1339
1369
  Parameters
1340
1370
  ----------
1341
1371
  project_guid: str
1342
- Identity of the project to remove members from.
1372
+ identity of the project to remove members from.
1343
1373
  actor_guid: str
1344
- Identity of the actor to remove.
1345
- body: dict | DeleteRequestBody, optional, default = None
1346
- Optional relationship properties.
1347
- cascade_delete: bool, optional, default = False
1348
- If True, deletes related anchored elements as applicable.
1374
+ identity of the actor to remove.
1349
1375
 
1350
1376
  Returns
1351
1377
  -------
@@ -1367,106 +1393,24 @@ class ProjectManager(Client2):
1367
1393
  f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/projects/{project_guid}/"
1368
1394
  f"members/{actor_guid}/detach"
1369
1395
  )
1370
- await self._async_delete_request(url, body, cascade_delete)
1371
- logger.info(f"Removed actor {actor_guid} from project {project_guid}")
1372
1396
 
1397
+ body = {"class": "NullRequestBody"}
1398
+ await self._async_make_request("POST", url, body)
1399
+ return
1373
1400
 
1374
1401
  def remove_from_project_team(
1375
1402
  self,
1376
1403
  project_guid: str,
1377
1404
  actor_guid: str,
1378
- body: dict | DeleteRequestBody = None,
1379
- cascade_delete: bool = False,
1380
1405
  ) -> None:
1381
1406
  """Remove an actor from a project.
1382
1407
 
1383
1408
  Parameters
1384
1409
  ----------
1385
1410
  project_guid: str
1386
- Identity of the project.
1411
+ identity of the project.
1387
1412
  actor_guid: str
1388
- Identity of the actor to remove.
1389
- body: dict | DeleteRequestBody, optional, default = None
1390
- Optional relationship properties.
1391
- cascade_delete: bool, optional, default = False
1392
- If True, deletes related anchored elements as applicable.
1393
-
1394
- Returns
1395
- -------
1396
- None
1397
-
1398
- Raises
1399
- ------
1400
-
1401
- InvalidParameterException
1402
- If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1403
- PropertyServerException
1404
- Raised by the server when an issue arises in processing a valid request
1405
- NotAuthorizedException
1406
- The principle specified by the user_id does not have authorization for the requested action
1407
-
1408
- """
1409
- loop = asyncio.get_event_loop()
1410
- loop.run_until_complete(
1411
- self._async_remove_from_project_team(project_guid, actor_guid, body, cascade_delete)
1412
- )
1413
-
1414
-
1415
- async def _async_setup_project_dependency(
1416
- self,
1417
- project_guid: str,
1418
- depends_on_project_guid: str,
1419
- body: dict | NewRelationshipRequestBody = None,
1420
- ) -> None:
1421
- """Create a project dependency link from one project to another. Async version.
1422
-
1423
- Parameters
1424
- ----------
1425
- project_guid: str
1426
- Identity of the project that has the dependency.
1427
- depends_on_project_guid: str
1428
- GUID of the project that the first project depends on.
1429
-
1430
-
1431
- Returns
1432
- -------
1433
- None
1434
-
1435
- Raises
1436
- ------
1437
-
1438
- InvalidParameterException
1439
- If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1440
- PropertyServerException
1441
- Raised by the server when an issue arises in processing a valid request
1442
- NotAuthorizedException
1443
- The principle specified by the user_id does not have authorization for the requested action
1444
-
1445
- """
1446
-
1447
- url = (
1448
- f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/projects/{project_guid}/"
1449
- f"project-dependencies/{depends_on_project_guid}/attach"
1450
- )
1451
- await self._async_new_relationship_request(url, "ProjectDependencyProperties", body)
1452
- logger.info(f"Added dependency between project {project_guid} depending on project {depends_on_project_guid}")
1453
-
1454
-
1455
- def setup_project_dependency(
1456
- self,
1457
- project_guid: str,
1458
- depends_on_project_guid: str,
1459
- body: dict | NewRelationshipRequestBody = None,
1460
- ) -> None:
1461
- """Create a project dependency link from one project to another.
1462
-
1463
- Parameters
1464
- ----------
1465
- project_guid: str
1466
- Identity of the project that has the dependency.
1467
- depends_on_project_guid: str
1468
- GUID of the project that the first project depends on.
1469
-
1413
+ identity of the actor to remove.
1470
1414
 
1471
1415
  Returns
1472
1416
  -------
@@ -1485,25 +1429,24 @@ class ProjectManager(Client2):
1485
1429
  """
1486
1430
  loop = asyncio.get_event_loop()
1487
1431
  loop.run_until_complete(
1488
- self._async_setup_project_dependency( project_guid, depends_on_project_guid, body)
1432
+ self._async_remove_from_project_team(project_guid, actor_guid)
1489
1433
  )
1490
1434
  return
1491
1435
 
1492
- async def _async_clear_project_dependency(
1436
+ async def _async_setup_project_management_role(
1493
1437
  self,
1494
1438
  project_guid: str,
1495
- depends_on_project_guid: str,
1496
- body: dict | DeleteRequestBody = None,
1497
- cascade_delete: bool = False
1439
+ project_role_guid: str,
1498
1440
  ) -> None:
1499
- """Remove a project dependency link between two projects. Async version.
1441
+ """Create a ProjectManagement relationship between a project and a person role to show that anyone appointed to
1442
+ the role is a member of the project. Async version.
1500
1443
 
1501
1444
  Parameters
1502
1445
  ----------
1503
1446
  project_guid: str
1504
- Identity of the project that previously had the dependency.
1505
- depends_on_project_guid: str
1506
- GUID of the project that was depended on.
1447
+ identity of the project.
1448
+ project_role_guid: str
1449
+ guid of the role to assign to the project.
1507
1450
 
1508
1451
 
1509
1452
  Returns
@@ -1524,105 +1467,27 @@ class ProjectManager(Client2):
1524
1467
 
1525
1468
  url = (
1526
1469
  f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/projects/{project_guid}/"
1527
- f"project-dependencies/{depends_on_project_guid}/detach"
1470
+ f"project-management-roles/{project_role_guid}/attach"
1528
1471
  )
1529
- await self._async_delete_request(url, body, cascade_delete)
1530
- logger.info(f"Removed project dependency between project {project_guid} and project {depends_on_project_guid}")
1531
-
1532
-
1533
- def clear_project_dependency(
1534
- self,
1535
- project_guid: str,
1536
- depends_on_project_guid: str,
1537
- body: dict | DeleteRequestBody = None,
1538
- cascade_delete: bool = False
1539
- ) -> None:
1540
- """Clear a project dependency link between two projects.
1541
1472
 
1542
- Parameters
1543
- ----------
1544
- project_guid: str
1545
- Identity of the project that previously had the dependency.
1546
- depends_on_project_guid: str
1547
- GUID of the project that was depended on.
1548
-
1549
-
1550
- Returns
1551
- -------
1552
- None
1553
-
1554
- Raises
1555
- ------
1556
-
1557
- InvalidParameterException
1558
- If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1559
- PropertyServerException
1560
- Raised by the server when an issue arises in processing a valid request
1561
- NotAuthorizedException
1562
- The principle specified by the user_id does not have authorization for the requested action
1563
-
1564
- """
1565
- loop = asyncio.get_event_loop()
1566
- loop.run_until_complete(
1567
- self._async_clear_project_dependency(project_guid, depends_on_project_guid,
1568
- body, cascade_delete)
1569
- )
1473
+ body = {"class": "NullRequestBody"}
1474
+ await self._async_make_request("POST", url, body)
1570
1475
  return
1571
1476
 
1572
- async def _async_setup_project_hierarchy(
1477
+ def setup_project_management_role(
1573
1478
  self,
1574
1479
  project_guid: str,
1575
- managed_project_guid: str,
1576
- body: dict | NewRelationshipRequestBody = None,
1480
+ project_role_guid: str,
1577
1481
  ) -> None:
1578
- """Create a project hierarchy link from a project to a managed (child) project. Async version.
1482
+ """Create a ProjectManagement relationship between a project and a person role to show that anyone appointed to
1483
+ the role is a member of the project. Async version.
1579
1484
 
1580
1485
  Parameters
1581
1486
  ----------
1582
1487
  project_guid: str
1583
- Identity of the parent (managing) project.
1584
- managed_project_guid: str
1585
- GUID of the managed (child) project.
1586
-
1587
-
1588
- Returns
1589
- -------
1590
- None
1591
-
1592
- Raises
1593
- ------
1594
-
1595
- InvalidParameterException
1596
- If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1597
- PropertyServerException
1598
- Raised by the server when an issue arises in processing a valid request
1599
- NotAuthorizedException
1600
- The principle specified by the user_id does not have authorization for the requested action
1601
-
1602
- """
1603
-
1604
- url = (
1605
- f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/projects/{project_guid}/"
1606
- f"project-hierarchies/{managed_project_guid}/attach"
1607
- )
1608
- await self._async_new_relationship_request(url, "ProjectHierarchyProperties", body)
1609
- logger.info(f"Added hierarchy between project {project_guid} abd project {managed_project_guid}")
1610
-
1611
-
1612
- def setup_project_hierarchy(
1613
- self,
1614
- project_guid: str,
1615
- managed_project_guid: str,
1616
- body: dict | NewRelationshipRequestBody = None,
1617
- ) -> None:
1618
- """Create a project hierarchy link from a project to a managed (child) project.
1619
-
1620
- Parameters
1621
- ----------
1622
- project_guid: str
1623
- Identity of the parent (managing) project.
1624
- managed_project_guid: str
1625
- GUID of the managed (child) project.
1488
+ identity of the project.
1489
+ project_role_guid: str
1490
+ guid of the role to assign to the project.
1626
1491
 
1627
1492
 
1628
1493
  Returns
@@ -1642,25 +1507,23 @@ class ProjectManager(Client2):
1642
1507
  """
1643
1508
  loop = asyncio.get_event_loop()
1644
1509
  loop.run_until_complete(
1645
- self._async_setup_project_dependency( project_guid, managed_project_guid, body)
1510
+ self._async_setup_project_management_role(project_guid, project_role_guid)
1646
1511
  )
1647
1512
  return
1648
1513
 
1649
- async def _async_clear_project_hierarchy(
1514
+ async def _async_clear_project_management_role(
1650
1515
  self,
1651
1516
  project_guid: str,
1652
- managed_project_guid: str,
1653
- body: dict | DeleteRequestBody = None,
1654
- cascade_delete: bool = False
1517
+ project_role_guid: str,
1655
1518
  ) -> None:
1656
- """Remove a project hierarchy link between two projects. Async version.
1519
+ """Remove a ProjectManagement relationship between a project and a person role. Async version.
1657
1520
 
1658
1521
  Parameters
1659
1522
  ----------
1660
1523
  project_guid: str
1661
- Identity of the parent (managing) project.
1662
- managed_project_guid: str
1663
- GUID of the managed (child) project.
1524
+ identity of the project.
1525
+ project_role_guid: str
1526
+ guid of the role to assign to the project.
1664
1527
 
1665
1528
 
1666
1529
  Returns
@@ -1681,27 +1544,26 @@ class ProjectManager(Client2):
1681
1544
 
1682
1545
  url = (
1683
1546
  f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/projects/{project_guid}/"
1684
- f"project-hierarchies/{managed_project_guid}/detach"
1547
+ f"project-management-roles/{project_role_guid}/detach"
1685
1548
  )
1686
- await self._async_delete_request(url, body, cascade_delete)
1687
- logger.info(f"Removed project hierarchy link between project {project_guid} and project {managed_project_guid}")
1688
1549
 
1550
+ body = {"class": "NullRequestBody"}
1551
+ await self._async_make_request("POST", url, body)
1552
+ return
1689
1553
 
1690
- def clear_project_hierarchy(
1554
+ def clear_project_management_role(
1691
1555
  self,
1692
1556
  project_guid: str,
1693
- managed_project_guid: str,
1694
- body: dict | DeleteRequestBody = None,
1695
- cascade_delete: bool = False
1557
+ project_role_guid: str,
1696
1558
  ) -> None:
1697
- """Clear a project hierarchy link between two projects.
1559
+ """Clear a ProjectManagement relationship between a project and a person role.
1698
1560
 
1699
1561
  Parameters
1700
1562
  ----------
1701
1563
  project_guid: str
1702
- Identity of the parent (managing) project.
1703
- managed_project_guid: str
1704
- GUID of the managed (child) project.
1564
+ identity of the project.
1565
+ project_role_guid: str
1566
+ guid of the role to assign to the project.
1705
1567
 
1706
1568
 
1707
1569
  Returns
@@ -1721,23 +1583,10 @@ class ProjectManager(Client2):
1721
1583
  """
1722
1584
  loop = asyncio.get_event_loop()
1723
1585
  loop.run_until_complete(
1724
- self._async_clear_project_hierarchy(project_guid, managed_project_guid,
1725
- body, cascade_delete)
1586
+ self._async_clear_project_management_role(project_guid, project_role_guid)
1726
1587
  )
1727
1588
  return
1728
1589
 
1729
1590
 
1730
1591
  if __name__ == "__main__":
1731
1592
  print("Main-Project Manager")
1732
-
1733
-
1734
- # Automatically apply @dynamic_catch to all methods of ProjectManager (excluding dunder methods)
1735
- try:
1736
- for _name, _attr in list(ProjectManager.__dict__.items()):
1737
- if callable(_attr) and not _name.startswith("__"):
1738
- # Avoid double-wrapping if already decorated
1739
- if not getattr(_attr, "__wrapped__", None):
1740
- setattr(ProjectManager, _name, dynamic_catch(_attr))
1741
- except Exception as _e:
1742
- # Be resilient; if anything goes wrong, leave methods as-is
1743
- logger.debug(f"dynamic_catch auto-wrap skipped due to: {_e}")