diff --git a/schema/schema.py b/schema/schema.py index a2925dc2f7..96c5beff67 100644 --- a/schema/schema.py +++ b/schema/schema.py @@ -2,7 +2,9 @@ import importlib -from typing import Dict, List, Optional, Union +import json +from enum import Enum +from typing import Any, Dict import click @@ -10,7 +12,13 @@ from samcli.lib.config.samconfig import SamConfig -def format_param(param: click.core.Option) -> Dict[str, Union[Optional[str], List[str]]]: +class SchemaKeys(Enum): + SCHEMA_FILE_NAME = "samcli.json" + SCHEMA_DRAFT = "http://json-schema.org/draft-04/schema" + TITLE = "AWS SAM CLI samconfig schema" + + +def format_param(param: click.core.Option) -> Dict[str, Any]: """Format a click Option parameter to a dictionary object. A parameter object should contain the following information that will be @@ -22,20 +30,23 @@ def format_param(param: click.core.Option) -> Dict[str, Union[Optional[str], Lis a list of those allowed options * default - The default option for that parameter """ - formatted_param: Dict[str, Union[Optional[str], List[str]]] = {"name": param.name, "help": param.help} + formatted_param: Dict[str, Any] = {"title": param.name, "description": param.help} # NOTE: Params do not have explicit "string" type; either "text" or "path". # All choice options are from a set of strings. - if param.type.name in ["text", "path", "choice"]: + param_type = param.type.name.lower() + if param_type in ["text", "path", "choice", "filename", "directory"]: formatted_param["type"] = "string" + elif param_type == "list": + formatted_param["type"] = "array" else: - formatted_param["type"] = param.type.name + formatted_param["type"] = param_type or "string" if param.default: - formatted_param["default"] = str(param.default) + formatted_param["default"] = list(param.default) if isinstance(param.default, tuple) else param.default if param.type.name == "choice" and isinstance(param.type, click.Choice): - formatted_param["choices"] = list(param.type.choices) + formatted_param["enum"] = list(param.type.choices) return formatted_param @@ -91,15 +102,34 @@ def generate_schema() -> dict: schema: dict = {} commands = {} params = set() # NOTE(leogama): Currently unused due to some params having different help values - # TODO: Populate schema with relevant attributes + + # Populate schema with relevant attributes + schema["$schema"] = SchemaKeys.SCHEMA_DRAFT.value + schema["title"] = SchemaKeys.TITLE.value + schema["type"] = "object" + schema["properties"] = { + # Version number required for samconfig files to be valid + "version": {"type": "number"} + } + schema["required"] = ["version"] + schema["additionalProperties"] = False + # Iterate through packages for command and parameter information for package_name in _SAM_CLI_COMMAND_PACKAGES: new_command = retrieve_command_structure(package_name) commands.update(new_command) for param_list in new_command.values(): command_params = [param for param in param_list] params.update(command_params) + # TODO: Generate schema for each of the commands return schema +def write_schema(): + """Generate the SAM CLI JSON schema and write it to file.""" + schema = generate_schema() + with open(SchemaKeys.SCHEMA_FILE_NAME.value, "w+", encoding="utf-8") as outfile: + json.dump(schema, outfile, indent=2) + + if __name__ == "__main__": generate_schema()