Skip to content

Commit bb91596

Browse files
committed
configurations
1 parent 9c97e65 commit bb91596

File tree

9 files changed

+1283
-80
lines changed

9 files changed

+1283
-80
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
\#*\#
2+
.#*
13
env/
24
py*/
35
__pycache__
@@ -6,6 +8,7 @@ __pycache__
68
tests/logs/*.log
79
build
810
dist
11+
.ipynb_checkpoints/
912

1013
/build
1114
/dist

EXAMPLE.ipynb

Lines changed: 806 additions & 0 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,7 @@ Documentation coming soon: see test folder for now
129129

130130
### Python
131131

132+
### csvjson
133+
134+
https://csvjson.com/json2csv
135+

examples/books1.json

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
{
2+
"all_book_series" : [
3+
{
4+
"books" : [
5+
{
6+
"price" : 5.99,
7+
"id" : "S001.1",
8+
"summary" : "Hobbits",
9+
"name" : "Fellowship of the Ring"
10+
},
11+
{
12+
"price" : 5.99,
13+
"summary" : "More hobbits",
14+
"id" : "S001.2",
15+
"name" : "The Two Towers"
16+
},
17+
{
18+
"price" : 6.99,
19+
"id" : "S001.3",
20+
"summary" : "Yet more hobbits",
21+
"name" : "Return of the King"
22+
}
23+
],
24+
"genres" : [
25+
"fantasy"
26+
],
27+
"id" : "S001",
28+
"name" : "Lord of the Rings",
29+
"creator" : {
30+
"from_country" : "England",
31+
"name" : "JRR Tolkein"
32+
}
33+
},
34+
{
35+
"name" : "The Culture Series",
36+
"creator" : {
37+
"name" : "Ian M Banks",
38+
"from_country" : "Scotland"
39+
},
40+
"id" : "S002",
41+
"genres" : [
42+
"scifi"
43+
],
44+
"books" : [
45+
{
46+
"price" : 5.99,
47+
"id" : "S002.1",
48+
"name" : "Consider Phlebas"
49+
},
50+
{
51+
"price" : 5.99,
52+
"name" : "Player of Games",
53+
"id" : "S002.2"
54+
}
55+
]
56+
},
57+
{
58+
"name" : "Book of the New Sun",
59+
"creator" : {
60+
"genres" : [
61+
"scifi",
62+
"fantasy"
63+
],
64+
"name" : "Gene Wolfe",
65+
"from_country" : "USA"
66+
},
67+
"books" : [
68+
{
69+
"name" : "Shadow of the Torturer",
70+
"id" : "S003.1"
71+
},
72+
{
73+
"id" : "S003.2",
74+
"name" : "Claw of the Conciliator",
75+
"price" : 6.99
76+
}
77+
],
78+
"id" : "S003",
79+
"genres" : [
80+
"scifi",
81+
"fantasy"
82+
]
83+
},
84+
{
85+
"books" : [
86+
{
87+
"name" : "Blah",
88+
"id" : "S004.1"
89+
}
90+
],
91+
"id" : "S004",
92+
"name" : "Example with single book",
93+
"creator" : {
94+
"name" : "Ms Writer",
95+
"genres" : [
96+
"romance"
97+
],
98+
"from_country" : "USA"
99+
}
100+
},
101+
{
102+
"id" : "S005",
103+
"creator" : {
104+
"from_country" : "USA",
105+
"genres" : [
106+
"romance",
107+
"scifi",
108+
"fantasy"
109+
],
110+
"name" : "Mr Unproductive"
111+
},
112+
"name" : "Example with no books"
113+
}
114+
]
115+
}

json_flattener/cli.py

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import os
2+
import io
23
import sys
34
import logging
45
import click
@@ -7,13 +8,21 @@
78
from json_flattener import flatten_to_csv, unflatten_from_csv, GlobalConfig, KeyConfig, Serializer
89

910

10-
def _get_format(input: str, input_format: str =None) -> str:
11+
def _get_format(input: str, input_format: str =None, default_format: str = None) -> str:
1112
if input_format is None:
13+
if input is None:
14+
if default_format is not None:
15+
return default_format
16+
else:
17+
raise Exception(f'Must pass input file or default format')
1218
_, ext = os.path.splitext(input)
1319
if ext is not None:
1420
input_format = ext.replace('.', '')
1521
else:
16-
raise Exception(f'Must pass format option OR use known file suffix: {input}')
22+
if default_format is not None:
23+
return default_format
24+
else:
25+
raise Exception(f'Must pass format option OR use known file suffix: {input}')
1726
return input_format.lower()
1827

1928
def _is_xsv(fmt: str) -> bool:
@@ -78,7 +87,7 @@ def _get_config(serializer: str = 'json', serialized_keys = [], multivalued_keys
7887
"-o", "--output", help="Output file, e.g. a SSSOM tsv file."
7988
)
8089
output_format_option = click.option(
81-
"-O",
90+
"-t",
8291
"--output-format",
8392
help=f'Desired output format, e.g. {",".join(FORMATS)}',
8493
)
@@ -119,6 +128,16 @@ def _get_config(serializer: str = 'json', serialized_keys = [], multivalued_keys
119128
multiple=True,
120129
help="Key configuration. Must be of form KEY={yaml,json,flat,multivalued}*",
121130
)
131+
load_config_option = click.option(
132+
"-c",
133+
"--load-config",
134+
help="Path to global configuration file to be loaded",
135+
)
136+
save_config_option = click.option(
137+
"-O",
138+
"--save-config",
139+
help="Path to global configuration file to be saved",
140+
)
122141
@click.group()
123142
@click.option("-v", "--verbose", count=True)
124143
@click.option("-q", "--quiet")
@@ -154,9 +173,12 @@ def main(verbose: int, quiet: bool):
154173
@serializer_option
155174
@serialized_keys_option
156175
@config_option
176+
@load_config_option
177+
@save_config_option
157178
@key_option
158179
def flatten(input: str, output: str, input_format: str, output_format: str, key: str,
159180
serializer: str, serialized_keys = [], multivalued_keys = [], flatten_keys = [],
181+
save_config: str = None, load_config: str = None,
160182
config_key = []):
161183
"""Flatten a file to TSV/CSV
162184
@@ -197,6 +219,9 @@ def flatten(input: str, output: str, input_format: str, output_format: str, key:
197219
logging.debug(f'CONFIG={config}')
198220
with open(output, 'w') as stream:
199221
flatten_to_csv(objs, stream, config=config)
222+
if save_config is not None:
223+
with open(save_config , 'w') as stream:
224+
yaml.dump(config.as_dict(), stream)
200225

201226

202227
@main.command()
@@ -209,23 +234,29 @@ def flatten(input: str, output: str, input_format: str, output_format: str, key:
209234
@serializer_option
210235
@serialized_keys_option
211236
@config_option
237+
@load_config_option
212238
@key_option
213239
def unflatten(input: str, output: str, input_format: str, output_format: str, key: str,
214-
serializer: str, serialized_keys = [], multivalued_keys = [], flatten_keys = [],
215-
config_key = []):
240+
serializer: str, serialized_keys = [], multivalued_keys = [], flatten_keys = [],
241+
load_config: str = None,
242+
config_key = []):
216243
"""Unflatten a file from TSV/CSV
217244
218245
Example:
219246
jfl unflatten --input my.tsv --output my.yaml
220247
221248
"""
222249
input_format = _get_format(input, input_format)
223-
output_format = _get_format(output, output_format)
250+
output_format = _get_format(output, output_format, 'json')
224251
config = _get_config(serializer = serializer,
225252
serialized_keys = serialized_keys,
226253
multivalued_keys = multivalued_keys,
227254
flatten_keys = flatten_keys,
228255
config_keys = config_key)
256+
if load_config is not None:
257+
with open(load_config) as stream:
258+
config = GlobalConfig.from_dict(**yaml.safe_load(stream))
259+
logging.debug(f'CONFIG={config}')
229260
with open(input) as stream:
230261
if input_format == 'tsv':
231262
sep = '\t'
@@ -246,5 +277,6 @@ def unflatten(input: str, output: str, input_format: str, output_format: str, ke
246277
else:
247278
json.dump(obj, stream)
248279

280+
249281
if __name__ == "__main__":
250282
main()

0 commit comments

Comments
 (0)