Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
mikf
GitHub Repository: mikf/gallery-dl
Path: blob/master/scripts/pyprint.py
5457 views
1
#!/usr/bin/env python3
2
# -*- coding: utf-8 -*-
3
4
# Copyright 2024-2025 Mike Fährmann
5
#
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License version 2 as
8
# published by the Free Software Foundation.
9
10
import re
11
12
13
def pyprint(obj, indent=0, sort=None, oneline=True, lmin=0, lmax=16):
14
15
if isinstance(obj, str):
16
if obj.startswith("lit:"):
17
return f'''{obj[4:]}'''
18
19
if "\\" in obj or obj.startswith("re:"):
20
prefix = "r"
21
else:
22
prefix = ""
23
24
quote_beg = quote_end = '"'
25
if "\n" in obj:
26
quote_beg = '"""\\\n'
27
quote_end = '\\\n"""'
28
elif '"' in obj:
29
obj = re.sub(r'(?<!\\)"', '\\"', obj)
30
31
return f'''{prefix}{quote_beg}{obj}{quote_end}'''
32
33
if isinstance(obj, bytes):
34
return f'''b"{str(obj)[2:-1]}"'''
35
36
if isinstance(obj, type):
37
if obj.__module__ == "builtins":
38
return f'''{obj.__name__}'''
39
40
name = obj.__module__.rpartition(".")[2]
41
if name[0].isdecimal():
42
name = f"_{name}"
43
return f'''{name}.{obj.__name__}'''
44
45
if isinstance(obj, dict):
46
if not obj:
47
return "{}"
48
if len(obj) == 1 and oneline:
49
key, value = next(iter(obj.items()))
50
return f'''{{"{key}": {pyprint(value, indent, sort)}}}'''
51
52
if sort:
53
if callable(sort):
54
lst = [(sort(key, value), key, value)
55
for key, value in obj.items()]
56
lst.sort()
57
obj = {key: value for _, key, value in lst}
58
else:
59
keys = list(obj)
60
keys.sort()
61
obj = {key: obj[key] for key in keys}
62
63
try:
64
keylen = max(kl for kl in map(len, obj) if kl <= lmax)
65
except Exception:
66
keylen = lmin
67
if keylen < lmin:
68
keylen = lmin
69
ws = " " * indent
70
71
lines = ["{"]
72
for key, value in obj.items():
73
if key.startswith("#blank-"):
74
lines.append("")
75
else:
76
lines.append(
77
f'''{ws} "{key}"'''
78
f'''{' '*(keylen - len(key))}: '''
79
f'''{pyprint(value, indent+4, sort)},'''
80
)
81
lines.append(f'''{ws}}}''')
82
return "\n".join(lines)
83
84
if isinstance(obj, list):
85
if not obj:
86
return "[]"
87
if len(obj) == 1 and oneline:
88
return f'''[{pyprint(obj[0], indent, sort)}]'''
89
90
ws = " " * indent
91
lines = ["["]
92
for value in obj:
93
lines.append(f'''{ws} {pyprint(value, indent+4, sort)},''')
94
lines.append(f'''{ws}]''')
95
return "\n".join(lines)
96
97
if isinstance(obj, tuple):
98
if not obj:
99
return "()"
100
if len(obj) == 1:
101
return f'''({pyprint(obj[0], indent, sort)},)'''
102
103
result = f'''({", ".join(pyprint(v, indent+4, sort) for v in obj)})'''
104
if len(result) < 80:
105
return result
106
107
ws = " " * indent
108
lines = ["("]
109
for value in obj:
110
lines.append(f'''{ws} {pyprint(value, indent+4, sort)},''')
111
lines.append(f'''{ws})''')
112
return "\n".join(lines)
113
114
if isinstance(obj, set):
115
if not obj:
116
return "set()"
117
return f'''{{{", ".join(pyprint(v, indent+4, sort) for v in obj)}}}'''
118
119
if obj.__class__.__name__ == "datetime":
120
if (off := obj.utcoffset()) is not None:
121
obj = obj.replace(tzinfo=None, microsecond=0) - off
122
elif obj.microsecond:
123
obj = obj.replace(microsecond=0)
124
return f'''"dt:{obj}"'''
125
126
return f'''{obj}'''
127
128