forked from stanford-cs336/lectures
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexecute_util.py
More file actions
130 lines (105 loc) · 4.15 KB
/
execute_util.py
File metadata and controls
130 lines (105 loc) · 4.15 KB
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
"""
Functions such as (e.g., note, image, link) populate the list of renderings,
which will be shown in place of the line of code in the interface.
"""
import os
import inspect
import re
import subprocess
from file_util import cached, relativize
from dataclasses import dataclass
from arxiv_util import is_arxiv_link, arxiv_reference
from reference import Reference
@dataclass(frozen=True)
class CodeLocation:
"""Refers to a specific line of code."""
path: str
line_number: int
@dataclass(frozen=True)
class Rendering:
"""
Specifies what to display instead of a line of code. Types:
- text: plain text (verbatim)
- markdown: to be rendered as markdown
- image: an image (data = url)
- link: an link to internal code or external URL
"""
type: str
data: str | None = None
style: dict | None = None
external_link: Reference | None = None
internal_link: CodeLocation | None = None
############################################################
def text(message: str, style: dict | None = None, verbatim: bool = False):
"""Make a note (bullet point) with `message`."""
style = style or {}
if verbatim:
messages = message.split("\n")
style = {
"fontFamily": "monospace",
"whiteSpace": "pre",
**style
}
else:
messages = [message]
for message in messages:
_current_renderings.append(Rendering(type="markdown", data=message, style=style))
def image(url: str, style: dict | None = None, width: int | str | None = None):
"""Show the image at `url`."""
style = style or {}
if width is not None:
style["width"] = width
if is_url(url):
path = cached(url, "image")
else:
path = url
if not os.path.exists(path):
raise ValueError(f"Image not found: {path}")
_current_renderings.append(Rendering(type="image", data=path, style=style))
def is_url(url: str) -> bool:
"""Check if `url` looks like a URL."""
return url.startswith("http")
def link(arg: type | Reference | str | None = None, style: dict | None = None, **kwargs):
"""
Shows a link. There are four possible usages:
1. link(title="...", url="...") [Creates a new reference]
2. link(arg: Reference) [Shows an existing reference]
3. link(arg: type) [Shows a link to the code]
4. link(arg: str) [Creates a new reference with the given URL]
"""
style = style or {}
if arg is None:
reference = Reference(**kwargs)
_current_renderings.append(Rendering(type="link", style=style, external_link=reference))
elif isinstance(arg, Reference):
_current_renderings.append(Rendering(type="link", style=style, external_link=arg))
elif isinstance(arg, type) or callable(arg):
path = inspect.getfile(arg)
_, line_number = inspect.getsourcelines(arg)
anchor = CodeLocation(relativize(path), line_number)
_current_renderings.append(Rendering(type="link", data=arg.__name__, style=style, internal_link=anchor))
elif isinstance(arg, str):
if is_arxiv_link(arg):
reference = arxiv_reference(arg)
_current_renderings.append(Rendering(type="link", style=style, external_link=reference))
else:
reference = Reference(url=arg)
_current_renderings.append(Rendering(type="link", style=style, external_link=reference))
else:
raise ValueError(f"Invalid argument: {arg}")
style = {"color": "gray"}
############################################################
# Accumulate the renderings during execution (gets flushed).
_current_renderings: list[Rendering] = []
def pop_renderings() -> list[Rendering]:
"""Return the renderings and clear the list."""
renderings = _current_renderings.copy()
_current_renderings.clear()
return renderings
def system_text(command: list[str]):
output = subprocess.check_output(command).decode('utf-8')
output = remove_ansi_escape_sequences(output)
text(output, verbatim=True)
def remove_ansi_escape_sequences(input_text: str) -> str:
ansi_escape_pattern = re.compile(r'\x1b\[[0-9;]*m')
return ansi_escape_pattern.sub('', input_text)