@@ -9,7 +9,7 @@ module PythonCallExt
99
1010import IJulia
1111using PythonCall
12-
12+ import PrecompileTools : @compile_workload
1313
1414# `_repr_mimebundle_()` is a standard in the IPython ecosystem for returning all
1515# the MIME's an object supports at once.
@@ -153,8 +153,11 @@ function manager_register_target(self, target_name, callback)
153153 target_name = pyconvert (String, target_name)
154154 comm_sym = Symbol (target_name)
155155
156- @eval function IJulia. CommManager. register_comm (comm:: IJulia.CommManager.Comm{$(QuoteNode(comm_sym))} , msg)
157- comm. on_msg = (msg) -> callback (comm, msg)
156+ if @ccall (jl_generating_output ():: Cint ) == 0
157+ # Only create the method if we aren't precompiling
158+ @eval function IJulia. CommManager. register_comm (comm:: IJulia.CommManager.Comm{$(QuoteNode(comm_sym))} , msg)
159+ comm. on_msg = (msg) -> callback (comm, msg)
160+ end
158161 end
159162 catch e
160163 @error " PyCommManager.register_target() failed" exception= (e, catch_backtrace ())
@@ -170,38 +173,46 @@ function IJulia.init_ipython()
170173 nothing
171174end
172175
176+ function create_pycomm ()
177+ pytype (" PyComm" , (), [
178+ " _comm" => nothing ,
179+ " comm_id" => pyproperty (; get= self -> self. _comm. id),
180+ pyfunc (pycomm_init; name= " __init__" ),
181+ pycomm_notimplemented (" publish_msg" ),
182+ pycomm_notimplemented (" open" ),
183+ pyfunc (pycomm_close; name= " close" ),
184+ pyfunc (pycomm_send; name= " send" ),
185+ pycomm_notimplemented (" on_close" ),
186+ pyfunc (pycomm_on_msg; name= " on_msg" ),
187+ pycomm_notimplemented (" handle_close" ),
188+ pycomm_notimplemented (" handle_msg" )
189+ ])
190+ end
191+
192+ function create_pycommmanager ()
193+ pytype (" PyCommManager" , (), [
194+ pyfunc (manager_register_target; name= " register_target" ),
195+ pycommmanager_notimplemented (" unregister_target" ),
196+ pycommmanager_notimplemented (" register_comm" ),
197+ pycommmanager_notimplemented (" unregister_comm" ),
198+ pycommmanager_notimplemented (" get_comm" ),
199+ pycommmanager_notimplemented (" comm_open" ),
200+ pycommmanager_notimplemented (" comm_msg" ),
201+ pycommmanager_notimplemented (" comm_close" ),
202+ ])
203+ end
204+
173205function IJulia. init_ipywidgets ()
174206 global PyComm
175207 global PyCommManager
176208
177209 IJulia. init_ipython ()
178210
179211 if isnothing (PyComm)
180- PyComm = pytype (" PyComm" , (), [
181- " _comm" => nothing ,
182- " comm_id" => pyproperty (; get= self -> self. _comm. id),
183- pyfunc (pycomm_init; name= " __init__" ),
184- pycomm_notimplemented (" publish_msg" ),
185- pycomm_notimplemented (" open" ),
186- pyfunc (pycomm_close; name= " close" ),
187- pyfunc (pycomm_send; name= " send" ),
188- pycomm_notimplemented (" on_close" ),
189- pyfunc (pycomm_on_msg; name= " on_msg" ),
190- pycomm_notimplemented (" handle_close" ),
191- pycomm_notimplemented (" handle_msg" )
192- ])
212+ PyComm = create_pycomm ()
193213 end
194214 if isnothing (PyCommManager)
195- PyCommManager = pytype (" PyCommManager" , (), [
196- pyfunc (manager_register_target; name= " register_target" ),
197- pycommmanager_notimplemented (" unregister_target" ),
198- pycommmanager_notimplemented (" register_comm" ),
199- pycommmanager_notimplemented (" unregister_comm" ),
200- pycommmanager_notimplemented (" get_comm" ),
201- pycommmanager_notimplemented (" comm_open" ),
202- pycommmanager_notimplemented (" comm_msg" ),
203- pycommmanager_notimplemented (" comm_close" ),
204- ])
215+ PyCommManager = create_pycommmanager ()
205216 end
206217
207218 comm = pyimport (" comm" )
@@ -214,7 +225,7 @@ function IJulia.init_ipywidgets()
214225 nothing
215226end
216227
217- function IJulia. init_matplotlib (backend= " ipympl" )
228+ function IJulia. init_matplotlib (backend:: String = " ipympl" )
218229 IJulia. init_ipywidgets ()
219230
220231 # Make sure it's in interactive mode and it's using the backend
@@ -241,4 +252,24 @@ precompile(pycomm_on_msg, (Py, Py))
241252precompile (pycomm_send, (Py, Py, Py, Py))
242253precompile (pycomm_close, (Py,))
243254
255+ @compile_workload begin
256+ create_pycomm ()
257+ create_pycommmanager ()
258+
259+ # If ipywidgets is installed in the environment try to precompile its
260+ # initializer. This is useful because the `ipywigets.register_comm_target()`
261+ # line is pretty heavy.
262+ try
263+ pyimport (" ipywidgets" )
264+ IJulia. init_ipywidgets ()
265+ catch ex
266+ if ! (ex isa PyException)
267+ @error " Ipywidgets precompilation failed" exception= (ex, catch_backtrace ())
268+ end
269+ finally
270+ global PyComm = nothing
271+ global PyCommManager = nothing
272+ end
273+ end
274+
244275end
0 commit comments