33
44__version__ = '0.9.1'
55
6- from ctypes import pointer , c_int , POINTER , c_char_p
7- from typing import Any
8-
96_newmodule = None
107
118def newmodule (name ):
@@ -50,52 +47,53 @@ def init():
5047 import sys
5148 import subprocess
5249
53- def option (name , default = None ):
50+ def option (name , default = None , xkey = None , envkey = None ):
5451 """Get an option.
5552
5653 Options can be set as command line arguments '-X juliacall_{name}={value}' or as
5754 environment variables 'PYTHON_JULIACALL_{NAME}={value}'.
5855 """
59- k = 'juliacall_' + name .lower ()
56+ k = xkey or 'juliacall_' + name .lower ()
6057 v = sys ._xoptions .get (k )
6158 if v is not None :
62- return v
63- k = 'PYTHON_JULIACALL_' + name .upper ()
59+ return v , f'-X { k } = { v } '
60+ k = envkey or 'PYTHON_JULIACALL_' + name .upper ()
6461 v = os .getenv (k )
6562 if v is not None :
66- return v
67- return default
63+ return v , f' { k } = { v } '
64+ return default , f'<default>= { v } '
6865
69- def choice (name , choices , default = None ):
70- v = option (name )
66+ def choice (name , choices , default = None , ** kw ):
67+ v , s = option (name , ** kw )
7168 if v is None :
72- return default
69+ return default , s
7370 if v in choices :
7471 if isinstance (choices , dict ):
75- return choices [v ]
72+ return choices [v ], s
7673 else :
77- return v
74+ return v , s
7875 raise ValueError (
79- f'invalid value for option: JULIACALL_ { name . upper () } = { v } , expecting one of { ", " .join (choices )} ' )
76+ f'{ s } : expecting one of { ", " .join (choices )} ' )
8077
81- def path_option (name , default = None ):
82- path = option (name )
78+ def path_option (name , default = None , check_exists = False , ** kw ):
79+ path , s = option (name , ** kw )
8380 if path is not None :
84- return os .path .abspath (path )
85- return default
81+ if check_exists and not os .path .exists (path ):
82+ raise ValueError (f'{ s } : path does not exist' )
83+ return os .path .abspath (path ), s
84+ return default , s
8685
87- def int_option (name , * , accept_auto = False ):
88- val = option (name )
86+ def int_option (name , * , accept_auto = False , ** kw ):
87+ val , s = option (name , ** kw )
8988 if val is None :
90- return None
89+ return None , s
9190 if accept_auto and val == "auto" :
92- return "auto"
91+ return "auto" , s
9392 try :
9493 int (val )
95- return val
94+ return val , s
9695 except ValueError :
97- raise ValueError (f'invalid value for option: JULIACALL_{ name .upper ()} ={ val } , '
98- f'expecting an int' + ' or auto' if accept_auto else "" )
96+ raise ValueError (f'{ s } : expecting an int' + (' or auto' if accept_auto else "" ))
9997
10098 def args_from_config ():
10199 argv = ["--" + opt [4 :].replace ("_" , "-" )+ "=" + val for opt , val in CONFIG .items ()
@@ -105,28 +103,28 @@ def args_from_config():
105103 argv = [s .encode ("utf-8" ) for s in argv ]
106104
107105 argc = len (argv )
108- c = c_int (argc )
109- v = POINTER (c_char_p )((c_char_p * len (argv ))(* argv ))
110- return c , v
106+ argc = c . c_int (argc )
107+ argv = c . POINTER (c . c_char_p )((c . c_char_p * len (argv ))(* argv ))
108+ return argc , argv
111109
112110 # Determine if we should skip initialising.
113- CONFIG ['init' ] = choice ('init' , ['yes' , 'no' ], default = 'yes' ) == 'yes'
111+ CONFIG ['init' ] = choice ('init' , ['yes' , 'no' ], default = 'yes' )[ 0 ] == 'yes'
114112 if not CONFIG ['init' ]:
115113 return
116114
117115 # Parse some more options
118- CONFIG ['opt_bindir ' ] = path_option ('bindir' )
119- CONFIG ['opt_check_bounds' ] = choice ('check_bounds' , ['yes' , 'no' , 'auto' ])
120- CONFIG ['opt_compile' ] = choice ('compile' , ['yes' , 'no' , 'all' , 'min' ])
121- CONFIG ['opt_compiled_modules' ] = choice ('compiled_modules' , ['yes' , 'no' ])
122- CONFIG ['opt_depwarn' ] = choice ('depwarn' , ['yes' , 'no' , 'error' ])
123- CONFIG ['opt_inline' ] = choice ('inline' , ['yes' , 'no' ])
124- CONFIG ['opt_min_optlevel' ] = choice ('min_optlevel' , ['0' , '1' , '2' , '3' ])
125- CONFIG ['opt_optimize' ] = choice ('optimize' , ['0' , '1' , '2' , '3' ])
126- CONFIG ['opt_procs' ] = int_option ('procs' , accept_auto = True )
127- CONFIG ['opt_sysimage' ] = path_option ('sysimage' )
128- CONFIG ['opt_threads' ] = int_option ('threads' , accept_auto = True )
129- CONFIG ['opt_warn_overwrite' ] = choice ('warn_overwrite' , ['yes' , 'no' ])
116+ CONFIG ['opt_home ' ] = path_option ('home' , check_exists = True , envkey = 'PYTHON_JULIACALL_BINDIR' )[ 0 ]
117+ CONFIG ['opt_check_bounds' ] = choice ('check_bounds' , ['yes' , 'no' , 'auto' ])[ 0 ]
118+ CONFIG ['opt_compile' ] = choice ('compile' , ['yes' , 'no' , 'all' , 'min' ])[ 0 ]
119+ CONFIG ['opt_compiled_modules' ] = choice ('compiled_modules' , ['yes' , 'no' ])[ 0 ]
120+ CONFIG ['opt_depwarn' ] = choice ('depwarn' , ['yes' , 'no' , 'error' ])[ 0 ]
121+ CONFIG ['opt_inline' ] = choice ('inline' , ['yes' , 'no' ])[ 0 ]
122+ CONFIG ['opt_min_optlevel' ] = choice ('min_optlevel' , ['0' , '1' , '2' , '3' ])[ 0 ]
123+ CONFIG ['opt_optimize' ] = choice ('optimize' , ['0' , '1' , '2' , '3' ])[ 0 ]
124+ CONFIG ['opt_procs' ] = int_option ('procs' , accept_auto = True )[ 0 ]
125+ CONFIG ['opt_sysimage' ] = path_option ('sysimage' , check_exists = True )[ 0 ]
126+ CONFIG ['opt_threads' ] = int_option ('threads' , accept_auto = True )[ 0 ]
127+ CONFIG ['opt_warn_overwrite' ] = choice ('warn_overwrite' , ['yes' , 'no' ])[ 0 ]
130128
131129 # Stop if we already initialised
132130 if CONFIG ['inited' ]:
@@ -155,7 +153,8 @@ def args_from_config():
155153 lib .jl_init__threading .argtypes = []
156154 lib .jl_init__threading .restype = None
157155 argc , argv = args_from_config ()
158- lib .jl_parse_opts (pointer (argc ), pointer (argv ))
156+ lib .jl_parse_opts (c .pointer (argc ), c .pointer (argv ))
157+ assert argc .value == 0
159158 lib .jl_init__threading ()
160159 lib .jl_eval_string .argtypes = [c .c_char_p ]
161160 lib .jl_eval_string .restype = c .c_void_p
0 commit comments