Skip to content

Commit

Permalink
Naming consistency changes and documentation cleanups.
Browse files Browse the repository at this point in the history
  • Loading branch information
freakboy3742 committed Feb 17, 2024
1 parent 7e2a6d6 commit ac7a31a
Show file tree
Hide file tree
Showing 16 changed files with 145 additions and 153 deletions.
2 changes: 1 addition & 1 deletion core/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -125,4 +125,4 @@ source = [
asyncio_mode = "auto"

[project.entry-points."toga.image_formats"]
pil = "toga.plugins.image_converters.PilConverter"
pil = "toga.plugins.image_formats.PILConverter"
21 changes: 10 additions & 11 deletions core/src/toga/images.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,21 @@


class ImageConverter(Protocol):
"""A class to convert between an externally defined image type and :any:`toga.Image`."""
"""A class to convert between an externally defined image type and
:any:`toga.Image`.
"""

#: The base image class this plugin can interpret.
image_class: type[ExternalImageT]
"""The externally defined image class this plugin is designed to interpret."""

@staticmethod
def convert_from_format(image_in_format: ExternalImageT) -> BytesLike:
"""Convert from :any:`image_class` to data in a :ref:`known image format <known-image-formats>`.
"""Convert from :any:`image_class` to data in a :ref:`known image format
<known-image-formats>`.
Will accept an instance of :any:`image_class`, or of a :ref:`subclass of it
<external_image_subclassing>`.
Will accept an instance of :any:`image_class`, or subclass of that class.
:param image_in_format: An instance of :any:`image_class` (or of a subclass).
:param image_in_format: An instance of :any:`image_class` (or a subclass).
:returns: The image data, in a :ref:`known image format <known-image-formats>`.
"""
...
Expand All @@ -68,9 +70,7 @@ def convert_to_format(
Accepts a bytes-like object representing the image in a
:ref:`known image format <known-image-formats>`, and returns an instance of the
image class specified. This image class is guaranteed to be either the
:any:`image_class` registered by the plugin, or a subclass of that class. If a
subclass is requested, the subclass's initializer must have a
:ref:`compatible constructor signature <external_image_subclassing>`.
:any:`image_class` registered by the plugin, or a subclass of that class.
:param data: Image data in a :ref:`known image format <known-image-formats>`.
:param image_class: The class of image to return.
Expand Down Expand Up @@ -212,8 +212,7 @@ def as_format(self, format: type[ImageT]) -> ImageT:
:param format: Format to provide. Defaults to :class:`~toga.images.Image`; also
supports :any:`PIL.Image.Image` if Pillow is installed, as well as any image
types defined by installed :doc:`image format plugins
</reference/plugins/image_plugins>`. If providing a subclass of :any:`Image`,
see note about :ref:`subclassing Image <toga_image_subclassing>`.
</reference/plugins/image_formats>`.
:returns: The image in the requested format
:raises TypeError: If the format supplied is not recognized.
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
PIL_imported = False


class PilConverter:
class PILConverter:
image_class = PIL.Image.Image if PIL_imported else None

@staticmethod
Expand Down
7 changes: 3 additions & 4 deletions core/src/toga/screens.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,9 @@ def as_image(self, format: type[ImageT] = Image) -> ImageT:
"""Render the current contents of the screen as an image.
:param format: Format to provide. Defaults to :class:`~toga.images.Image`; also
supports :any:`PIL.Image.Image` if Pillow is installed, as well as any image
types defined by installed :doc:`image format plugins
</reference/plugins/image_plugins>`. If providing a subclass of :any:`Image`,
see note about :ref:`subclassing Image <toga_image_subclassing>`.
supports :any:`PIL.Image.Image` if Pillow is installed, as well as any image
types defined by installed :doc:`image format plugins
</reference/plugins/image_formats>`.
:returns: An image containing the screen content, in the format requested.
"""
return Image(self._impl.get_image_data()).as_format(format)
7 changes: 3 additions & 4 deletions core/src/toga/widgets/canvas.py
Original file line number Diff line number Diff line change
Expand Up @@ -1453,10 +1453,9 @@ def as_image(self, format: type[ImageT] = toga.Image) -> ImageT:
"""Render the canvas as an image.
:param format: Format to provide. Defaults to :class:`~toga.images.Image`; also
supports :any:`PIL.Image.Image` if Pillow is installed, as well as any image
types defined by installed :doc:`image format plugins
</reference/plugins/image_plugins>`. If providing a subclass of :any:`Image`,
see note about :ref:`subclassing Image <toga_image_subclassing>`.
supports :any:`PIL.Image.Image` if Pillow is installed, as well as any image
types defined by installed :doc:`image format plugins
</reference/plugins/image_formats>`
:returns: The canvas as an image of the specified type.
"""
return toga.Image(self._impl.get_image_data()).as_format(format)
Expand Down
7 changes: 3 additions & 4 deletions core/src/toga/widgets/imageview.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,9 @@ def as_image(self, format: type[ImageT] = toga.Image) -> ImageT:
"""Return the image in the specified format.
:param format: Format to provide. Defaults to :class:`~toga.images.Image`; also
supports :any:`PIL.Image.Image` if Pillow is installed, as well as any image
types defined by installed :doc:`image format plugins
</reference/plugins/image_plugins>`. If providing a subclass of :any:`Image`,
see note about :ref:`subclassing Image <toga_image_subclassing>`.
supports :any:`PIL.Image.Image` if Pillow is installed, as well as any image
types defined by installed :doc:`image format plugins
</reference/plugins/image_formats>`.
:returns: The image in the specified format.
"""
return self.image.as_format(format)
7 changes: 3 additions & 4 deletions core/src/toga/window.py
Original file line number Diff line number Diff line change
Expand Up @@ -438,10 +438,9 @@ def as_image(self, format: type[ImageT] = Image) -> ImageT:
"""Render the current contents of the window as an image.
:param format: Format to provide. Defaults to :class:`~toga.images.Image`; also
supports :any:`PIL.Image.Image` if Pillow is installed, as well as any image
types defined by installed :doc:`image format plugins
</reference/plugins/image_plugins>`. If providing a subclass of :any:`Image`,
see note about :ref:`subclassing Image <toga_image_subclassing>`.
supports :any:`PIL.Image.Image` if Pillow is installed, as well as any image
types defined by installed :doc:`image format plugins
</reference/plugins/image_formats>`.
:returns: An image containing the window content, in the format requested.
"""
return Image(self._impl.get_image_data()).as_format(format)
Expand Down
9 changes: 6 additions & 3 deletions core/tests/test_images.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
import pytest

import toga
from toga_dummy.plugins import disabled_converter
from toga_dummy.plugins.image_converter import CustomImage, CustomImageSubclass
from toga_dummy.plugins.image_formats import (
CustomImage,
CustomImageSubclass,
DisabledImageConverter,
)
from toga_dummy.utils import assert_action_performed_with

RELATIVE_FILE_PATH = Path("resources/sample.png")
Expand Down Expand Up @@ -289,7 +292,7 @@ def test_as_format_custom_class(app, ImageClass):

def test_disabled_image_plugin(app):
"""Disabled image plugin shouldn't be available."""
assert disabled_converter not in toga.Image._converters()
assert DisabledImageConverter not in toga.Image._converters()


# None is same as supplying nothing; also test a random unrecognized class
Expand Down
18 changes: 5 additions & 13 deletions docs/reference/api/resources/images.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ An image can be constructed from a :any:`wide range of sources <ImageContent>`:
my_toga_image = toga.Image(my_pil_image)
You can also tell Toga how to convert from (and to) other classes that represent images
via :doc:`image format plugins </reference/plugins/image_plugins>`.
via :doc:`image format plugins </reference/plugins/image_formats>`.

Notes
-----
Expand All @@ -79,17 +79,9 @@ Notes

.. _toga_image_subclassing:

* If you subclass :any:`Image`, you can supply that subclass as the requested
format to :any:`Image.as_format`. If you do, make sure that your subclass has a compatible
constructor signature, as Toga will attempt to create it the same way as it would a
base :any:`Image`.

The same consideration applies when providing such a subclass as the format argument to:

- :any:`Canvas.as_image`
- :any:`ImageView.as_image`
- :any:`Screen.as_image`
- :any:`Window.as_image`
* If you subclass :any:`Image`, you can supply that subclass as the requested format to
any ``as_format()`` method in Toga, provided that your subclass has a constructor
signature compatible with the base :any:`Image` class.

Reference
---------
Expand All @@ -108,7 +100,7 @@ Reference
* if `Pillow <https://pillow.readthedocs.io/>`_ is installed, an instance of
:any:`PIL.Image.Image`;
* an image of a class registered via an :doc:`image format plugin
</reference/plugins/image_plugins>` (or a subclass of such a class); or
</reference/plugins/image_formats>` (or a subclass of such a class); or
* an instance of the :ref:`native platform image representation <native-image-rep>`.

If a relative path is provided, it will be anchored relative to the module that
Expand Down
56 changes: 56 additions & 0 deletions docs/reference/plugins/image_formats.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
====================
Image Format Plugins
====================

Usage
-----

Toga can be extended, via plugins, to understand externally defined image types, gaining
the ability to convert them to and from its own :any:`Image` class. Toga's `Pillow
<https://pillow.readthedocs.io/en/stable/index.html>`__ support is, in fact,
implemented as a plugin that's included as part of the core Toga package.

An image format plugin consists of two things:

- a converter class conforming to the :any:`ImageConverter` protocol, with methods
defining how to convert to and from your image class
- an `entry point
<https://packaging.python.org/en/latest/guides/creating-and-discovering-plugins/#using-package-metadata>`__
in the ``toga.image_formats`` group telling Toga the path to your converter class.

Let's say you want to tell Toga how to handle an image class called ``MyImage``, and
you're publishing your plugin as a package named ``togax-myimage`` (see :ref:`package
prefixes <package_prefixes>`) that contains a ``plugins.py`` module that defines your
``MyImageConverter`` plugin class. Your ``pyproject.toml`` might include something like
the following:

.. code-block:: toml
[project.entry-points."toga.image_formats"]
myimage = "togax_myimage.plugins.MyImageConverter"
The variable name being assigned to (``myimage`` in this case) can be whatever you like
(although it should probably have some relationship to the image format name) What
matters is the string assigned to it, which represents where Toga can find (and import)
your :any:`ImageConverter` class.

.. _package_prefixes:

Package prefixes
~~~~~~~~~~~~~~~~

An image plugin can be registered from any Python module. If you maintain a package
defining an image format, you could include a Toga converter plugin along with it. If
you're publishing a plugin as a standalone package, you should title it with a
``togax-`` prefix, to indicate that it's an unofficial extension for Toga. Do *not* use
the ``toga-`` prefix, as the BeeWare Project wishes to reserve that package prefix for
"official" packages.

Reference
---------

.. c:type:: ExternalImageT
Any class that represents an image.

.. autoprotocol:: toga.images.ImageConverter
75 changes: 0 additions & 75 deletions docs/reference/plugins/image_plugins.rst

This file was deleted.

4 changes: 1 addition & 3 deletions docs/reference/plugins/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@
Plugins
=======



.. toctree::
:maxdepth: 1

image_plugins
image_formats
4 changes: 2 additions & 2 deletions dummy/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,5 @@ dependencies = [
]

[project.entry-points."toga.image_formats"]
dummy = "toga_dummy.plugins.image_converter"
disabled = "toga_dummy.plugins.disabled_converter"
dummy = "toga_dummy.plugins.image_formats.CustomImageConverter"
disabled = "toga_dummy.plugins.image_formats.DisabledImageConverter"
4 changes: 0 additions & 4 deletions dummy/src/toga_dummy/plugins/disabled_converter.py

This file was deleted.

24 changes: 0 additions & 24 deletions dummy/src/toga_dummy/plugins/image_converter.py

This file was deleted.

Loading

0 comments on commit ac7a31a

Please sign in to comment.