Skip to content

Commit ac1af40

Browse files
author
Christopher Doris
committed
more conversions
1 parent ac0a297 commit ac1af40

File tree

13 files changed

+289
-112
lines changed

13 files changed

+289
-112
lines changed

src/PyException.jl

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -140,28 +140,21 @@ function Base.showerror(io::IO, e::PyException)
140140
try
141141
@py ```
142142
import traceback
143-
$(fs :: C.PyObjectRef) = fs = traceback.extract_tb($(e.bref))
144-
$(nfs :: Int) = len(fs)
143+
$(fs :: Vector{Tuple{String, String, Int}}) = [(x.name, x.filename, x.lineno) for x in traceback.extract_tb($(e.bref))]
145144
```
146-
try
147-
for i in 1:nfs
148-
@py ```
149-
f = $(fs)[$(i-1)]
150-
$(name::String) = f.name
151-
$(fname::String) = f.filename
152-
$(lineno::Int) = f.lineno
153-
```
154-
println(io)
155-
printstyled(io, " [", i, "] ")
156-
printstyled(io, name, bold=true)
157-
printstyled(io, " at ")
158-
printstyled(io, fname, ":", lineno, bold=true)
159-
end
160-
finally
161-
C.Py_DecRef(fs)
145+
for (i,(name, fname, lineno)) in enumerate(fs)
146+
println(io)
147+
printstyled(io, " [", i, "] ")
148+
printstyled(io, name, bold=true)
149+
printstyled(io, " at ")
150+
# if (m=match(r"^(.*):([0-9]+)$", fname)) !== nothing
151+
# fname = m.captures[1]
152+
# lineno += parse(Int, m.captures[2]) - 1
153+
# end
154+
printstyled(io, fname, ":", lineno, bold=true)
162155
end
163-
catch
164-
print(io, "<error while printing stacktrace>")
156+
catch err
157+
print(io, "<error while printing stacktrace: $err>")
165158
end
166159
end
167160
end

src/builtins.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ export pyrepr
128128
129129
Equivalent to `str(x)` in Python.
130130
"""
131-
pystr(::Type{T}, x) where {T} = cpyop(T, C.PyObject_Repr, x)
131+
pystr(::Type{T}, x) where {T} = cpyop(T, C.PyObject_Str, x)
132132
pystr(x) = pystr(PyObject, x)
133133
export pystr
134134

src/cpython/CPython.jl

Lines changed: 61 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ include("dict.jl")
4747
include("set.jl")
4848
include("buffer.jl")
4949
include("collections.jl")
50+
include("range.jl")
5051

5152
__init__() = begin
5253
PyObject_TryConvert_AddRules("builtins.NoneType", [
@@ -56,30 +57,36 @@ __init__() = begin
5657
PyObject_TryConvert_AddRules("builtins.bool", [
5758
(Bool, PyBool_TryConvertRule_bool, 100),
5859
])
59-
PyObject_TryConvert_AddRules("builtins.int", [
60-
(Integer, PyLong_TryConvertRule_integer, 100),
61-
(Rational, PyLong_TryConvertRule_tryconvert),
62-
(Real, PyLong_TryConvertRule_tryconvert),
63-
(Number, PyLong_TryConvertRule_tryconvert),
64-
(Any, PyLong_TryConvertRule_tryconvert),
60+
PyObject_TryConvert_AddRules("numbers.Integral", [
61+
(Integer, PyLongable_TryConvertRule_integer, 100),
62+
(Rational, PyLongable_TryConvertRule_tryconvert),
63+
(Real, PyLongable_TryConvertRule_tryconvert),
64+
(Number, PyLongable_TryConvertRule_tryconvert),
65+
(Any, PyLongable_TryConvertRule_tryconvert),
6566
])
6667
PyObject_TryConvert_AddRules("builtins.float", [
67-
(Float64, PyFloat_TryConvertRule_convert, 100),
68-
(BigFloat, PyFloat_TryConvertRule_convert),
69-
(Float32, PyFloat_TryConvertRule_convert),
70-
(Float16, PyFloat_TryConvertRule_convert),
71-
(AbstractFloat, PyFloat_TryConvertRule_tryconvert),
72-
(Real, PyFloat_TryConvertRule_tryconvert),
73-
(Number, PyFloat_TryConvertRule_tryconvert),
68+
(Float64, PyFloatable_TryConvertRule_convert, 100)
69+
])
70+
PyObject_TryConvert_AddRules("numbers.Real", [
71+
(Float64, PyFloatable_TryConvertRule_convert),
72+
(BigFloat, PyFloatable_TryConvertRule_convert),
73+
(Float32, PyFloatable_TryConvertRule_convert),
74+
(Float16, PyFloatable_TryConvertRule_convert),
75+
(AbstractFloat, PyFloatable_TryConvertRule_tryconvert),
76+
(Real, PyFloatable_TryConvertRule_tryconvert),
77+
(Number, PyFloatable_TryConvertRule_tryconvert),
7478
])
7579
PyObject_TryConvert_AddRules("builtins.complex", [
76-
(Complex{Float64}, PyComplex_TryConvertRule_convert, 100),
77-
(Complex{BigFloat}, PyComplex_TryConvertRule_convert),
78-
(Complex{Float32}, PyComplex_TryConvertRule_convert),
79-
(Complex{Float16}, PyComplex_TryConvertRule_convert),
80-
(Complex{T} where {T<:AbstractFloat}, PyComplex_TryConvertRule_tryconvert),
81-
(Complex{T} where {T<:Real}, PyComplex_TryConvertRule_tryconvert),
82-
(Number, PyComplex_TryConvertRule_tryconvert),
80+
(Complex{Float64}, PyComplexable_TryConvertRule_convert, 100),
81+
])
82+
PyObject_TryConvert_AddRules("numbers.Complex", [
83+
(Complex{Float64}, PyComplexable_TryConvertRule_convert),
84+
(Complex{BigFloat}, PyComplexable_TryConvertRule_convert),
85+
(Complex{Float32}, PyComplexable_TryConvertRule_convert),
86+
(Complex{Float16}, PyComplexable_TryConvertRule_convert),
87+
(Complex{T} where {T<:AbstractFloat}, PyComplexable_TryConvertRule_tryconvert),
88+
(Complex{T} where {T<:Real}, PyComplexable_TryConvertRule_tryconvert),
89+
(Number, PyComplexable_TryConvertRule_tryconvert),
8390
])
8491
PyObject_TryConvert_AddRules("builtins.bytes", [
8592
(Vector{UInt8}, PyBytes_TryConvertRule_vector),
@@ -96,6 +103,10 @@ __init__() = begin
96103
PyObject_TryConvert_AddRules("builtins.tuple", [
97104
(Tuple, PyIterable_ConvertRule_tuple, 100),
98105
])
106+
PyObject_TryConvert_AddRules("builtins.range", [
107+
(StepRange{T,S} where {T<:Integer, S<:Integer}, PyRange_TryConvertRule_steprange, 100),
108+
(UnitRange{T} where {T<:Integer}, PyRange_TryConvertRule_unitrange),
109+
])
99110
PyObject_TryConvert_AddRules("collections.abc.Iterable", [
100111
(Vector, PyIterable_ConvertRule_vector),
101112
(Set, PyIterable_ConvertRule_set),
@@ -112,13 +123,37 @@ __init__() = begin
112123
(Dict, PyMapping_ConvertRule_dict),
113124
])
114125
PyObject_TryConvert_AddExtraTypes([
115-
("collections.abc.Iterable", PyIterableABC_SubclassCheck),
116-
("collections.abc.Callable", PyCallableABC_SubclassCheck),
117-
("collections.abc.Sequence", PySequenceABC_SubclassCheck),
118-
("collections.abc.Mapping", PyMappingABC_SubclassCheck),
119-
("collections.abc.Set", PySetABC_SubclassCheck),
120-
("builtins.bufferable", PyType_CheckBuffer),
126+
PyIterableABC_Type,
127+
PyCallableABC_Type,
128+
PySequenceABC_Type,
129+
PyMappingABC_Type,
130+
PySetABC_Type,
131+
PyNumberABC_Type,
132+
PyComplexABC_Type,
133+
PyRealABC_Type,
134+
PyRationalABC_Type,
135+
PyIntegralABC_Type,
121136
])
137+
### Numpy
138+
# These aren't necessary but exist just to preserve the datatype.
139+
# TODO: Access these types directly.
140+
# TODO: Compound types?
141+
PyObject_TryConvert_AddRule("numpy.int8", Int8, PyLongable_TryConvertRule_integer, 100)
142+
PyObject_TryConvert_AddRule("numpy.int16", Int16, PyLongable_TryConvertRule_integer, 100)
143+
PyObject_TryConvert_AddRule("numpy.int32", Int32, PyLongable_TryConvertRule_integer, 100)
144+
PyObject_TryConvert_AddRule("numpy.int64", Int64, PyLongable_TryConvertRule_integer, 100)
145+
PyObject_TryConvert_AddRule("numpy.int128", Int128, PyLongable_TryConvertRule_integer, 100)
146+
PyObject_TryConvert_AddRule("numpy.uint8", UInt8, PyLongable_TryConvertRule_integer, 100)
147+
PyObject_TryConvert_AddRule("numpy.uint16", UInt16, PyLongable_TryConvertRule_integer, 100)
148+
PyObject_TryConvert_AddRule("numpy.uint32", UInt32, PyLongable_TryConvertRule_integer, 100)
149+
PyObject_TryConvert_AddRule("numpy.uint64", UInt64, PyLongable_TryConvertRule_integer, 100)
150+
PyObject_TryConvert_AddRule("numpy.uint128", UInt128, PyLongable_TryConvertRule_integer, 100)
151+
PyObject_TryConvert_AddRule("numpy.float16", Float16, PyFloatable_TryConvertRule_convert, 100)
152+
PyObject_TryConvert_AddRule("numpy.float32", Float32, PyFloatable_TryConvertRule_convert, 100)
153+
PyObject_TryConvert_AddRule("numpy.float64", Float64, PyFloatable_TryConvertRule_convert, 100)
154+
PyObject_TryConvert_AddRule("numpy.complex32", Complex{Float16}, PyComplexable_TryConvertRule_convert, 100)
155+
PyObject_TryConvert_AddRule("numpy.complex64", Complex{Float32}, PyComplexable_TryConvertRule_convert, 100)
156+
PyObject_TryConvert_AddRule("numpy.complex128", Complex{Float64}, PyComplexable_TryConvertRule_convert, 100)
122157
end
123158

124159
end

src/cpython/collections.jl

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ for n in [:Container, :Hashable, :Iterable, :Iterator, :Reversible, :Generator,
66
t = Symbol(p, :_Type)
77
tr = Symbol(p, :__ref)
88
c = Symbol(p, :_Check)
9-
ct = Symbol(p, :_SubclassCheck)
109
@eval const $tr = Ref(PyPtr())
1110
@eval $t() = begin
1211
ptr = $tr[]
@@ -18,18 +17,11 @@ for n in [:Container, :Hashable, :Iterable, :Iterator, :Reversible, :Generator,
1817
isnull(b) && return b
1918
$tr[] = b
2019
end
21-
@eval $c(_o) = GC.@preserve _o begin
22-
o = Base.unsafe_convert(PyPtr, _o)
20+
@eval $c(o) = begin
2321
t = $t()
2422
isnull(t) && return Cint(-1)
2523
PyObject_IsInstance(o, t)
2624
end
27-
@eval $ct(_o) = GC.@preserve _o begin
28-
o = Base.unsafe_convert(PyPtr, _o)
29-
t = $t()
30-
isnull(t) && return Cint(-1)
31-
PyObject_IsSubclass(o, t)
32-
end
3325
end
3426

3527
PyIterable_ConvertRule_vector(o, ::Type{T}, ::Type{S}) where {T, S<:Vector} = begin

src/cpython/complex.jl

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
@cdef :PyComplex_FromDoubles PyPtr (Cdouble, Cdouble)
22
@cdef :PyComplex_RealAsDouble Cdouble (PyPtr,)
33
@cdef :PyComplex_ImagAsDouble Cdouble (PyPtr,)
4+
@cdef :PyComplex_AsCComplex Py_complex (PyPtr,)
45

56
const PyComplex_Type__ref = Ref(PyPtr())
67
PyComplex_Type() = pyglobal(PyComplex_Type__ref, :PyComplex_Type)
@@ -9,23 +10,23 @@ PyComplex_Check(o) = Py_TypeCheck(o, PyComplex_Type())
910

1011
PyComplex_CheckExact(o) = Py_TypeCheckExact(o, PyComplex_Type())
1112

13+
PyComplex_AsComplex(o) = begin
14+
r = PyComplex_AsCComplex(o)
15+
Complex(r.real, r.imag)
16+
end
17+
1218
PyComplex_From(x::Union{Float16,Float32,Float64}) = PyComplex_FromDoubles(x, 0)
1319
PyComplex_From(x::Complex{<:Union{Float16,Float32,Float64}}) = PyComplex_FromDoubles(real(x), imag(x))
1420

15-
PyComplex_TryConvertRule_convert(o, ::Type{T}, ::Type{S}) where {T,S} = begin
16-
x = PyComplex_RealAsDouble(o)
21+
# "Complexable" means a 'complex' or anything with a '__complex__' method
22+
PyComplexable_TryConvertRule_convert(o, ::Type{T}, ::Type{S}) where {T,S} = begin
23+
x = PyComplex_AsComplex(o)
1724
ism1(x) && PyErr_IsSet() && return -1
18-
y = PyComplex_ImagAsDouble(o)
19-
ism1(y) && PyErr_IsSet() && return -1
20-
z = Complex(x, y)
21-
putresult(T, convert(S, z))
25+
putresult(T, convert(S, x))
2226
end
2327

24-
PyComplex_TryConvertRule_tryconvert(o, ::Type{T}, ::Type{S}) where {T,S} = begin
25-
x = PyComplex_RealAsDouble(o)
28+
PyComplexable_TryConvertRule_tryconvert(o, ::Type{T}, ::Type{S}) where {T,S} = begin
29+
x = PyComplexable_AsComplex(o)
2630
ism1(x) && PyErr_IsSet() && return -1
27-
y = PyComplex_ImagAsDouble(o)
28-
ism1(y) && PyErr_IsSet() && return -1
29-
z = Complex(x, y)
30-
putresult(T, tryconvert(S, z))
31+
putresult(T, tryconvert(S, x))
3132
end

src/cpython/float.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@ PyFloat_CheckExact(o) = Py_TypeCheckExact(o, PyFloat_Type())
1010

1111
PyFloat_From(o::Union{Float16,Float32,Float64}) = PyFloat_FromDouble(o)
1212

13-
PyFloat_TryConvertRule_convert(o, ::Type{T}, ::Type{S}) where {T,S} = begin
13+
# "Floatable" means a 'float' or anything with a '__float__' method
14+
PyFloatable_TryConvertRule_convert(o, ::Type{T}, ::Type{S}) where {T,S} = begin
1415
x = PyFloat_AsDouble(o)
1516
ism1(x) && PyErr_IsSet() && return -1
1617
putresult(T, convert(S, x))
1718
end
1819

19-
PyFloat_TryConvertRule_tryconvert(o, ::Type{T}, ::Type{S}) where {T,S} = begin
20+
PyFloatable_TryConvertRule_tryconvert(o, ::Type{T}, ::Type{S}) where {T,S} = begin
2021
x = PyFloat_AsDouble(o)
2122
ism1(x) && PyErr_IsSet() && return -1
2223
putresult(T, tryconvert(S, x))

src/cpython/int.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ PyLong_From(x::Integer) = begin
2727
PyLong_From(y::BigInt)
2828
end
2929

30-
PyLong_TryConvertRule_integer(o, ::Type{T}, ::Type{S}) where {T, S<:Integer} = begin
30+
# "Longable" means an 'int' or anything with an '__int__' method.
31+
PyLongable_TryConvertRule_integer(o, ::Type{T}, ::Type{S}) where {T, S<:Integer} = begin
3132
# first try to convert to Clonglong (or Culonglong if unsigned)
3233
x = S <: Unsigned ? PyLong_AsUnsignedLongLong(o) : PyLong_AsLongLong(o)
3334
if !ism1(x) || !PyErr_IsSet()
@@ -56,7 +57,7 @@ PyLong_TryConvertRule_integer(o, ::Type{T}, ::Type{S}) where {T, S<:Integer} = b
5657
end
5758
end
5859

59-
PyLong_TryConvertRule_tryconvert(o, ::Type{T}, ::Type{S}) where {T,S} = begin
60+
PyLongable_TryConvertRule_tryconvert(o, ::Type{T}, ::Type{S}) where {T,S} = begin
6061
r = PyLong_TryConvertRule_integer(o, Integer, Integer)
6162
r == 1 ? putresult(T, tryconvert(S, takeresult(Integer))) : r
6263
end

src/cpython/number.jl

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,26 @@
3232
@cdef :PyNumber_Long PyPtr (PyPtr,)
3333
@cdef :PyNumber_Float PyPtr (PyPtr,)
3434
@cdef :PyNumber_Index PyPtr (PyPtr,)
35+
36+
for n in [:Number, :Complex, :Real, :Rational, :Integral]
37+
p = Symbol(:Py, n, :ABC)
38+
t = Symbol(p, :_Type)
39+
tr = Symbol(p, :__ref)
40+
c = Symbol(p, :_Check)
41+
@eval const $tr = Ref(PyPtr())
42+
@eval $t() = begin
43+
ptr = $tr[]
44+
isnull(ptr) || return ptr
45+
a = PyImport_ImportModule("numbers")
46+
isnull(a) && return a
47+
b = PyObject_GetAttrString(a, $(string(n)))
48+
Py_DecRef(a)
49+
isnull(b) && return b
50+
$tr[] = b
51+
end
52+
@eval $c(o) = begin
53+
t = $t()
54+
isnull(t) && return Cint(-1)
55+
PyObject_IsInstance(o, t)
56+
end
57+
end

0 commit comments

Comments
 (0)