Skip to content

Commit 479699e

Browse files
authored
Merge pull request #3 from hx2A/release090a0
release 0.9.0a0
2 parents 42eb58c + 239ae6e commit 479699e

Some content is hidden

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

84 files changed

+15509
-15268
lines changed

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66

77
[![mybinder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/py5coding/py5examples/HEAD?urlpath=lab)
88

9-
py5 is a new version of [**Processing**][processing] for Python 3.8+. It makes the Java [**Processing**][processing] jars available to the CPython interpreter using [**JPype**][jpype]. It can do just about all of the 2D and 3D drawing [**Processing**][processing] can do, except with Python instead of Java code.
9+
py5 is a version of [**Processing**][processing] for Python 3.8+. It makes the Java [**Processing**][processing] jars available to the CPython interpreter using [**JPype**][jpype]. It can do just about all of the 2D and 3D drawing [**Processing**][processing] can do, except with Python instead of Java code.
1010

11-
The goal of py5 is to create a new version of Processing that is integrated into the Python ecosystem. Built into the library are thoughtful choices about how to best get py5 to work with other popular Python libraries and tools such as [Jupyter][jupyter], [numpy][numpy], and [Pillow][pillow].
11+
The goal of py5 is to offer a new version of Processing that is integrated into the Python ecosystem. Built into the library are thoughtful choices about how to best get py5 to work with other popular Python libraries and tools such as [Jupyter][jupyter], [numpy][numpy], and [Pillow][pillow].
1212

1313
## Simple Example
1414

@@ -46,14 +46,15 @@ pip install py5
4646

4747
## Getting Started
4848

49-
There are currently four basic ways to use py5. They are:
49+
There are currently five basic ways to use py5. They are:
5050

5151
* **module mode**: create a sketch with `setup()` and `draw()` functions that call methods provided by the `py5` library. The above example is created in module mode.
5252
* **class mode**: create a Python class inherited from `py5.Sketch`. This mode supports multiple Sketches running at the same time.
5353
* **imported mode**: simplified code that omits the `py5.` prefix. This mode is supported by the py5 Jupyter notebook kernel and the `run_sketch` command line utility.
5454
* **static mode**: functionless code to create static images. This mode is supported by the py5bot Jupyter notebook kernel, the `%%py5bot` IPython magic, and the `run_sketch` command line utility.
55+
* **processing mode**: make calls to Python from a Processing (Java) Sketch. This mode enables py5 to function as bridge, connecting the Python and Java ecosystems through a new `callPython()` method.
5556

56-
The documentation website, [https://py5coding.org/](https://py5coding.org/), is a work in progress. The reference documentation is solid but the how-to's and tutorials are incomplete.
57+
The documentation website, [https://py5coding.org/](https://py5coding.org/), is a work in progress, but contains solid reference documentation and many tutorials for beginner coders.
5758

5859
[py5generator][py5_generator_repo] is a meta-programming project that creates the py5 library. To view the actual installed py5 library code, look at the [py5 repository][py5_repo]. All py5 library development is done through py5generator.
5960

py5/__init__.py

Lines changed: 5130 additions & 5033 deletions
Large diffs are not rendered by default.

py5/base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# *****************************************************************************
22
#
33
# Part of the py5 library
4-
# Copyright (C) 2020-2022 Jim Schmitz
4+
# Copyright (C) 2020-2023 Jim Schmitz
55
#
66
# This library is free software: you can redistribute it and/or modify it
77
# under the terms of the GNU Lesser General Public License as published by

py5/bridge.py

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# *****************************************************************************
22
#
33
# Part of the py5 library
4-
# Copyright (C) 2020-2022 Jim Schmitz
4+
# Copyright (C) 2020-2023 Jim Schmitz
55
#
66
# This library is free software: you can redistribute it and/or modify it
77
# under the terms of the GNU Lesser General Public License as published by
@@ -33,11 +33,7 @@
3333
import py5_tools
3434
from . import reference
3535
from . import custom_exceptions
36-
# from . import java_conversion
3736

38-
# *** stacktrace configuration ***
39-
# set stackprinter color style. Default is plaintext. Other choices are darkbg,
40-
# darkbg2, darkbg3, lightbg, lightbg2, lightbg3.
4137
_stackprinter_style = 'plaintext'
4238
# prune tracebacks to only show only show stack levels in the user's py5 code.
4339
_prune_tracebacks = True
@@ -95,12 +91,13 @@ def handle_exception(println, exc_type, exc_value, exc_tb):
9591
tb = exc_tb.tb_next
9692
while hasattr(tb, 'tb_next') and hasattr(tb, 'tb_frame'):
9793
f_code = tb.tb_frame.f_code
98-
if f_code.co_filename.startswith(_MODULE_INSTALL_DIR):
94+
if f_code.co_filename.startswith(
95+
_MODULE_INSTALL_DIR) and not f_code.co_name.endswith('py5_no_prune'):
9996
py5info.append((Path(f_code.co_filename[(len(_MODULE_INSTALL_DIR) + 1):]).parts,
10097
f_code.co_name))
10198
if trim_tb is None:
10299
trim_tb = prev_tb
103-
elif f_code.co_filename.startswith(_PY5TOOLS_MODULE_INSTALL_DIR):
100+
elif f_code.co_filename.startswith(_PY5TOOLS_MODULE_INSTALL_DIR) and not f_code.co_name.endswith('py5_no_prune'):
104101
py5info.append((Path(f_code.co_filename[(
105102
len(_PY5TOOLS_MODULE_INSTALL_DIR) + 1):]).parts, f_code.co_name))
106103
if trim_tb is None:
@@ -134,7 +131,7 @@ def handle_exception(println, exc_type, exc_value, exc_tb):
134131
while m := _PY5_STATIC_CODE_FILENAME_REGEX.search(errmsg):
135132
errmsg = errmsg[m.span()[1]:]
136133
else:
137-
errmsg = "py5 encountered an error in your code:" + errmsg
134+
errmsg = "py5 encountered an error in your code:\n\n" + errmsg
138135

139136
println(errmsg, stderr=True)
140137

@@ -174,8 +171,9 @@ def __init__(self, sketch):
174171
self._current_running_method = None
175172
self._is_terminated = False
176173

177-
from .java_conversion import convert_to_python_types
174+
from .object_conversion import convert_to_python_types, convert_to_java_type
178175
self._convert_to_python_types = convert_to_python_types
176+
self._convert_to_java_type = convert_to_java_type
179177

180178
def set_functions(self, functions, function_param_counts):
181179
self._function_param_counts = dict()
@@ -294,11 +292,11 @@ def call_function(self, key, params):
294292
subd = d[s]
295293
if isinstance(subd, dict):
296294
d = subd
297-
elif hasattr(subd, '__dict__'):
298-
d = subd.__dict__
295+
elif hasattr(subd, '__dir__') or hasattr(subd, '__dict__'):
296+
d = {k: getattr(subd, k) for k in dir(subd)}
299297
else:
300298
return _JAVA_RUNTIMEEXCEPTION(
301-
f'{s} in key {key} does map to dict or object with __dict__ attribute')
299+
f'{s} in key {key} does not map to a dict or an object that can be inspected with dir()')
302300
else:
303301
return _JAVA_RUNTIMEEXCEPTION(
304302
f'{s} not found with key {key}')
@@ -314,7 +312,7 @@ def call_function(self, key, params):
314312
key)
315313
if key in py5_tools.config._PY5_PROCESSING_MODE_KEYS:
316314
py5_tools.config._PY5_PROCESSING_MODE_KEYS.pop(key)
317-
return retval
315+
return self._convert_to_java_type(retval)
318316
except Exception as e:
319317
handle_exception(self._sketch.println, *sys.exc_info())
320318
return _JAVA_RUNTIMEEXCEPTION(str(e))

py5/create_font_tool.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# *****************************************************************************
22
#
33
# Part of the py5 library
4-
# Copyright (C) 2020-2022 Jim Schmitz
4+
# Copyright (C) 2020-2023 Jim Schmitz
55
#
66
# This library is free software: you can redistribute it and/or modify it
77
# under the terms of the GNU Lesser General Public License as published by
@@ -36,6 +36,13 @@ def __init__(
3636
self.filename = filename or f'{font_name}-{font_size}.vlw'
3737
self.characters = characters
3838

39+
def __str__(self) -> str:
40+
return f"CreateFontTool(font_name='" + self.font_name + \
41+
"', font_size=" + str(self.font_size) + ")"
42+
43+
def __repr__(self) -> str:
44+
return self.__str__()
45+
3946
def settings(self):
4047
self.size(400, 100, self.P2D)
4148

@@ -103,16 +110,16 @@ def create_font_file(
103110
104111
By default it will create data files for every character available in the
105112
specified font. To reduce execution time and output file size, limit the
106-
characters using the ``characters`` parameter. The default output filename is
107-
``{font_name}-{font_size}.vlw`` and will be saved to the current directory.
113+
characters using the `characters` parameter. The default output filename is
114+
`{font_name}-{font_size}.vlw` and will be saved to the current directory.
108115
109116
This utility function opens a window that displays a short message about the
110117
number of glyphs written to the file. To make the window close automatically,
111-
set the ``pause`` parameter to ``False``.
118+
set the `pause` parameter to `False`.
112119
113120
Get a list of font names available on your computer with Py5Font's
114-
``Py5Font.list()`` method. If you request an unavailable font, it will create
115-
the data file anyway but using a default font."""
121+
`Py5Font.list()` method. If you request an unavailable font, it will create the
122+
data file anyway but using a default font."""
116123
vlw_creator = CreateFontTool(font_name, font_size,
117124
filename=filename, characters=characters,
118125
pause=pause)

py5/custom_exceptions.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# *****************************************************************************
22
#
33
# Part of the py5 library
4-
# Copyright (C) 2020-2022 Jim Schmitz
4+
# Copyright (C) 2020-2023 Jim Schmitz
55
#
66
# This library is free software: you can redistribute it and/or modify it
77
# under the terms of the GNU Lesser General Public License as published by
@@ -19,10 +19,14 @@
1919
# *****************************************************************************
2020
import re
2121

22+
import py5_tools
23+
2224
from . import reference
25+
from . import spelling
2326

2427
JPYPE_TYPEERROR_REGEX = re.compile(
2528
r'No matching overloads found for [\w\.]*(\([^\)]*\))')
29+
IMPORTED_MODE_NAMEERROR_REGEX = re.compile(r"name '(\w+)' is not defined")
2630

2731

2832
def handle_typeerror(exc_type_name, exc_msg, py5info):
@@ -46,6 +50,21 @@ def handle_typeerror(exc_type_name, exc_msg, py5info):
4650
return exc_msg
4751

4852

53+
def handle_nameerror(exc_type_name, exc_msg, py5info):
54+
if py5_tools.imported.get_imported_mode():
55+
m = IMPORTED_MODE_NAMEERROR_REGEX.match(exc_msg)
56+
if m:
57+
fname = m.group(1)
58+
exc_msg = 'The name "' + fname + '" is not defined.'
59+
suggestion_list = spelling.suggestions(
60+
fname, py5_tools.reference.PY5_DIR_STR)
61+
if suggestion_list:
62+
exc_msg += ' Did you mean ' + suggestion_list + '?'
63+
64+
return exc_msg
65+
66+
4967
CUSTOM_EXCEPTION_MSGS = dict(
5068
TypeError=handle_typeerror,
69+
NameError=handle_nameerror,
5170
)

py5/decorators.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# *****************************************************************************
22
#
33
# Part of the py5 library
4-
# Copyright (C) 2020-2022 Jim Schmitz
4+
# Copyright (C) 2020-2023 Jim Schmitz
55
#
66
# This library is free software: you can redistribute it and/or modify it
77
# under the terms of the GNU Lesser General Public License as published by

0 commit comments

Comments
 (0)