Skip to content

Commit ae96cb2

Browse files
author
Christopher Doris
committed
split Compat into independent modules
1 parent 194f171 commit ae96cb2

File tree

8 files changed

+90
-70
lines changed

8 files changed

+90
-70
lines changed

src/Compat/Compat.jl

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,5 @@
1-
"""
2-
module PythonCall.Compat
3-
4-
Misc bits and bobs for compatibility.
5-
"""
1+
"""Misc bits and bobs for compatibility."""
62
module Compat
7-
using ..PythonCall
8-
using ..Core
9-
using ..Core:
10-
Core,
11-
C,
12-
Utils,
13-
pynew,
14-
incref,
15-
getptr,
16-
pycopy!,
17-
pymodulehooks,
18-
pyisnull,
19-
pybytes_asvector,
20-
pysysmodule,
21-
pyosmodule,
22-
pystr_fromUTF8
23-
using ..Convert: pyconvert, @pyconvert
24-
using ..Wrap: PyArray, PyPandasDataFrame
25-
using Serialization: Serialization, AbstractSerializer, serialize, deserialize
26-
using Tables: Tables
27-
using Requires: @require
28-
import ..PythonCall: pytable, event_loop_on, event_loop_off, fix_qt_plugin_path
293

304
include("gui.jl")
315
include("ipython.jl")
@@ -34,10 +8,4 @@ include("serialization.jl")
348
include("tables.jl")
359
include("pycall.jl")
3610

37-
function __init__()
38-
init_gui()
39-
init_pyshow()
40-
init_tables()
41-
@require PyCall = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0" init_pycall(PyCall)
42-
end
4311
end

src/Compat/gui.jl

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
"""Integration with various GUI libraries"""
2+
module GUI
3+
4+
using ...PythonCall
5+
using ...C: C
6+
using ...Core: pynew, pyosmodule, pycopy!, pymodulehooks
7+
8+
import ...PythonCall: event_loop_on, event_loop_off, fix_qt_plugin_path
9+
110
"""
211
fix_qt_plugin_path()
312
@@ -58,7 +67,7 @@ const EVENT_LOOPS = Dict{Symbol,Base.Timer}()
5867

5968
const new_event_loop_callback = pynew()
6069

61-
function init_gui()
70+
function __init__()
6271
if !C.CTX.is_embedded
6372
# define callbacks
6473
g = pydict()
@@ -205,3 +214,5 @@ function _unset_python_input_hook()
205214
C.PyOS_SetInputHook(C_NULL)
206215
return
207216
end
217+
218+
end

src/Compat/ipython.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
"""Integration with IPython"""
2+
module IPython
3+
4+
using ...PythonCall
5+
using ...Core: pystr_fromUTF8
6+
17
"""
28
PythonDisplay()
39
@@ -68,3 +74,5 @@ function Base.display(d::IPythonDisplay, @nospecialize(x))
6874
ipy.display.display(dict, raw = true)
6975
return
7076
end
77+
78+
end

src/Compat/multimedia.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
### Extensible system for multimedia display of Python objects
1+
"""Extensible system for multimedia display of Python objects"""
2+
module Multimedia
3+
4+
using ...PythonCall
5+
using ...Core: pyisnull, pysysmodule
26

37
const PYSHOW_RULES = Function[]
48

@@ -124,7 +128,7 @@ function pyshow_rule_savefig(io::IO, mime::String, x::Py)
124128
end
125129
end
126130

127-
function init_pyshow()
131+
function __init__()
128132
pyshow_add_rule(pyshow_rule_mimebundle)
129133
pyshow_add_rule(pyshow_rule_repr)
130134
pyshow_add_rule(pyshow_rule_savefig)
@@ -150,3 +154,5 @@ Base.show(io::IO, mime::MIME"text/csv", df::PyPandasDataFrame) = pyshow(io, mime
150154
Base.show(io::IO, mime::MIME"text/tab-separated-values", df::PyPandasDataFrame) =
151155
pyshow(io, mime, df)
152156
Base.showable(mime::MIME, df::PyPandasDataFrame) = pyshowable(mime, df)
157+
158+
end

src/Compat/pycall.jl

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
"""Interoperability with PyCall.jl"""
2+
module PyCall
3+
4+
using ...PythonCall
5+
using ...C: C
6+
using ...Core: pynew
7+
8+
using Requires: @require
9+
110
function init_pycall(PyCall::Module)
211
# allow explicit conversion between PythonCall.Py and PyCall.PyObject
312
# provided they are using the same interpretr
@@ -10,7 +19,7 @@ function init_pycall(PyCall::Module)
1019
- Set the environment variable `PYTHON` to `PythonCall.C.CTX.exe_path` and rebuild PyCall. This forces PyCall
1120
to use the same interpreter as PythonCall, but needs to be repeated whenever you switch Julia environment.
1221
"""
13-
@eval function Core.Py(x::$PyCall.PyObject)
22+
@eval function PythonCall.Py(x::$PyCall.PyObject)
1423
C.CTX.matches_pycall::Bool || error($errmsg)
1524
return pynew(C.PyPtr($PyCall.pyreturn(x)))
1625
end
@@ -19,3 +28,9 @@ function init_pycall(PyCall::Module)
1928
return $PyCall.PyObject($PyCall.PyPtr(incref(getptr(x))))
2029
end
2130
end
31+
32+
function __init__()
33+
@require PyCall = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0" init_pycall(PyCall)
34+
end
35+
36+
end

src/Compat/serialization.jl

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,36 @@
1-
### Py
2-
#
3-
# We use pickle to serialise Python objects to bytes.
1+
module Serialization
2+
3+
using ...PythonCall
4+
using ...Core: pyisnull, pybytes_asvector, pynew
5+
6+
using Serialization: Serialization as S
47

58
_pickle_module() = pyimport(get(ENV, "JULIA_PYTHONCALL_PICKLE", "pickle"))
69

710
function serialize_py(s, x::Py)
811
if pyisnull(x)
9-
serialize(s, nothing)
12+
S.serialize(s, nothing)
1013
else
1114
b = _pickle_module().dumps(x)
12-
serialize(s, pybytes_asvector(b))
15+
S.serialize(s, pybytes_asvector(b))
1316
end
1417
end
1518

1619
function deserialize_py(s)
17-
v = deserialize(s)
20+
v = S.deserialize(s)
1821
if v === nothing
1922
pynew()
2023
else
2124
_pickle_module().loads(pybytes(v))
2225
end
2326
end
2427

25-
function Serialization.serialize(s::AbstractSerializer, x::Py)
26-
Serialization.serialize_type(s, Py, false)
28+
function S.serialize(s::S.AbstractSerializer, x::Py)
29+
S.serialize_type(s, Py, false)
2730
serialize_py(s, x)
2831
end
2932

30-
Serialization.deserialize(s::AbstractSerializer, ::Type{Py}) = deserialize_py(s)
33+
S.deserialize(s::S.AbstractSerializer, ::Type{Py}) = deserialize_py(s)
3134

3235
### PyException
3336
#
@@ -38,26 +41,27 @@ Serialization.deserialize(s::AbstractSerializer, ::Type{Py}) = deserialize_py(s)
3841
# This means the user can install something like "tblib" to enable pickling of tracebacks
3942
# and for free this enables serializing PyException including the traceback.
4043

41-
function Serialization.serialize(s::AbstractSerializer, x::PyException)
42-
Serialization.serialize_type(s, PyException, false)
44+
function S.serialize(s::S.AbstractSerializer, x::PyException)
45+
S.serialize_type(s, PyException, false)
4346
serialize_py(s, x.v)
4447
end
4548

46-
Serialization.deserialize(s::AbstractSerializer, ::Type{PyException}) =
47-
PyException(deserialize_py(s))
49+
S.deserialize(s::S.AbstractSerializer, ::Type{PyException}) = PyException(deserialize_py(s))
4850

4951
### PyArray
5052
#
5153
# This type holds a pointer and a handle (usually a python memoryview or capsule) which are
5254
# not serializable by default, and even if they were would not be consistent after
5355
# serializing each field independently. So we just serialize the wrapped Python object.
5456

55-
function Serialization.serialize(s::AbstractSerializer, x::PyArray)
56-
Serialization.serialize_type(s, typeof(x), false)
57+
function S.serialize(s::S.AbstractSerializer, x::PyArray)
58+
S.serialize_type(s, typeof(x), false)
5759
serialize_py(s, x.py)
5860
end
5961

60-
function Serialization.deserialize(s::AbstractSerializer, ::Type{T}) where {T<:PyArray}
62+
function S.deserialize(s::S.AbstractSerializer, ::Type{T}) where {T<:PyArray}
6163
# TODO: set buffer and array args too?
6264
T(deserialize_py(s); copy = false)
6365
end
66+
67+
end

src/Compat/tables.jl

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
module Tables
2+
3+
using ...PythonCall
4+
using Tables: Tables as T
5+
6+
using Requires: @require
7+
8+
import ...PythonCall: pytable
9+
10+
111
asvector(x::AbstractVector) = x
212
asvector(x) = collect(x)
313

@@ -27,44 +37,40 @@ function pytable(src, format = :pandas; opts...)
2737
end
2838
end
2939

30-
function _pytable_columns(src, cols = Tables.columns(src))
31-
pydict(
32-
pystr(String(n)) => asvector(Tables.getcolumn(cols, n)) for
33-
n in Tables.columnnames(cols)
34-
)
40+
function _pytable_columns(src, cols = T.columns(src))
41+
pydict(pystr(String(n)) => asvector(T.getcolumn(cols, n)) for n in T.columnnames(cols))
3542
end
3643

37-
function _pytable_rows(src, rows = Tables.rows(src))
38-
names = Tables.columnnames(rows)
44+
function _pytable_rows(src, rows = T.rows(src))
45+
names = T.columnnames(rows)
3946
t = pyimport("collections" => "namedtuple")(
4047
"Row",
4148
pylist(pystr(string(n)) for n in names),
4249
)
43-
pylist(t(map(n -> Tables.getcolumn(row, n), names)...) for row in rows)
50+
pylist(t(map(n -> T.getcolumn(row, n), names)...) for row in rows)
4451
end
4552

46-
function _pytable_rowdicts(src, rows = Tables.rows(src))
47-
names = Tables.columnnames(rows)
53+
function _pytable_rowdicts(src, rows = T.rows(src))
54+
names = T.columnnames(rows)
4855
pynames = [pystr(string(n)) for n in names]
4956
pylist(
50-
pydict(p => Tables.getcolumn(row, n) for (n, p) in zip(names, pynames)) for
51-
row in rows
57+
pydict(p => T.getcolumn(row, n) for (n, p) in zip(names, pynames)) for row in rows
5258
)
5359
end
5460

5561
aspandasvector(x) = asvector(x)
5662

57-
function _pytable_pandas(src, cols = Tables.columns(src); opts...)
63+
function _pytable_pandas(src, cols = T.columns(src); opts...)
5864
pyimport("pandas").DataFrame(
5965
pydict(
60-
pystr(string(n)) => aspandasvector(Tables.getcolumn(cols, n)) for
61-
n in Tables.columnnames(cols)
66+
pystr(string(n)) => aspandasvector(T.getcolumn(cols, n)) for
67+
n in T.columnnames(cols)
6268
);
6369
opts...,
6470
)
6571
end
6672

67-
function init_tables()
73+
function __init__()
6874
@require CategoricalArrays = "324d7699-5711-5eae-9e2f-1d82baa6b597" @eval begin
6975
aspandasvector(x::CategoricalArrays.CategoricalArray) = begin
7076
codes = map(x -> x === missing ? -1 : Int(CategoricalArrays.levelcode(x)) - 1, x)
@@ -74,3 +80,5 @@ function init_tables()
7480
end
7581
end
7682
end
83+
84+
end

test/Compat.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ end
2121
pystdout = sys.stdout
2222
fp = sys.stdout = io.StringIO()
2323
try
24-
d = PythonCall.Internals.Compat.PythonDisplay()
24+
d = PythonCall.Internals.Compat.IPython.PythonDisplay()
2525
@test display(d, 123) === nothing
2626
fp.seek(0)
2727
@test pyconvert(String, fp.read()) == "123\n"

0 commit comments

Comments
 (0)