11#!/usr/bin/env python
22
33import sys
4+
45if sys .version_info < (3 , 0 ):
5- sys .stdout .write ("Sorry, Python 3 og higher required\n " )
6+ sys .stderr .write ("Sorry, Python 3 og higher required\n " )
67 sys .exit (1 )
78
89import os
9- import json , sys , argparse
10+ import io
11+ import json
12+ import sys
13+ import argparse
1014import warnings
1115
1216try :
2327 jinja2 = None
2428
2529
26- # API compatibility between pyyaml and ruamel.yaml might break in the future
27- # https://yaml.readthedocs.io/en/latest/api.html
2830try :
2931 import ruamel .yaml as yaml
3032except ImportError :
31- import yaml
32- from yaml import (
33- safe_load as yaml_safe_load ,
34- safe_dump as yaml_safe_dump ,
35- )
33+ print ("ruame.yaml is required" , file = sys .stderr )
34+ sys .exit (1 )
3635else :
36+
3737 def yaml_safe_load (stream ):
3838 return yaml .YAML (typ = "safe" ).load (stream )
3939
4040 def yaml_safe_dump (data , stream = None , ** kwargs ):
4141 return yaml .YAML (typ = "safe" ).dump (data , stream = stream , ** kwargs )
4242
43+
4344try :
4445 pygments = True
4546 from pygments import highlight
@@ -48,20 +49,32 @@ def yaml_safe_dump(data, stream=None, **kwargs):
4849except ImportError :
4950 pygments = False
5051
51- parser = argparse .ArgumentParser (description = 'Convert json to yaml and vice versa' )
52- parser .add_argument ('--indent' , '-i' , dest = 'indent' , default = 4 , type = int , help = 'text indentation' )
53- parser .add_argument ('--json' , '-j' , dest = 'alwaysjson' , action = 'store_true' , help = 'always output to json' )
54- parser .add_argument ('infile' , nargs = '?' , type = argparse .FileType ('r' ), default = sys .stdin , help = 'json/yaml input' )
52+ parser = argparse .ArgumentParser (description = "Convert json to yaml and vice versa" )
53+ parser .add_argument (
54+ "--indent" , "-i" , dest = "indent" , default = 4 , type = int , help = "text indentation"
55+ )
56+ parser .add_argument (
57+ "--json" , "-j" , dest = "alwaysjson" , action = "store_true" , help = "always output to json"
58+ )
59+ parser .add_argument (
60+ "infile" ,
61+ nargs = "?" ,
62+ type = argparse .FileType ("r" ),
63+ default = sys .stdin ,
64+ help = "json/yaml input" ,
65+ )
5566
5667if pygments :
57- parser .add_argument ('--color' , '-c' , dest = 'color' , action = 'store_true' , help = 'syntax colored output' )
68+ parser .add_argument (
69+ "--color" , "-c" , dest = "color" , action = "store_true" , help = "syntax colored output"
70+ )
5871
5972args = parser .parse_args ()
6073
6174terminal_red = "\033 [91m"
6275terminal_yellow = "\033 [93m"
6376terminal_default = "\033 [39m"
64-
77+
6578if pygments :
6679 if args .color :
6780 formatter = Terminal256Formatter
@@ -70,90 +83,112 @@ def yaml_safe_dump(data, stream=None, **kwargs):
7083
7184
7285def human_readable_path (path ):
73- out = str ()
86+ out = str ()
7487 for i in path :
7588 if not isinstance (i , int ):
76- out += str (i )+ ' -> '
89+ out += str (i ) + " -> "
7790 return out
7891
92+
7993def eprint (* args , ** kwargs ):
80- ''' print to stderr '''
94+ """ print to stderr"""
8195 print (* args , file = sys .stderr , ** kwargs )
8296
8397
8498def print_table (schema ):
85- ''' pretty print schema as markdown table '''
99+ """ pretty print schema as markdown table"""
86100 properties = schema .get ("properties" , "" )
87101 if isinstance (properties , dict ):
88102 eprint (terminal_yellow + "Need help, my young apprentice?\n " + terminal_red )
89- eprint ("{:25} | {:7} | {:50}" .format (25 * "-" , 7 * "-" , 50 * "-" ))
103+ eprint ("{:25} | {:7} | {:50}" .format (25 * "-" , 7 * "-" , 50 * "-" ))
90104 eprint ("{:25} | {:7} | {:50}" .format ("Property" , "Type" , "Description" ))
91- eprint ("{:25} | {:7} | {:50}" .format (25 * "-" , 7 * "-" , 50 * "-" ))
105+ eprint ("{:25} | {:7} | {:50}" .format (25 * "-" , 7 * "-" , 50 * "-" ))
92106 for key , value in properties .items ():
93107 required = key in schema .get ("required" , ["" ])
94108 _property = key + str ("*" if required else "" )
95109 if isinstance (value , dict ):
96110 _description = value .get ("description" , "" )
97111 if "type" in value :
98112 _default = value .get ("default" , "" )
99- if _default != "" :
100- _property = _property + '=' + str (_default )
113+ if _default != "" :
114+ _property = _property + "=" + str (_default )
101115 _type = value ["type" ]
102116 if isinstance (_type , list ):
103- _type = '/' .join (_type )
104- eprint ("{:25} | {:7} | {}" .format ('`' + _property + '`' , _type , _description ))
117+ _type = "/" .join (_type )
118+ eprint (
119+ "{:25} | {:7} | {}" .format (
120+ "`" + _property + "`" , _type , _description
121+ )
122+ )
105123 else :
106- eprint ("{:25} | {:7} | {}" .format ('`' + _property + '`' , 'n/a' , _description ))
107- eprint (terminal_default ) # restore terminal color
124+ eprint (
125+ "{:25} | {:7} | {}" .format (
126+ "`" + _property + "`" , "n/a" , _description
127+ )
128+ )
129+ eprint (terminal_default ) # restore terminal color
130+
108131
109132def validate_input (instance ):
110- ''' JSON schema checker '''
133+ """ JSON schema checker"""
111134 if jsonschema :
112- pathname = os .path .dirname (sys .argv [0 ]) # location of yason.py
113- for subdir in ["/../docs" , "/../share/faunus" ]: # schema file can be in src or installed
114- schemafile = os .path .abspath (pathname + subdir ) + '/schema.yml'
135+ pathname = os .path .dirname (sys .argv [0 ]) # location of yason.py
136+ for subdir in [
137+ "/../docs" ,
138+ "/../share/faunus" ,
139+ ]: # schema file can be in src or installed
140+ schemafile = os .path .abspath (pathname + subdir ) + "/schema.yml"
115141 if os .path .exists (schemafile ):
116142 with open (schemafile , "r" ) as f :
117143 _schema = yaml_safe_load (f )
118- error = best_match (Draft201909Validator (_schema ).iter_errors (instance ))
119- if error != None :
120- eprint ( "{}{}\n " .format (human_readable_path (error .path ), error .message ) )
144+ error = best_match (
145+ Draft201909Validator (_schema ).iter_errors (instance )
146+ )
147+ if error is not None :
148+ eprint (
149+ "{}{}\n " .format (
150+ human_readable_path (error .path ), error .message
151+ )
152+ )
121153 print_table (error .schema )
122154 sys .exit (1 )
123155 break
124156
157+
125158try : # ... to read json
126- i = args .infile .read ()
159+ file_as_str = args .infile .read ()
127160 if jinja2 :
128161 # additional files can be used with {% include "file" %}
129162 dirs = [os .getcwd (), os .path .dirname (os .path .realpath (__file__ )) + "/../top" ]
130163 loader = jinja2 .FileSystemLoader (dirs )
131164 env = jinja2 .Environment (loader = loader )
132- i = env .from_string (i ).render () # render jinja2
133- # i = jinja2.Template(i).render() # render jinja2
165+ file_as_str = env .from_string (file_as_str ).render () # render jinja2
134166
135- d = json .loads (i )
136- if "mcloop" in d or "version" in d :
137- validate_input (d )
167+ file_as_dict = json .loads (file_as_str )
168+ if "mcloop" in file_as_dict or "version" in file_as_dict :
169+ validate_input (file_as_dict )
138170 if args .alwaysjson :
139171 if pygments :
140- i = highlight (out , JsonLexer (), formatter ())
141- print (i )
172+ file_as_str = highlight (file_as_str , JsonLexer (), formatter ())
173+ print (file_as_str )
142174 else :
143- out = yaml_safe_dump (d , indent = args .indent , allow_unicode = True )
175+ stream = io .StringIO ()
176+ yaml_safe_dump (file_as_dict , stream = stream )
144177 if pygments :
145- out = highlight (out , YamlLexer (), formatter ())
146- print (out )
178+ stream = highlight (stream .getvalue (), YamlLexer (), formatter ())
179+ print (stream )
180+ else :
181+ print (stream .getvalue ())
147182except json .decoder .JSONDecodeError :
148183 try : # ... to read yaml
149- d = yaml_safe_load (i ) # plain load was deprecated in PyYAML
150- if "mcloop" in d or "version" in d :
151- validate_input (d )
152- out = json .dumps (d , indent = args .indent )
184+ file_as_dict = yaml_safe_load (file_as_str )
185+ if "mcloop" in file_as_dict or "version" in file_as_dict :
186+ validate_input (file_as_dict )
187+ stream = json .dumps (file_as_dict , indent = args .indent )
153188 if pygments :
154- out = highlight (out , JsonLexer (), formatter ())
155- print (out )
189+ stream = highlight (stream , JsonLexer (), formatter ())
190+ print (stream )
156191 except yaml .parser .ParserError as exception :
157- print ("input error: invalid json or yaml format" , file = sys . stderr )
158- print (exception , file = sys . stderr )
192+ eprint ("input error: invalid json or yaml format" )
193+ eprint (exception )
159194 sys .exit (1 )
0 commit comments