sysmlpy 0.40.0__tar.gz → 0.41.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.40.0 → sysmlpy-0.41.0}/PKG-INFO +3 -1
  2. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/README.md +2 -0
  3. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/pyproject.toml +1 -1
  4. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/__init__.py +1 -1
  5. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/antlr_visitor.py +113 -10
  6. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/usage.py +125 -22
  7. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/LICENSE +0 -0
  8. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/__main__.py +0 -0
  9. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/antlr/README.md +0 -0
  10. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/antlr/SysMLv2Lexer.interp +0 -0
  11. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/antlr/SysMLv2Lexer.py +0 -0
  12. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/antlr/SysMLv2Lexer.tokens +0 -0
  13. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/antlr/SysMLv2Parser.interp +0 -0
  14. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/antlr/SysMLv2Parser.py +0 -0
  15. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/antlr/SysMLv2Parser.tokens +0 -0
  16. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/antlr/SysMLv2ParserListener.py +0 -0
  17. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/antlr/SysMLv2ParserVisitor.py +0 -0
  18. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.interp +0 -0
  19. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.py +0 -0
  20. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.tokens +0 -0
  21. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/antlr_parser.py +0 -0
  22. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/boxes_view.py +0 -0
  23. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/definition.py +0 -0
  24. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/examples/attribute_values.py +0 -0
  25. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/examples/part_attributes.py +0 -0
  26. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/examples/tuples_sequences.py +0 -0
  27. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/formatting.py +0 -0
  28. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/grammar/antlr4/README.md +0 -0
  29. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.g4 +0 -0
  30. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.interp +0 -0
  31. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.py +0 -0
  32. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.tokens +0 -0
  33. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.g4 +0 -0
  34. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.interp +0 -0
  35. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.py +0 -0
  36. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.tokens +0 -0
  37. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/grammar/antlr4/SysMLv2ParserListener.py +0 -0
  38. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/grammar/antlr4/SysMLv2ParserVisitor.py +0 -0
  39. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/grammar/antlr4/desc.xml +0 -0
  40. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/grammar/antlr4/examples/camera.sysml +0 -0
  41. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/grammar/antlr4/examples/toaster-system.sysml +0 -0
  42. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/grammar/antlr4/examples/vehicle-model.sysml +0 -0
  43. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/grammar/antlr4/pom.xml +0 -0
  44. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/grammar/classes.py +0 -0
  45. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/LICENSE +0 -0
  46. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/README.md +0 -0
  47. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/__init__.py +0 -0
  48. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Analysis/AnalysisTooling.sysml +0 -0
  49. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Analysis/SampledFunctions.sysml +0 -0
  50. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Analysis/StateSpaceRepresentation.sysml +0 -0
  51. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Analysis/TradeStudies.sysml +0 -0
  52. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Cause and Effect/CausationConnections.sysml +0 -0
  53. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Cause and Effect/CauseAndEffect.sysml +0 -0
  54. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Geometry/ShapeItems.sysml +0 -0
  55. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Geometry/SpatialItems.sysml +0 -0
  56. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Metadata/ImageMetadata.sysml +0 -0
  57. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Metadata/ModelingMetadata.sysml +0 -0
  58. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Metadata/ParametersOfInterestMetadata.sysml +0 -0
  59. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Metadata/RiskMetadata.sysml +0 -0
  60. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Quantities and Units/ISQ.sysml +0 -0
  61. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Quantities and Units/ISQAcoustics.sysml +0 -0
  62. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Quantities and Units/ISQAtomicNuclear.sysml +0 -0
  63. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Quantities and Units/ISQBase.sysml +0 -0
  64. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Quantities and Units/ISQCharacteristicNumbers.sysml +0 -0
  65. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Quantities and Units/ISQChemistryMolecular.sysml +0 -0
  66. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Quantities and Units/ISQCondensedMatter.sysml +0 -0
  67. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Quantities and Units/ISQElectromagnetism.sysml +0 -0
  68. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Quantities and Units/ISQInformation.sysml +0 -0
  69. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Quantities and Units/ISQLight.sysml +0 -0
  70. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Quantities and Units/ISQMechanics.sysml +0 -0
  71. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Quantities and Units/ISQSpaceTime.sysml +0 -0
  72. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Quantities and Units/ISQThermodynamics.sysml +0 -0
  73. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Quantities and Units/MeasurementRefCalculations.sysml +0 -0
  74. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Quantities and Units/MeasurementReferences.sysml +0 -0
  75. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Quantities and Units/Quantities.sysml +0 -0
  76. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Quantities and Units/QuantityCalculations.sysml +0 -0
  77. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Quantities and Units/SI.sysml +0 -0
  78. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Quantities and Units/SIPrefixes.sysml +0 -0
  79. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Quantities and Units/TensorCalculations.sysml +0 -0
  80. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Quantities and Units/Time.sysml +0 -0
  81. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Quantities and Units/USCustomaryUnits.sysml +0 -0
  82. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Quantities and Units/VectorCalculations.sysml +0 -0
  83. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Requirement Derivation/DerivationConnections.sysml +0 -0
  84. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/domain/Requirement Derivation/RequirementDerivation.sysml +0 -0
  85. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/Base.kerml +0 -0
  86. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/BaseFunctions.kerml +0 -0
  87. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/BooleanFunctions.kerml +0 -0
  88. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/Clocks.kerml +0 -0
  89. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/CollectionFunctions.kerml +0 -0
  90. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/Collections.kerml +0 -0
  91. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/ComplexFunctions.kerml +0 -0
  92. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/ControlFunctions.kerml +0 -0
  93. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/ControlPerformances.kerml +0 -0
  94. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/DataFunctions.kerml +0 -0
  95. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/FeatureReferencingPerformances.kerml +0 -0
  96. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/IntegerFunctions.kerml +0 -0
  97. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/KerML.kerml +0 -0
  98. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/Links.kerml +0 -0
  99. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/Metaobjects.kerml +0 -0
  100. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/NaturalFunctions.kerml +0 -0
  101. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/NumericalFunctions.kerml +0 -0
  102. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/Objects.kerml +0 -0
  103. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/Observation.kerml +0 -0
  104. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/OccurrenceFunctions.kerml +0 -0
  105. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/Occurrences.kerml +0 -0
  106. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/Performances.kerml +0 -0
  107. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/RationalFunctions.kerml +0 -0
  108. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/RealFunctions.kerml +0 -0
  109. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/ScalarFunctions.kerml +0 -0
  110. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/ScalarValues.kerml +0 -0
  111. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/SequenceFunctions.kerml +0 -0
  112. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/SpatialFrames.kerml +0 -0
  113. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/StatePerformances.kerml +0 -0
  114. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/StringFunctions.kerml +0 -0
  115. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/Transfers.kerml +0 -0
  116. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/TransitionPerformances.kerml +0 -0
  117. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/TrigFunctions.kerml +0 -0
  118. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/Triggers.kerml +0 -0
  119. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/VectorFunctions.kerml +0 -0
  120. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/kernel/VectorValues.kerml +0 -0
  121. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/systems/Actions.sysml +0 -0
  122. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/systems/Allocations.sysml +0 -0
  123. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/systems/AnalysisCases.sysml +0 -0
  124. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/systems/Attributes.sysml +0 -0
  125. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/systems/Calculations.sysml +0 -0
  126. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/systems/Cases.sysml +0 -0
  127. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/systems/Connections.sysml +0 -0
  128. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/systems/Constraints.sysml +0 -0
  129. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/systems/Flows.sysml +0 -0
  130. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/systems/Interfaces.sysml +0 -0
  131. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/systems/Items.sysml +0 -0
  132. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/systems/Metadata.sysml +0 -0
  133. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/systems/Parts.sysml +0 -0
  134. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/systems/Ports.sysml +0 -0
  135. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/systems/Requirements.sysml +0 -0
  136. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/systems/StandardViewDefinitions.sysml +0 -0
  137. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/systems/States.sysml +0 -0
  138. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/systems/SysML.sysml +0 -0
  139. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/systems/UseCases.sysml +0 -0
  140. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/systems/VerificationCases.sysml +0 -0
  141. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/library/systems/Views.sysml +0 -0
  142. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/navigate.py +0 -0
  143. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/plantuml.py +0 -0
  144. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/project.py +0 -0
  145. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/semantic.py +0 -0
  146. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/store.py +0 -0
  147. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/us_customary_units.txt +0 -0
  148. {sysmlpy-0.40.0 → sysmlpy-0.41.0}/src/sysmlpy/validator.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sysmlpy
3
- Version: 0.40.0
3
+ Version: 0.41.0
4
4
  Summary:
5
5
  License-File: LICENSE
6
6
  Author: Jon R. Fox (mycr0ft)
@@ -39,6 +39,8 @@ The project had diverged so much from sysml2py that a new name, sysmlpy, was sel
39
39
 
40
40
  ![Lines of Code Over Time](loc_history.svg)
41
41
 
42
+ **v0.41.0:** Full-specialization capture across all usage kinds — v0.40.0 fixed `attributeUsage` only; actions, calculations, constraints, requirements, use cases, interfaces and nested occurrences still dropped `:>`, `:>>`, `::>` specializations. New `_full_specialization_for_ctx` helper walks any usage-like context to its featureSpecializationPart; twelve visitor sites now use it (typed-by kept as fallback). `Action.load_from_grammar` captures all four kinds and the hand-rolled dumps on Action/Interface/UseCase/Requirement render them (`action a2 ::> RefType;`). `Usage.redefined_name` now works on deeper declaration nestings too. 10 tests in `tests/redefined_name_test.py`.
43
+
42
44
  **v0.40.0:** `References` (`::>` / `references` keyword) implemented end-to-end — previously the grammar-side `FeatureSpecialization` had a silent "not yet implemented" stub and the visitor never emitted dicts for it, so `ref attribute ::> X;` lost its specialization on round-trip (dump emitted `attribute ;`). New `References` grammar class mirrors `Redefinitions`; visitor branches in both full-specialization builders now cover the operator and keyword forms. The top-level `attributeUsage` path was the only one still using the typed-by-only helper; it now uses `_build_full_specialization_from_ctx` so all four kinds (Typings, Subsettings, Redefinitions, References) round-trip. `redefined_name` / `display_name` already handled this case. New `test_attribute_ref_references_operator_roundtrip` in `tests/grammar_test.py`; two new cases in `tests/redefined_name_test.py`. 97/97 grammar round-trip tests pass.
43
45
 
44
46
  **v0.39.0:** Redefined-Usage name resolution — `attribute :>> exampleAttribute = ...;` previously dumped the name correctly but exposed a UUID sentinel via `attribute.name`. Two new helpers surface the user-visible identifier without changing the historical `self.name` semantics: `Usage.redefined_name` (last identifier segment of the first re-declaration chain — `Redefinitions` / `Subsettings` / `References`) and `Usage.display_name` (UUID-aware user-meaningful name). `get_value()`, `dump()`, and `get_child()` continue to work unchanged. New `tests/redefined_name_test.py` (6 tests) — the original two-package `DummyDefinitionModel` / `DummyUsageModel` round-trips and the helper properties are exercised.
@@ -14,6 +14,8 @@ The project had diverged so much from sysml2py that a new name, sysmlpy, was sel
14
14
 
15
15
  ![Lines of Code Over Time](loc_history.svg)
16
16
 
17
+ **v0.41.0:** Full-specialization capture across all usage kinds — v0.40.0 fixed `attributeUsage` only; actions, calculations, constraints, requirements, use cases, interfaces and nested occurrences still dropped `:>`, `:>>`, `::>` specializations. New `_full_specialization_for_ctx` helper walks any usage-like context to its featureSpecializationPart; twelve visitor sites now use it (typed-by kept as fallback). `Action.load_from_grammar` captures all four kinds and the hand-rolled dumps on Action/Interface/UseCase/Requirement render them (`action a2 ::> RefType;`). `Usage.redefined_name` now works on deeper declaration nestings too. 10 tests in `tests/redefined_name_test.py`.
18
+
17
19
  **v0.40.0:** `References` (`::>` / `references` keyword) implemented end-to-end — previously the grammar-side `FeatureSpecialization` had a silent "not yet implemented" stub and the visitor never emitted dicts for it, so `ref attribute ::> X;` lost its specialization on round-trip (dump emitted `attribute ;`). New `References` grammar class mirrors `Redefinitions`; visitor branches in both full-specialization builders now cover the operator and keyword forms. The top-level `attributeUsage` path was the only one still using the typed-by-only helper; it now uses `_build_full_specialization_from_ctx` so all four kinds (Typings, Subsettings, Redefinitions, References) round-trip. `redefined_name` / `display_name` already handled this case. New `test_attribute_ref_references_operator_roundtrip` in `tests/grammar_test.py`; two new cases in `tests/redefined_name_test.py`. 97/97 grammar round-trip tests pass.
18
20
 
19
21
  **v0.39.0:** Redefined-Usage name resolution — `attribute :>> exampleAttribute = ...;` previously dumped the name correctly but exposed a UUID sentinel via `attribute.name`. Two new helpers surface the user-visible identifier without changing the historical `self.name` semantics: `Usage.redefined_name` (last identifier segment of the first re-declaration chain — `Redefinitions` / `Subsettings` / `References`) and `Usage.display_name` (UUID-aware user-meaningful name). `get_value()`, `dump()`, and `get_child()` continue to work unchanged. New `tests/redefined_name_test.py` (6 tests) — the original two-package `DummyDefinitionModel` / `DummyUsageModel` round-trips and the helper properties are exercised.
@@ -6,7 +6,7 @@ build-backend = "poetry.core.masonry.api"
6
6
 
7
7
  [project]
8
8
  name = "sysmlpy"
9
- version = "0.40.0"
9
+ version = "0.41.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.40.0"
28
+ __version__ = "0.41.0"
29
29
 
30
30
  from sysmlpy.usage import (
31
31
  Item, Attribute, Part, Port, Action, Reference, UseCase, Requirement, Interface, Message,
@@ -1432,7 +1432,11 @@ def _make_use_case_usage_dict(ctx, prefix=None):
1432
1432
  if typed_by is None:
1433
1433
  typed_by = _get_action_usage_subsetted_by(ctx)
1434
1434
 
1435
- specialization = _build_specialization(typed_by) if typed_by else None
1435
+ spec_full = _full_specialization_for_ctx(ctx)
1436
+ if spec_full is not None:
1437
+ specialization = spec_full
1438
+ else:
1439
+ specialization = _build_specialization(typed_by) if typed_by else None
1436
1440
  occ_prefix = _get_occurrence_usage_prefix(ctx) if ctx else None
1437
1441
 
1438
1442
  # Get case body items
@@ -3000,8 +3004,13 @@ def _make_action_usage_element(ctx, member_prefix=None):
3000
3004
  # Get body items
3001
3005
  action_items = _visit_action_body_items(ctx)
3002
3006
 
3003
- # Build specialization if typed_by is present
3004
- specialization = _build_specialization(typed_by) if typed_by else None
3007
+ # Full specialization (Typings + Subsettings + Redefinitions +
3008
+ # References); typed-by fallback for odd contexts.
3009
+ spec_full = _full_specialization_for_ctx(ctx)
3010
+ if spec_full is not None:
3011
+ specialization = spec_full
3012
+ else:
3013
+ specialization = _build_specialization(typed_by) if typed_by else None
3005
3014
 
3006
3015
  return {
3007
3016
  "name": "BehaviorUsageMember",
@@ -6143,7 +6152,11 @@ def _make_calculation_usage_dict(ctx, prefix=None):
6143
6152
  if typed_by is None:
6144
6153
  typed_by = _get_action_usage_subsetted_by(ctx)
6145
6154
 
6146
- specialization = _build_specialization(typed_by) if typed_by else None
6155
+ spec_full = _full_specialization_for_ctx(ctx)
6156
+ if spec_full is not None:
6157
+ specialization = spec_full
6158
+ else:
6159
+ specialization = _build_specialization(typed_by) if typed_by else None
6147
6160
  body_parts = _visit_calculation_body_items(ctx)
6148
6161
  occ_prefix = _get_occurrence_usage_prefix(ctx) if ctx else None
6149
6162
 
@@ -6253,7 +6266,11 @@ def _make_constraint_usage_dict(ctx, prefix=None):
6253
6266
  if typed_by is None:
6254
6267
  typed_by = _get_action_usage_subsetted_by(ctx)
6255
6268
 
6256
- specialization = _build_specialization(typed_by) if typed_by else None
6269
+ spec_full = _full_specialization_for_ctx(ctx)
6270
+ if spec_full is not None:
6271
+ specialization = spec_full
6272
+ else:
6273
+ specialization = _build_specialization(typed_by) if typed_by else None
6257
6274
  body_parts = _visit_calculation_body_items(ctx)
6258
6275
  occ_prefix = _get_occurrence_usage_prefix(ctx) if ctx else None
6259
6276
 
@@ -6336,7 +6353,11 @@ def _make_requirement_usage_dict(ctx, prefix=None):
6336
6353
  if typed_by is None:
6337
6354
  typed_by = _get_action_usage_subsetted_by(ctx)
6338
6355
 
6339
- specialization = _build_specialization(typed_by) if typed_by else None
6356
+ spec_full = _full_specialization_for_ctx(ctx)
6357
+ if spec_full is not None:
6358
+ specialization = spec_full
6359
+ else:
6360
+ specialization = _build_specialization(typed_by) if typed_by else None
6340
6361
  occ_prefix = _get_occurrence_usage_prefix(ctx) if ctx else None
6341
6362
 
6342
6363
  # Get requirement body items
@@ -6505,7 +6526,11 @@ def _make_interface_usage_dict(ctx, prefix=None):
6505
6526
  if item_dict:
6506
6527
  body_items.append(item_dict)
6507
6528
 
6508
- specialization = _build_specialization(typed_by) if typed_by else None
6529
+ spec_full = _full_specialization_for_ctx(ctx)
6530
+ if spec_full is not None:
6531
+ specialization = spec_full
6532
+ else:
6533
+ specialization = _build_specialization(typed_by) if typed_by else None
6509
6534
 
6510
6535
  interface_end_members = []
6511
6536
  if interface_part:
@@ -9705,7 +9730,11 @@ def _visit_nested_occurrence_usage(occ_elem):
9705
9730
  typed_by = _get_action_usage_typed_by(ctx)
9706
9731
  if typed_by is None:
9707
9732
  typed_by = _get_action_usage_subsetted_by(ctx)
9708
- specialization = _build_specialization(typed_by) if typed_by else None
9733
+ spec_full = _full_specialization_for_ctx(ctx)
9734
+ if spec_full is not None:
9735
+ specialization = spec_full
9736
+ else:
9737
+ specialization = _build_specialization(typed_by) if typed_by else None
9709
9738
 
9710
9739
  occ_prefix = _get_occurrence_usage_prefix(ctx)
9711
9740
 
@@ -11225,8 +11254,13 @@ def _visit_usage_element_dict(usage_elem_ctx, prefix=None):
11225
11254
  # Get body items
11226
11255
  action_items = _visit_action_body_items(ctx)
11227
11256
 
11228
- # Build specialization if typed_by is present
11229
- specialization = _build_specialization(typed_by) if typed_by else None
11257
+ # Full specialization (Typings + Subsettings + Redefinitions +
11258
+ # References); typed-by fallback for odd contexts.
11259
+ spec_full = _full_specialization_for_ctx(ctx)
11260
+ if spec_full is not None:
11261
+ specialization = spec_full
11262
+ else:
11263
+ specialization = _build_specialization(typed_by) if typed_by else None
11230
11264
 
11231
11265
  return {
11232
11266
  "name": "PackageMember",
@@ -11527,6 +11561,75 @@ def _get_action_usage_subsetted_by(ctx):
11527
11561
  return None
11528
11562
 
11529
11563
 
11564
+ def _full_specialization_for_ctx(ctx):
11565
+ """Best-effort full specialization for any usage-like context.
11566
+
11567
+ Tries, in order:
11568
+ 1. ctx.usage().usageDeclaration().featureSpecializationPart()
11569
+ (whole-usage contexts: attributeUsage, partUsage, …)
11570
+ 2. ctx.usageDeclaration().featureSpecializationPart()
11571
+ 3. ctx.<x>UsageDeclaration().usageDeclaration().featureSpecializationPart()
11572
+ for any ``*UsageDeclaration`` accessor on ctx
11573
+ (actionUsageDeclaration, constraintUsageDeclaration, …)
11574
+
11575
+ Returns None when no path yields a featureSpecializationPart. Callers
11576
+ that previously did ``_build_specialization(typed_by)`` can call this
11577
+ instead to also capture Redefinitions / Subsettings / References.
11578
+ """
11579
+ if ctx is None:
11580
+ return None
11581
+
11582
+ def _fsp_from_ud(ud):
11583
+ if ud is None:
11584
+ return None
11585
+ if isinstance(ud, list):
11586
+ ud = ud[0] if ud else None
11587
+ if ud is None:
11588
+ return None
11589
+ fsp_getter = getattr(ud, "featureSpecializationPart", None)
11590
+ if callable(fsp_getter) and fsp_getter():
11591
+ return _build_full_specialization_from_fsp(fsp_getter())
11592
+ return None
11593
+
11594
+ # 1) whole-usage context
11595
+ usage = getattr(ctx, "usage", None)
11596
+ if callable(usage):
11597
+ u = usage()
11598
+ if u is not None and hasattr(u, "usageDeclaration"):
11599
+ spec = _fsp_from_ud(u.usageDeclaration())
11600
+ if spec is not None:
11601
+ return spec
11602
+
11603
+ # 2) direct usageDeclaration on ctx
11604
+ ud_getter = getattr(ctx, "usageDeclaration", None)
11605
+ if callable(ud_getter):
11606
+ spec = _fsp_from_ud(ud_getter())
11607
+ if spec is not None:
11608
+ return spec
11609
+
11610
+ # 3) any *UsageDeclaration holder (actionUsageDeclaration, …)
11611
+ for attr in sorted(dir(ctx)):
11612
+ if not attr.endswith("UsageDeclaration") or attr == "usageDeclaration":
11613
+ continue
11614
+ getter = getattr(ctx, attr, None)
11615
+ if callable(getter):
11616
+ try:
11617
+ holder = getter()
11618
+ except Exception:
11619
+ continue
11620
+ if holder is None:
11621
+ continue
11622
+ if callable(getattr(holder, "usageDeclaration", None)):
11623
+ spec = _fsp_from_ud(holder.usageDeclaration())
11624
+ if spec is not None:
11625
+ return spec
11626
+ spec = _fsp_from_ud(holder)
11627
+ if spec is not None:
11628
+ return spec
11629
+
11630
+ return None
11631
+
11632
+
11530
11633
  def _build_specialization(typed_by):
11531
11634
  """Build the specialization dictionary structure for a typed-by reference."""
11532
11635
  if not typed_by:
@@ -352,7 +352,16 @@ class Usage(Searchable):
352
352
  else:
353
353
  d = getattr(g, 'declaration', None)
354
354
  if d is not None:
355
- spec = getattr(d, 'specialization', None)
355
+ # Walk to the FeatureDeclaration: some grammars nest
356
+ # declaration -> declaration -> declaration (e.g.
357
+ # ActionUsageDeclaration -> UsageDeclaration ->
358
+ # FeatureDeclaration).
359
+ node = d
360
+ for _ in range(3):
361
+ if node is None or hasattr(node, 'specialization'):
362
+ break
363
+ node = getattr(node, 'declaration', None)
364
+ spec = getattr(node, 'specialization', None) if node is not None else None
356
365
  resolved = _resolve_name_from_specialization(spec)
357
366
  return resolved or ""
358
367
 
@@ -1732,11 +1741,16 @@ class Interface(Usage):
1732
1741
  keyword = getattr(self, 'keyword', 'interface')
1733
1742
 
1734
1743
  # Build type/specialization suffix
1735
- type_suffix = ""
1736
- if hasattr(self, '_typed_by_name') and self._typed_by_name:
1737
- type_suffix = f" : {self._typed_by_name}"
1738
- elif hasattr(self, '_specializes_names') and self._specializes_names:
1739
- type_suffix = " :> " + ", ".join(self._specializes_names)
1744
+ suffix_parts = []
1745
+ if getattr(self, '_typed_by_name', None):
1746
+ suffix_parts.append(f" : {self._typed_by_name}")
1747
+ if getattr(self, '_specializes_names', None):
1748
+ suffix_parts.append(" :> " + ", ".join(self._specializes_names))
1749
+ if getattr(self, '_redefined_refs', None):
1750
+ suffix_parts.append(" :>> " + ", ".join(self._redefined_refs))
1751
+ if getattr(self, '_referenced_refs', None):
1752
+ suffix_parts.append(" ::> " + ", ".join(self._referenced_refs))
1753
+ type_suffix = "".join(suffix_parts)
1740
1754
 
1741
1755
  body_items = []
1742
1756
 
@@ -1846,6 +1860,11 @@ class Action(Usage):
1846
1860
  self._succession_targets = []
1847
1861
  self._succession_condition = None
1848
1862
  self._control_flow_nodes = []
1863
+ # Re-declaration chains captured from grammar (v0.41.0)
1864
+ self._typed_by_name = None
1865
+ self._specializes_names = []
1866
+ self._redefined_refs = []
1867
+ self._referenced_refs = []
1849
1868
 
1850
1869
  if definition:
1851
1870
  self.keyword = "action def"
@@ -1969,7 +1988,76 @@ class Action(Usage):
1969
1988
  self._extract_action_target_succession(child)
1970
1989
  elif child_name == "GuardedSuccessionMember":
1971
1990
  self._extract_guarded_succession(child)
1972
-
1991
+
1992
+ self._extract_specialization_info(grammar)
1993
+
1994
+ return self
1995
+
1996
+ def _extract_specialization_info(self, grammar):
1997
+ """Capture Typings / Subsettings / Redefinitions / References names
1998
+ from the grammar's feature specialization so ``dump()`` can render
1999
+ them (v0.41.0)."""
2000
+ fd = None
2001
+ if getattr(grammar, 'declaration', None) is not None:
2002
+ ud = getattr(grammar.declaration, 'declaration', None)
2003
+ if ud is not None:
2004
+ fd = getattr(ud, 'declaration', None)
2005
+ spec = getattr(fd, 'specialization', None) if fd is not None else None
2006
+ if spec is None:
2007
+ return
2008
+ for fs in getattr(spec, 'specializations', None) or []:
2009
+ rel = getattr(fs, 'relationship', None)
2010
+ kind = rel.__class__.__name__ if rel is not None else None
2011
+ if kind == 'Typings':
2012
+ tb = getattr(rel, 'typing', None)
2013
+ for ft in getattr(tb, 'relationships', []) or []:
2014
+ rel2 = getattr(ft, 'relationship', None)
2015
+ ftype = getattr(rel2, 'type', None)
2016
+ qn = getattr(ftype, 'type', None)
2017
+ names = getattr(qn, 'names', None)
2018
+ if names:
2019
+ self._typed_by_name = '::'.join(names)
2020
+ break
2021
+ elements = getattr(ftype, 'elements', None) or []
2022
+ seg_names = []
2023
+ for el in elements:
2024
+ if hasattr(el, 'names') and el.names:
2025
+ seg_names.extend(el.names)
2026
+ elif hasattr(el, 'feature'):
2027
+ for seg in getattr(el.feature, 'children', []) or []:
2028
+ cf = getattr(seg, 'chainingFeature', None)
2029
+ if cf is not None and getattr(cf, 'names', None):
2030
+ seg_names.extend(cf.names)
2031
+ if seg_names:
2032
+ self._typed_by_name = '.'.join(seg_names)
2033
+ break
2034
+ elif kind in ('Subsettings', 'Redefinitions', 'References'):
2035
+ target = (
2036
+ self._specializes_names if kind == 'Subsettings'
2037
+ else self._redefined_refs if kind == 'Redefinitions'
2038
+ else self._referenced_refs
2039
+ )
2040
+ for child in getattr(rel, 'children', None) or []:
2041
+ qn = (
2042
+ getattr(child, 'redefinedFeature', None)
2043
+ or getattr(child, 'referencedFeature', None)
2044
+ )
2045
+ if qn is not None and getattr(qn, 'names', None):
2046
+ target.append('::'.join(qn.names))
2047
+ continue
2048
+ elements = getattr(child, 'elements', None) or []
2049
+ seg_names = []
2050
+ for el in elements:
2051
+ if hasattr(el, 'names') and el.names:
2052
+ seg_names.extend(el.names)
2053
+ elif hasattr(el, 'feature'):
2054
+ for seg in getattr(el.feature, 'children', []) or []:
2055
+ cf = getattr(seg, 'chainingFeature', None)
2056
+ if cf is not None and getattr(cf, 'names', None):
2057
+ seg_names.extend(cf.names)
2058
+ if seg_names:
2059
+ target.append('.'.join(seg_names))
2060
+
1973
2061
  return self
1974
2062
 
1975
2063
  def _extract_initial_node(self, node):
@@ -2341,11 +2429,16 @@ class Action(Usage):
2341
2429
  params.append(f"out {out_name}")
2342
2430
 
2343
2431
  # Build type/specialization suffix
2344
- type_suffix = ""
2345
- if hasattr(self, '_typed_by_name') and self._typed_by_name:
2346
- type_suffix = f" : {self._typed_by_name}"
2347
- elif hasattr(self, '_specializes_names') and self._specializes_names:
2348
- type_suffix = " :> " + ", ".join(self._specializes_names)
2432
+ suffix_parts = []
2433
+ if getattr(self, '_typed_by_name', None):
2434
+ suffix_parts.append(f" : {self._typed_by_name}")
2435
+ if getattr(self, '_specializes_names', None):
2436
+ suffix_parts.append(" :> " + ", ".join(self._specializes_names))
2437
+ if getattr(self, '_redefined_refs', None):
2438
+ suffix_parts.append(" :>> " + ", ".join(self._redefined_refs))
2439
+ if getattr(self, '_referenced_refs', None):
2440
+ suffix_parts.append(" ::> " + ", ".join(self._referenced_refs))
2441
+ type_suffix = "".join(suffix_parts)
2349
2442
 
2350
2443
  if params:
2351
2444
  return f"{keyword} {name_str}{type_suffix} {{ " + "; ".join(params) + "; }"
@@ -2497,11 +2590,16 @@ class UseCase(Usage):
2497
2590
  keyword = getattr(self, 'keyword', 'use case')
2498
2591
 
2499
2592
  # Build type/specialization suffix
2500
- type_suffix = ""
2501
- if hasattr(self, '_typed_by_name') and self._typed_by_name:
2502
- type_suffix = f" : {self._typed_by_name}"
2503
- elif hasattr(self, '_specializes_names') and self._specializes_names:
2504
- type_suffix = " :> " + ", ".join(self._specializes_names)
2593
+ suffix_parts = []
2594
+ if getattr(self, '_typed_by_name', None):
2595
+ suffix_parts.append(f" : {self._typed_by_name}")
2596
+ if getattr(self, '_specializes_names', None):
2597
+ suffix_parts.append(" :> " + ", ".join(self._specializes_names))
2598
+ if getattr(self, '_redefined_refs', None):
2599
+ suffix_parts.append(" :>> " + ", ".join(self._redefined_refs))
2600
+ if getattr(self, '_referenced_refs', None):
2601
+ suffix_parts.append(" ::> " + ", ".join(self._referenced_refs))
2602
+ type_suffix = "".join(suffix_parts)
2505
2603
 
2506
2604
  # Build body members
2507
2605
  body_items = []
@@ -2718,11 +2816,16 @@ class Requirement(Usage):
2718
2816
  shortname_str = f" <{self.req_shortname}>"
2719
2817
 
2720
2818
  # Build type/specialization suffix
2721
- type_suffix = ""
2722
- if hasattr(self, '_typed_by_name') and self._typed_by_name:
2723
- type_suffix = f" : {self._typed_by_name}"
2724
- elif hasattr(self, '_specializes_names') and self._specializes_names:
2725
- type_suffix = " :> " + ", ".join(self._specializes_names)
2819
+ suffix_parts = []
2820
+ if getattr(self, '_typed_by_name', None):
2821
+ suffix_parts.append(f" : {self._typed_by_name}")
2822
+ if getattr(self, '_specializes_names', None):
2823
+ suffix_parts.append(" :> " + ", ".join(self._specializes_names))
2824
+ if getattr(self, '_redefined_refs', None):
2825
+ suffix_parts.append(" :>> " + ", ".join(self._redefined_refs))
2826
+ if getattr(self, '_referenced_refs', None):
2827
+ suffix_parts.append(" ::> " + ", ".join(self._referenced_refs))
2828
+ type_suffix = "".join(suffix_parts)
2726
2829
 
2727
2830
  # Build body members
2728
2831
  body_items = []
File without changes
File without changes