Skip to content

Commit 860b11f

Browse files
committed
feat: sys.displayhook, fix(py): repl now sets _
1 parent 417defd commit 860b11f

File tree

4 files changed

+70
-14
lines changed

4 files changed

+70
-14
lines changed

Python/intrinsics.nim

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
import ./sysmodule/attrs
3+
import ./call
4+
import ../Objects/[
5+
pyobject, exceptions,
6+
]
7+
import ../Include/internal/pycore_global_strings
8+
9+
# ******* Unary functions *******
10+
proc print_expr*(value: PyObject; res: var PyObject): PyBaseErrorObject =
11+
var hook: PyObject
12+
retIfExc PySys_GetAttr(pyID(displayhook), hook)
13+
res = call(hook, value)
14+
retIfExc res
15+
res = nil

Python/neval.nim

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@ import builtindict
88
import ../Objects/[pyobject, baseBundle, tupleobject, listobject, dictobject,
99
sliceobject, codeobject, frameobject, funcobject, cellobject,
1010
setobject, notimplementedobject, boolobjectImpl,
11-
exceptionsImpl, methodobject,
11+
exceptionsImpl,
1212
]
1313
import ../Objects/abstract/[dunder, number,]
1414
import ../Utils/utils
1515
import ./[
1616
neval_frame,
1717
pyimport,
18+
intrinsics,
1819
]
1920
export pyimport, neval_frame
2021

@@ -385,17 +386,10 @@ proc evalFrame*(f: PyFrameObject): PyObject =
385386

386387
of OpCode.PrintExpr:
387388
let top = sPop()
388-
if top.id != pyNone.id:
389-
# all object should have a repr method properly initialized in typeobject.nim
390-
let reprObj = top.pyType.magicMethods.repr(top)
391-
if reprObj.isThrownException:
392-
handleException(reprObj)
393-
394-
# todo: optimization - build a cache
395-
let printFunction = PyNimFuncObject(KeyError!bltinDict[newPyAscii"print"])
396-
let retObj = tpMagic(NimFunc, call)(printFunction, @[reprObj])
397-
if retObj.isThrownException:
398-
handleException(retObj)
389+
var unused: PyObject
390+
let retObj: PyBaseErrorObject = print_expr(top, unused)
391+
if not retObj.isNil:
392+
handleException(retObj)
399393

400394
of OpCode.LoadBuildClass:
401395
sPush KeyError!bltinDict[newPyAscii"__build_class__"]

Python/sysmodule.nim

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ implSysModuleMethod audit(eventObj: PyStrObject, *args):
2828
implSysModuleMethod excepthook(exctype: PyTypeObject, value: PyBaseErrorObject, traceback):
2929
excepthook(exctype, value, traceback)
3030
pyNone
31+
implSysModuleMethod displayhook(x): displayhook(x)
3132

3233
implSysModuleMethod get_int_max_str_digits(): newPyInt PySys_GetIntMaxStrDigits()
3334
implSysModuleMethod set_int_max_str_digits(*a, **kw):

Python/sysmodule/hooks.nim

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,53 @@
11

2-
import ../../Objects/[pyobjectBase, exceptions,]
2+
import ../../Objects/[
3+
pyobjectBase, exceptions,
4+
noneobject,
5+
stringobject,
6+
]
7+
import ../../Objects/pyobject_apis/[attrs, io]
38
import ../pythonrun/pyerr_display
4-
9+
import ../pyimport/utils
10+
import ../../Include/internal/pycore_global_strings
11+
import ../../Utils/[fileio,]
512

613
proc excepthook*(exctype: PyObject, value: PyBaseErrorObject, traceback: PyObject) =
714
PyErr_Display(nil, value, traceback)
15+
16+
proc displayhook_impl*(o: PyObject): PyBaseErrorObject =
17+
var builtins: PyObject
18+
retIfExc PyImport_GetModule(pyId(builtins), builtins)
19+
if builtins.isNil:
20+
return newRuntimeError newPyAscii"lost builtins module"
21+
retIfExc builtins
22+
23+
# Print value except if None
24+
# After printing, also assign to '_'
25+
# Before, set '_' to None to avoid recursion
26+
if o.isPyNone: return
27+
retIfExc PyObject_SetAttr(builtins, newPyAscii('_'), pyNone)
28+
29+
#TODO:sys.stdout
30+
#TODO:encoding
31+
#[
32+
var outf: PyObject
33+
retIfExc PySys_GetAttr(pyId(stdout), outf)
34+
if outf.isPyNone:
35+
return newRuntimeError newPyAscii"lost sys.stdout"
36+
let res = PyFile_WriteObject(o, outf)
37+
if res.ofPyUnicodeEncodeErrorObject:
38+
#[/* repr(o) is not encodable to sys.stdout.encoding with
39+
* sys.stdout.errors error handler (which is probably 'strict') */]#
40+
retIfExc sys_displayhook_unencodable(outf, o)
41+
retIfExc res
42+
retIfExc PyFile_WriteObject(newPyAscii('\n'), outf, Py_PRINT_RAW)
43+
]#
44+
45+
46+
let res = PyObject_Println(o, fileio.stdout)
47+
retIfExc res
48+
49+
retIfExc PyObject_SetAttr(builtins, newPyAscii('_'), o)
50+
51+
proc displayhook*(o: PyObject): PyObject =
52+
retIfExc displayhook_impl(o)
53+
return pyNone

0 commit comments

Comments
 (0)