From 4596fe50932ada33d2c671cae1d754ecb3bff5b2 Mon Sep 17 00:00:00 2001 From: Adam McKellar Date: Sun, 19 May 2024 16:50:22 +0200 Subject: [PATCH 1/5] Added main file. Added shim to main called ibi. --- installation_instruction/__main__.py | 16 ++++++++++++++++ pyproject.toml | 3 +++ 2 files changed, 19 insertions(+) create mode 100644 installation_instruction/__main__.py diff --git a/installation_instruction/__main__.py b/installation_instruction/__main__.py new file mode 100644 index 0000000..b61f2c2 --- /dev/null +++ b/installation_instruction/__main__.py @@ -0,0 +1,16 @@ +# Copyright 2024 Adam McKellar, Kanushka Gupta, Timo Ege + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +def main(): + print("hello") \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index edf19bf..fba08ac 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,6 +46,9 @@ docs = [ "sphinx-autoapi", ] +# Here you can list scripts. (Listed is a shim to the cli.) +[project.scripts] +ibi = "installation_instruction.__main__:main" # The following section contains setuptools-specific configuration # options. For a full reference of available options, check the overview From 36832554cdf4e09422416fbf53b58a1ec4b44077 Mon Sep 17 00:00:00 2001 From: Adam McKellar Date: Sun, 19 May 2024 18:09:17 +0200 Subject: [PATCH 2/5] Added that config files are read by cli. --- installation_instruction/__main__.py | 39 +++++++++++++++++++++++++++- pyproject.toml | 2 +- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/installation_instruction/__main__.py b/installation_instruction/__main__.py index b61f2c2..0df0b6c 100644 --- a/installation_instruction/__main__.py +++ b/installation_instruction/__main__.py @@ -12,5 +12,42 @@ # See the License for the specific language governing permissions and # limitations under the License. +from sys import argv, exit +from os.path import isfile + +import click + +from .get_flags_and_options_from_schema import get_flags_and_options +from .installation_instruction import InstallationInstruction + + +class ConfigReadCommand(click.MultiCommand): + def __init__(self, *args, **kwargs): + super().__init__( + *args, + **kwargs, + subcommand_metavar="CONFIG [OPTIONS]...", + options_metavar="", + ) + + def get_command(self, ctx, config_file: str) -> click.Command: + if not isfile(config_file): + print("Config file not found.") + exit(1) + + instruction = InstallationInstruction.from_file(config_file) + options = get_flags_and_options(instruction.schema) + + return click.Command( + name=config_file, + params=options, + ) + + +@click.command(cls=ConfigReadCommand) def main(): - print("hello") \ No newline at end of file + pass + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index fba08ac..904c1f5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,7 +31,7 @@ dependencies = [ "jinja2", "jsonschema", "PyYAML", - "click" + "click < 9.0.0", ] [project.optional-dependencies] From 953fb0be21d9ea1cc639523e07540a86515a7e49 Mon Sep 17 00:00:00 2001 From: Adam McKellar Date: Sun, 19 May 2024 18:21:01 +0200 Subject: [PATCH 3/5] Added callback to command. Cli shows the installation instruction now. --- installation_instruction/__main__.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/installation_instruction/__main__.py b/installation_instruction/__main__.py index 0df0b6c..ec12be3 100644 --- a/installation_instruction/__main__.py +++ b/installation_instruction/__main__.py @@ -38,9 +38,19 @@ def get_command(self, ctx, config_file: str) -> click.Command: instruction = InstallationInstruction.from_file(config_file) options = get_flags_and_options(instruction.schema) + def callback(**kwargs): + inst = instruction.validate_and_render(kwargs) + if not inst[1]: + print(inst[0]) + exit(0) + else: + print(inst[0]) + exit(1) + return click.Command( name=config_file, params=options, + callback=callback, ) From e3c8b4158e1014fca9061cc0707c5757769947cb Mon Sep 17 00:00:00 2001 From: Adam McKellar Date: Sun, 19 May 2024 19:09:19 +0200 Subject: [PATCH 4/5] Added show command. --- installation_instruction/__main__.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/installation_instruction/__main__.py b/installation_instruction/__main__.py index ec12be3..d0b8cb4 100644 --- a/installation_instruction/__main__.py +++ b/installation_instruction/__main__.py @@ -26,14 +26,14 @@ def __init__(self, *args, **kwargs): super().__init__( *args, **kwargs, - subcommand_metavar="CONFIG [OPTIONS]...", + subcommand_metavar="CONFIG_FILE [OPTIONS]...", options_metavar="", ) - def get_command(self, ctx, config_file: str) -> click.Command: + def get_command(self, ctx, config_file: str) -> click.Command|None: if not isfile(config_file): - print("Config file not found.") - exit(1) + click.echo("Config file not found.") + return None instruction = InstallationInstruction.from_file(config_file) options = get_flags_and_options(instruction.schema) @@ -54,10 +54,15 @@ def callback(**kwargs): ) -@click.command(cls=ConfigReadCommand) +@click.command(cls=ConfigReadCommand, help="Shows installation instructions for your specified config file and parameters.") +def show(): + pass + +@click.group() def main(): pass +main.add_command(show) if __name__ == "__main__": main() \ No newline at end of file From 03e2ed4260d2e1733a7fed147b836b3d8384f58d Mon Sep 17 00:00:00 2001 From: Adam McKellar Date: Sun, 19 May 2024 19:21:34 +0200 Subject: [PATCH 5/5] Added section in readme for cli usage. Added cli to changelog. --- CHANGELOG.md | 1 + README.md | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea38a2b..31c8537 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +* Added cli for rendering installation instructions for end users. * Added config section in readme. * Added examples. * Added many tests. diff --git a/README.md b/README.md index 6d645ca..b5d9b90 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,29 @@ +## CLI Usage + +``` +Usage: ibi [OPTIONS] COMMAND [ARGS]... + +Options: + --help Show this message and exit. + +Commands: + show Shows installation instructions for your specified config file... +``` + +Options are dynamically created with the schema part of the config file. + +> [!TIP] +> Show help for a config file with: `ibi show CONFIG_FILE --help`. + + ## Config The config is comprised of a single file. (Currently there is no fixed filename.) For ease of use you should use the file extension `.yml.jinja` and develope said config file as two seperate files at first. -The config file has two parts delimited by `------` (6 or more `-`). +The config file has two parts delimited by `------` (6 or more `-`). The first part is the schema (*What is valid user input?*). The second part is the template (*What is the actual command for said user input?*). The first part must be a valid [JSON Schema](https://json-schema.org/) in [JSON](https://www.json.org/json-en.html) or to JSON capabilites restricted [YAML](https://yaml.org/) and the second part must be a valid [jinja2 template](https://jinja.palletsprojects.com/en/3.0.x/templates/). The exception to this is that `anyOf` and `oneOf` are only usable for enum like behaviour on the schema side.