sysmlpy 0.70.0__tar.gz → 0.72.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 (158) hide show
  1. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/PKG-INFO +1 -1
  2. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/pyproject.toml +1 -1
  3. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/__init__.py +1 -1
  4. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/semantic.py +388 -0
  5. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/traceability.py +73 -0
  6. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/usage.py +7 -0
  7. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/LICENSE +0 -0
  8. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/README.md +0 -0
  9. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/__main__.py +0 -0
  10. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/antlr/README.md +0 -0
  11. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/antlr/SysMLv2Lexer.interp +0 -0
  12. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/antlr/SysMLv2Lexer.py +0 -0
  13. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/antlr/SysMLv2Lexer.tokens +0 -0
  14. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/antlr/SysMLv2Parser.interp +0 -0
  15. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/antlr/SysMLv2Parser.py +0 -0
  16. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/antlr/SysMLv2Parser.tokens +0 -0
  17. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/antlr/SysMLv2ParserListener.py +0 -0
  18. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/antlr/SysMLv2ParserVisitor.py +0 -0
  19. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.interp +0 -0
  20. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.py +0 -0
  21. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.tokens +0 -0
  22. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/antlr_parser.py +0 -0
  23. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/antlr_visitor.py +0 -0
  24. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/boxes_view.py +0 -0
  25. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/definition.py +0 -0
  26. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/evaluator.py +0 -0
  27. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/examples/attribute_values.py +0 -0
  28. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/examples/part_attributes.py +0 -0
  29. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/examples/tuples_sequences.py +0 -0
  30. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/formatting.py +0 -0
  31. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/grammar/antlr4/README.md +0 -0
  32. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.g4 +0 -0
  33. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.interp +0 -0
  34. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.py +0 -0
  35. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.tokens +0 -0
  36. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.g4 +0 -0
  37. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.interp +0 -0
  38. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.py +0 -0
  39. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.tokens +0 -0
  40. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/grammar/antlr4/SysMLv2ParserListener.py +0 -0
  41. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/grammar/antlr4/SysMLv2ParserVisitor.py +0 -0
  42. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/grammar/antlr4/desc.xml +0 -0
  43. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/grammar/antlr4/examples/camera.sysml +0 -0
  44. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/grammar/antlr4/examples/toaster-system.sysml +0 -0
  45. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/grammar/antlr4/examples/vehicle-model.sysml +0 -0
  46. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/grammar/antlr4/pom.xml +0 -0
  47. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/grammar/classes.py +0 -0
  48. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/interchange.py +0 -0
  49. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/LICENSE +0 -0
  50. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/README.md +0 -0
  51. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/__init__.py +0 -0
  52. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Analysis/AnalysisTooling.sysml +0 -0
  53. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Analysis/SampledFunctions.sysml +0 -0
  54. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Analysis/StateSpaceRepresentation.sysml +0 -0
  55. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Analysis/TradeStudies.sysml +0 -0
  56. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Cause and Effect/CausationConnections.sysml +0 -0
  57. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Cause and Effect/CauseAndEffect.sysml +0 -0
  58. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Geometry/ShapeItems.sysml +0 -0
  59. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Geometry/SpatialItems.sysml +0 -0
  60. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Metadata/ImageMetadata.sysml +0 -0
  61. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Metadata/ModelingMetadata.sysml +0 -0
  62. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Metadata/ParametersOfInterestMetadata.sysml +0 -0
  63. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Metadata/RiskMetadata.sysml +0 -0
  64. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Quantities and Units/ISQ.sysml +0 -0
  65. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Quantities and Units/ISQAcoustics.sysml +0 -0
  66. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Quantities and Units/ISQAtomicNuclear.sysml +0 -0
  67. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Quantities and Units/ISQBase.sysml +0 -0
  68. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Quantities and Units/ISQCharacteristicNumbers.sysml +0 -0
  69. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Quantities and Units/ISQChemistryMolecular.sysml +0 -0
  70. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Quantities and Units/ISQCondensedMatter.sysml +0 -0
  71. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Quantities and Units/ISQElectromagnetism.sysml +0 -0
  72. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Quantities and Units/ISQInformation.sysml +0 -0
  73. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Quantities and Units/ISQLight.sysml +0 -0
  74. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Quantities and Units/ISQMechanics.sysml +0 -0
  75. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Quantities and Units/ISQSpaceTime.sysml +0 -0
  76. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Quantities and Units/ISQThermodynamics.sysml +0 -0
  77. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Quantities and Units/MeasurementRefCalculations.sysml +0 -0
  78. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Quantities and Units/MeasurementReferences.sysml +0 -0
  79. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Quantities and Units/Quantities.sysml +0 -0
  80. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Quantities and Units/QuantityCalculations.sysml +0 -0
  81. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Quantities and Units/SI.sysml +0 -0
  82. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Quantities and Units/SIPrefixes.sysml +0 -0
  83. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Quantities and Units/TensorCalculations.sysml +0 -0
  84. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Quantities and Units/Time.sysml +0 -0
  85. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Quantities and Units/USCustomaryUnits.sysml +0 -0
  86. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Quantities and Units/VectorCalculations.sysml +0 -0
  87. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Requirement Derivation/DerivationConnections.sysml +0 -0
  88. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/domain/Requirement Derivation/RequirementDerivation.sysml +0 -0
  89. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/Base.kerml +0 -0
  90. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/BaseFunctions.kerml +0 -0
  91. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/BooleanFunctions.kerml +0 -0
  92. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/Clocks.kerml +0 -0
  93. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/CollectionFunctions.kerml +0 -0
  94. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/Collections.kerml +0 -0
  95. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/ComplexFunctions.kerml +0 -0
  96. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/ControlFunctions.kerml +0 -0
  97. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/ControlPerformances.kerml +0 -0
  98. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/DataFunctions.kerml +0 -0
  99. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/FeatureReferencingPerformances.kerml +0 -0
  100. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/IntegerFunctions.kerml +0 -0
  101. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/KerML.kerml +0 -0
  102. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/Links.kerml +0 -0
  103. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/Metaobjects.kerml +0 -0
  104. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/NaturalFunctions.kerml +0 -0
  105. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/NumericalFunctions.kerml +0 -0
  106. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/Objects.kerml +0 -0
  107. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/Observation.kerml +0 -0
  108. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/OccurrenceFunctions.kerml +0 -0
  109. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/Occurrences.kerml +0 -0
  110. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/Performances.kerml +0 -0
  111. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/RationalFunctions.kerml +0 -0
  112. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/RealFunctions.kerml +0 -0
  113. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/ScalarFunctions.kerml +0 -0
  114. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/ScalarValues.kerml +0 -0
  115. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/SequenceFunctions.kerml +0 -0
  116. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/SpatialFrames.kerml +0 -0
  117. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/StatePerformances.kerml +0 -0
  118. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/StringFunctions.kerml +0 -0
  119. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/Transfers.kerml +0 -0
  120. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/TransitionPerformances.kerml +0 -0
  121. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/TrigFunctions.kerml +0 -0
  122. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/Triggers.kerml +0 -0
  123. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/VectorFunctions.kerml +0 -0
  124. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/kernel/VectorValues.kerml +0 -0
  125. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/systems/Actions.sysml +0 -0
  126. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/systems/Allocations.sysml +0 -0
  127. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/systems/AnalysisCases.sysml +0 -0
  128. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/systems/Attributes.sysml +0 -0
  129. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/systems/Calculations.sysml +0 -0
  130. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/systems/Cases.sysml +0 -0
  131. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/systems/Connections.sysml +0 -0
  132. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/systems/Constraints.sysml +0 -0
  133. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/systems/Flows.sysml +0 -0
  134. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/systems/Interfaces.sysml +0 -0
  135. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/systems/Items.sysml +0 -0
  136. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/systems/Metadata.sysml +0 -0
  137. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/systems/Parts.sysml +0 -0
  138. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/systems/Ports.sysml +0 -0
  139. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/systems/Requirements.sysml +0 -0
  140. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/systems/StandardViewDefinitions.sysml +0 -0
  141. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/systems/States.sysml +0 -0
  142. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/systems/SysML.sysml +0 -0
  143. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/systems/UseCases.sysml +0 -0
  144. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/systems/VerificationCases.sysml +0 -0
  145. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/library/systems/Views.sysml +0 -0
  146. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/lsp/__init__.py +0 -0
  147. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/lsp/__main__.py +0 -0
  148. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/lsp/protocol.py +0 -0
  149. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/lsp/server.py +0 -0
  150. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/lsp/stdio.py +0 -0
  151. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/navigate.py +0 -0
  152. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/plantuml.py +0 -0
  153. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/project.py +0 -0
  154. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/sim.py +0 -0
  155. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/spreadsheet.py +0 -0
  156. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/store.py +0 -0
  157. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/us_customary_units.txt +0 -0
  158. {sysmlpy-0.70.0 → sysmlpy-0.72.0}/src/sysmlpy/validator.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sysmlpy
3
- Version: 0.70.0
3
+ Version: 0.72.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.70.0"
9
+ version = "0.72.0"
10
10
  description = ""
11
11
  authors = [{ name = "Jon R. Fox (mycr0ft)", email = "jon.fox@drfox.com" }]
12
12
  readme = "README.md"
@@ -34,7 +34,7 @@ __all__ = [
34
34
  "render_state_transition_view_svg", "boxes_view",
35
35
  ]
36
36
  __author__ = "Jon Fox"
37
- __version__ = "0.70.0"
37
+ __version__ = "0.72.0"
38
38
 
39
39
  from sysmlpy.usage import (
40
40
  Item, Attribute, Part, Port, Action, Reference, UseCase, Requirement, Interface, Message,
@@ -1236,6 +1236,139 @@ class ExpressionIdentifierCollector:
1236
1236
  self._walk(child, results, child_scope)
1237
1237
 
1238
1238
 
1239
+ def _satisfy_by_ref(satisfy_dict: dict):
1240
+ """The ``by <part>`` reference of a SatisfyRequirementUsage dict.
1241
+
1242
+ Shape: ``ssm`` = SatisfactionSubjectMember → SatisfactionParameter
1243
+ → … → FeatureChainMember.memberElement (QualifiedName) whose last
1244
+ segment is the satisfying feature. ``ors.referencedFeature.names``
1245
+ carries the target requirement reference.
1246
+ """
1247
+ ssm = satisfy_dict.get("ssm")
1248
+ if not isinstance(ssm, dict):
1249
+ return None
1250
+ members = _find_named_dicts(ssm, "FeatureChainMember")
1251
+ for m in members:
1252
+ me = m.get("memberElement") or {}
1253
+ names = me.get("names")
1254
+ if isinstance(names, list) and names:
1255
+ return "::".join(str(n) for n in names)
1256
+ return None
1257
+
1258
+
1259
+ def _find_named_dicts(node: Any, name: str) -> list:
1260
+ """Locate every dict with ``dict["name"] == name`` in a tree."""
1261
+ out: list = []
1262
+
1263
+ def walk(n: Any) -> None:
1264
+ if isinstance(n, dict):
1265
+ if n.get("name") == name:
1266
+ out.append(n)
1267
+ for v in n.values():
1268
+ if isinstance(v, (dict, list)):
1269
+ walk(v)
1270
+ elif isinstance(n, list):
1271
+ for item in n:
1272
+ if isinstance(item, (dict, list)):
1273
+ walk(item)
1274
+
1275
+ walk(node)
1276
+ return out
1277
+
1278
+
1279
+ def _as_list_dicts(v: Any) -> list:
1280
+ """Normalize an optional-dict-or-list relationship field to a list."""
1281
+ if isinstance(v, list):
1282
+ return [x for x in v if isinstance(x, dict)]
1283
+ if isinstance(v, dict):
1284
+ return [v]
1285
+ return []
1286
+
1287
+
1288
+ def _find_declared_name(d: dict):
1289
+ """Bounded search for ``identification.declaredName`` in a usage/
1290
+ definition dict (the identification nesting varies by shape)."""
1291
+ frontier = [d]
1292
+ for _ in range(4):
1293
+ nxt = []
1294
+ for n in frontier:
1295
+ if not isinstance(n, dict):
1296
+ continue
1297
+ ident = n.get("identification")
1298
+ if isinstance(ident, dict):
1299
+ name = ident.get("declaredName")
1300
+ if name:
1301
+ return name
1302
+ for v in n.values():
1303
+ if isinstance(v, dict):
1304
+ nxt.append(v)
1305
+ elif isinstance(v, list):
1306
+ nxt.extend(x for x in v if isinstance(x, dict))
1307
+ frontier = nxt
1308
+ return None
1309
+
1310
+
1311
+ def _port_direction(port_usage: dict):
1312
+ """The explicit direction keyword on a PortUsage dict, if any.
1313
+
1314
+ The prefix chain is
1315
+ ``OccurrenceUsagePrefix → BasicUsagePrefix → RefPrefix.direction``
1316
+ where ``direction`` is ``{"in": ..., "out": ..., "inout": ...}`` —
1317
+ the present keyword is the non-empty string value.
1318
+ """
1319
+ pre = port_usage.get("prefix")
1320
+ while isinstance(pre, dict):
1321
+ d = pre.get("direction")
1322
+ if isinstance(d, dict):
1323
+ for k in ("in", "out", "inout"):
1324
+ v = d.get(k)
1325
+ if isinstance(v, str) and v.strip():
1326
+ return k
1327
+ return None
1328
+ pre = pre.get("prefix")
1329
+ return None
1330
+
1331
+
1332
+ def _connector_end_chain(end: dict) -> list:
1333
+ """Feature-chain segment names of a ConnectorEnd dict."""
1334
+ ors = end.get("ownedRelationship") if isinstance(end, dict) else None
1335
+ for rel in _as_list_dicts(ors):
1336
+ if rel.get("name") != "OwnedReferenceSubsetting":
1337
+ continue
1338
+ ofc_list = _as_list_dicts(rel.get("ownedRelatedElement"))
1339
+ ofc = ofc_list[0] if ofc_list else {}
1340
+ if ofc.get("name") != "OwnedFeatureChain":
1341
+ continue
1342
+ feat = ofc.get("feature") or {}
1343
+ names = []
1344
+ for chain_rel in _as_list_dicts(feat.get("ownedRelationship")):
1345
+ if chain_rel.get("name") != "OwnedFeatureChaining":
1346
+ continue
1347
+ cf = chain_rel.get("chainingFeature") or {}
1348
+ qn = cf.get("names")
1349
+ if isinstance(qn, list) and qn:
1350
+ names.append(str(qn[-1]))
1351
+ return names
1352
+ return []
1353
+
1354
+
1355
+ def _usage_typed_by(usage: dict):
1356
+ """The last segment of a usage dict's OwnedFeatureTyping, if any.
1357
+
1358
+ The typing rides the declaration/specialization chain, which
1359
+ precedes the body in dict order, so a usage's own typing is found
1360
+ before any nested member's typing.
1361
+ """
1362
+ for rel in _find_named_dicts(usage, "OwnedFeatureTyping"):
1363
+ ft = rel.get("type") or {}
1364
+ qn = ft.get("type") if isinstance(ft, dict) else None
1365
+ if isinstance(qn, dict):
1366
+ names = qn.get("names")
1367
+ if isinstance(names, list) and names:
1368
+ return str(names[-1])
1369
+ return None
1370
+
1371
+
1239
1372
  def _find_payload_parameters(node: Any) -> list:
1240
1373
  """Locate every ``PayloadParameter`` dict in a grammar tree."""
1241
1374
  out: list = []
@@ -2381,6 +2514,9 @@ class SemanticAnalyzer:
2381
2514
  issues.extend(self._check_trigger_payloads(model, symtab, lib_roots))
2382
2515
  issues.extend(self._check_requirement_coverage(model))
2383
2516
  issues.extend(self._check_trace_targets(model, symtab, lib_roots))
2517
+ issues.extend(self._check_verify_targets(model, symtab, lib_roots))
2518
+ issues.extend(self._check_satisfy_parts(model, symtab, lib_roots))
2519
+ issues.extend(self._check_connector_directions(model))
2384
2520
 
2385
2521
  # Step 6: Stylistic checks (warnings, not errors)
2386
2522
  if style_checks:
@@ -3179,6 +3315,258 @@ class SemanticAnalyzer:
3179
3315
  return table.lookup(parts[-1])
3180
3316
  return None
3181
3317
 
3318
+ def _check_satisfy_parts(
3319
+ self,
3320
+ model: Any,
3321
+ symtab: "SymbolTable",
3322
+ lib_roots: list,
3323
+ ) -> list[SemanticIssue]:
3324
+ """Resolve ``satisfy <req> by <part>`` subjects (Goal 9).
3325
+
3326
+ The ``by`` reference names the satisfying part; both
3327
+ package-level satisfies (grammar ``SatisfyRequirementUsage``
3328
+ wrappers yielded by ``_walk_usages``) and satisfies nested
3329
+ inside requirement bodies (extracted from the requirement's
3330
+ grammar dict — the visitor surfaces nested verify members but
3331
+ not satisfy members) are checked. An unresolved by-part is a
3332
+ UNRESOLVED_SATISFY_PART error.
3333
+ """
3334
+ issues: list[SemanticIssue] = []
3335
+
3336
+ def issue(obj, ref):
3337
+ issues.append(SemanticIssue(
3338
+ severity="error",
3339
+ code="UNRESOLVED_SATISFY_PART",
3340
+ message=(
3341
+ f"satisfy 'by {ref}' does not resolve to a "
3342
+ "defined part"),
3343
+ element=obj,
3344
+ reference=ref,
3345
+ ))
3346
+
3347
+ for element, scope_path in self._walk_usages(model):
3348
+ gname = (element.grammar.__class__.__name__
3349
+ if getattr(element, "grammar", None) is not None else "")
3350
+ if gname == "SatisfyRequirementUsage":
3351
+ # package-level wrapper; .ssm dump is the by reference
3352
+ g = element.grammar
3353
+ ssm = getattr(g, "ssm", None)
3354
+ if ssm is None:
3355
+ continue
3356
+ ref = ssm.dump().strip().rstrip(";").strip()
3357
+ if not ref:
3358
+ continue
3359
+ if not self._is_resolved(ref, symtab, scope_path, lib_roots):
3360
+ issue(element, ref)
3361
+ continue
3362
+ if gname not in ("RequirementDefinition", "RequirementUsage"):
3363
+ continue
3364
+ # nested satisfy members: scan the requirement's grammar dict
3365
+ grammar = element.grammar
3366
+ if grammar is None:
3367
+ continue
3368
+ try:
3369
+ grammar_def = grammar.get_definition()
3370
+ except Exception:
3371
+ continue
3372
+ if not isinstance(grammar_def, dict):
3373
+ continue
3374
+ for sat in _find_named_dicts(
3375
+ grammar_def, "SatisfyRequirementUsage"):
3376
+ by_ref = _satisfy_by_ref(sat)
3377
+ if not by_ref:
3378
+ continue
3379
+ if not self._is_resolved(
3380
+ by_ref, symtab, scope_path, lib_roots):
3381
+ issue(element, by_ref)
3382
+ return issues
3383
+
3384
+ def _check_verify_targets(
3385
+ self,
3386
+ model: Any,
3387
+ symtab: "SymbolTable",
3388
+ lib_roots: list,
3389
+ ) -> list[SemanticIssue]:
3390
+ """Resolve ``verify <vc>`` members inside requirements (Goal 9).
3391
+
3392
+ ``verify v1 : VC;`` in a requirement body parses as a
3393
+ VerifyRequirementUsage whose ``ors`` holds the referenced
3394
+ verification-case name. Notably the visitor drops the
3395
+ ``: VC`` typing specialization entirely (``fsp`` is empty), so
3396
+ a typo'd verification-case *type* is invisible — but the
3397
+ member name reference is checkable: resolve it against the
3398
+ symbol table in the requirement's scope. Unresolved targets
3399
+ produce UNRESOLVED_VERIFY_TARGET errors (same contract as
3400
+ UNRESOLVED_TRACE_TARGET for satisfy).
3401
+ """
3402
+ issues: list[SemanticIssue] = []
3403
+ for element, scope_path in self._walk_usages(model):
3404
+ # verify members live inside Requirement grammar trees
3405
+ # (no VerifyRequirementUsage object of their own)
3406
+ if type(element).__name__ != "Requirement":
3407
+ continue
3408
+ grammar = getattr(element, "grammar", None)
3409
+ if grammar is None:
3410
+ continue
3411
+ try:
3412
+ grammar_def = grammar.get_definition()
3413
+ except Exception:
3414
+ continue
3415
+ if not isinstance(grammar_def, dict):
3416
+ continue
3417
+ for vr in _find_named_dicts(grammar_def, "VerifyRequirementUsage"):
3418
+ ors = vr.get("ors")
3419
+ if not isinstance(ors, dict):
3420
+ continue
3421
+ rf = ors.get("referencedFeature") or {}
3422
+ # referencedFeature *is* the QualifiedName node here
3423
+ names = rf.get("names") if isinstance(rf, dict) else None
3424
+ if not names:
3425
+ continue
3426
+ ref = "::".join(str(n) for n in names)
3427
+ if self._is_resolved(ref, symtab, scope_path, lib_roots):
3428
+ continue
3429
+ issues.append(SemanticIssue(
3430
+ severity="error",
3431
+ code="UNRESOLVED_VERIFY_TARGET",
3432
+ message=(
3433
+ f"verify target '{ref}' in requirement "
3434
+ f"'{getattr(element, 'name', '<anonymous>')}' "
3435
+ "does not resolve to a defined element"),
3436
+ element=element,
3437
+ reference=ref,
3438
+ ))
3439
+ return issues
3440
+
3441
+ def _check_connector_directions(self, model: Any) -> list[SemanticIssue]:
3442
+ """Check connection-end port direction compatibility (Goal 9).
3443
+
3444
+ ``connection c connect a.p1 to b.p2;`` — when both end ports
3445
+ carry explicit directions and neither is ``inout``, wiring
3446
+ ``out`` to ``out`` or ``in`` to ``in`` flags
3447
+ CONNECTOR_DIRECTION_MISMATCH (warning — conjugated ports and
3448
+ exotic flow conventions exist, so this is advisory, not an
3449
+ error). Ends without a direction keyword, ``inout`` ends,
3450
+ chains deeper than two segments and unresolvable parts are
3451
+ skipped.
3452
+ """
3453
+ issues: list[SemanticIssue] = []
3454
+ try:
3455
+ from sysmlpy.sim import load_model_grammar
3456
+ visit = load_model_grammar(model)
3457
+ except Exception:
3458
+ return issues
3459
+
3460
+ scope_ports: dict = {} # def/usage name -> {port: direction}
3461
+ part_typing: dict = {} # part usage name -> typed-by name
3462
+ member_typing: dict = {} # (container name, member) -> typed-by
3463
+ connections: list = [] # (name, scope_stack, [chain, ...])
3464
+
3465
+ def walk2(node, scope_stack):
3466
+ if isinstance(node, dict):
3467
+ nm = node.get("name")
3468
+ declared = _find_declared_name(node)
3469
+ new_stack = scope_stack
3470
+ if declared and isinstance(nm, str) and (
3471
+ nm.endswith("Usage") or nm.endswith("Definition")):
3472
+ if nm != "PortUsage":
3473
+ new_stack = scope_stack + [declared]
3474
+ if nm == "PortUsage":
3475
+ d = _port_direction(node)
3476
+ if d and scope_stack:
3477
+ scope_ports.setdefault(
3478
+ scope_stack[-1], {})[declared] = d
3479
+ elif nm == "ConnectionUsage":
3480
+ chains = []
3481
+ part = node.get("part") or {}
3482
+ bp = part.get("part") or {}
3483
+ for rel in _as_list_dicts(
3484
+ bp.get("ownedRelationship")):
3485
+ if rel.get("name") != "ConnectorEndMember":
3486
+ continue
3487
+ ends = _as_list_dicts(
3488
+ rel.get("ownedRelatedElement"))
3489
+ if not ends:
3490
+ continue
3491
+ chain = _connector_end_chain(ends[0])
3492
+ if chain:
3493
+ chains.append(chain)
3494
+ if len(chains) == 2:
3495
+ connections.append((declared, new_stack, chains))
3496
+ elif nm.endswith("Usage"):
3497
+ t = _usage_typed_by(node)
3498
+ if t:
3499
+ part_typing[declared] = t
3500
+ if scope_stack:
3501
+ member_typing[(scope_stack[-1],
3502
+ declared)] = t
3503
+ for k, v in node.items():
3504
+ if isinstance(v, (dict, list)):
3505
+ walk2(v, new_stack)
3506
+ elif isinstance(node, list):
3507
+ for x in node:
3508
+ walk2(x, scope_stack)
3509
+
3510
+ walk2(visit, [])
3511
+
3512
+ def end_direction(chain, scope_stack):
3513
+ if len(chain) == 2:
3514
+ part_name, port_name = chain
3515
+ t = part_typing.get(part_name)
3516
+ if t and port_name in scope_ports.get(t, {}):
3517
+ return scope_ports[t][port_name]
3518
+ return scope_ports.get(part_name, {}).get(port_name)
3519
+ if len(chain) == 1:
3520
+ port_name = chain[0]
3521
+ for scope in reversed(scope_stack):
3522
+ if port_name in scope_ports.get(scope, {}):
3523
+ return scope_ports[scope][port_name]
3524
+ t = part_typing.get(scope)
3525
+ if t and port_name in scope_ports.get(t, {}):
3526
+ return scope_ports[t][port_name]
3527
+ # deep chains (>=3 segments: bus.a.p3) — resolve segment by
3528
+ # segment: seg0 via the part's typing, middle segments via
3529
+ # member typing in the resolved container, final port via
3530
+ # the container's port directions.
3531
+ first = chain[0]
3532
+ cur = part_typing.get(first)
3533
+ if cur is None:
3534
+ for scope in reversed(scope_stack):
3535
+ t = member_typing.get((scope, first))
3536
+ if t:
3537
+ cur = t
3538
+ break
3539
+ if cur is None:
3540
+ return None
3541
+ for seg in chain[1:-1]:
3542
+ t = member_typing.get((cur, seg))
3543
+ if t is None:
3544
+ # members declared on the seg0 *usage* itself
3545
+ t = member_typing.get((first, seg))
3546
+ if t is None:
3547
+ return None
3548
+ cur = t
3549
+ return scope_ports.get(cur, {}).get(chain[-1])
3550
+
3551
+ for cname, cstack, chains in connections:
3552
+ d1 = end_direction(chains[0], cstack)
3553
+ d2 = end_direction(chains[1], cstack)
3554
+ if not d1 or not d2:
3555
+ continue
3556
+ if d1 == "inout" or d2 == "inout":
3557
+ continue
3558
+ if d1 == d2:
3559
+ issues.append(SemanticIssue(
3560
+ severity="warning",
3561
+ code="CONNECTOR_DIRECTION_MISMATCH",
3562
+ message=(
3563
+ f"Connection '{cname}' binds two '{d1}' ports "
3564
+ f"({chains[0][-1]} -> {chains[1][-1]}); a "
3565
+ "connection normally pairs 'out' with 'in'"),
3566
+ reference=cname,
3567
+ ))
3568
+ return issues
3569
+
3182
3570
  def _check_state_machines(self, model: Any) -> list[SemanticIssue]:
3183
3571
  """OCL well-formedness for ``state def`` machines (Goal 9).
3184
3572
 
@@ -224,6 +224,59 @@ def _qualified_name(obj) -> str:
224
224
  return "::".join(reversed(segments))
225
225
 
226
226
 
227
+ def _find_named_dicts_local(node, name: str) -> list:
228
+ """Locate every dict with ``dict["name"] == name`` in a tree.
229
+
230
+ Local copy of the semantic-module helper (semantic imports this
231
+ module, so a shared util would be circular).
232
+ """
233
+ out: list = []
234
+
235
+ def walk(n):
236
+ if isinstance(n, dict):
237
+ if n.get("name") == name:
238
+ out.append(n)
239
+ for v in n.values():
240
+ if isinstance(v, (dict, list)):
241
+ walk(v)
242
+ elif isinstance(n, list):
243
+ for item in n:
244
+ if isinstance(item, (dict, list)):
245
+ walk(item)
246
+
247
+ walk(node)
248
+ return out
249
+
250
+
251
+ def _nested_satisfy_ref(satisfy_dict: dict):
252
+ """``(target, by_part)`` of a SatisfyRequirementUsage dict.
253
+
254
+ ``ors.referencedFeature.names`` carries the target requirement;
255
+ ``ssm`` (SatisfactionSubjectMember) nests
256
+ FeatureChainMember.memberElement (QualifiedName) whose last
257
+ segment is the satisfying feature.
258
+ """
259
+ ors = satisfy_dict.get("ors")
260
+ if not isinstance(ors, dict):
261
+ return None
262
+ rf = ors.get("referencedFeature") or {}
263
+ names = rf.get("names") if isinstance(rf, dict) else None
264
+ if not names:
265
+ return None
266
+ target = "::".join(str(n) for n in names)
267
+
268
+ ssm = satisfy_dict.get("ssm")
269
+ by_ref = None
270
+ if isinstance(ssm, dict):
271
+ for m in _find_named_dicts_local(ssm, "FeatureChainMember"):
272
+ me = m.get("memberElement") or {}
273
+ mnames = me.get("names")
274
+ if isinstance(mnames, list) and mnames:
275
+ by_ref = "::".join(str(n) for n in mnames)
276
+ break
277
+ return target, by_ref
278
+
279
+
227
280
  def _last_segment(ref: str) -> str:
228
281
  """Last segment of a dotted/qualified reference (``Pkg::r1`` → ``r1``)."""
229
282
  for sep in ("::", "."):
@@ -300,6 +353,26 @@ def extract_traceability(model) -> TraceabilityReport:
300
353
  is_definition=(gclass == "RequirementDefinition"),
301
354
  )
302
355
  traces.append(trace)
356
+ # Nested satisfy members (``requirement top { satisfy top by v;
357
+ # }``) parse as SatisfyRequirementUsage dicts inside the
358
+ # requirement's grammar — the visitor handles nested *verify*
359
+ # members but not satisfy, so they are invisible to pass 2 and
360
+ # the requirement would read as uncovered. Record the edge.
361
+ if grammar is not None:
362
+ try:
363
+ grammar_def = grammar.get_definition()
364
+ except Exception:
365
+ grammar_def = None
366
+ if isinstance(grammar_def, dict):
367
+ for sat in _find_named_dicts_local(
368
+ grammar_def, "SatisfyRequirementUsage"):
369
+ ref = _nested_satisfy_ref(sat)
370
+ if ref is None:
371
+ continue
372
+ target, by_part = ref
373
+ if by_part and _last_segment(target) == name and (
374
+ by_part not in trace.satisfied_by):
375
+ trace.satisfied_by.append(by_part)
303
376
  # Index by both the bare name and every suffix of the qualified
304
377
  # name so `Pkg::req` / `req` / `Sub::req` references all resolve.
305
378
  traces_by_name.setdefault(name, trace)
@@ -3239,6 +3239,13 @@ class Requirement(Usage):
3239
3239
  c = Requirement(definition=True).load_from_grammar(target)
3240
3240
  c.parent = self
3241
3241
  self.children.append(c)
3242
+ elif target_cls in ("SatisfyRequirementUsage",
3243
+ "VerifyRequirementUsage"):
3244
+ # satisfy members are extracted from the grammar
3245
+ # dicts by traceability/semantic (nested verify
3246
+ # members ride _extract_verification_member); no
3247
+ # Requirement child belongs here.
3248
+ pass
3242
3249
  elif target_cls and "Requirement" in target_cls:
3243
3250
  print(f"[Requirement] Unhandled nested requirement type: {target_cls}")
3244
3251
 
File without changes
File without changes
File without changes
File without changes