Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature(cli): add command to export rules context in current environment #492

Merged
merged 9 commits into from
Apr 23, 2024
10 changes: 9 additions & 1 deletion docs/reference/qdt_profile.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Rules

> Added in version 0.34

You can add rules to make the profile deployment conditional. In the following example, the profile will be deployed only on Linux:

```json
Expand Down Expand Up @@ -35,7 +37,7 @@ You can add rules to make the profile deployment conditional. In the following e

The rules engine is based on [Python Rule Engine](https://github.com/santalvarez/python-rule-engine/) project whom rules syntax belongs to [JSON Rules Engine](https://github.com/CacheControl/json-rules-engine).

### Conditions
### Conditions and rules context

Rules is a set of conditions that use logical operators to compare values with context (a set of facts) which is exposed as a JSON object. Here comes the context for a Linux environment:

Expand All @@ -44,6 +46,12 @@ Rules is a set of conditions that use logical operators to compare values with c
:language: json
```

To help you writing rules, QDT provides a [command to export rules context](../usage/cli.md#rules-context-export):

```sh
qdt export-rules-context -o qdt_rules_context.json
```

----

## Model definition
Expand Down
2 changes: 0 additions & 2 deletions docs/usage/cli.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# Command-line interface usage

## Main command

Aliases : `qdt`, `qgis-deployment-toolbelt`, `qdeploy-toolbelt`

```{sphinx_argparse_cli}
Expand Down
17 changes: 16 additions & 1 deletion qgis_deployment_toolbelt/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@
__uri_homepage__,
__version__,
)
from qgis_deployment_toolbelt.commands import parser_main_deployment, parser_upgrade
from qgis_deployment_toolbelt.commands.cmd_rules_context import (
parser_rules_context_export,
)
from qgis_deployment_toolbelt.commands.deployment import parser_main_deployment
from qgis_deployment_toolbelt.commands.upgrade import parser_upgrade
from qgis_deployment_toolbelt.utils.journalizer import configure_logger

# #############################################################################
Expand Down Expand Up @@ -166,6 +170,17 @@ def main(in_args: list[str] = None):
add_common_arguments(subcmd_deployment)
parser_main_deployment(subcmd_deployment)

# Rules context
subcmd_rules_context = subparsers.add_parser(
"export-rules-context",
help="Export QDT rules context taking into account the local environment to "
"help rules writing.",
formatter_class=main_parser.formatter_class,
prog="rules-context-export",
)
add_common_arguments(subcmd_rules_context)
parser_rules_context_export(subcmd_rules_context)

# Upgrader
subcmd_upgrade = subparsers.add_parser(
"upgrade",
Expand Down
5 changes: 0 additions & 5 deletions qgis_deployment_toolbelt/commands/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +0,0 @@
#! python3 # noqa: E265

# submodules
from .deployment import parser_main_deployment # noqa: F401
from .upgrade import parser_upgrade # noqa: F401
91 changes: 91 additions & 0 deletions qgis_deployment_toolbelt/commands/cmd_rules_context.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#! python3 # noqa: E265


"""
Sub-command to export local rules context.

Author: Julien M. (https://github.com/guts)
"""


# ############################################################################
# ########## IMPORTS #############
# ################################

# standard library
import argparse
import logging
from pathlib import Path

# package
from qgis_deployment_toolbelt.constants import get_qdt_working_directory
from qgis_deployment_toolbelt.profiles.rules_context import QdtRulesContext
from qgis_deployment_toolbelt.utils.bouncer import exit_cli_error, exit_cli_success

# ############################################################################
# ########## GLOBALS #############
# ################################

logger = logging.getLogger(__name__)


# ############################################################################
# ########## CLI #################
# ################################


def parser_rules_context_export(
subparser: argparse.ArgumentParser,
) -> argparse.ArgumentParser:
"""Set the argument parser for subcommand.

Args:
subparser (argparse.ArgumentParser): parser to set up

Returns:
argparse.ArgumentParser: parser ready to use
"""

subparser.add_argument(
"-o",
"--output",
help="Path to the output file where to write rules context.",
default=get_qdt_working_directory().joinpath("export/qdt_rules_context.json"),
type=Path,
dest="output_path",
)

subparser.set_defaults(func=run)

return subparser


# ############################################################################
# ########## MAIN ################
# ################################


def run(args: argparse.Namespace):
"""Run the sub command logic.

Open result of a previous command.

Args:
args (argparse.Namespace): arguments passed to the subcommand
"""
logger.debug(f"Running {args.command} with {args}")

try:
context_json_path = Path(args.output_path)
context_json_path.parent.mkdir(parents=True, exist_ok=True)
rules_context = QdtRulesContext()

# write into the file passing extra parameters to json.dumps
with context_json_path.open("w", encoding="UTF8") as wf:
wf.write(rules_context.to_json(indent=4, sort_keys=True))

# exit nicely
print(f"Rules context exported in {args.output_path}")
exit_cli_success(f"Rules context exported in {args.output_path}")
except Exception as err:
exit_cli_error(err)
1 change: 0 additions & 1 deletion qgis_deployment_toolbelt/profiles/rules_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@


class QdtRulesContext:
pass

@property
def _context_date(self) -> dict:
Expand Down
17 changes: 5 additions & 12 deletions tests/test_cli_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ def test_main_run(capsys, option):
with pytest.raises(SystemExit):
cli.main(option)

out, err = capsys.readouterr()
_, err = capsys.readouterr()
assert err == ""

# checks
Expand All @@ -128,7 +128,7 @@ def test_main_run_as_admin(capsys):
]
)

out, err = capsys.readouterr()
_, err = capsys.readouterr()
assert err == ""


Expand All @@ -142,7 +142,7 @@ def test_main_run_unexising_jobs(capsys):
]
)

out, err = capsys.readouterr()
_, err = capsys.readouterr()
assert err == ""


Expand All @@ -151,7 +151,7 @@ def test_main_run_failed(capsys):
with pytest.raises(FileExistsError):
cli.main(["deploy", f"--scenario={str(sample_scenario_false.resolve())}"])

out, err = capsys.readouterr()
_, err = capsys.readouterr()
assert err == ""


Expand All @@ -169,12 +169,5 @@ def test_main_run_removing_splash(capsys):
]
)

out, err = capsys.readouterr()
_, err = capsys.readouterr()
assert err == ""


# #############################################################################
# ######## Standalone ##############
# ##################################
if __name__ == "__main__":
pass
43 changes: 43 additions & 0 deletions tests/test_cli_rules_context_export.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#! python3 # noqa: E265

"""
Test CLI's rules context export command.

Author: Julien Moura (Oslandia)
"""

# #############################################################################
# ########## Libraries #############
# ##################################


# 3rd party
import pytest

# project
from qgis_deployment_toolbelt import cli

# #############################################################################
# ######## Classes #################
# ##################################


@pytest.mark.parametrize("option", ("-h", "--help"))
def test_cli_export_rules_context_help(capsys, option):
"""Test CLI help."""
with pytest.raises(SystemExit):
cli.main(["export-rules-context", option])

_, err = capsys.readouterr()

assert err == ""


def test_cli_export_rules_context(capsys):
"""Test CLI."""
with pytest.raises(SystemExit):
cli.main(["export-rules-context"])

_, err = capsys.readouterr()

assert err == ""
4 changes: 2 additions & 2 deletions tests/test_cli_upgrade.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def test_cli_upgrade_check_only(capsys):
with pytest.raises(SystemExit):
cli.main(["upgrade", "-c"])

out, err = capsys.readouterr()
_, err = capsys.readouterr()

assert err == ""

Expand All @@ -48,7 +48,7 @@ def test_cli_upgrade_download(capsys):
with pytest.raises(SystemExit):
cli.main(["upgrade", "-n", "-w", "tests/"])

out, err = capsys.readouterr()
_, err = capsys.readouterr()

assert err == ""

Expand Down