From 29ba8b7845b10b28dced4d29cf521a833d580449 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Thu, 9 Jan 2025 03:16:29 +0100 Subject: [PATCH] =?UTF-8?q?Add=20a=20data/gdal=5Falgorithm.schema.json=20t?= =?UTF-8?q?o=20validate=20'gdal=20[command]=C2=A0[subcommand]=20--json-usa?= =?UTF-8?q?ge'=20output?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/alpine/build.sh | 9 ++ apps/CMakeLists.txt | 1 + apps/data/gdal_algorithm.schema.json | 198 +++++++++++++++++++++++++++ 3 files changed, 208 insertions(+) create mode 100644 apps/data/gdal_algorithm.schema.json diff --git a/.github/workflows/alpine/build.sh b/.github/workflows/alpine/build.sh index d20df60990d7..dc96272b428f 100755 --- a/.github/workflows/alpine/build.sh +++ b/.github/workflows/alpine/build.sh @@ -39,3 +39,12 @@ else echo "DeclareDeferredFOO() has NOT been run" exit 1 fi + +# +echo "Validating gdal --json-usage output" +apps/gdal --json-usage > out.json +export PYTHON_CMD=python3 +$PYTHON_CMD -m venv myvenv +source myvenv/bin/activate +$PYTHON_CMD -m pip install -U check-jsonschema +check-jsonschema --schemafile data/gdal_algorithm.schema.json out.json diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index e37a04fc79f1..47492b836e30 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -236,6 +236,7 @@ if (BUILD_APPS) endif () set(GDAL_DATA_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/data/gdal_algorithm.schema.json ${CMAKE_CURRENT_SOURCE_DIR}/data/gdalinfo_output.schema.json ${CMAKE_CURRENT_SOURCE_DIR}/data/gdalmdiminfo_output.schema.json ${CMAKE_CURRENT_SOURCE_DIR}/data/ogrinfo_output.schema.json diff --git a/apps/data/gdal_algorithm.schema.json b/apps/data/gdal_algorithm.schema.json new file mode 100644 index 000000000000..d19b04a9797f --- /dev/null +++ b/apps/data/gdal_algorithm.schema.json @@ -0,0 +1,198 @@ +{ + "$id": "https://gdal.org/gdal_algorithm.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Validate the output of the 'gdal [command] [subcommand] --json-usage'", + + "oneOf": [ + { + "$ref": "#/definitions/algorithm" + } + ], + + "definitions": { + + "algorithm": { + "type": "object", + "properties": { + "name": { + "type": "string", + "$comment": "Algorithm name. Normally always set, except for the top 'gdal' algorithm" + }, + "full_path": { + "type": "array", + "items": { + "type": "string" + }, + "$comment": "Full path to get to this algorithm. For example, for 'gdal raster info', this will be [\"gdal\", \"raster\", \"info\"]" + }, + "description": { + "type": "string", + "$comment": "One sentence description of the algorithm" + }, + "short_url": { + "type": "string", + "$comment": "URL to the help page, without the server. For example \"/programs/gdal_raster_info.html\"" + }, + "url": { + "type": "string", + "$comment": "Full URL to the help page. For example \"https://gdal.org/programs/gdal_raster_info.html\"" + }, + "sub_algorithms": { + "type": "array", + "items": { + "$ref": "#/definitions/algorithm" + }, + "$comment": "Names of the immediate sub-algorithm of this algorithm. For example, or 'gdal raster', this will be [\"info\", \"convert\", ...]" + }, + "input_arguments": { + "type": "array", + "items": { + "$ref": "#/definitions/argument" + }, + "$comment": "Input arguments of the algorithm" + }, + "output_arguments": { + "type": "array", + "items": { + "$ref": "#/definitions/argument" + }, + "$comment": "Output arguments of the algorithm, that is arguments that are set by the algorithm (typically an output dataset)" + }, + "input_output_arguments": { + "type": "array", + "items": { + "$ref": "#/definitions/argument" + }, + "$comment": "Arguments of the algorithm that are both read and written by it." + }, + "pipeline_algorithms": { + "type": "array", + "items": { + "$ref": "#/definitions/algorithm" + }, + "$comment": "For pipeline algorithm, description of the accepted step algorithms. Only present for such pipeline algorithms" + } + }, + "required": [ + "description", + "short_url", + "url", + "sub_algorithms", + "input_arguments", + "output_arguments", + "input_output_arguments" + ], + "additionalProperties": false + }, + + "argument": { + "type": "object", + "properties": { + "name": { + "type": "string", + "$comment": "Argument name" + }, + "type": { + "enum": [ + "boolean", + "integer", + "real", + "string", + "dataset", + "integer_list", + "real_list", + "string_list", + "dataset_list" + ], + "$comment": "Argument type" + }, + "description": { + "type": "string", + "$comment": "Argument description" + }, + "choices": { + "type": "array", + "items": { + "type": "string" + }, + "$comment": "Valid values for the argument, when it accepts an enumeration as a value" + }, + "default": { + "$comment": "Default value (optional)" + }, + "required": { + "type": "boolean", + "$comment": "Whether this argument is required" + }, + "packed_values_allowed": { + "type": "boolean", + "$comment": "For command-line specification, for multi-valued arguments (type: integer_list, real_list, string_list), whether comma-separated values are accepted. e.g. '--my-arg=first,second'" + }, + "repeated_arg_allowed": { + "type": "boolean", + "$comment": "For command-line specification, for multi-valued arguments (type: integer_list, real_list, string_list), whether several repetition of the argument are accepted. e.g. '--my-arg first --my-arg second'" + }, + "min_count": { + "type": "integer", + "$comment": "For multi-valued arguments (type: integer_list, real_list, string_list, dataset_list), minimum number of values" + }, + "max_count": { + "type": "integer", + "$comment": "For multi-valued arguments (type: integer_list, real_list, string_list, dataset_list), maximum number of values" + }, + "category": { + "type": "string", + "$comment": "Category of the argument. Common categories include \"Base\", \"Advanced\", \"Esoteric\", but algorithms may define their own categories." + }, + "mutual_exclusion_group": { + "type": "string", + "$comment": "Identifier shared by several arguments to mean they are mutually exclusive." + }, + "metadata": { + "type": "object", + "$comment": "Object whose keys are metadata item names. This is typically used for type=dataset arguments. e.g. \"metadata\":{ \"required_capabilities\":[ \"DCAP_RASTER\", \"DCAP_CREATECOPY\" ] }" + }, + "dataset_type": { + "type": "array", + "items": { + "enum": [ + "raster", + "vector", + "multidim_raster" + ] + }, + "$comment": "Type of accepted datasets. Only used for type=dataset or type=dataset_list." + }, + "input_flags": { + "type": "array", + "items": { + "enum": [ + "name", + "dataset" + ] + }, + "$comment": "Which fields of a dataset argument may be set, by the user, when the argument is dealt as an input dataset. Only used for type=dataset or type=dataset_list." + }, + "output_flags": { + "type": "array", + "items": { + "enum": [ + "name", + "dataset" + ] + }, + "$comment": "Which fields of a dataset argument may be set, by the algorithm, when the argument is dealt as an output dataset. Only used for type=dataset or type=dataset_list." + } + }, + "required": [ + "name", + "type", + "description", + "required", + "category" + ], + "additionalProperties": false + } + + } +}