Skip to content

Commit 1767024

Browse files
committed
Get traceback working in wasm
1 parent 46a070f commit 1767024

6 files changed

Lines changed: 44 additions & 64 deletions

File tree

Lib/_dummy_os.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@
77
except ImportError:
88
import abc
99

10-
# this will throw an appropriate error if os isn't available and a module
11-
# tries to use an os function. If os has become available, then this will
12-
# just work.
1310
def __getattr__(name):
14-
import os
15-
return getattr(os, name)
11+
raise OSError("no os specific module found")
12+
13+
def _shim():
14+
import _dummy_os, sys
15+
sys.modules['os'] = _dummy_os
16+
sys.modules['os.path'] = _dummy_os.path
1617

1718
import posixpath as path
1819
import sys

Lib/linecache.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77

88
import functools
99
import sys
10-
import os
10+
try:
11+
import os
12+
except ImportError:
13+
import _dummy_os as os
1114
import tokenize
1215

1316
__all__ = ["getline", "clearcache", "checkcache"]

wasm/demo/snippets/import_pypi.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
import asyncweb
2-
import pypimport
2+
import whlimport
33

4-
pypimport.setup()
4+
whlimport.setup()
55

6-
# shim path utilities into the "os" module
7-
class os:
8-
import posixpath as path
9-
import sys
10-
sys.modules['os'] = os
11-
sys.modules['os.path'] = os.path
12-
del sys, os
6+
# make sys.modules['os'] a dumb version of the os module, which has posixpath
7+
# available as os.path as well as a few other utilities, but will raise an
8+
# OSError for anything that actually requires an OS
9+
import _dummy_os
10+
_dummy_os._shim()
1311

1412
@asyncweb.main
1513
async def main():
16-
await pypimport.load_package("pygments")
14+
await whlimport.load_package("pygments")
1715
import pygments
1816
import pygments.lexers
1917
import pygments.formatters.html

wasm/demo/src/browser_module.rs

Whitespace-only changes.

wasm/lib/Lib/asyncweb.py

Lines changed: 9 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -48,51 +48,16 @@ def main(async_func):
4848
async def _main_wrapper(coro):
4949
try:
5050
await coro
51-
except BaseException as e:
52-
for line in _format_exc(e, 1):
53-
print(line)
54-
55-
56-
# TODO: get traceback/linecache working in wasm
57-
58-
59-
def _format_exc(exc, skip_tb=0):
60-
exc_type, exc_value, exc_traceback = type(exc), exc, exc.__traceback__
61-
62-
_str = _some_str(exc_value)
63-
64-
yield "Traceback (most recent call last):"
65-
tb = exc_traceback
66-
while tb:
67-
if skip_tb:
68-
skip_tb -= 1
69-
else:
70-
co = tb.tb_frame.f_code
71-
yield f' File "{co.co_filename}", line {tb.tb_lineno}, in {co.co_name}'
72-
tb = tb.tb_next
73-
74-
stype = exc_type.__qualname__
75-
smod = exc_type.__module__
76-
if smod not in ("__main__", "builtins"):
77-
stype = smod + "." + stype
78-
79-
yield _format_final_exc_line(stype, _str)
80-
81-
82-
def _format_final_exc_line(etype, value):
83-
valuestr = _some_str(value)
84-
if value is None or not valuestr:
85-
line = "%s" % etype
86-
else:
87-
line = "%s: %s" % (etype, valuestr)
88-
return line
89-
90-
91-
def _some_str(value):
92-
try:
93-
return str(value)
9451
except:
95-
return "<unprintable %s object>" % type(value).__name__
52+
try:
53+
import traceback, sys
54+
traceback.print_exc(file=sys.stdout)
55+
except BaseException as e:
56+
tb = e.__traceback__
57+
while tb:
58+
print(tb.tb_lineno, tb.tb_frame.f_code.co_name, tb.tb_frame.f_code.co_filename)
59+
tb = tb.tb_next
60+
print(type(e), e)
9661

9762

9863
def _resolve(prom):

wasm/lib/Lib/whlimport.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,27 @@ def create_module(cls, spec):
7373
return None
7474

7575
@classmethod
76-
def exec_module(cls, module):
77-
origin = module.__spec__.origin
76+
def get_source(cls, fullname):
77+
spec = cls.find_spec(fullname)
78+
if spec:
79+
return cls._get_source(spec)
80+
else:
81+
raise ImportError('cannot find source for module', name=fullname)
82+
83+
@classmethod
84+
def _get_source(cls, spec):
85+
origin = spec.origin
7886
if not origin or not origin.startswith("wheel:"):
7987
raise ImportError(f'{module.__spec__.name!r} is not a zip module')
8088

8189
zipname, slash, path = origin[len('wheel:'):].partition('/')
82-
source = cls._packages[zipname].read(path)
83-
code = _bootstrap._call_with_frames_removed(compile, source, origin, 'exec', dont_inherit=True)
90+
return cls._packages[zipname].read(path).decode()
91+
92+
@classmethod
93+
def exec_module(cls, module):
94+
spec = module.__spec__
95+
source = cls._get_source(spec)
96+
code = _bootstrap._call_with_frames_removed(compile, source, spec.origin, 'exec', dont_inherit=True)
8497
_bootstrap._call_with_frames_removed(exec, code, module.__dict__)
8598

8699

0 commit comments

Comments
 (0)