diff --git a/README.md b/README.md index 624c883..65c4d5c 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![mybinder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/py5coding/py5examples/HEAD?urlpath=lab) -py5 is a new version of [Processing][processing] for Python 3.9+. The goal of py5 is to create a version of Processing that is [integrated into the Python ecosystem](https://py5coding.org/integrations/python_ecosystem_integrations.html). 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](https://jupyter.org/), [numpy](https://numpy.org/), [shapely](https://shapely.readthedocs.io/en/stable/), [trimesh](https://trimesh.org/), [matplotlib](https://matplotlib.org/), and [Pillow](https://python-pillow.org/). +py5 is a new version of [Processing][processing] for Python. The goal of py5 is to create a version of Processing that is [integrated into the Python ecosystem](https://py5coding.org/integrations/python_ecosystem_integrations.html). 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](https://jupyter.org/), [numpy](https://numpy.org/), [shapely](https://shapely.readthedocs.io/en/stable/), [trimesh](https://trimesh.org/), [matplotlib](https://matplotlib.org/), and [Pillow](https://python-pillow.org/). py5 is an excellent choice for educators looking to teach Python in the context of creative coding and is currently used in classrooms all around the world. The documentation website includes [introductory tutorials](https://py5coding.org/tutorials/intro_to_py5_and_python.html) as well as extensive [reference documentation](https://py5coding.org/reference/summary.html), complete with example code. diff --git a/py5/__init__.py b/py5/__init__.py index ec55d1c..5ca7109 100644 --- a/py5/__init__.py +++ b/py5/__init__.py @@ -19,7 +19,7 @@ # ***************************************************************************** # -*- coding: utf-8 -*- """ -py5 is a version of Processing for Python 3.9+. It makes the Processing Java libraries available to the CPython interpreter using JPype. +py5 is a version of Processing for Python. It makes the Processing Java libraries available to the CPython interpreter using JPype. """ from __future__ import annotations @@ -208,6 +208,8 @@ BASELINE = 0 BEVEL = 32 BEZIER_VERTEX = 1 +BICUBIC = 2 +BILINEAR = 1 BLEND = 1 BLUR = 11 BOTTOM = 102 @@ -289,6 +291,7 @@ MODEL = 4 MOVE = 13 MULTIPLY = 128 +NEAREST_NEIGHBOR = 0 NORMAL = 1 OPAQUE = 14 OPEN = 1 @@ -3792,6 +3795,10 @@ def copy() -> Py5Image: the source image has an alpha channel set, it will be copied as well. This function ignores `image_mode()`. + + If you want to create a new image with the contents of a rectangular region of + the sketch, check out `get_pixels()` where x, y, w, h, are the position and + dimensions of the area to be copied. It will return a `Py5Image` object. """ pass @@ -3856,6 +3863,10 @@ def copy( the source image has an alpha channel set, it will be copied as well. This function ignores `image_mode()`. + + If you want to create a new image with the contents of a rectangular region of + the sketch, check out `get_pixels()` where x, y, w, h, are the position and + dimensions of the area to be copied. It will return a `Py5Image` object. """ pass @@ -3929,6 +3940,10 @@ def copy( the source image has an alpha channel set, it will be copied as well. This function ignores `image_mode()`. + + If you want to create a new image with the contents of a rectangular region of + the sketch, check out `get_pixels()` where x, y, w, h, are the position and + dimensions of the area to be copied. It will return a `Py5Image` object. """ pass @@ -3990,6 +4005,10 @@ def copy(*args): the source image has an alpha channel set, it will be copied as well. This function ignores `image_mode()`. + + If you want to create a new image with the contents of a rectangular region of + the sketch, check out `get_pixels()` where x, y, w, h, are the position and + dimensions of the area to be copied. It will return a `Py5Image` object. """ return _py5sketch.copy(*args) diff --git a/py5/graphics.py b/py5/graphics.py index 7bc8d56..1b00ead 100644 --- a/py5/graphics.py +++ b/py5/graphics.py @@ -1651,6 +1651,8 @@ def color(self, *args) -> int: BASELINE = 0 BEVEL = 32 BEZIER_VERTEX = 1 + BICUBIC = 2 + BILINEAR = 1 BLEND = 1 BLUE_MASK = 255 BLUR = 11 @@ -1731,6 +1733,7 @@ def color(self, *args) -> int: MODEL = 4 MOVE = 13 MULTIPLY = 128 + NEAREST_NEIGHBOR = 0 NORMAL = 1 OPAQUE = 14 OPEN = 1 @@ -5581,6 +5584,11 @@ def copy(self) -> Py5Image: This method is the same as `copy()` but linked to a `Py5Graphics` object. To see example code for how it can be used, see `copy()`. + + If you want to create a new image with the contents of a rectangular region of a + `Py5Graphics` object, check out the `Py5Graphics.get_pixels()` method, where x, + y, w, h, are the position and dimensions of the area to be copied. It will + return a `Py5Image` object. """ pass @@ -5647,6 +5655,11 @@ def copy( This method is the same as `copy()` but linked to a `Py5Graphics` object. To see example code for how it can be used, see `copy()`. + + If you want to create a new image with the contents of a rectangular region of a + `Py5Graphics` object, check out the `Py5Graphics.get_pixels()` method, where x, + y, w, h, are the position and dimensions of the area to be copied. It will + return a `Py5Image` object. """ pass @@ -5723,6 +5736,11 @@ def copy( This method is the same as `copy()` but linked to a `Py5Graphics` object. To see example code for how it can be used, see `copy()`. + + If you want to create a new image with the contents of a rectangular region of a + `Py5Graphics` object, check out the `Py5Graphics.get_pixels()` method, where x, + y, w, h, are the position and dimensions of the area to be copied. It will + return a `Py5Image` object. """ pass @@ -5787,6 +5805,11 @@ def copy(self, *args): This method is the same as `copy()` but linked to a `Py5Graphics` object. To see example code for how it can be used, see `copy()`. + + If you want to create a new image with the contents of a rectangular region of a + `Py5Graphics` object, check out the `Py5Graphics.get_pixels()` method, where x, + y, w, h, are the position and dimensions of the area to be copied. It will + return a `Py5Image` object. """ return self._instance.copy(*args) diff --git a/py5/image.py b/py5/image.py index b8287c4..879f2d2 100644 --- a/py5/image.py +++ b/py5/image.py @@ -103,6 +103,8 @@ def __getattr__(self, name): ALPHA = 4 ALPHA_MASK = -16777216 ARGB = 2 + BICUBIC = 2 + BILINEAR = 1 BLEND = 1 BLUE_MASK = 255 BLUR = 11 @@ -120,6 +122,7 @@ def __getattr__(self, name): INVERT = 13 LIGHTEST = 8 MULTIPLY = 128 + NEAREST_NEIGHBOR = 0 OPAQUE = 14 OVERLAY = 512 POSTERIZE = 15 @@ -591,6 +594,11 @@ def copy(self) -> Py5Image: as well. This function ignores `image_mode()`. + + If you want to create a new image with the contents of a rectangular region of a + `Py5Image` object, check out the `Py5Image.get_pixels()` method, where x, y, w, + h, are the position and dimensions of the area to be copied. It will return a + `Py5Image` object. """ pass @@ -651,6 +659,11 @@ def copy( as well. This function ignores `image_mode()`. + + If you want to create a new image with the contents of a rectangular region of a + `Py5Image` object, check out the `Py5Image.get_pixels()` method, where x, y, w, + h, are the position and dimensions of the area to be copied. It will return a + `Py5Image` object. """ pass @@ -721,6 +734,11 @@ def copy( as well. This function ignores `image_mode()`. + + If you want to create a new image with the contents of a rectangular region of a + `Py5Image` object, check out the `Py5Image.get_pixels()` method, where x, y, w, + h, are the position and dimensions of the area to be copied. It will return a + `Py5Image` object. """ pass @@ -779,6 +797,11 @@ def copy(self, *args): as well. This function ignores `image_mode()`. + + If you want to create a new image with the contents of a rectangular region of a + `Py5Image` object, check out the `Py5Image.get_pixels()` method, where x, y, w, + h, are the position and dimensions of the area to be copied. It will return a + `Py5Image` object. """ return self._instance.copy(*args) @@ -1270,6 +1293,140 @@ def mask(self, *args): """ return self._instance.mask(*args) + @overload + def resize(self, w: int, h: int, /) -> None: + """Resize the Py5Image object to a new height and width. + + Underlying Processing method: PImage.resize + + Methods + ------- + + You can use any of the following signatures: + + * resize(w: int, h: int, /) -> None + * resize(w: int, h: int, interpolation_mode: int, /) -> None + + Parameters + ---------- + + h: int + height to size image to + + interpolation_mode: int + interpolation method for resize operation + + w: int + width to size image to + + Notes + ----- + + Resize the Py5Image object to a new height and width. This will modify the + Py5Image object in place, meaning that rather than returning a resized copy, it + will modify your existing Py5Image object. If this isn't what you want, pair + this method with `Py5Image.copy()`, as shown in the example. + + To make the image scale proportionally, use 0 as the value for either the `w` or + `h` parameter. + + The default resize interpolation mode is `BILINEAR`. Alternatively you can use + the `interpolation_mode` parameter to interpolate using the `NEAREST_NEIGHBOR` + method, which is faster but yields lower quality results. You can also use + `BICUBIC` interpolation, which is the most computationally intensive but looks + the best, particularly for up-scaling operations. + """ + pass + + @overload + def resize(self, w: int, h: int, interpolation_mode: int, /) -> None: + """Resize the Py5Image object to a new height and width. + + Underlying Processing method: PImage.resize + + Methods + ------- + + You can use any of the following signatures: + + * resize(w: int, h: int, /) -> None + * resize(w: int, h: int, interpolation_mode: int, /) -> None + + Parameters + ---------- + + h: int + height to size image to + + interpolation_mode: int + interpolation method for resize operation + + w: int + width to size image to + + Notes + ----- + + Resize the Py5Image object to a new height and width. This will modify the + Py5Image object in place, meaning that rather than returning a resized copy, it + will modify your existing Py5Image object. If this isn't what you want, pair + this method with `Py5Image.copy()`, as shown in the example. + + To make the image scale proportionally, use 0 as the value for either the `w` or + `h` parameter. + + The default resize interpolation mode is `BILINEAR`. Alternatively you can use + the `interpolation_mode` parameter to interpolate using the `NEAREST_NEIGHBOR` + method, which is faster but yields lower quality results. You can also use + `BICUBIC` interpolation, which is the most computationally intensive but looks + the best, particularly for up-scaling operations. + """ + pass + + def resize(self, *args): + """Resize the Py5Image object to a new height and width. + + Underlying Processing method: PImage.resize + + Methods + ------- + + You can use any of the following signatures: + + * resize(w: int, h: int, /) -> None + * resize(w: int, h: int, interpolation_mode: int, /) -> None + + Parameters + ---------- + + h: int + height to size image to + + interpolation_mode: int + interpolation method for resize operation + + w: int + width to size image to + + Notes + ----- + + Resize the Py5Image object to a new height and width. This will modify the + Py5Image object in place, meaning that rather than returning a resized copy, it + will modify your existing Py5Image object. If this isn't what you want, pair + this method with `Py5Image.copy()`, as shown in the example. + + To make the image scale proportionally, use 0 as the value for either the `w` or + `h` parameter. + + The default resize interpolation mode is `BILINEAR`. Alternatively you can use + the `interpolation_mode` parameter to interpolate using the `NEAREST_NEIGHBOR` + method, which is faster but yields lower quality results. You can also use + `BICUBIC` interpolation, which is the most computationally intensive but looks + the best, particularly for up-scaling operations. + """ + return self._instance.resize(*args) + @overload def set_pixels(self, x: int, y: int, c: int, /) -> None: """Changes the color of any pixel or writes an image directly into the Py5Image diff --git a/py5/jars/core.jar b/py5/jars/core.jar index 4ec7d16..d4b1c3b 100755 Binary files a/py5/jars/core.jar and b/py5/jars/core.jar differ diff --git a/py5/jars/dxf/dxf.jar b/py5/jars/dxf/dxf.jar index 61e2b69..54d8f00 100755 Binary files a/py5/jars/dxf/dxf.jar and b/py5/jars/dxf/dxf.jar differ diff --git a/py5/jars/pdf/pdf.jar b/py5/jars/pdf/pdf.jar index 12e7746..6661510 100755 Binary files a/py5/jars/pdf/pdf.jar and b/py5/jars/pdf/pdf.jar differ diff --git a/py5/jars/py5.jar b/py5/jars/py5.jar index e201504..67ee020 100644 Binary files a/py5/jars/py5.jar and b/py5/jars/py5.jar differ diff --git a/py5/jars/svg/svg.jar b/py5/jars/svg/svg.jar index a77efa8..dcbbb20 100755 Binary files a/py5/jars/svg/svg.jar and b/py5/jars/svg/svg.jar differ diff --git a/py5/macos_problem.py b/py5/macos_problem.py deleted file mode 100644 index 4f3fb19..0000000 --- a/py5/macos_problem.py +++ /dev/null @@ -1,122 +0,0 @@ -# ***************************************************************************** -# -# Part of the py5 library -# Copyright (C) 2020-2025 Jim Schmitz -# -# This library is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation, either version 2.1 of the License, or (at -# your option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser -# General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this library. If not, see . -# -# ***************************************************************************** -import functools -import platform - -from py5_tools.environ import Environment - -_environ = Environment() - -_enforce_safety_check = ( - platform.system() == "Darwin" - and ( - platform.processor() == "i386" - or int(platform.mac_ver()[0].split(".", 1)[0]) < 14 - ) - and _environ.in_ipython_session -) -_first_renderer_opengl = None - - -def disable_safety_check(): - global _enforce_safety_check - _enforce_safety_check = False - - -def enable_safety_check(): - global _enforce_safety_check - _enforce_safety_check = True - - -OPENGL_RENDERERS = [ - "processing.opengl.PGraphics2D", - "processing.opengl.PGraphics3D", -] - -MESSAGE = """Sorry, but you can't use an OpenGL renderer in your Sketch right now. Doing so might cause Python to crash. - -Here's the problem: On macOS machines with Intel CPUs and/or older macOS versions, this version of py5 seems to crash when you use an OpenGL renderer in an IPython or Jupyter session if the first Sketch run in that Python session used the default (JAVA2D) renderer. Sorry if that sounds crazy. This is an unfortunate side effect of an important code change that significantly improved py5 for all macOS users. - -The root issue is somewhere in native macOS code that Processing and py5 both depend on. Hopefully in the future we will find a real fix or a better workaround. - -You are seeing this message because this version of py5 has a safety feature that detects the sequence of events that might lead to this crash. However, if you'd like to disable this safety feature (and risk Python crashing), use the following code: - - from py5 import macos_problem - - macos_problem.disable_safety_check() - -But before doing that, it would be great if you could do a quick test for us. Please run the following code in a new Jupyter Notebook or IPython REPL, with each line of code executed separately: - - from py5 import macos_problem, test - - macos_problem.disable_safety_check() - - # run a Sketch with the default renderer - test.test_java2d() - - # run a Sketch with an opengl renderer - # does this cause a crash??? - test.test_p2d() - -Then report your findings to the below GitHub issue thread. Include your macOS version and CPU type. (For your convenience, this information will be displayed at the end of this message.) Your feedback will help us understand the problem better and more accurately calibrate this crash protection feature. - -https://github.com/py5coding/py5generator/issues/578 - -If the above test code doesn't cause Python to crash on your machine, great! You can keep using that `disable_safety_check()` function so you never see this warning again. But please take the time report your findings to the GitHub issue thread. The next version of py5 will incorporate your feedback and the safety feature will be adjusted accordingly. - -If the above test code does cause Python to crash on your machine, it's OK. If you really need to mix Java2D and OpenGL renderers together in one Python session, you just need to make sure that the first executed Sketch is always an OpenGL Sketch. For convenience, you can use the following code to open a quick Sketch right after importing py5. This will ensure the first Sketch is always an OpenGL Sketch, eliminating the problem (and this warning) entirely: - - import py5 - from py5 import test - - test.test_p2d() - -If you'd like to read about our progress understanding this issue, please visit the above GitHub issue thread. - -Sorry again for the weird limitation. We're doing our best to make py5 as stable as possible. This safety feature is here because we don't want users to become upset because Python crashed for confusing reasons. Thank you for your understanding. -""" - - -def _macos_safety_check(f): - @functools.wraps(f) - def decorated(self_, *args): - global _first_renderer_opengl - if _enforce_safety_check: - if _first_renderer_opengl is None: - # This is the first Sketch. Record if the renderer is OpenGL. - if len(args) >= 3 and args[2] in OPENGL_RENDERERS: - _first_renderer_opengl = True - else: - _first_renderer_opengl = False - - elif _first_renderer_opengl is False: - # The first Sketch was not OpenGL. OpenGL is not allowed now. - if len(args) >= 3 and args[2] in OPENGL_RENDERERS: - self_.println(MESSAGE) - if platform.system() == "Darwin": # just in case - self_.println("macOS version:", platform.mac_ver()[0]) - self_.println("macOS CPU type:", platform.processor()) - raise RuntimeError( - "Halting Sketch startup to prevent Python from crashing" - ) - - f(self_, *args) - - return decorated diff --git a/py5/reference.py b/py5/reference.py index b6e8ad6..5a8e643 100644 --- a/py5/reference.py +++ b/py5/reference.py @@ -578,6 +578,7 @@ (('Py5Image', 'get_pixels'), ['() -> Py5Image', '(x: int, y: int, /) -> int', '(x: int, y: int, w: int, h: int, /) -> Py5Image']), (('Py5Image', 'load_pixels'), ['() -> None']), (('Py5Image', 'mask'), ['(mask_array: Sequence[int], /) -> None', '(img: Py5Image, /) -> None']), + (('Py5Image', 'resize'), ['(w: int, h: int, /) -> None', '(w: int, h: int, interpolation_mode: int, /) -> None']), (('Py5Image', 'set_pixels'), ['(x: int, y: int, c: int, /) -> None', '(x: int, y: int, img: Py5Image, /) -> None']), (('Py5Image', 'update_pixels'), ['() -> None', '(x: int, y: int, w: int, h: int, /) -> None']), (('Py5KeyEvent', 'get_action'), ['() -> int']), diff --git a/py5/shape_conversion.py b/py5/shape_conversion.py index 99bed48..dc64e5d 100644 --- a/py5/shape_conversion.py +++ b/py5/shape_conversion.py @@ -138,12 +138,16 @@ def shapely_to_py5shape_converter(sketch, obj, _first_call=True, **kwargs): shape.vertices(coords[:-1]) return shape elif isinstance(obj, LineString): + coords = np.array(obj.coords) shape = sketch.create_shape() - with shape.begin_shape(): - if not kwargs.get("lines_allow_fill", False): - shape.no_fill() - coords = np.array(obj.coords) - shape.vertices(coords) + if coords.shape[0] == 2: + with shape.begin_shape(sketch.LINES): + shape.vertices(coords) + elif coords.shape[0] > 2: + with shape.begin_shape(): + if not kwargs.get("lines_allow_fill", False): + shape.no_fill() + shape.vertices(coords) return shape elif isinstance(obj, MultiPoint): shape = sketch.create_shape() diff --git a/py5/sketch.py b/py5/sketch.py index a2523f0..78a3a29 100644 --- a/py5/sketch.py +++ b/py5/sketch.py @@ -54,7 +54,6 @@ from .graphics import Py5Graphics, _return_py5graphics # noqa from .image import Py5Image, _return_py5image # noqa from .keyevent import Py5KeyEvent, _convert_jchar_to_chr, _convert_jint_to_int # noqa -from .macos_problem import _macos_safety_check from .mixins import DataMixin, MathMixin, PixelMixin, PrintlnStream, ThreadsMixin from .mixins.threads import Py5Promise # noqa from .mouseevent import Py5MouseEvent # noqa @@ -3844,6 +3843,8 @@ def color(self, *args) -> int: BASELINE = 0 BEVEL = 32 BEZIER_VERTEX = 1 + BICUBIC = 2 + BILINEAR = 1 BLEND = 1 BLUR = 11 BOTTOM = 102 @@ -3925,6 +3926,7 @@ def color(self, *args) -> int: MODEL = 4 MOVE = 13 MULTIPLY = 128 + NEAREST_NEIGHBOR = 0 NORMAL = 1 OPAQUE = 14 OPEN = 1 @@ -8394,6 +8396,10 @@ def copy(self) -> Py5Image: the source image has an alpha channel set, it will be copied as well. This function ignores `image_mode()`. + + If you want to create a new image with the contents of a rectangular region of + the sketch, check out `get_pixels()` where x, y, w, h, are the position and + dimensions of the area to be copied. It will return a `Py5Image` object. """ pass @@ -8457,6 +8463,10 @@ def copy( the source image has an alpha channel set, it will be copied as well. This function ignores `image_mode()`. + + If you want to create a new image with the contents of a rectangular region of + the sketch, check out `get_pixels()` where x, y, w, h, are the position and + dimensions of the area to be copied. It will return a `Py5Image` object. """ pass @@ -8530,6 +8540,10 @@ def copy( the source image has an alpha channel set, it will be copied as well. This function ignores `image_mode()`. + + If you want to create a new image with the contents of a rectangular region of + the sketch, check out `get_pixels()` where x, y, w, h, are the position and + dimensions of the area to be copied. It will return a `Py5Image` object. """ pass @@ -8592,6 +8606,10 @@ def copy(self, *args): the source image has an alpha channel set, it will be copied as well. This function ignores `image_mode()`. + + If you want to create a new image with the contents of a rectangular region of + the sketch, check out `get_pixels()` where x, y, w, h, are the position and + dimensions of the area to be copied. It will return a `Py5Image` object. """ return self._instance.copy(*args) @@ -16909,7 +16927,6 @@ class mode. pass @_settings_only("size") - @_macos_safety_check def size(self, *args): """Defines the dimension of the display window width and height in units of pixels. diff --git a/py5_tools/colors/mpl_cmaps.py b/py5_tools/colors/mpl_cmaps.py index 54cb82f..091d1a4 100644 --- a/py5_tools/colors/mpl_cmaps.py +++ b/py5_tools/colors/mpl_cmaps.py @@ -27,6 +27,9 @@ TWILIGHT = "twilight" TWILIGHT_SHIFTED = "twilight_shifted" TURBO = "turbo" +BERLIN = "berlin" +MANAGUA = "managua" +VANIMO = "vanimo" BLUES = "Blues" BRBG = "BrBG" BUGN = "BuGn" @@ -114,6 +117,9 @@ TWILIGHT_R = "twilight_r" TWILIGHT_SHIFTED_R = "twilight_shifted_r" TURBO_R = "turbo_r" +BERLIN_R = "berlin_r" +MANAGUA_R = "managua_r" +VANIMO_R = "vanimo_r" BLUES_R = "Blues_r" BRBG_R = "BrBG_r" BUGN_R = "BuGn_r" @@ -189,6 +195,10 @@ TAB20_R = "tab20_r" TAB20B_R = "tab20b_r" TAB20C_R = "tab20c_r" +GREY_R = "grey_r" +GIST_GREY_R = "gist_grey_r" +GIST_YERG_R = "gist_yerg_r" +GRAYS_R = "Grays_r" def __getattr__(name): diff --git a/py5_tools/constants.py b/py5_tools/constants.py index e5a4b14..b28cb67 100644 --- a/py5_tools/constants.py +++ b/py5_tools/constants.py @@ -21,8 +21,8 @@ import platform from pathlib import Path -VERSION = "0.10.6.a0" -PROCESSING_BUILD_NUMBER = 1304 +VERSION = "0.10.7a0" +PROCESSING_BUILD_NUMBER = 1306 if not (PY5_HOME := os.environ.get("PY5_HOME")): if platform.system() == "Windows": diff --git a/py5_tools/reference.py b/py5_tools/reference.py index d00a8a7..cdcb746 100644 --- a/py5_tools/reference.py +++ b/py5_tools/reference.py @@ -72,6 +72,8 @@ 'BEZIER_VERTEX', 'bezier_vertex', 'bezier_vertices', + 'BICUBIC', + 'BILINEAR', 'BLEND', 'blend', 'blend_mode', @@ -280,6 +282,7 @@ 'MOVE', 'mpl_cmaps', 'MULTIPLY', + 'NEAREST_NEIGHBOR', 'no_clip', 'no_cursor', 'no_fill', @@ -558,6 +561,8 @@ 'BEZIER_VERTEX', 'bezier_vertex', 'bezier_vertices', + 'BICUBIC', + 'BILINEAR', 'BLEND', 'blend', 'blend_mode', @@ -747,6 +752,7 @@ 'MOVE', 'mpl_cmaps', 'MULTIPLY', + 'NEAREST_NEIGHBOR', 'no_clip', 'no_cursor', 'no_fill', diff --git a/pyproject.toml b/pyproject.toml index 6a5621d..4ad1806 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ dynamic = ["version"] description = "Processing for CPython" readme = "README.md" license = "LGPL-2.1-only" -requires-python = ">=3.9" +requires-python = ">=3.10" authors = [ { name = "Jim Schmitz", email = "jim@ixora.io" }, ] @@ -33,15 +33,15 @@ classifiers = [ "Topic :: Multimedia :: Graphics", ] dependencies = [ - "autopep8>=2.2", - "jpype1>=1.5.2", - "line_profiler>=4.1", - "numpy>=1.26", - "pillow>=10.2", + "autopep8>=2.3", + "jpype1>=1.6", + "line_profiler>=4.2", + "numpy>=2.2", + "pillow>=11.0", "pyobjc>=10.1;sys_platform==\"darwin\"", "pywin32>=308;sys_platform==\"win32\"", - "requests>=2.31", - "stackprinter>=0.2.11", + "requests>=2.32", + "stackprinter>=0.2.12", ] [project.optional-dependencies] @@ -50,10 +50,10 @@ jupyter = [ ] extras = [ "colour>=0.1.5", - "matplotlib>=3.9", + "matplotlib>=3.10", "py5jupyter>=0.2.0a0", "shapely>=2.0", - "trimesh>=4.3", + "trimesh>=4.6", ] [project.scripts]