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

v.info: Add JSON output for history #4989

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
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
5 changes: 5 additions & 0 deletions vector/v.info/local_proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#define SHELL_BASIC 0x02
#define SHELL_REGION 0x04
#define SHELL_TOPO 0x08
#define STR_LEN 1001
#define MAX_STR_LEN 3003

enum OutputFormat { PLAIN, SHELL, JSON };

Expand All @@ -14,6 +16,8 @@ int level_one_info(struct Map_info *);
/* parse.c */
void parse_args(int, char **, char **, char **, int *, int *, int *,
enum OutputFormat *);
void parse_history_json(char *, char *, char *, char *, char *, char *, char *,
char *, JSON_Array *);

/* print.c */
void format_double(double, char *);
Expand All @@ -24,3 +28,4 @@ void print_columns(struct Map_info *, const char *, const char *,
void print_info(struct Map_info *);
void print_shell(struct Map_info *, const char *, enum OutputFormat,
JSON_Object *);
void print_history(struct Map_info *, enum OutputFormat);
7 changes: 1 addition & 6 deletions vector/v.info/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,7 @@ int main(int argc, char *argv[])

if (hist_flag || col_flag) {
if (hist_flag) {
char buf[1001];

Vect_hist_rewind(&Map);
while (Vect_hist_read(buf, 1000, &Map) != NULL) {
fprintf(stdout, "%s\n", buf);
}
print_history(&Map, format);
}
else if (col_flag) {
print_columns(&Map, input_opt, field_opt, format);
Expand Down
33 changes: 33 additions & 0 deletions vector/v.info/parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,36 @@ void parse_args(int argc, char **argv, char **input, char **field, int *history,
}
}
}

void parse_history_json(char *buf, char *command, char *gisdbase,
char *location, char *mapset, char *user, char *date,
char *mapset_path, JSON_Array *record_array)
{

if (strncmp(buf, "COMMAND:", 8) == 0) {
sscanf(buf, "COMMAND: %[^\n]", command);
}
else if (strncmp(buf, "GISDBASE:", 9) == 0) {
sscanf(buf, "GISDBASE: %[^\n]", gisdbase);
}
else if (strncmp(buf, "LOCATION:", 9) == 0) {
sscanf(buf, "LOCATION: %s MAPSET: %s USER: %s DATE: %[^\n]", location,
mapset, user, date);

JSON_Value *info_value = json_value_init_object();
if (info_value == NULL) {
G_fatal_error(
_("Failed to initialize JSON object. Out of memory?"));
}
JSON_Object *info_object = json_object(info_value);

json_object_set_string(info_object, "command", command);
snprintf(mapset_path, MAX_STR_LEN, "%s/%s/%s", gisdbase, location,
mapset);
json_object_set_string(info_object, "mapset_path", mapset_path);
json_object_set_string(info_object, "user", user);
json_object_set_string(info_object, "date", date);

json_array_append_value(record_array, info_value);
}
}
57 changes: 57 additions & 0 deletions vector/v.info/print.c
Original file line number Diff line number Diff line change
Expand Up @@ -771,3 +771,60 @@ void print_info(struct Map_info *Map)
divider('+');
fprintf(stdout, "\n");
}

void print_history(struct Map_info *Map, enum OutputFormat format)
{
char buf[STR_LEN];
char command[STR_LEN], gisdbase[STR_LEN];
char location[STR_LEN], mapset[STR_LEN];
char user[STR_LEN], date[STR_LEN];
char mapset_path[MAX_STR_LEN];

JSON_Value *root_value = NULL, *record_value = NULL;
JSON_Object *root_object = NULL;
JSON_Array *record_array = NULL;

if (format == JSON) {
root_value = json_value_init_object();
if (root_value == NULL) {
G_fatal_error(
_("Failed to initialize JSON object. Out of memory?"));
}
root_object = json_object(root_value);

record_value = json_value_init_array();
if (record_value == NULL) {
G_fatal_error(_("Failed to initialize JSON array. Out of memory?"));
}
record_array = json_array(record_value);
}

Vect_hist_rewind(Map);
while (Vect_hist_read(buf, sizeof(buf), Map) != NULL) {
switch (format) {
case PLAIN:
case SHELL:
fprintf(stdout, "%s\n", buf);
break;
case JSON:
// Parse each line based on its prefix
parse_history_json(buf, command, gisdbase, location, mapset, user,
date, mapset_path, record_array);
break;
}
}

if (format == JSON) {
json_object_set_value(root_object, "records", record_value);

char *serialized_string = json_serialize_to_string_pretty(root_value);
if (!serialized_string) {
json_value_free(root_value);
G_fatal_error(_("Failed to initialize pretty JSON string."));
}
puts(serialized_string);

json_free_serialized_string(serialized_string);
json_value_free(root_value);
}
}
27 changes: 27 additions & 0 deletions vector/v.info/testsuite/test_vinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,33 @@ def test_json_column(self):

self.assertDictEqual(expected_json, result)

def test_json_histroy(self):
"""Test the v.info JSON output format with the history flag."""
module = SimpleModule(
"v.info", map=self.test_vinfo_with_db_3d, format="json", flags="h"
)
self.runModule(module)
result = json.loads(module.outputs.stdout)

expected_json = {
"records": [
{
"command": 'v.random -z output="test_vinfo_with_db_3d" npoints=5 layer="-1" zmin=0 zmax=100 column="elevation" column_type="double precision"'
}
]
}

# The following fields vary depending on the Grass sample data's path,
# date, and user. Therefore, only check for their presence in the JSON output
# and not for their exact values.
remove_fields = ["mapset_path", "date", "user"]
for record in result["records"]:
for field in remove_fields:
self.assertIn(field, record)
record.pop(field)

self.assertDictEqual(expected_json, result)

def test_database_table(self):
"""Test the database table column and type of the two vector maps with attribute data"""
self.assertModuleKeyValue(
Expand Down
Loading