buildzr 0.0.17__tar.gz → 0.0.18__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 (46) hide show
  1. {buildzr-0.0.17 → buildzr-0.0.18}/PKG-INFO +1 -1
  2. buildzr-0.0.18/buildzr/__about__.py +1 -0
  3. {buildzr-0.0.17 → buildzr-0.0.18}/buildzr/dsl/dsl.py +7 -0
  4. {buildzr-0.0.17 → buildzr-0.0.18}/tests/test_dsl.py +84 -1
  5. {buildzr-0.0.17 → buildzr-0.0.18}/tests/test_explorer.py +2 -2
  6. buildzr-0.0.17/buildzr/__about__.py +0 -1
  7. {buildzr-0.0.17 → buildzr-0.0.18}/.gitignore +0 -0
  8. {buildzr-0.0.17 → buildzr-0.0.18}/CONTRIBUTING.md +0 -0
  9. {buildzr-0.0.17 → buildzr-0.0.18}/LICENSE.md +0 -0
  10. {buildzr-0.0.17 → buildzr-0.0.18}/README.md +0 -0
  11. {buildzr-0.0.17 → buildzr-0.0.18}/buildzr/__init__.py +0 -0
  12. {buildzr-0.0.17 → buildzr-0.0.18}/buildzr/dsl/__init__.py +0 -0
  13. {buildzr-0.0.17 → buildzr-0.0.18}/buildzr/dsl/color.py +0 -0
  14. {buildzr-0.0.17 → buildzr-0.0.18}/buildzr/dsl/explorer.py +0 -0
  15. {buildzr-0.0.17 → buildzr-0.0.18}/buildzr/dsl/expression.py +0 -0
  16. {buildzr-0.0.17 → buildzr-0.0.18}/buildzr/dsl/factory/__init__.py +0 -0
  17. {buildzr-0.0.17 → buildzr-0.0.18}/buildzr/dsl/factory/gen_id.py +0 -0
  18. {buildzr-0.0.17 → buildzr-0.0.18}/buildzr/dsl/interfaces/__init__.py +0 -0
  19. {buildzr-0.0.17 → buildzr-0.0.18}/buildzr/dsl/interfaces/interfaces.py +0 -0
  20. {buildzr-0.0.17 → buildzr-0.0.18}/buildzr/dsl/relations.py +0 -0
  21. {buildzr-0.0.17 → buildzr-0.0.18}/buildzr/encoders/__init__.py +0 -0
  22. {buildzr-0.0.17 → buildzr-0.0.18}/buildzr/encoders/encoder.py +0 -0
  23. {buildzr-0.0.17 → buildzr-0.0.18}/buildzr/models/__init__.py +0 -0
  24. {buildzr-0.0.17 → buildzr-0.0.18}/buildzr/models/generate.sh +0 -0
  25. {buildzr-0.0.17 → buildzr-0.0.18}/buildzr/models/models.py +0 -0
  26. {buildzr-0.0.17 → buildzr-0.0.18}/buildzr/sinks/__init__.py +0 -0
  27. {buildzr-0.0.17 → buildzr-0.0.18}/buildzr/sinks/interfaces.py +0 -0
  28. {buildzr-0.0.17 → buildzr-0.0.18}/buildzr/sinks/json_sink.py +0 -0
  29. {buildzr-0.0.17 → buildzr-0.0.18}/pyproject.toml +0 -0
  30. {buildzr-0.0.17 → buildzr-0.0.18}/tests/__init__.py +0 -0
  31. {buildzr-0.0.17 → buildzr-0.0.18}/tests/abstract_builder.py +0 -0
  32. {buildzr-0.0.17 → buildzr-0.0.18}/tests/samples/__init__.py +0 -0
  33. {buildzr-0.0.17 → buildzr-0.0.18}/tests/samples/component_view.py +0 -0
  34. {buildzr-0.0.17 → buildzr-0.0.18}/tests/samples/container_view.py +0 -0
  35. {buildzr-0.0.17 → buildzr-0.0.18}/tests/samples/container_view_sugar.py +0 -0
  36. {buildzr-0.0.17 → buildzr-0.0.18}/tests/samples/groups.py +0 -0
  37. {buildzr-0.0.17 → buildzr-0.0.18}/tests/samples/implied_relationships.py +0 -0
  38. {buildzr-0.0.17 → buildzr-0.0.18}/tests/samples/nested_groups.py +0 -0
  39. {buildzr-0.0.17 → buildzr-0.0.18}/tests/samples/simple.py +0 -0
  40. {buildzr-0.0.17 → buildzr-0.0.18}/tests/samples/simple_dsl.py +0 -0
  41. {buildzr-0.0.17 → buildzr-0.0.18}/tests/samples/system_context_view.py +0 -0
  42. {buildzr-0.0.17 → buildzr-0.0.18}/tests/samples/system_landscape_view.py +0 -0
  43. {buildzr-0.0.17 → buildzr-0.0.18}/tests/test_expression.py +0 -0
  44. {buildzr-0.0.17 → buildzr-0.0.18}/tests/test_typehints.py +0 -0
  45. {buildzr-0.0.17 → buildzr-0.0.18}/tests/test_views.py +0 -0
  46. {buildzr-0.0.17 → buildzr-0.0.18}/tests/test_workspaces.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: buildzr
3
- Version: 0.0.17
3
+ Version: 0.0.18
4
4
  Summary: Structurizr for the `buildzr`s 🧱⚒️
5
5
  Project-URL: homepage, https://github.com/amirulmenjeni/buildzr
6
6
  Project-URL: issues, https://github.com/amirulmenjeni/buildzr/issues
@@ -0,0 +1 @@
1
+ VERSION = "0.0.18"
@@ -139,6 +139,9 @@ class Workspace(DslWorkspaceElement):
139
139
  If we have relationship s.ss >> do >> a.b.c, then create s.ss >> do >> a.b and s.ss >> do >> a.
140
140
  And so on...
141
141
 
142
+ Relationships of `SoftwareSystemInstance`s and `ContainerInstance`s are
143
+ skipped.
144
+
142
145
  This process is idempotent, which means this can be called multiple times
143
146
  without duplicating similar relationships.
144
147
  """
@@ -155,6 +158,10 @@ class Workspace(DslWorkspaceElement):
155
158
  destination = relationship.destination
156
159
  destination_parent = destination.parent
157
160
 
161
+ if isinstance(source, (SoftwareSystemInstance, ContainerInstance)) or \
162
+ isinstance(destination, (SoftwareSystemInstance, ContainerInstance)):
163
+ continue
164
+
158
165
  while destination_parent is not None and \
159
166
  isinstance(source, DslElement) and \
160
167
  not isinstance(source.model, buildzr.models.Workspace) and \
@@ -15,6 +15,7 @@ from buildzr.dsl import (
15
15
  SystemContextView,
16
16
  DeploymentEnvironment,
17
17
  DeploymentNode,
18
+ DeploymentView,
18
19
  InfrastructureNode,
19
20
  DeploymentGroup,
20
21
  SoftwareSystemInstance,
@@ -394,6 +395,10 @@ def test_implied_relationship() -> Optional[None]:
394
395
  assert w.u.model.relationships[1].id in system_context_view_relationships
395
396
  assert w.u.model.relationships[1].linkedRelationshipId == w.u.model.relationships[0].id
396
397
 
398
+ import os
399
+ os.remove('workspace.test.json')
400
+ os.remove('workspace2.test.json')
401
+
397
402
  def test_tags_on_elements() -> Optional[None]:
398
403
 
399
404
  u = Person('My User', tags={'admin'})
@@ -1099,4 +1104,82 @@ def test_json_sink_empty_views() -> Optional[None]:
1099
1104
  assert data
1100
1105
 
1101
1106
  import os
1102
- os.remove("test.json")
1107
+ os.remove("test.json")
1108
+ def test_deployment_instance_relationships_with_implied_relationships() -> Optional[None]:
1109
+ """
1110
+ Test that deployment instance relationships are created correctly when
1111
+ implied_relationships=True, without creating duplicates.
1112
+
1113
+ This test ensures:
1114
+ 1. Container relationships automatically create ContainerInstance relationships
1115
+ 2. No duplicate instance relationships are created when implied_relationships=True
1116
+ 3. Instance relationships are only created once, even with multiple view/export calls
1117
+ """
1118
+
1119
+ with Workspace('deployment-test', implied_relationships=True) as w:
1120
+ # Create containers with relationships
1121
+ ecommerce = SoftwareSystem('E-Commerce System')
1122
+ with ecommerce:
1123
+ api_gateway = Container('API Gateway', technology='Kong')
1124
+ order_svc = Container('Order Service', technology='Node.js')
1125
+ db = Container('Database', technology='MongoDB')
1126
+
1127
+ # Define container relationships
1128
+ api_gateway >> "Routes to" >> order_svc
1129
+ order_svc >> "Stores in" >> db
1130
+
1131
+ # Create deployment with container instances
1132
+ with DeploymentEnvironment('Production') as prod:
1133
+ with DeploymentNode('AWS', technology='Cloud Provider'):
1134
+ api_gw_instance = ContainerInstance(api_gateway)
1135
+ order_instance = ContainerInstance(order_svc)
1136
+ db_instance = ContainerInstance(db)
1137
+
1138
+ # Create views and export (triggers implied relationships multiple times)
1139
+ SystemContextView(
1140
+ software_system_selector=ecommerce,
1141
+ key='test-system-context',
1142
+ description="Test System Context",
1143
+ )
1144
+
1145
+ DeploymentView(
1146
+ environment=prod,
1147
+ key='test-deployment',
1148
+ )
1149
+
1150
+ # Export multiple times to ensure idempotency
1151
+ w.to_json('test_deployment1.json')
1152
+ w.to_json('test_deployment2.json')
1153
+
1154
+ # Verify instance relationships exist
1155
+ assert api_gw_instance.model.relationships is not None
1156
+ assert order_instance.model.relationships is not None
1157
+
1158
+ # Get all instance relationships
1159
+ api_gw_rels = api_gw_instance.model.relationships
1160
+ order_rels = order_instance.model.relationships
1161
+
1162
+ # Should have exactly 1 relationship from api_gw_instance to order_instance
1163
+ api_to_order_rels = [
1164
+ r for r in api_gw_rels
1165
+ if r.destinationId == order_instance.model.id
1166
+ ]
1167
+ assert len(api_to_order_rels) == 1, f"Expected 1 relationship, found {len(api_to_order_rels)}"
1168
+ assert api_to_order_rels[0].description == "Routes to"
1169
+
1170
+ # Should have exactly 1 relationship from order_instance to db_instance
1171
+ order_to_db_rels = [
1172
+ r for r in order_rels
1173
+ if r.destinationId == db_instance.model.id
1174
+ ]
1175
+ assert len(order_to_db_rels) == 1, f"Expected 1 relationship, found {len(order_to_db_rels)}"
1176
+ assert order_to_db_rels[0].description == "Stores in"
1177
+
1178
+ # Verify linkedRelationshipId is set correctly
1179
+ assert api_to_order_rels[0].linkedRelationshipId is not None
1180
+ assert order_to_db_rels[0].linkedRelationshipId is not None
1181
+
1182
+ # Clean up
1183
+ import os
1184
+ os.remove('test_deployment1.json')
1185
+ os.remove('test_deployment2.json')
@@ -90,7 +90,7 @@ def test_walk_relationships(workspace: Workspace) -> Optional[None]:
90
90
 
91
91
  # 5 explicit relationships.
92
92
  # Add one additional implied relationship.
93
- # And four additional from container instances for each two container instance (2x2=4 + 2x2=4 more).
93
+ # And four additional from container instances for each two container instance (2x2=4).
94
94
  #
95
95
  # Explanation: if we have containers A and B with relationship A >> "Uses" >> B,
96
96
  # and container instances ci_A_1, ci_A_2, ci_B_1, ci_B_2, then we have the
@@ -99,7 +99,7 @@ def test_walk_relationships(workspace: Workspace) -> Optional[None]:
99
99
  # ci_A_1 >> "Uses" >> ci_B_2
100
100
  # ci_A_2 >> "Uses" >> ci_B_1
101
101
  # ci_A_2 >> "Uses" >> ci_B_2
102
- assert len(relationships) == 14
102
+ assert len(relationships) == 10
103
103
 
104
104
  for relationship in relationships:
105
105
  relationship_set = (
@@ -1 +0,0 @@
1
- VERSION = "0.0.17"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes