rhapsody-cli 0.1.0__tar.gz → 0.2.0__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 (124) hide show
  1. {rhapsody_cli-0.1.0/src/rhapsody_cli.egg-info → rhapsody_cli-0.2.0}/PKG-INFO +87 -44
  2. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/README.md +85 -43
  3. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/pyproject.toml +10 -1
  4. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/actions/class_action.py +2 -1
  5. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/actions/package_action.py +69 -1
  6. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/actions/project_action.py +67 -1
  7. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/application.py +168 -1
  8. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/commands/package_command.py +5 -1
  9. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/commands/project_command.py +5 -1
  10. rhapsody_cli-0.2.0/src/rhapsody_cli/exchange/__init__.py +20 -0
  11. rhapsody_cli-0.2.0/src/rhapsody_cli/exchange/core.py +310 -0
  12. rhapsody_cli-0.2.0/src/rhapsody_cli/exchange/exporter.py +354 -0
  13. rhapsody_cli-0.2.0/src/rhapsody_cli/exchange/importer.py +343 -0
  14. rhapsody_cli-0.2.0/src/rhapsody_cli/exchange/schema.py +12 -0
  15. rhapsody_cli-0.2.0/src/rhapsody_cli/exchange/yaml_utils.py +58 -0
  16. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/core.py +281 -164
  17. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/activity/model_actions.py +72 -63
  18. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/activity/model_activity.py +118 -111
  19. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/classifiers/__init__.py +2 -0
  20. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/classifiers/model_actor.py +26 -8
  21. rhapsody_cli-0.2.0/src/rhapsody_cli/models/elements/classifiers/model_association_class.py +68 -0
  22. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/classifiers/model_class.py +51 -32
  23. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/classifiers/model_classifier.py +49 -49
  24. rhapsody_cli-0.2.0/src/rhapsody_cli/models/elements/classifiers/model_exception.py +10 -0
  25. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/classifiers/model_interface_item.py +11 -20
  26. rhapsody_cli-0.2.0/src/rhapsody_cli/models/elements/classifiers/model_operation.py +399 -0
  27. rhapsody_cli-0.2.0/src/rhapsody_cli/models/elements/classifiers/model_statechart.py +452 -0
  28. rhapsody_cli-0.2.0/src/rhapsody_cli/models/elements/classifiers/model_stereotype.py +92 -0
  29. rhapsody_cli-0.2.0/src/rhapsody_cli/models/elements/classifiers/model_usecase.py +223 -0
  30. rhapsody_cli-0.2.0/src/rhapsody_cli/models/elements/common/model_misc.py +74 -0
  31. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/common/model_other_model.py +115 -111
  32. rhapsody_cli-0.2.0/src/rhapsody_cli/models/elements/containment/model_collaboration.py +570 -0
  33. rhapsody_cli-0.2.0/src/rhapsody_cli/models/elements/containment/model_component.py +556 -0
  34. rhapsody_cli-0.2.0/src/rhapsody_cli/models/elements/containment/model_component_instance.py +57 -0
  35. rhapsody_cli-0.2.0/src/rhapsody_cli/models/elements/containment/model_configuration.py +572 -0
  36. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/containment/model_module.py +1 -1
  37. rhapsody_cli-0.2.0/src/rhapsody_cli/models/elements/containment/model_node.py +100 -0
  38. rhapsody_cli-0.2.0/src/rhapsody_cli/models/elements/containment/model_package.py +1445 -0
  39. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/containment/model_profile.py +1 -1
  40. rhapsody_cli-0.2.0/src/rhapsody_cli/models/elements/containment/model_project.py +954 -0
  41. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/diagrams/model_diagram_types.py +81 -56
  42. rhapsody_cli-0.2.0/src/rhapsody_cli/models/elements/diagrams/model_diagrams.py +486 -0
  43. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/graphics/model_graphics.py +447 -432
  44. rhapsody_cli-0.2.0/src/rhapsody_cli/models/elements/interactions/model_interactions.py +460 -0
  45. rhapsody_cli-0.2.0/src/rhapsody_cli/models/elements/relations/model_association_role.py +56 -0
  46. rhapsody_cli-0.2.0/src/rhapsody_cli/models/elements/relations/model_dependency.py +103 -0
  47. rhapsody_cli-0.2.0/src/rhapsody_cli/models/elements/relations/model_generalization.py +140 -0
  48. rhapsody_cli-0.2.0/src/rhapsody_cli/models/elements/relations/model_hyperlink.py +83 -0
  49. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/relations/model_instance.py +13 -13
  50. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/relations/model_port.py +14 -14
  51. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/relations/model_relation.py +34 -31
  52. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/requirements/model_requirements.py +15 -14
  53. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/statemachine/model_statemachine.py +119 -116
  54. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/templates/model_templates.py +36 -29
  55. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/values/model_values.py +45 -39
  56. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/variables/model_variables.py +196 -38
  57. rhapsody_cli-0.2.0/src/rhapsody_cli/models/support/__init__.py +28 -0
  58. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/support/model_codegen.py +115 -115
  59. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/support/model_files.py +32 -32
  60. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/support/model_ide.py +54 -54
  61. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0/src/rhapsody_cli.egg-info}/PKG-INFO +87 -44
  62. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli.egg-info/SOURCES.txt +7 -0
  63. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli.egg-info/requires.txt +1 -0
  64. rhapsody_cli-0.1.0/src/rhapsody_cli/models/elements/classifiers/model_association_class.py +0 -21
  65. rhapsody_cli-0.1.0/src/rhapsody_cli/models/elements/classifiers/model_operation.py +0 -182
  66. rhapsody_cli-0.1.0/src/rhapsody_cli/models/elements/classifiers/model_statechart.py +0 -108
  67. rhapsody_cli-0.1.0/src/rhapsody_cli/models/elements/classifiers/model_stereotype.py +0 -23
  68. rhapsody_cli-0.1.0/src/rhapsody_cli/models/elements/classifiers/model_usecase.py +0 -86
  69. rhapsody_cli-0.1.0/src/rhapsody_cli/models/elements/common/model_misc.py +0 -45
  70. rhapsody_cli-0.1.0/src/rhapsody_cli/models/elements/containment/model_collaboration.py +0 -55
  71. rhapsody_cli-0.1.0/src/rhapsody_cli/models/elements/containment/model_component.py +0 -59
  72. rhapsody_cli-0.1.0/src/rhapsody_cli/models/elements/containment/model_component_instance.py +0 -20
  73. rhapsody_cli-0.1.0/src/rhapsody_cli/models/elements/containment/model_configuration.py +0 -62
  74. rhapsody_cli-0.1.0/src/rhapsody_cli/models/elements/containment/model_node.py +0 -22
  75. rhapsody_cli-0.1.0/src/rhapsody_cli/models/elements/containment/model_package.py +0 -285
  76. rhapsody_cli-0.1.0/src/rhapsody_cli/models/elements/containment/model_project.py +0 -248
  77. rhapsody_cli-0.1.0/src/rhapsody_cli/models/elements/diagrams/model_diagrams.py +0 -114
  78. rhapsody_cli-0.1.0/src/rhapsody_cli/models/elements/interactions/model_interactions.py +0 -1336
  79. rhapsody_cli-0.1.0/src/rhapsody_cli/models/elements/relations/model_association_role.py +0 -20
  80. rhapsody_cli-0.1.0/src/rhapsody_cli/models/elements/relations/model_dependency.py +0 -23
  81. rhapsody_cli-0.1.0/src/rhapsody_cli/models/elements/relations/model_generalization.py +0 -26
  82. rhapsody_cli-0.1.0/src/rhapsody_cli/models/elements/relations/model_hyperlink.py +0 -25
  83. rhapsody_cli-0.1.0/src/rhapsody_cli/models/support/__init__.py +0 -5
  84. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/LICENSE +0 -0
  85. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/setup.cfg +0 -0
  86. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/__init__.py +0 -0
  87. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/actions/__init__.py +0 -0
  88. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/actions/abstract_action.py +0 -0
  89. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/actions/attribute_action.py +0 -0
  90. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/actions/operation_action.py +0 -0
  91. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/actions/port_action.py +0 -0
  92. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/cli/__init__.py +0 -0
  93. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/cli/cli.py +0 -0
  94. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/cli/formatters.py +0 -0
  95. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/cli/logging_config.py +0 -0
  96. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/cli/main.py +0 -0
  97. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/cli/path_resolver.py +0 -0
  98. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/com_utils.py +0 -0
  99. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/commands/__init__.py +0 -0
  100. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/commands/abstract_command.py +0 -0
  101. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/commands/attribute_command.py +0 -0
  102. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/commands/class_command.py +0 -0
  103. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/commands/operation_command.py +0 -0
  104. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/commands/port_command.py +0 -0
  105. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/exceptions/__init__.py +0 -0
  106. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/exceptions/core.py +0 -0
  107. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/__init__.py +0 -0
  108. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/__init__.py +0 -0
  109. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/activity/__init__.py +0 -0
  110. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/common/__init__.py +0 -0
  111. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/containment/__init__.py +0 -0
  112. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/diagrams/__init__.py +0 -0
  113. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/graphics/__init__.py +0 -0
  114. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/interactions/__init__.py +0 -0
  115. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/relations/__init__.py +0 -0
  116. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/requirements/__init__.py +0 -0
  117. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/statemachine/__init__.py +0 -0
  118. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/templates/__init__.py +0 -0
  119. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/values/__init__.py +0 -0
  120. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/models/elements/variables/__init__.py +0 -0
  121. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli/py.typed +0 -0
  122. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli.egg-info/dependency_links.txt +0 -0
  123. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli.egg-info/entry_points.txt +0 -0
  124. {rhapsody_cli-0.1.0 → rhapsody_cli-0.2.0}/src/rhapsody_cli.egg-info/top_level.txt +0 -0
@@ -1,12 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rhapsody-cli
3
- Version: 0.1.0
3
+ Version: 0.2.0
4
4
  Summary: Pythonic wrapper around the IBM Rhapsody COM API, mirroring the Rhapsody Java API
5
5
  License: MIT
6
6
  Requires-Python: >=3.8
7
7
  Description-Content-Type: text/markdown
8
8
  License-File: LICENSE
9
9
  Requires-Dist: pywin32>=306; sys_platform == "win32"
10
+ Requires-Dist: PyYAML>=6.0
10
11
  Provides-Extra: dev
11
12
  Requires-Dist: pytest>=7.4; extra == "dev"
12
13
  Requires-Dist: pytest-cov>=4.1; extra == "dev"
@@ -20,7 +21,7 @@ Dynamic: license-file
20
21
 
21
22
  # rhapsody-cli
22
23
 
23
- [![Version](https://img.shields.io/badge/version-0.1.0-blue.svg)](https://github.com/user/rhapsody-cli)
24
+ [![Version](https://img.shields.io/badge/version-0.2.0-blue.svg)](https://github.com/user/rhapsody-cli)
24
25
  [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
25
26
  [![Python](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
26
27
  [![Platform](https://img.shields.io/badge/platform-Windows-lightgrey.svg)](https://www.microsoft.com/windows)
@@ -32,12 +33,12 @@ knowledge and documentation transfer directly.
32
33
 
33
34
  ## Features
34
35
 
35
- - **Complete API Mirroring**: Method names and signatures match the Rhapsody Java API exactly
36
+ - **Complete API Mirroring**: Method names and signatures match the Rhapsody Java API exactly (converted to snake_case)
36
37
  - **Object-Oriented Design**: Clean Python classes wrapping COM objects with proper type hints
37
- - **Comprehensive Element Support**: 50+ Rhapsody element types wrapped with full method coverage
38
- - **CLI Tools**: Command-line utilities for element management, I/O operations, and project handling
38
+ - **Comprehensive Element Support**: 96 Rhapsody element types wrapped with full method coverage
39
+ - **CLI Tools**: Command-line utilities for project, package, class, operation, attribute, port, export, and import management
39
40
  - **Multi-Level Path Navigation**: Navigate hierarchical model structures using `/` or `\` separators
40
- - **Bulk Operations**: Add multiple elements, query recursively, and delete with safety confirmations
41
+ - **Bulk Operations**: Create multiple elements, list recursively, and delete with safety confirmations
41
42
  - **Robust Error Handling**: Automatic COM error translation with user-friendly exception messages
42
43
  - **Mocked Testing**: Full test suite runs without Rhapsody installation or license
43
44
  - **Type Safety**: Strict mypy checking with comprehensive type annotations
@@ -84,12 +85,12 @@ app = RhapsodyApplication.connect()
84
85
  project = app.open_project(r"C:\Models\MyProject.rpy")
85
86
 
86
87
  # Create a new package
87
- package = project.addPackage("Sensors")
88
+ package = project.add_package("Sensors")
88
89
 
89
90
  # Add classes with attributes and operations
90
- sensor_class = package.addClass("TemperatureSensor")
91
- sensor_class.addAttribute("currentTemperature")
92
- sensor_class.addOperation("readTemperature")
91
+ sensor_class = package.add_class("TemperatureSensor")
92
+ sensor_class.add_attribute("currentTemperature")
93
+ sensor_class.add_operation("readTemperature")
93
94
 
94
95
  # Navigate existing elements
95
96
  for cls in project.get_nested_elements_by_meta_class("Class", 1): # recursive
@@ -104,57 +105,86 @@ app.quit()
104
105
 
105
106
  ### Command-Line Interface
106
107
 
107
- The CLI provides three main command groups:
108
+ The CLI provides eight command groups: `project`, `package`, `class`, `attribute`, `operation`, `port`, `export`, and `import`.
108
109
 
109
- #### Element Management
110
+ #### Project Management
110
111
 
111
112
  ```bash
112
- # Add elements with multi-level paths
113
- rhapsody-cli element add --type class --path "Sensors/TemperatureSensor"
114
- rhapsody-cli element add --type actor --path "System/User" --name "AdminUser"
113
+ # Create a new project
114
+ rhapsody-cli project new "C:\Models" NewProject
115
115
 
116
- # View element details (supports JSON, CSV, table output)
117
- rhapsody-cli element view --path "Sensors/TemperatureSensor" --output json
116
+ # Open an existing project
117
+ rhapsody-cli project open "C:\Models\MyProject.rpy"
118
+
119
+ # List open projects / close the active project
120
+ rhapsody-cli project list
121
+ rhapsody-cli project close
122
+ ```
118
123
 
119
- # Query elements with pattern matching
120
- rhapsody-cli element query "Sensor*" --output table
121
- rhapsody-cli element query --path "Sensors" --recursive
124
+ #### Package Management
122
125
 
123
- # Delete elements with safety confirmation
124
- rhapsody-cli element delete "Sensors/OldSensor"
126
+ ```bash
127
+ # Create a package (omit --path for a root package)
128
+ rhapsody-cli package create --path Sensors '{"name":"Actuators"}'
129
+
130
+ # View / list packages (supports table, json, csv output)
131
+ rhapsody-cli package view --path Sensors/Actuators --format json
132
+ rhapsody-cli package list --path Sensors --format table
133
+
134
+ # Update or delete a package
135
+ rhapsody-cli package update --path Sensors/Actuators '{"description":"Updated"}'
136
+ rhapsody-cli package delete --path Sensors/Actuators
125
137
  ```
126
138
 
127
- #### Project Management
139
+ #### Class Management
128
140
 
129
141
  ```bash
130
- # Create a new project
131
- rhapsody-cli project create --location "C:\Models" --name "NewProject"
142
+ rhapsody-cli class create --path Sensors '{"name":"TemperatureSensor"}'
143
+ rhapsody-cli class view --path Sensors/TemperatureSensor --format json
144
+ rhapsody-cli class list --path Sensors
145
+ rhapsody-cli class link --path Sensors/TemperatureSensor --add BaseSensor
146
+ rhapsody-cli class update --path Sensors/TemperatureSensor '{"isAbstract":true}'
147
+ rhapsody-cli class delete --path Sensors/TemperatureSensor
148
+ ```
149
+
150
+ #### Attribute, Operation, and Port Management
151
+
152
+ `attribute`, `operation`, and `port` share the same argument shape (`--path` to the owning classifier, `--name` or `--guid` to identify the member, and an inline/`--input` JSON payload):
132
153
 
133
- # Open existing project
134
- rhapsody-cli project open --file "C:\Models\MyProject.rpy"
154
+ ```bash
155
+ rhapsody-cli attribute create --path Sensors/TemperatureSensor '{"name":"threshold","type":"int"}'
156
+ rhapsody-cli operation create --path Sensors/TemperatureSensor '{"name":"readValue"}'
157
+ rhapsody-cli port create --path Sensors/TemperatureSensor '{"name":"clientPort"}'
135
158
 
136
- # Attach to active project in running Rhapsody
137
- rhapsody-cli project attach
159
+ rhapsody-cli attribute list --path Sensors/TemperatureSensor
160
+ rhapsody-cli attribute update --path Sensors/TemperatureSensor --name threshold '{"isStatic":true}'
161
+ rhapsody-cli attribute delete --path Sensors/TemperatureSensor --name threshold
138
162
  ```
139
163
 
140
- #### I/O Operations
164
+ #### Export and Import (YAML)
165
+
166
+ The `export` and `import` command groups serialize Rhapsody model elements to / from YAML:
141
167
 
142
168
  ```bash
143
- # Export model to various formats
144
- rhapsody-cli io export --format json --output model.json
169
+ # Export a project or package to a YAML file
170
+ rhapsody-cli export project --path MyProject "C:\Models\MyProject.yaml"
171
+ rhapsody-cli export package --path Sensors "C:\Models\Sensors.yaml"
145
172
 
146
- # Import model data
147
- rhapsody-cli io import --file import_data.json
173
+ # Import a previously exported YAML file back into Rhapsody
174
+ rhapsody-cli import project "C:\Models\MyProject.yaml"
175
+ rhapsody-cli import package "C:\Models\Sensors.yaml"
148
176
  ```
149
177
 
150
178
  ### Global Options
151
179
 
180
+ `--verbose`/`-v` and `--format {table,json,csv}` are specified **after** the command group name (most subcommands also accept a per-action `--output <file>`):
181
+
152
182
  ```bash
153
183
  # Enable verbose logging
154
- rhapsody-cli --verbose element query
184
+ rhapsody-cli class list --path Sensors --verbose
155
185
 
156
186
  # Specify output format
157
- rhapsody-cli --output json element view --path " MyClass"
187
+ rhapsody-cli package view --path Sensors --format json
158
188
  ```
159
189
 
160
190
  ### Multi-Instance Support
@@ -162,9 +192,10 @@ rhapsody-cli --output json element view --path " MyClass"
162
192
  ```python
163
193
  from rhapsody_cli import RhapsodyApplication
164
194
 
165
- # Manage multiple simultaneous Rhapsody instances
166
- app1 = RhapsodyApplication.attach() # Attach to first instance
167
- app2 = RhapsodyApplication.launch() # Launch second instance
195
+ # Manage multiple simultaneous Rhapsody instances via connect()
196
+ # (attach()/launch() are internal; connect() is the public entry point)
197
+ app1 = RhapsodyApplication.connect(attach_only=True) # Attach to a running instance
198
+ app2 = RhapsodyApplication.connect() # Attach, or launch a new one if none running
168
199
 
169
200
  project1 = app1.open_project("project1.rpy")
170
201
  project2 = app2.open_project("project2.rpy")
@@ -177,7 +208,7 @@ project2 = app2.open_project("project2.rpy")
177
208
  ### Running Tests
178
209
 
179
210
  ```bash
180
- # Run all unit tests (554 tests, no Rhapsody installation required)
211
+ # Run all unit tests (1621 tests, no Rhapsody installation required)
181
212
  pytest tests/unit
182
213
 
183
214
  # Run with coverage
@@ -205,8 +236,8 @@ pytest && ruff check src/ tests/ && black --check src/ tests/ && mypy src/ tests
205
236
 
206
237
  ### Test Coverage
207
238
 
208
- - **554 unit tests** covering all wrapped methods and edge cases
209
- - **Mocked COM objects** (`tests/fakes.py`) - no Rhapsody installation required
239
+ - **1621 unit tests** covering all wrapped methods and edge cases
240
+ - **Mocked COM objects** (`tests/unit/models/fakes.py`) - no Rhapsody installation required
210
241
  - **Integration tests** for real COM automation verification
211
242
  - **Branch coverage** tracking with 80% minimum threshold
212
243
 
@@ -236,7 +267,7 @@ RPModelElement (wraps IRPModelElement - base for all model elements)
236
267
  │ ├─ RPActor (wraps IRPActor)
237
268
  │ ├─ RPUseCase (wraps IRPUseCase)
238
269
  │ └─ ... (15+ classifier types)
239
- └─ ... (50+ total wrapped element types)
270
+ └─ ... (96 total wrapped element types)
240
271
  ```
241
272
 
242
273
  ### Adding New Element Types
@@ -334,7 +365,7 @@ The `docs/conf.py` configuration includes:
334
365
 
335
366
  ## Supported Rhapsody Elements
336
367
 
337
- The package currently wraps **50+ element types** including:
368
+ The package currently wraps **96 element types** including:
338
369
 
339
370
  **Containment Elements**: Project, Package, Profile, Module, Configuration, Node, Component, ComponentInstance, Collaboration
340
371
 
@@ -361,6 +392,18 @@ MIT License - see [LICENSE](LICENSE) file for details.
361
392
 
362
393
  ## Changelog
363
394
 
395
+ ### v0.2.0 (2026-07-20)
396
+
397
+ - **Breaking**: Renamed all wrapper methods from camelCase to snake_case (`addClass` → `add_class`, `getName` → `get_name`, etc.) for consistent Pythonic naming
398
+ - **Breaking**: Removed the generic `element` and `io` command groups in favor of dedicated per-type commands
399
+ - Added `package`, `class`, `operation`, `attribute`, and `port` command groups, each with `create`/`list`/`view`/`delete` subcommands (plus `update` for `package` and `class`, and `link` for `class` generalization)
400
+ - Added `RPPort` wrapper and `RPClassifier.add_port()` convenience method
401
+ - Added `export` and `import` command groups with `project`/`package` subcommands for YAML-based model exchange (RhapsodyExporter / RhapsodyImporter)
402
+ - Expanded wrapped element coverage from 50+ to **96** element types
403
+ - Enhanced package duplicate detection with clearer, user-friendly error messages
404
+ - Refactored CLI error handling to use logger + `CliExecutionError` instead of `print()`/`sys.exit()`
405
+ - Various Sphinx documentation and build-warning fixes
406
+
364
407
  ### v0.1.0 (2026-07-09)
365
408
 
366
409
  - Initial release with 50+ wrapped Rhapsody element types
@@ -1,6 +1,6 @@
1
1
  # rhapsody-cli
2
2
 
3
- [![Version](https://img.shields.io/badge/version-0.1.0-blue.svg)](https://github.com/user/rhapsody-cli)
3
+ [![Version](https://img.shields.io/badge/version-0.2.0-blue.svg)](https://github.com/user/rhapsody-cli)
4
4
  [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
5
5
  [![Python](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
6
6
  [![Platform](https://img.shields.io/badge/platform-Windows-lightgrey.svg)](https://www.microsoft.com/windows)
@@ -12,12 +12,12 @@ knowledge and documentation transfer directly.
12
12
 
13
13
  ## Features
14
14
 
15
- - **Complete API Mirroring**: Method names and signatures match the Rhapsody Java API exactly
15
+ - **Complete API Mirroring**: Method names and signatures match the Rhapsody Java API exactly (converted to snake_case)
16
16
  - **Object-Oriented Design**: Clean Python classes wrapping COM objects with proper type hints
17
- - **Comprehensive Element Support**: 50+ Rhapsody element types wrapped with full method coverage
18
- - **CLI Tools**: Command-line utilities for element management, I/O operations, and project handling
17
+ - **Comprehensive Element Support**: 96 Rhapsody element types wrapped with full method coverage
18
+ - **CLI Tools**: Command-line utilities for project, package, class, operation, attribute, port, export, and import management
19
19
  - **Multi-Level Path Navigation**: Navigate hierarchical model structures using `/` or `\` separators
20
- - **Bulk Operations**: Add multiple elements, query recursively, and delete with safety confirmations
20
+ - **Bulk Operations**: Create multiple elements, list recursively, and delete with safety confirmations
21
21
  - **Robust Error Handling**: Automatic COM error translation with user-friendly exception messages
22
22
  - **Mocked Testing**: Full test suite runs without Rhapsody installation or license
23
23
  - **Type Safety**: Strict mypy checking with comprehensive type annotations
@@ -64,12 +64,12 @@ app = RhapsodyApplication.connect()
64
64
  project = app.open_project(r"C:\Models\MyProject.rpy")
65
65
 
66
66
  # Create a new package
67
- package = project.addPackage("Sensors")
67
+ package = project.add_package("Sensors")
68
68
 
69
69
  # Add classes with attributes and operations
70
- sensor_class = package.addClass("TemperatureSensor")
71
- sensor_class.addAttribute("currentTemperature")
72
- sensor_class.addOperation("readTemperature")
70
+ sensor_class = package.add_class("TemperatureSensor")
71
+ sensor_class.add_attribute("currentTemperature")
72
+ sensor_class.add_operation("readTemperature")
73
73
 
74
74
  # Navigate existing elements
75
75
  for cls in project.get_nested_elements_by_meta_class("Class", 1): # recursive
@@ -84,57 +84,86 @@ app.quit()
84
84
 
85
85
  ### Command-Line Interface
86
86
 
87
- The CLI provides three main command groups:
87
+ The CLI provides eight command groups: `project`, `package`, `class`, `attribute`, `operation`, `port`, `export`, and `import`.
88
88
 
89
- #### Element Management
89
+ #### Project Management
90
90
 
91
91
  ```bash
92
- # Add elements with multi-level paths
93
- rhapsody-cli element add --type class --path "Sensors/TemperatureSensor"
94
- rhapsody-cli element add --type actor --path "System/User" --name "AdminUser"
92
+ # Create a new project
93
+ rhapsody-cli project new "C:\Models" NewProject
95
94
 
96
- # View element details (supports JSON, CSV, table output)
97
- rhapsody-cli element view --path "Sensors/TemperatureSensor" --output json
95
+ # Open an existing project
96
+ rhapsody-cli project open "C:\Models\MyProject.rpy"
97
+
98
+ # List open projects / close the active project
99
+ rhapsody-cli project list
100
+ rhapsody-cli project close
101
+ ```
98
102
 
99
- # Query elements with pattern matching
100
- rhapsody-cli element query "Sensor*" --output table
101
- rhapsody-cli element query --path "Sensors" --recursive
103
+ #### Package Management
102
104
 
103
- # Delete elements with safety confirmation
104
- rhapsody-cli element delete "Sensors/OldSensor"
105
+ ```bash
106
+ # Create a package (omit --path for a root package)
107
+ rhapsody-cli package create --path Sensors '{"name":"Actuators"}'
108
+
109
+ # View / list packages (supports table, json, csv output)
110
+ rhapsody-cli package view --path Sensors/Actuators --format json
111
+ rhapsody-cli package list --path Sensors --format table
112
+
113
+ # Update or delete a package
114
+ rhapsody-cli package update --path Sensors/Actuators '{"description":"Updated"}'
115
+ rhapsody-cli package delete --path Sensors/Actuators
105
116
  ```
106
117
 
107
- #### Project Management
118
+ #### Class Management
108
119
 
109
120
  ```bash
110
- # Create a new project
111
- rhapsody-cli project create --location "C:\Models" --name "NewProject"
121
+ rhapsody-cli class create --path Sensors '{"name":"TemperatureSensor"}'
122
+ rhapsody-cli class view --path Sensors/TemperatureSensor --format json
123
+ rhapsody-cli class list --path Sensors
124
+ rhapsody-cli class link --path Sensors/TemperatureSensor --add BaseSensor
125
+ rhapsody-cli class update --path Sensors/TemperatureSensor '{"isAbstract":true}'
126
+ rhapsody-cli class delete --path Sensors/TemperatureSensor
127
+ ```
128
+
129
+ #### Attribute, Operation, and Port Management
130
+
131
+ `attribute`, `operation`, and `port` share the same argument shape (`--path` to the owning classifier, `--name` or `--guid` to identify the member, and an inline/`--input` JSON payload):
112
132
 
113
- # Open existing project
114
- rhapsody-cli project open --file "C:\Models\MyProject.rpy"
133
+ ```bash
134
+ rhapsody-cli attribute create --path Sensors/TemperatureSensor '{"name":"threshold","type":"int"}'
135
+ rhapsody-cli operation create --path Sensors/TemperatureSensor '{"name":"readValue"}'
136
+ rhapsody-cli port create --path Sensors/TemperatureSensor '{"name":"clientPort"}'
115
137
 
116
- # Attach to active project in running Rhapsody
117
- rhapsody-cli project attach
138
+ rhapsody-cli attribute list --path Sensors/TemperatureSensor
139
+ rhapsody-cli attribute update --path Sensors/TemperatureSensor --name threshold '{"isStatic":true}'
140
+ rhapsody-cli attribute delete --path Sensors/TemperatureSensor --name threshold
118
141
  ```
119
142
 
120
- #### I/O Operations
143
+ #### Export and Import (YAML)
144
+
145
+ The `export` and `import` command groups serialize Rhapsody model elements to / from YAML:
121
146
 
122
147
  ```bash
123
- # Export model to various formats
124
- rhapsody-cli io export --format json --output model.json
148
+ # Export a project or package to a YAML file
149
+ rhapsody-cli export project --path MyProject "C:\Models\MyProject.yaml"
150
+ rhapsody-cli export package --path Sensors "C:\Models\Sensors.yaml"
125
151
 
126
- # Import model data
127
- rhapsody-cli io import --file import_data.json
152
+ # Import a previously exported YAML file back into Rhapsody
153
+ rhapsody-cli import project "C:\Models\MyProject.yaml"
154
+ rhapsody-cli import package "C:\Models\Sensors.yaml"
128
155
  ```
129
156
 
130
157
  ### Global Options
131
158
 
159
+ `--verbose`/`-v` and `--format {table,json,csv}` are specified **after** the command group name (most subcommands also accept a per-action `--output <file>`):
160
+
132
161
  ```bash
133
162
  # Enable verbose logging
134
- rhapsody-cli --verbose element query
163
+ rhapsody-cli class list --path Sensors --verbose
135
164
 
136
165
  # Specify output format
137
- rhapsody-cli --output json element view --path " MyClass"
166
+ rhapsody-cli package view --path Sensors --format json
138
167
  ```
139
168
 
140
169
  ### Multi-Instance Support
@@ -142,9 +171,10 @@ rhapsody-cli --output json element view --path " MyClass"
142
171
  ```python
143
172
  from rhapsody_cli import RhapsodyApplication
144
173
 
145
- # Manage multiple simultaneous Rhapsody instances
146
- app1 = RhapsodyApplication.attach() # Attach to first instance
147
- app2 = RhapsodyApplication.launch() # Launch second instance
174
+ # Manage multiple simultaneous Rhapsody instances via connect()
175
+ # (attach()/launch() are internal; connect() is the public entry point)
176
+ app1 = RhapsodyApplication.connect(attach_only=True) # Attach to a running instance
177
+ app2 = RhapsodyApplication.connect() # Attach, or launch a new one if none running
148
178
 
149
179
  project1 = app1.open_project("project1.rpy")
150
180
  project2 = app2.open_project("project2.rpy")
@@ -157,7 +187,7 @@ project2 = app2.open_project("project2.rpy")
157
187
  ### Running Tests
158
188
 
159
189
  ```bash
160
- # Run all unit tests (554 tests, no Rhapsody installation required)
190
+ # Run all unit tests (1621 tests, no Rhapsody installation required)
161
191
  pytest tests/unit
162
192
 
163
193
  # Run with coverage
@@ -185,8 +215,8 @@ pytest && ruff check src/ tests/ && black --check src/ tests/ && mypy src/ tests
185
215
 
186
216
  ### Test Coverage
187
217
 
188
- - **554 unit tests** covering all wrapped methods and edge cases
189
- - **Mocked COM objects** (`tests/fakes.py`) - no Rhapsody installation required
218
+ - **1621 unit tests** covering all wrapped methods and edge cases
219
+ - **Mocked COM objects** (`tests/unit/models/fakes.py`) - no Rhapsody installation required
190
220
  - **Integration tests** for real COM automation verification
191
221
  - **Branch coverage** tracking with 80% minimum threshold
192
222
 
@@ -216,7 +246,7 @@ RPModelElement (wraps IRPModelElement - base for all model elements)
216
246
  │ ├─ RPActor (wraps IRPActor)
217
247
  │ ├─ RPUseCase (wraps IRPUseCase)
218
248
  │ └─ ... (15+ classifier types)
219
- └─ ... (50+ total wrapped element types)
249
+ └─ ... (96 total wrapped element types)
220
250
  ```
221
251
 
222
252
  ### Adding New Element Types
@@ -314,7 +344,7 @@ The `docs/conf.py` configuration includes:
314
344
 
315
345
  ## Supported Rhapsody Elements
316
346
 
317
- The package currently wraps **50+ element types** including:
347
+ The package currently wraps **96 element types** including:
318
348
 
319
349
  **Containment Elements**: Project, Package, Profile, Module, Configuration, Node, Component, ComponentInstance, Collaboration
320
350
 
@@ -341,6 +371,18 @@ MIT License - see [LICENSE](LICENSE) file for details.
341
371
 
342
372
  ## Changelog
343
373
 
374
+ ### v0.2.0 (2026-07-20)
375
+
376
+ - **Breaking**: Renamed all wrapper methods from camelCase to snake_case (`addClass` → `add_class`, `getName` → `get_name`, etc.) for consistent Pythonic naming
377
+ - **Breaking**: Removed the generic `element` and `io` command groups in favor of dedicated per-type commands
378
+ - Added `package`, `class`, `operation`, `attribute`, and `port` command groups, each with `create`/`list`/`view`/`delete` subcommands (plus `update` for `package` and `class`, and `link` for `class` generalization)
379
+ - Added `RPPort` wrapper and `RPClassifier.add_port()` convenience method
380
+ - Added `export` and `import` command groups with `project`/`package` subcommands for YAML-based model exchange (RhapsodyExporter / RhapsodyImporter)
381
+ - Expanded wrapped element coverage from 50+ to **96** element types
382
+ - Enhanced package duplicate detection with clearer, user-friendly error messages
383
+ - Refactored CLI error handling to use logger + `CliExecutionError` instead of `print()`/`sys.exit()`
384
+ - Various Sphinx documentation and build-warning fixes
385
+
344
386
  ### v0.1.0 (2026-07-09)
345
387
 
346
388
  - Initial release with 50+ wrapped Rhapsody element types
@@ -4,13 +4,14 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "rhapsody-cli"
7
- version = "0.1.0"
7
+ version = "0.2.0"
8
8
  description = "Pythonic wrapper around the IBM Rhapsody COM API, mirroring the Rhapsody Java API"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
11
11
  license = { text = "MIT" }
12
12
  dependencies = [
13
13
  "pywin32>=306; sys_platform == 'win32'",
14
+ "PyYAML>=6.0",
14
15
  ]
15
16
 
16
17
  [project.optional-dependencies]
@@ -63,8 +64,16 @@ ignore_missing_imports = true
63
64
  module = "pywintypes"
64
65
  ignore_missing_imports = true
65
66
 
67
+ [[tool.mypy.overrides]]
68
+ module = "yaml"
69
+ ignore_missing_imports = true
70
+
66
71
  [tool.pytest.ini_options]
67
72
  testpaths = ["tests"]
73
+ markers = [
74
+ "integration: marks tests as integration tests (require Rhapsody)",
75
+ "system: marks tests as system tests (subprocess CLI, require Rhapsody)",
76
+ ]
68
77
  addopts = [
69
78
  "--cov=rhapsody_cli",
70
79
  "--cov-report=term-missing",
@@ -563,7 +563,8 @@ class ClassLinkAction(AbstractClassAction):
563
563
  source = self._resolve_and_validate_class(args.path)
564
564
 
565
565
  target_name = args.add if args.add else args.remove
566
- target = source.find_nested_classifier_recursive(target_name)
566
+ owner = source.get_owner()
567
+ target = owner.find_nested_classifier_recursive(target_name)
567
568
  if target is None:
568
569
  raise CliExecutionError(f"Class '{target_name}' not found")
569
570
 
@@ -21,7 +21,10 @@ from typing import Any, Dict, List, cast
21
21
 
22
22
  from rhapsody_cli.actions.abstract_action import ElementManagementAction
23
23
  from rhapsody_cli.cli.formatters import OutputFormatter
24
- from rhapsody_cli.exceptions import CliExecutionError
24
+ from rhapsody_cli.exceptions import CliExecutionError, RhapsodyConnectionError
25
+ from rhapsody_cli.exchange.exporter import RhapsodyExporter
26
+ from rhapsody_cli.exchange.importer import RhapsodyImporter
27
+ from rhapsody_cli.exchange.yaml_utils import RhapsodyYaml
25
28
 
26
29
  logger = logging.getLogger(__name__)
27
30
 
@@ -590,3 +593,68 @@ class PackageUpdateAction(AbstractPackageAction):
590
593
  data = self._load_json_data(args)
591
594
  self._set_attributes(package, data)
592
595
  self.logger.info("Successfully updated package: %s", package.get_name())
596
+
597
+
598
+ class PackageExportAction(AbstractPackageAction):
599
+ """Action for `package export` — exports a package to a YAML file.
600
+
601
+ SWR_XCH_001: Import/Export CLI Actions
602
+ """
603
+
604
+ def __init__(self) -> None:
605
+ super().__init__(command_id="export")
606
+
607
+ def init_arguments(self, sub_parser: "argparse._SubParsersAction[argparse.ArgumentParser]") -> None:
608
+ parser = sub_parser.add_parser(self.command_id, help="Export a package to a YAML file")
609
+ self.add_path_argument(parser, required=False, help_text="Path to package (defaults to root)")
610
+ parser.add_argument("--file", required=True, help="Output YAML file path")
611
+ self.add_verbose_argument(parser)
612
+
613
+ def execute(self, args: argparse.Namespace) -> None:
614
+ try:
615
+ app = self._connect_app()
616
+ package = self._resolve_and_validate_package(args.path)
617
+ exporter = RhapsodyExporter(app=app)
618
+ data = exporter.export(package)
619
+ yaml_io = RhapsodyYaml()
620
+ yaml_io.write(args.file, data)
621
+ self.logger.info("Exported package to %s", args.file)
622
+ except RhapsodyConnectionError as e:
623
+ self._handle_connection_error(e, "export package")
624
+ except CliExecutionError:
625
+ raise
626
+ except Exception as e:
627
+ self._handle_execution_error(e, "export package")
628
+
629
+
630
+ class PackageImportAction(AbstractPackageAction):
631
+ """Action for `package import` — imports a YAML file into a package.
632
+
633
+ SWR_XCH_001: Import/Export CLI Actions
634
+ """
635
+
636
+ def __init__(self) -> None:
637
+ super().__init__(command_id="import")
638
+
639
+ def init_arguments(self, sub_parser: "argparse._SubParsersAction[argparse.ArgumentParser]") -> None:
640
+ parser = sub_parser.add_parser(self.command_id, help="Import a YAML file into a package")
641
+ self.add_path_argument(parser, required=False, help_text="Path to target package (defaults to root)")
642
+ parser.add_argument("--file", required=True, help="Input YAML file path")
643
+ self.add_verbose_argument(parser)
644
+
645
+ def execute(self, args: argparse.Namespace) -> None:
646
+ try:
647
+ app = self._connect_app()
648
+ package = self._resolve_and_validate_package(args.path)
649
+ yaml_io = RhapsodyYaml()
650
+ data = yaml_io.read(args.file)
651
+ importer = RhapsodyImporter(app=app)
652
+ importer.import_template(data, package)
653
+ app.save_all()
654
+ self.logger.info("Imported %s into package", args.file)
655
+ except RhapsodyConnectionError as e:
656
+ self._handle_connection_error(e, "import package")
657
+ except CliExecutionError:
658
+ raise
659
+ except Exception as e:
660
+ self._handle_execution_error(e, "import package")