|
| 1 | +import csv |
| 2 | +import io |
1 | 3 | import json |
2 | 4 | import logging |
3 | 5 | import os |
|
9 | 11 | log = logging.getLogger() |
10 | 12 |
|
11 | 13 |
|
12 | | -def get_script_path(): |
| 14 | +def _get_script_path(): |
13 | 15 | return os.path.dirname(__file__) |
14 | 16 |
|
15 | 17 |
|
16 | | -# Create a output printer |
17 | | -# |
18 | | -# Formatting of output is defined in okdata/cli/data/ouput-format. |
19 | | -# Each command defines what (from the API response) should be printed, and |
20 | | -# what the human-readable name should be |
21 | | -def create_output(format, configfile): |
22 | | - datadir = f"{get_script_path()}/data/output-format" |
23 | | - filename = f"{datadir}/{configfile}" |
24 | | - log.info(f"Creating output format: {format}, from: {filename}") |
25 | | - with open(filename) as config_file: |
26 | | - config = json.load(config_file) |
| 18 | +def create_output(fmt, config_file): |
| 19 | + """Create and return an output printer. |
27 | 20 |
|
28 | | - if format == "json": |
29 | | - return JsonOutput(config) |
30 | | - return TableOutput(config) |
| 21 | + Formatting of output is defined in the `okdata/cli/data/ouput-format` |
| 22 | + directory. Each command defines which fields from the API response should |
| 23 | + be printed, and what the human-readable name should be. |
| 24 | + """ |
| 25 | + datadir = f"{_get_script_path()}/data/output-format" |
| 26 | + filename = f"{datadir}/{config_file}" |
| 27 | + log.info(f"Creating output format: {fmt}, from: {filename}") |
| 28 | + |
| 29 | + with open(filename) as f: |
| 30 | + config = json.load(f) |
| 31 | + |
| 32 | + return { |
| 33 | + "json": JsonOutput(config), |
| 34 | + "csv": CSVOutput(config), |
| 35 | + }.get(fmt, TableOutput(config)) |
31 | 36 |
|
32 | 37 |
|
33 | 38 | class TableOutput(PrettyTable): |
@@ -104,13 +109,9 @@ def format_cell_value(value, max_width): |
104 | 109 | return value |
105 | 110 |
|
106 | 111 |
|
107 | | -# TODO: merge many outputs to one array of elements when listing a version |
108 | | -class JsonOutput: |
| 112 | +class StructuredDataOutput: |
109 | 113 | def __init__(self, config): |
110 | 114 | self.config = config |
111 | | - # set to True it will return a single object from self.out when printed. This will make it |
112 | | - # easier to pass output to jq without having to access out[0] from the CLI |
113 | | - self.output_singular_object = False |
114 | 115 | self.out = [] |
115 | 116 |
|
116 | 117 | def field_values(self, row, row_key, key): |
@@ -144,6 +145,36 @@ def add_rows(self, rows): |
144 | 145 | for row in rows: |
145 | 146 | self.add_row(row) |
146 | 147 |
|
| 148 | + def __str__(self): |
| 149 | + raise NotImplementedError |
| 150 | + |
| 151 | + |
| 152 | +class CSVOutput(StructuredDataOutput): |
| 153 | + def __str__(self): |
| 154 | + out = io.StringIO() |
| 155 | + writer = csv.DictWriter(out, self.out[0].keys()) |
| 156 | + writer.writeheader() |
| 157 | + writer.writerows(self.out) |
| 158 | + return out.getvalue() |
| 159 | + |
| 160 | + def get_row_value(self, row, key): |
| 161 | + val = super().get_row_value(row, key) |
| 162 | + |
| 163 | + if isinstance(val, str): |
| 164 | + return val.replace("\n", "") |
| 165 | + elif isinstance(val, list): |
| 166 | + return ";".join(val) |
| 167 | + return val |
| 168 | + |
| 169 | + |
| 170 | +# TODO: merge many outputs to one array of elements when listing a version |
| 171 | +class JsonOutput(StructuredDataOutput): |
| 172 | + def __init__(self, config): |
| 173 | + super().__init__(config) |
| 174 | + # set to True it will return a single object from self.out when printed. This will make it |
| 175 | + # easier to pass output to jq without having to access out[0] from the CLI |
| 176 | + self.output_singular_object = False |
| 177 | + |
147 | 178 | def __repr__(self): |
148 | 179 | return json.dumps(self.out) |
149 | 180 |
|
|
0 commit comments