Skip to content

Commit b806776

Browse files
committed
dev release
1 parent c10c2d4 commit b806776

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+6808
-4711
lines changed

py5/__init__.py

Lines changed: 2377 additions & 1894 deletions
Large diffs are not rendered by default.

py5/base.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
#
1919
# *****************************************************************************
2020
class Py5Base:
21-
2221
def __init__(self, instance):
2322
self._instance = instance
2423

py5/bridge.py

Lines changed: 93 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -17,43 +17,42 @@
1717
# along with this library. If not, see <https://www.gnu.org/licenses/>.
1818
#
1919
# *****************************************************************************
20-
import sys
20+
import inspect
2121
import re
22-
from pathlib import Path
22+
import sys
23+
import traceback
2324
from collections import defaultdict
25+
from pathlib import Path
2426
from 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
3130
import 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

5453
def 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]):
8583
def 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")
162185
class 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

Comments
 (0)