@@ -61,17 +61,14 @@ def option(name, default=None, xkey=None, envkey=None):
6161 v = os .getenv (k )
6262 if v is not None :
6363 return v , f'{ k } ={ v } '
64- return default , f'<default>={ v } '
64+ return default , f'<default>={ default } '
6565
6666 def choice (name , choices , default = None , ** kw ):
6767 v , s = option (name , ** kw )
6868 if v is None :
6969 return default , s
7070 if v in choices :
71- if isinstance (choices , dict ):
72- return choices [v ], s
73- else :
74- return v , s
71+ return v , s
7572 raise ValueError (
7673 f'{ s } : expecting one of { ", " .join (choices )} ' )
7774
@@ -113,7 +110,7 @@ def args_from_config():
113110 return
114111
115112 # Parse some more options
116- CONFIG ['opt_home' ] = path_option ('home' , check_exists = True , envkey = 'PYTHON_JULIACALL_BINDIR' )[0 ]
113+ CONFIG ['opt_home' ] = bindir = path_option ('home' , check_exists = True , envkey = 'PYTHON_JULIACALL_BINDIR' )[0 ]
117114 CONFIG ['opt_check_bounds' ] = choice ('check_bounds' , ['yes' , 'no' , 'auto' ])[0 ]
118115 CONFIG ['opt_compile' ] = choice ('compile' , ['yes' , 'no' , 'all' , 'min' ])[0 ]
119116 CONFIG ['opt_compiled_modules' ] = choice ('compiled_modules' , ['yes' , 'no' ])[0 ]
@@ -122,7 +119,7 @@ def args_from_config():
122119 CONFIG ['opt_min_optlevel' ] = choice ('min_optlevel' , ['0' , '1' , '2' , '3' ])[0 ]
123120 CONFIG ['opt_optimize' ] = choice ('optimize' , ['0' , '1' , '2' , '3' ])[0 ]
124121 CONFIG ['opt_procs' ] = int_option ('procs' , accept_auto = True )[0 ]
125- CONFIG ['opt_sysimage' ] = path_option ('sysimage' , check_exists = True )[0 ]
122+ CONFIG ['opt_sysimage' ] = sysimg = path_option ('sysimage' , check_exists = True )[0 ]
126123 CONFIG ['opt_threads' ] = int_option ('threads' , accept_auto = True )[0 ]
127124 CONFIG ['opt_warn_overwrite' ] = choice ('warn_overwrite' , ['yes' , 'no' ])[0 ]
128125
@@ -150,27 +147,44 @@ def args_from_config():
150147 # Open the library
151148 os .chdir (os .path .dirname (libpath ))
152149 CONFIG ['lib' ] = lib = c .CDLL (libpath , mode = c .RTLD_GLOBAL )
153- lib . jl_init__threading . argtypes = []
154- lib . jl_init__threading . restype = None
150+
151+ # parse options
155152 argc , argv = args_from_config ()
156- lib .jl_parse_opts (c .pointer (argc ), c .pointer (argv ))
153+ jl_parse_opts = lib .jl_parse_opts
154+ jl_parse_opts .argtypes = [c .c_void_p , c .c_void_p ]
155+ jl_parse_opts .restype = None
156+ jl_parse_opts (c .pointer (argc ), c .pointer (argv ))
157157 assert argc .value == 0
158- lib .jl_init__threading ()
159- lib .jl_eval_string .argtypes = [c .c_char_p ]
160- lib .jl_eval_string .restype = c .c_void_p
161- os .environ ['JULIA_PYTHONCALL_LIBPTR' ] = str (c .pythonapi ._handle )
162- os .environ ['JULIA_PYTHONCALL_EXE' ] = sys .executable or ''
163- os .environ ['JULIA_PYTHONCALL_PROJECT' ] = project
164- os .environ ['JULIA_PYTHONCALL_INIT_JL' ] = os .path .join (os .path .dirname (__file__ ), 'init.jl' )
158+
159+ # initialise julia
160+ try :
161+ jl_init = lib .jl_init_with_image__threading
162+ except AttributeError :
163+ jl_init = lib .jl_init_with_image
164+ jl_init .argtypes = [c .c_char_p , c .c_char_p ]
165+ jl_init .restype = None
166+ jl_init (
167+ (os .path .dirname (exepath ) if bindir is None else bindir ).encode ('utf8' ),
168+ None if sysimg is None else sysimg .encode ('utf8' ),
169+ )
170+
171+ # initialise PythonCall
172+ jl_eval = lib .jl_eval_string
173+ jl_eval .argtypes = [c .c_char_p ]
174+ jl_eval .restype = c .c_void_p
175+ def jlstr (x ):
176+ return 'raw"' + x .replace ('"' , '\\ "' ).replace ('\\ ' , '\\ \\ ' ) + '"'
165177 script = '''
166178 try
167179 import Pkg
168- Pkg.activate(ENV["JULIA_PYTHONCALL_PROJECT"], io=devnull)
180+ ENV["JULIA_PYTHONCALL_LIBPTR"] = {}
181+ ENV["JULIA_PYTHONCALL_EXE"] = {}
182+ Pkg.activate({}, io=devnull)
169183 import PythonCall
170184 # This uses some internals, but Base._start() gets the state more like Julia
171185 # is if you call the executable directly, in particular it creates workers when
172186 # the --procs argument is given.
173- push!(Core.ARGS, ENV["JULIA_PYTHONCALL_INIT_JL"] )
187+ push!(Core.ARGS, {} )
174188 Base._start()
175189 @eval Base PROGRAM_FILE=""
176190 catch err
@@ -179,8 +193,13 @@ def args_from_config():
179193 flush(stderr)
180194 rethrow()
181195 end
182- '''
183- res = lib .jl_eval_string (script .encode ('utf8' ))
196+ ''' .format (
197+ jlstr (str (c .pythonapi ._handle )),
198+ jlstr (sys .executable or '' ),
199+ jlstr (project ),
200+ jlstr (os .path .join (os .path .dirname (__file__ ), 'init.jl' )),
201+ )
202+ res = jl_eval (script .encode ('utf8' ))
184203 if res is None :
185204 raise Exception ('PythonCall.jl did not start properly' )
186205 finally :
0 commit comments