sysmlpy 0.60.0__tar.gz → 0.62.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.60.0 → sysmlpy-0.62.0}/PKG-INFO +1 -1
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/pyproject.toml +1 -1
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/__init__.py +7 -1
- sysmlpy-0.62.0/src/sysmlpy/__main__.py +578 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/antlr_visitor.py +242 -12
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/definition.py +16 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/grammar/classes.py +85 -1
- sysmlpy-0.62.0/src/sysmlpy/traceability.py +441 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/usage.py +85 -1
- sysmlpy-0.60.0/src/sysmlpy/__main__.py +0 -97
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/LICENSE +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/README.md +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/antlr/README.md +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/antlr/SysMLv2Lexer.interp +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/antlr/SysMLv2Lexer.py +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/antlr/SysMLv2Lexer.tokens +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/antlr/SysMLv2Parser.interp +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/antlr/SysMLv2Parser.py +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/antlr/SysMLv2Parser.tokens +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/antlr/SysMLv2ParserListener.py +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/antlr/SysMLv2ParserVisitor.py +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.interp +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.py +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.tokens +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/antlr_parser.py +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/boxes_view.py +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/examples/attribute_values.py +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/examples/part_attributes.py +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/examples/tuples_sequences.py +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/formatting.py +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/grammar/antlr4/README.md +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.g4 +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.interp +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.py +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.tokens +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.g4 +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.interp +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.py +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.tokens +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/grammar/antlr4/SysMLv2ParserListener.py +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/grammar/antlr4/SysMLv2ParserVisitor.py +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/grammar/antlr4/desc.xml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/grammar/antlr4/examples/camera.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/grammar/antlr4/examples/toaster-system.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/grammar/antlr4/examples/vehicle-model.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/grammar/antlr4/pom.xml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/LICENSE +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/README.md +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/__init__.py +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Analysis/AnalysisTooling.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Analysis/SampledFunctions.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Analysis/StateSpaceRepresentation.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Analysis/TradeStudies.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Cause and Effect/CausationConnections.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Cause and Effect/CauseAndEffect.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Geometry/ShapeItems.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Geometry/SpatialItems.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Metadata/ImageMetadata.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Metadata/ModelingMetadata.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Metadata/ParametersOfInterestMetadata.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Metadata/RiskMetadata.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Quantities and Units/ISQ.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Quantities and Units/ISQAcoustics.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Quantities and Units/ISQAtomicNuclear.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Quantities and Units/ISQBase.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Quantities and Units/ISQCharacteristicNumbers.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Quantities and Units/ISQChemistryMolecular.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Quantities and Units/ISQCondensedMatter.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Quantities and Units/ISQElectromagnetism.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Quantities and Units/ISQInformation.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Quantities and Units/ISQLight.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Quantities and Units/ISQMechanics.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Quantities and Units/ISQSpaceTime.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Quantities and Units/ISQThermodynamics.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Quantities and Units/MeasurementRefCalculations.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Quantities and Units/MeasurementReferences.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Quantities and Units/Quantities.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Quantities and Units/QuantityCalculations.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Quantities and Units/SI.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Quantities and Units/SIPrefixes.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Quantities and Units/TensorCalculations.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Quantities and Units/Time.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Quantities and Units/USCustomaryUnits.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Quantities and Units/VectorCalculations.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Requirement Derivation/DerivationConnections.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/domain/Requirement Derivation/RequirementDerivation.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/Base.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/BaseFunctions.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/BooleanFunctions.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/Clocks.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/CollectionFunctions.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/Collections.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/ComplexFunctions.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/ControlFunctions.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/ControlPerformances.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/DataFunctions.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/FeatureReferencingPerformances.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/IntegerFunctions.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/KerML.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/Links.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/Metaobjects.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/NaturalFunctions.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/NumericalFunctions.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/Objects.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/Observation.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/OccurrenceFunctions.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/Occurrences.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/Performances.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/RationalFunctions.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/RealFunctions.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/ScalarFunctions.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/ScalarValues.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/SequenceFunctions.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/SpatialFrames.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/StatePerformances.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/StringFunctions.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/Transfers.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/TransitionPerformances.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/TrigFunctions.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/Triggers.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/VectorFunctions.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/kernel/VectorValues.kerml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/systems/Actions.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/systems/Allocations.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/systems/AnalysisCases.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/systems/Attributes.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/systems/Calculations.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/systems/Cases.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/systems/Connections.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/systems/Constraints.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/systems/Flows.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/systems/Interfaces.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/systems/Items.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/systems/Metadata.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/systems/Parts.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/systems/Ports.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/systems/Requirements.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/systems/StandardViewDefinitions.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/systems/States.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/systems/SysML.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/systems/UseCases.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/systems/VerificationCases.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/library/systems/Views.sysml +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/navigate.py +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/plantuml.py +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/project.py +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/semantic.py +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/store.py +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/us_customary_units.txt +0 -0
- {sysmlpy-0.60.0 → sysmlpy-0.62.0}/src/sysmlpy/validator.py +0 -0
|
@@ -16,7 +16,9 @@ __all__ = [
|
|
|
16
16
|
"as_action_flow_view", "as_interconnection_view", "as_state_transition_view",
|
|
17
17
|
"as_general_view", "as_package_view",
|
|
18
18
|
"as_tabular_view", "as_data_value_tabular_view", "as_relationship_matrix_view",
|
|
19
|
+
"as_traceability_matrix_view",
|
|
19
20
|
"as_sequence_view", "as_case_view", "as_browser_view",
|
|
21
|
+
"extract_traceability", "TraceabilityReport", "RequirementTrace",
|
|
20
22
|
"analyze", "AnalysisResult", "SemanticIssue", "SemanticAnalyzer",
|
|
21
23
|
"SysMLSyntaxError", "PartialParseError",
|
|
22
24
|
"loads_partial", "load_partial",
|
|
@@ -25,7 +27,7 @@ __all__ = [
|
|
|
25
27
|
"render_state_transition_view_svg", "boxes_view",
|
|
26
28
|
]
|
|
27
29
|
__author__ = "Jon Fox"
|
|
28
|
-
__version__ = "0.
|
|
30
|
+
__version__ = "0.62.0"
|
|
29
31
|
|
|
30
32
|
from sysmlpy.usage import (
|
|
31
33
|
Item, Attribute, Part, Port, Action, Reference, UseCase, Requirement, Interface, Message,
|
|
@@ -41,6 +43,10 @@ from sysmlpy.store import Store, InMemoryStore, NetworkXStore, KuzuStore, Cayley
|
|
|
41
43
|
|
|
42
44
|
from sysmlpy.usage import ureg
|
|
43
45
|
from sysmlpy.antlr_parser import SysMLSyntaxError
|
|
46
|
+
from sysmlpy.traceability import (
|
|
47
|
+
extract_traceability, TraceabilityReport, RequirementTrace,
|
|
48
|
+
as_traceability_matrix_view,
|
|
49
|
+
)
|
|
44
50
|
|
|
45
51
|
|
|
46
52
|
class PartialParseError(Exception):
|
|
@@ -0,0 +1,578 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Command line interface for sysmlpy.
|
|
4
|
+
|
|
5
|
+
Subcommands
|
|
6
|
+
-----------
|
|
7
|
+
parse Parse a SysML file and print a representation (default: repr()).
|
|
8
|
+
analyze Run semantic analysis on one or more files; CI-friendly exit codes.
|
|
9
|
+
view Render a PlantUML / Markdown / HTML view of a model.
|
|
10
|
+
format Canonicalize (pretty-print) SysML files (alias: fmt).
|
|
11
|
+
|
|
12
|
+
Exit codes
|
|
13
|
+
----------
|
|
14
|
+
0 success (for analyze: no issues at the --fail-on threshold)
|
|
15
|
+
1 findings at or above the failure threshold (analyze) or an
|
|
16
|
+
operational error such as an unknown focus element (view) /
|
|
17
|
+
unformatted file (format --check)
|
|
18
|
+
2 parse or load failure, or usage error
|
|
19
|
+
|
|
20
|
+
Legacy flat invocation (``sysmlpy FILE --dump`` etc.) is preserved for
|
|
21
|
+
backward compatibility and behaves exactly like ``sysmlpy parse``.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
import argparse
|
|
25
|
+
import inspect
|
|
26
|
+
import json
|
|
27
|
+
import sys
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
|
|
30
|
+
import sysmlpy
|
|
31
|
+
from sysmlpy import loads
|
|
32
|
+
|
|
33
|
+
# Subcommand table, also used to detect the legacy flat invocation form.
|
|
34
|
+
SUBCOMMANDS = ("parse", "analyze", "view", "trace", "format", "fmt")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# ---------------------------------------------------------------------------
|
|
38
|
+
# shared helpers
|
|
39
|
+
# ---------------------------------------------------------------------------
|
|
40
|
+
|
|
41
|
+
def _read_file(path: Path) -> str:
|
|
42
|
+
try:
|
|
43
|
+
return path.read_text(encoding="utf-8")
|
|
44
|
+
except OSError as e:
|
|
45
|
+
print(f"Error reading file: {e}", file=sys.stderr)
|
|
46
|
+
sys.exit(2)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _missing_files(paths: list[Path]) -> list[Path]:
|
|
50
|
+
return [p for p in paths if not p.exists()]
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _load_model(files: list[Path], library: str | None):
|
|
54
|
+
"""Load one or more SysML files into a single Model.
|
|
55
|
+
|
|
56
|
+
Returns ``(model, error_message)``; ``error_message`` is None on
|
|
57
|
+
success. Uses :func:`sysmlpy.load_files` so multi-file projects are
|
|
58
|
+
merged (same-named packages share a namespace).
|
|
59
|
+
"""
|
|
60
|
+
from sysmlpy import load_files
|
|
61
|
+
|
|
62
|
+
paths = [str(f) for f in files]
|
|
63
|
+
try:
|
|
64
|
+
model = sysmlpy.load_files(paths, library=library)
|
|
65
|
+
return model, None
|
|
66
|
+
except Exception as e: # SysMLSyntaxError and any parse-time failure
|
|
67
|
+
return None, str(e)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
# ---------------------------------------------------------------------------
|
|
71
|
+
# sysmlpy parse
|
|
72
|
+
# ---------------------------------------------------------------------------
|
|
73
|
+
|
|
74
|
+
def cmd_parse(args) -> int:
|
|
75
|
+
file_path = Path(args.file)
|
|
76
|
+
missing = _missing_files([file_path])
|
|
77
|
+
if missing:
|
|
78
|
+
print(f"Error: File '{missing[0]}' not found.", file=sys.stderr)
|
|
79
|
+
return 2
|
|
80
|
+
content = file_path.read_text(encoding="utf-8")
|
|
81
|
+
|
|
82
|
+
try:
|
|
83
|
+
model = sysmlpy.loads(content, library=args.library)
|
|
84
|
+
except Exception as e:
|
|
85
|
+
print(f"Error parsing SysML file: {e}", file=sys.stderr)
|
|
86
|
+
return 2
|
|
87
|
+
|
|
88
|
+
if args.json:
|
|
89
|
+
from sysmlpy import load_grammar
|
|
90
|
+
grammar_dict = sysmlpy.load_grammar(content)
|
|
91
|
+
print(json.dumps(grammar_dict, indent=2))
|
|
92
|
+
elif args.dump:
|
|
93
|
+
print(model.dump())
|
|
94
|
+
else:
|
|
95
|
+
# Default or --python flag: show repr()
|
|
96
|
+
print(repr(model))
|
|
97
|
+
return 0
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
# ---------------------------------------------------------------------------
|
|
101
|
+
# sysmlpy analyze
|
|
102
|
+
# ---------------------------------------------------------------------------
|
|
103
|
+
|
|
104
|
+
def cmd_analyze(args) -> int:
|
|
105
|
+
from sysmlpy import analyze
|
|
106
|
+
|
|
107
|
+
paths = [Path(f) for f in args.files]
|
|
108
|
+
for p in _missing_files(paths):
|
|
109
|
+
print(f"Error: File '{p}' not found.", file=sys.stderr)
|
|
110
|
+
return 2
|
|
111
|
+
|
|
112
|
+
model, error = _load_model(paths, args.library)
|
|
113
|
+
if model is None:
|
|
114
|
+
print(f"Parse error: {error}", file=sys.stderr)
|
|
115
|
+
return 2
|
|
116
|
+
|
|
117
|
+
result = analyze(model)
|
|
118
|
+
errors = [i for i in result if i.severity == "error"]
|
|
119
|
+
warnings = [i for i in result if i.severity == "warning"]
|
|
120
|
+
|
|
121
|
+
if args.format == "json":
|
|
122
|
+
print(json.dumps({
|
|
123
|
+
"files": [str(p) for p in paths],
|
|
124
|
+
"issues": [
|
|
125
|
+
{
|
|
126
|
+
"severity": i.severity,
|
|
127
|
+
"code": i.code,
|
|
128
|
+
"message": i.message,
|
|
129
|
+
"reference": i.reference,
|
|
130
|
+
}
|
|
131
|
+
for i in result
|
|
132
|
+
],
|
|
133
|
+
"summary": {"errors": len(errors), "warnings": len(warnings)},
|
|
134
|
+
}, indent=2))
|
|
135
|
+
else:
|
|
136
|
+
shown = list(result)
|
|
137
|
+
if args.no_warnings:
|
|
138
|
+
shown = [i for i in shown if i.severity != "warning"]
|
|
139
|
+
for issue in shown:
|
|
140
|
+
prefix = "error" if issue.severity == "error" else "warning"
|
|
141
|
+
ref = f" [ref: {issue.reference}]" if issue.reference else ""
|
|
142
|
+
print(f"{prefix}: {issue.code}: {issue.message}{ref}")
|
|
143
|
+
if not args.no_summary and shown:
|
|
144
|
+
print(
|
|
145
|
+
f"\n{len(errors)} error(s), {len(warnings)} warning(s) "
|
|
146
|
+
f"in {', '.join(str(p) for p in paths)}"
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
if args.fail_on == "never":
|
|
150
|
+
return 0
|
|
151
|
+
threshold = "error" if args.fail_on == "error" else "warning"
|
|
152
|
+
if threshold == "warning":
|
|
153
|
+
return 1 if (errors or warnings) else 0
|
|
154
|
+
return 1 if errors else 0
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
# ---------------------------------------------------------------------------
|
|
158
|
+
# sysmlpy view
|
|
159
|
+
# ---------------------------------------------------------------------------
|
|
160
|
+
|
|
161
|
+
# view short name -> (view function, supports output_format)
|
|
162
|
+
VIEW_TABLE = {
|
|
163
|
+
"gv": "as_general_view", # General View
|
|
164
|
+
"pv": "as_package_view", # Package View
|
|
165
|
+
"afv": "as_action_flow_view", # ActionFlowView
|
|
166
|
+
"iv": "as_interconnection_view", # InterconnectionView
|
|
167
|
+
"stv": "as_state_transition_view", # StateTransitionView
|
|
168
|
+
"sv": "as_sequence_view", # Sequence View
|
|
169
|
+
"cv": "as_case_view", # Case View
|
|
170
|
+
"tabular": "as_tabular_view", # GridView (Tabular)
|
|
171
|
+
"datavalue": "as_data_value_tabular_view", # Data Value Tabular
|
|
172
|
+
"matrix": "as_relationship_matrix_view", # Relationship Matrix
|
|
173
|
+
"browser": "as_browser_view", # Browser (tree) view
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def cmd_view(args) -> int:
|
|
178
|
+
func_name = VIEW_TABLE[args.view]
|
|
179
|
+
view_func = getattr(sysmlpy, func_name)
|
|
180
|
+
|
|
181
|
+
file_path = Path(args.file)
|
|
182
|
+
missing = _missing_files([file_path])
|
|
183
|
+
if missing:
|
|
184
|
+
print(f"Error: File '{missing[0]}' not found.", file=sys.stderr)
|
|
185
|
+
return 2
|
|
186
|
+
content = file_path.read_text(encoding="utf-8")
|
|
187
|
+
|
|
188
|
+
try:
|
|
189
|
+
model = sysmlpy.loads(content, library=args.library)
|
|
190
|
+
except Exception as e:
|
|
191
|
+
print(f"Parse error: {e}", file=sys.stderr)
|
|
192
|
+
return 2
|
|
193
|
+
|
|
194
|
+
# Focus must name an existing element, so a typo fails loudly instead
|
|
195
|
+
# of silently rendering the whole model.
|
|
196
|
+
if args.focus is not None:
|
|
197
|
+
try:
|
|
198
|
+
found = model.find_one(args.focus)
|
|
199
|
+
except LookupError as e:
|
|
200
|
+
print(f"Error: --focus '{args.focus}': {e}", file=sys.stderr)
|
|
201
|
+
return 1
|
|
202
|
+
if found is None:
|
|
203
|
+
print(
|
|
204
|
+
f"Error: --focus '{args.focus}': no element with that name",
|
|
205
|
+
file=sys.stderr,
|
|
206
|
+
)
|
|
207
|
+
return 1
|
|
208
|
+
|
|
209
|
+
# Only pass keyword arguments the view function actually accepts.
|
|
210
|
+
kwargs = {}
|
|
211
|
+
sig = inspect.signature(view_func)
|
|
212
|
+
if "focus" in sig.parameters and args.focus is not None:
|
|
213
|
+
kwargs["focus"] = args.focus
|
|
214
|
+
if "elements" in sig.parameters and args.elements:
|
|
215
|
+
kwargs["elements"] = args.elements
|
|
216
|
+
if "style" in sig.parameters:
|
|
217
|
+
kwargs["style"] = args.style
|
|
218
|
+
if "direction" in sig.parameters and args.direction:
|
|
219
|
+
kwargs["direction"] = args.direction
|
|
220
|
+
if "output_format" in sig.parameters and args.format:
|
|
221
|
+
kwargs["output_format"] = args.format
|
|
222
|
+
|
|
223
|
+
try:
|
|
224
|
+
output = view_func(model, **kwargs)
|
|
225
|
+
except LookupError as e:
|
|
226
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
227
|
+
return 1
|
|
228
|
+
except Exception as e:
|
|
229
|
+
print(
|
|
230
|
+
f"Error: view '{args.view}' failed on this model: "
|
|
231
|
+
f"{type(e).__name__}: {e}",
|
|
232
|
+
file=sys.stderr,
|
|
233
|
+
)
|
|
234
|
+
return 1
|
|
235
|
+
|
|
236
|
+
if args.output:
|
|
237
|
+
Path(args.output).write_text(str(output), encoding="utf-8")
|
|
238
|
+
print(f"Wrote {args.output}")
|
|
239
|
+
else:
|
|
240
|
+
print(output)
|
|
241
|
+
return 0
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
# ---------------------------------------------------------------------------
|
|
245
|
+
# sysmlpy format
|
|
246
|
+
# ---------------------------------------------------------------------------
|
|
247
|
+
|
|
248
|
+
def cmd_format(args) -> int:
|
|
249
|
+
paths = [Path(f) for f in args.files]
|
|
250
|
+
missing = _missing_files(paths)
|
|
251
|
+
if missing:
|
|
252
|
+
for p in missing:
|
|
253
|
+
print(f"Error: File '{p}' not found.", file=sys.stderr)
|
|
254
|
+
return 2
|
|
255
|
+
|
|
256
|
+
exit_code = 0
|
|
257
|
+
for file_path in paths:
|
|
258
|
+
content = file_path.read_text(encoding="utf-8")
|
|
259
|
+
try:
|
|
260
|
+
model = sysmlpy.loads(content, library=args.library)
|
|
261
|
+
except Exception as e:
|
|
262
|
+
print(f"Error parsing SysML file '{file_path}': {e}", file=sys.stderr)
|
|
263
|
+
exit_code = 2
|
|
264
|
+
continue
|
|
265
|
+
|
|
266
|
+
formatted = model.dump()
|
|
267
|
+
if args.check:
|
|
268
|
+
if formatted != content:
|
|
269
|
+
print(f"{file_path} would be reformatted")
|
|
270
|
+
exit_code = 1
|
|
271
|
+
elif args.in_place:
|
|
272
|
+
if formatted != content:
|
|
273
|
+
file_path.write_text(formatted, encoding="utf-8")
|
|
274
|
+
print(f"Formatted {file_path}")
|
|
275
|
+
else:
|
|
276
|
+
print(formatted)
|
|
277
|
+
return exit_code
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def cmd_trace(args) -> int:
|
|
281
|
+
"""Requirement traceability & verification coverage (v0.62.0, Goal 2)."""
|
|
282
|
+
from sysmlpy.traceability import extract_traceability
|
|
283
|
+
|
|
284
|
+
paths = [Path(f) for f in args.files]
|
|
285
|
+
for p in _missing_files(paths):
|
|
286
|
+
print(f"Error: File '{p}' not found.", file=sys.stderr)
|
|
287
|
+
return 2
|
|
288
|
+
|
|
289
|
+
try:
|
|
290
|
+
model = sysmlpy.load_files(paths, library=args.library)
|
|
291
|
+
except Exception as e:
|
|
292
|
+
print(f"Parse error: {e}", file=sys.stderr)
|
|
293
|
+
return 2
|
|
294
|
+
|
|
295
|
+
report = extract_traceability(model)
|
|
296
|
+
|
|
297
|
+
if args.format == "json":
|
|
298
|
+
output = json.dumps(report.to_json(), indent=2)
|
|
299
|
+
elif args.format == "markdown":
|
|
300
|
+
output = report.to_markdown()
|
|
301
|
+
else:
|
|
302
|
+
output = report.to_text()
|
|
303
|
+
|
|
304
|
+
if args.output:
|
|
305
|
+
Path(args.output).write_text(output + "\n", encoding="utf-8")
|
|
306
|
+
print(f"Wrote {args.output}")
|
|
307
|
+
else:
|
|
308
|
+
print(output)
|
|
309
|
+
|
|
310
|
+
if args.fail_on == "uncovered" and report.uncovered():
|
|
311
|
+
for trace in report.uncovered():
|
|
312
|
+
print(
|
|
313
|
+
f"uncovered: {trace.qualified_name or trace.name}",
|
|
314
|
+
file=sys.stderr,
|
|
315
|
+
)
|
|
316
|
+
return 1
|
|
317
|
+
return 0
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
# ---------------------------------------------------------------------------
|
|
321
|
+
# legacy flat invocation (kept for backward compatibility)
|
|
322
|
+
# ---------------------------------------------------------------------------
|
|
323
|
+
|
|
324
|
+
def _legacy_main(args) -> int:
|
|
325
|
+
"""Legacy flat behavior, with its original exit codes (1 on errors).
|
|
326
|
+
|
|
327
|
+
Returns the exit code instead of calling sys.exit so in-process
|
|
328
|
+
callers can inspect it; the console script wrapper applies it.
|
|
329
|
+
"""
|
|
330
|
+
file_path = Path(args.file)
|
|
331
|
+
if not file_path.exists():
|
|
332
|
+
print(f"Error: File '{args.file}' not found.", file=sys.stderr)
|
|
333
|
+
return 1
|
|
334
|
+
|
|
335
|
+
try:
|
|
336
|
+
content = file_path.read_text(encoding="utf-8")
|
|
337
|
+
except OSError as e:
|
|
338
|
+
print(f"Error reading file: {e}", file=sys.stderr)
|
|
339
|
+
return 1
|
|
340
|
+
|
|
341
|
+
try:
|
|
342
|
+
model = sysmlpy.loads(content, library=args.library)
|
|
343
|
+
except Exception as e:
|
|
344
|
+
print(f"Error parsing SysML file: {e}", file=sys.stderr)
|
|
345
|
+
return 1
|
|
346
|
+
|
|
347
|
+
if args.json:
|
|
348
|
+
grammar_dict = sysmlpy.load_grammar(content)
|
|
349
|
+
print(json.dumps(grammar_dict, indent=2))
|
|
350
|
+
return 0
|
|
351
|
+
|
|
352
|
+
if args.dump or args.in_place or args.check:
|
|
353
|
+
formatted = model.dump()
|
|
354
|
+
if args.check:
|
|
355
|
+
return 0 if formatted == content else 1
|
|
356
|
+
if args.in_place:
|
|
357
|
+
file_path.write_text(formatted, encoding="utf-8")
|
|
358
|
+
print(f"Formatted {file_path}")
|
|
359
|
+
return 0
|
|
360
|
+
print(formatted)
|
|
361
|
+
return 0
|
|
362
|
+
|
|
363
|
+
# Default or --python flag: show repr()
|
|
364
|
+
print(repr(model))
|
|
365
|
+
return 0
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
# ---------------------------------------------------------------------------
|
|
369
|
+
# argument parser assembly
|
|
370
|
+
# ---------------------------------------------------------------------------
|
|
371
|
+
|
|
372
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
373
|
+
parser = argparse.ArgumentParser(
|
|
374
|
+
prog="sysmlpy",
|
|
375
|
+
description=(
|
|
376
|
+
"Parse, analyze, and render SysML v2 models.\n\n"
|
|
377
|
+
"Exit codes: 0 = success / clean, 1 = findings at or above the\n"
|
|
378
|
+
"failure threshold (analyze) or an operational error, 2 = parse\n"
|
|
379
|
+
"or load failure."
|
|
380
|
+
),
|
|
381
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
382
|
+
)
|
|
383
|
+
parser.add_argument(
|
|
384
|
+
"--version", action="version", version=f"sysmlpy {sysmlpy.__version__}"
|
|
385
|
+
)
|
|
386
|
+
sub = parser.add_subparsers(dest="command")
|
|
387
|
+
|
|
388
|
+
# -- parse ---------------------------------------------------------------
|
|
389
|
+
p_parse = sub.add_parser(
|
|
390
|
+
"parse",
|
|
391
|
+
help="Parse a SysML file and print a representation",
|
|
392
|
+
description="Parse a SysML v2 file and display its Python "
|
|
393
|
+
"representation (default), dumped SysML text (--dump) "
|
|
394
|
+
"or grammar JSON (--json).",
|
|
395
|
+
)
|
|
396
|
+
p_parse.add_argument("file", help="Path to the SysML v2 file to parse")
|
|
397
|
+
p_parse.add_argument(
|
|
398
|
+
"--python", action="store_true",
|
|
399
|
+
help="Display the Python repr() representation (default)",
|
|
400
|
+
)
|
|
401
|
+
p_parse.add_argument(
|
|
402
|
+
"--dump", action="store_true",
|
|
403
|
+
help="Display the SysML text output (dump format)",
|
|
404
|
+
)
|
|
405
|
+
p_parse.add_argument(
|
|
406
|
+
"--json", action="store_true",
|
|
407
|
+
help="Display the grammar dictionary/JSON representation",
|
|
408
|
+
)
|
|
409
|
+
p_parse.add_argument(
|
|
410
|
+
"-l", "--library",
|
|
411
|
+
help="Path to SysML v2 library files to use for parsing",
|
|
412
|
+
)
|
|
413
|
+
p_parse.set_defaults(func=cmd_parse)
|
|
414
|
+
|
|
415
|
+
# -- analyze -------------------------------------------------------------
|
|
416
|
+
p_analyze = sub.add_parser(
|
|
417
|
+
"analyze",
|
|
418
|
+
help="Run semantic analysis; CI-friendly with exit codes",
|
|
419
|
+
description="Load one or more SysML v2 files (merged into a single "
|
|
420
|
+
"model) and run the semantic analyzer. Exit 0 when "
|
|
421
|
+
"clean, 1 when issues at or above --fail-on are found, "
|
|
422
|
+
"2 on parse/load failure.",
|
|
423
|
+
)
|
|
424
|
+
p_analyze.add_argument(
|
|
425
|
+
"files", nargs="+", help="SysML v2 file(s) to analyze"
|
|
426
|
+
)
|
|
427
|
+
p_analyze.add_argument(
|
|
428
|
+
"-l", "--library",
|
|
429
|
+
help="Path to SysML v2 library files to use for parsing",
|
|
430
|
+
)
|
|
431
|
+
p_analyze.add_argument(
|
|
432
|
+
"--format", choices=("text", "json"), default="text",
|
|
433
|
+
help="Output format: human-readable text (default) or JSON",
|
|
434
|
+
)
|
|
435
|
+
p_analyze.add_argument(
|
|
436
|
+
"--fail-on", choices=("error", "warning", "never"), default="error",
|
|
437
|
+
help="Issue severity that causes exit code 1 (default: error)",
|
|
438
|
+
)
|
|
439
|
+
p_analyze.add_argument(
|
|
440
|
+
"--no-warnings", action="store_true",
|
|
441
|
+
help="Suppress warning lines in text output",
|
|
442
|
+
)
|
|
443
|
+
p_analyze.add_argument(
|
|
444
|
+
"--no-summary", action="store_true",
|
|
445
|
+
help="Suppress the trailing error/warning count",
|
|
446
|
+
)
|
|
447
|
+
p_analyze.set_defaults(func=cmd_analyze)
|
|
448
|
+
|
|
449
|
+
# -- view ----------------------------------------------------------------
|
|
450
|
+
p_view = sub.add_parser(
|
|
451
|
+
"view",
|
|
452
|
+
help="Render a PlantUML / Markdown / HTML view of a model",
|
|
453
|
+
description="Render one of the sysmlpy views for a SysML file and "
|
|
454
|
+
"print it (or write it with -o). Graph views (gv, pv, "
|
|
455
|
+
"afv, iv, stv, sv, cv, browser) emit PlantUML; "
|
|
456
|
+
"tabular/datavalue/matrix support --format.",
|
|
457
|
+
)
|
|
458
|
+
p_view.add_argument("file", help="SysML v2 file to render")
|
|
459
|
+
p_view.add_argument(
|
|
460
|
+
"--view", required=True, choices=tuple(VIEW_TABLE),
|
|
461
|
+
help="View short name: " + ", ".join(sorted(VIEW_TABLE)),
|
|
462
|
+
)
|
|
463
|
+
p_view.add_argument(
|
|
464
|
+
"-o", "--output",
|
|
465
|
+
help="Write the view to this file instead of stdout",
|
|
466
|
+
)
|
|
467
|
+
p_view.add_argument(
|
|
468
|
+
"--focus",
|
|
469
|
+
help="Element name to focus the view on (renders its subtree)",
|
|
470
|
+
)
|
|
471
|
+
p_view.add_argument(
|
|
472
|
+
"--element", action="append", dest="elements",
|
|
473
|
+
help="Specific element(s) to include (repeatable)",
|
|
474
|
+
)
|
|
475
|
+
p_view.add_argument(
|
|
476
|
+
"--style", choices=("bw", "color"), default="bw",
|
|
477
|
+
help="Diagram style (default: bw)",
|
|
478
|
+
)
|
|
479
|
+
p_view.add_argument(
|
|
480
|
+
"--direction", choices=("TB", "LR"),
|
|
481
|
+
help="Graph direction (graph views only)",
|
|
482
|
+
)
|
|
483
|
+
p_view.add_argument(
|
|
484
|
+
"--format", choices=("plantuml", "markdown", "html"),
|
|
485
|
+
help="Output format for tabular/datavalue/matrix views",
|
|
486
|
+
)
|
|
487
|
+
p_view.add_argument(
|
|
488
|
+
"-l", "--library",
|
|
489
|
+
help="Path to SysML v2 library files to use for parsing",
|
|
490
|
+
)
|
|
491
|
+
p_view.set_defaults(func=cmd_view)
|
|
492
|
+
|
|
493
|
+
# -- format --------------------------------------------------------------
|
|
494
|
+
p_format = sub.add_parser(
|
|
495
|
+
"format",
|
|
496
|
+
aliases=("fmt",),
|
|
497
|
+
help="Pretty-print (canonicalize) SysML files",
|
|
498
|
+
description="Parse each file and print the canonical dumped text "
|
|
499
|
+
"to stdout, write it back in place (-i), or verify "
|
|
500
|
+
"formatting (--check).",
|
|
501
|
+
)
|
|
502
|
+
p_format.add_argument("files", nargs="+", help="SysML v2 file(s)")
|
|
503
|
+
p_format.add_argument(
|
|
504
|
+
"-i", "--in-place", action="store_true",
|
|
505
|
+
help="Rewrite the files with formatted output",
|
|
506
|
+
)
|
|
507
|
+
p_format.add_argument(
|
|
508
|
+
"--check", action="store_true",
|
|
509
|
+
help="Check formatting; exit 1 if a file would be reformatted",
|
|
510
|
+
)
|
|
511
|
+
p_format.add_argument(
|
|
512
|
+
"-l", "--library",
|
|
513
|
+
help="Path to SysML v2 library files to use for parsing",
|
|
514
|
+
)
|
|
515
|
+
p_format.set_defaults(func=cmd_format)
|
|
516
|
+
|
|
517
|
+
p_trace = sub.add_parser(
|
|
518
|
+
"trace",
|
|
519
|
+
help="Requirement traceability \u0026 verification coverage report",
|
|
520
|
+
description="Load the files as one merged model, extract satisfy "
|
|
521
|
+
"and verify relationships, and report requirement "
|
|
522
|
+
"coverage. Exit codes: 0 clean, 1 uncovered "
|
|
523
|
+
"requirements (--fail-on uncovered), 2 parse error.",
|
|
524
|
+
)
|
|
525
|
+
p_trace.add_argument("files", nargs="+", help="SysML v2 file(s)")
|
|
526
|
+
p_trace.add_argument(
|
|
527
|
+
"--format", choices=("text", "markdown", "json"), default="text",
|
|
528
|
+
help="Report format (default: text)",
|
|
529
|
+
)
|
|
530
|
+
p_trace.add_argument(
|
|
531
|
+
"--fail-on", choices=("uncovered", "none"), default="none",
|
|
532
|
+
help="Exit 1 when uncovered requirements exist (default: none)",
|
|
533
|
+
)
|
|
534
|
+
p_trace.add_argument(
|
|
535
|
+
"-o", "--output",
|
|
536
|
+
help="Write the report to a file instead of stdout",
|
|
537
|
+
)
|
|
538
|
+
p_trace.add_argument(
|
|
539
|
+
"-l", "--library",
|
|
540
|
+
help="Path to SysML v2 library files to use for parsing",
|
|
541
|
+
)
|
|
542
|
+
p_trace.set_defaults(func=cmd_trace)
|
|
543
|
+
|
|
544
|
+
return parser
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
def main(argv=None):
|
|
548
|
+
argv = list(sys.argv[1:] if argv is None else argv)
|
|
549
|
+
|
|
550
|
+
if not argv or argv[0] in ("-h", "--help"):
|
|
551
|
+
parser = build_parser()
|
|
552
|
+
parser.print_help()
|
|
553
|
+
return 0 if argv else 2
|
|
554
|
+
|
|
555
|
+
if argv[0] in SUBCOMMANDS or argv[0] == "--version":
|
|
556
|
+
parser = build_parser()
|
|
557
|
+
args = parser.parse_args(argv)
|
|
558
|
+
return args.func(args)
|
|
559
|
+
|
|
560
|
+
# Legacy flat form: ``sysmlpy FILE [--dump|--json|-i|--check]`` (also
|
|
561
|
+
# preserves flag-first orders like ``--dump FILE``).
|
|
562
|
+
legacy_parser = argparse.ArgumentParser(
|
|
563
|
+
prog="sysmlpy",
|
|
564
|
+
description="Parse a SysML v2 file and display its representation "
|
|
565
|
+
"(legacy form of 'sysmlpy parse').",
|
|
566
|
+
)
|
|
567
|
+
legacy_parser.add_argument("file", help="Path to the SysML v2 file")
|
|
568
|
+
legacy_parser.add_argument("--python", action="store_true")
|
|
569
|
+
legacy_parser.add_argument("-l", "--library")
|
|
570
|
+
legacy_parser.add_argument("--dump", action="store_true")
|
|
571
|
+
legacy_parser.add_argument("--json", action="store_true")
|
|
572
|
+
legacy_parser.add_argument("-i", "--in-place", action="store_true")
|
|
573
|
+
legacy_parser.add_argument("--check", action="store_true")
|
|
574
|
+
return _legacy_main(legacy_parser.parse_args(argv))
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
if __name__ == "__main__":
|
|
578
|
+
sys.exit(main())
|