8000 Add _pyrepl (#5540) · RustPython/RustPython@d96374f · GitHub
[go: up one dir, main page]

Skip to content

Commit d96374f

Browse files
authored
Add _pyrepl (#5540)
--------- Signed-off-by: Ashwin Naren <arihant2math@gmail.com>
1 parent 02533ac commit d96374f

27 files changed

+5521
-0
lines changed

.cspell.dict/python-more.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ asend
1212
asyncgen
1313
athrow
1414
backslashreplace
15+
baserepl
1516
basicsize
1617
bdfl
1718
bigcharset

Lib/_pyrepl/__init__.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Copyright 2000-2008 Michael Hudson-Doyle <micahel@gmail.com>
2+
# Armin Rigo
3+
#
4+
# All Rights Reserved
5+
#
6+
#
7+
# Permission to use, copy, modify, and distribute this software and
8+
# its documentation for any purpose is hereby granted without fee,
9+
# provided that the above copyright notice appear in all copies and
10+
# that both that copyright notice and this permission notice appear in
11+
# supporting documentation.
12+
#
13+
# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
14+
# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15+
# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
16+
# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
17+
# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
18+
# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
19+
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

Lib/_pyrepl/__main__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Important: don't add things to this module, as they will end up in the REPL's
2+
# default globals. Use _pyrepl.main instead.
3+
4+
if __name__ == "__main__":
5+
from .main import interactive_console as __pyrepl_interactive_console
6+
__pyrepl_interactive_console()

Lib/_pyrepl/_minimal_curses.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
"""Minimal '_curses' module, the low-level interface for curses module
2+
which is not meant to be used directly.
3+
4+
Based on ctypes. It's too incomplete to be really called '_curses', so
5+
to use it, you have to import it and stick it in sys.modules['_curses']
6+
manually.
7+
8+
Note that there is also a built-in module _minimal_curses which will
9+
hide this one if compiled in.
10+
"""
11+
12+
import ctypes
13+
import ctypes.util
14+
15+
16+
class error(Exception):
17+
pass
18+
19+
20+
def _find_clib() -> str:
21+
trylibs = ["ncursesw", "ncurses", "curses"]
22+
23+
for lib in trylibs:
24+
path = ctypes.util.find_library(lib)
25+
if path:
26+
return path
27+
raise ModuleNotFoundError("curses library not found", name="_pyrepl._minimal_curses")
28+
29+
30+
_clibpath = _find_clib()
31+
clib = ctypes.cdll.LoadLibrary(_clibpath)
32+
33+
clib.setupterm.argtypes = [ctypes.c_char_p, ctypes.c_int, ctypes.POINTER(ctypes.c_int)]
34+
clib.setupterm.restype = ctypes.c_int
35+
36+
clib.tigetstr.argtypes = [ctypes.c_char_p]
37+
clib.tigetstr.restype = ctypes.c_ssize_t
38+
39+
clib.tparm.argtypes = [ctypes.c_char_p] + 9 * [ctypes.c_int] # type: ignore[operator]
40+
clib.tparm.restype = ctypes.c_char_p
41+
42+
OK = 0
43+
ERR = -1
44+
45+
# ____________________________________________________________
46+
47+
48+
def setupterm(termstr, fd):
49+
err = ctypes.c_int(0)
50+
result = clib.setupterm(termstr, fd, ctypes.byref(err))
51+
if result == ERR:
52+
raise error("setupterm() failed (err=%d)" % err.value)
53+
54+
55+
def tigetstr(cap):
56+
if not isinstance(cap, bytes):
57+
cap = cap.encode("ascii")
58+
result = clib.tigetstr(cap)
59+
if result == ERR:
60+
return None
61+
return ctypes.cast(result, ctypes.c_char_p).value
62+
63+
64+
def tparm(str, i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0, i8=0, i9=0):
65+
result = clib.tparm(str, i1, i2, i3, i4, i5, i6, i7, i8, i9)
66+
if result is None:
67+
raise error("tparm() returned NULL")
68+
return result

Lib/_pyrepl/_threading_handler.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
from __future__ import annotations
2+
3+
from dataclasses import dataclass, field
4+
import traceback
5+
6+
7+
TYPE_CHECKING = False
8+
if TYPE_CHECKING:
9+
from threading import Thread
10+
from types import TracebackType
11+
from typing import Protocol
12+
13+
class ExceptHookArgs(Protocol):
14+
@property
15+
def exc_type(self) -> type[BaseException]: ...
16+
@property
17+
def exc_value(self) -> BaseException | None: ...
18+
@property
19+
def exc_traceback(self) -> TracebackType | None: ...
20+
@property
21+
def thread(self) -> Thread | None: ...
22+
23+
class ShowExceptions(Protocol):
24+
def __call__(self) -> int: ...
25+
def add(self, s: str) -> None: ...
26+
27+
from .reader import Reader
28+
29+
30+
def install_threading_hook(reader: Reader) -> None:
31+
import threading
32+
33+
@dataclass
34+
class ExceptHookHandler:
35+
lock: threading.Lock = field(default_factory=threading.Lock)
36+
messages: list[str] = field(default_factory=list)
37+
38+
def show(self) -> int:
39+
count = 0
40+
with self.lock:
41+
if not self.messages:
42+
return 0
43+
reader.restore()
44+
for tb in self.messages:
45+
count += 1
46+
if tb:
47+
print(tb)
48+
self.messages.clear()
49+
reader.scheduled_commands.append("ctrl-c")
50+
reader.prepare()
51+
return count
52+
53+
def add(self, s: str) -> None:
54+
with self.lock:
55+
self.messages.append(s)
56+
57+
def exception(self, args: ExceptHookArgs) -> None:
58+
lines = traceback.format_exception(
59+
args.exc_type,
60+
args.exc_value,
61+
args.exc_traceback,
62+
colorize=reader.can_colorize,
63+
) # type: ignore[call-overload]
64+
pre = f"\nException in {args.thread.name}:\n" if args.thread else "\n"
65+
tb = pre + "".join(lines)
66+
self.add(tb)
67+
68+
def __call__(self) -> int:
69+
return self.show()
70+
71+
72+
handler = ExceptHookHandler()
73+
reader.threading_hook = handler
74+
threading.excepthook = handler.exception

0 commit comments

Comments
 (0)
0