Enable print_output common function to print json and yaml from python dict or list
[osm/osmclient.git] / osmclient / common / print_output.py
1 #######################################################################################
2 # Copyright ETSI Contributors and Others.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13 # implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 #######################################################################################
17 import click
18 import logging
19 import json
20 import yaml
21 from prettytable import PrettyTable
22
23 from jsonpath_ng import parse
24
25
26 logger = logging.getLogger("osmclient")
27
28
29 def evaluate_output_format(ctx, param, value):
30 logger.debug("")
31 if value in ["table", "json", "yaml", "csv"]:
32 return value
33 elif value.startswith("jsonpath="):
34 return value
35 else:
36 raise click.BadParameter(
37 f"{value} is not one of 'table', 'json', 'yaml', 'csv', 'jsonpath'"
38 )
39
40
41 output_option = click.option(
42 "-o",
43 "--output",
44 default="table",
45 is_eager=True,
46 callback=evaluate_output_format,
47 help="output format (default: table)",
48 )
49
50
51 literal_option = click.option(
52 "--literal", is_flag=True, help="print literally, no pretty table"
53 )
54
55
56 def print_output(format="table", headers=["field", "value"], rows=[], data=None):
57 """
58 Prints content in specified format.
59 :param format: output format (table, yaml, json, csv, jsonpath=...). Default:
60 :param headers: headers of the content
61 :param rows: rows of the content
62 :param data: dictionary or list with the content to be printed. Only applies to yaml, json or jsonpath format.
63 If specified, headers and rows are ignored, and json/yaml/jsonpath output is generated directly from data.
64 """
65
66 logger.debug("")
67 if format == "table":
68 table = PrettyTable(headers)
69 table.align = "l"
70 for row in rows:
71 table.add_row(row)
72 print(table)
73 elif format == "csv":
74 table = PrettyTable(headers)
75 for row in rows:
76 table.add_row(row)
77 print(table.get_csv_string())
78 elif format == "json" or format == "yaml" or format.startswith("jsonpath="):
79 if not data:
80 data = []
81 for row in rows:
82 item = {}
83 for i in range(len(row)):
84 item[headers[i]] = row[i]
85 data.append(item)
86 if format == "json":
87 print(json.dumps(data, indent=4))
88 elif format == "yaml":
89 print(
90 yaml.safe_dump(
91 data, indent=4, default_flow_style=False, sort_keys=False
92 )
93 )
94 elif format.startswith("jsonpath="):
95 # JSONPath expression
96 json_path_expression = format.partition("=")[-1]
97 logger.debug(f"Jsonpath expression: {json_path_expression}")
98 json_path = parse(json_path_expression)
99 # Apply JSONPath expression on the JSON object
100 results = [match.value for match in json_path.find(data)]
101 for i in results:
102 print(i)