Skip to content
75 changes: 62 additions & 13 deletions general/g.parser/g.parser.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,28 +255,77 @@ v.in.db --interface-description
## JSON

The flag **--json** added to a GRASS command with parameters mandatorily
to be specified generates a module interface description in JSON.
Example:
to be specified generates a module interface description in JSON. The JSON
output can be used as building blocks in actinia processing chains.

actinia specific parametrization is supported for both import and export.

Import of input data is denoted with a "@" as delimiter followed by a
valid URL.

Request for actinia to export a raster, vector or other file-based data
can be invoked with a "+" behind the file-name followed by an
actinia-format name. Currently recognized formats are:

- COG
- GTiff
- GPKG
- SQLite
- GML
- GeoJSON
- ESRI_Shapefile
- CSV
- TXT
- PDF
- PostgreSQL

Many GRASS tools produce textual output to *stdout* and actinia allows
to export that output. However, the **--json** flag does not yet
allow to specify export of *stdout*, so export instructions need to be
added manually to the resulting JSON data. In an actinia processing
chain, exporting *stdout* may be requested as follows:

```json
{
...
'stdout': {'id': 'stats', 'format': 'kv', 'delimiter': '='},
}
```

Please consult the
[actinia documentation](https://actinia-org.github.io/actinia-core/tutorial_process_chain/)
for possible export formats and settings of *stdout* results.

Here is a full example for usage of the **--json** flag:

```sh
v.in.db driver=sqlite database=mysqlite.db table=pointsfile x=x y=y z=z key=idcol out=dtmpoints --json
r.slope.aspect --o --q -e \
elevation="elevation@https://storage.googleapis.com/graas-geodata/elev_ned_30m.tif" \
slope="slope+GTiff" aspect="aspect+GTiff" --json
```

```json
{
"module": "v.in.db",
"id": "v.in.db_1804289383",
"module": "r.slope.aspect",
"overwrite": true,
"quiet": true,
"id": "r.slope.aspect_1804289383",
"flags":"e",
"inputs":[
{"param": "table", "value": "pointsfile"},
{"param": "driver", "value": "sqlite"},
{"param": "database", "value": "mysqlite.db"},
{"param": "x", "value": "x"},
{"param": "y", "value": "y"},
{"param": "z", "value": "z"},
{"param": "key", "value": "idcol"}
{"import_descr": {"source":"https://storage.googleapis.com/graas-geodata/elev_ned_30m.tif", "type":"raster"},
"param": "elevation", "value": "elevation"},
{"param": "format", "value": "degrees"},
{"param": "precision", "value": "FCELL"},
{"param": "zscale", "value": "1.0"},
{"param": "min_slope", "value": "0.0"},
{"param": "nprocs", "value": "0"},
{"param": "memory", "value": "300"}
],
"outputs":[
{"param": "output", "value": "dtmpoints"}
{"export": {"format":"GTiff", "type":"raster"},
"param": "slope", "value": "slope"},
{"export": {"format":"GTiff", "type":"raster"},
"param": "aspect", "value": "aspect"}
]
}
```
Expand Down
37 changes: 30 additions & 7 deletions lib/gis/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,6 @@ int G_parser(int argc, char **argv)
}

/* Loop through all command line arguments */

while (--argc) {
ptr = *(++argv);

Expand Down Expand Up @@ -547,10 +546,19 @@ int G_parser(int argc, char **argv)
snprintf(buff, sizeof(buff), "GRASS_VERBOSE=%d",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With G_set_verbose() added, may this snprintf + putenv blocks be removed?

When i ran some local tests, it does not seem to have any effect after the first time such a block had run, e.g. if users provide both --v and --pp.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With G_set_verbose() added, may this snprintf + putenv blocks be removed?

I believe it can, G_set_verbose() is the dedicated API for just this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the snprintf + putenv blocks.

G_verbose_max());
putenv(G_store(buff));
G_set_verbose(G_verbose_max());
if (st->quiet == 1) {
G_warning(_("Use either --quiet or --verbose flag, not "
"both. Assuming --verbose."));
}
if (st->superquiet) {

/* Reactivate warnings */
G_suppress_warnings(FALSE);
G_warning(_("Use either --qq or --verbose flag, not "
"both. Assuming --verbose."));
}
st->superquiet = 0; /* for passing to gui init */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably set a bool to either true or false for future compatibility (see https://en.cppreference.com/w/c/language/bool_constant.html).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 7197c4a

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For real bool value (as in the case with the change to bool superquiet;) lowercase true and false should be used. Uppercase variants are macros defined in:

/* For boolean values and comparisons use the C99 type 'bool' with values 'true'
*/
/* and 'false' For historical reasons 'TRUE' and 'FALSE' are still valid. */
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif

and are used in int-based boolean functionality, e.g.:

int G_suppress_warnings(int);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to lowercase for superquiet.

st->quiet = -1;
}

Expand All @@ -563,28 +571,43 @@ int G_parser(int argc, char **argv)
snprintf(buff, sizeof(buff), "GRASS_VERBOSE=%d",
G_verbose_min());
putenv(G_store(buff));
G_set_verbose(G_verbose_min());
if (st->quiet == -1) {
G_warning(_("Use either --quiet or --verbose flag, not "
"both. Assuming --quiet."));
}
st->quiet = 1; /* for passing to gui init */
if (st->superquiet) {

/* Reactivate warnings */
G_suppress_warnings(FALSE);
G_warning(_("Use either --qq or --quiet flag, not "
"both. Assuming --quiet."));
}
st->superquiet = 0; /* for passing to gui init */
st->quiet = 1;
}

/* Super quiet option */
else if (strcmp(ptr, "--qq") == 0) {
char buff[32];

if (st->module_info.verbose == G_verbose_max()) {
G_warning(_("Use either --qq or --verbose flag, not both. "
"Assuming --qq."));
}
if (st->quiet == 1) {
G_warning(_("Use either --qq or --quiet flag, not "
"both. Assuming --qq."));
}
/* print nothing, but errors */
st->module_info.verbose = G_verbose_min();
snprintf(buff, sizeof(buff), "GRASS_VERBOSE=%d",
G_verbose_min());
putenv(G_store(buff));
G_set_verbose(G_verbose_min());
G_suppress_warnings(TRUE);
if (st->quiet == -1) {
G_warning(_("Use either --qq or --verbose flag, not both. "
"Assuming --qq."));
}
st->quiet = 1; /* for passing to gui init */
st->superquiet = 1; /* for passing to gui init */
st->quiet = -1;
}

/* Force gui to come up */
Expand Down
23 changes: 19 additions & 4 deletions lib/gis/parser_json.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ char *check_mapset_in_layer_name(char *, int);
static char *str_json_escape(const char *str);
static char *str_replace_free_buffer(char *buffer, const char old_char,
const char *new_str);

/*!
\brief This function generates actinia JSON process chain building blocks
from the command line arguments that can be used in the actinia processing
Expand Down Expand Up @@ -229,7 +228,6 @@ char *G__json(void)
/* Count input and output options */
if (st->n_opts) {
struct Option *opt;

for (opt = &st->first_option; opt; opt = opt->next_opt) {
if (opt->answer) {
if (opt->gisprompt) {
Expand All @@ -254,6 +252,23 @@ char *G__json(void)

fprintf(fp, "{\n");
fprintf(fp, " \"module\": \"%s\",\n", G_program_name());
if (st->overwrite || getenv("GRASS_OVERWRITE")) {
fprintf(fp, " \"overwrite\": true,\n");
}

if (st->module_info.verbose == G_verbose_max() ||
G_verbose() == G_verbose_max()) {
fprintf(fp, " \"verbose\": true,\n");
}

if (st->quiet == 1 || (G_verbose() == G_verbose_min() && !st->superquiet)) {
fprintf(fp, " \"quiet\": true,\n");
}

if (st->superquiet || G_verbose() == -1) {
fprintf(fp, " \"superquiet\": true,\n");
}

fprintf(fp, " \"id\": \"%s_%i\"", G_program_name(), random_int);

if (st->n_flags && num_flags > 0) {
Expand Down Expand Up @@ -336,10 +351,10 @@ char *G__json(void)
}
}
}
fprintf(fp, " ]\n");
fprintf(fp, " ]");
}

fprintf(fp, "}\n");
fprintf(fp, "\n}\n");
fclose(fp);

/* Print the file content to stdout */
Expand Down
1 change: 1 addition & 0 deletions lib/gis/parser_local_proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ struct state {
int n_keys_alloc;
int overwrite;
int quiet;
bool superquiet;
int has_required;
int suppress_required;
int suppress_overwrite;
Expand Down
Loading