Skip to content

Commit 4486901

Browse files
author
Christopher Doris
committed
faster conversion
1 parent 13c0791 commit 4486901

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+1500
-843
lines changed

src/PyCode.jl

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
mutable struct PyCode
2+
ptr :: CPyPtr
3+
code :: String
4+
filename :: String
5+
mode :: Symbol
6+
function PyCode(code::String, filename::String, mode::Symbol)
7+
mode in (:exec, :eval) || error("invalid mode $(repr(mode))")
8+
o = new(CPyPtr(), code, filename, mode)
9+
finalizer(o) do o
10+
if CONFIG.isinitialized
11+
ptr = getfield(o, :ptr)
12+
if !isnull(ptr)
13+
with_gil(false) do
14+
C.Py_DecRef(ptr)
15+
end
16+
end
17+
end
18+
end
19+
return o
20+
end
21+
end
22+
export PyCode
23+
24+
function pyptr(co::PyCode)
25+
ptr = getfield(co, :ptr)
26+
if isnull(ptr)
27+
ptr = C.Py_CompileString(co.code, co.filename, co.mode == :exec ? C.Py_file_input : co.mode == :eval ? C.Py_eval_input : error("invalid mode $(repr(co.mode))"))
28+
if isnull(ptr)
29+
pythrow()
30+
else
31+
setfield!(co, :ptr, ptr)
32+
ptr
33+
end
34+
else
35+
ptr
36+
end
37+
end

src/PyDict.jl

Lines changed: 31 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,37 @@
1-
"""
2-
PyDict{K=PyObject, V=PyObject}(o=pydict())
3-
4-
Wrap the Python dictionary `o` (or anything satisfying the mapping interface) as a Julia dictionary with keys of type `K` and values of type `V`.
5-
"""
6-
struct PyDict{K,V} <: AbstractDict{K,V}
7-
o :: PyObject
8-
PyDict{K,V}(o::PyObject) where {K,V} = new{K,V}(o)
1+
mutable struct PyDict
2+
ptr :: CPyPtr
3+
hasbuiltins :: Bool
4+
function PyDict()
5+
o = new(CPyPtr(), false)
6+
finalizer(o) do o
7+
if CONFIG.isinitialized
8+
ptr = getfield(o, :ptr)
9+
if !isnull(ptr)
10+
with_gil(false) do
11+
C.Py_DecRef(ptr)
12+
end
13+
end
14+
end
15+
end
16+
return o
17+
end
918
end
10-
PyDict{K,V}(o=pydict()) where {K,V} = PyDict{K,V}(pydict(o))
11-
PyDict{K}(o=pydict()) where {K} = PyDict{K,PyObject}(o)
12-
PyDict(o=pydict()) = PyDict{PyObject}(o)
1319
export PyDict
1420

15-
pyobject(x::PyDict) = x.o
16-
17-
function Base.iterate(x::PyDict{K,V}, it=pyiter(x.o.items())) where {K,V}
18-
ptr = C.PyIter_Next(it)
19-
if ptr == C_NULL
20-
pyerrcheck()
21-
nothing
21+
const pyglobals = PyDict()
22+
export pyglobals
23+
24+
function pyptr(x::PyDict)
25+
ptr = getfield(x, :ptr)
26+
if isnull(ptr)
27+
ptr = C.PyDict_New()
28+
if isnull(ptr)
29+
pythrow()
30+
else
31+
setfield!(x, :ptr, ptr)
32+
ptr
33+
end
2234
else
23-
kv = pynewobject(ptr)
24-
(pyconvert(K, kv[0]) => pyconvert(V, kv[1])), it
35+
ptr
2536
end
2637
end
27-
28-
Base.setindex!(x::PyDict{K,V}, v, k) where {K,V} =
29-
(pysetitem(x.o, convert(K, k), convert(V, v)); x)
30-
31-
Base.getindex(x::PyDict{K,V}, k) where {K,V} =
32-
pyconvert(V, pygetitem(x.o, convert(K, k)))
33-
34-
Base.delete!(x::PyDict{K,V}, k) where {K,V} =
35-
(pydelitem(x.o, convert(K, k)); x)
36-
37-
Base.length(x::PyDict) = Int(pylen(x.o))
38-
39-
Base.empty!(x::PyDict) = (x.o.clear(); x)
40-
41-
Base.copy(x::PyDict) = typeof(x)(x.o.copy())
42-
43-
function Base.get(x::PyDict{K,V}, _k, d) where {K,V}
44-
k = convert(K, _k)
45-
pycontains(x.o, k) ? x[k] : d
46-
end
47-
48-
function Base.get(f::Function, x::PyDict{K,V}, _k) where {K,V}
49-
k = convert(K, _k)
50-
pycontains(x.o, k) ? x[k] : f()
51-
end
52-
53-
function Base.get!(x::PyDict{K,V}, _k, d) where {K,V}
54-
k = convert(K, _k)
55-
pycontains(x.o, k) ? x[k] : (x[k] = d)
56-
end
57-
58-
function Base.get!(f::Function, x::PyDict{K,V}, _k) where {K,V}
59-
k = convert(K, _k)
60-
pycontains(x.o, k) ? x[k] : (x[k] = f())
61-
end

src/PyException.jl

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
mutable struct PyException <: Exception
2+
tptr :: CPyPtr
3+
vptr :: CPyPtr
4+
bptr :: CPyPtr
5+
function PyException(::Val{:new}, t::Ptr=C_NULL, v::Ptr=C_NULL, b::Ptr=C_NULL, borrowed::Bool=false)
6+
o = new(CPyPtr(t), CPyPtr(v), CPyPtr(b))
7+
if borrowed
8+
C.Py_IncRef(t)
9+
C.Py_IncRef(v)
10+
C.Py_IncRef(b)
11+
end
12+
finalizer(o) do o
13+
if CONFIG.isinitialized
14+
tptr = getfield(o, :tptr)
15+
vptr = getfield(o, :vptr)
16+
bptr = getfield(o, :bptr)
17+
if !isnull(tptr) || !isnull(vptr) || !isnull(bptr)
18+
with_gil(false) do
19+
C.Py_DecRef(tptr)
20+
C.Py_DecRef(vptr)
21+
C.Py_DecRef(bptr)
22+
end
23+
end
24+
end
25+
end
26+
return o
27+
end
28+
end
29+
export PyException
30+
31+
pythrow() = throw(PyException(Val(:new), C.PyErr_FetchTuple()...))
32+
33+
function Base.showerror(io::IO, e::PyException)
34+
if isnull(e.tptr)
35+
print(io, "Python: mysterious error (no error was actually set)")
36+
return
37+
end
38+
39+
if CONFIG.sysautolasttraceback
40+
err = C.Py_DecRef(C.PyImport_ImportModule("sys"), PYERR()) do sys
41+
err = C.PyObject_SetAttrString(sys, "last_type", isnull(e.tptr) ? C.Py_None() : e.tptr)
42+
ism1(err) && return PYERR()
43+
err = C.PyObject_SetAttrString(sys, "last_value", isnull(e.vptr) ? C.Py_None() : e.vptr)
44+
ism1(err) && return PYERR()
45+
err = C.PyObject_SetAttrString(sys, "last_traceback", isnull(e.bptr) ? C.Py_None() : e.bptr)
46+
ism1(err) && return PYERR()
47+
nothing
48+
end
49+
if err == PYERR()
50+
C.PyErr_Clear()
51+
print(io, "<error while setting 'sys.last_traceback'>")
52+
end
53+
end
54+
55+
# # if this is a Julia exception then recursively print it and its stacktrace
56+
# if pyerrmatches(e.t, pyjlexception)
57+
# try
58+
# jp = pyjlgetvalue(e.v.args[0])
59+
# if jp !== nothing
60+
# je, jb = jp
61+
# print(io, "Python: Julia: ")
62+
# showerror(io, je)
63+
# if jb === nothing
64+
# println(io)
65+
# print(io, "Stacktrace: none")
66+
# else
67+
# io2 = IOBuffer()
68+
# Base.show_backtrace(IOContext(io2, :color=>true, :displaysize=>displaysize(io)), jb)
69+
# printstyled(io, String(take!(io2)))
70+
# end
71+
# end
72+
# if pyisnone(e.b)
73+
# println(io)
74+
# printstyled(io, "Python stacktrace: none")
75+
# return
76+
# else
77+
# @goto pystacktrace
78+
# end
79+
# catch err
80+
# println(io, "<error while printing Julia excpetion inside Python exception: $(err)>")
81+
# end
82+
# end
83+
84+
# otherwise, print the Python exception ****** TODO ******
85+
print(io, "Python: ")
86+
87+
# print the type name
88+
tname = C.Py_DecRef(C.PyObject_GetAttrString(e.tptr, "__name__")) do tnameo
89+
C.PyUnicode_As(tnameo, String)
90+
end
91+
if tname === PYERR()
92+
C.PyErr_Clear()
93+
print(io, "<error while printing type>")
94+
else
95+
print(io, tname)
96+
end
97+
98+
# print the error message
99+
if !isnull(e.vptr)
100+
print(io, ": ")
101+
vstr = C.PyObject_StrAs(e.vptr, String)
102+
if vstr === PYERR()
103+
C.PyErr_Clear()
104+
print(io, "<error while printing value>")
105+
else
106+
print(io, vstr)
107+
end
108+
end
109+
110+
# print the stacktrace
111+
if !isnull(e.bptr)
112+
@label pystacktrace
113+
println(io)
114+
printstyled(io, "Python stacktrace:")
115+
err = C.Py_DecRef(C.PyImport_ImportModule("traceback")) do tb
116+
C.Py_DecRef(C.PyObject_GetAttrString(tb, "extract_tb")) do extr
117+
C.Py_DecRef(C.PyObject_CallNice(extr, C.PyObjectRef(e.bptr))) do fs
118+
nfs = C.PySequence_Length(fs)
119+
ism1(nfs) && return PYERR()
120+
for i in 1:nfs
121+
println(io)
122+
printstyled(io, " [", i, "] ")
123+
# name
124+
err = C.Py_DecRef(C.PySequence_GetItem(fs, i-1)) do f
125+
name = C.Py_DecRef(C.PyObject_GetAttrString(f, "name")) do nameo
126+
C.PyObject_StrAs(nameo, String)
127+
end
128+
name === PYERR() && return PYERR()
129+
printstyled(io, name, bold=true)
130+
printstyled(io, " at ")
131+
fname = C.Py_DecRef(C.PyObject_GetAttrString(f, "filename")) do fnameo
132+
C.PyObject_StrAs(fnameo, String)
133+
end
134+
fname === PYERR() && return PYERR()
135+
printstyled(io, fname, ":", bold=true)
136+
lineno = C.Py_DecRef(C.PyObject_GetAttrString(f, "lineno")) do linenoo
137+
C.PyObject_StrAs(linenoo, String)
138+
end
139+
lineno === PYERR() && return PYERR()
140+
printstyled(io, lineno, bold=true)
141+
nothing
142+
end
143+
err === PYERR() && return PYERR()
144+
end
145+
end
146+
end
147+
end
148+
if err === PYERR()
149+
C.PyErr_Clear()
150+
print(io, "<error while printing stacktrace>")
151+
end
152+
end
153+
end

0 commit comments

Comments
 (0)