1717# along with this library. If not, see <https://www.gnu.org/licenses/>.
1818#
1919# *****************************************************************************
20- import sys
20+ import inspect
2121import re
22- from pathlib import Path
22+ import sys
23+ import traceback
2324from collections import defaultdict
25+ from pathlib import Path
2426from typing import Union
25- import inspect
26- import line_profiler
27- import traceback
28-
29- from jpype import JClass , JImplements , JOverride , JString
3027
28+ import line_profiler
29+ import py5_tools
3130import stackprinter
31+ from jpype import JClass , JImplements , JOverride , JString
3232
33- import py5_tools
34- from . import reference
35- from . import custom_exceptions
33+ from . import custom_exceptions , reference
3634
37- _stackprinter_style = ' plaintext'
35+ _stackprinter_style = " plaintext"
3836# prune tracebacks to only show only show stack levels in the user's py5 code.
3937_prune_tracebacks = True
4038
4139_MODULE_INSTALL_DIR = str (Path (__file__ ).parent )
4240_PY5TOOLS_MODULE_INSTALL_DIR = str (Path (py5_tools .__file__ ).parent )
4341
4442_PY5_STATIC_CODE_FILENAME_REGEX = re .compile (
45- r'File "[^\"]*?_PY5_STATIC_(SETUP|SETTINGS|FRAMEWORK)_CODE_\.py", line \d+, in .*' )
43+ r'File "[^\"]*?_PY5_STATIC_(SETUP|SETTINGS|FRAMEWORK)_CODE_\.py", line \d+, in .*'
44+ )
4645
4746_EXCEPTION_MSGS = {
4847 ** custom_exceptions .CUSTOM_EXCEPTION_MSGS ,
4948}
5049
51- _JAVA_RUNTIMEEXCEPTION = JClass (' java.lang.RuntimeException' )
50+ _JAVA_RUNTIMEEXCEPTION = JClass (" java.lang.RuntimeException" )
5251
5352
5453def check_run_method_callstack ():
5554 for t in traceback .extract_stack ():
56- if t .filename == __file__ and t .name == ' run_method' :
55+ if t .filename == __file__ and t .name == " run_method" :
5756 return True
5857 else :
5958 return False
@@ -68,13 +67,12 @@ def _exception_msg(println, exc_type_name, exc_msg, py5info):
6867 return msg (exc_type_name , exc_msg , py5info )
6968 else :
7069 println (
71- f'unknown exception msg type for { exc_type_name } : { type (msg ).__name__ } ' ,
72- stderr = True )
70+ f"unknown exception msg type for { exc_type_name } : { type (msg ).__name__ } " ,
71+ stderr = True ,
72+ )
7373 return exc_msg
7474 except Exception as e :
75- println (
76- f'error generating exception msg for { exc_type_name } : { e } ' ,
77- stderr = True )
75+ println (f"error generating exception msg for { exc_type_name } : { e } " , stderr = True )
7876 return exc_msg
7977
8078
@@ -85,21 +83,38 @@ def register_exception_msg(exc_type_name: str, msg: Union[str, callable]):
8583def handle_exception (println , exc_type , exc_value , exc_tb ):
8684 py5info = []
8785 try :
88- if _prune_tracebacks and hasattr (exc_tb , ' tb_next' ):
86+ if _prune_tracebacks and hasattr (exc_tb , " tb_next" ):
8987 prev_tb = exc_tb
9088 trim_tb = None
9189 tb = exc_tb .tb_next
92- while hasattr (tb , ' tb_next' ) and hasattr (tb , ' tb_frame' ):
90+ while hasattr (tb , " tb_next" ) and hasattr (tb , " tb_frame" ):
9391 f_code = tb .tb_frame .f_code
9492 if f_code .co_filename .startswith (
95- _MODULE_INSTALL_DIR ) and not f_code .co_name .endswith ('py5_no_prune' ):
96- py5info .append ((Path (f_code .co_filename [(len (_MODULE_INSTALL_DIR ) + 1 ):]).parts ,
97- f_code .co_name ))
93+ _MODULE_INSTALL_DIR
94+ ) and not f_code .co_name .endswith ("py5_no_prune" ):
95+ py5info .append (
96+ (
97+ Path (
98+ f_code .co_filename [(len (_MODULE_INSTALL_DIR ) + 1 ) :]
99+ ).parts ,
100+ f_code .co_name ,
101+ )
102+ )
98103 if trim_tb is None :
99104 trim_tb = prev_tb
100- elif f_code .co_filename .startswith (_PY5TOOLS_MODULE_INSTALL_DIR ) and not f_code .co_name .endswith ('py5_no_prune' ):
101- py5info .append ((Path (f_code .co_filename [(
102- len (_PY5TOOLS_MODULE_INSTALL_DIR ) + 1 ):]).parts , f_code .co_name ))
105+ elif f_code .co_filename .startswith (
106+ _PY5TOOLS_MODULE_INSTALL_DIR
107+ ) and not f_code .co_name .endswith ("py5_no_prune" ):
108+ py5info .append (
109+ (
110+ Path (
111+ f_code .co_filename [
112+ (len (_PY5TOOLS_MODULE_INSTALL_DIR ) + 1 ) :
113+ ]
114+ ).parts ,
115+ f_code .co_name ,
116+ )
117+ )
103118 if trim_tb is None :
104119 trim_tb = prev_tb
105120 prev_tb = tb
@@ -108,28 +123,28 @@ def handle_exception(println, exc_type, exc_value, exc_tb):
108123 trim_tb .tb_next = None
109124 except Exception as e :
110125 println (
111- f' Exception thrown while examining error traceback: { str (e )} ' ,
112- stderr = True )
126+ f" Exception thrown while examining error traceback: { str (e )} " , stderr = True
127+ )
113128
114129 errmsg = stackprinter .format (
115130 thing = (exc_type , exc_value , exc_tb .tb_next ),
116- show_vals = ' line' ,
131+ show_vals = " line" ,
117132 style = _stackprinter_style ,
118- suppressed_paths = [r"lib/python.*?/site-packages/numpy/" ,
119- r"lib/python.*?/site-packages/py5/" ,
120- r"lib/python.*?/site-packages/py5tools/" ])
133+ suppressed_paths = [
134+ r"lib/python.*?/site-packages/numpy/" ,
135+ r"lib/python.*?/site-packages/py5/" ,
136+ r"lib/python.*?/site-packages/py5tools/" ,
137+ ],
138+ )
121139
122140 if _prune_tracebacks :
123141 errmsg = errmsg .replace (
124142 str (exc_value ),
125- _exception_msg (
126- println ,
127- exc_type .__name__ ,
128- str (exc_value ),
129- py5info ))
143+ _exception_msg (println , exc_type .__name__ , str (exc_value ), py5info ),
144+ )
130145
131146 while m := _PY5_STATIC_CODE_FILENAME_REGEX .search (errmsg ):
132- errmsg = errmsg [m .span ()[1 ]:]
147+ errmsg = errmsg [m .span ()[1 ] :]
133148 else :
134149 errmsg = "py5 encountered an error in your code:\n \n " + errmsg
135150
@@ -146,10 +161,18 @@ def _extract_py5_user_function_data(d: dict):
146161 continue
147162
148163 sig = inspect .signature (d [name ])
149- pargs_count = len ([p for p in sig .parameters .values () if p .kind in [
150- inspect .Parameter .POSITIONAL_ONLY , inspect .Parameter .POSITIONAL_OR_KEYWORD ]])
151- if pargs_count != len (
152- sig .parameters ) or pargs_count not in allowed_parg_count :
164+ pargs_count = len (
165+ [
166+ p
167+ for p in sig .parameters .values ()
168+ if p .kind
169+ in [
170+ inspect .Parameter .POSITIONAL_ONLY ,
171+ inspect .Parameter .POSITIONAL_OR_KEYWORD ,
172+ ]
173+ ]
174+ )
175+ if pargs_count != len (sig .parameters ) or pargs_count not in allowed_parg_count :
153176 continue
154177
155178 functions [name ] = d [name ]
@@ -158,9 +181,8 @@ def _extract_py5_user_function_data(d: dict):
158181 return functions , function_param_counts
159182
160183
161- @JImplements (' py5.core.Py5Bridge' )
184+ @JImplements (" py5.core.Py5Bridge" )
162185class Py5Bridge :
163-
164186 def __init__ (self , sketch ):
165187 self ._sketch = sketch
166188 self ._caller_locals = dict ()
@@ -173,7 +195,8 @@ def __init__(self, sketch):
173195 self ._current_running_method = None
174196 self ._is_terminated = False
175197
176- from .object_conversion import convert_to_python_types , convert_to_java_type
198+ from .object_conversion import convert_to_java_type , convert_to_python_types
199+
177200 self ._convert_to_python_types = convert_to_python_types
178201 self ._convert_to_java_type = convert_to_java_type
179202
@@ -189,9 +212,10 @@ def set_functions(self, functions, function_param_counts):
189212 def add_functions (self , functions , function_param_counts ):
190213 for name , f in functions .items ():
191214 self ._functions [name ] = f
192- if name == 'settings' :
193- self ._function_param_counts ['settings' ] = function_param_counts .get (
194- 'settings' , function_param_counts .get ('setup' ))
215+ if name == "settings" :
216+ self ._function_param_counts ["settings" ] = function_param_counts .get (
217+ "settings" , function_param_counts .get ("setup" )
218+ )
195219 else :
196220 self ._function_param_counts [name ] = function_param_counts [name ]
197221
@@ -208,13 +232,13 @@ def dump_stats(self):
208232 self ._profiler .print_stats ()
209233
210234 def add_pre_hook (self , method_name , hook_name , hook ):
211- if self ._is_terminated and hasattr (hook , ' sketch_terminated' ):
235+ if self ._is_terminated and hasattr (hook , " sketch_terminated" ):
212236 hook .sketch_terminated ()
213237 else :
214238 self ._pre_hooks [method_name ][hook_name ] = hook
215239
216240 def add_post_hook (self , method_name , hook_name , hook ):
217- if self ._is_terminated and hasattr (hook , ' sketch_terminated' ):
241+ if self ._is_terminated and hasattr (hook , " sketch_terminated" ):
218242 hook .sketch_terminated ()
219243 else :
220244 self ._post_hooks [method_name ][hook_name ] = hook
@@ -238,19 +262,21 @@ def remove_post_hook(self, method_name, hook_name):
238262 def terminate_hooks (self ):
239263 for method_name , hooks in self ._pre_hooks .items ():
240264 for hook_name , hook in list (hooks .items ()):
241- if hasattr (hook , ' sketch_terminated' ):
265+ if hasattr (hook , " sketch_terminated" ):
242266 hook .sketch_terminated ()
243267 self .remove_pre_hook (method_name , hook_name )
244268 for method_name , hooks in self ._post_hooks .items ():
245269 for hook_name , hook in list (hooks .items ()):
246- if hasattr (hook , ' sketch_terminated' ):
270+ if hasattr (hook , " sketch_terminated" ):
247271 hook .sketch_terminated ()
248272 self .remove_post_hook (method_name , hook_name )
249273
250274 @JOverride
251275 def get_function_list (self ):
252- return [JString (f'{ name } :{ self ._function_param_counts [name ]} ' )
253- for name in self ._functions .keys ()]
276+ return [
277+ JString (f"{ name } :{ self ._function_param_counts [name ]} " )
278+ for name in self ._functions .keys ()
279+ ]
254280
255281 @JOverride
256282 def terminate_sketch (self ):
@@ -268,8 +294,7 @@ def run_method(self, method_name, params):
268294 hook (self ._sketch )
269295
270296 # now run the actual method
271- self ._functions [method_name ](
272- * self ._convert_to_python_types (params ))
297+ self ._functions [method_name ](* self ._convert_to_python_types (params ))
273298
274299 # finally, post-hooks
275300 if method_name in self ._post_hooks :
@@ -285,14 +310,15 @@ def run_method(self, method_name, params):
285310
286311 def _get_current_running_method (self ):
287312 return self ._current_running_method
313+
288314 current_running_method = property (fget = _get_current_running_method )
289315
290316 @JOverride
291317 def call_function (self , key , params ):
292318 try :
293319 key = str (key )
294- * str_hierarchy , c = key .split ('.' )
295- key_start = key .split ('.' )[0 ]
320+ * str_hierarchy , c = key .split ("." )
321+ key_start = key .split ("." )[0 ]
296322
297323 if key_start in py5_tools .config ._PY5_PROCESSING_MODE_KEYS :
298324 d = py5_tools .config ._PY5_PROCESSING_MODE_KEYS
@@ -301,32 +327,29 @@ def call_function(self, key, params):
301327 elif key_start in self ._caller_globals :
302328 d = self ._caller_globals
303329 else :
304- return _JAVA_RUNTIMEEXCEPTION (
305- f'callable { c } not found with key { key } ' )
330+ return _JAVA_RUNTIMEEXCEPTION (f"callable { c } not found with key { key } " )
306331
307332 for s in str_hierarchy :
308333 if s in d :
309334 subd = d [s ]
310335 if isinstance (subd , dict ):
311336 d = subd
312- elif hasattr (subd , ' __dir__' ) or hasattr (subd , ' __dict__' ):
337+ elif hasattr (subd , " __dir__" ) or hasattr (subd , " __dict__" ):
313338 d = {k : getattr (subd , k ) for k in dir (subd )}
314339 else :
315340 return _JAVA_RUNTIMEEXCEPTION (
316- f'{ s } in key { key } does not map to a dict or an object that can be inspected with dir()' )
341+ f"{ s } in key { key } does not map to a dict or an object that can be inspected with dir()"
342+ )
317343 else :
318- return _JAVA_RUNTIMEEXCEPTION (
319- f'{ s } not found with key { key } ' )
344+ return _JAVA_RUNTIMEEXCEPTION (f"{ s } not found with key { key } " )
320345
321346 if c not in d or not callable (func := d [c ]):
322- return _JAVA_RUNTIMEEXCEPTION (
323- f'callable { c } not found with key { key } ' )
347+ return _JAVA_RUNTIMEEXCEPTION (f"callable { c } not found with key { key } " )
324348
325349 try :
326350 retval = func (* self ._convert_to_python_types (params ))
327351 if key in py5_tools .config ._PY5_PROCESSING_MODE_CALLBACK_ONCE :
328- py5_tools .config ._PY5_PROCESSING_MODE_CALLBACK_ONCE .remove (
329- key )
352+ py5_tools .config ._PY5_PROCESSING_MODE_CALLBACK_ONCE .remove (key )
330353 if key in py5_tools .config ._PY5_PROCESSING_MODE_KEYS :
331354 py5_tools .config ._PY5_PROCESSING_MODE_KEYS .pop (key )
332355 return self ._convert_to_java_type (retval )
@@ -347,6 +370,4 @@ def shutdown(self):
347370 self ._is_terminated = True
348371 self .terminate_hooks ()
349372 except Exception :
350- self ._sketch .println (
351- 'exception in sketch shutdown sequence' ,
352- stderr = True )
373+ self ._sketch .println ("exception in sketch shutdown sequence" , stderr = True )
0 commit comments