-
-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathmdf.py
157 lines (128 loc) · 4.94 KB
/
mdf.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import sys
import re
from io import StringIO
import inspect
import traceback
import contextlib
import subb
def header_md(line, nesting=1):
""" show argument string as markdown header. Nesting of level is set by nesting argument """
print( "\n" + ('#' * nesting) + " " + line + "\n")
def print_md(*args):
"""show text as a paragraph, as part of markdown file, quotes underscores, removes leading spaces"""
paragraph = " ".join(map(str, args))
paragraph = paragraph.replace('_', "\\_") #.replace('#','\\#')
paragraph = re.sub(r"^\s+","", paragraph)
print(paragraph)
def _quote_string(str):
return str.replace("<","<").replace(">",">")
def print_quoted(*args):
"""show arguments as quoted text in markdown"""
msg = '\n'.join(map(str, args))
print("```\n" + msg + "\n```" )
def print_quoted_pre(*args, quote_lt_gt):
"""show arguments as quoted text in markdown"""
msg = '\n'.join(map(str, args))
if quote_lt_gt:
msg = _quote_string(msg)
print("<pre>\n" + msg + "\n</pre>" )
def print_code(*args,lang="python"):
"""show arguments as quoted text in markdown"""
print(f"```{lang}\n" + '\n'.join(map(str, args)) + "\n```" )
def run_and_quote(file_name, command="python3", line_prefix="> ", exit_on_error=True, quote_lt_gt=False):
"""show contents of file name, run the file name with command and show results"""
print("")
print("__Source:__")
with open(file_name,"r") as file:
src_code = file.read()
print_code(src_code)
cmd_str = f"{command} {file_name}"
cmd = subb.RunCommand(stderr_as_stdout=True)
cmd.run(cmd_str)
out = cmd.output
sline = out.strip()
if sline != "":
print("")
print("__Result:__")
print_quoted_pre( '\n'.join( map( lambda line : line_prefix + line, sline.split("\n") ) ), quote_lt_gt=quote_lt_gt)
print("")
if exit_on_error and cmd.exit_code != 0:
print(f"Error: Command {cmd_str} returned status {cmd.exit_code}")
sys.exit(1)
def eval_and_quote(arg_str):
"""evaluate the argument string, show the source and show the results"""
print("")
print("__Source:__")
print_code(arg_str)
@contextlib.contextmanager
def stderr_io(stderr=None):
old = sys.stderr
if stderr is None:
stderr = StringIO()
sys.stderr = stderr
yield stderr
sys.stderr = old
@contextlib.contextmanager
def stdout_io(stdout=None):
old = sys.stdout
if stdout is None:
stdout = StringIO()
sys.stdout = stdout
yield stdout
sys.stdout = old
def format_result(out, is_first):
sline = out.getvalue().strip()
if sline != "":
print("")
if is_first:
print("__Result:__")
is_first = False
print_quoted( '\n'.join( map( lambda line : ">> " + line, sline.split("\n") ) ) )
print("")
return is_first
# from walk_tb in https://github.com/python/cpython/blob/f6648e229edf07a1e4897244d7d34989dd9ea647/Lib/traceback.py#L93
# don't know if that might break in the future
def show_custom_trace(code, ex):
code_lines = arg_str.split("\n")
te = traceback.TracebackException.from_exception(ex)
first_frame = True
for frame_summary in te.stack:
if not first_frame:
lineno = frame_summary.lineno
error_line = ""
if len(code_lines) > lineno -1:
error_line = code_lines[ lineno-1 ]
print(f"{frame_summary.name}")
print(f"\t{lineno}) {error_line}")
first_frame = False
frame = inspect.currentframe()
# get globals from calling frame...
calling_frame_globals = frame.f_back.f_globals
has_error = False
with stderr_io() as serr:
with stdout_io() as sout:
exc = None
try:
exec(arg_str, calling_frame_globals)
except SyntaxError as err:
# get error line
error_line = ""
code_lines = arg_str.split("\n")
if len(code_lines) > err.lineno -1:
error_line = code_lines[ err.lineno-1 ]
print("syntax error: ", err, "\n" + str(err.lineno-1) + ")", error_line)
has_error = True
except Exception as err:
print("Error in code. exception:", err)
exc = err
has_error = True
if exc is not None:
# this doesn't show the line that caused the exception
#traceback.print_exc()
show_custom_trace(arg_str, exc)
is_first = True
is_first = format_result(sout, is_first)
format_result(serr, is_first)
if has_error:
print("Error during evalutation of the preceeding code snippet, see standard output for more details.", file=sys.stderr)
sys.exit(1)