sysmlpy 0.48.0__tar.gz → 0.50.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 (148) hide show
  1. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/PKG-INFO +1 -1
  2. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/pyproject.toml +1 -1
  3. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/__init__.py +1 -1
  4. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/antlr_visitor.py +117 -4
  5. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/grammar/classes.py +26 -9
  6. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/LICENSE +0 -0
  7. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/README.md +0 -0
  8. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/__main__.py +0 -0
  9. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/antlr/README.md +0 -0
  10. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/antlr/SysMLv2Lexer.interp +0 -0
  11. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/antlr/SysMLv2Lexer.py +0 -0
  12. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/antlr/SysMLv2Lexer.tokens +0 -0
  13. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/antlr/SysMLv2Parser.interp +0 -0
  14. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/antlr/SysMLv2Parser.py +0 -0
  15. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/antlr/SysMLv2Parser.tokens +0 -0
  16. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/antlr/SysMLv2ParserListener.py +0 -0
  17. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/antlr/SysMLv2ParserVisitor.py +0 -0
  18. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.interp +0 -0
  19. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.py +0 -0
  20. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.tokens +0 -0
  21. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/antlr_parser.py +0 -0
  22. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/boxes_view.py +0 -0
  23. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/definition.py +0 -0
  24. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/examples/attribute_values.py +0 -0
  25. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/examples/part_attributes.py +0 -0
  26. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/examples/tuples_sequences.py +0 -0
  27. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/formatting.py +0 -0
  28. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/grammar/antlr4/README.md +0 -0
  29. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.g4 +0 -0
  30. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.interp +0 -0
  31. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.py +0 -0
  32. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.tokens +0 -0
  33. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.g4 +0 -0
  34. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.interp +0 -0
  35. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.py +0 -0
  36. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.tokens +0 -0
  37. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/grammar/antlr4/SysMLv2ParserListener.py +0 -0
  38. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/grammar/antlr4/SysMLv2ParserVisitor.py +0 -0
  39. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/grammar/antlr4/desc.xml +0 -0
  40. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/grammar/antlr4/examples/camera.sysml +0 -0
  41. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/grammar/antlr4/examples/toaster-system.sysml +0 -0
  42. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/grammar/antlr4/examples/vehicle-model.sysml +0 -0
  43. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/grammar/antlr4/pom.xml +0 -0
  44. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/LICENSE +0 -0
  45. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/README.md +0 -0
  46. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/__init__.py +0 -0
  47. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Analysis/AnalysisTooling.sysml +0 -0
  48. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Analysis/SampledFunctions.sysml +0 -0
  49. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Analysis/StateSpaceRepresentation.sysml +0 -0
  50. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Analysis/TradeStudies.sysml +0 -0
  51. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Cause and Effect/CausationConnections.sysml +0 -0
  52. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Cause and Effect/CauseAndEffect.sysml +0 -0
  53. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Geometry/ShapeItems.sysml +0 -0
  54. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Geometry/SpatialItems.sysml +0 -0
  55. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Metadata/ImageMetadata.sysml +0 -0
  56. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Metadata/ModelingMetadata.sysml +0 -0
  57. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Metadata/ParametersOfInterestMetadata.sysml +0 -0
  58. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Metadata/RiskMetadata.sysml +0 -0
  59. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Quantities and Units/ISQ.sysml +0 -0
  60. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Quantities and Units/ISQAcoustics.sysml +0 -0
  61. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Quantities and Units/ISQAtomicNuclear.sysml +0 -0
  62. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Quantities and Units/ISQBase.sysml +0 -0
  63. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Quantities and Units/ISQCharacteristicNumbers.sysml +0 -0
  64. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Quantities and Units/ISQChemistryMolecular.sysml +0 -0
  65. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Quantities and Units/ISQCondensedMatter.sysml +0 -0
  66. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Quantities and Units/ISQElectromagnetism.sysml +0 -0
  67. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Quantities and Units/ISQInformation.sysml +0 -0
  68. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Quantities and Units/ISQLight.sysml +0 -0
  69. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Quantities and Units/ISQMechanics.sysml +0 -0
  70. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Quantities and Units/ISQSpaceTime.sysml +0 -0
  71. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Quantities and Units/ISQThermodynamics.sysml +0 -0
  72. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Quantities and Units/MeasurementRefCalculations.sysml +0 -0
  73. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Quantities and Units/MeasurementReferences.sysml +0 -0
  74. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Quantities and Units/Quantities.sysml +0 -0
  75. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Quantities and Units/QuantityCalculations.sysml +0 -0
  76. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Quantities and Units/SI.sysml +0 -0
  77. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Quantities and Units/SIPrefixes.sysml +0 -0
  78. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Quantities and Units/TensorCalculations.sysml +0 -0
  79. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Quantities and Units/Time.sysml +0 -0
  80. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Quantities and Units/USCustomaryUnits.sysml +0 -0
  81. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Quantities and Units/VectorCalculations.sysml +0 -0
  82. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Requirement Derivation/DerivationConnections.sysml +0 -0
  83. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/domain/Requirement Derivation/RequirementDerivation.sysml +0 -0
  84. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/Base.kerml +0 -0
  85. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/BaseFunctions.kerml +0 -0
  86. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/BooleanFunctions.kerml +0 -0
  87. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/Clocks.kerml +0 -0
  88. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/CollectionFunctions.kerml +0 -0
  89. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/Collections.kerml +0 -0
  90. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/ComplexFunctions.kerml +0 -0
  91. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/ControlFunctions.kerml +0 -0
  92. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/ControlPerformances.kerml +0 -0
  93. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/DataFunctions.kerml +0 -0
  94. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/FeatureReferencingPerformances.kerml +0 -0
  95. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/IntegerFunctions.kerml +0 -0
  96. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/KerML.kerml +0 -0
  97. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/Links.kerml +0 -0
  98. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/Metaobjects.kerml +0 -0
  99. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/NaturalFunctions.kerml +0 -0
  100. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/NumericalFunctions.kerml +0 -0
  101. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/Objects.kerml +0 -0
  102. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/Observation.kerml +0 -0
  103. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/OccurrenceFunctions.kerml +0 -0
  104. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/Occurrences.kerml +0 -0
  105. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/Performances.kerml +0 -0
  106. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/RationalFunctions.kerml +0 -0
  107. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/RealFunctions.kerml +0 -0
  108. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/ScalarFunctions.kerml +0 -0
  109. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/ScalarValues.kerml +0 -0
  110. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/SequenceFunctions.kerml +0 -0
  111. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/SpatialFrames.kerml +0 -0
  112. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/StatePerformances.kerml +0 -0
  113. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/StringFunctions.kerml +0 -0
  114. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/Transfers.kerml +0 -0
  115. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/TransitionPerformances.kerml +0 -0
  116. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/TrigFunctions.kerml +0 -0
  117. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/Triggers.kerml +0 -0
  118. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/VectorFunctions.kerml +0 -0
  119. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/kernel/VectorValues.kerml +0 -0
  120. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/systems/Actions.sysml +0 -0
  121. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/systems/Allocations.sysml +0 -0
  122. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/systems/AnalysisCases.sysml +0 -0
  123. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/systems/Attributes.sysml +0 -0
  124. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/systems/Calculations.sysml +0 -0
  125. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/systems/Cases.sysml +0 -0
  126. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/systems/Connections.sysml +0 -0
  127. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/systems/Constraints.sysml +0 -0
  128. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/systems/Flows.sysml +0 -0
  129. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/systems/Interfaces.sysml +0 -0
  130. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/systems/Items.sysml +0 -0
  131. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/systems/Metadata.sysml +0 -0
  132. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/systems/Parts.sysml +0 -0
  133. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/systems/Ports.sysml +0 -0
  134. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/systems/Requirements.sysml +0 -0
  135. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/systems/StandardViewDefinitions.sysml +0 -0
  136. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/systems/States.sysml +0 -0
  137. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/systems/SysML.sysml +0 -0
  138. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/systems/UseCases.sysml +0 -0
  139. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/systems/VerificationCases.sysml +0 -0
  140. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/library/systems/Views.sysml +0 -0
  141. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/navigate.py +0 -0
  142. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/plantuml.py +0 -0
  143. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/project.py +0 -0
  144. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/semantic.py +0 -0
  145. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/store.py +0 -0
  146. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/us_customary_units.txt +0 -0
  147. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/usage.py +0 -0
  148. {sysmlpy-0.48.0 → sysmlpy-0.50.0}/src/sysmlpy/validator.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sysmlpy
3
- Version: 0.48.0
3
+ Version: 0.50.0
4
4
  Summary:
5
5
  License-File: LICENSE
6
6
  Author: Jon R. Fox (mycr0ft)
@@ -6,7 +6,7 @@ build-backend = "poetry.core.masonry.api"
6
6
 
7
7
  [project]
8
8
  name = "sysmlpy"
9
- version = "0.48.0"
9
+ version = "0.50.0"
10
10
  description = ""
11
11
  authors = [{ name = "Jon R. Fox (mycr0ft)", email = "jon.fox@drfox.com" }]
12
12
  readme = "README.md"
@@ -25,7 +25,7 @@ __all__ = [
25
25
  "render_state_transition_view_svg", "boxes_view",
26
26
  ]
27
27
  __author__ = "Jon Fox"
28
- __version__ = "0.48.0"
28
+ __version__ = "0.50.0"
29
29
 
30
30
  from sysmlpy.usage import (
31
31
  Item, Attribute, Part, Port, Action, Reference, UseCase, Requirement, Interface, Message,
@@ -314,6 +314,7 @@ def _visit_metadata_feature_dict(ctx):
314
314
  })
315
315
 
316
316
  body = ""
317
+ body_features = []
317
318
  if ctx.metadataBody():
318
319
  if ctx.metadataBody().SEMI():
319
320
  body = ";"
@@ -323,14 +324,124 @@ def _visit_metadata_feature_dict(ctx):
323
324
  # the round-trip. Without this, every `key = value;` inside
324
325
  # a metadata application is silently dropped at visit time.
325
326
  body = ctx.metadataBody().getText()
326
-
327
+ # Issue #8: also surface each metadataBodyElement as a
328
+ # structured bodyFeatures entry so downstream consumers
329
+ # (sysml2kit, validators, etc.) can read individual
330
+ # key = value fields without re-parsing the raw text.
331
+ # Mirrors the per-endpoint capture introduced for issue #5.
332
+ body_features = _visit_metadata_body_features(ctx.metadataBody())
333
+
327
334
  return {
328
335
  "name": "MetadataFeature",
329
336
  "prefixMetadataMember": prefix_members,
330
337
  "identification": identification,
331
338
  "ownedFeatureTyping": owned_feature_typing,
332
339
  "ownedRelationship_about": annotations,
333
- "body": body
340
+ "body": body,
341
+ "bodyFeatures": body_features,
342
+ }
343
+
344
+
345
+ def _visit_metadata_body_features(mb_ctx):
346
+ """Capture each ``metadataBodyElement`` from a braced metadata body.
347
+
348
+ Issue #8: ``_visit_metadata_feature_dict`` previously emitted the
349
+ raw body text but never surfaced the individual ``key = value;``
350
+ items, so consumers of ``load_grammar_antlr`` had no way to read
351
+ the field assignments without re-parsing the raw text.
352
+
353
+ The emitted ``bodyFeatures`` list contains one dict per
354
+ ``metadataBodyElement``. For the common ``metadataBodyFeature``
355
+ case each entry carries ``name`` (the feature name from
356
+ ``ownedRedefinition``), ``value`` (the raw ``=value`` text from
357
+ ``valuePart``), and ``text`` (the full source text of the
358
+ element). For the heterogeneous alternative
359
+ (``definitionMember | metadataBodyUsageMember | aliasMember |
360
+ importRule``) only ``text`` is captured.
361
+ """
362
+ if mb_ctx is None:
363
+ return []
364
+
365
+ features = []
366
+
367
+ # First alternative: metadataBodyElement list (the common path).
368
+ if hasattr(mb_ctx, 'metadataBodyElement') and mb_ctx.metadataBodyElement():
369
+ for elem in mb_ctx.metadataBodyElement():
370
+ entry = _visit_metadata_body_element(elem)
371
+ if entry is not None:
372
+ features.append(entry)
373
+
374
+ # Second alternative: heterogeneous (definitionMember |
375
+ # metadataBodyUsageMember | aliasMember | importRule). ANTLR
376
+ # matches exactly one of the two alternatives; if the first
377
+ # alternative returned nothing, try the heterogeneous shapes.
378
+ if not features:
379
+ for attr in ('definitionMember', 'metadataBodyUsageMember',
380
+ 'aliasMember', 'importRule'):
381
+ if hasattr(mb_ctx, attr) and getattr(mb_ctx, attr)():
382
+ items = getattr(mb_ctx, attr)()
383
+ if not isinstance(items, list):
384
+ items = [items]
385
+ for item in items:
386
+ features.append({
387
+ "name": None,
388
+ "value": None,
389
+ "text": item.getText(),
390
+ })
391
+
392
+ return features
393
+
394
+
395
+ def _visit_metadata_body_element(elem_ctx):
396
+ """Capture a single ``metadataBodyElement`` as a bodyFeatures entry."""
397
+ if elem_ctx is None:
398
+ return None
399
+
400
+ text = elem_ctx.getText()
401
+
402
+ # Common case: metadataBodyFeatureMember -> metadataBodyFeature.
403
+ if hasattr(elem_ctx, 'metadataBodyFeatureMember') and elem_ctx.metadataBodyFeatureMember():
404
+ fbm = elem_ctx.metadataBodyFeatureMember()
405
+ if hasattr(fbm, 'metadataBodyFeature') and fbm.metadataBodyFeature():
406
+ f = fbm.metadataBodyFeature()
407
+ # Feature name from ownedRedefinition (qualifiedName).
408
+ name_text = None
409
+ if hasattr(f, 'ownedRedefinition') and f.ownedRedefinition():
410
+ name_text = f.ownedRedefinition().getText()
411
+ # Value text from valuePart (e.g. '="demo"' or '=0.5').
412
+ # Preserve the operator so downstream tools can decide
413
+ # whether '=' vs ':=' vs 'default =' was used.
414
+ value_text = None
415
+ if hasattr(f, 'valuePart') and f.valuePart():
416
+ value_text = f.valuePart().getText()
417
+ # Optional featureSpecializationPart (e.g. ': Type') and
418
+ # FEATURE keyword (redefinition marker). Capture for
419
+ # downstream consumers that need to distinguish redefines
420
+ # vs new feature declarations.
421
+ specialization = None
422
+ if hasattr(f, 'featureSpecializationPart') and f.featureSpecializationPart():
423
+ specialization = f.featureSpecializationPart().getText()
424
+ is_feature_keyword = (
425
+ hasattr(f, 'FEATURE') and f.FEATURE() is not None
426
+ )
427
+ is_redefines = (
428
+ hasattr(f, 'REDEFINES') and getattr(f, 'REDEFINES', lambda: None)() is not None
429
+ )
430
+ return {
431
+ "name": name_text,
432
+ "value": value_text,
433
+ "text": text,
434
+ "featureKeyword": is_feature_keyword,
435
+ "redefines": is_redefines,
436
+ "specialization": specialization,
437
+ }
438
+
439
+ # Fallback for non-feature metadataBodyElement shapes
440
+ # (aliasMember / importRule / nonFeatureMember).
441
+ return {
442
+ "name": None,
443
+ "value": None,
444
+ "text": text,
334
445
  }
335
446
 
336
447
 
@@ -7955,7 +8066,9 @@ def _make_allocation_usage_dict(ctx, prefix=None):
7955
8066
  Issue #5: the connector endpoints (`allocate X to Y`) were silently
7956
8067
  dropped before reaching the dict. Mirror the InterfaceUsage pattern:
7957
8068
  walk `aud.connectorPart()` (when present) and emit a ConnectorPart
7958
- dict with binary or nary ends.
8069
+ dict with binary or nary ends under the `part` key — the same key
8070
+ ConnectionUsage already uses, so downstream consumers share one
8071
+ shape across connector-bearing usages.
7959
8072
  """
7960
8073
  name = None
7961
8074
  shortname = None
@@ -8011,7 +8124,7 @@ def _make_allocation_usage_dict(ctx, prefix=None):
8011
8124
  "specialization": None
8012
8125
  }
8013
8126
  },
8014
- "connectorPart": connector_part,
8127
+ "part": connector_part,
8015
8128
  "body": {
8016
8129
  "name": "UsageBody",
8017
8130
  "body": {
@@ -4558,24 +4558,29 @@ class MetadataFeature:
4558
4558
  # )? metadataBody
4559
4559
  # ;
4560
4560
  def __init__(self, definition):
4561
- if valid_definition(definition, "MetadataFeature"):
4561
+ if valid_definition(definition, self.__class__.__name__):
4562
4562
  self.prefix = []
4563
4563
  for p in definition.get("prefixMetadataMember", []):
4564
4564
  self.prefix.append(PrefixMetadataMember(p))
4565
-
4565
+
4566
4566
  self.identification = None
4567
4567
  if definition.get("identification") is not None:
4568
4568
  self.identification = Identification(definition["identification"])
4569
-
4569
+
4570
4570
  self.typing = None
4571
4571
  if definition.get("ownedFeatureTyping") is not None:
4572
4572
  self.typing = OwnedFeatureTyping(definition["ownedFeatureTyping"])
4573
-
4573
+
4574
4574
  self.annotations = []
4575
4575
  for ann in definition.get("ownedRelationship_about", []):
4576
4576
  self.annotations.append(Annotation(ann))
4577
-
4577
+
4578
4578
  self.body = definition.get("body", "")
4579
+ # Issue #8: structured per-element capture so consumers can
4580
+ # read individual key = value features without re-parsing
4581
+ # the raw body text. ``dump()`` continues to use the raw
4582
+ # ``self.body`` so whitespace is preserved exactly.
4583
+ self.bodyFeatures = list(definition.get("bodyFeatures", []))
4579
4584
 
4580
4585
  def dump(self):
4581
4586
  output = []
@@ -4601,7 +4606,8 @@ class MetadataFeature:
4601
4606
  "identification": self.identification.get_definition() if self.identification else None,
4602
4607
  "ownedFeatureTyping": self.typing.get_definition() if self.typing else None,
4603
4608
  "ownedRelationship_about": [a.get_definition() for a in self.annotations],
4604
- "body": self.body
4609
+ "body": self.body,
4610
+ "bodyFeatures": list(self.bodyFeatures),
4605
4611
  }
4606
4612
  return output
4607
4613
 
@@ -9887,10 +9893,18 @@ class AllocationUsage(_PrefixedUsageBase):
9887
9893
 
9888
9894
  def __init__(self, definition=None):
9889
9895
  super().__init__(definition)
9896
+ # Issue #5 / PR #6: stores the connectorPart (the `allocate X to Y`
9897
+ # endpoints) on the same `part` key ConnectionUsage already uses, so
9898
+ # downstream consumers share one shape across connector-bearing
9899
+ # usages. Initialized from `definition["part"]` for round-trip
9900
+ # compatibility with the visitor; legacy `definition["connectorPart"]`
9901
+ # is also accepted as a fallback so callers that built dicts using
9902
+ # the v0.47.0 contract keep working until they migrate.
9890
9903
  self.connectorPart = None
9891
9904
  if definition is not None and valid_definition(definition, self.__class__.__name__):
9892
- if definition.get("connectorPart") is not None:
9893
- self.connectorPart = ConnectorPart(definition["connectorPart"])
9905
+ raw = definition.get("part", definition.get("connectorPart"))
9906
+ if raw is not None:
9907
+ self.connectorPart = ConnectorPart(raw)
9894
9908
 
9895
9909
  def dump(self):
9896
9910
  parts = []
@@ -9910,8 +9924,11 @@ class AllocationUsage(_PrefixedUsageBase):
9910
9924
  return " ".join(parts)
9911
9925
 
9912
9926
  def get_definition(self):
9927
+ # Emit under the `part` key (matching ConnectionUsage convention
9928
+ # from PR #6). The legacy `connectorPart` alias is no longer emitted
9929
+ # but ``__init__`` still accepts it for back-compat reads.
9913
9930
  output = super().get_definition()
9914
- output["connectorPart"] = self.connectorPart.get_definition() if self.connectorPart else None
9931
+ output["part"] = self.connectorPart.get_definition() if self.connectorPart else None
9915
9932
  return output
9916
9933
 
9917
9934
 
File without changes
File without changes
File without changes
File without changes