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

Added CLI #10

Merged
merged 5 commits into from
May 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,29 @@

</div>

## 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.
Expand Down
68 changes: 68 additions & 0 deletions installation_instruction/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# 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.

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_FILE [OPTIONS]...",
options_metavar="",
)

def get_command(self, ctx, config_file: str) -> click.Command|None:
if not isfile(config_file):
click.echo("Config file not found.")
return None

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,
)


@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()
5 changes: 4 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ dependencies = [
"jinja2",
"jsonschema",
"PyYAML",
"click"
"click < 9.0.0",
]

[project.optional-dependencies]
Expand All @@ -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
Expand Down