Skip to content

Commit

Permalink
Add and document the conversion plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
DoctorJohn committed Sep 14, 2024
1 parent 069b59e commit 2b54e6a
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 1 deletion.
7 changes: 7 additions & 0 deletions cfmtoolbox/plugins/conversion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from cfmtoolbox import CFM, app


@app.command()
def convert(cfm: CFM | None) -> CFM | None:
print("Converting CFM...")
return cfm
37 changes: 37 additions & 0 deletions docs/plugins/conversion.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
The conversion plugin adds a `convert` command to the toolbox, which can be used to convert feature models between different formats.
The supported formats depend on the installed plugins.

## Usage

To convert an XML-based FeatureIDE feature model to the UVL format, use the following command:

```bash
python3 -m cfmtoolbox --import model.xml --export model.uvl convert
```

## Example

Create a simple feature model in FeatureIDE's XML format:

```xml
cat <<EOT >> basic-sandwich.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<featureModel>
<struct>
<feature abstract="true" mandatory="true" name="Sandwich"/>
</struct>
</featureModel>
EOT
```

Convert the feature model to the UVL format:

```bash
python3 -m cfmtoolbox --import basic-sandwich.xml --export basic-sandwich.uvl convert
```

## Limitations

Currently, the toolbox determines the importer and exporter plugin to use solely based on the file extensions of the input and output files.
In case multiple formats use the same file extension, the toolbox will still only use the first plugin supporting the file extension.
This may be improved in the future.
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ nav:
- Plugins:
- Plugin Overview: plugins/index.md
- Core Plugins:
- Conversion: plugins/conversion.md
- FeatureIDE Import: plugins/featureide-import.md
- UVL Import: plugins/uvl-import.md
- UVL Export: plugins/uvl-export.md
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ mkdocs-material = "^9.5.34"
cfmtoolbox = "cfmtoolbox.__main__:__name__"

[tool.poetry.plugins."cfmtoolbox.plugins"]
conversion = "cfmtoolbox.plugins.conversion"
random-sampling = "cfmtoolbox.plugins.random_sampling"
uvl-export = "cfmtoolbox.plugins.uvl_export"
uvl-import = "cfmtoolbox.plugins.uvl_import"
Expand Down
44 changes: 44 additions & 0 deletions tests/plugins/test_conversion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import json

from typer.testing import CliRunner

from cfmtoolbox import app

runner = CliRunner()


def test_convert_command(tmp_path):
input_path = "tests/data/sandwich.uvl"
output_path = tmp_path / "sandwich.json"

result = runner.invoke(
app.typer, ["--import", input_path, "--export", str(output_path), "convert"]
)
assert result.exit_code == 0
assert result.stdout == "Converting CFM...\n"
assert output_path.exists()

output_data = json.loads(output_path.read_text())
assert isinstance(output_data, dict)
assert "root" in output_data
assert "constraints" in output_data


def test_convert_command_can_is_generally_idempotent(tmp_path):
original_path = "tests/data/sandwich.json"
output_path1 = tmp_path / "sandwich-output1.json"
output_path2 = tmp_path / "sandwich-output2.json"

result1 = runner.invoke(
app.typer, ["--import", original_path, "--export", str(output_path1), "convert"]
)
assert result1.exit_code == 0
assert output_path1.exists()

result2 = runner.invoke(
app.typer, ["--import", output_path1, "--export", str(output_path2), "convert"]
)
assert result2.exit_code == 0
assert output_path2.exists()

assert output_path1.read_text() == output_path2.read_text()
2 changes: 1 addition & 1 deletion tests/test_toolbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,4 @@ def export_uvl(cfm: CFM):
def test_load_plugins():
app = CFMToolbox()
plugins = app.load_plugins()
assert len(plugins) == 8
assert len(plugins) == 9

0 comments on commit 2b54e6a

Please sign in to comment.