sysmlpy 0.30.2__tar.gz → 0.32.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.30.2/README.md → sysmlpy-0.32.0/PKG-INFO +183 -26
  2. sysmlpy-0.30.2/PKG-INFO → sysmlpy-0.32.0/README.md +157 -72
  3. sysmlpy-0.32.0/pyproject.toml +33 -0
  4. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/__init__.py +1 -1
  5. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/definition.py +19 -0
  6. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/grammar/classes.py +2 -3
  7. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/plantuml.py +41 -9
  8. sysmlpy-0.30.2/pyproject.toml +0 -140
  9. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/LICENSE +0 -0
  10. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/__main__.py +0 -0
  11. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/antlr/README.md +0 -0
  12. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/antlr/SysMLv2Lexer.interp +0 -0
  13. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/antlr/SysMLv2Lexer.py +0 -0
  14. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/antlr/SysMLv2Lexer.tokens +0 -0
  15. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/antlr/SysMLv2Parser.interp +0 -0
  16. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/antlr/SysMLv2Parser.py +0 -0
  17. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/antlr/SysMLv2Parser.tokens +0 -0
  18. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/antlr/SysMLv2ParserListener.py +0 -0
  19. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/antlr/SysMLv2ParserVisitor.py +0 -0
  20. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.interp +0 -0
  21. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.py +0 -0
  22. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.tokens +0 -0
  23. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/antlr_parser.py +0 -0
  24. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/antlr_visitor.py +0 -0
  25. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/examples/attribute_values.py +0 -0
  26. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/examples/part_attributes.py +0 -0
  27. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/examples/tuples_sequences.py +0 -0
  28. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/formatting.py +0 -0
  29. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/grammar/antlr4/README.md +0 -0
  30. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.g4 +0 -0
  31. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.interp +0 -0
  32. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.py +0 -0
  33. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.tokens +0 -0
  34. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.g4 +0 -0
  35. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.interp +0 -0
  36. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.py +0 -0
  37. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.tokens +0 -0
  38. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/grammar/antlr4/SysMLv2ParserListener.py +0 -0
  39. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/grammar/antlr4/SysMLv2ParserVisitor.py +0 -0
  40. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/grammar/antlr4/desc.xml +0 -0
  41. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/grammar/antlr4/examples/camera.sysml +0 -0
  42. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/grammar/antlr4/examples/toaster-system.sysml +0 -0
  43. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/grammar/antlr4/examples/vehicle-model.sysml +0 -0
  44. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/grammar/antlr4/pom.xml +0 -0
  45. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/LICENSE +0 -0
  46. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/README.md +0 -0
  47. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/__init__.py +0 -0
  48. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Analysis/AnalysisTooling.sysml +0 -0
  49. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Analysis/SampledFunctions.sysml +0 -0
  50. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Analysis/StateSpaceRepresentation.sysml +0 -0
  51. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Analysis/TradeStudies.sysml +0 -0
  52. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Cause and Effect/CausationConnections.sysml +0 -0
  53. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Cause and Effect/CauseAndEffect.sysml +0 -0
  54. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Geometry/ShapeItems.sysml +0 -0
  55. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Geometry/SpatialItems.sysml +0 -0
  56. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Metadata/ImageMetadata.sysml +0 -0
  57. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Metadata/ModelingMetadata.sysml +0 -0
  58. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Metadata/ParametersOfInterestMetadata.sysml +0 -0
  59. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Metadata/RiskMetadata.sysml +0 -0
  60. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Quantities and Units/ISQ.sysml +0 -0
  61. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Quantities and Units/ISQAcoustics.sysml +0 -0
  62. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Quantities and Units/ISQAtomicNuclear.sysml +0 -0
  63. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Quantities and Units/ISQBase.sysml +0 -0
  64. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Quantities and Units/ISQCharacteristicNumbers.sysml +0 -0
  65. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Quantities and Units/ISQChemistryMolecular.sysml +0 -0
  66. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Quantities and Units/ISQCondensedMatter.sysml +0 -0
  67. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Quantities and Units/ISQElectromagnetism.sysml +0 -0
  68. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Quantities and Units/ISQInformation.sysml +0 -0
  69. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Quantities and Units/ISQLight.sysml +0 -0
  70. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Quantities and Units/ISQMechanics.sysml +0 -0
  71. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Quantities and Units/ISQSpaceTime.sysml +0 -0
  72. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Quantities and Units/ISQThermodynamics.sysml +0 -0
  73. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Quantities and Units/MeasurementRefCalculations.sysml +0 -0
  74. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Quantities and Units/MeasurementReferences.sysml +0 -0
  75. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Quantities and Units/Quantities.sysml +0 -0
  76. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Quantities and Units/QuantityCalculations.sysml +0 -0
  77. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Quantities and Units/SI.sysml +0 -0
  78. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Quantities and Units/SIPrefixes.sysml +0 -0
  79. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Quantities and Units/TensorCalculations.sysml +0 -0
  80. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Quantities and Units/Time.sysml +0 -0
  81. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Quantities and Units/USCustomaryUnits.sysml +0 -0
  82. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Quantities and Units/VectorCalculations.sysml +0 -0
  83. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Requirement Derivation/DerivationConnections.sysml +0 -0
  84. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/domain/Requirement Derivation/RequirementDerivation.sysml +0 -0
  85. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/Base.kerml +0 -0
  86. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/BaseFunctions.kerml +0 -0
  87. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/BooleanFunctions.kerml +0 -0
  88. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/Clocks.kerml +0 -0
  89. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/CollectionFunctions.kerml +0 -0
  90. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/Collections.kerml +0 -0
  91. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/ComplexFunctions.kerml +0 -0
  92. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/ControlFunctions.kerml +0 -0
  93. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/ControlPerformances.kerml +0 -0
  94. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/DataFunctions.kerml +0 -0
  95. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/FeatureReferencingPerformances.kerml +0 -0
  96. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/IntegerFunctions.kerml +0 -0
  97. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/KerML.kerml +0 -0
  98. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/Links.kerml +0 -0
  99. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/Metaobjects.kerml +0 -0
  100. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/NaturalFunctions.kerml +0 -0
  101. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/NumericalFunctions.kerml +0 -0
  102. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/Objects.kerml +0 -0
  103. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/Observation.kerml +0 -0
  104. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/OccurrenceFunctions.kerml +0 -0
  105. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/Occurrences.kerml +0 -0
  106. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/Performances.kerml +0 -0
  107. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/RationalFunctions.kerml +0 -0
  108. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/RealFunctions.kerml +0 -0
  109. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/ScalarFunctions.kerml +0 -0
  110. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/ScalarValues.kerml +0 -0
  111. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/SequenceFunctions.kerml +0 -0
  112. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/SpatialFrames.kerml +0 -0
  113. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/StatePerformances.kerml +0 -0
  114. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/StringFunctions.kerml +0 -0
  115. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/Transfers.kerml +0 -0
  116. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/TransitionPerformances.kerml +0 -0
  117. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/TrigFunctions.kerml +0 -0
  118. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/Triggers.kerml +0 -0
  119. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/VectorFunctions.kerml +0 -0
  120. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/kernel/VectorValues.kerml +0 -0
  121. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/systems/Actions.sysml +0 -0
  122. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/systems/Allocations.sysml +0 -0
  123. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/systems/AnalysisCases.sysml +0 -0
  124. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/systems/Attributes.sysml +0 -0
  125. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/systems/Calculations.sysml +0 -0
  126. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/systems/Cases.sysml +0 -0
  127. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/systems/Connections.sysml +0 -0
  128. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/systems/Constraints.sysml +0 -0
  129. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/systems/Flows.sysml +0 -0
  130. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/systems/Interfaces.sysml +0 -0
  131. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/systems/Items.sysml +0 -0
  132. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/systems/Metadata.sysml +0 -0
  133. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/systems/Parts.sysml +0 -0
  134. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/systems/Ports.sysml +0 -0
  135. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/systems/Requirements.sysml +0 -0
  136. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/systems/StandardViewDefinitions.sysml +0 -0
  137. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/systems/States.sysml +0 -0
  138. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/systems/SysML.sysml +0 -0
  139. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/systems/UseCases.sysml +0 -0
  140. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/systems/VerificationCases.sysml +0 -0
  141. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/library/systems/Views.sysml +0 -0
  142. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/navigate.py +0 -0
  143. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/project.py +0 -0
  144. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/semantic.py +0 -0
  145. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/store.py +0 -0
  146. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/us_customary_units.txt +0 -0
  147. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/usage.py +0 -0
  148. {sysmlpy-0.30.2 → sysmlpy-0.32.0}/src/sysmlpy/validator.py +0 -0
@@ -1,3 +1,28 @@
1
+ Metadata-Version: 2.4
2
+ Name: sysmlpy
3
+ Version: 0.32.0
4
+ Summary:
5
+ License-File: LICENSE
6
+ Author: Jon R. Fox (mycr0ft)
7
+ Author-email: jon.fox@drfox.com
8
+ Requires-Python: >=3.9,<4.0
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.9
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Programming Language :: Python :: 3.14
16
+ Provides-Extra: graph
17
+ Provides-Extra: kuzu
18
+ Requires-Dist: antlr4-python3-runtime (>=4.13)
19
+ Requires-Dist: arrow (>=1.4.0,<2.0.0)
20
+ Requires-Dist: kuzu (>=0.7,<0.12) ; extra == "kuzu"
21
+ Requires-Dist: networkx (>=3.0) ; extra == "graph"
22
+ Requires-Dist: pint (>=0.24)
23
+ Requires-Dist: pyyaml (>=6.0)
24
+ Description-Content-Type: text/markdown
25
+
1
26
  # sysmlpy
2
27
  [![PyPI version](https://badge.fury.io/py/sysmlpy.svg)](https://badge.fury.io/py/sysmlpy)[![PyPI status](https://img.shields.io/pypi/status/sysmlpy.svg)](https://pypi.python.org/pypi/sysmlpy/)[![MIT license](https://img.shields.io/badge/License-MIT-blue.svg)](https://lbesson.mit-license.org/)
3
28
 
@@ -14,6 +39,10 @@ The project had diverged so much from sysml2py that a new name, sysmlpy, was sel
14
39
 
15
40
  ![Lines of Code Over Time](loc_history.svg)
16
41
 
42
+ **v0.31.0:** Documentation overhaul — all docs rewritten to showcase the modern public API. New Model Parsing and Model Navigation sections. Semantic Analysis updated with `AnalysisResult`. Grammar round-trip: 77/77 (100%). 211 core tests passing.
43
+
44
+ **v0.31.1:** Fixed `pyproject.toml` for CI compatibility — removed duplicate version and invalid `allow_zero_version` from `[project]` table.
45
+
17
46
  **v0.28.0:** Complete Gap 4 coverage — Block Definition Diagram (BDD), Internal Block Diagram (IBD), Parametric Diagram, and Package Diagram views. All 6 specialized SysML v2 view types now implemented (144 PlantUML tests). IBD shows flow/connection arrows with endpoint extraction. Parametric view extracts constraint parameters with types. Package diagram renders nested folder-style hierarchy.
18
47
 
19
48
  **v0.27.0:** General View (GV), Package View, and three GridView specializations (Tabular View, Data Value Tabular View, Relationship Matrix View) with PlantUML, Markdown, and HTML output. 108 PlantUML tests. All 68+ `NotImplementedError` stubs in `grammar/classes.py` replaced with graceful handling.
@@ -57,44 +86,60 @@ Documentation can be found [here.](https://mycr0ft.github.io/sysmlpy/)
57
86
 
58
87
  ### Basic Usage
59
88
 
60
- The code below will create a part called Stage 1, with a shortname of <'3.1'>
61
- referencing a specific requirement or document. It has a mass attribute of 100
62
- kg. It has a thrust attribute of 1000 N. These attributes are created and placed
63
- as a child of the part. Next, we recall the part value for thrust and add 199 N.
64
- Finally, we can dump the output from this class.
65
- ```
66
- from sysmlpy import Attribute, Part, ureg
89
+ Build models programmatically using the public API:
90
+
91
+ ```python
92
+ from sysmlpy import Part, Item, Attribute, ureg
93
+
94
+ # Create a sensor part with children
95
+ sensor = Part(name="sensor")
96
+ camera = Part(name="camera")
97
+ lens = Item(name="lens")
98
+ mass = Attribute(name="mass")
99
+ mass.set_value(100 * ureg.kilogram)
100
+
101
+ camera.add_child(mass)
102
+ sensor.add_child(camera)
103
+ sensor.add_child(lens)
67
104
 
68
- a = Attribute(name='mass')
69
- a.set_value(100 * ureg.kilogram)
70
- b = Attribute(name='thrust')
71
- b.set_value(1000 * ureg.newton)
72
- c = Part(name="Stage_1", shortname="'3.1'")
73
- c._set_child(a)
74
- c._set_child(b)
75
- v = "Stage_1.thrust"
76
- c._get_child(v).set_value(c._get_child(v).get_value() + 199 * ureg.newton)
77
- print(c.dump())
105
+ print(sensor.dump())
106
+ # part sensor {
107
+ # → part camera {
108
+ # → attribute mass = 100 [kilogram];
109
+ # → }
110
+ # → item lens;
111
+ # → }
112
+
113
+ # Navigate children by name
114
+ found = sensor.find_one("camera")
115
+ print(found.name) # → camera
116
+
117
+ # Iterate over children
118
+ for child in sensor:
119
+ print(child.name)
120
+
121
+ # Check containment
122
+ "camera" in sensor # → True
78
123
  ```
79
124
 
80
125
  It will output the following:
81
126
  ```
82
- part <'3.1'> Stage_1 {
127
+ part <'3.1'> Stage_1 {
83
128
  attribute mass= 100 [kilogram];
84
129
  attribute thrust= 1199.0 [newton];
85
- }
130
+ }
86
131
  ```
87
132
 
88
133
  The package is able to handle Items, Parts, and Attributes.
89
134
 
90
- ```
135
+ ```python
91
136
  a = Part(name='camera')
92
137
  b = Item(name='lens')
93
138
  d = Attribute(name='mass')
94
139
  c = Part(name='sensor')
95
- c._set_child(a)
96
- c._set_child(b)
97
- a._set_child(d)
140
+ c.add_child(a)
141
+ c.add_child(b)
142
+ a.add_child(d)
98
143
  print(c.dump())
99
144
  ```
100
145
 
@@ -158,6 +203,87 @@ print(r3.dump())
158
203
  # → ref :>> payload : Person;
159
204
  ```
160
205
 
206
+ ## Model Parsing
207
+
208
+ ```python
209
+ from sysmlpy import loads, parse
210
+
211
+ # loads() — raises on syntax error
212
+ model = loads("package P { part def Engine; }")
213
+
214
+ # parse() — returns (model, errors) tuple, never raises
215
+ model, errors = parse("package P { part def Engine; }")
216
+ assert errors == []
217
+
218
+ model, errors = parse("invalid @@ syntax")
219
+ assert model is None
220
+ assert len(errors) > 0
221
+ ```
222
+
223
+ ## Model Navigation
224
+
225
+ Every parsed model element supports search, iteration, and containment checks:
226
+
227
+ ```python
228
+ from sysmlpy import loads, Part
229
+
230
+ model = loads("""
231
+ package Vehicle {
232
+ part def Engine;
233
+ part engine1 : Engine { attribute mass = 100 [kg]; }
234
+ part chassis { part wheel1; part wheel2; }
235
+ }
236
+ """)
237
+
238
+ # find() — returns list of matching elements (empty list if none)
239
+ parts = model.find(sysml_type="part")
240
+ assert len(parts) >= 3
241
+
242
+ # find_one() — returns single element or None
243
+ engine = model.find_one("engine1")
244
+ assert engine is not None
245
+
246
+ missing = model.find_one("DoesNotExist")
247
+ assert missing is None # no IndexError!
248
+
249
+ # find_one() raises LookupError if multiple matches
250
+ # model.find_one("wheel") → LookupError: 2 matches
251
+
252
+ # Container protocol — iterate, length, containment
253
+ for child in model:
254
+ print(child.name)
255
+
256
+ len(model) # → number of direct children
257
+ "Vehicle" in model # → True (checks child names)
258
+
259
+ # __str__ returns SysML text
260
+ print(str(model))
261
+ # → package Vehicle { ... }
262
+
263
+ # Typed property accessors
264
+ model.packages # direct Package children
265
+ model.parts # direct Part children
266
+ model.actions # direct Action children
267
+ ```
268
+
269
+ All search methods accept `sysml_type=` (keyword string or class) and `recursive=`:
270
+
271
+ ```python
272
+ from sysmlpy import Part
273
+
274
+ # By string keyword
275
+ model.find(sysml_type="action")
276
+
277
+ # By class
278
+ model.find(sysml_type=Part)
279
+
280
+ # Non-recursive (direct children only)
281
+ model.find("engine1", recursive=False)
282
+
283
+ # Legacy type= keyword still works (emits DeprecationWarning)
284
+ model.find(type="action")
285
+ ```
286
+
161
287
  ## Grammar Round-Trip
162
288
 
163
289
  `loads()` parses SysML v2 text and `classtree()` converts the result back to text. This round-trip is the basis for the grammar test suite.
@@ -193,7 +319,7 @@ tree = classtree(model)
193
319
  print(tree.dump())
194
320
  ```
195
321
 
196
- **61 of 77 grammar round-trip tests pass** (61/77). All 61 non-control-flow tests pass (100%). The 16 deferred tests require action control-flow node classes (`IfNode`, `WhileLoopNode`, `ControlNode`, `SendNode`, `AcceptNode`, `TerminateNode`) not yet ported to `grammar/classes.py`. Covered categories: packages, parts, items, ports, interfaces, binding connectors, flow connections, all action forms (definition, shorthand, succession, decomposition), expressions, calculations, constraints, state definitions, requirements, analysis cases, and trade studies.
322
+ **All 77 grammar round-trip tests pass** (100%). Covered categories: packages, parts, items, ports, interfaces, binding connectors, flow connections, all action forms (definition, shorthand, succession, decomposition), expressions, calculations, constraints, state definitions, requirements, analysis cases, control flow (if/else, while, loop, fork, join, decision, send, accept, terminate), and trade studies.
197
323
 
198
324
  ## Semantic Analysis
199
325
 
@@ -213,10 +339,33 @@ model = loads("""
213
339
  }
214
340
  """)
215
341
 
216
- issues = analyze(model)
217
- for issue in issues:
342
+ result = analyze(model)
343
+
344
+ # Iterate issues (backward-compatible with list)
345
+ for issue in result:
218
346
  print(f"[{issue.severity}] {issue.code}: {issue.message}")
219
347
  # → [error] UNDEFINED_SYMBOL: Undefined symbol 'Wheel' referenced in Part 'myWheel'
348
+
349
+ # Separated by severity
350
+ for err in result.errors:
351
+ print(f"ERROR: {err.message}")
352
+
353
+ for warn in result.warnings:
354
+ print(f"WARNING: {warn.message}")
355
+
356
+ # Boolean check: True when no errors (warnings are OK)
357
+ if result:
358
+ print("Model is semantically valid!")
359
+ else:
360
+ print(f"Found {len(result.errors)} error(s) — fix before proceeding")
361
+
362
+ # Raise on errors
363
+ result.raise_on_errors() # ValueError if any errors exist
364
+
365
+ # Strict mode: raise immediately on any error
366
+ result = analyze(model, strict=True)
367
+ # → ValueError: Semantic errors found:
368
+ # [UNDEFINED_SYMBOL] Undefined symbol 'Wheel' referenced in Part 'myWheel'
220
369
  ```
221
370
 
222
371
  ### Symbol Resolution
@@ -652,5 +801,13 @@ See [`docs/plantuml-examples/`](docs/plantuml-examples/) for all rendered exampl
652
801
 
653
802
  **100% of 123 OMG XPect conformance tests pass** (123/123).
654
803
 
804
+ ## Companion Projects
805
+
806
+ Two companion tools for the SysML v2 community, created by the same author:
807
+
808
+ - **[sysml-style](https://github.com/mycr0ft/sysml-style)** — A SysML v2 code formatter with configurable indentation, line width, and bracket style. Can be used standalone or integrated as a pre-commit hook.
809
+ - **[sysml-vim](https://github.com/mycr0ft/sysml-vim)** — Vim syntax highlighting and indentation support for SysML v2 textual notation (`.sysml` and `.kerml` files).
810
+
655
811
  ## License
656
812
  sysmlpy is released under the MIT license, hence allowing commercial use of the library.
813
+
@@ -1,48 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: sysmlpy
3
- Version: 0.30.2
4
- Summary: SysML v2.0 Parser
5
- License: MIT License
6
-
7
- Copyright (c) 2023-2026 Westfall-io
8
- Copyright (c) 2026 Jon R. Fox
9
-
10
- Permission is hereby granted, free of charge, to any person obtaining a copy
11
- of this software and associated documentation files (the "Software"), to deal
12
- in the Software without restriction, including without limitation the rights
13
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
- copies of the Software, and to permit persons to whom the Software is
15
- furnished to do so, subject to the following conditions:
16
-
17
- The above copyright notice and this permission notice shall be included in all
18
- copies or substantial portions of the Software.
19
-
20
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
- SOFTWARE.
27
- License-File: LICENSE
28
- Author: Jon R. Fox (mycr0ft)
29
- Author-email: jon.fox@drfox.com
30
- Requires-Python: >=3.7
31
- Classifier: Development Status :: 3 - Alpha
32
- Classifier: Programming Language :: Python :: 3
33
- Classifier: License :: OSI Approved :: MIT License
34
- Classifier: Operating System :: OS Independent
35
- Provides-Extra: graph
36
- Provides-Extra: kuzu
37
- Requires-Dist: antlr4-python3-runtime (>=4.13)
38
- Requires-Dist: kuzu (>=0.7,<0.12) ; extra == "kuzu"
39
- Requires-Dist: networkx (>=3.0) ; extra == "graph"
40
- Requires-Dist: pint (>=0.24)
41
- Requires-Dist: pyyaml (>=6.0)
42
- Project-URL: Bug Tracker, https://github.com/mycr0ft/sysmlpy/issues
43
- Project-URL: Homepage, https://github.com/mycr0ft/sysmlpy
44
- Description-Content-Type: text/markdown
45
-
46
1
  # sysmlpy
47
2
  [![PyPI version](https://badge.fury.io/py/sysmlpy.svg)](https://badge.fury.io/py/sysmlpy)[![PyPI status](https://img.shields.io/pypi/status/sysmlpy.svg)](https://pypi.python.org/pypi/sysmlpy/)[![MIT license](https://img.shields.io/badge/License-MIT-blue.svg)](https://lbesson.mit-license.org/)
48
3
 
@@ -59,6 +14,10 @@ The project had diverged so much from sysml2py that a new name, sysmlpy, was sel
59
14
 
60
15
  ![Lines of Code Over Time](loc_history.svg)
61
16
 
17
+ **v0.31.0:** Documentation overhaul — all docs rewritten to showcase the modern public API. New Model Parsing and Model Navigation sections. Semantic Analysis updated with `AnalysisResult`. Grammar round-trip: 77/77 (100%). 211 core tests passing.
18
+
19
+ **v0.31.1:** Fixed `pyproject.toml` for CI compatibility — removed duplicate version and invalid `allow_zero_version` from `[project]` table.
20
+
62
21
  **v0.28.0:** Complete Gap 4 coverage — Block Definition Diagram (BDD), Internal Block Diagram (IBD), Parametric Diagram, and Package Diagram views. All 6 specialized SysML v2 view types now implemented (144 PlantUML tests). IBD shows flow/connection arrows with endpoint extraction. Parametric view extracts constraint parameters with types. Package diagram renders nested folder-style hierarchy.
63
22
 
64
23
  **v0.27.0:** General View (GV), Package View, and three GridView specializations (Tabular View, Data Value Tabular View, Relationship Matrix View) with PlantUML, Markdown, and HTML output. 108 PlantUML tests. All 68+ `NotImplementedError` stubs in `grammar/classes.py` replaced with graceful handling.
@@ -102,44 +61,60 @@ Documentation can be found [here.](https://mycr0ft.github.io/sysmlpy/)
102
61
 
103
62
  ### Basic Usage
104
63
 
105
- The code below will create a part called Stage 1, with a shortname of <'3.1'>
106
- referencing a specific requirement or document. It has a mass attribute of 100
107
- kg. It has a thrust attribute of 1000 N. These attributes are created and placed
108
- as a child of the part. Next, we recall the part value for thrust and add 199 N.
109
- Finally, we can dump the output from this class.
110
- ```
111
- from sysmlpy import Attribute, Part, ureg
64
+ Build models programmatically using the public API:
65
+
66
+ ```python
67
+ from sysmlpy import Part, Item, Attribute, ureg
68
+
69
+ # Create a sensor part with children
70
+ sensor = Part(name="sensor")
71
+ camera = Part(name="camera")
72
+ lens = Item(name="lens")
73
+ mass = Attribute(name="mass")
74
+ mass.set_value(100 * ureg.kilogram)
75
+
76
+ camera.add_child(mass)
77
+ sensor.add_child(camera)
78
+ sensor.add_child(lens)
112
79
 
113
- a = Attribute(name='mass')
114
- a.set_value(100 * ureg.kilogram)
115
- b = Attribute(name='thrust')
116
- b.set_value(1000 * ureg.newton)
117
- c = Part(name="Stage_1", shortname="'3.1'")
118
- c._set_child(a)
119
- c._set_child(b)
120
- v = "Stage_1.thrust"
121
- c._get_child(v).set_value(c._get_child(v).get_value() + 199 * ureg.newton)
122
- print(c.dump())
80
+ print(sensor.dump())
81
+ # part sensor {
82
+ # → part camera {
83
+ # → attribute mass = 100 [kilogram];
84
+ # → }
85
+ # → item lens;
86
+ # → }
87
+
88
+ # Navigate children by name
89
+ found = sensor.find_one("camera")
90
+ print(found.name) # → camera
91
+
92
+ # Iterate over children
93
+ for child in sensor:
94
+ print(child.name)
95
+
96
+ # Check containment
97
+ "camera" in sensor # → True
123
98
  ```
124
99
 
125
100
  It will output the following:
126
101
  ```
127
- part <'3.1'> Stage_1 {
102
+ part <'3.1'> Stage_1 {
128
103
  attribute mass= 100 [kilogram];
129
104
  attribute thrust= 1199.0 [newton];
130
- }
105
+ }
131
106
  ```
132
107
 
133
108
  The package is able to handle Items, Parts, and Attributes.
134
109
 
135
- ```
110
+ ```python
136
111
  a = Part(name='camera')
137
112
  b = Item(name='lens')
138
113
  d = Attribute(name='mass')
139
114
  c = Part(name='sensor')
140
- c._set_child(a)
141
- c._set_child(b)
142
- a._set_child(d)
115
+ c.add_child(a)
116
+ c.add_child(b)
117
+ a.add_child(d)
143
118
  print(c.dump())
144
119
  ```
145
120
 
@@ -203,6 +178,87 @@ print(r3.dump())
203
178
  # → ref :>> payload : Person;
204
179
  ```
205
180
 
181
+ ## Model Parsing
182
+
183
+ ```python
184
+ from sysmlpy import loads, parse
185
+
186
+ # loads() — raises on syntax error
187
+ model = loads("package P { part def Engine; }")
188
+
189
+ # parse() — returns (model, errors) tuple, never raises
190
+ model, errors = parse("package P { part def Engine; }")
191
+ assert errors == []
192
+
193
+ model, errors = parse("invalid @@ syntax")
194
+ assert model is None
195
+ assert len(errors) > 0
196
+ ```
197
+
198
+ ## Model Navigation
199
+
200
+ Every parsed model element supports search, iteration, and containment checks:
201
+
202
+ ```python
203
+ from sysmlpy import loads, Part
204
+
205
+ model = loads("""
206
+ package Vehicle {
207
+ part def Engine;
208
+ part engine1 : Engine { attribute mass = 100 [kg]; }
209
+ part chassis { part wheel1; part wheel2; }
210
+ }
211
+ """)
212
+
213
+ # find() — returns list of matching elements (empty list if none)
214
+ parts = model.find(sysml_type="part")
215
+ assert len(parts) >= 3
216
+
217
+ # find_one() — returns single element or None
218
+ engine = model.find_one("engine1")
219
+ assert engine is not None
220
+
221
+ missing = model.find_one("DoesNotExist")
222
+ assert missing is None # no IndexError!
223
+
224
+ # find_one() raises LookupError if multiple matches
225
+ # model.find_one("wheel") → LookupError: 2 matches
226
+
227
+ # Container protocol — iterate, length, containment
228
+ for child in model:
229
+ print(child.name)
230
+
231
+ len(model) # → number of direct children
232
+ "Vehicle" in model # → True (checks child names)
233
+
234
+ # __str__ returns SysML text
235
+ print(str(model))
236
+ # → package Vehicle { ... }
237
+
238
+ # Typed property accessors
239
+ model.packages # direct Package children
240
+ model.parts # direct Part children
241
+ model.actions # direct Action children
242
+ ```
243
+
244
+ All search methods accept `sysml_type=` (keyword string or class) and `recursive=`:
245
+
246
+ ```python
247
+ from sysmlpy import Part
248
+
249
+ # By string keyword
250
+ model.find(sysml_type="action")
251
+
252
+ # By class
253
+ model.find(sysml_type=Part)
254
+
255
+ # Non-recursive (direct children only)
256
+ model.find("engine1", recursive=False)
257
+
258
+ # Legacy type= keyword still works (emits DeprecationWarning)
259
+ model.find(type="action")
260
+ ```
261
+
206
262
  ## Grammar Round-Trip
207
263
 
208
264
  `loads()` parses SysML v2 text and `classtree()` converts the result back to text. This round-trip is the basis for the grammar test suite.
@@ -238,7 +294,7 @@ tree = classtree(model)
238
294
  print(tree.dump())
239
295
  ```
240
296
 
241
- **61 of 77 grammar round-trip tests pass** (61/77). All 61 non-control-flow tests pass (100%). The 16 deferred tests require action control-flow node classes (`IfNode`, `WhileLoopNode`, `ControlNode`, `SendNode`, `AcceptNode`, `TerminateNode`) not yet ported to `grammar/classes.py`. Covered categories: packages, parts, items, ports, interfaces, binding connectors, flow connections, all action forms (definition, shorthand, succession, decomposition), expressions, calculations, constraints, state definitions, requirements, analysis cases, and trade studies.
297
+ **All 77 grammar round-trip tests pass** (100%). Covered categories: packages, parts, items, ports, interfaces, binding connectors, flow connections, all action forms (definition, shorthand, succession, decomposition), expressions, calculations, constraints, state definitions, requirements, analysis cases, control flow (if/else, while, loop, fork, join, decision, send, accept, terminate), and trade studies.
242
298
 
243
299
  ## Semantic Analysis
244
300
 
@@ -258,10 +314,33 @@ model = loads("""
258
314
  }
259
315
  """)
260
316
 
261
- issues = analyze(model)
262
- for issue in issues:
317
+ result = analyze(model)
318
+
319
+ # Iterate issues (backward-compatible with list)
320
+ for issue in result:
263
321
  print(f"[{issue.severity}] {issue.code}: {issue.message}")
264
322
  # → [error] UNDEFINED_SYMBOL: Undefined symbol 'Wheel' referenced in Part 'myWheel'
323
+
324
+ # Separated by severity
325
+ for err in result.errors:
326
+ print(f"ERROR: {err.message}")
327
+
328
+ for warn in result.warnings:
329
+ print(f"WARNING: {warn.message}")
330
+
331
+ # Boolean check: True when no errors (warnings are OK)
332
+ if result:
333
+ print("Model is semantically valid!")
334
+ else:
335
+ print(f"Found {len(result.errors)} error(s) — fix before proceeding")
336
+
337
+ # Raise on errors
338
+ result.raise_on_errors() # ValueError if any errors exist
339
+
340
+ # Strict mode: raise immediately on any error
341
+ result = analyze(model, strict=True)
342
+ # → ValueError: Semantic errors found:
343
+ # [UNDEFINED_SYMBOL] Undefined symbol 'Wheel' referenced in Part 'myWheel'
265
344
  ```
266
345
 
267
346
  ### Symbol Resolution
@@ -697,6 +776,12 @@ See [`docs/plantuml-examples/`](docs/plantuml-examples/) for all rendered exampl
697
776
 
698
777
  **100% of 123 OMG XPect conformance tests pass** (123/123).
699
778
 
779
+ ## Companion Projects
780
+
781
+ Two companion tools for the SysML v2 community, created by the same author:
782
+
783
+ - **[sysml-style](https://github.com/mycr0ft/sysml-style)** — A SysML v2 code formatter with configurable indentation, line width, and bracket style. Can be used standalone or integrated as a pre-commit hook.
784
+ - **[sysml-vim](https://github.com/mycr0ft/sysml-vim)** — Vim syntax highlighting and indentation support for SysML v2 textual notation (`.sysml` and `.kerml` files).
785
+
700
786
  ## License
701
787
  sysmlpy is released under the MIT license, hence allowing commercial use of the library.
702
-
@@ -0,0 +1,33 @@
1
+ [build-system]
2
+ #requires = ["setuptools>=61.0"]
3
+ #build-backend = "setuptools.build_meta"
4
+ requires = ["poetry-core"]
5
+ build-backend = "poetry.core.masonry.api"
6
+
7
+ [project]
8
+ name = "sysmlpy"
9
+ version = "0.32.0"
10
+ description = ""
11
+ authors = [{ name = "Jon R. Fox (mycr0ft)", email = "jon.fox@drfox.com" }]
12
+ readme = "README.md"
13
+ packages = [{ include = "sysmlpy", from = "src" }]
14
+
15
+ [tool.poetry.dependencies]
16
+ python = "^3.9"
17
+ pint = ">=0.24"
18
+ pyyaml = ">=6.0"
19
+ antlr4-python3-runtime = ">=4.13"
20
+ networkx = { version = ">=3.0", optional = true }
21
+ kuzu = { version = ">=0.7,<0.12", optional = true }
22
+ arrow = "^1.4.0"
23
+
24
+ [tool.poetry.extras]
25
+ graph = ["networkx"]
26
+ kuzu = ["kuzu"]
27
+
28
+ [tool.poetry.scripts]
29
+ sysmlpy = "sysmlpy.__main__:main"
30
+
31
+ [tool.poetry.group.dev.dependencies]
32
+ pytest = ">=8.0,<9.0"
33
+
@@ -21,7 +21,7 @@ __all__ = [
21
21
  "SysMLSyntaxError",
22
22
  ]
23
23
  __author__ = "Jon Fox"
24
- __version__ = "0.30.2"
24
+ __version__ = "0.32.0"
25
25
 
26
26
  from sysmlpy.usage import (
27
27
  Item, Attribute, Part, Port, Action, Reference, UseCase, Requirement, Interface, Message,
@@ -415,6 +415,7 @@ class Package(Searchable):
415
415
  """
416
416
  self.name = str(uuidlib.uuid4())
417
417
  self.children = []
418
+ self._imports = []
418
419
  self.typedby = None
419
420
  self.grammar = PackageGrammar()
420
421
  self.parent = None
@@ -773,8 +774,20 @@ class Package(Searchable):
773
774
  self.grammar.body = PackageBody({"name": "PackageBody", "ownedRelationship": []})
774
775
 
775
776
  self.grammar.body.children.append(import_rel)
777
+ self._imports.append(import_rel)
776
778
  return self
777
779
 
780
+ @property
781
+ def imports(self):
782
+ """Import and AliasMember declarations in this package.
783
+
784
+ Returns
785
+ -------
786
+ list
787
+ Grammar objects (Import or AliasMember) that belong to this package.
788
+ """
789
+ return list(self._imports)
790
+
778
791
  def load_from_grammar(self, grammar):
779
792
  """Load package structure from a parsed grammar object.
780
793
 
@@ -1283,6 +1296,12 @@ class Package(Searchable):
1283
1296
  else:
1284
1297
  print(f"[Package.load_from_grammar] Unknown class: {inner_class} - skipping") # pragma: no cover
1285
1298
 
1299
+ # Collect Import and AliasMember grammar objects for public API access
1300
+ self._imports = []
1301
+ for child in grammar.body.children:
1302
+ if child.__class__.__name__ in ('Import', 'AliasMember'):
1303
+ self._imports.append(child)
1304
+
1286
1305
  return self
1287
1306
 
1288
1307
  def _get_grammar(self):
@@ -2555,8 +2555,7 @@ class ActionDefinition:
2555
2555
  output.append(self.prefix.dump())
2556
2556
  output.append(self.keyword)
2557
2557
  output.append(self.declaration.dump())
2558
- output.append(self.body.dump())
2559
- return " ".join(output)
2558
+ return " ".join(filter(None, output)) + self.body.dump()
2560
2559
 
2561
2560
  def get_definition(self):
2562
2561
  output = {"name": self.__class__.__name__, "prefix": None}
@@ -4611,7 +4610,7 @@ class Definition:
4611
4610
  self.body = DefinitionBody()
4612
4611
 
4613
4612
  def dump(self):
4614
- return " ".join([self.declaration.dump(), self.body.dump()])
4613
+ return "".join([self.declaration.dump(), self.body.dump()])
4615
4614
 
4616
4615
  def get_definition(self):
4617
4616
  return {