midpoint-cli 1.5.0.dev1__tar.gz → 1.5.0.dev2__tar.gz

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 (24) hide show
  1. {midpoint_cli-1.5.0.dev1 → midpoint_cli-1.5.0.dev2}/PKG-INFO +1 -1
  2. {midpoint_cli-1.5.0.dev1 → midpoint_cli-1.5.0.dev2}/pyproject.toml +1 -1
  3. {midpoint_cli-1.5.0.dev1 → midpoint_cli-1.5.0.dev2}/src/midpoint_cli/client/__init__.py +1 -1
  4. {midpoint_cli-1.5.0.dev1 → midpoint_cli-1.5.0.dev2}/src/midpoint_cli/client/objects.py +58 -0
  5. {midpoint_cli-1.5.0.dev1 → midpoint_cli-1.5.0.dev2}/src/midpoint_cli/prompt/delete.py +10 -2
  6. {midpoint_cli-1.5.0.dev1 → midpoint_cli-1.5.0.dev2}/src/midpoint_cli/prompt/get.py +4 -1
  7. {midpoint_cli-1.5.0.dev1 → midpoint_cli-1.5.0.dev2}/src/midpoint_cli/prompt/task.py +1 -2
  8. {midpoint_cli-1.5.0.dev1 → midpoint_cli-1.5.0.dev2}/LICENSE +0 -0
  9. {midpoint_cli-1.5.0.dev1 → midpoint_cli-1.5.0.dev2}/README.md +0 -0
  10. {midpoint_cli-1.5.0.dev1 → midpoint_cli-1.5.0.dev2}/src/midpoint_cli/__init__.py +0 -0
  11. {midpoint_cli-1.5.0.dev1 → midpoint_cli-1.5.0.dev2}/src/midpoint_cli/client/observer.py +0 -0
  12. {midpoint_cli-1.5.0.dev1 → midpoint_cli-1.5.0.dev2}/src/midpoint_cli/client/patch.py +0 -0
  13. {midpoint_cli-1.5.0.dev1 → midpoint_cli-1.5.0.dev2}/src/midpoint_cli/client/progress.py +0 -0
  14. {midpoint_cli-1.5.0.dev1 → midpoint_cli-1.5.0.dev2}/src/midpoint_cli/client/session.py +0 -0
  15. {midpoint_cli-1.5.0.dev1 → midpoint_cli-1.5.0.dev2}/src/midpoint_cli/prompt/__init__.py +0 -0
  16. {midpoint_cli-1.5.0.dev1 → midpoint_cli-1.5.0.dev2}/src/midpoint_cli/prompt/base.py +0 -0
  17. {midpoint_cli-1.5.0.dev1 → midpoint_cli-1.5.0.dev2}/src/midpoint_cli/prompt/complete.py +0 -0
  18. {midpoint_cli-1.5.0.dev1 → midpoint_cli-1.5.0.dev2}/src/midpoint_cli/prompt/configuration.py +0 -0
  19. {midpoint_cli-1.5.0.dev1 → midpoint_cli-1.5.0.dev2}/src/midpoint_cli/prompt/console.py +0 -0
  20. {midpoint_cli-1.5.0.dev1 → midpoint_cli-1.5.0.dev2}/src/midpoint_cli/prompt/org.py +0 -0
  21. {midpoint_cli-1.5.0.dev1 → midpoint_cli-1.5.0.dev2}/src/midpoint_cli/prompt/put.py +0 -0
  22. {midpoint_cli-1.5.0.dev1 → midpoint_cli-1.5.0.dev2}/src/midpoint_cli/prompt/resource.py +0 -0
  23. {midpoint_cli-1.5.0.dev1 → midpoint_cli-1.5.0.dev2}/src/midpoint_cli/prompt/script.py +0 -0
  24. {midpoint_cli-1.5.0.dev1 → midpoint_cli-1.5.0.dev2}/src/midpoint_cli/prompt/user.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: midpoint-cli
3
- Version: 1.5.0.dev1
3
+ Version: 1.5.0.dev2
4
4
  Summary: A command line client to Midpoint Identity Management system.
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [tool.poetry]
6
6
  name = "midpoint-cli"
7
- version = "1.5.0.dev1"
7
+ version = "1.5.0.dev2"
8
8
  description = "A command line client to Midpoint Identity Management system."
9
9
  readme = "README.md"
10
10
 
@@ -105,7 +105,7 @@ class RestApiClient:
105
105
  tree_root = self._load_xml(xml_filename)
106
106
 
107
107
  root_tag_name = tree_root.tag.split('}', 1)[1] if '}' in tree_root.tag else tree_root.tag # strip namespace
108
- object_type = MidpointObjectTypes.find_by_tagname(root_tag_name)
108
+ object_type = MidpointObjectTypes.find_by_name(root_tag_name)
109
109
 
110
110
  if not object_type.endpoint:
111
111
  raise MidpointUnsupportedOperation(f'Upload of {object_type} is not supported through REST API')
@@ -398,6 +398,64 @@ class MidpointObjectTypes(Enum):
398
398
  def find_by_tagname(tagname: str) -> MidpointObjectType:
399
399
  return MidpointObjectTypes.__find(tagname, lambda t: t.tagname)
400
400
 
401
+ @staticmethod
402
+ def find_by_name(name: str) -> MidpointObjectType:
403
+ """
404
+ Flexible type lookup that tries multiple matching strategies:
405
+ 1. Case-insensitive tagname match (e.g., "objectTemplate", "ObjectTemplate")
406
+ 2. Case-insensitive Java type match (e.g., "ObjectTemplateType")
407
+ 3. Partial name with Type suffix appended (e.g., "ObjectTemplate" → "ObjectTemplateType")
408
+ 4. Partial name with Type suffix removed (e.g., "ObjectTemplateType" → "ObjectTemplate")
409
+
410
+ Raises MidpointTypeNotFound with helpful suggestions if no match is found.
411
+ """
412
+ if not name:
413
+ raise MidpointTypeNotFound('Type name cannot be empty')
414
+
415
+ name_lower = name.lower()
416
+
417
+ # Strategy 1: Try case-insensitive tagname match
418
+ for mp_type in MidpointObjectTypes:
419
+ if mp_type.value.tagname and mp_type.value.tagname.lower() == name_lower:
420
+ return mp_type.value
421
+
422
+ # Strategy 2: Try case-insensitive Java type match
423
+ for mp_type in MidpointObjectTypes:
424
+ if mp_type.value.object_type and mp_type.value.object_type.lower() == name_lower:
425
+ return mp_type.value
426
+
427
+ # Strategy 3: Try appending "Type" suffix for partial matches
428
+ # (e.g., "ObjectTemplate" → "ObjectTemplateType")
429
+ if not name_lower.endswith('type'):
430
+ name_with_type = name + 'Type'
431
+ name_with_type_lower = name_with_type.lower()
432
+ for mp_type in MidpointObjectTypes:
433
+ if mp_type.value.object_type and mp_type.value.object_type.lower() == name_with_type_lower:
434
+ return mp_type.value
435
+
436
+ # Strategy 4: Try removing "Type" suffix
437
+ # (e.g., "ObjectTemplateType" → "objectTemplate")
438
+ if name_lower.endswith('type'):
439
+ name_without_type = name[:-4] # Remove "Type"
440
+ name_without_type_lower = name_without_type.lower()
441
+ for mp_type in MidpointObjectTypes:
442
+ if mp_type.value.tagname and mp_type.value.tagname.lower() == name_without_type_lower:
443
+ return mp_type.value
444
+
445
+ # No match found - create helpful error message
446
+ valid_types = []
447
+ for mp_type in MidpointObjectTypes:
448
+ if mp_type.value.tagname != 'objects': # Skip the generic "objects" type
449
+ if mp_type.value.object_type:
450
+ valid_types.append(f'{mp_type.value.tagname} ({mp_type.value.object_type})')
451
+ else:
452
+ valid_types.append(mp_type.value.tagname)
453
+
454
+ valid_types_str = ', '.join(sorted(valid_types))
455
+ raise MidpointTypeNotFound(
456
+ f'No type found for value "{name}". Valid types are: {valid_types_str}'
457
+ )
458
+
401
459
 
402
460
  def optional_text(node: Optional[Element]) -> Optional[str]:
403
461
  return node.text if node is not None else None
@@ -1,7 +1,10 @@
1
1
  import shlex
2
2
  from argparse import ArgumentParser, RawTextHelpFormatter
3
3
 
4
+ from midpoint_cli.client import MidpointObjectTypes
5
+ from midpoint_cli.client.objects import MidpointTypeNotFound
4
6
  from midpoint_cli.prompt.base import PromptBase
7
+ from midpoint_cli.prompt.console import print_error
5
8
 
6
9
  delete_parser = ArgumentParser(
7
10
  formatter_class=RawTextHelpFormatter, prog='delete', description='Delete a server object.', epilog=''
@@ -21,10 +24,15 @@ class DeleteClientPrompt(PromptBase):
21
24
  try:
22
25
  delete_args = shlex.split(inp)
23
26
  ns = delete_parser.parse_args(delete_args)
24
- self.client.delete(ns.objectclass, ns.oid)
25
27
 
28
+ # Resolve the type string to a MidpointObjectType
29
+ midpoint_type = MidpointObjectTypes.find_by_name(ns.objectclass)
30
+ self.client.delete(midpoint_type, ns.oid)
31
+
32
+ except MidpointTypeNotFound as e:
33
+ print_error(str(e))
26
34
  except AttributeError as e:
27
- print('Error:', e)
35
+ print_error(str(e))
28
36
  except SystemExit:
29
37
  pass
30
38
 
@@ -3,6 +3,7 @@ from argparse import ArgumentParser, RawTextHelpFormatter
3
3
  from xml.etree import ElementTree
4
4
 
5
5
  from midpoint_cli.client import MidpointObjectTypes
6
+ from midpoint_cli.client.objects import MidpointTypeNotFound
6
7
  from midpoint_cli.prompt.base import PromptBase
7
8
  from midpoint_cli.prompt.console import print_error, print_xml
8
9
 
@@ -20,7 +21,7 @@ class GetClientPrompt(PromptBase):
20
21
  get_args = shlex.split(inp)
21
22
  ns = get_parser.parse_args(get_args)
22
23
 
23
- midpoint_type = MidpointObjectTypes.find_by_tagname(ns.objectclass)
24
+ midpoint_type = MidpointObjectTypes.find_by_name(ns.objectclass)
24
25
 
25
26
  xml_text = self.client.get_xml(midpoint_type, ns.oid)
26
27
  xml_root = ElementTree.fromstring(xml_text)
@@ -38,6 +39,8 @@ class GetClientPrompt(PromptBase):
38
39
  with open(ns.file, 'w') as f:
39
40
  f.write(xml_text)
40
41
 
42
+ except MidpointTypeNotFound as e:
43
+ print_error(str(e))
41
44
  except AttributeError as e:
42
45
  print_error(str(e))
43
46
  except SystemExit:
@@ -140,8 +140,7 @@ class TaskClientPrompt(PromptBase):
140
140
  from xml.etree import ElementTree
141
141
 
142
142
  failed_task_xml = self.client.api_client.get_element(
143
- MidpointObjectTypes.TASK.value,
144
- task_oid
143
+ MidpointObjectTypes.TASK.value, task_oid
145
144
  )
146
145
  failed_task = MidpointTask(ElementTree.fromstring(failed_task_xml))
147
146
  console = get_console()