sysmlpy 0.33.3__tar.gz → 0.33.4__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 (147) hide show
  1. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/PKG-INFO +8 -1
  2. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/README.md +7 -0
  3. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/pyproject.toml +1 -1
  4. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/__init__.py +1 -1
  5. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/antlr_visitor.py +154 -0
  6. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/grammar/classes.py +36 -0
  7. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/plantuml.py +22 -1
  8. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/usage.py +8 -0
  9. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/LICENSE +0 -0
  10. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/__main__.py +0 -0
  11. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/antlr/README.md +0 -0
  12. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/antlr/SysMLv2Lexer.interp +0 -0
  13. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/antlr/SysMLv2Lexer.py +0 -0
  14. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/antlr/SysMLv2Lexer.tokens +0 -0
  15. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/antlr/SysMLv2Parser.interp +0 -0
  16. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/antlr/SysMLv2Parser.py +0 -0
  17. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/antlr/SysMLv2Parser.tokens +0 -0
  18. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/antlr/SysMLv2ParserListener.py +0 -0
  19. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/antlr/SysMLv2ParserVisitor.py +0 -0
  20. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.interp +0 -0
  21. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.py +0 -0
  22. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.tokens +0 -0
  23. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/antlr_parser.py +0 -0
  24. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/definition.py +0 -0
  25. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/examples/attribute_values.py +0 -0
  26. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/examples/part_attributes.py +0 -0
  27. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/examples/tuples_sequences.py +0 -0
  28. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/formatting.py +0 -0
  29. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/grammar/antlr4/README.md +0 -0
  30. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.g4 +0 -0
  31. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.interp +0 -0
  32. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.py +0 -0
  33. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.tokens +0 -0
  34. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.g4 +0 -0
  35. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.interp +0 -0
  36. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.py +0 -0
  37. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.tokens +0 -0
  38. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/grammar/antlr4/SysMLv2ParserListener.py +0 -0
  39. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/grammar/antlr4/SysMLv2ParserVisitor.py +0 -0
  40. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/grammar/antlr4/desc.xml +0 -0
  41. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/grammar/antlr4/examples/camera.sysml +0 -0
  42. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/grammar/antlr4/examples/toaster-system.sysml +0 -0
  43. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/grammar/antlr4/examples/vehicle-model.sysml +0 -0
  44. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/grammar/antlr4/pom.xml +0 -0
  45. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/LICENSE +0 -0
  46. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/README.md +0 -0
  47. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/__init__.py +0 -0
  48. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Analysis/AnalysisTooling.sysml +0 -0
  49. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Analysis/SampledFunctions.sysml +0 -0
  50. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Analysis/StateSpaceRepresentation.sysml +0 -0
  51. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Analysis/TradeStudies.sysml +0 -0
  52. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Cause and Effect/CausationConnections.sysml +0 -0
  53. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Cause and Effect/CauseAndEffect.sysml +0 -0
  54. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Geometry/ShapeItems.sysml +0 -0
  55. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Geometry/SpatialItems.sysml +0 -0
  56. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Metadata/ImageMetadata.sysml +0 -0
  57. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Metadata/ModelingMetadata.sysml +0 -0
  58. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Metadata/ParametersOfInterestMetadata.sysml +0 -0
  59. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Metadata/RiskMetadata.sysml +0 -0
  60. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Quantities and Units/ISQ.sysml +0 -0
  61. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Quantities and Units/ISQAcoustics.sysml +0 -0
  62. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Quantities and Units/ISQAtomicNuclear.sysml +0 -0
  63. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Quantities and Units/ISQBase.sysml +0 -0
  64. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Quantities and Units/ISQCharacteristicNumbers.sysml +0 -0
  65. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Quantities and Units/ISQChemistryMolecular.sysml +0 -0
  66. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Quantities and Units/ISQCondensedMatter.sysml +0 -0
  67. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Quantities and Units/ISQElectromagnetism.sysml +0 -0
  68. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Quantities and Units/ISQInformation.sysml +0 -0
  69. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Quantities and Units/ISQLight.sysml +0 -0
  70. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Quantities and Units/ISQMechanics.sysml +0 -0
  71. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Quantities and Units/ISQSpaceTime.sysml +0 -0
  72. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Quantities and Units/ISQThermodynamics.sysml +0 -0
  73. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Quantities and Units/MeasurementRefCalculations.sysml +0 -0
  74. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Quantities and Units/MeasurementReferences.sysml +0 -0
  75. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Quantities and Units/Quantities.sysml +0 -0
  76. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Quantities and Units/QuantityCalculations.sysml +0 -0
  77. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Quantities and Units/SI.sysml +0 -0
  78. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Quantities and Units/SIPrefixes.sysml +0 -0
  79. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Quantities and Units/TensorCalculations.sysml +0 -0
  80. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Quantities and Units/Time.sysml +0 -0
  81. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Quantities and Units/USCustomaryUnits.sysml +0 -0
  82. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Quantities and Units/VectorCalculations.sysml +0 -0
  83. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Requirement Derivation/DerivationConnections.sysml +0 -0
  84. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/domain/Requirement Derivation/RequirementDerivation.sysml +0 -0
  85. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/Base.kerml +0 -0
  86. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/BaseFunctions.kerml +0 -0
  87. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/BooleanFunctions.kerml +0 -0
  88. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/Clocks.kerml +0 -0
  89. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/CollectionFunctions.kerml +0 -0
  90. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/Collections.kerml +0 -0
  91. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/ComplexFunctions.kerml +0 -0
  92. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/ControlFunctions.kerml +0 -0
  93. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/ControlPerformances.kerml +0 -0
  94. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/DataFunctions.kerml +0 -0
  95. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/FeatureReferencingPerformances.kerml +0 -0
  96. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/IntegerFunctions.kerml +0 -0
  97. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/KerML.kerml +0 -0
  98. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/Links.kerml +0 -0
  99. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/Metaobjects.kerml +0 -0
  100. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/NaturalFunctions.kerml +0 -0
  101. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/NumericalFunctions.kerml +0 -0
  102. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/Objects.kerml +0 -0
  103. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/Observation.kerml +0 -0
  104. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/OccurrenceFunctions.kerml +0 -0
  105. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/Occurrences.kerml +0 -0
  106. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/Performances.kerml +0 -0
  107. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/RationalFunctions.kerml +0 -0
  108. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/RealFunctions.kerml +0 -0
  109. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/ScalarFunctions.kerml +0 -0
  110. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/ScalarValues.kerml +0 -0
  111. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/SequenceFunctions.kerml +0 -0
  112. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/SpatialFrames.kerml +0 -0
  113. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/StatePerformances.kerml +0 -0
  114. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/StringFunctions.kerml +0 -0
  115. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/Transfers.kerml +0 -0
  116. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/TransitionPerformances.kerml +0 -0
  117. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/TrigFunctions.kerml +0 -0
  118. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/Triggers.kerml +0 -0
  119. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/VectorFunctions.kerml +0 -0
  120. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/kernel/VectorValues.kerml +0 -0
  121. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/systems/Actions.sysml +0 -0
  122. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/systems/Allocations.sysml +0 -0
  123. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/systems/AnalysisCases.sysml +0 -0
  124. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/systems/Attributes.sysml +0 -0
  125. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/systems/Calculations.sysml +0 -0
  126. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/systems/Cases.sysml +0 -0
  127. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/systems/Connections.sysml +0 -0
  128. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/systems/Constraints.sysml +0 -0
  129. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/systems/Flows.sysml +0 -0
  130. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/systems/Interfaces.sysml +0 -0
  131. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/systems/Items.sysml +0 -0
  132. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/systems/Metadata.sysml +0 -0
  133. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/systems/Parts.sysml +0 -0
  134. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/systems/Ports.sysml +0 -0
  135. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/systems/Requirements.sysml +0 -0
  136. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/systems/StandardViewDefinitions.sysml +0 -0
  137. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/systems/States.sysml +0 -0
  138. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/systems/SysML.sysml +0 -0
  139. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/systems/UseCases.sysml +0 -0
  140. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/systems/VerificationCases.sysml +0 -0
  141. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/library/systems/Views.sysml +0 -0
  142. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/navigate.py +0 -0
  143. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/project.py +0 -0
  144. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/semantic.py +0 -0
  145. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/store.py +0 -0
  146. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/us_customary_units.txt +0 -0
  147. {sysmlpy-0.33.3 → sysmlpy-0.33.4}/src/sysmlpy/validator.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sysmlpy
3
- Version: 0.33.3
3
+ Version: 0.33.4
4
4
  Summary:
5
5
  License-File: LICENSE
6
6
  Author: Jon R. Fox (mycr0ft)
@@ -831,6 +831,13 @@ See [`docs/plantuml-examples/`](docs/plantuml-examples/) for all rendered exampl
831
831
  3. New `as_case_view()` — maps actors and use cases onto PlantUML use-case diagram syntax.
832
832
  4. Added `docs/GUARDS.md` documenting guard condition syntax for confused users (canonical keyword is `if`, transition order is `accept` before `if` before `do` before `then`).
833
833
 
834
+ - **v0.33.4** — Fix `timeslice`/`snapshot`/`individual` parsing and PlantUML rendering:
835
+ 1. `portionUsage` and `individualUsage` were silently dropped from nested body definitions (visitor gaps in `_visit_nested_occurrence_usage`, `_visit_nested_usage`).
836
+ 2. Added `PortionUsage` grammar class and dispatch in `StructureUsageElement.__init__`.
837
+ 3. Added `_make_portion_usage_prefix()` to extract prefix info from `PortionUsageContext`.
838
+ 4. Added `load_from_grammar` handler for `PortionUsage` in `usage.py`.
839
+ 5. PlantUML `_get_stereotype()` now includes `individual`/`timeslice`/`snapshot` prefixes (e.g. `<<timeslice part>>`, `<<individual part>>`).
840
+
834
841
  ## Conformance
835
842
 
836
843
  **100% of 123 OMG XPect conformance tests pass** (123/123).
@@ -806,6 +806,13 @@ See [`docs/plantuml-examples/`](docs/plantuml-examples/) for all rendered exampl
806
806
  3. New `as_case_view()` — maps actors and use cases onto PlantUML use-case diagram syntax.
807
807
  4. Added `docs/GUARDS.md` documenting guard condition syntax for confused users (canonical keyword is `if`, transition order is `accept` before `if` before `do` before `then`).
808
808
 
809
+ - **v0.33.4** — Fix `timeslice`/`snapshot`/`individual` parsing and PlantUML rendering:
810
+ 1. `portionUsage` and `individualUsage` were silently dropped from nested body definitions (visitor gaps in `_visit_nested_occurrence_usage`, `_visit_nested_usage`).
811
+ 2. Added `PortionUsage` grammar class and dispatch in `StructureUsageElement.__init__`.
812
+ 3. Added `_make_portion_usage_prefix()` to extract prefix info from `PortionUsageContext`.
813
+ 4. Added `load_from_grammar` handler for `PortionUsage` in `usage.py`.
814
+ 5. PlantUML `_get_stereotype()` now includes `individual`/`timeslice`/`snapshot` prefixes (e.g. `<<timeslice part>>`, `<<individual part>>`).
815
+
809
816
  ## Conformance
810
817
 
811
818
  **100% of 123 OMG XPect conformance tests pass** (123/123).
@@ -6,7 +6,7 @@ build-backend = "poetry.core.masonry.api"
6
6
 
7
7
  [project]
8
8
  name = "sysmlpy"
9
- version = "0.33.3"
9
+ version = "0.33.4"
10
10
  description = ""
11
11
  authors = [{ name = "Jon R. Fox (mycr0ft)", email = "jon.fox@drfox.com" }]
12
12
  readme = "README.md"
@@ -22,7 +22,7 @@ __all__ = [
22
22
  "SysMLSyntaxError",
23
23
  ]
24
24
  __author__ = "Jon Fox"
25
- __version__ = "0.33.3"
25
+ __version__ = "0.33.4"
26
26
 
27
27
  from sysmlpy.usage import (
28
28
  Item, Attribute, Part, Port, Action, Reference, UseCase, Requirement, Interface, Message,
@@ -1079,6 +1079,81 @@ def _get_occurrence_usage_prefix(ctx):
1079
1079
  }
1080
1080
 
1081
1081
 
1082
+ def _make_portion_usage_prefix(ctx):
1083
+ """Build an OccurrenceUsagePrefix dict from a PortionUsageContext.
1084
+
1085
+ PortionUsageContext has basicUsagePrefix directly (not via occurrenceUsagePrefix),
1086
+ plus optional INDIVIDUAL and required portionKind.
1087
+ """
1088
+ is_reference = False
1089
+ direction_in = ""
1090
+ direction_out = ""
1091
+ direction_inout = ""
1092
+ is_end = False
1093
+ is_individual = False
1094
+ portion_kind = None
1095
+
1096
+ if hasattr(ctx, 'basicUsagePrefix') and ctx.basicUsagePrefix():
1097
+ bup = ctx.basicUsagePrefix()
1098
+ is_reference = hasattr(bup, 'REF') and bup.REF() is not None
1099
+ if hasattr(bup, 'refPrefix') and bup.refPrefix():
1100
+ rp = bup.refPrefix()
1101
+ if hasattr(rp, 'featureDirection') and rp.featureDirection():
1102
+ fd = rp.featureDirection()
1103
+ direction_in = "in " if fd.IN() is not None else ""
1104
+ direction_out = "out" if fd.OUT() is not None else ""
1105
+ direction_inout = "inout" if fd.INOUT() is not None else ""
1106
+ if hasattr(rp, 'END') and rp.END() is not None:
1107
+ is_end = True
1108
+
1109
+ if hasattr(ctx, 'INDIVIDUAL') and ctx.INDIVIDUAL() is not None:
1110
+ is_individual = True
1111
+
1112
+ if hasattr(ctx, 'portionKind') and ctx.portionKind():
1113
+ pk_ctx = ctx.portionKind()
1114
+ if hasattr(pk_ctx, 'SNAPSHOT') and pk_ctx.SNAPSHOT() is not None:
1115
+ portion_kind = "snapshot"
1116
+ elif hasattr(pk_ctx, 'TIMESLICE') and pk_ctx.TIMESLICE() is not None:
1117
+ portion_kind = "timeslice"
1118
+
1119
+ ref_prefix = None
1120
+ has_direction = any([direction_in, direction_out, direction_inout])
1121
+ if has_direction or is_end:
1122
+ ref_prefix = {
1123
+ "name": "RefPrefix",
1124
+ "direction": {
1125
+ "name": "FeatureDirection",
1126
+ "in": direction_in,
1127
+ "out": direction_out,
1128
+ "inout": direction_inout
1129
+ },
1130
+ "isAbstract": None,
1131
+ "isVariation": None,
1132
+ "isReadOnly": None,
1133
+ "isDerived": None,
1134
+ "isEnd": "end" if is_end else None
1135
+ }
1136
+
1137
+ portion_kind_dict = None
1138
+ if portion_kind is not None:
1139
+ portion_kind_dict = {
1140
+ "name": "PortionKind",
1141
+ "kind": portion_kind
1142
+ }
1143
+
1144
+ return {
1145
+ "name": "OccurrenceUsagePrefix",
1146
+ "prefix": {
1147
+ "name": "BasicUsagePrefix",
1148
+ "prefix": ref_prefix,
1149
+ "isReference": is_reference
1150
+ },
1151
+ "isIndividual": "individual" if is_individual else None,
1152
+ "portionKind": portion_kind_dict,
1153
+ "usageExtension": []
1154
+ }
1155
+
1156
+
1082
1157
  def _get_occurrence_definition_prefix(ctx):
1083
1158
  """Extract OccurrenceDefinitionPrefix from a definition context (for 'abstract' etc.)."""
1084
1159
  is_abstract = False
@@ -9322,6 +9397,22 @@ def _visit_nested_occurrence_usage(occ_elem):
9322
9397
  inner = result.get("ownedRelatedElement", {})
9323
9398
  return inner
9324
9399
  return result
9400
+ elif hasattr(occ_elem, 'portionUsage') and occ_elem.portionUsage():
9401
+ ctx = occ_elem.portionUsage()
9402
+ name, shortname = _get_usage_identification(ctx)
9403
+ body_items = _get_usage_body_items(ctx)
9404
+ occ_prefix = _make_portion_usage_prefix(ctx)
9405
+ specialization = _build_full_specialization_from_ctx(ctx)
9406
+ valuepart = _get_usage_value_part(ctx)
9407
+ return _make_nested_usage_element("PortionUsage", name, shortname, occ_prefix, body_items, specialization, valuepart)
9408
+ elif hasattr(occ_elem, 'individualUsage') and occ_elem.individualUsage():
9409
+ ctx = occ_elem.individualUsage()
9410
+ name, shortname = _get_usage_identification(ctx)
9411
+ body_items = _get_usage_body_items(ctx)
9412
+ occ_prefix = _make_portion_usage_prefix(ctx)
9413
+ specialization = _build_full_specialization_from_ctx(ctx)
9414
+ valuepart = _get_usage_value_part(ctx)
9415
+ return _make_nested_usage_element("PortionUsage", name, shortname, occ_prefix, body_items, specialization, valuepart)
9325
9416
  return None
9326
9417
 
9327
9418
  # print(f"DEBUG _visit_nested_occurrence_usage: {type(occ_elem).__name__}")
@@ -9377,6 +9468,22 @@ def _visit_nested_occurrence_usage(occ_elem):
9377
9468
  elif hasattr(struct_elem, 'connectionUsage') and struct_elem.connectionUsage():
9378
9469
  ctx = struct_elem.connectionUsage()
9379
9470
  return _make_nested_connection_usage_dict(ctx, None)
9471
+ elif hasattr(struct_elem, 'portionUsage') and struct_elem.portionUsage():
9472
+ ctx = struct_elem.portionUsage()
9473
+ name, shortname = _get_usage_identification(ctx)
9474
+ body_items = _get_usage_body_items(ctx)
9475
+ occ_prefix = _make_portion_usage_prefix(ctx)
9476
+ specialization = _build_full_specialization_from_ctx(ctx)
9477
+ valuepart = _get_usage_value_part(ctx)
9478
+ return _make_nested_usage_element("PortionUsage", name, shortname, occ_prefix, body_items, specialization, valuepart)
9479
+ elif hasattr(struct_elem, 'individualUsage') and struct_elem.individualUsage():
9480
+ ctx = struct_elem.individualUsage()
9481
+ name, shortname = _get_usage_identification(ctx)
9482
+ body_items = _get_usage_body_items(ctx)
9483
+ occ_prefix = _make_portion_usage_prefix(ctx)
9484
+ specialization = _build_full_specialization_from_ctx(ctx)
9485
+ valuepart = _get_usage_value_part(ctx)
9486
+ return _make_nested_usage_element("PortionUsage", name, shortname, occ_prefix, body_items, specialization, valuepart)
9380
9487
 
9381
9488
  # Check for interface occurrence usage element (has defaultInterfaceEnd keyword)
9382
9489
  if hasattr(occ_elem, 'defaultInterfaceEnd') and occ_elem.defaultInterfaceEnd() is not None:
@@ -9625,6 +9732,22 @@ def _visit_nested_occurrence_usage(occ_elem):
9625
9732
  inner = result.get("ownedRelatedElement", {})
9626
9733
  return inner
9627
9734
  return result
9735
+ elif hasattr(struct_elem, 'portionUsage') and struct_elem.portionUsage():
9736
+ ctx = struct_elem.portionUsage()
9737
+ name, shortname = _get_usage_identification(ctx)
9738
+ body_items = _get_usage_body_items(ctx)
9739
+ occ_prefix = _make_portion_usage_prefix(ctx)
9740
+ specialization = _build_full_specialization_from_ctx(ctx)
9741
+ valuepart = _get_usage_value_part(ctx)
9742
+ return _make_nested_usage_element("PortionUsage", name, shortname, occ_prefix, body_items, specialization, valuepart)
9743
+ elif hasattr(struct_elem, 'individualUsage') and struct_elem.individualUsage():
9744
+ ctx = struct_elem.individualUsage()
9745
+ name, shortname = _get_usage_identification(ctx)
9746
+ body_items = _get_usage_body_items(ctx)
9747
+ occ_prefix = _make_portion_usage_prefix(ctx)
9748
+ specialization = _build_full_specialization_from_ctx(ctx)
9749
+ valuepart = _get_usage_value_part(ctx)
9750
+ return _make_nested_usage_element("PortionUsage", name, shortname, occ_prefix, body_items, specialization, valuepart)
9628
9751
 
9629
9752
  # Check behavior usage elements (action)
9630
9753
  if hasattr(occ_elem, 'behaviorUsageElement') and occ_elem.behaviorUsageElement():
@@ -10653,6 +10776,22 @@ def _visit_nested_usage(usage_elem_ctx):
10653
10776
  specialization = _build_full_specialization_from_ctx(ctx)
10654
10777
  valuepart = _get_usage_value_part(ctx)
10655
10778
  return _make_nested_usage_element("PortUsage", name, shortname, occ_prefix, body_items, specialization, valuepart)
10779
+ elif hasattr(struct_elem, 'portionUsage') and struct_elem.portionUsage():
10780
+ ctx = struct_elem.portionUsage()
10781
+ name, shortname = _get_usage_identification(ctx)
10782
+ body_items = _get_usage_body_items(ctx)
10783
+ occ_prefix = _make_portion_usage_prefix(ctx)
10784
+ specialization = _build_full_specialization_from_ctx(ctx)
10785
+ valuepart = _get_usage_value_part(ctx)
10786
+ return _make_nested_usage_element("PortionUsage", name, shortname, occ_prefix, body_items, specialization, valuepart)
10787
+ elif hasattr(struct_elem, 'individualUsage') and struct_elem.individualUsage():
10788
+ ctx = struct_elem.individualUsage()
10789
+ name, shortname = _get_usage_identification(ctx)
10790
+ body_items = _get_usage_body_items(ctx)
10791
+ occ_prefix = _make_portion_usage_prefix(ctx)
10792
+ specialization = _build_full_specialization_from_ctx(ctx)
10793
+ valuepart = _get_usage_value_part(ctx)
10794
+ return _make_nested_usage_element("PortionUsage", name, shortname, occ_prefix, body_items, specialization, valuepart)
10656
10795
 
10657
10796
  # Check behavior usage elements (action)
10658
10797
  if hasattr(occ_elem, 'behaviorUsageElement') and occ_elem.behaviorUsageElement():
@@ -10837,6 +10976,21 @@ def _visit_usage_element_dict(usage_elem_ctx, prefix=None):
10837
10976
  elif hasattr(struct_elem, 'individualUsage') and struct_elem.individualUsage():
10838
10977
  ctx = struct_elem.individualUsage()
10839
10978
  return _make_individual_usage_dict(ctx, prefix)
10979
+ elif hasattr(struct_elem, 'portionUsage') and struct_elem.portionUsage():
10980
+ ctx = struct_elem.portionUsage()
10981
+ name, shortname = _get_usage_identification(ctx)
10982
+ body_items = _get_usage_body_items(ctx)
10983
+ occ_prefix = _make_portion_usage_prefix(ctx)
10984
+ specialization = _build_full_specialization_from_ctx(ctx)
10985
+ valuepart = _get_usage_value_part(ctx)
10986
+ inner = _make_nested_usage_element("PortionUsage", name, shortname, occ_prefix, body_items, specialization, valuepart)
10987
+ if inner:
10988
+ return {
10989
+ "name": "PackageMember",
10990
+ "prefix": None,
10991
+ "ownedRelatedElement": inner
10992
+ }
10993
+ return None
10840
10994
  elif hasattr(struct_elem, 'viewUsage') and struct_elem.viewUsage():
10841
10995
  ctx = struct_elem.viewUsage()
10842
10996
  return _make_view_usage_dict(ctx, prefix)
@@ -6298,6 +6298,8 @@ class StructureUsageElement:
6298
6298
  self.children = AllocationUsage(definition["ownedRelatedElement"])
6299
6299
  elif name == "RenderingUsage":
6300
6300
  self.children = RenderingUsage(definition["ownedRelatedElement"])
6301
+ elif name == "PortionUsage":
6302
+ self.children = PortionUsage(definition["ownedRelatedElement"])
6301
6303
  elif name == "ViewUsage":
6302
6304
  self.children = ViewUsage(definition["ownedRelatedElement"])
6303
6305
  elif name == "SuccessionFlowConnectionUsage":
@@ -9615,6 +9617,40 @@ class IndividualUsageSimple(_PrefixedUsageBase):
9615
9617
  keyword = "individual"
9616
9618
 
9617
9619
 
9620
+ class PortionUsage:
9621
+ """Portion usage (timeslice or snapshot) inside a body."""
9622
+
9623
+ def __init__(self, definition=None):
9624
+ if definition is not None:
9625
+ if valid_definition(definition, "PortionUsage"):
9626
+ if definition.get("prefix") is not None:
9627
+ prefix_name = definition["prefix"].get("name", "OccurrenceUsagePrefix")
9628
+ self.prefix = globals()[prefix_name](definition["prefix"])
9629
+ else:
9630
+ self.prefix = None
9631
+ self.usage = Usage(definition.get("usage"))
9632
+ else:
9633
+ self.prefix = None
9634
+ self.usage = Usage()
9635
+
9636
+ def dump(self):
9637
+ output = []
9638
+ if self.prefix is not None:
9639
+ output.append(self.prefix.dump())
9640
+ if self.usage is not None:
9641
+ output.append(self.usage.dump())
9642
+ return " ".join(output)
9643
+
9644
+ def get_definition(self):
9645
+ pre = None
9646
+ if self.prefix is not None:
9647
+ pre = self.prefix.get_definition()
9648
+ u = None
9649
+ if self.usage is not None:
9650
+ u = self.usage.get_definition()
9651
+ return {"name": self.__class__.__name__, "prefix": pre, "usage": u}
9652
+
9653
+
9618
9654
  class FlowUsageSimple(_PrefixedUsageBase):
9619
9655
  """Alternative FlowUsage (flow without connection - simple usage)."""
9620
9656
  keyword = "flow"
@@ -310,8 +310,21 @@ def _get_stereotype(element, style="bw"):
310
310
  stereotype_map = DEFINITION_STEREOTYPES if is_def else USAGE_STEREOTYPES
311
311
  label = stereotype_map.get(sysml_type, sysml_type)
312
312
 
313
+ # Check for portionKind and individual in the grammar prefix
314
+ prefix = _get_grammar_prefix(element)
315
+ if prefix is not None:
316
+ parts = []
317
+ if getattr(prefix, 'isIndividual', None):
318
+ parts.append("individual")
319
+ pk = getattr(prefix, 'portionKind', None)
320
+ if pk is not None:
321
+ pk_kind = getattr(pk, 'kind', None)
322
+ if pk_kind:
323
+ parts.append(pk_kind)
324
+ if parts:
325
+ label = " ".join(parts) + " " + label
326
+
313
327
  if style == "bw":
314
- # Simple label without colors for journal rendering
315
328
  return f"<<{label}>>"
316
329
 
317
330
  color_info = STEREOTYPE_COLORS.get(sysml_type, ("T", "#3498DB"))
@@ -320,6 +333,14 @@ def _get_stereotype(element, style="bw"):
320
333
  return f"<<({letter},{color}) {label}>>"
321
334
 
322
335
 
336
+ def _get_grammar_prefix(element):
337
+ """Navigate element.grammar to find the OccurrenceUsagePrefix."""
338
+ grammar = getattr(element, 'grammar', None)
339
+ if grammar is None:
340
+ return None
341
+ return getattr(grammar, 'prefix', None)
342
+
343
+
323
344
  def _get_element_name(element):
324
345
  """Get a safe PlantUML name for an element."""
325
346
  name = getattr(element, 'name', None)
@@ -818,6 +818,10 @@ class Usage(Searchable):
818
818
  c = Item().load_from_grammar(sc)
819
819
  c.parent = self
820
820
  self.children.append(c)
821
+ elif class_name == "PortionUsage":
822
+ c = Part().load_from_grammar(sc)
823
+ c.parent = self
824
+ self.children.append(c)
821
825
  elif class_name == "AttributeUsage":
822
826
  c = Attribute().load_from_grammar(sc)
823
827
  c.parent = self
@@ -849,6 +853,10 @@ class Usage(Searchable):
849
853
  c = Flow().load_from_grammar(inner)
850
854
  c.parent = self
851
855
  self.children.append(c)
856
+ elif inner.__class__.__name__ == "PortionUsage":
857
+ c = Part().load_from_grammar(inner)
858
+ c.parent = self
859
+ self.children.append(c)
852
860
  elif class_name == "StructureDefinitionElement":
853
861
  if hasattr(sc, 'children'):
854
862
  inner = sc.children
File without changes
File without changes