blob: afb6375ced82e427f78b750e285e237c9e90f150 [file] [log] [blame]
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +03001__doc__ = "functions for make pretty yaml files"
2__all__ = ['dumps']
3
4
koder aka kdanilovf4b82c22015-04-11 13:35:25 +03005def dumps_simple(val):
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +03006 bad_symbols = set(" \r\t\n,':{}[]><;")
koder aka kdanilovf4b82c22015-04-11 13:35:25 +03007
8 if isinstance(val, basestring):
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +03009 if isinstance(val, unicode):
10 val = val.encode('utf8')
11
koder aka kdanilov7248c7b2015-05-31 22:53:03 +030012 try:
13 float(val)
14 val = repr(val)
15 except ValueError:
16 if len(bad_symbols & set(val)) != 0:
17 val = repr(val)
18
koder aka kdanilovf4b82c22015-04-11 13:35:25 +030019 return val
20 elif val is True:
21 return 'true'
22 elif val is False:
23 return 'false'
24 elif val is None:
25 return 'null'
26
27 return str(val)
28
29
30def is_simple(val):
31 simple_type = isinstance(val, (str, unicode, int, long, bool, float))
32 return simple_type or val is None
33
34
35def all_nums(vals):
36 return all(isinstance(val, (int, float, long)) for val in vals)
37
38
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +030039def dumpv(data, tab_sz=4, width=160, min_width=40):
koder aka kdanilovf4b82c22015-04-11 13:35:25 +030040 tab = ' ' * tab_sz
41
42 if width < min_width:
43 width = min_width
44
45 res = []
46 if is_simple(data):
47 return [dumps_simple(data)]
48
49 if isinstance(data, (list, tuple)):
50 if all(map(is_simple, data)):
51 if all_nums(data):
koder aka kdanilova047e1b2015-04-21 23:16:59 +030052 one_line = "[{0}]".format(", ".join(map(dumps_simple, data)))
koder aka kdanilovf4b82c22015-04-11 13:35:25 +030053 else:
koder aka kdanilova047e1b2015-04-21 23:16:59 +030054 one_line = "[{0}]".format(",".join(map(dumps_simple, data)))
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +030055 elif len(data) == 0:
56 one_line = "[]"
koder aka kdanilovf4b82c22015-04-11 13:35:25 +030057 else:
58 one_line = None
59
60 if one_line is None or len(one_line) > width:
61 pref = "-" + ' ' * (tab_sz - 1)
62
63 for val in data:
64 items = dumpv(val, tab_sz, width - tab_sz, min_width)
65 items = [pref + items[0]] + \
66 [tab + item for item in items[1:]]
67 res.extend(items)
68 else:
69 res.append(one_line)
70 elif isinstance(data, dict):
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +030071 if len(data) == 0:
72 res.append("{}")
73 else:
74 assert all(map(is_simple, data.keys()))
koder aka kdanilovf4b82c22015-04-11 13:35:25 +030075
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +030076 one_line = None
77 if all(map(is_simple, data.values())):
78 one_line = ", ".join(
79 "{0}: {1}".format(dumps_simple(k), dumps_simple(v))
80 for k, v in sorted(data.items()))
81 one_line = "{" + one_line + "}"
82 if len(one_line) > width:
83 one_line = None
koder aka kdanilovf4b82c22015-04-11 13:35:25 +030084
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +030085 if one_line is None:
86 for k, v in data.items():
87 key_str = dumps_simple(k) + ": "
88 val_res = dumpv(v, tab_sz, width - tab_sz, min_width)
89
90 if len(val_res) == 1 and \
91 len(key_str + val_res[0]) < width and \
koder aka kdanilovbb6d6cd2015-06-20 02:55:07 +030092 not isinstance(v, dict) and \
93 not val_res[0].strip().startswith('-'):
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +030094 res.append(key_str + val_res[0])
95 else:
96 res.append(key_str)
97 res.extend(tab + i for i in val_res)
koder aka kdanilovf4b82c22015-04-11 13:35:25 +030098 else:
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +030099 res.append(one_line)
koder aka kdanilovf4b82c22015-04-11 13:35:25 +0300100 else:
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300101 try:
102 get_yamable = data.get_yamable
103 except AttributeError:
104 raise ValueError("Can't pack {0!r}".format(data))
105 res = dumpv(get_yamable(), tab_sz, width, min_width)
koder aka kdanilovf4b82c22015-04-11 13:35:25 +0300106
107 return res
108
109
110def dumps(data, tab_sz=4, width=120, min_width=40):
111 return "\n".join(dumpv(data, tab_sz, width, min_width))