sysmlpy 0.65.0__tar.gz → 0.66.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 (157) hide show
  1. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/PKG-INFO +3 -1
  2. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/pyproject.toml +3 -1
  3. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/__init__.py +9 -1
  4. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/__main__.py +89 -3
  5. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/plantuml.py +25 -0
  6. sysmlpy-0.66.0/src/sysmlpy/spreadsheet.py +259 -0
  7. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/LICENSE +0 -0
  8. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/README.md +0 -0
  9. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/antlr/README.md +0 -0
  10. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/antlr/SysMLv2Lexer.interp +0 -0
  11. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/antlr/SysMLv2Lexer.py +0 -0
  12. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/antlr/SysMLv2Lexer.tokens +0 -0
  13. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/antlr/SysMLv2Parser.interp +0 -0
  14. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/antlr/SysMLv2Parser.py +0 -0
  15. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/antlr/SysMLv2Parser.tokens +0 -0
  16. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/antlr/SysMLv2ParserListener.py +0 -0
  17. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/antlr/SysMLv2ParserVisitor.py +0 -0
  18. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.interp +0 -0
  19. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.py +0 -0
  20. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.tokens +0 -0
  21. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/antlr_parser.py +0 -0
  22. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/antlr_visitor.py +0 -0
  23. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/boxes_view.py +0 -0
  24. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/definition.py +0 -0
  25. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/evaluator.py +0 -0
  26. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/examples/attribute_values.py +0 -0
  27. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/examples/part_attributes.py +0 -0
  28. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/examples/tuples_sequences.py +0 -0
  29. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/formatting.py +0 -0
  30. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/grammar/antlr4/README.md +0 -0
  31. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.g4 +0 -0
  32. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.interp +0 -0
  33. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.py +0 -0
  34. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.tokens +0 -0
  35. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.g4 +0 -0
  36. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.interp +0 -0
  37. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.py +0 -0
  38. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.tokens +0 -0
  39. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/grammar/antlr4/SysMLv2ParserListener.py +0 -0
  40. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/grammar/antlr4/SysMLv2ParserVisitor.py +0 -0
  41. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/grammar/antlr4/desc.xml +0 -0
  42. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/grammar/antlr4/examples/camera.sysml +0 -0
  43. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/grammar/antlr4/examples/toaster-system.sysml +0 -0
  44. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/grammar/antlr4/examples/vehicle-model.sysml +0 -0
  45. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/grammar/antlr4/pom.xml +0 -0
  46. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/grammar/classes.py +0 -0
  47. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/interchange.py +0 -0
  48. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/LICENSE +0 -0
  49. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/README.md +0 -0
  50. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/__init__.py +0 -0
  51. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Analysis/AnalysisTooling.sysml +0 -0
  52. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Analysis/SampledFunctions.sysml +0 -0
  53. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Analysis/StateSpaceRepresentation.sysml +0 -0
  54. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Analysis/TradeStudies.sysml +0 -0
  55. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Cause and Effect/CausationConnections.sysml +0 -0
  56. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Cause and Effect/CauseAndEffect.sysml +0 -0
  57. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Geometry/ShapeItems.sysml +0 -0
  58. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Geometry/SpatialItems.sysml +0 -0
  59. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Metadata/ImageMetadata.sysml +0 -0
  60. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Metadata/ModelingMetadata.sysml +0 -0
  61. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Metadata/ParametersOfInterestMetadata.sysml +0 -0
  62. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Metadata/RiskMetadata.sysml +0 -0
  63. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Quantities and Units/ISQ.sysml +0 -0
  64. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Quantities and Units/ISQAcoustics.sysml +0 -0
  65. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Quantities and Units/ISQAtomicNuclear.sysml +0 -0
  66. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Quantities and Units/ISQBase.sysml +0 -0
  67. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Quantities and Units/ISQCharacteristicNumbers.sysml +0 -0
  68. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Quantities and Units/ISQChemistryMolecular.sysml +0 -0
  69. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Quantities and Units/ISQCondensedMatter.sysml +0 -0
  70. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Quantities and Units/ISQElectromagnetism.sysml +0 -0
  71. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Quantities and Units/ISQInformation.sysml +0 -0
  72. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Quantities and Units/ISQLight.sysml +0 -0
  73. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Quantities and Units/ISQMechanics.sysml +0 -0
  74. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Quantities and Units/ISQSpaceTime.sysml +0 -0
  75. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Quantities and Units/ISQThermodynamics.sysml +0 -0
  76. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Quantities and Units/MeasurementRefCalculations.sysml +0 -0
  77. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Quantities and Units/MeasurementReferences.sysml +0 -0
  78. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Quantities and Units/Quantities.sysml +0 -0
  79. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Quantities and Units/QuantityCalculations.sysml +0 -0
  80. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Quantities and Units/SI.sysml +0 -0
  81. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Quantities and Units/SIPrefixes.sysml +0 -0
  82. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Quantities and Units/TensorCalculations.sysml +0 -0
  83. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Quantities and Units/Time.sysml +0 -0
  84. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Quantities and Units/USCustomaryUnits.sysml +0 -0
  85. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Quantities and Units/VectorCalculations.sysml +0 -0
  86. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Requirement Derivation/DerivationConnections.sysml +0 -0
  87. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/domain/Requirement Derivation/RequirementDerivation.sysml +0 -0
  88. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/Base.kerml +0 -0
  89. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/BaseFunctions.kerml +0 -0
  90. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/BooleanFunctions.kerml +0 -0
  91. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/Clocks.kerml +0 -0
  92. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/CollectionFunctions.kerml +0 -0
  93. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/Collections.kerml +0 -0
  94. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/ComplexFunctions.kerml +0 -0
  95. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/ControlFunctions.kerml +0 -0
  96. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/ControlPerformances.kerml +0 -0
  97. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/DataFunctions.kerml +0 -0
  98. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/FeatureReferencingPerformances.kerml +0 -0
  99. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/IntegerFunctions.kerml +0 -0
  100. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/KerML.kerml +0 -0
  101. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/Links.kerml +0 -0
  102. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/Metaobjects.kerml +0 -0
  103. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/NaturalFunctions.kerml +0 -0
  104. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/NumericalFunctions.kerml +0 -0
  105. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/Objects.kerml +0 -0
  106. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/Observation.kerml +0 -0
  107. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/OccurrenceFunctions.kerml +0 -0
  108. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/Occurrences.kerml +0 -0
  109. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/Performances.kerml +0 -0
  110. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/RationalFunctions.kerml +0 -0
  111. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/RealFunctions.kerml +0 -0
  112. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/ScalarFunctions.kerml +0 -0
  113. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/ScalarValues.kerml +0 -0
  114. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/SequenceFunctions.kerml +0 -0
  115. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/SpatialFrames.kerml +0 -0
  116. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/StatePerformances.kerml +0 -0
  117. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/StringFunctions.kerml +0 -0
  118. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/Transfers.kerml +0 -0
  119. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/TransitionPerformances.kerml +0 -0
  120. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/TrigFunctions.kerml +0 -0
  121. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/Triggers.kerml +0 -0
  122. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/VectorFunctions.kerml +0 -0
  123. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/kernel/VectorValues.kerml +0 -0
  124. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/systems/Actions.sysml +0 -0
  125. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/systems/Allocations.sysml +0 -0
  126. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/systems/AnalysisCases.sysml +0 -0
  127. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/systems/Attributes.sysml +0 -0
  128. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/systems/Calculations.sysml +0 -0
  129. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/systems/Cases.sysml +0 -0
  130. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/systems/Connections.sysml +0 -0
  131. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/systems/Constraints.sysml +0 -0
  132. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/systems/Flows.sysml +0 -0
  133. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/systems/Interfaces.sysml +0 -0
  134. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/systems/Items.sysml +0 -0
  135. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/systems/Metadata.sysml +0 -0
  136. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/systems/Parts.sysml +0 -0
  137. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/systems/Ports.sysml +0 -0
  138. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/systems/Requirements.sysml +0 -0
  139. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/systems/StandardViewDefinitions.sysml +0 -0
  140. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/systems/States.sysml +0 -0
  141. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/systems/SysML.sysml +0 -0
  142. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/systems/UseCases.sysml +0 -0
  143. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/systems/VerificationCases.sysml +0 -0
  144. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/library/systems/Views.sysml +0 -0
  145. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/lsp/__init__.py +0 -0
  146. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/lsp/__main__.py +0 -0
  147. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/lsp/protocol.py +0 -0
  148. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/lsp/server.py +0 -0
  149. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/lsp/stdio.py +0 -0
  150. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/navigate.py +0 -0
  151. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/project.py +0 -0
  152. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/semantic.py +0 -0
  153. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/store.py +0 -0
  154. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/traceability.py +0 -0
  155. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/us_customary_units.txt +0 -0
  156. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/usage.py +0 -0
  157. {sysmlpy-0.65.0 → sysmlpy-0.66.0}/src/sysmlpy/validator.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sysmlpy
3
- Version: 0.65.0
3
+ Version: 0.66.0
4
4
  Summary:
5
5
  License-File: LICENSE
6
6
  Author: Jon R. Fox (mycr0ft)
@@ -15,10 +15,12 @@ Classifier: Programming Language :: Python :: 3.13
15
15
  Classifier: Programming Language :: Python :: 3.14
16
16
  Provides-Extra: graph
17
17
  Provides-Extra: kuzu
18
+ Provides-Extra: xlsx
18
19
  Requires-Dist: antlr4-python3-runtime (>=4.13)
19
20
  Requires-Dist: arrow (>=1.4.0,<2.0.0)
20
21
  Requires-Dist: kuzu (>=0.7,<0.12) ; extra == "kuzu"
21
22
  Requires-Dist: networkx (>=3.0) ; extra == "graph"
23
+ Requires-Dist: openpyxl (>=3.1) ; extra == "xlsx"
22
24
  Requires-Dist: pint (>=0.24)
23
25
  Requires-Dist: pyyaml (>=6.0)
24
26
  Description-Content-Type: text/markdown
@@ -6,7 +6,7 @@ build-backend = "poetry.core.masonry.api"
6
6
 
7
7
  [project]
8
8
  name = "sysmlpy"
9
- version = "0.65.0"
9
+ version = "0.66.0"
10
10
  description = ""
11
11
  authors = [{ name = "Jon R. Fox (mycr0ft)", email = "jon.fox@drfox.com" }]
12
12
  readme = "README.md"
@@ -19,11 +19,13 @@ pyyaml = ">=6.0"
19
19
  antlr4-python3-runtime = ">=4.13"
20
20
  networkx = { version = ">=3.0", optional = true }
21
21
  kuzu = { version = ">=0.7,<0.12", optional = true }
22
+ openpyxl = { version = ">=3.1", optional = true }
22
23
  arrow = "^1.4.0"
23
24
 
24
25
  [tool.poetry.extras]
25
26
  graph = ["networkx"]
26
27
  kuzu = ["kuzu"]
28
+ xlsx = ["openpyxl"]
27
29
 
28
30
  [tool.poetry.scripts]
29
31
  sysmlpy = "sysmlpy.__main__:main"
@@ -22,6 +22,9 @@ __all__ = [
22
22
  "to_interchange", "from_interchange", "interchange_to_json_text",
23
23
  "evaluate_expression", "evaluate_calculation", "collect_values",
24
24
  "check_constraints", "ConstraintReport", "ConstraintResult",
25
+ "tabular_view_to_csv", "data_value_tabular_to_csv",
26
+ "relationship_matrix_to_csv", "write_xlsx",
27
+ "import_values_csv", "import_values_xlsx", "parse_value_literal",
25
28
  "analyze", "AnalysisResult", "SemanticIssue", "SemanticAnalyzer",
26
29
  "SysMLSyntaxError", "PartialParseError",
27
30
  "loads_partial", "load_partial",
@@ -30,7 +33,7 @@ __all__ = [
30
33
  "render_state_transition_view_svg", "boxes_view",
31
34
  ]
32
35
  __author__ = "Jon Fox"
33
- __version__ = "0.65.0"
36
+ __version__ = "0.66.0"
34
37
 
35
38
  from sysmlpy.usage import (
36
39
  Item, Attribute, Part, Port, Action, Reference, UseCase, Requirement, Interface, Message,
@@ -57,6 +60,11 @@ from sysmlpy.evaluator import (
57
60
  evaluate_expression, evaluate_calculation, collect_values,
58
61
  check_constraints, ConstraintReport, ConstraintResult,
59
62
  )
63
+ from sysmlpy.spreadsheet import (
64
+ tabular_view_to_csv, data_value_tabular_to_csv,
65
+ relationship_matrix_to_csv, write_xlsx,
66
+ import_values_csv, import_values_xlsx, parse_value_literal,
67
+ )
60
68
 
61
69
 
62
70
  class PartialParseError(Exception):
@@ -31,7 +31,7 @@ import sysmlpy
31
31
  from sysmlpy import loads
32
32
 
33
33
  # Subcommand table, also used to detect the legacy flat invocation form.
34
- SUBCOMMANDS = ("parse", "analyze", "view", "trace", "export", "import", "eval", "format", "fmt")
34
+ SUBCOMMANDS = ("parse", "analyze", "view", "trace", "export", "import", "eval", "xlsx", "format", "fmt")
35
35
 
36
36
 
37
37
  # ---------------------------------------------------------------------------
@@ -433,6 +433,26 @@ def cmd_eval(args) -> int:
433
433
  name, _, raw = spec.partition("=")
434
434
  bindings[name.strip()] = _parse_eval_value(raw)
435
435
 
436
+ if getattr(args, "set_file", None):
437
+ from sysmlpy.spreadsheet import import_values_csv, import_values_xlsx
438
+ setfile = Path(args.set_file)
439
+ if not setfile.exists():
440
+ print(f"Error: --set-file '{setfile}' not found.", file=sys.stderr)
441
+ return 2
442
+ try:
443
+ if setfile.suffix.lower() == ".xlsx":
444
+ file_bindings = import_values_xlsx(setfile)
445
+ else:
446
+ # utf-8-sig tolerates Excel's BOM on CSV exports
447
+ file_bindings = import_values_csv(
448
+ setfile.read_text(encoding="utf-8-sig")
449
+ )
450
+ except (ValueError, ImportError, OSError) as e:
451
+ print(f"Error: --set-file: {e}", file=sys.stderr)
452
+ return 1
453
+ # --set flags win over spreadsheet values
454
+ bindings = {**file_bindings, **bindings}
455
+
436
456
  if args.expr is not None:
437
457
  try:
438
458
  value = evaluate_expression(
@@ -478,6 +498,36 @@ def _format_value(value):
478
498
  return str(value)
479
499
 
480
500
 
501
+ def cmd_xlsx(args) -> int:
502
+ """Export tabular views to an Excel workbook (v0.66.0, Goal 7)."""
503
+ from sysmlpy.spreadsheet import write_xlsx
504
+
505
+ paths = [Path(f) for f in args.files]
506
+ for p in _missing_files(paths):
507
+ print(f"Error: File '{p}' not found.", file=sys.stderr)
508
+ return 2
509
+
510
+ try:
511
+ model = sysmlpy.load_files(paths, library=args.library)
512
+ except Exception as e:
513
+ print(f"Parse error: {e}", file=sys.stderr)
514
+ return 2
515
+
516
+ include = tuple(s.strip() for s in args.sheets.split(",") if s.strip())
517
+ try:
518
+ out = write_xlsx(model, args.output, include=include,
519
+ focus=args.focus)
520
+ except ImportError as e:
521
+ print(f"Error: {e}", file=sys.stderr)
522
+ return 1
523
+ except Exception as e:
524
+ print(f"Error: xlsx export failed: {type(e).__name__}: {e}",
525
+ file=sys.stderr)
526
+ return 1
527
+ print(f"Wrote {out}")
528
+ return 0
529
+
530
+
481
531
  # ---------------------------------------------------------------------------
482
532
  # legacy flat invocation (kept for backward compatibility)
483
533
  # ---------------------------------------------------------------------------
@@ -642,8 +692,9 @@ def build_parser() -> argparse.ArgumentParser:
642
692
  help="Graph direction (graph views only)",
643
693
  )
644
694
  p_view.add_argument(
645
- "--format", choices=("plantuml", "markdown", "html"),
646
- help="Output format for tabular/datavalue/matrix views",
695
+ "--format", choices=("plantuml", "markdown", "html", "csv"),
696
+ help="Output format for tabular/datavalue/matrix views "
697
+ "(csv added in v0.66.0)",
647
698
  )
648
699
  p_view.add_argument(
649
700
  "-l", "--library",
@@ -757,6 +808,12 @@ def build_parser() -> argparse.ArgumentParser:
757
808
  help="Override a name for this evaluation (repeatable; values "
758
809
  "may be numbers, true/false, or unit strings like '80 km/h')",
759
810
  )
811
+ p_eval.add_argument(
812
+ "--set-file", metavar="FILE",
813
+ help="Load bindings from a CSV/XLSX values file "
814
+ "(v0.66.0; headers: Name,Value[,Unit] or "
815
+ "Element,Attribute,Value[,Unit])",
816
+ )
760
817
  p_eval.add_argument(
761
818
  "--element",
762
819
  help="Qualified element name whose scope to evaluate in",
@@ -775,6 +832,35 @@ def build_parser() -> argparse.ArgumentParser:
775
832
  )
776
833
  p_eval.set_defaults(func=cmd_eval)
777
834
 
835
+ # -- xlsx (v0.66.0, Goal 7) -------------------------------------------------
836
+ p_xlsx = sub.add_parser(
837
+ "xlsx",
838
+ help="Export tabular views to an Excel workbook",
839
+ description="Write the Tabular / DataValues / Matrix views into "
840
+ "an .xlsx workbook (requires the 'openpyxl' extra: "
841
+ "pip install 'sysmlpy[xlsx]'). Exit codes: 0 clean, "
842
+ "1 error, 2 parse error.",
843
+ )
844
+ p_xlsx.add_argument("files", nargs="+", help="SysML v2 file(s)")
845
+ p_xlsx.add_argument(
846
+ "-o", "--output", required=True,
847
+ help="Output .xlsx file path",
848
+ )
849
+ p_xlsx.add_argument(
850
+ "--sheets", default="tabular,data_value,matrix",
851
+ help="Comma-separated sheet selection: tabular,data_value,matrix "
852
+ "(default: all)",
853
+ )
854
+ p_xlsx.add_argument(
855
+ "--focus",
856
+ help="Focus element for the tabular views",
857
+ )
858
+ p_xlsx.add_argument(
859
+ "-l", "--library",
860
+ help="Path to SysML v2 library files to use for parsing",
861
+ )
862
+ p_xlsx.set_defaults(func=cmd_xlsx)
863
+
778
864
  return parser
779
865
 
780
866
 
@@ -3139,6 +3139,22 @@ def _format_table_rows_plantuml(header, rows):
3139
3139
  return lines
3140
3140
 
3141
3141
 
3142
+ def _format_table_rows_csv(header, rows):
3143
+ """Format header + rows as CSV text (v0.66.0, Goal 7).
3144
+
3145
+ Uses the ``csv`` module for proper quoting/escaping. Returns a
3146
+ trailing-newline-free string with LF line endings.
3147
+ """
3148
+ import csv as _csv
3149
+ import io as _io
3150
+
3151
+ buf = _io.StringIO()
3152
+ writer = _csv.writer(buf, lineterminator="\n")
3153
+ writer.writerow(header)
3154
+ writer.writerows(rows)
3155
+ return buf.getvalue().rstrip("\n")
3156
+
3157
+
3142
3158
  def _format_table_rows_markdown(header, rows, align=None):
3143
3159
  """Format a markdown table from header and rows."""
3144
3160
  if align is None:
@@ -3250,6 +3266,9 @@ def as_tabular_view(model, focus=None, style="bw", output_format="markdown",
3250
3266
  row.append("")
3251
3267
  rows.append(row)
3252
3268
 
3269
+ if output_format == "csv":
3270
+ return _format_table_rows_csv(header, rows)
3271
+
3253
3272
  if output_format == "markdown":
3254
3273
  align = []
3255
3274
  for col in columns:
@@ -3349,6 +3368,9 @@ def as_data_value_tabular_view(model, focus=None, style="bw",
3349
3368
  row = [parent_name, name, val_str, unit_str, typed_by]
3350
3369
  rows.append(row)
3351
3370
 
3371
+ if output_format == "csv":
3372
+ return _format_table_rows_csv(header, rows)
3373
+
3352
3374
  if output_format == "markdown":
3353
3375
  align = [":---", ":---", ":--", ":--", ":---"]
3354
3376
  parts = _format_table_rows_markdown(header, rows, align=align)
@@ -3516,6 +3538,9 @@ def as_relationship_matrix_view(model, focus=None, style="bw",
3516
3538
  row.append("")
3517
3539
  matrix_rows.append(row)
3518
3540
 
3541
+ if output_format == "csv":
3542
+ return _format_table_rows_csv(header, matrix_rows)
3543
+
3519
3544
  if output_format == "markdown":
3520
3545
  parts = _format_table_rows_markdown(header, matrix_rows, align=None)
3521
3546
  if custom_style:
@@ -0,0 +1,259 @@
1
+ # -*- coding: utf-8 -*-
2
+ """Spreadsheet bridge (v0.66.0 — Adoption Roadmap Goal 7).
3
+
4
+ Two directions:
5
+
6
+ **Export** — tabular views to CSV/XLSX workbooks:
7
+
8
+ from sysmlpy import loads, tabular_view_csv, write_xlsx
9
+ model = loads(sysml_text)
10
+ csv_text = tabular_view_to_csv(model) # Name,Type,Kind,...
11
+ write_xlsx(model, "model.xlsx") # one sheet per view
12
+
13
+ **Import** — attribute values from a spreadsheet into evaluator
14
+ bindings (what-if runs, constraint gates):
15
+
16
+ from sysmlpy import import_values_csv, check_constraints
17
+ bindings = import_values_csv("values.csv")
18
+ report = check_constraints(model, bindings=bindings)
19
+
20
+ Imported CSV/XLSX files accept either header set:
21
+
22
+ Name,Value[,Unit] e.g. mass,1200 kg
23
+ Element,Attribute,Value[,Unit] qualified element + attribute name
24
+
25
+ Values parse as int → float → boolean (`true`/`false`) → pint unit
26
+ string (e.g. ``1200 kg``) → raw string. Names may be bare
27
+ (``mass``) or qualified (``VehicleSpec::Vehicle::mass``).
28
+ """
29
+
30
+ from __future__ import annotations
31
+
32
+ import csv
33
+ import io
34
+ from typing import Any, Dict, List, Optional, Sequence
35
+
36
+ __all__ = [
37
+ "tabular_view_to_csv", "data_value_tabular_to_csv",
38
+ "relationship_matrix_to_csv", "write_xlsx",
39
+ "import_values_csv", "import_values_xlsx", "parse_value_literal",
40
+ ]
41
+
42
+
43
+ # ---------------------------------------------------------------------------
44
+ # value parsing (shared by import + CLI --set)
45
+ # ---------------------------------------------------------------------------
46
+
47
+
48
+ def parse_value_literal(raw: str) -> Any:
49
+ """Parse a spreadsheet/CLI value literal into a Python value.
50
+
51
+ Order: bool → int → float → pint quantity → raw string. Pint
52
+ strings like ``1200 kg`` or ``80 km/h`` become ``Quantity`` objects;
53
+ anything that parses nowhere is kept as a string (e.g. names).
54
+ """
55
+ from sysmlpy.usage import ureg
56
+
57
+ text = raw.strip() if isinstance(raw, str) else raw
58
+ low = str(text).strip().lower()
59
+ if low == "true":
60
+ return True
61
+ if low == "false":
62
+ return False
63
+ s = str(text)
64
+ try:
65
+ return int(s)
66
+ except ValueError:
67
+ pass
68
+ try:
69
+ return float(s)
70
+ except ValueError:
71
+ pass
72
+ try:
73
+ return ureg(s)
74
+ except Exception:
75
+ pass
76
+ return s
77
+
78
+
79
+ # ---------------------------------------------------------------------------
80
+ # CSV export of the tabular views
81
+ # ---------------------------------------------------------------------------
82
+
83
+
84
+ def tabular_view_to_csv(model, focus=None, columns=None) -> str:
85
+ """Tabular View (Name/Type/Kind/Parent/…) as CSV text."""
86
+ from sysmlpy.plantuml import as_tabular_view
87
+ return as_tabular_view(model, focus=focus, output_format="csv",
88
+ columns=columns)
89
+
90
+
91
+ def data_value_tabular_to_csv(model, focus=None, include_units=True) -> str:
92
+ """Data Value Tabular View (Element/Attribute/Value/Unit/…) as CSV."""
93
+ from sysmlpy.plantuml import as_data_value_tabular_view
94
+ return as_data_value_tabular_view(model, focus=focus,
95
+ output_format="csv",
96
+ include_units=include_units)
97
+
98
+
99
+ def relationship_matrix_to_csv(model, focus=None, row_type=None,
100
+ col_type=None, symmetric=True) -> str:
101
+ """Relationship Matrix View as CSV."""
102
+ from sysmlpy.plantuml import as_relationship_matrix_view
103
+ return as_relationship_matrix_view(model, focus=focus,
104
+ row_type=row_type, col_type=col_type,
105
+ symmetric=symmetric,
106
+ output_format="csv")
107
+
108
+
109
+ # ---------------------------------------------------------------------------
110
+ # XLSX export (openpyxl optional)
111
+ # ---------------------------------------------------------------------------
112
+
113
+
114
+ def _require_openpyxl():
115
+ try:
116
+ import openpyxl # noqa: F401
117
+ except ImportError:
118
+ raise ImportError(
119
+ "XLSX export requires the 'openpyxl' package — "
120
+ "install with: pip install 'sysmlpy[xlsx]' (or pip install openpyxl)"
121
+ ) from None
122
+ import openpyxl
123
+ return openpyxl
124
+
125
+
126
+ def write_xlsx(model, path, include=("tabular", "data_value", "matrix"),
127
+ focus=None) -> str:
128
+ """Write tabular views into an Excel workbook (one sheet per view).
129
+
130
+ *include* selects sheets: ``"tabular"``, ``"data_value"``,
131
+ ``"matrix"``. Requires openpyxl (``pip install openpyxl``).
132
+ Returns the resolved output path.
133
+ """
134
+ from pathlib import Path
135
+
136
+ openpyxl = _require_openpyxl()
137
+
138
+ sheet_sources = {
139
+ "tabular": lambda: tabular_view_to_csv(model, focus=focus),
140
+ "data_value": lambda: data_value_tabular_to_csv(model, focus=focus),
141
+ "matrix": lambda: relationship_matrix_to_csv(model, focus=focus),
142
+ }
143
+ sheet_names = {
144
+ "tabular": "Tabular",
145
+ "data_value": "DataValues",
146
+ "matrix": "Matrix",
147
+ }
148
+
149
+ wb = openpyxl.Workbook()
150
+ wb.remove(wb.active)
151
+ wrote_any = False
152
+ for key in include:
153
+ if key not in sheet_sources:
154
+ raise ValueError(f"Unknown sheet kind: {key!r} — expected one "
155
+ f"of {sorted(sheet_sources)}")
156
+ rows = list(csv.reader(io.StringIO(sheet_sources[key]())))
157
+ if not rows:
158
+ continue
159
+ ws = wb.create_sheet(sheet_names[key])
160
+ for row in rows:
161
+ ws.append(row)
162
+ # bold header row for readability
163
+ for cell in ws[1]:
164
+ cell.font = openpyxl.styles.Font(bold=True)
165
+ wrote_any = True
166
+
167
+ if not wrote_any:
168
+ # still produce a valid workbook with a note sheet
169
+ ws = wb.create_sheet("Empty")
170
+ ws.append(["(no tabular content in this model)"])
171
+
172
+ out = Path(path)
173
+ out.parent.mkdir(parents=True, exist_ok=True)
174
+ wb.save(out)
175
+ return str(out)
176
+
177
+
178
+ # ---------------------------------------------------------------------------
179
+ # Value import → evaluator bindings
180
+ # ---------------------------------------------------------------------------
181
+
182
+ _VALUE_HEADERS = ("value", "val")
183
+ _NAME_HEADERS = ("name", "element", "qualified name", "qualified_name")
184
+ _ATTRIBUTE_HEADERS = ("attribute", "feature", "attr")
185
+ _UNIT_HEADERS = ("unit", "units")
186
+
187
+
188
+ def _normalize_header(cell) -> str:
189
+ return str(cell).strip().lower() if cell is not None else ""
190
+
191
+
192
+ def _rows_to_bindings(rows: List[List[Any]]) -> Dict[str, Any]:
193
+ """Turn spreadsheet rows into evaluator ``bindings``.
194
+
195
+ Accepted layouts (header row required, case-insensitive):
196
+ Name,Value[,Unit] — Name may be bare or qualified
197
+ Element,Attribute,Value[,Unit]
198
+ """
199
+ if not rows:
200
+ return {}
201
+ header = [_normalize_header(c) for c in rows[0]]
202
+ col = {}
203
+ for idx, h in enumerate(header):
204
+ if h in _NAME_HEADERS and "name" not in col:
205
+ col["name"] = idx
206
+ elif h in _ATTRIBUTE_HEADERS and "attr" not in col:
207
+ col["attr"] = idx
208
+ elif h in _VALUE_HEADERS and "value" not in col:
209
+ col["value"] = idx
210
+ elif h in _UNIT_HEADERS and "unit" not in col:
211
+ col["unit"] = idx
212
+ if "value" not in col or ("name" not in col and "attr" not in col):
213
+ raise ValueError(
214
+ "Import CSV needs a header row with Name/Value (or "
215
+ "Element/Attribute/Value) columns — "
216
+ f"got header {rows[0]!r}"
217
+ )
218
+
219
+ bindings: Dict[str, Any] = {}
220
+ for lineno, row in enumerate(rows[1:], start=2):
221
+ if not row or all(c is None or str(c).strip() == ""
222
+ for c in row):
223
+ continue # blank row
224
+ raw_value = row[col["value"]] if col["value"] < len(row) else None
225
+ raw_value = str(raw_value).strip() if raw_value is not None else ""
226
+ if not raw_value:
227
+ raise ValueError(f"Row {lineno}: missing value for "
228
+ f"{row[:2]!r}")
229
+ if "unit" in col and col["unit"] < len(row) and row[col["unit"]]:
230
+ raw_value = f"{raw_value} {str(row[col['unit']]).strip()}"
231
+ value = parse_value_literal(raw_value)
232
+ if "attr" in col:
233
+ attr = str(row[col["attr"]]).strip() \
234
+ if col["attr"] < len(row) else ""
235
+ base = str(row[col["name"]]).strip() \
236
+ if col["name"] < len(row) else ""
237
+ name = f"{base}::{attr}" if base and attr else (attr or base)
238
+ else:
239
+ name = str(row[col["name"]]).strip()
240
+ bindings[name] = value
241
+ return bindings
242
+
243
+
244
+ def import_values_csv(text: str) -> Dict[str, Any]:
245
+ """Import attribute values from CSV text → evaluator bindings dict.
246
+
247
+ See the module docstring for the accepted layouts.
248
+ """
249
+ rows = list(csv.reader(io.StringIO(text)))
250
+ return _rows_to_bindings(rows)
251
+
252
+
253
+ def import_values_xlsx(path) -> Dict[str, Any]:
254
+ """Import attribute values from the first sheet of an XLSX workbook."""
255
+ openpyxl = _require_openpyxl()
256
+ wb = openpyxl.load_workbook(path, data_only=True)
257
+ ws = wb.worksheets[0]
258
+ rows = [[cell.value for cell in row] for row in ws.iter_rows()]
259
+ return _rows_to_bindings(rows)
File without changes
File without changes
File without changes
File without changes