sysmlpy 0.91.0__tar.gz → 0.95.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.
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/PKG-INFO +87 -1
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/README.md +84 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/pyproject.toml +3 -1
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/__init__.py +5 -1
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/__main__.py +124 -1
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/antlr_visitor.py +101 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/evaluator.py +27 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/grammar/classes.py +8 -1
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/plantuml.py +260 -2
- sysmlpy-0.95.0/src/sysmlpy/repl.py +638 -0
- sysmlpy-0.95.0/src/sysmlpy/reqif_io.py +411 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/usage.py +56 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/LICENSE +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/antlr/README.md +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/antlr/SysMLv2Lexer.interp +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/antlr/SysMLv2Lexer.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/antlr/SysMLv2Lexer.tokens +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/antlr/SysMLv2Parser.interp +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/antlr/SysMLv2Parser.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/antlr/SysMLv2Parser.tokens +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/antlr/SysMLv2ParserListener.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/antlr/SysMLv2ParserVisitor.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.interp +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.tokens +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/antlr_parser.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/boxes_view.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/definition.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/dfa_cache.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/diff.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/examples/attribute_values.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/examples/part_attributes.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/examples/tuples_sequences.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/formatting.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/grammar/antlr4/README.md +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.g4 +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.interp +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.tokens +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.g4 +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.interp +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.tokens +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/grammar/antlr4/SysMLv2ParserListener.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/grammar/antlr4/SysMLv2ParserVisitor.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/grammar/antlr4/desc.xml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/grammar/antlr4/examples/camera.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/grammar/antlr4/examples/toaster-system.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/grammar/antlr4/examples/vehicle-model.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/grammar/antlr4/pom.xml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/interchange.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/ipython_magic.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/LICENSE +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/README.md +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/__init__.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Analysis/AnalysisTooling.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Analysis/SampledFunctions.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Analysis/StateSpaceRepresentation.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Analysis/TradeStudies.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Cause and Effect/CausationConnections.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Cause and Effect/CauseAndEffect.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Geometry/ShapeItems.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Geometry/SpatialItems.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Metadata/ImageMetadata.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Metadata/ModelingMetadata.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Metadata/ParametersOfInterestMetadata.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Metadata/RiskMetadata.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Quantities and Units/ISQ.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Quantities and Units/ISQAcoustics.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Quantities and Units/ISQAtomicNuclear.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Quantities and Units/ISQBase.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Quantities and Units/ISQCharacteristicNumbers.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Quantities and Units/ISQChemistryMolecular.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Quantities and Units/ISQCondensedMatter.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Quantities and Units/ISQElectromagnetism.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Quantities and Units/ISQInformation.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Quantities and Units/ISQLight.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Quantities and Units/ISQMechanics.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Quantities and Units/ISQSpaceTime.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Quantities and Units/ISQThermodynamics.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Quantities and Units/MeasurementRefCalculations.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Quantities and Units/MeasurementReferences.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Quantities and Units/Quantities.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Quantities and Units/QuantityCalculations.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Quantities and Units/SI.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Quantities and Units/SIPrefixes.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Quantities and Units/TensorCalculations.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Quantities and Units/Time.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Quantities and Units/USCustomaryUnits.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Quantities and Units/VectorCalculations.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Requirement Derivation/DerivationConnections.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/domain/Requirement Derivation/RequirementDerivation.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/Base.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/BaseFunctions.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/BooleanFunctions.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/Clocks.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/CollectionFunctions.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/Collections.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/ComplexFunctions.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/ControlFunctions.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/ControlPerformances.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/DataFunctions.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/FeatureReferencingPerformances.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/IntegerFunctions.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/KerML.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/Links.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/Metaobjects.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/NaturalFunctions.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/NumericalFunctions.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/Objects.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/Observation.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/OccurrenceFunctions.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/Occurrences.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/Performances.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/RationalFunctions.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/RealFunctions.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/ScalarFunctions.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/ScalarValues.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/SequenceFunctions.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/SpatialFrames.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/StatePerformances.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/StringFunctions.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/Transfers.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/TransitionPerformances.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/TrigFunctions.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/Triggers.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/VectorFunctions.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/kernel/VectorValues.kerml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/systems/Actions.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/systems/Allocations.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/systems/AnalysisCases.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/systems/Attributes.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/systems/Calculations.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/systems/Cases.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/systems/Connections.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/systems/Constraints.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/systems/Flows.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/systems/Interfaces.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/systems/Items.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/systems/Metadata.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/systems/Parts.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/systems/Ports.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/systems/Requirements.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/systems/StandardViewDefinitions.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/systems/States.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/systems/SysML.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/systems/UseCases.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/systems/VerificationCases.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/library/systems/Views.sysml +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/lsp/__init__.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/lsp/__main__.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/lsp/protocol.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/lsp/server.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/lsp/stdio.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/navigate.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/project.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/semantic.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/sim.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/spreadsheet.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/store.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/traceability.py +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/us_customary_units.txt +0 -0
- {sysmlpy-0.91.0 → sysmlpy-0.95.0}/src/sysmlpy/validator.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sysmlpy
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.95.0
|
|
4
4
|
Summary:
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Author: Jon R. Fox (mycr0ft)
|
|
@@ -17,6 +17,7 @@ Provides-Extra: cayley
|
|
|
17
17
|
Provides-Extra: graph
|
|
18
18
|
Provides-Extra: jupyter
|
|
19
19
|
Provides-Extra: kuzu
|
|
20
|
+
Provides-Extra: reqif
|
|
20
21
|
Provides-Extra: sim
|
|
21
22
|
Provides-Extra: xlsx
|
|
22
23
|
Requires-Dist: antlr4-python3-runtime (>=4.13)
|
|
@@ -27,6 +28,7 @@ Requires-Dist: networkx (>=3.0) ; extra == "graph"
|
|
|
27
28
|
Requires-Dist: openpyxl (>=3.1) ; extra == "xlsx"
|
|
28
29
|
Requires-Dist: pint (>=0.24)
|
|
29
30
|
Requires-Dist: pyyaml (>=6.0)
|
|
31
|
+
Requires-Dist: reqif (>=0.1) ; extra == "reqif"
|
|
30
32
|
Requires-Dist: requests (>=2.31) ; extra == "cayley"
|
|
31
33
|
Requires-Dist: transitions (>=0.9,<0.10) ; extra == "sim"
|
|
32
34
|
Description-Content-Type: text/markdown
|
|
@@ -73,6 +75,7 @@ sysmlpy requires the following Python packages:
|
|
|
73
75
|
- [networkx](https://networkx.org/) — graph analysis backend (install with `pip install sysmlpy[graph]`)
|
|
74
76
|
- [kuzu](https://kuzudb.com/) — embedded graph database with disk persistence and Cypher queries (install with `pip install sysmlpy[kuzu]`)
|
|
75
77
|
- [cayley](https://cayley.io/) — graph database via HTTP API, supports BoltDB/LevelDB backends (install with `pip install sysmlpy[cayley]`)
|
|
78
|
+
- [reqif](https://github.com/strictdoc-project/reqif) — ReqIF 1.0 requirements interchange, import/export with any ReqIF-capable tool (install with `pip install sysmlpy[reqif]`; see [ReqIF Interchange](#reqif-interchange-requirements-interchange-format))
|
|
76
79
|
- [PlantUML](https://plantuml.com/) **v1.2020.0+** — diagram rendering (requires Java + PlantUML JAR or [PlantUML server](https://www.plantuml.com/plantuml)). The generator uses `<style>` blocks and `skinparam` stereotype selectors introduced in v1.2020.
|
|
77
80
|
- [IPython](https://ipython.org/) **v8.0+** — the `%%sysml` Jupyter cell magic (install with `pip install sysmlpy[jupyter]`; see [Jupyter integration](#jupyter-integration))
|
|
78
81
|
|
|
@@ -150,9 +153,12 @@ threshold or operational error, `2` = parse/load failure — so
|
|
|
150
153
|
| `sysmlpy trace <file>` | Requirement traceability & verification coverage |
|
|
151
154
|
| `sysmlpy export <file>` | Export to the JSON interchange format |
|
|
152
155
|
| `sysmlpy import <file>` | Import a JSON interchange document as SysML text |
|
|
156
|
+
| `sysmlpy reqif-import <file>` | Import a ReqIF file as SysML v2 requirements |
|
|
157
|
+
| `sysmlpy reqif-export <file>` | Export model requirements as ReqIF 1.0 XML |
|
|
153
158
|
| `sysmlpy eval <file>` | Evaluate expressions, attribute values, constraints |
|
|
154
159
|
| `sysmlpy sim <file>` | Simulate a state machine (guards evaluated for real) |
|
|
155
160
|
| `sysmlpy xlsx <file>` | Export tabular views to an Excel workbook |
|
|
161
|
+
| `sysmlpy repl <file...>` | Interactive REPL: declarations accumulate into a session model; `%eval`, `%sim`, `%view`, `%check`, ... inspect it |
|
|
156
162
|
| `sysmlpy-lsp` | Language server (stdio) for SysML v2 editors |
|
|
157
163
|
|
|
158
164
|
Examples:
|
|
@@ -171,6 +177,15 @@ sysmlpy view model.sysml --view sv > model.puml
|
|
|
171
177
|
# Drive a state machine interactively
|
|
172
178
|
sysmlpy sim traffic_light.sysml
|
|
173
179
|
|
|
180
|
+
# Or work in an accumulating session: declare, query, evaluate, simulate
|
|
181
|
+
sysmlpy repl
|
|
182
|
+
sysml> package Demo { part def Wheel { attribute diameter : Real = 16.0; } }
|
|
183
|
+
✓ Demo
|
|
184
|
+
sysml> %eval Demo::Wheel::diameter
|
|
185
|
+
= 16.0
|
|
186
|
+
sysml> %view Demo pkg
|
|
187
|
+
sysml> %quit
|
|
188
|
+
|
|
174
189
|
# Excel workbook of the tabular views
|
|
175
190
|
sysmlpy xlsx bill_of_materials.sysml -o bom.xlsx
|
|
176
191
|
```
|
|
@@ -864,6 +879,77 @@ See [`docs/plantuml-examples/`](docs/plantuml-examples/) for all rendered exampl
|
|
|
864
879
|
| 15 | Relationship Matrix (GridView) | Relationship Matrix |
|
|
865
880
|
| 16 | Tabular View — Color | Tabular View (color) |
|
|
866
881
|
|
|
882
|
+
## ReqIF Interchange (Requirements Interchange Format)
|
|
883
|
+
|
|
884
|
+
sysmlpy imports and exports **ReqIF 1.0** — the OMG requirements interchange
|
|
885
|
+
standard used by DOORS, Polarion, ReqIF Studio, Capella, Enterprise Architect,
|
|
886
|
+
and most requirements-management tools. This makes sysmlpy a viable
|
|
887
|
+
*single source of truth* for requirements: author them as SysML v2
|
|
888
|
+
`requirement` elements, then exchange them with any ReqIF-capable toolchain.
|
|
889
|
+
|
|
890
|
+
Install the optional dependency once:
|
|
891
|
+
|
|
892
|
+
```bash
|
|
893
|
+
pip install sysmlpy[reqif]
|
|
894
|
+
```
|
|
895
|
+
|
|
896
|
+
### Import — ReqIF → SysML requirements
|
|
897
|
+
|
|
898
|
+
```python
|
|
899
|
+
from sysmlpy import reqif_import, loads
|
|
900
|
+
|
|
901
|
+
text = reqif_import("requirements.reqif") # ReqIF XML → SysML v2 text
|
|
902
|
+
model = loads(text) # → live requirement tree
|
|
903
|
+
```
|
|
904
|
+
|
|
905
|
+
Each ReqIF SpecObject becomes a `requirement` element; the ReqIF
|
|
906
|
+
specification hierarchy becomes requirement ownership nesting;
|
|
907
|
+
`ReqIF.Text` (XHTML) becomes the requirement's `doc` comment with tags
|
|
908
|
+
stripped; other attributes (e.g. `ReqIF.ForeignID`) are folded into the
|
|
909
|
+
doc so no data is lost.
|
|
910
|
+
|
|
911
|
+
### Export — SysML requirements → ReqIF
|
|
912
|
+
|
|
913
|
+
```python
|
|
914
|
+
from sysmlpy import loads, reqif_export
|
|
915
|
+
|
|
916
|
+
model = loads("model.sysml")
|
|
917
|
+
reqif_export(model, "requirements.reqif")
|
|
918
|
+
```
|
|
919
|
+
|
|
920
|
+
Requirement ownership becomes the ReqIF hierarchy; `doc` comments become
|
|
921
|
+
`ReqIF.Text` XHTML values.
|
|
922
|
+
|
|
923
|
+
### CLI
|
|
924
|
+
|
|
925
|
+
```bash
|
|
926
|
+
sysmlpy reqif-import requirements.reqif -o requirements.sysml
|
|
927
|
+
sysmlpy reqif-export model.sysml -o requirements.reqif
|
|
928
|
+
```
|
|
929
|
+
|
|
930
|
+
The import direction was validated against real-world anonymized ReqIF
|
|
931
|
+
files from multiple vendor flavors (ReqIF Studio, DOORS, Polarion,
|
|
932
|
+
Eclipse RMF, Enterprise Architect — see the
|
|
933
|
+
[reqif project's corpus](https://github.com/strictdoc-project/reqif/tree/main/tests/integration/reqif_software)),
|
|
934
|
+
including a 137-requirement model with a 3-level hierarchy and 14
|
|
935
|
+
relations, round-tripped through sysmlpy with exact structural fidelity.
|
|
936
|
+
|
|
937
|
+
> **Note:** ReqIF "flavors" differ across tools (attribute naming,
|
|
938
|
+
> datatypes, relation semantics). The importer handles the common
|
|
939
|
+
> `ReqIF.Text` / `ReqIF.ChapterName` / `ReqIF.ForeignID` attributes
|
|
940
|
+
> found in every flavor; exotic vendor extensions are skipped
|
|
941
|
+
> gracefully. If a file fails to import, it is genuinely malformed.
|
|
942
|
+
|
|
943
|
+
### Relationship to other tools
|
|
944
|
+
|
|
945
|
+
- **Cameo / MagicDraw** — export ReqIF from them, import with sysmlpy;
|
|
946
|
+
no license needed on the sysmlpy side.
|
|
947
|
+
- **Doorstop** — the [Doorstop](https://doorstop.readthedocs.io) text-file
|
|
948
|
+
requirements tool can serve as a git-native review/publishing front-end;
|
|
949
|
+
exchange via ReqIF or the XLSX bridge.
|
|
950
|
+
- **[strictdoc/reqif](https://github.com/strictdoc-project/reqif)** — the
|
|
951
|
+
parser library sysmlpy uses for the ReqIF wire format (Apache-2.0).
|
|
952
|
+
|
|
867
953
|
## Conformance
|
|
868
954
|
|
|
869
955
|
**100% of 123 OMG XPect conformance tests pass** (123/123).
|
|
@@ -40,6 +40,7 @@ sysmlpy requires the following Python packages:
|
|
|
40
40
|
- [networkx](https://networkx.org/) — graph analysis backend (install with `pip install sysmlpy[graph]`)
|
|
41
41
|
- [kuzu](https://kuzudb.com/) — embedded graph database with disk persistence and Cypher queries (install with `pip install sysmlpy[kuzu]`)
|
|
42
42
|
- [cayley](https://cayley.io/) — graph database via HTTP API, supports BoltDB/LevelDB backends (install with `pip install sysmlpy[cayley]`)
|
|
43
|
+
- [reqif](https://github.com/strictdoc-project/reqif) — ReqIF 1.0 requirements interchange, import/export with any ReqIF-capable tool (install with `pip install sysmlpy[reqif]`; see [ReqIF Interchange](#reqif-interchange-requirements-interchange-format))
|
|
43
44
|
- [PlantUML](https://plantuml.com/) **v1.2020.0+** — diagram rendering (requires Java + PlantUML JAR or [PlantUML server](https://www.plantuml.com/plantuml)). The generator uses `<style>` blocks and `skinparam` stereotype selectors introduced in v1.2020.
|
|
44
45
|
- [IPython](https://ipython.org/) **v8.0+** — the `%%sysml` Jupyter cell magic (install with `pip install sysmlpy[jupyter]`; see [Jupyter integration](#jupyter-integration))
|
|
45
46
|
|
|
@@ -117,9 +118,12 @@ threshold or operational error, `2` = parse/load failure — so
|
|
|
117
118
|
| `sysmlpy trace <file>` | Requirement traceability & verification coverage |
|
|
118
119
|
| `sysmlpy export <file>` | Export to the JSON interchange format |
|
|
119
120
|
| `sysmlpy import <file>` | Import a JSON interchange document as SysML text |
|
|
121
|
+
| `sysmlpy reqif-import <file>` | Import a ReqIF file as SysML v2 requirements |
|
|
122
|
+
| `sysmlpy reqif-export <file>` | Export model requirements as ReqIF 1.0 XML |
|
|
120
123
|
| `sysmlpy eval <file>` | Evaluate expressions, attribute values, constraints |
|
|
121
124
|
| `sysmlpy sim <file>` | Simulate a state machine (guards evaluated for real) |
|
|
122
125
|
| `sysmlpy xlsx <file>` | Export tabular views to an Excel workbook |
|
|
126
|
+
| `sysmlpy repl <file...>` | Interactive REPL: declarations accumulate into a session model; `%eval`, `%sim`, `%view`, `%check`, ... inspect it |
|
|
123
127
|
| `sysmlpy-lsp` | Language server (stdio) for SysML v2 editors |
|
|
124
128
|
|
|
125
129
|
Examples:
|
|
@@ -138,6 +142,15 @@ sysmlpy view model.sysml --view sv > model.puml
|
|
|
138
142
|
# Drive a state machine interactively
|
|
139
143
|
sysmlpy sim traffic_light.sysml
|
|
140
144
|
|
|
145
|
+
# Or work in an accumulating session: declare, query, evaluate, simulate
|
|
146
|
+
sysmlpy repl
|
|
147
|
+
sysml> package Demo { part def Wheel { attribute diameter : Real = 16.0; } }
|
|
148
|
+
✓ Demo
|
|
149
|
+
sysml> %eval Demo::Wheel::diameter
|
|
150
|
+
= 16.0
|
|
151
|
+
sysml> %view Demo pkg
|
|
152
|
+
sysml> %quit
|
|
153
|
+
|
|
141
154
|
# Excel workbook of the tabular views
|
|
142
155
|
sysmlpy xlsx bill_of_materials.sysml -o bom.xlsx
|
|
143
156
|
```
|
|
@@ -831,6 +844,77 @@ See [`docs/plantuml-examples/`](docs/plantuml-examples/) for all rendered exampl
|
|
|
831
844
|
| 15 | Relationship Matrix (GridView) | Relationship Matrix |
|
|
832
845
|
| 16 | Tabular View — Color | Tabular View (color) |
|
|
833
846
|
|
|
847
|
+
## ReqIF Interchange (Requirements Interchange Format)
|
|
848
|
+
|
|
849
|
+
sysmlpy imports and exports **ReqIF 1.0** — the OMG requirements interchange
|
|
850
|
+
standard used by DOORS, Polarion, ReqIF Studio, Capella, Enterprise Architect,
|
|
851
|
+
and most requirements-management tools. This makes sysmlpy a viable
|
|
852
|
+
*single source of truth* for requirements: author them as SysML v2
|
|
853
|
+
`requirement` elements, then exchange them with any ReqIF-capable toolchain.
|
|
854
|
+
|
|
855
|
+
Install the optional dependency once:
|
|
856
|
+
|
|
857
|
+
```bash
|
|
858
|
+
pip install sysmlpy[reqif]
|
|
859
|
+
```
|
|
860
|
+
|
|
861
|
+
### Import — ReqIF → SysML requirements
|
|
862
|
+
|
|
863
|
+
```python
|
|
864
|
+
from sysmlpy import reqif_import, loads
|
|
865
|
+
|
|
866
|
+
text = reqif_import("requirements.reqif") # ReqIF XML → SysML v2 text
|
|
867
|
+
model = loads(text) # → live requirement tree
|
|
868
|
+
```
|
|
869
|
+
|
|
870
|
+
Each ReqIF SpecObject becomes a `requirement` element; the ReqIF
|
|
871
|
+
specification hierarchy becomes requirement ownership nesting;
|
|
872
|
+
`ReqIF.Text` (XHTML) becomes the requirement's `doc` comment with tags
|
|
873
|
+
stripped; other attributes (e.g. `ReqIF.ForeignID`) are folded into the
|
|
874
|
+
doc so no data is lost.
|
|
875
|
+
|
|
876
|
+
### Export — SysML requirements → ReqIF
|
|
877
|
+
|
|
878
|
+
```python
|
|
879
|
+
from sysmlpy import loads, reqif_export
|
|
880
|
+
|
|
881
|
+
model = loads("model.sysml")
|
|
882
|
+
reqif_export(model, "requirements.reqif")
|
|
883
|
+
```
|
|
884
|
+
|
|
885
|
+
Requirement ownership becomes the ReqIF hierarchy; `doc` comments become
|
|
886
|
+
`ReqIF.Text` XHTML values.
|
|
887
|
+
|
|
888
|
+
### CLI
|
|
889
|
+
|
|
890
|
+
```bash
|
|
891
|
+
sysmlpy reqif-import requirements.reqif -o requirements.sysml
|
|
892
|
+
sysmlpy reqif-export model.sysml -o requirements.reqif
|
|
893
|
+
```
|
|
894
|
+
|
|
895
|
+
The import direction was validated against real-world anonymized ReqIF
|
|
896
|
+
files from multiple vendor flavors (ReqIF Studio, DOORS, Polarion,
|
|
897
|
+
Eclipse RMF, Enterprise Architect — see the
|
|
898
|
+
[reqif project's corpus](https://github.com/strictdoc-project/reqif/tree/main/tests/integration/reqif_software)),
|
|
899
|
+
including a 137-requirement model with a 3-level hierarchy and 14
|
|
900
|
+
relations, round-tripped through sysmlpy with exact structural fidelity.
|
|
901
|
+
|
|
902
|
+
> **Note:** ReqIF "flavors" differ across tools (attribute naming,
|
|
903
|
+
> datatypes, relation semantics). The importer handles the common
|
|
904
|
+
> `ReqIF.Text` / `ReqIF.ChapterName` / `ReqIF.ForeignID` attributes
|
|
905
|
+
> found in every flavor; exotic vendor extensions are skipped
|
|
906
|
+
> gracefully. If a file fails to import, it is genuinely malformed.
|
|
907
|
+
|
|
908
|
+
### Relationship to other tools
|
|
909
|
+
|
|
910
|
+
- **Cameo / MagicDraw** — export ReqIF from them, import with sysmlpy;
|
|
911
|
+
no license needed on the sysmlpy side.
|
|
912
|
+
- **Doorstop** — the [Doorstop](https://doorstop.readthedocs.io) text-file
|
|
913
|
+
requirements tool can serve as a git-native review/publishing front-end;
|
|
914
|
+
exchange via ReqIF or the XLSX bridge.
|
|
915
|
+
- **[strictdoc/reqif](https://github.com/strictdoc-project/reqif)** — the
|
|
916
|
+
parser library sysmlpy uses for the ReqIF wire format (Apache-2.0).
|
|
917
|
+
|
|
834
918
|
## Conformance
|
|
835
919
|
|
|
836
920
|
**100% of 123 OMG XPect conformance tests pass** (123/123).
|
|
@@ -6,7 +6,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "sysmlpy"
|
|
9
|
-
version = "0.
|
|
9
|
+
version = "0.95.0"
|
|
10
10
|
description = ""
|
|
11
11
|
authors = [{ name = "Jon R. Fox (mycr0ft)", email = "jon.fox@drfox.com" }]
|
|
12
12
|
readme = "README.md"
|
|
@@ -20,6 +20,7 @@ antlr4-python3-runtime = ">=4.13"
|
|
|
20
20
|
networkx = { version = ">=3.0", optional = true }
|
|
21
21
|
kuzu = { version = ">=0.7,<0.12", optional = true }
|
|
22
22
|
openpyxl = { version = ">=3.1", optional = true }
|
|
23
|
+
reqif = { version = ">=0.1", optional = true }
|
|
23
24
|
arrow = "^1.4.0"
|
|
24
25
|
transitions = {version = "^0.9", optional = true}
|
|
25
26
|
requests = { version = ">=2.31", optional = true }
|
|
@@ -30,6 +31,7 @@ graph = ["networkx"]
|
|
|
30
31
|
kuzu = ["kuzu"]
|
|
31
32
|
xlsx = ["openpyxl"]
|
|
32
33
|
sim = ["transitions"]
|
|
34
|
+
reqif = ["reqif"]
|
|
33
35
|
cayley = ["requests"]
|
|
34
36
|
jupyter = ["ipython"]
|
|
35
37
|
|
|
@@ -20,6 +20,7 @@ __all__ = [
|
|
|
20
20
|
"as_sequence_view", "as_case_view", "as_browser_view",
|
|
21
21
|
"extract_traceability", "TraceabilityReport", "RequirementTrace",
|
|
22
22
|
"to_interchange", "from_interchange", "interchange_to_json_text",
|
|
23
|
+
"reqif_import", "reqif_import_model", "reqif_export",
|
|
23
24
|
"evaluate_expression", "evaluate_calculation", "collect_values",
|
|
24
25
|
"check_constraints", "ConstraintReport", "ConstraintResult",
|
|
25
26
|
"tabular_view_to_csv", "data_value_tabular_to_csv",
|
|
@@ -34,7 +35,7 @@ __all__ = [
|
|
|
34
35
|
"render_state_transition_view_svg", "boxes_view",
|
|
35
36
|
]
|
|
36
37
|
__author__ = "Jon Fox"
|
|
37
|
-
__version__ = "0.
|
|
38
|
+
__version__ = "0.95.0"
|
|
38
39
|
|
|
39
40
|
from sysmlpy.usage import (
|
|
40
41
|
Item, Attribute, Part, Port, Action, Reference, UseCase, Requirement, Interface, Message,
|
|
@@ -57,6 +58,9 @@ from sysmlpy.traceability import (
|
|
|
57
58
|
from sysmlpy.interchange import (
|
|
58
59
|
to_interchange, from_interchange, interchange_to_json_text,
|
|
59
60
|
)
|
|
61
|
+
from sysmlpy.reqif_io import (
|
|
62
|
+
reqif_import, reqif_import_model, reqif_export,
|
|
63
|
+
)
|
|
60
64
|
from sysmlpy.evaluator import (
|
|
61
65
|
evaluate_expression, evaluate_calculation, collect_values,
|
|
62
66
|
check_constraints, ConstraintReport, ConstraintResult,
|
|
@@ -33,7 +33,8 @@ from sysmlpy import loads
|
|
|
33
33
|
|
|
34
34
|
# Subcommand table, also used to detect the legacy flat invocation form.
|
|
35
35
|
SUBCOMMANDS = ("parse", "analyze", "view", "trace", "export", "import",
|
|
36
|
-
"
|
|
36
|
+
"reqif-import", "reqif-export",
|
|
37
|
+
"eval", "xlsx", "sim", "diff", "format", "fmt", "repl")
|
|
37
38
|
|
|
38
39
|
|
|
39
40
|
# ---------------------------------------------------------------------------
|
|
@@ -442,6 +443,60 @@ def cmd_import(args) -> int:
|
|
|
442
443
|
return 0
|
|
443
444
|
|
|
444
445
|
|
|
446
|
+
def cmd_reqif_import(args) -> int:
|
|
447
|
+
"""ReqIF file → SysML v2 requirements text."""
|
|
448
|
+
from sysmlpy.reqif_io import ReqIFImportError, reqif_import
|
|
449
|
+
|
|
450
|
+
path = Path(args.file)
|
|
451
|
+
if not path.exists():
|
|
452
|
+
print(f"Error: File '{path}' not found.", file=sys.stderr)
|
|
453
|
+
return 2
|
|
454
|
+
|
|
455
|
+
try:
|
|
456
|
+
output = reqif_import(str(path))
|
|
457
|
+
except ReqIFImportError as e:
|
|
458
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
459
|
+
return 2
|
|
460
|
+
except Exception as e: # noqa: BLE001 - surface parser failures cleanly
|
|
461
|
+
print(f"Error: ReqIF import failed: {e}", file=sys.stderr)
|
|
462
|
+
return 2
|
|
463
|
+
|
|
464
|
+
if args.output:
|
|
465
|
+
Path(args.output).write_text(output, encoding="utf-8")
|
|
466
|
+
print(f"Wrote {args.output}")
|
|
467
|
+
else:
|
|
468
|
+
print(output)
|
|
469
|
+
return 0
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
def cmd_reqif_export(args) -> int:
|
|
473
|
+
"""SysML requirements → ReqIF 1.0 XML."""
|
|
474
|
+
from sysmlpy.reqif_io import ReqIFExportError, reqif_export
|
|
475
|
+
|
|
476
|
+
paths = [Path(f) for f in args.files]
|
|
477
|
+
for p in _missing_files(paths):
|
|
478
|
+
print(f"Error: File '{p}' not found.", file=sys.stderr)
|
|
479
|
+
return 2
|
|
480
|
+
|
|
481
|
+
try:
|
|
482
|
+
model = sysmlpy.load_files(paths, library=args.library)
|
|
483
|
+
except Exception as e:
|
|
484
|
+
print(f"Parse error: {e}", file=sys.stderr)
|
|
485
|
+
return 2
|
|
486
|
+
|
|
487
|
+
try:
|
|
488
|
+
reqif_export(model, args.output)
|
|
489
|
+
except ReqIFExportError as e:
|
|
490
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
491
|
+
return 1
|
|
492
|
+
except Exception as e: # noqa: BLE001 - surface unparser failures cleanly
|
|
493
|
+
print(f"Error: ReqIF export failed: {e}", file=sys.stderr)
|
|
494
|
+
return 1
|
|
495
|
+
|
|
496
|
+
print(f"Wrote {args.output}")
|
|
497
|
+
return 0
|
|
498
|
+
|
|
499
|
+
|
|
445
500
|
def _parse_eval_value(text):
|
|
446
501
|
"""Parse a --set NAME=VALUE literal (number / bool / string / unit)."""
|
|
447
502
|
from sysmlpy.usage import ureg
|
|
@@ -606,6 +661,16 @@ def cmd_sim(args) -> int:
|
|
|
606
661
|
return 0
|
|
607
662
|
|
|
608
663
|
|
|
664
|
+
def cmd_repl(args) -> int:
|
|
665
|
+
"""Interactive REPL (declarations accumulate; %commands inspect)."""
|
|
666
|
+
from sysmlpy.repl import main as repl_main
|
|
667
|
+
|
|
668
|
+
return repl_main(
|
|
669
|
+
[*(args.files or []), *(["--no-banner"] if args.no_banner else [])]
|
|
670
|
+
+ (["-l", args.library] if getattr(args, "library", None) else []),
|
|
671
|
+
)
|
|
672
|
+
|
|
673
|
+
|
|
609
674
|
def cmd_xlsx(args) -> int:
|
|
610
675
|
"""Export tabular views to an Excel workbook (v0.66.0, Goal 7)."""
|
|
611
676
|
from sysmlpy.spreadsheet import write_xlsx
|
|
@@ -922,6 +987,43 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
922
987
|
)
|
|
923
988
|
p_import.set_defaults(func=cmd_import)
|
|
924
989
|
|
|
990
|
+
# -- reqif-import / reqif-export ------------------------------------------
|
|
991
|
+
p_reqif_import = sub.add_parser(
|
|
992
|
+
"reqif-import",
|
|
993
|
+
help="Import a ReqIF file as SysML v2 requirements",
|
|
994
|
+
description="Convert a ReqIF 1.0 XML file (ReqIF Studio, DOORS, "
|
|
995
|
+
"Polarion, Eclipse RMF, ...) into SysML v2 requirement "
|
|
996
|
+
"usages, nested by the ReqIF specification hierarchy. "
|
|
997
|
+
"Exit 2 on invalid input. Requires the optional 'reqif' "
|
|
998
|
+
"package.",
|
|
999
|
+
)
|
|
1000
|
+
p_reqif_import.add_argument("file", help="ReqIF XML file")
|
|
1001
|
+
p_reqif_import.add_argument(
|
|
1002
|
+
"-o", "--output",
|
|
1003
|
+
help="Write the SysML text to a file instead of stdout",
|
|
1004
|
+
)
|
|
1005
|
+
p_reqif_import.set_defaults(func=cmd_reqif_import)
|
|
1006
|
+
|
|
1007
|
+
p_reqif_export = sub.add_parser(
|
|
1008
|
+
"reqif-export",
|
|
1009
|
+
help="Export model requirements as a ReqIF 1.0 file",
|
|
1010
|
+
description="Export the requirements of the merged model as ReqIF "
|
|
1011
|
+
"1.0 XML (one spec object per requirement, hierarchy "
|
|
1012
|
+
"from ownership, doc comments as ReqIF.Text). Exit 1 "
|
|
1013
|
+
"when the model has no requirements. Requires the "
|
|
1014
|
+
"optional 'reqif' package.",
|
|
1015
|
+
)
|
|
1016
|
+
p_reqif_export.add_argument("files", nargs="+", help="SysML v2 file(s)")
|
|
1017
|
+
p_reqif_export.add_argument(
|
|
1018
|
+
"-o", "--output", required=True,
|
|
1019
|
+
help="Destination ReqIF XML file",
|
|
1020
|
+
)
|
|
1021
|
+
p_reqif_export.add_argument(
|
|
1022
|
+
"-l", "--library",
|
|
1023
|
+
help="Path to SysML v2 library files to use for parsing",
|
|
1024
|
+
)
|
|
1025
|
+
p_reqif_export.set_defaults(func=cmd_reqif_export)
|
|
1026
|
+
|
|
925
1027
|
p_eval = sub.add_parser(
|
|
926
1028
|
"eval",
|
|
927
1029
|
help="Evaluate expressions, attribute values and constraints",
|
|
@@ -1030,6 +1132,27 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
1030
1132
|
)
|
|
1031
1133
|
p_xlsx.set_defaults(func=cmd_xlsx)
|
|
1032
1134
|
|
|
1135
|
+
# -- repl ----------------------------------------------------------------
|
|
1136
|
+
p_repl = sub.add_parser(
|
|
1137
|
+
"repl",
|
|
1138
|
+
help="Interactive SysML v2 REPL",
|
|
1139
|
+
description="Declarations accumulate into a session model; "
|
|
1140
|
+
"%commands inspect it (%eval, %sim, %view, ...). "
|
|
1141
|
+
"See %help inside the REPL for the command list.",
|
|
1142
|
+
)
|
|
1143
|
+
p_repl.add_argument("files", nargs="*", metavar="FILE",
|
|
1144
|
+
help="model file(s) to load into the session first")
|
|
1145
|
+
p_repl.add_argument(
|
|
1146
|
+
"-l", "--library",
|
|
1147
|
+
help="Path to SysML v2 library files (accepted for parity; "
|
|
1148
|
+
"submissions parse without it)",
|
|
1149
|
+
)
|
|
1150
|
+
p_repl.add_argument(
|
|
1151
|
+
"--no-banner", action="store_true",
|
|
1152
|
+
help="suppress the startup banner",
|
|
1153
|
+
)
|
|
1154
|
+
p_repl.set_defaults(func=cmd_repl)
|
|
1155
|
+
|
|
1033
1156
|
return parser
|
|
1034
1157
|
|
|
1035
1158
|
|
|
@@ -6389,6 +6389,92 @@ def _make_state_usage_dict(ctx, prefix=None):
|
|
|
6389
6389
|
}
|
|
6390
6390
|
|
|
6391
6391
|
|
|
6392
|
+
def _make_exhibit_state_usage_dict(ctx, prefix=None):
|
|
6393
|
+
"""Create a StateUsage dictionary for an ``exhibit state`` usage.
|
|
6394
|
+
|
|
6395
|
+
Grammar:
|
|
6396
|
+
exhibitStateUsage
|
|
6397
|
+
: occurrenceUsagePrefix EXHIBIT
|
|
6398
|
+
( ownedReferenceSubsetting featureSpecializationPart?
|
|
6399
|
+
| STATE usageDeclaration? ) valuePart? stateUsageBody
|
|
6400
|
+
;
|
|
6401
|
+
|
|
6402
|
+
Both spellings met in practice carry a usageDeclaration:
|
|
6403
|
+
exhibit state phases : MissionPhases; (typed reference)
|
|
6404
|
+
exhibit state modes { ... } (inline body)
|
|
6405
|
+
The dict is a StateUsage with ``exhibit: True`` so the grammar class
|
|
6406
|
+
dumps the ``exhibit`` keyword and every downstream consumer (public
|
|
6407
|
+
tree, boxes collector, sim) sees a plain StateUsage node. Previously
|
|
6408
|
+
``exhibit state`` was silently dropped by the visitor, which made
|
|
6409
|
+
part-embedded state machines invisible to sim and lossy on dump.
|
|
6410
|
+
"""
|
|
6411
|
+
if ctx is None:
|
|
6412
|
+
return None
|
|
6413
|
+
|
|
6414
|
+
occ_prefix = _get_occurrence_usage_prefix(ctx)
|
|
6415
|
+
if prefix is not None:
|
|
6416
|
+
occ_prefix = prefix
|
|
6417
|
+
|
|
6418
|
+
# Declaration: name/shortname from the usageDeclaration, typing from
|
|
6419
|
+
# its featureSpecializationPart (``: MissionPhases``).
|
|
6420
|
+
name, shortname = _get_usage_identification(ctx)
|
|
6421
|
+
specialization = _build_full_specialization_from_ctx(ctx)
|
|
6422
|
+
|
|
6423
|
+
decl_dict = None
|
|
6424
|
+
if hasattr(ctx, 'usageDeclaration') and ctx.usageDeclaration():
|
|
6425
|
+
ud = ctx.usageDeclaration()
|
|
6426
|
+
if isinstance(ud, list):
|
|
6427
|
+
ud = ud[0] if ud else None
|
|
6428
|
+
if ud is not None:
|
|
6429
|
+
decl_dict = {
|
|
6430
|
+
"name": "ActionUsageDeclaration",
|
|
6431
|
+
"declaration": {
|
|
6432
|
+
"name": "UsageDeclaration",
|
|
6433
|
+
"declaration": {
|
|
6434
|
+
"name": "FeatureDeclaration",
|
|
6435
|
+
"identification": {
|
|
6436
|
+
"name": "Identification",
|
|
6437
|
+
"declaredShortName": shortname,
|
|
6438
|
+
"declaredName": name
|
|
6439
|
+
},
|
|
6440
|
+
"specialization": specialization
|
|
6441
|
+
}
|
|
6442
|
+
},
|
|
6443
|
+
"valuepart": None
|
|
6444
|
+
}
|
|
6445
|
+
|
|
6446
|
+
# Body: a stateUsageBody, exactly like a plain stateUsage.
|
|
6447
|
+
body_dict = {"name": "StateUsageBody", "body": {"name": "StateDefBody", "part": None, "isParallel": None}}
|
|
6448
|
+
if hasattr(ctx, 'stateUsageBody') and ctx.stateUsageBody():
|
|
6449
|
+
sub = ctx.stateUsageBody()
|
|
6450
|
+
if isinstance(sub, list):
|
|
6451
|
+
sub = sub[0]
|
|
6452
|
+
if sub:
|
|
6453
|
+
body_dict = _visit_state_usage_body(sub)
|
|
6454
|
+
|
|
6455
|
+
return {
|
|
6456
|
+
"name": "PackageMember",
|
|
6457
|
+
"prefix": None,
|
|
6458
|
+
"ownedRelatedElement": {
|
|
6459
|
+
"name": "UsageElement",
|
|
6460
|
+
"ownedRelatedElement": {
|
|
6461
|
+
"name": "OccurrenceUsageElement",
|
|
6462
|
+
"ownedRelatedElement": {
|
|
6463
|
+
"name": "BehaviorUsageElement",
|
|
6464
|
+
"ownedRelationship": {
|
|
6465
|
+
"name": "StateUsage",
|
|
6466
|
+
"prefix": occ_prefix,
|
|
6467
|
+
"exhibit": True,
|
|
6468
|
+
"keyword": "state",
|
|
6469
|
+
"declaration": decl_dict,
|
|
6470
|
+
"body": body_dict
|
|
6471
|
+
}
|
|
6472
|
+
}
|
|
6473
|
+
}
|
|
6474
|
+
}
|
|
6475
|
+
}
|
|
6476
|
+
|
|
6477
|
+
|
|
6392
6478
|
def _make_calculation_usage_dict(ctx, prefix=None):
|
|
6393
6479
|
"""Create a CalculationUsage dictionary.
|
|
6394
6480
|
|
|
@@ -10650,6 +10736,16 @@ def _visit_nested_occurrence_usage(occ_elem):
|
|
|
10650
10736
|
inner = result.get("ownedRelatedElement", {})
|
|
10651
10737
|
return inner
|
|
10652
10738
|
return result
|
|
10739
|
+
elif hasattr(behav_elem, 'exhibitStateUsage') and behav_elem.exhibitStateUsage():
|
|
10740
|
+
# ``exhibit state`` usages share the BehaviorUsageElement
|
|
10741
|
+
# wrapper; previously silently dropped (part-embedded state
|
|
10742
|
+
# machines vanished from the tree, dump, boxes and sim).
|
|
10743
|
+
ctx = behav_elem.exhibitStateUsage()
|
|
10744
|
+
result = _make_exhibit_state_usage_dict(ctx, None)
|
|
10745
|
+
if result and result.get("name") == "PackageMember":
|
|
10746
|
+
inner = result.get("ownedRelatedElement", {})
|
|
10747
|
+
return inner
|
|
10748
|
+
return result
|
|
10653
10749
|
elif hasattr(behav_elem, 'allocationUsage') and behav_elem.allocationUsage():
|
|
10654
10750
|
# Phase 0: allocation usages inside a definition body.
|
|
10655
10751
|
ctx = behav_elem.allocationUsage()
|
|
@@ -13136,6 +13232,11 @@ def _visit_usage_element_dict(usage_elem_ctx, prefix=None):
|
|
|
13136
13232
|
if hasattr(behav_elem, 'stateUsage') and behav_elem.stateUsage():
|
|
13137
13233
|
ctx = behav_elem.stateUsage()
|
|
13138
13234
|
return _make_state_usage_dict(ctx, prefix)
|
|
13235
|
+
elif hasattr(behav_elem, 'exhibitStateUsage') and behav_elem.exhibitStateUsage():
|
|
13236
|
+
# ``exhibit state`` — same wrapper, StateUsage with
|
|
13237
|
+
# exhibit=True (previously dropped).
|
|
13238
|
+
ctx = behav_elem.exhibitStateUsage()
|
|
13239
|
+
return _make_exhibit_state_usage_dict(ctx, prefix)
|
|
13139
13240
|
elif hasattr(behav_elem, 'performActionUsage') and behav_elem.performActionUsage():
|
|
13140
13241
|
ctx = behav_elem.performActionUsage()
|
|
13141
13242
|
return _make_nested_perform_action_usage_dict(ctx, None)
|
|
@@ -96,6 +96,28 @@ def _sqrt(x):
|
|
|
96
96
|
return math.sqrt(x)
|
|
97
97
|
|
|
98
98
|
|
|
99
|
+
def _exp(x):
|
|
100
|
+
if isinstance(x, ureg.Quantity):
|
|
101
|
+
return math.exp(x.magnitude) * ureg.dimensionless
|
|
102
|
+
return math.exp(x)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _ln(x):
|
|
106
|
+
if isinstance(x, ureg.Quantity):
|
|
107
|
+
return math.log(x.magnitude) * ureg.dimensionless
|
|
108
|
+
return math.log(x)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _log(x, base=None):
|
|
112
|
+
if isinstance(x, ureg.Quantity):
|
|
113
|
+
x = x.magnitude
|
|
114
|
+
if base is None:
|
|
115
|
+
return math.log10(x) * ureg.dimensionless
|
|
116
|
+
if isinstance(base, ureg.Quantity):
|
|
117
|
+
base = base.magnitude
|
|
118
|
+
return math.log(x, base) * ureg.dimensionless
|
|
119
|
+
|
|
120
|
+
|
|
99
121
|
def _floor(x):
|
|
100
122
|
if isinstance(x, ureg.Quantity):
|
|
101
123
|
return math.floor(x.magnitude) * x.units
|
|
@@ -110,6 +132,11 @@ def _ceil(x):
|
|
|
110
132
|
|
|
111
133
|
_FUNCTIONS = {
|
|
112
134
|
"sqrt": _sqrt,
|
|
135
|
+
"exp": _exp,
|
|
136
|
+
"ln": _ln,
|
|
137
|
+
"log": _log,
|
|
138
|
+
"log2": lambda x: _log(x, 2.0),
|
|
139
|
+
"log10": lambda x: _log(x, 10.0),
|
|
113
140
|
"abs": abs,
|
|
114
141
|
"min": min,
|
|
115
142
|
"max": max,
|
|
@@ -1055,11 +1055,16 @@ class StateBodyItem:
|
|
|
1055
1055
|
class StateUsage:
|
|
1056
1056
|
# prefix=OccurrenceUsagePrefix StateUsageKeyword
|
|
1057
1057
|
# declaration=ActionUsageDeclaration body=StateUsageBody
|
|
1058
|
+
# An ``exhibit state`` usage is the same node with exhibit=True; the
|
|
1059
|
+
# visitor emits exhibit on the StateUsage dict (v0.93.x — previously
|
|
1060
|
+
# ``exhibit state`` was dropped by the visitor entirely).
|
|
1058
1061
|
def __init__(self, definition=None):
|
|
1059
1062
|
self.prefix = None
|
|
1060
1063
|
self.keyword = "state"
|
|
1064
|
+
self.exhibit = None
|
|
1061
1065
|
if definition is not None:
|
|
1062
1066
|
if valid_definition(definition, self.__class__.__name__):
|
|
1067
|
+
self.exhibit = definition.get("exhibit")
|
|
1063
1068
|
if definition["prefix"] is not None:
|
|
1064
1069
|
self.prefix = OccurrenceUsagePrefix(definition["prefix"])
|
|
1065
1070
|
self.declaration = ActionUsageDeclaration(definition["declaration"])
|
|
@@ -1072,13 +1077,15 @@ class StateUsage:
|
|
|
1072
1077
|
output = []
|
|
1073
1078
|
if self.prefix is not None:
|
|
1074
1079
|
output.append(self.prefix.dump())
|
|
1080
|
+
if self.exhibit:
|
|
1081
|
+
output.append("exhibit")
|
|
1075
1082
|
output.append(self.keyword)
|
|
1076
1083
|
output.append(self.declaration.dump())
|
|
1077
1084
|
output.append(self.body.dump())
|
|
1078
1085
|
return " ".join(output)
|
|
1079
1086
|
|
|
1080
1087
|
def get_definition(self):
|
|
1081
|
-
output = {"name": self.__class__.__name__, "prefix": None}
|
|
1088
|
+
output = {"name": self.__class__.__name__, "prefix": None, "exhibit": self.exhibit}
|
|
1082
1089
|
if self.prefix is not None:
|
|
1083
1090
|
output["prefix"] = self.prefix.get_definition()
|
|
1084
1091
|
output["declaration"] = self.declaration.get_definition()
|