sysmlpy 0.85.0__tar.gz → 0.87.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 (160) hide show
  1. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/PKG-INFO +1 -1
  2. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/pyproject.toml +6 -1
  3. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/__init__.py +1 -1
  4. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/antlr_visitor.py +204 -33
  5. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/definition.py +19 -0
  6. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/grammar/classes.py +119 -12
  7. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/store.py +213 -2
  8. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/usage.py +16 -1
  9. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/LICENSE +0 -0
  10. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/README.md +0 -0
  11. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/__main__.py +0 -0
  12. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/antlr/README.md +0 -0
  13. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/antlr/SysMLv2Lexer.interp +0 -0
  14. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/antlr/SysMLv2Lexer.py +0 -0
  15. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/antlr/SysMLv2Lexer.tokens +0 -0
  16. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/antlr/SysMLv2Parser.interp +0 -0
  17. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/antlr/SysMLv2Parser.py +0 -0
  18. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/antlr/SysMLv2Parser.tokens +0 -0
  19. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/antlr/SysMLv2ParserListener.py +0 -0
  20. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/antlr/SysMLv2ParserVisitor.py +0 -0
  21. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.interp +0 -0
  22. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.py +0 -0
  23. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.tokens +0 -0
  24. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/antlr_parser.py +0 -0
  25. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/boxes_view.py +0 -0
  26. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/dfa_cache.py +0 -0
  27. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/diff.py +0 -0
  28. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/evaluator.py +0 -0
  29. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/examples/attribute_values.py +0 -0
  30. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/examples/part_attributes.py +0 -0
  31. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/examples/tuples_sequences.py +0 -0
  32. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/formatting.py +0 -0
  33. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/grammar/antlr4/README.md +0 -0
  34. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.g4 +0 -0
  35. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.interp +0 -0
  36. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.py +0 -0
  37. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.tokens +0 -0
  38. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.g4 +0 -0
  39. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.interp +0 -0
  40. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.py +0 -0
  41. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.tokens +0 -0
  42. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/grammar/antlr4/SysMLv2ParserListener.py +0 -0
  43. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/grammar/antlr4/SysMLv2ParserVisitor.py +0 -0
  44. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/grammar/antlr4/desc.xml +0 -0
  45. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/grammar/antlr4/examples/camera.sysml +0 -0
  46. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/grammar/antlr4/examples/toaster-system.sysml +0 -0
  47. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/grammar/antlr4/examples/vehicle-model.sysml +0 -0
  48. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/grammar/antlr4/pom.xml +0 -0
  49. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/interchange.py +0 -0
  50. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/LICENSE +0 -0
  51. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/README.md +0 -0
  52. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/__init__.py +0 -0
  53. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Analysis/AnalysisTooling.sysml +0 -0
  54. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Analysis/SampledFunctions.sysml +0 -0
  55. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Analysis/StateSpaceRepresentation.sysml +0 -0
  56. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Analysis/TradeStudies.sysml +0 -0
  57. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Cause and Effect/CausationConnections.sysml +0 -0
  58. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Cause and Effect/CauseAndEffect.sysml +0 -0
  59. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Geometry/ShapeItems.sysml +0 -0
  60. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Geometry/SpatialItems.sysml +0 -0
  61. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Metadata/ImageMetadata.sysml +0 -0
  62. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Metadata/ModelingMetadata.sysml +0 -0
  63. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Metadata/ParametersOfInterestMetadata.sysml +0 -0
  64. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Metadata/RiskMetadata.sysml +0 -0
  65. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Quantities and Units/ISQ.sysml +0 -0
  66. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Quantities and Units/ISQAcoustics.sysml +0 -0
  67. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Quantities and Units/ISQAtomicNuclear.sysml +0 -0
  68. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Quantities and Units/ISQBase.sysml +0 -0
  69. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Quantities and Units/ISQCharacteristicNumbers.sysml +0 -0
  70. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Quantities and Units/ISQChemistryMolecular.sysml +0 -0
  71. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Quantities and Units/ISQCondensedMatter.sysml +0 -0
  72. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Quantities and Units/ISQElectromagnetism.sysml +0 -0
  73. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Quantities and Units/ISQInformation.sysml +0 -0
  74. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Quantities and Units/ISQLight.sysml +0 -0
  75. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Quantities and Units/ISQMechanics.sysml +0 -0
  76. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Quantities and Units/ISQSpaceTime.sysml +0 -0
  77. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Quantities and Units/ISQThermodynamics.sysml +0 -0
  78. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Quantities and Units/MeasurementRefCalculations.sysml +0 -0
  79. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Quantities and Units/MeasurementReferences.sysml +0 -0
  80. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Quantities and Units/Quantities.sysml +0 -0
  81. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Quantities and Units/QuantityCalculations.sysml +0 -0
  82. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Quantities and Units/SI.sysml +0 -0
  83. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Quantities and Units/SIPrefixes.sysml +0 -0
  84. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Quantities and Units/TensorCalculations.sysml +0 -0
  85. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Quantities and Units/Time.sysml +0 -0
  86. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Quantities and Units/USCustomaryUnits.sysml +0 -0
  87. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Quantities and Units/VectorCalculations.sysml +0 -0
  88. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Requirement Derivation/DerivationConnections.sysml +0 -0
  89. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/domain/Requirement Derivation/RequirementDerivation.sysml +0 -0
  90. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/Base.kerml +0 -0
  91. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/BaseFunctions.kerml +0 -0
  92. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/BooleanFunctions.kerml +0 -0
  93. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/Clocks.kerml +0 -0
  94. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/CollectionFunctions.kerml +0 -0
  95. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/Collections.kerml +0 -0
  96. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/ComplexFunctions.kerml +0 -0
  97. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/ControlFunctions.kerml +0 -0
  98. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/ControlPerformances.kerml +0 -0
  99. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/DataFunctions.kerml +0 -0
  100. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/FeatureReferencingPerformances.kerml +0 -0
  101. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/IntegerFunctions.kerml +0 -0
  102. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/KerML.kerml +0 -0
  103. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/Links.kerml +0 -0
  104. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/Metaobjects.kerml +0 -0
  105. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/NaturalFunctions.kerml +0 -0
  106. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/NumericalFunctions.kerml +0 -0
  107. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/Objects.kerml +0 -0
  108. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/Observation.kerml +0 -0
  109. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/OccurrenceFunctions.kerml +0 -0
  110. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/Occurrences.kerml +0 -0
  111. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/Performances.kerml +0 -0
  112. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/RationalFunctions.kerml +0 -0
  113. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/RealFunctions.kerml +0 -0
  114. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/ScalarFunctions.kerml +0 -0
  115. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/ScalarValues.kerml +0 -0
  116. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/SequenceFunctions.kerml +0 -0
  117. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/SpatialFrames.kerml +0 -0
  118. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/StatePerformances.kerml +0 -0
  119. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/StringFunctions.kerml +0 -0
  120. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/Transfers.kerml +0 -0
  121. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/TransitionPerformances.kerml +0 -0
  122. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/TrigFunctions.kerml +0 -0
  123. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/Triggers.kerml +0 -0
  124. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/VectorFunctions.kerml +0 -0
  125. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/kernel/VectorValues.kerml +0 -0
  126. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/systems/Actions.sysml +0 -0
  127. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/systems/Allocations.sysml +0 -0
  128. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/systems/AnalysisCases.sysml +0 -0
  129. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/systems/Attributes.sysml +0 -0
  130. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/systems/Calculations.sysml +0 -0
  131. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/systems/Cases.sysml +0 -0
  132. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/systems/Connections.sysml +0 -0
  133. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/systems/Constraints.sysml +0 -0
  134. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/systems/Flows.sysml +0 -0
  135. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/systems/Interfaces.sysml +0 -0
  136. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/systems/Items.sysml +0 -0
  137. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/systems/Metadata.sysml +0 -0
  138. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/systems/Parts.sysml +0 -0
  139. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/systems/Ports.sysml +0 -0
  140. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/systems/Requirements.sysml +0 -0
  141. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/systems/StandardViewDefinitions.sysml +0 -0
  142. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/systems/States.sysml +0 -0
  143. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/systems/SysML.sysml +0 -0
  144. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/systems/UseCases.sysml +0 -0
  145. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/systems/VerificationCases.sysml +0 -0
  146. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/library/systems/Views.sysml +0 -0
  147. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/lsp/__init__.py +0 -0
  148. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/lsp/__main__.py +0 -0
  149. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/lsp/protocol.py +0 -0
  150. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/lsp/server.py +0 -0
  151. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/lsp/stdio.py +0 -0
  152. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/navigate.py +0 -0
  153. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/plantuml.py +0 -0
  154. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/project.py +0 -0
  155. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/semantic.py +0 -0
  156. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/sim.py +0 -0
  157. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/spreadsheet.py +0 -0
  158. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/traceability.py +0 -0
  159. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/us_customary_units.txt +0 -0
  160. {sysmlpy-0.85.0 → sysmlpy-0.87.0}/src/sysmlpy/validator.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sysmlpy
3
- Version: 0.85.0
3
+ Version: 0.87.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.85.0"
9
+ version = "0.87.0"
10
10
  description = ""
11
11
  authors = [{ name = "Jon R. Fox (mycr0ft)", email = "jon.fox@drfox.com" }]
12
12
  readme = "README.md"
@@ -38,3 +38,8 @@ sysmlpy-lsp = "sysmlpy.lsp.stdio:main"
38
38
  [tool.poetry.group.dev.dependencies]
39
39
  pytest = ">=8.0,<9.0"
40
40
 
41
+ [tool.pytest.ini_options]
42
+ markers = [
43
+ "conformance: OMG 2026-03 XPect parse conformance suite (slow; deselect with -m 'not conformance')",
44
+ ]
45
+
@@ -34,7 +34,7 @@ __all__ = [
34
34
  "render_state_transition_view_svg", "boxes_view",
35
35
  ]
36
36
  __author__ = "Jon Fox"
37
- __version__ = "0.85.0"
37
+ __version__ = "0.87.0"
38
38
 
39
39
  from sysmlpy.usage import (
40
40
  Item, Attribute, Part, Port, Action, Reference, UseCase, Requirement, Interface, Message,
@@ -2383,7 +2383,7 @@ def _make_assert_constraint_usage_dict(acu_ctx, prefix=None):
2383
2383
  if hasattr(cud, 'valuePart') and cud.valuePart():
2384
2384
  vp = cud.valuePart()
2385
2385
  if hasattr(vp, 'ownedExpression') and vp.ownedExpression():
2386
- expr = _visit_expression(vp.ownedExpression())
2386
+ expr = _visit_owned_expression(vp.ownedExpression())
2387
2387
  if expr:
2388
2388
  valuepart = {"name": "ValuePart", "ownedRelationship": expr}
2389
2389
 
@@ -2497,7 +2497,7 @@ def _make_satisfy_requirement_usage_dict(sru_ctx, prefix=None):
2497
2497
  if hasattr(sru_ctx, 'valuePart') and sru_ctx.valuePart():
2498
2498
  vp = sru_ctx.valuePart()
2499
2499
  if hasattr(vp, 'ownedExpression') and vp.ownedExpression():
2500
- expr = _visit_expression(vp.ownedExpression())
2500
+ expr = _visit_owned_expression(vp.ownedExpression())
2501
2501
  if expr:
2502
2502
  valuepart = {"name": "ValuePart", "ownedRelationship": expr}
2503
2503
 
@@ -5024,30 +5024,48 @@ def _visit_entry_transition_member(ctx):
5024
5024
 
5025
5025
 
5026
5026
  def _visit_guarded_target_succession(ctx):
5027
- """Visit a guardedTargetSuccession context."""
5027
+ """Visit a guardedTargetSuccession context.
5028
+
5029
+ guardedTargetSuccession : guardExpressionMember THEN transitionSuccessionMember
5030
+
5031
+ Emits the ``ownedRelationship`` member-list shape the
5032
+ ``GuardedTargetSuccession`` grammar class loads (guard + target were
5033
+ silently dropped before v0.87.0, and the old dict shape crashed the
5034
+ class loader with a KeyError).
5035
+ """
5028
5036
  if ctx is None:
5029
5037
  return None
5030
-
5031
- guard = None
5032
- if hasattr(ctx, 'guardExpression') and ctx.guardExpression():
5033
- guard_dict = _visit_expression(ctx.guardExpression())
5034
- guard = {
5035
- "name": "GuardExpression",
5036
- "expression": guard_dict
5037
- }
5038
-
5039
- succession = None
5040
- if hasattr(ctx, 'succession') and ctx.succession():
5041
- succ = ctx.succession()
5042
- if isinstance(succ, list):
5043
- succ = succ[0]
5044
- if succ:
5045
- succession = _visit_succession(succ)
5046
-
5038
+
5039
+ owned_relationship = []
5040
+
5041
+ gem = None
5042
+ if hasattr(ctx, 'guardExpressionMember') and ctx.guardExpressionMember():
5043
+ gem = ctx.guardExpressionMember()
5044
+ if isinstance(gem, list):
5045
+ gem = gem[0]
5046
+ guard_member = _visit_guard_expression_member(gem)
5047
+ if guard_member:
5048
+ owned_relationship.append(guard_member)
5049
+
5050
+ tsm = None
5051
+ if hasattr(ctx, 'transitionSuccessionMember') and ctx.transitionSuccessionMember():
5052
+ tsm = ctx.transitionSuccessionMember()
5053
+ if isinstance(tsm, list):
5054
+ tsm = tsm[0]
5055
+ ts = None
5056
+ if hasattr(tsm, 'transitionSuccession') and tsm.transitionSuccession():
5057
+ ts = tsm.transitionSuccession()
5058
+ if isinstance(ts, list):
5059
+ ts = ts[0]
5060
+ if ts:
5061
+ owned_relationship.append({
5062
+ "name": "TransitionSuccessionMember",
5063
+ "ownedRelatedElement": _visit_transition_succession(ts),
5064
+ })
5065
+
5047
5066
  return {
5048
5067
  "name": "GuardedTargetSuccession",
5049
- "guard": guard,
5050
- "ownedRelatedElement": succession
5068
+ "ownedRelationship": owned_relationship,
5051
5069
  }
5052
5070
 
5053
5071
 
@@ -6661,6 +6679,10 @@ def _make_connection_usage_dict(ctx, prefix=None):
6661
6679
  """Create a ConnectionUsage dictionary."""
6662
6680
  name, shortname = _get_usage_identification(ctx)
6663
6681
 
6682
+ # Typed-by etc. on the connection declaration (e.g.
6683
+ # ``connection cn1 : CD``) — previously hardcoded to None.
6684
+ specialization = _build_full_specialization_from_ctx(ctx)
6685
+
6664
6686
  # Parse the connector part (``connect X to Y``) so endpoints survive
6665
6687
  # into the grammar object tree (v0.67.0 — fixes the "part": None stub)
6666
6688
  # connectionUsage: occurrenceUsagePrefix ( CONNECTION usageDeclaration?
@@ -6731,7 +6753,7 @@ def _make_connection_usage_dict(ctx, prefix=None):
6731
6753
  "declaredShortName": shortname,
6732
6754
  "declaredName": name
6733
6755
  },
6734
- "specialization": None
6756
+ "specialization": specialization
6735
6757
  }
6736
6758
  },
6737
6759
  "part": conn_part_dict,
@@ -8050,6 +8072,9 @@ def _make_view_usage_dict(ctx, prefix=None):
8050
8072
  body_items = []
8051
8073
  if hasattr(ctx, 'viewBody') and ctx.viewBody():
8052
8074
  body_items = _visit_view_body_dict(ctx.viewBody())
8075
+ # Typed-by / redefinition / subsets on the view declaration
8076
+ # (e.g. ``view v : Engine``) — previously hardcoded to None.
8077
+ specialization = _build_full_specialization_from_ctx(ctx)
8053
8078
  return {
8054
8079
  "name": "PackageMember",
8055
8080
  "prefix": None,
@@ -8071,7 +8096,7 @@ def _make_view_usage_dict(ctx, prefix=None):
8071
8096
  "declaredShortName": shortname,
8072
8097
  "declaredName": name
8073
8098
  },
8074
- "specialization": None
8099
+ "specialization": specialization
8075
8100
  }
8076
8101
  },
8077
8102
  "body": {
@@ -8092,6 +8117,7 @@ def _make_viewpoint_usage_dict(ctx, prefix=None):
8092
8117
  """
8093
8118
  name = None
8094
8119
  shortname = None
8120
+ specialization = None
8095
8121
  if ctx is not None:
8096
8122
  cud = None
8097
8123
  if hasattr(ctx, 'constraintUsageDeclaration') and ctx.constraintUsageDeclaration():
@@ -8112,6 +8138,11 @@ def _make_viewpoint_usage_dict(ctx, prefix=None):
8112
8138
  elif len(name_list) == 1:
8113
8139
  name_text = name_list[0].getText()
8114
8140
  name, shortname = _extract_name_shortname(name_text)
8141
+
8142
+ # Typed-by etc. on the viewpoint declaration (e.g.
8143
+ # ``viewpoint v : R``) — previously dropped.
8144
+ if ud is not None:
8145
+ specialization = _build_full_specialization_from_ud(ud)
8115
8146
 
8116
8147
  return {
8117
8148
  "name": "PackageMember",
@@ -8134,7 +8165,7 @@ def _make_viewpoint_usage_dict(ctx, prefix=None):
8134
8165
  "declaredShortName": shortname,
8135
8166
  "declaredName": name
8136
8167
  },
8137
- "specialization": None
8168
+ "specialization": specialization
8138
8169
  }
8139
8170
  },
8140
8171
  "body": {
@@ -8158,6 +8189,7 @@ def _make_concern_usage_dict(ctx, prefix=None):
8158
8189
  """
8159
8190
  name = None
8160
8191
  shortname = None
8192
+ specialization = None
8161
8193
  if ctx is not None:
8162
8194
  cud = None
8163
8195
  if hasattr(ctx, 'constraintUsageDeclaration') and ctx.constraintUsageDeclaration():
@@ -8178,6 +8210,10 @@ def _make_concern_usage_dict(ctx, prefix=None):
8178
8210
  elif len(name_list) == 1:
8179
8211
  name_text = name_list[0].getText()
8180
8212
  name, shortname = _extract_name_shortname(name_text)
8213
+
8214
+ # Typed-by etc. on the concern declaration — previously dropped.
8215
+ if ud is not None:
8216
+ specialization = _build_full_specialization_from_ud(ud)
8181
8217
 
8182
8218
  return {
8183
8219
  "name": "PackageMember",
@@ -8200,7 +8236,7 @@ def _make_concern_usage_dict(ctx, prefix=None):
8200
8236
  "declaredShortName": shortname,
8201
8237
  "declaredName": name
8202
8238
  },
8203
- "specialization": None
8239
+ "specialization": specialization
8204
8240
  }
8205
8241
  },
8206
8242
  "body": {
@@ -8236,6 +8272,7 @@ def _make_allocation_usage_dict(ctx, prefix=None):
8236
8272
  name = None
8237
8273
  shortname = None
8238
8274
  connector_part = None
8275
+ specialization = None
8239
8276
  if ctx is not None:
8240
8277
  aud = None
8241
8278
  if hasattr(ctx, 'allocationUsageDeclaration') and ctx.allocationUsageDeclaration():
@@ -8263,6 +8300,11 @@ def _make_allocation_usage_dict(ctx, prefix=None):
8263
8300
  if aud and hasattr(aud, 'connectorPart') and aud.connectorPart():
8264
8301
  connector_part = _build_connector_part_dict(aud.connectorPart())
8265
8302
 
8303
+ # Typed-by etc. on the allocation declaration (e.g.
8304
+ # ``allocation a1 : AD``) — previously dropped.
8305
+ if ud is not None:
8306
+ specialization = _build_full_specialization_from_ud(ud)
8307
+
8266
8308
  return {
8267
8309
  "name": "PackageMember",
8268
8310
  "prefix": None,
@@ -8284,7 +8326,7 @@ def _make_allocation_usage_dict(ctx, prefix=None):
8284
8326
  "declaredShortName": shortname,
8285
8327
  "declaredName": name
8286
8328
  },
8287
- "specialization": None
8329
+ "specialization": specialization
8288
8330
  }
8289
8331
  },
8290
8332
  "part": connector_part,
@@ -8309,6 +8351,7 @@ def _make_rendering_usage_dict(ctx, prefix=None):
8309
8351
  """
8310
8352
  name = None
8311
8353
  shortname = None
8354
+ specialization = None
8312
8355
  if ctx is not None:
8313
8356
  # RenderingUsage uses just `usage` (not usageDeclaration)
8314
8357
  usage = None
@@ -8330,6 +8373,12 @@ def _make_rendering_usage_dict(ctx, prefix=None):
8330
8373
  elif len(name_list) == 1:
8331
8374
  name_text = name_list[0].getText()
8332
8375
  name, shortname = _extract_name_shortname(name_text)
8376
+
8377
+ # Typed-by etc. on the rendering declaration (e.g.
8378
+ # ``rendering r1 : RD``) — previously dropped. The rendering
8379
+ # usage ctx carries ``usage`` directly, so the ctx-based
8380
+ # builder works here.
8381
+ specialization = _build_full_specialization_from_ctx(ctx)
8333
8382
 
8334
8383
  return {
8335
8384
  "name": "PackageMember",
@@ -8352,7 +8401,7 @@ def _make_rendering_usage_dict(ctx, prefix=None):
8352
8401
  "declaredShortName": shortname,
8353
8402
  "declaredName": name
8354
8403
  },
8355
- "specialization": None
8404
+ "specialization": specialization
8356
8405
  }
8357
8406
  },
8358
8407
  "body": {
@@ -8376,6 +8425,7 @@ def _make_individual_usage_dict(ctx, prefix=None):
8376
8425
  """
8377
8426
  name = None
8378
8427
  shortname = None
8428
+ specialization = None
8379
8429
  if ctx is not None:
8380
8430
  # individualUsage has `usage` at the end
8381
8431
  usage = None
@@ -8397,6 +8447,9 @@ def _make_individual_usage_dict(ctx, prefix=None):
8397
8447
  elif len(name_list) == 1:
8398
8448
  name_text = name_list[0].getText()
8399
8449
  name, shortname = _extract_name_shortname(name_text)
8450
+
8451
+ # Typed-by etc. on the individual declaration — previously dropped.
8452
+ specialization = _build_full_specialization_from_ctx(ctx)
8400
8453
 
8401
8454
  # Use IndividualUsageSimple per our simplified model
8402
8455
  return {
@@ -8420,7 +8473,7 @@ def _make_individual_usage_dict(ctx, prefix=None):
8420
8473
  "declaredShortName": shortname,
8421
8474
  "declaredName": name
8422
8475
  },
8423
- "specialization": None
8476
+ "specialization": specialization
8424
8477
  }
8425
8478
  },
8426
8479
  "body": {
@@ -8992,7 +9045,7 @@ def _make_view_rendering_member_dict(ctx, prefix=None):
8992
9045
  "declaredShortName": shortname,
8993
9046
  "declaredName": name
8994
9047
  },
8995
- "specialization": None
9048
+ "specialization": _build_full_specialization_from_ctx(usage_ctx)
8996
9049
  }
8997
9050
  },
8998
9051
  "completion": None
@@ -9074,6 +9127,102 @@ def _make_render_state_member_dict(ctx, prefix=None):
9074
9127
  }
9075
9128
 
9076
9129
 
9130
+ def _make_element_filter_member_dict(ctx):
9131
+ """Visit an elementFilterMember context and return its dict.
9132
+
9133
+ elementFilterMember : memberPrefix FILTER ownedExpression SEMI
9134
+
9135
+ e.g. ``filter @e1;`` — the element filter of a view.
9136
+ """
9137
+ if ctx is None:
9138
+ return None
9139
+
9140
+ prefix = None
9141
+ if hasattr(ctx, 'memberPrefix') and ctx.memberPrefix():
9142
+ mp = ctx.memberPrefix()
9143
+ if hasattr(mp, 'visibilityIndicator') and mp.visibilityIndicator():
9144
+ prefix = {
9145
+ "name": "MemberPrefix",
9146
+ "visibility": _visit_visibility_indicator_dict(mp.visibilityIndicator()),
9147
+ }
9148
+
9149
+ expr = None
9150
+ if hasattr(ctx, 'ownedExpression') and ctx.ownedExpression():
9151
+ expr = _visit_owned_expression(ctx.ownedExpression())
9152
+
9153
+ return {
9154
+ "name": "ElementFilterMember",
9155
+ "prefix": prefix,
9156
+ "ownedRelatedElement": expr,
9157
+ }
9158
+
9159
+
9160
+ def _make_expose_dict(ctx):
9161
+ """Visit an expose context and return its dict.
9162
+
9163
+ expose : EXPOSE ( membershipExpose | namespaceExpose ) relationshipBody
9164
+ membershipExpose : membershipImport
9165
+ namespaceExpose : namespaceImport
9166
+
9167
+ e.g. ``expose e;`` (membership form) or ``expose P::*;`` (namespace
9168
+ form). The membership/namespace payload reuses the Import dict
9169
+ shapes (without the import prefix).
9170
+ """
9171
+ if ctx is None:
9172
+ return None
9173
+
9174
+ relationship = None
9175
+
9176
+ if hasattr(ctx, 'membershipExpose') and ctx.membershipExpose():
9177
+ me = ctx.membershipExpose()
9178
+ if not hasattr(me, 'membershipImport') or me.membershipImport() is None:
9179
+ print("[visitor] expose: unsupported membershipExpose form, skipped")
9180
+ return None
9181
+ mi = me.membershipImport()
9182
+ qn_text = mi.qualifiedName().getText()
9183
+ is_recursive = mi.STAR_STAR() is not None
9184
+ relationship = {
9185
+ "name": "MembershipExpose",
9186
+ "membership": {
9187
+ "name": "ImportedMembership",
9188
+ "importedMembership": {
9189
+ "name": "QualifiedName",
9190
+ "names": qn_text.split("::"),
9191
+ },
9192
+ "isRecursive": is_recursive,
9193
+ },
9194
+ }
9195
+
9196
+ elif hasattr(ctx, 'namespaceExpose') and ctx.namespaceExpose():
9197
+ ne = ctx.namespaceExpose()
9198
+ if not hasattr(ne, 'namespaceImport') or ne.namespaceImport() is None:
9199
+ print("[visitor] expose: unsupported namespaceExpose form, skipped")
9200
+ return None
9201
+ ns = ne.namespaceImport()
9202
+ if ns.filterPackage() is not None:
9203
+ print("[visitor] expose: filterPackage form not supported, skipped")
9204
+ return None
9205
+ qn_text = ns.qualifiedName().getText()
9206
+ is_recursive = ns.STAR_STAR() is not None
9207
+ relationship = {
9208
+ "name": "NamespaceExpose",
9209
+ "namespace": {
9210
+ "name": "ImportedNamespace",
9211
+ "namespace": {"name": "QualifiedName", "names": qn_text.split("::")},
9212
+ "isRecursive": is_recursive,
9213
+ },
9214
+ }
9215
+
9216
+ if relationship is None:
9217
+ return None
9218
+
9219
+ return {
9220
+ "name": "Expose",
9221
+ "body": {"name": "RelationshipBody", "ownedRelationship": []},
9222
+ "ownedRelationship": relationship,
9223
+ }
9224
+
9225
+
9077
9226
  def _visit_view_definition_body_dict(body_ctx):
9078
9227
  """Visit a viewDefinitionBody and return a list of body item dicts.
9079
9228
 
@@ -9107,7 +9256,9 @@ def _visit_view_definition_body_dict(body_ctx):
9107
9256
  if item_dict:
9108
9257
  items.append(item_dict)
9109
9258
  elif hasattr(item_ctx, 'elementFilterMember') and item_ctx.elementFilterMember():
9110
- pass # TODO: handle elementFilterMember
9259
+ item_dict = _make_element_filter_member_dict(item_ctx.elementFilterMember())
9260
+ if item_dict:
9261
+ items.append(item_dict)
9111
9262
 
9112
9263
  return items
9113
9264
 
@@ -9146,9 +9297,13 @@ def _visit_view_body_dict(body_ctx):
9146
9297
  if item_dict:
9147
9298
  items.append(item_dict)
9148
9299
  elif hasattr(item_ctx, 'elementFilterMember') and item_ctx.elementFilterMember():
9149
- pass # TODO: handle elementFilterMember
9300
+ item_dict = _make_element_filter_member_dict(item_ctx.elementFilterMember())
9301
+ if item_dict:
9302
+ items.append(item_dict)
9150
9303
  elif hasattr(item_ctx, 'expose') and item_ctx.expose():
9151
- pass # TODO: handle expose
9304
+ item_dict = _make_expose_dict(item_ctx.expose())
9305
+ if item_dict:
9306
+ items.append(item_dict)
9152
9307
 
9153
9308
  return items
9154
9309
 
@@ -13976,6 +14131,22 @@ def _build_full_specialization_from_ctx(ctx):
13976
14131
  if isinstance(ud, list):
13977
14132
  ud = ud[0] if ud else None
13978
14133
 
14134
+ if ud is None and hasattr(ctx, 'usageDeclaration') and ctx.usageDeclaration():
14135
+ # Some usage contexts (e.g. viewUsage) carry the usageDeclaration
14136
+ # directly instead of through a nested ``usage`` element.
14137
+ ud = ctx.usageDeclaration()
14138
+ if isinstance(ud, list):
14139
+ ud = ud[0] if ud else None
14140
+
14141
+ if ud is None:
14142
+ return None
14143
+
14144
+ return _build_full_specialization_from_ud(ud)
14145
+
14146
+
14147
+ def _build_full_specialization_from_ud(ud):
14148
+ """Build a full FeatureSpecializationPart dict from a usageDeclaration
14149
+ ANTLR context (the shared core of the ctx-based variant above)."""
13979
14150
  if ud is None:
13980
14151
  return None
13981
14152
 
@@ -1514,6 +1514,25 @@ class Package(Searchable):
1514
1514
  for child in grammar.body.children:
1515
1515
  if child.__class__.__name__ in ('Import', 'AliasMember'):
1516
1516
  self._imports.append(child)
1517
+
1518
+ # v0.87.0: several dispatch branches above assign ``grammar``
1519
+ # manually instead of going through Usage.load_from_grammar, so
1520
+ # _extract_specialization_info never ran for those kinds and
1521
+ # typed_by_name stayed None (viewpoint, concern, allocation,
1522
+ # rendering, metadata, individual, constraint, calculation,
1523
+ # connection, flow, satisfy...). Run it once over the built
1524
+ # children; kinds that went through the full load path already
1525
+ # carry their typing and are skipped by the _typed_by_name guard.
1526
+ for child in self.children:
1527
+ g = getattr(child, 'grammar', None)
1528
+ if g is None or getattr(child, '_typed_by_name', None) is not None:
1529
+ continue
1530
+ extract = getattr(child, '_extract_specialization_info', None)
1531
+ if extract is not None:
1532
+ try:
1533
+ extract(g)
1534
+ except Exception as exc: # pragma: no cover
1535
+ print(f"[Package.load_from_grammar] specialization extraction failed for {getattr(child, 'name', child)!r}: {exc}")
1517
1536
 
1518
1537
  return self
1519
1538
 
@@ -58,8 +58,10 @@ class RootNamespace:
58
58
  except ValueError:
59
59
  try:
60
60
  if valid_definition(definition, "NamespaceBodyElement"):
61
- # This is a KerML Element
62
- pass
61
+ # KerML root: member dicts share the PackageBodyElement
62
+ # shapes, so load them through the same dispatch instead
63
+ # of silently dropping them.
64
+ self.load_package_body(definition.get("ownedRelationship", []))
63
65
  except ValueError: # pragma: no cover
64
66
  print(definition)
65
67
  raise ValueError("Not expecting any other root node names.")
@@ -71,7 +73,14 @@ class RootNamespace:
71
73
  if member["name"] == "PackageMember":
72
74
  memberclass = PackageMember(member)
73
75
  elif member["name"] == "ElementFilterMember":
74
- pass # pragma: no cover
76
+ # Element filters belong to view bodies; a root-level
77
+ # one has no standalone meaning — warn and skip rather
78
+ # than leaving `memberclass` unbound (v0.27.0 contract).
79
+ print(
80
+ "[RootNamespace] Skipping unsupported root member: "
81
+ "ElementFilterMember"
82
+ ) # pragma: no cover
83
+ continue
75
84
  elif member["name"] == "AliasMember":
76
85
  memberclass = AliasMember(member)
77
86
  elif member["name"] == "Import":
@@ -7692,7 +7701,7 @@ class ConnectionUsage:
7692
7701
  self.prefix = None
7693
7702
  self.declaration = None
7694
7703
  self.keyword = "connection"
7695
- self.keyword2 = "connect\n"
7704
+ self.keyword2 = "connect"
7696
7705
  self.part = None
7697
7706
  if definition is not None:
7698
7707
  if valid_definition(definition, self.__class__.__name__):
@@ -7715,7 +7724,23 @@ class ConnectionUsage:
7715
7724
  if self.prefix is not None:
7716
7725
  output.append(self.prefix.dump())
7717
7726
 
7727
+ # Only emit the `connection <name>` form when the declaration
7728
+ # actually names something — a bare `connect a to b` has an
7729
+ # empty Identification and must not dump as `connection connect ...`.
7730
+ # A typed but nameless declaration (`connection : PressureSeat`)
7731
+ # still needs the `connection` keyword.
7732
+ declared = None
7718
7733
  if self.declaration is not None:
7734
+ decl = getattr(self.declaration, "declaration", None)
7735
+ ident = getattr(decl, "identification", None)
7736
+ if ident is not None:
7737
+ declared = " ".join(
7738
+ filter(None, (ident.declaredShortName, ident.declaredName))
7739
+ )
7740
+ if not declared and decl is not None and decl.specialization is not None:
7741
+ declared = True
7742
+
7743
+ if declared:
7719
7744
  output.append(self.keyword)
7720
7745
  output.append(self.declaration.dump())
7721
7746
 
@@ -9758,33 +9783,113 @@ class VerificationCaseDefinition(_DeclaredDefinitionBase):
9758
9783
 
9759
9784
 
9760
9785
  class ElementFilterMember:
9761
- # Stub for elementFilterMember — not yet fully implemented
9786
+ # elementFilterMember : memberPrefix FILTER ownedExpression SEMI
9787
+ # e.g. ``filter @e1;`` — the element filter of a view body.
9762
9788
  def __init__(self, definition=None):
9763
9789
  self.children = []
9790
+ self.prefix = None
9791
+ self.filter_expression = None
9764
9792
  if definition is not None:
9765
9793
  if valid_definition(definition, "ElementFilterMember"):
9766
- pass # TODO: parse filter expression
9794
+ if definition.get("prefix") is not None:
9795
+ self.prefix = MemberPrefix(definition["prefix"])
9796
+ oe = definition.get("ownedRelatedElement")
9797
+ if oe is not None:
9798
+ self.filter_expression = OwnedExpression(oe)
9767
9799
 
9768
9800
  def dump(self):
9769
- return ""
9801
+ output = []
9802
+ if self.prefix is not None:
9803
+ output.append(self.prefix.dump())
9804
+ output.append("filter")
9805
+ if self.filter_expression is not None:
9806
+ output.append(self.filter_expression.dump())
9807
+ return " ".join(filter(None, output)) + ";"
9808
+
9809
+ def get_definition(self):
9810
+ return {
9811
+ "name": self.__class__.__name__,
9812
+ "prefix": self.prefix.get_definition() if self.prefix else None,
9813
+ "ownedRelatedElement": (
9814
+ self.filter_expression.get_definition()
9815
+ if self.filter_expression is not None
9816
+ else None
9817
+ ),
9818
+ }
9819
+
9820
+
9821
+ class MembershipExpose:
9822
+ # membershipExpose : membershipImport
9823
+ # Payload of a membership expose (``expose e;``) — reuses the
9824
+ # ImportedMembership shape without the import prefix.
9825
+ def __init__(self, definition):
9826
+ if valid_definition(definition, "MembershipExpose"):
9827
+ self.membership = ImportedMembership(definition["membership"])
9828
+
9829
+ def dump(self):
9830
+ return self.membership.dump()
9770
9831
 
9771
9832
  def get_definition(self):
9772
- return {"name": self.__class__.__name__}
9833
+ return {
9834
+ "name": self.__class__.__name__,
9835
+ "membership": self.membership.get_definition(),
9836
+ }
9837
+
9838
+
9839
+ class NamespaceExpose:
9840
+ # namespaceExpose : namespaceImport
9841
+ # Payload of a namespace expose (``expose P::*;``) — reuses the
9842
+ # ImportedNamespace shape without the import prefix.
9843
+ def __init__(self, definition):
9844
+ if valid_definition(definition, "NamespaceExpose"):
9845
+ self.namespace = ImportedNamespace(definition["namespace"])
9846
+
9847
+ def dump(self):
9848
+ return self.namespace.dump()
9849
+
9850
+ def get_definition(self):
9851
+ return {
9852
+ "name": self.__class__.__name__,
9853
+ "ownedRelatedElement": [],
9854
+ "namespace": self.namespace.get_definition(),
9855
+ }
9773
9856
 
9774
9857
 
9775
9858
  class Expose:
9776
- # Stub for expose — not yet fully implemented
9859
+ # expose : EXPOSE ( membershipExpose | namespaceExpose ) relationshipBody
9860
+ # e.g. ``expose e;`` or ``expose P::*;`` — a member of a view body.
9777
9861
  def __init__(self, definition=None):
9778
9862
  self.children = []
9863
+ self.body = RelationshipBody({"name": "RelationshipBody", "ownedRelationship": []})
9779
9864
  if definition is not None:
9780
9865
  if valid_definition(definition, "Expose"):
9781
- pass # TODO: parse expose
9866
+ self.body = RelationshipBody(definition["body"])
9867
+ relationship = definition.get("ownedRelationship")
9868
+ if relationship is not None:
9869
+ if relationship["name"] == "NamespaceExpose":
9870
+ self.children.append(NamespaceExpose(relationship))
9871
+ elif relationship["name"] == "MembershipExpose":
9872
+ self.children.append(MembershipExpose(relationship))
9873
+ else:
9874
+ print(
9875
+ f"[Expose] Unknown relationship: "
9876
+ f"{relationship.get('name', relationship)}"
9877
+ )
9782
9878
 
9783
9879
  def dump(self):
9784
- return ""
9880
+ output = ["expose"]
9881
+ for child in self.children:
9882
+ output.append(child.dump())
9883
+ return " ".join(output) + self.body.dump()
9785
9884
 
9786
9885
  def get_definition(self):
9787
- return {"name": self.__class__.__name__}
9886
+ return {
9887
+ "name": self.__class__.__name__,
9888
+ "body": self.body.get_definition(),
9889
+ "ownedRelationship": (
9890
+ self.children[0].get_definition() if self.children else None
9891
+ ),
9892
+ }
9788
9893
 
9789
9894
 
9790
9895
  class RenderStateMember:
@@ -9946,6 +10051,8 @@ class ViewDefinitionBody:
9946
10051
  self.children.append(RenderStateMember(item))
9947
10052
  elif item_name == "ElementFilterMember":
9948
10053
  self.children.append(ElementFilterMember(item))
10054
+ elif item_name == "Expose":
10055
+ self.children.append(Expose(item))
9949
10056
  else:
9950
10057
  print(f"ViewDefinitionBody: unknown item {item_name}") # pragma: no cover
9951
10058