pyegeria 5.4.0.24__py3-none-any.whl → 5.4.0.26__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 (50) hide show
  1. commands/cat/debug_log +7373 -1452
  2. commands/cat/dr_egeria_md.py +21 -4
  3. commands/cat/logs/pyegeria.log +4 -0
  4. md_processing/.DS_Store +0 -0
  5. md_processing/__init__.py +7 -3
  6. md_processing/data/commands.json +1683 -2801
  7. md_processing/dr_egeria_inbox/product.md +69 -20
  8. md_processing/dr_egeria_outbox/.obsidian/workspace.json +5 -5
  9. md_processing/dr_egeria_outbox/monday/processed-2025-08-19 07:05-product.md +426 -0
  10. md_processing/dr_egeria_outbox/monday/processed-2025-08-19 07:56-product.md +212 -0
  11. md_processing/dr_egeria_outbox/monday/processed-2025-08-19 09:43-product.md +201 -0
  12. md_processing/dr_egeria_outbox/tuesday/processed-2025-08-19 10:55-product.md +209 -0
  13. md_processing/md_commands/governance_officer_commands.py +1 -73
  14. md_processing/md_commands/product_manager_commands.py +453 -211
  15. md_processing/md_processing_utils/common_md_proc_utils.py +60 -5
  16. md_processing/md_processing_utils/common_md_utils.py +21 -9
  17. md_processing/md_processing_utils/extraction_utils.py +2 -2
  18. md_processing/md_processing_utils/md_processing_constants.py +8 -7
  19. pyegeria/.DS_Store +0 -0
  20. pyegeria/__init__.py +4 -300
  21. pyegeria/_client_new.py +59 -11
  22. pyegeria/_output_formats.py +43 -0
  23. pyegeria/collection_manager.py +79 -14
  24. pyegeria/{data_designer_omvs.py → data_designer.py} +1171 -1675
  25. pyegeria/egeria_cat_client.py +2 -2
  26. pyegeria/egeria_client.py +4 -4
  27. pyegeria/egeria_tech_client.py +1 -1
  28. pyegeria/glossary_browser.py +1259 -0
  29. pyegeria/{glossary_manager_omvs.py → glossary_manager.py} +1181 -1099
  30. pyegeria/models.py +9 -3
  31. pyegeria/output_formatter.py +2 -1
  32. pyegeria/project_manager.py +1743 -0
  33. pyegeria/solution_architect_omvs.py +1 -1
  34. pyegeria/utils.py +4 -1
  35. {pyegeria-5.4.0.24.dist-info → pyegeria-5.4.0.26.dist-info}/METADATA +1 -1
  36. {pyegeria-5.4.0.24.dist-info → pyegeria-5.4.0.26.dist-info}/RECORD +39 -43
  37. commands/cat/debug_log.2025-08-15_09-14-07_444802.zip +0 -0
  38. commands/cat/debug_log.2025-08-16_10-21-59_388912.zip +0 -0
  39. md_processing/dr_egeria_outbox/monday/processed-2025-07-14 12:38-data_designer_out.md +0 -663
  40. md_processing/dr_egeria_outbox/monday/processed-2025-07-21 10:52-generated_help_report.md +0 -2744
  41. md_processing/dr_egeria_outbox/monday/processed-2025-07-21 18:38-collections.md +0 -62
  42. md_processing/dr_egeria_outbox/monday/processed-2025-08-01 11:34-gov_def.md +0 -444
  43. md_processing/dr_egeria_outbox/monday/processed-2025-08-17 21:04-product.md +0 -97
  44. pyegeria/collection_manager_omvs.py +0 -6541
  45. pyegeria/glossary_browser_omvs.py +0 -3840
  46. pyegeria/governance_officer_omvs.py +0 -2367
  47. pyegeria/project_manager_omvs.py +0 -1933
  48. {pyegeria-5.4.0.24.dist-info → pyegeria-5.4.0.26.dist-info}/LICENSE +0 -0
  49. {pyegeria-5.4.0.24.dist-info → pyegeria-5.4.0.26.dist-info}/WHEEL +0 -0
  50. {pyegeria-5.4.0.24.dist-info → pyegeria-5.4.0.26.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,1743 @@
1
+ """
2
+ PDX-License-Identifier: Apache-2.0
3
+ Copyright Contributors to the ODPi Egeria project.
4
+
5
+ Create, maintain and explore projects.
6
+ https://egeria-project.org/concepts/project
7
+
8
+ """
9
+
10
+ import asyncio
11
+
12
+ from loguru import logger
13
+
14
+ from pyegeria._client_new import Client2
15
+ from pyegeria.load_config import get_app_config
16
+ from pyegeria.models import (SearchStringRequestBody, FilterRequestBody, GetRequestBody, NewElementRequestBody,
17
+ TemplateRequestBody, UpdateElementRequestBody, DeleteRequestBody,
18
+ NewRelationshipRequestBody)
19
+ 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
+
26
+ app_settings = get_app_config()
27
+ EGERIA_LOCAL_QUALIFIER = app_settings.User_Profile.egeria_local_qualifier
28
+ from pyegeria._globals import NO_ELEMENTS_FOUND, NO_PROJECTS_FOUND
29
+
30
+ PROJECT_TYPES = ["Project", "Campaign", "StudyProject", "Task", "PersonalProject"]
31
+ PROJECT_PROPERTIES_LIST = ["ProjectProperties", "CampaignProperties", "StudyProjectProperties", "TaskProperties",
32
+ "PersonalProjectProperties"]
33
+
34
+ class ProjectManager(Client2):
35
+ """
36
+ Create and manage projects. Projects may be organized in a hierarchy.
37
+ See https://egeria-project.org/types/1/0130-Projects
38
+
39
+ Attributes:
40
+
41
+ server_name: str
42
+ The name of the View Server to connect to.
43
+ platform_url : str
44
+ URL of the server platform to connect to
45
+ user_id : str
46
+ The identity of the user calling the method - this sets a default optionally used by the methods
47
+ when the user doesn't pass the user_id on a method call.
48
+ user_pwd: str
49
+ The password associated with the user_id. Defaults to None
50
+ """
51
+
52
+ def __init__(
53
+ self,
54
+ view_server: str,
55
+ platform_url: str,
56
+ user_id: str,
57
+ user_pwd: str = None,
58
+ token: str = None,
59
+ ):
60
+ self.view_server = view_server
61
+ self.platform_url = platform_url
62
+ self.user_id = user_id
63
+ self.user_pwd = user_pwd
64
+ self.project_command_base: str = (
65
+ f"/api/open-metadata/project-manager/projects"
66
+ )
67
+ Client2.__init__(self, view_server, platform_url, user_id, user_pwd, token)
68
+
69
+
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
+ )
146
+ #
147
+ # Retrieving Projects= Information - https://egeria-project.org/concepts/project
148
+ #
149
+ async def _async_get_linked_projects(
150
+ self,
151
+ 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,
157
+ ) -> list | str:
158
+ """Returns the list of projects that are linked off of the supplied element. Any relationship will do.
159
+ The request body is optional, but if supplied acts as a filter on project status. Async version.
160
+
161
+ Parameters
162
+ ----------
163
+ parent_guid: str
164
+ The identity of the parent to find linked projects from.
165
+ project_status: str, optional
166
+ Optionally, filter results by project status.
167
+ effective_time: str, optional
168
+ Time at which to query for projects. Time format is "YYYY-MM-DDTHH:MM:SS" (ISO 8601).
169
+
170
+ start_from: int, [default=0], optional
171
+ When multiple pages of results are available, the page number to start from.
172
+ page_size: int, [default=None]
173
+ The number of items to return in a single page. If not specified, the default will be taken from
174
+ the class instance.
175
+ Returns
176
+ -------
177
+ List | str
178
+
179
+ A list of projects linked off of the supplied element filtered by project status and effective time.
180
+
181
+ Raises
182
+ ------
183
+
184
+ InvalidParameterException
185
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
186
+ PropertyServerException
187
+ Raised by the server when an issue arises in processing a valid request
188
+ NotAuthorizedException
189
+ The principle specified by the user_id does not have authorization for the requested action
190
+
191
+ """
192
+
193
+ url = (
194
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/"
195
+ f"metadata-elements/{parent_guid}/projects"
196
+ )
197
+
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
207
+
208
+ def get_linked_projects(
209
+ self,
210
+ 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,
216
+ ) -> 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
+ )
222
+
223
+ return resp
224
+
225
+
226
+
227
+
228
+
229
+
230
+ async def _async_get_classified_projects(
231
+ self,
232
+ 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
+
238
+ ) -> list | str:
239
+ """Returns the list of projects with a particular classification. The name of the classification is
240
+ supplied in the request body. Examples of these classifications include StudyProject, PersonalProject,
241
+ Campaign or Task. There is also GlossaryProject and GovernanceProject. Async version.
242
+
243
+ Parameters
244
+ ----------
245
+ project_classification: str
246
+ The project classification to search for.
247
+ effective_time: str, optional
248
+ Time at which to query for projects. Time format is "YYYY-MM-DDTHH:MM:SS" (ISO 8601).
249
+
250
+ start_from: int, [default=0], optional
251
+ When multiple pages of results are available, the page number to start from.
252
+ page_size: int, [default=None]
253
+ The number of items to return in a single page. If not specified, the default will be taken from
254
+ the class instance.
255
+ Returns
256
+ -------
257
+ List | str
258
+
259
+ A list of projects filtered by project classification, and effective time.
260
+
261
+ Raises
262
+ ------
263
+
264
+ InvalidParameterException
265
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
266
+ PropertyServerException
267
+ Raised by the server when an issue arises in processing a valid request
268
+ NotAuthorizedException
269
+ The principle specified by the user_id does not have authorization for the requested action
270
+
271
+ """
272
+
273
+
274
+ url = (
275
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/"
276
+ f"projects/by-classifications"
277
+ )
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
+
288
+
289
+ def get_classified_projects(
290
+ self,
291
+ 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
+
297
+ ) -> list | str:
298
+ """Returns the list of projects with a particular classification. The name of the classification is
299
+ supplied in the request body. Examples of these classifications include StudyProject, PersonalProject,
300
+ Campaign or Task. There is also GlossaryProject and GovernanceProject.
301
+
302
+ Parameters
303
+ ----------
304
+ project_classification: str
305
+ The project classification to search for.
306
+ effective_time: str, optional
307
+ Time at which to query for projects. Time format is "YYYY-MM-DDTHH:MM:SS" (ISO 8601).
308
+
309
+ start_from: int, [default=0], optional
310
+ When multiple pages of results are available, the page number to start from.
311
+ page_size: int, [default=None]
312
+ The number of items to return in a single page. If not specified, the default will be taken from
313
+ the class instance.
314
+ Returns
315
+ -------
316
+ List | str
317
+
318
+ A list of projects filtered by project classification, and effective time.
319
+
320
+ Raises
321
+ ------
322
+
323
+ InvalidParameterException
324
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
325
+ PropertyServerException
326
+ Raised by the server when an issue arises in processing a valid request
327
+ NotAuthorizedException
328
+ The principle specified by the user_id does not have authorization for the requested action
329
+
330
+ """
331
+ loop = asyncio.get_event_loop()
332
+ resp = loop.run_until_complete(
333
+ self._async_get_classified_projects(
334
+ project_classification,
335
+ classification_names,
336
+ body, start_from,
337
+ page_size,
338
+ output_format,
339
+ output_format_set,
340
+ )
341
+ )
342
+ return resp
343
+
344
+ async def _async_get_project_team(
345
+ self,
346
+ project_guid: str,
347
+ 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,
352
+ ) -> list | str:
353
+ """Returns the list of actors that are linked off of the project. This includes the project managers.
354
+ The optional request body allows a teamRole to be specified as a filter. To filter out the project managers,
355
+ specify ProjectManagement as the team role. See https://egeria-project.org/concepts/project for details.
356
+ Async version.
357
+
358
+ Parameters
359
+ ----------
360
+ project_guid: str
361
+ The identity of the project to return team information about.
362
+ team_role: str, optional
363
+ team role to filter on. Project managers would be "ProjectManagement".
364
+ effective_time: str, optional
365
+ Time at which to query the team role. Time format is "YYYY-MM-DDTHH:MM:SS" (ISO 8601).
366
+
367
+ start_from: int, [default=0], optional
368
+ When multiple pages of results are available, the page number to start from.
369
+ page_size: int, [default=None]
370
+ The number of items to return in a single page. If not specified, the default will be taken from
371
+ the class instance.
372
+
373
+ Returns
374
+ -------
375
+ list | str
376
+ The list of actors linked off the project, including project managers Returns a string if none found.
377
+
378
+ Raises
379
+ ------
380
+ InvalidParameterException
381
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
382
+ PropertyServerException
383
+ Raised by the server when an issue arises in processing a valid request.
384
+ NotAuthorizedException
385
+ The principle specified by the user_id does not have authorization for the requested action.
386
+ Notes
387
+ -----
388
+ """
389
+
390
+
391
+ url = (
392
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/projects/"
393
+ f"{project_guid}/team"
394
+ )
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
+
403
+ return response
404
+
405
+ def get_project_team(
406
+ self,
407
+ project_guid: str,
408
+ 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,
413
+ ) -> list | str:
414
+ """Returns the list of actors that are linked off of the project. This includes the project managers.
415
+ The optional request body allows a teamRole to be specified as a filter. To filter out the project managers,
416
+ specify ProjectManagement as the team role. See https://egeria-project.org/concepts/project for details.
417
+ Async version.
418
+
419
+ Parameters
420
+ ----------
421
+ project_guid: str
422
+ The identity of the project to return team information about.
423
+ team_role: str, optional
424
+ team role to filter on. Project managers would be "ProjectManagement".
425
+ effective_time: str, optional
426
+ Time at which to query the team role. Time format is "YYYY-MM-DDTHH:MM:SS" (ISO 8601).
427
+
428
+ start_from: int, [default=0], optional
429
+ When multiple pages of results are available, the page number to start from.
430
+ page_size: int, [default=None]
431
+ The number of items to return in a single page. If not specified, the default will be taken from
432
+ the class instance.
433
+
434
+ Returns
435
+ -------
436
+ list | str
437
+ The list of actors linked off the project, including project managers Returns a string if none found.
438
+
439
+ Raises
440
+ ------
441
+ InvalidParameterException
442
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
443
+ PropertyServerException
444
+ Raised by the server when an issue arises in processing a valid request.
445
+ NotAuthorizedException
446
+ The principle specified by the user_id does not have authorization for the requested action.
447
+ Notes
448
+ -----
449
+ """
450
+ loop = asyncio.get_event_loop()
451
+ resp = loop.run_until_complete(
452
+ self._async_get_project_team(
453
+ project_guid,
454
+ team_role,
455
+ classification_names,
456
+ body, start_from,
457
+ page_size,
458
+ output_format,
459
+ output_format_set,
460
+ )
461
+ )
462
+ return resp
463
+
464
+ @dynamic_catch
465
+ async def _async_find_projects(
466
+ self,
467
+ search_string: str, classification_names: list[str] = None, metadata_element_types: list[str] = None,
468
+ starts_with: bool = False,
469
+ ends_with: bool = False,
470
+ ignore_case: bool = False,
471
+ start_from: int = 0,
472
+ page_size: int = 0,
473
+ output_format: str = "json", output_format_set: str | dict = None,
474
+ body: dict | SearchStringRequestBody = None
475
+ ) -> list | str:
476
+ """Returns the list of projects matching the search string.
477
+ The search string is located in the request body and is interpreted as a plain string.
478
+ The request parameters, startsWith, endsWith and ignoreCase can be used to allow a fuzzy search.
479
+ Async version.
480
+
481
+ Parameters
482
+ ----------
483
+ search_string: str,
484
+ Search string to use to find matching projects. If the search string is '*' then all projects returned.
485
+ effective_time: str, [default=None], optional
486
+ Effective time of the query. If not specified will default to any time.
487
+
488
+ starts_with : bool, [default=False], optional
489
+ Starts with the supplied string.
490
+ ends_with : bool, [default=False], optional
491
+ Ends with the supplied string
492
+ ignore_case : bool, [default=False], optional
493
+ Ignore case when searching
494
+ start_from: int, [default=0], optional
495
+ When multiple pages of results are available, the page number to start from.
496
+ page_size: int, [default=None]
497
+ The number of items to return in a single page. If not specified, the default will be taken from
498
+ the class instance.
499
+ Returns
500
+ -------
501
+ List | str
502
+
503
+ A list of projects matching the search string. Returns a string if none found.
504
+
505
+ Raises
506
+ ------
507
+
508
+ InvalidParameterException
509
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
510
+ PropertyServerException
511
+ Raised by the server when an issue arises in processing a valid request
512
+ NotAuthorizedException
513
+ The principle specified by the user_id does not have authorization for the requested action
514
+
515
+ """
516
+
517
+ url = (
518
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/projects/"
519
+ f"by-search-string"
520
+ )
521
+
522
+ response = await self._async_find_request(url, _type="Project",
523
+ _gen_output=self._generate_project_output,
524
+ search_string=search_string,
525
+ classification_names=classification_names,
526
+ metadata_element_types=metadata_element_types,
527
+ starts_with=starts_with, ends_with=ends_with, ignore_case=ignore_case,
528
+ start_from=start_from, page_size=page_size,
529
+ output_format=output_format, output_format_set=output_format_set,
530
+ body=body)
531
+
532
+ return response
533
+
534
+ @dynamic_catch
535
+ def find_projects(
536
+ self,
537
+ search_string: str, classification_names: list[str] = None, metadata_element_types: list[str] = None,
538
+ starts_with: bool = False,
539
+ ends_with: bool = False,
540
+ ignore_case: bool = False,
541
+ start_from: int = 0,
542
+ page_size: int = 0,
543
+ output_format: str = "json", output_format_set: str | dict = None,
544
+ body: dict | SearchStringRequestBody = None
545
+ ) -> list | str:
546
+
547
+ """Returns the list of projects matching the search string.
548
+ The search string is located in the request body and is interpreted as a plain string.
549
+ The request parameters, startsWith, endsWith and ignoreCase can be used to allow a fuzzy search.
550
+
551
+ Parameters
552
+ ----------
553
+ search_string: str,
554
+ Search string to use to find matching projects. If the search string is '*' then all projects returned.
555
+ effective_time: str, [default=None], optional
556
+ Effective time of the query. If not specified will default to any time.
557
+
558
+ starts_with : bool, [default=False], optional
559
+ Starts with the supplied string.
560
+ ends_with : bool, [default=False], optional
561
+ Ends with the supplied string
562
+ ignore_case : bool, [default=False], optional
563
+ Ignore case when searching
564
+ start_from: int, [default=0], optional
565
+ When multiple pages of results are available, the page number to start from.
566
+ page_size: int, [default=None]
567
+ The number of items to return in a single page. If not specified, the default will be taken from
568
+ the class instance.
569
+ Returns
570
+ -------
571
+ List | str
572
+
573
+ A list of projects matching the search string. Returns a string if none found.
574
+
575
+ Raises
576
+ ------
577
+
578
+ InvalidParameterException
579
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
580
+ PropertyServerException
581
+ Raised by the server when an issue arises in processing a valid request
582
+ NotAuthorizedException
583
+ The principle specified by the user_id does not have authorization for the requested action
584
+
585
+ """
586
+ loop = asyncio.get_event_loop()
587
+ resp = loop.run_until_complete(
588
+ self._async_find_projects(
589
+ search_string,
590
+ classification_names,
591
+ metadata_element_types,
592
+ starts_with,
593
+ ends_with,
594
+ ignore_case,
595
+ start_from,
596
+ page_size,
597
+ output_format,
598
+ output_format_set,
599
+ body,
600
+ )
601
+ )
602
+
603
+ return resp
604
+
605
+ @dynamic_catch
606
+ async def _async_get_projects_by_name(
607
+ self, filter_string: str = None, classification_names: list[str] = None,
608
+ body: dict | FilterRequestBody = None,
609
+ start_from: int = 0, page_size: int = 0,
610
+ output_format: str = 'JSON',
611
+ output_format_set: str | dict = None) -> list | str:
612
+ url = f"{self.project_command_base}/by-name"
613
+
614
+ response = await self._async_get_name_request(url, _type="Project",
615
+ _gen_output=self._generate_project_output,
616
+ filter_string=filter_string,
617
+ classification_names=classification_names,
618
+ start_from=start_from, page_size=page_size,
619
+ output_format=output_format, output_format_set=output_format_set,
620
+ body=body)
621
+
622
+ return response
623
+
624
+ @dynamic_catch
625
+ def get_projects_by_name(
626
+ self, filter_string: str = None, classification_names: list[str] = None,
627
+ body: dict | FilterRequestBody = None,
628
+ start_from: int = 0, page_size: int = 0,
629
+ output_format: str = 'JSON',
630
+ output_format_set: str | dict = None) -> list | str:
631
+
632
+ loop = asyncio.get_event_loop()
633
+ resp = loop.run_until_complete(
634
+ self._async_get_projects_by_name(
635
+ filter_string,
636
+ classification_names,
637
+ body,
638
+ start_from,
639
+ page_size,
640
+ output_format,
641
+ output_format_set,
642
+ )
643
+ )
644
+ return resp
645
+
646
+ @dynamic_catch
647
+ async def _async_get_project_by_guid(self, project_guid: str, element_type: str = None,
648
+ body: dict | GetRequestBody = None,
649
+ output_format: str = 'JSON',
650
+ output_format_set: str | dict = None) -> dict | str:
651
+ """Return the properties of a specific project. Async version.
652
+
653
+ Parameters
654
+ ----------
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").
659
+ 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".
663
+ output_format_set: str | dict, optional, default = None
664
+ The desired output columns/fields definition or a label referring to a predefined set.
665
+
666
+ Returns
667
+ -------
668
+ dict | str
669
+ JSON dict representing the specified project when output_format == "JSON";
670
+ otherwise a formatted string (or list) according to output_format.
671
+
672
+ Raises
673
+ ------
674
+ InvalidParameterException
675
+ If the client passes incorrect parameters on the request (bad URLs/values)
676
+ PropertyServerException
677
+ Raised by the server when an issue arises in processing a valid request
678
+ NotAuthorizedException
679
+ The requesting user is not authorized to issue this request
680
+
681
+ Notes
682
+ -----
683
+ Body sample:
684
+ {
685
+ "class": "GetRequestBody",
686
+ "asOfTime": "{{$isoTimestamp}}",
687
+ "effectiveTime": "{{$isoTimestamp}}",
688
+ "forLineage": false,
689
+ "forDuplicateProcessing": false
690
+ }
691
+ """
692
+
693
+ url = (f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/projects/"
694
+ f"{project_guid}")
695
+ type = element_type if element_type else "Project"
696
+
697
+ response = await self._async_get_guid_request(url, _type=type,
698
+ _gen_output=self._generate_project_output,
699
+ output_format=output_format, output_format_set=output_format_set,
700
+ body=body)
701
+
702
+ return response
703
+
704
+ @dynamic_catch
705
+ def get_project_by_guid(self, project_guid: str, element_type: str = None,
706
+ body: dict | GetRequestBody = None,
707
+ output_format: str = 'JSON',
708
+ output_format_set: str | dict = None) -> dict | str:
709
+ """Return the properties of a specific project.
710
+
711
+ Parameters
712
+ ----------
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").
717
+ 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".
721
+ output_format_set: str | dict, optional, default = None
722
+ The desired output columns/fields definition or a label referring to a predefined set.
723
+
724
+ Returns
725
+ -------
726
+ dict | str
727
+ JSON dict representing the specified project when output_format == "JSON";
728
+ otherwise a formatted string (or list) according to output_format.
729
+
730
+ Raises
731
+ ------
732
+ InvalidParameterException
733
+ If the client passes incorrect parameters on the request (bad URLs/values)
734
+ PropertyServerException
735
+ Raised by the server when an issue arises in processing a valid request
736
+ NotAuthorizedException
737
+ The requesting user is not authorized to issue this request
738
+
739
+ Notes
740
+ -----
741
+ Body sample:
742
+ {
743
+ "class": "GetRequestBody",
744
+ "asOfTime": "{{$isoTimestamp}}",
745
+ "effectiveTime": "{{$isoTimestamp}}",
746
+ "forLineage": false,
747
+ "forDuplicateProcessing": false
748
+ }
749
+ """
750
+ loop = asyncio.get_event_loop()
751
+ resp = loop.run_until_complete(
752
+ self._async_get_project_by_guid(project_guid, element_type, body, output_format, output_format_set )
753
+ )
754
+
755
+ return resp
756
+
757
+ @dynamic_catch
758
+ async def _async_get_project_graph(
759
+ self,
760
+ project_guid: str,
761
+ element_type: str = None,
762
+ body: dict | GetRequestBody = None,
763
+ output_format: str = 'JSON',
764
+ output_format_set: str | dict = None,
765
+ ) -> dict | str:
766
+ """Return the mermaid graph or formatted details of a specific project. Async version.
767
+
768
+ Parameters
769
+ ----------
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").
774
+ 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.
780
+
781
+ Returns
782
+ -------
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").
786
+
787
+ Raises
788
+ ------
789
+ InvalidParameterException
790
+ If the client passes incorrect parameters on the request (bad URLs/values)
791
+ PropertyServerException
792
+ Raised by the server when an issue arises in processing a valid request
793
+ NotAuthorizedException
794
+ The requesting user is not authorized to issue this request
795
+
796
+ """
797
+
798
+
799
+ url = (f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/pr"
800
+ f"ojects/{project_guid}/graph")
801
+
802
+ response = await self._async_get_guid_request(url, _type=element_type or 'Project',
803
+ _gen_output=self._generate_project_output,
804
+ output_format=output_format, output_format_set=output_format_set,
805
+ body=body)
806
+
807
+ return response
808
+
809
+ @dynamic_catch
810
+ def get_project_graph(
811
+ self,
812
+ project_guid: str,
813
+ element_type: str = None,
814
+ body: dict | GetRequestBody = None,
815
+ output_format: str = 'JSON',
816
+ output_format_set: str | dict = None,
817
+ ) -> dict | str:
818
+ """Return the mermaid graph or formatted details of a specific project.
819
+
820
+ Parameters
821
+ ----------
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").
826
+ 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.
832
+
833
+ Returns
834
+ -------
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").
838
+
839
+ Raises
840
+ ------
841
+ InvalidParameterException
842
+ If the client passes incorrect parameters on the request (bad URLs/values)
843
+ PropertyServerException
844
+ Raised by the server when an issue arises in processing a valid request
845
+ NotAuthorizedException
846
+ The requesting user is not authorized to issue this request
847
+
848
+ """
849
+ loop = asyncio.get_event_loop()
850
+ resp = loop.run_until_complete(
851
+ self._async_get_project_graph(project_guid, element_type, body, output_format, output_format_set)
852
+ )
853
+
854
+ return resp
855
+
856
+ #
857
+ # Create project methods
858
+ #
859
+ @dynamic_catch
860
+ async def _async_create_project(
861
+ self,
862
+ body: dict | NewElementRequestBody,
863
+ ) -> str:
864
+ """Create project: https://egeria-project.org/concepts/project Async version.
865
+
866
+ Parameters
867
+ ----------.
868
+ body: dict
869
+ A dict representing the details of the project to create. To create different kinds of projects,
870
+ set the initial_classifications in the body to be, for instance, "PersonalProject" or "Campaign".
871
+
872
+
873
+ Returns
874
+ -------
875
+ str - the guid of the created project
876
+
877
+ Raises
878
+ ------
879
+ InvalidParameterException
880
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
881
+ PropertyServerException
882
+ Raised by the server when an issue arises in processing a valid request
883
+ NotAuthorizedException
884
+ The principle specified by the user_id does not have authorization for the requested action
885
+ Notes
886
+ -----
887
+
888
+ Body structure like:
889
+ {
890
+ "class": "NewElementRequestBody",
891
+ "anchorGUID" : "anchor GUID, if set then isOwnAnchor=false",
892
+ "isOwnAnchor" : False,
893
+ "parentGUID" : "parent GUID, if set, set all parameters beginning 'parent'",
894
+ "parentRelationshipTypeName" : "open metadata type name",
895
+ "parentAtEnd1": True,
896
+ "initialClassifications" : {
897
+ "Folder" : {
898
+ "class": "FolderProperties"
899
+ }
900
+ },
901
+ "projectProperties": {
902
+ "class" : "ProjectProperties",
903
+ "qualifiedName": "Must provide a unique name here",
904
+ "identifier" : "Add business identifier",
905
+ "name" : "Add display name here",
906
+ "description" : "Add description of the project here",
907
+ "projectStatus": "Add appropriate valid value for type",
908
+ "projectPhase" : "Add appropriate valid value for phase",
909
+ "projectHealth" : "Add appropriate valid value for health",
910
+ "startDate" : "date/time",
911
+ "plannedEndDate" : "date/time"
912
+ }
913
+ }
914
+
915
+ """
916
+
917
+
918
+ url = f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/projects"
919
+
920
+ return await self._async_create_element_body_request(body, ["ProjectProperties"], body)
921
+
922
+ @dynamic_catch
923
+ def create_project(
924
+ self,
925
+ body: dict | NewElementRequestBody,
926
+ ) -> str:
927
+ """Create project: https://egeria-project.org/concepts/project
928
+
929
+ Parameters
930
+ ----------
931
+ body: dict | NewElementRequestBody
932
+ A dict or NewElementRequestBody representing the details of the project to create.
933
+
934
+ Returns
935
+ -------
936
+ str
937
+ The GUID of the created project.
938
+
939
+ Raises
940
+ ------
941
+ InvalidParameterException
942
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
943
+ PropertyServerException
944
+ Raised by the server when an issue arises in processing a valid request
945
+ NotAuthorizedException
946
+ The principle specified by the user_id does not have authorization for the requested action
947
+
948
+ Notes
949
+ -----
950
+ Body structure like:
951
+ {
952
+ "anchorGUID" : "anchor GUID, if set then isOwnAnchor=false",
953
+ "isOwnAnchor" : False,
954
+ "parentGUID" : "parent GUID, if set, set all parameters beginning 'parent'",
955
+ "parentRelationshipTypeName" : "open metadata type name",
956
+ "parentAtEnd1": True,
957
+ "projectProperties": {
958
+ "class" : "ProjectProperties",
959
+ "qualifiedName": "Must provide a unique name here",
960
+ "identifier" : "Add business identifier",
961
+ "name" : "Add display name here",
962
+ "description" : "Add description of the project here",
963
+ "projectStatus": "Add appropriate valid value for type",
964
+ "projectPhase" : "Add appropriate valid value for phase",
965
+ "projectHealth" : "Add appropriate valid value for health",
966
+ "startDate" : "date/time",
967
+ "plannedEndDate" : "date/time"
968
+ }
969
+ }
970
+
971
+ """
972
+ loop = asyncio.get_event_loop()
973
+ resp = loop.run_until_complete(
974
+ self._async_create_project(body)
975
+ )
976
+ return resp
977
+
978
+ @dynamic_catch
979
+ async def _async_create_project_from_template(
980
+ self,
981
+ body: dict | TemplateRequestBody,
982
+ ) -> str:
983
+ """Create a new metadata element to represent a project using an existing metadata element as a template.
984
+ The template defines additional classifications and relationships that should be added to the new project.
985
+ Async version.
986
+
987
+ Parameters
988
+ ----------
989
+
990
+ body: dict
991
+ A dict representing the details of the collection to create.
992
+
993
+
994
+ Returns
995
+ -------
996
+ str - the guid of the created project.
997
+
998
+ Raises
999
+ ------
1000
+ InvalidParameterException
1001
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1002
+ PropertyServerException
1003
+ Raised by the server when an issue arises in processing a valid request
1004
+ NotAuthorizedException
1005
+ The principle specified by the user_id does not have authorization for the requested action
1006
+
1007
+ Notes
1008
+ -----
1009
+ JSON Structure looks like:
1010
+ {
1011
+ "class": "TemplateRequestBody",
1012
+ "anchorGUID": "anchor GUID, if set then isOwnAnchor=false",
1013
+ "isOwnAnchor": false,
1014
+ "parentGUID": "parent GUID, if set, set all parameters beginning 'parent'",
1015
+ "parentRelationshipTypeName": "open metadata type name",
1016
+ "parentAtEnd1": true,
1017
+ "templateGUID": "template GUID",
1018
+ "replacementProperties": {
1019
+ "class": "ElementProperties",
1020
+ "propertyValueMap" : {
1021
+ "propertyName" : {
1022
+ "class": "PrimitiveTypePropertyValue",
1023
+ "typeName": "string",
1024
+ "primitiveTypeCategory" : "OM_PRIMITIVE_TYPE_STRING",
1025
+ "primitiveValue" : "value of property"
1026
+ }
1027
+ }
1028
+ },
1029
+ "placeholderPropertyValues" : {
1030
+ "placeholderProperty1Name" : "property1Value",
1031
+ "placeholderProperty2Name" : "property2Value"
1032
+ }
1033
+ }
1034
+
1035
+
1036
+ """
1037
+
1038
+ url = f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/projects/from-template"
1039
+ return await self._async_create_element_from_template(url, body)
1040
+
1041
+ @dynamic_catch
1042
+ def create_project_from_template(
1043
+ self,
1044
+ body: dict,
1045
+ ) -> str:
1046
+ """Create a new metadata element to represent a project using an existing metadata element as a template.
1047
+ The template defines additional classifications and relationships that should be added to the new project.
1048
+
1049
+ Parameters
1050
+ ----------
1051
+
1052
+ body: dict
1053
+ A dict representing the details of the collection to create.
1054
+
1055
+
1056
+ Returns
1057
+ -------
1058
+ str - the guid of the created project.
1059
+
1060
+ Raises
1061
+ ------
1062
+ InvalidParameterException
1063
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1064
+ PropertyServerException
1065
+ Raised by the server when an issue arises in processing a valid request
1066
+ NotAuthorizedException
1067
+ The principle specified by the user_id does not have authorization for the requested action
1068
+
1069
+ Notes
1070
+ -----
1071
+ JSON Structure looks like:
1072
+ {
1073
+ "class": "TemplateRequestBody",
1074
+ "anchorGUID": "anchor GUID, if set then isOwnAnchor=false",
1075
+ "isOwnAnchor": false,
1076
+ "parentGUID": "parent GUID, if set, set all parameters beginning 'parent'",
1077
+ "parentRelationshipTypeName": "open metadata type name",
1078
+ "parentAtEnd1": true,
1079
+ "templateGUID": "template GUID",
1080
+ "replacementProperties": {
1081
+ "class": "ElementProperties",
1082
+ "propertyValueMap" : {
1083
+ "propertyName" : {
1084
+ "class": "PrimitiveTypePropertyValue",
1085
+ "typeName": "string",
1086
+ "primitiveTypeCategory" : "OM_PRIMITIVE_TYPE_STRING",
1087
+ "primitiveValue" : "value of property"
1088
+ }
1089
+ }
1090
+ },
1091
+ "placeholderPropertyValues" : {
1092
+ "placeholderProperty1Name" : "property1Value",
1093
+ "placeholderProperty2Name" : "property2Value"
1094
+ }
1095
+ }
1096
+ """
1097
+ loop = asyncio.get_event_loop()
1098
+ resp = loop.run_until_complete(self._async_create_project_from_template(body))
1099
+ return resp
1100
+
1101
+
1102
+ #
1103
+ #
1104
+ #
1105
+
1106
+ async def _async_update_project(
1107
+ self,
1108
+ project_guid: str,
1109
+ body: dict | UpdateElementRequestBody,
1110
+ ) -> None:
1111
+ """Update the properties of a project. Async version.
1112
+
1113
+ Parameters
1114
+ ----------
1115
+ project_guid: str
1116
+ Unique identifier of the project to update.
1117
+ body: dict | UpdateElementRequestBody
1118
+ The update payload specifying properties to change.
1119
+
1120
+ Returns
1121
+ -------
1122
+ None
1123
+
1124
+ Raises
1125
+ ------
1126
+ InvalidParameterException
1127
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1128
+ PropertyServerException
1129
+ Raised by the server when an issue arises in processing a valid request
1130
+ NotAuthorizedException
1131
+ The principle specified by the user_id does not have authorization for the requested action
1132
+ """
1133
+
1134
+ url = (
1135
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/projects/{project_guid}/update"
1136
+ )
1137
+
1138
+ await self._async_update_element_body_request(url, PROJECT_PROPERTIES_LIST, body)
1139
+
1140
+ def update_project(
1141
+ self,
1142
+ project_guid: str,
1143
+ body: dict | UpdateElementRequestBody ) -> None:
1144
+ """Update the properties of a project.
1145
+
1146
+ Parameters
1147
+ ----------
1148
+ project_guid: str
1149
+ Unique identifier of the project to update.
1150
+ body: dict | UpdateElementRequestBody
1151
+ The update payload specifying properties to change.
1152
+
1153
+ Returns
1154
+ -------
1155
+ None
1156
+
1157
+ Raises
1158
+ ------
1159
+ InvalidParameterException
1160
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1161
+ PropertyServerException
1162
+ Raised by the server when an issue arises in processing a valid request
1163
+ NotAuthorizedException
1164
+ The principle specified by the user_id does not have authorization for the requested action
1165
+ """
1166
+ loop = asyncio.get_event_loop()
1167
+ loop.run_until_complete(
1168
+ self._async_update_project(
1169
+ project_guid,
1170
+ body
1171
+ )
1172
+ )
1173
+ return
1174
+
1175
+ async def _async_delete_project(
1176
+ self,
1177
+ project_guid: str, cascade_delete: bool = False,
1178
+ body: dict | DeleteRequestBody = None
1179
+ ) -> None:
1180
+ """Delete a project. Async version.
1181
+
1182
+ Parameters
1183
+ ----------
1184
+ 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
+
1191
+ Returns
1192
+ -------
1193
+ None
1194
+
1195
+ Raises
1196
+ ------
1197
+ InvalidParameterException
1198
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1199
+ PropertyServerException
1200
+ Raised by the server when an issue arises in processing a valid request
1201
+ NotAuthorizedException
1202
+ The principle specified by the user_id does not have authorization for the requested action
1203
+
1204
+ """
1205
+
1206
+ url = (
1207
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/projects/"
1208
+ f"{project_guid}/delete"
1209
+ )
1210
+ await self._async_delete_request(url, body, cascade_delete)
1211
+ logger.info(f"Deleted project {project_guid} with cascade {cascade_delete}")
1212
+
1213
+ def delete_project(
1214
+ self,
1215
+ project_guid: str, cascade_delete: bool = False,
1216
+ body: dict |DeleteRequestBody = None
1217
+ ) -> None:
1218
+ """Delete a project.
1219
+
1220
+ Parameters
1221
+ ----------
1222
+ 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
+
1229
+ Returns
1230
+ -------
1231
+ None
1232
+
1233
+ Raises
1234
+ ------
1235
+
1236
+ InvalidParameterException
1237
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1238
+ PropertyServerException
1239
+ Raised by the server when an issue arises in processing a valid request
1240
+ NotAuthorizedException
1241
+ The principle specified by the user_id does not have authorization for the requested action
1242
+
1243
+ """
1244
+ loop = asyncio.get_event_loop()
1245
+ loop.run_until_complete(self._async_delete_project(project_guid, cascade_delete, body))
1246
+
1247
+
1248
+ async def _async_add_to_project_team(
1249
+ self,
1250
+ project_guid: str,
1251
+ actor_guid: str,
1252
+ body: dict | NewRelationshipRequestBody = None,
1253
+ ) -> None:
1254
+ """Add an actor to a project. Async version.
1255
+
1256
+ Parameters
1257
+ ----------
1258
+ project_guid: str
1259
+ Identity of the project to update.
1260
+ 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).
1264
+
1265
+ Returns
1266
+ -------
1267
+ None
1268
+
1269
+ Raises
1270
+ ------
1271
+
1272
+ InvalidParameterException
1273
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1274
+ PropertyServerException
1275
+ Raised by the server when an issue arises in processing a valid request
1276
+ NotAuthorizedException
1277
+ The principle specified by the user_id does not have authorization for the requested action
1278
+
1279
+ """
1280
+
1281
+ url = (
1282
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/projects/{project_guid}/"
1283
+ f"members/{actor_guid}/attach"
1284
+ )
1285
+ await self._async_new_relationship_request(url, "AssignmentScopeProperties", body)
1286
+ logger.info(f"Added actor {actor_guid} to project {project_guid}")
1287
+
1288
+ def add_to_project_team(
1289
+ self,
1290
+ project_guid: str,
1291
+ actor_guid: str,
1292
+ body: dict | NewRelationshipRequestBody = None,
1293
+ ) -> None:
1294
+ """Add an actor to a project.
1295
+
1296
+ Parameters
1297
+ ----------
1298
+ project_guid: str
1299
+ Identity of the project to update.
1300
+ 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).
1304
+
1305
+ Returns
1306
+ -------
1307
+ None
1308
+
1309
+ Raises
1310
+ ------
1311
+
1312
+ InvalidParameterException
1313
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1314
+ PropertyServerException
1315
+ Raised by the server when an issue arises in processing a valid request
1316
+ NotAuthorizedException
1317
+ The principle specified by the user_id does not have authorization for the requested action
1318
+
1319
+ """
1320
+ loop = asyncio.get_event_loop()
1321
+ loop.run_until_complete(
1322
+ self._async_add_to_project_team(
1323
+ project_guid,
1324
+ actor_guid,
1325
+ body
1326
+ )
1327
+ )
1328
+
1329
+
1330
+ async def _async_remove_from_project_team(
1331
+ self,
1332
+ project_guid: str,
1333
+ actor_guid: str,
1334
+ body: dict | DeleteRequestBody = None,
1335
+ cascade_delete: bool = False,
1336
+ ) -> None:
1337
+ """Remove an actor from a project. Async version.
1338
+
1339
+ Parameters
1340
+ ----------
1341
+ project_guid: str
1342
+ Identity of the project to remove members from.
1343
+ 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.
1349
+
1350
+ Returns
1351
+ -------
1352
+ None
1353
+
1354
+ Raises
1355
+ ------
1356
+
1357
+ InvalidParameterException
1358
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1359
+ PropertyServerException
1360
+ Raised by the server when an issue arises in processing a valid request
1361
+ NotAuthorizedException
1362
+ The principle specified by the user_id does not have authorization for the requested action
1363
+
1364
+ """
1365
+
1366
+ url = (
1367
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/projects/{project_guid}/"
1368
+ f"members/{actor_guid}/detach"
1369
+ )
1370
+ await self._async_delete_request(url, body, cascade_delete)
1371
+ logger.info(f"Removed actor {actor_guid} from project {project_guid}")
1372
+
1373
+
1374
+ def remove_from_project_team(
1375
+ self,
1376
+ project_guid: str,
1377
+ actor_guid: str,
1378
+ body: dict | DeleteRequestBody = None,
1379
+ cascade_delete: bool = False,
1380
+ ) -> None:
1381
+ """Remove an actor from a project.
1382
+
1383
+ Parameters
1384
+ ----------
1385
+ project_guid: str
1386
+ Identity of the project.
1387
+ 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
+
1470
+
1471
+ Returns
1472
+ -------
1473
+ None
1474
+
1475
+ Raises
1476
+ ------
1477
+
1478
+ InvalidParameterException
1479
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1480
+ PropertyServerException
1481
+ Raised by the server when an issue arises in processing a valid request
1482
+ NotAuthorizedException
1483
+ The principle specified by the user_id does not have authorization for the requested action
1484
+
1485
+ """
1486
+ loop = asyncio.get_event_loop()
1487
+ loop.run_until_complete(
1488
+ self._async_setup_project_dependency( project_guid, depends_on_project_guid, body)
1489
+ )
1490
+ return
1491
+
1492
+ async def _async_clear_project_dependency(
1493
+ self,
1494
+ project_guid: str,
1495
+ depends_on_project_guid: str,
1496
+ body: dict | DeleteRequestBody = None,
1497
+ cascade_delete: bool = False
1498
+ ) -> None:
1499
+ """Remove a project dependency link between two projects. Async version.
1500
+
1501
+ Parameters
1502
+ ----------
1503
+ 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.
1507
+
1508
+
1509
+ Returns
1510
+ -------
1511
+ None
1512
+
1513
+ Raises
1514
+ ------
1515
+
1516
+ InvalidParameterException
1517
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1518
+ PropertyServerException
1519
+ Raised by the server when an issue arises in processing a valid request
1520
+ NotAuthorizedException
1521
+ The principle specified by the user_id does not have authorization for the requested action
1522
+
1523
+ """
1524
+
1525
+ url = (
1526
+ 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"
1528
+ )
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
+
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
+ )
1570
+ return
1571
+
1572
+ async def _async_setup_project_hierarchy(
1573
+ self,
1574
+ project_guid: str,
1575
+ managed_project_guid: str,
1576
+ body: dict | NewRelationshipRequestBody = None,
1577
+ ) -> None:
1578
+ """Create a project hierarchy link from a project to a managed (child) project. Async version.
1579
+
1580
+ Parameters
1581
+ ----------
1582
+ 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.
1626
+
1627
+
1628
+ Returns
1629
+ -------
1630
+ None
1631
+
1632
+ Raises
1633
+ ------
1634
+
1635
+ InvalidParameterException
1636
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1637
+ PropertyServerException
1638
+ Raised by the server when an issue arises in processing a valid request
1639
+ NotAuthorizedException
1640
+ The principle specified by the user_id does not have authorization for the requested action
1641
+
1642
+ """
1643
+ loop = asyncio.get_event_loop()
1644
+ loop.run_until_complete(
1645
+ self._async_setup_project_dependency( project_guid, managed_project_guid, body)
1646
+ )
1647
+ return
1648
+
1649
+ async def _async_clear_project_hierarchy(
1650
+ self,
1651
+ project_guid: str,
1652
+ managed_project_guid: str,
1653
+ body: dict | DeleteRequestBody = None,
1654
+ cascade_delete: bool = False
1655
+ ) -> None:
1656
+ """Remove a project hierarchy link between two projects. Async version.
1657
+
1658
+ Parameters
1659
+ ----------
1660
+ project_guid: str
1661
+ Identity of the parent (managing) project.
1662
+ managed_project_guid: str
1663
+ GUID of the managed (child) project.
1664
+
1665
+
1666
+ Returns
1667
+ -------
1668
+ None
1669
+
1670
+ Raises
1671
+ ------
1672
+
1673
+ InvalidParameterException
1674
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1675
+ PropertyServerException
1676
+ Raised by the server when an issue arises in processing a valid request
1677
+ NotAuthorizedException
1678
+ The principle specified by the user_id does not have authorization for the requested action
1679
+
1680
+ """
1681
+
1682
+ url = (
1683
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/projects/{project_guid}/"
1684
+ f"project-hierarchies/{managed_project_guid}/detach"
1685
+ )
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
+
1689
+
1690
+ def clear_project_hierarchy(
1691
+ self,
1692
+ project_guid: str,
1693
+ managed_project_guid: str,
1694
+ body: dict | DeleteRequestBody = None,
1695
+ cascade_delete: bool = False
1696
+ ) -> None:
1697
+ """Clear a project hierarchy link between two projects.
1698
+
1699
+ Parameters
1700
+ ----------
1701
+ project_guid: str
1702
+ Identity of the parent (managing) project.
1703
+ managed_project_guid: str
1704
+ GUID of the managed (child) project.
1705
+
1706
+
1707
+ Returns
1708
+ -------
1709
+ None
1710
+
1711
+ Raises
1712
+ ------
1713
+
1714
+ InvalidParameterException
1715
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1716
+ PropertyServerException
1717
+ Raised by the server when an issue arises in processing a valid request
1718
+ NotAuthorizedException
1719
+ The principle specified by the user_id does not have authorization for the requested action
1720
+
1721
+ """
1722
+ loop = asyncio.get_event_loop()
1723
+ loop.run_until_complete(
1724
+ self._async_clear_project_hierarchy(project_guid, managed_project_guid,
1725
+ body, cascade_delete)
1726
+ )
1727
+ return
1728
+
1729
+
1730
+ if __name__ == "__main__":
1731
+ 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}")