Added type hints

This commit is contained in:
Andrew Murray 2024-01-13 14:40:59 +11:00
parent 9923531742
commit 10cf2f2651
4 changed files with 40 additions and 28 deletions

View File

@ -147,7 +147,6 @@ exclude = [
'^src/PIL/FpxImagePlugin.py$', '^src/PIL/FpxImagePlugin.py$',
'^src/PIL/Image.py$', '^src/PIL/Image.py$',
'^src/PIL/ImageQt.py$', '^src/PIL/ImageQt.py$',
'^src/PIL/ImageShow.py$',
'^src/PIL/ImImagePlugin.py$', '^src/PIL/ImImagePlugin.py$',
'^src/PIL/MicImagePlugin.py$', '^src/PIL/MicImagePlugin.py$',
'^src/PIL/PdfParser.py$', '^src/PIL/PdfParser.py$',

View File

@ -242,7 +242,7 @@ MODES = ["1", "CMYK", "F", "HSV", "I", "L", "LAB", "P", "RGB", "RGBA", "RGBX", "
_MAPMODES = ("L", "P", "RGBX", "RGBA", "CMYK", "I;16", "I;16L", "I;16B") _MAPMODES = ("L", "P", "RGBX", "RGBA", "CMYK", "I;16", "I;16L", "I;16B")
def getmodebase(mode): def getmodebase(mode: str) -> str:
""" """
Gets the "base" mode for given mode. This function returns "L" for Gets the "base" mode for given mode. This function returns "L" for
images that contain grayscale data, and "RGB" for images that images that contain grayscale data, and "RGB" for images that
@ -583,7 +583,9 @@ class Image:
else: else:
self.load() self.load()
def _dump(self, file=None, format=None, **options): def _dump(
self, file: str | None = None, format: str | None = None, **options
) -> str:
suffix = "" suffix = ""
if format: if format:
suffix = "." + format suffix = "." + format

View File

@ -13,18 +13,20 @@
# #
from __future__ import annotations from __future__ import annotations
import abc
import os import os
import shutil import shutil
import subprocess import subprocess
import sys import sys
from shlex import quote from shlex import quote
from typing import Any
from . import Image from . import Image
_viewers = [] _viewers = []
def register(viewer, order=1): def register(viewer, order: int = 1) -> None:
""" """
The :py:func:`register` function is used to register additional viewers:: The :py:func:`register` function is used to register additional viewers::
@ -49,7 +51,7 @@ def register(viewer, order=1):
_viewers.insert(0, viewer) _viewers.insert(0, viewer)
def show(image, title=None, **options): def show(image: Image.Image, title: str | None = None, **options: Any) -> bool:
r""" r"""
Display a given image. Display a given image.
@ -69,7 +71,7 @@ class Viewer:
# main api # main api
def show(self, image, **options): def show(self, image: Image.Image, **options: Any) -> int:
""" """
The main function for displaying an image. The main function for displaying an image.
Converts the given image to the target format and displays it. Converts the given image to the target format and displays it.
@ -87,16 +89,16 @@ class Viewer:
# hook methods # hook methods
format = None format: str | None = None
"""The format to convert the image into.""" """The format to convert the image into."""
options = {} options: dict[str, Any] = {}
"""Additional options used to convert the image.""" """Additional options used to convert the image."""
def get_format(self, image): def get_format(self, image: Image.Image) -> str | None:
"""Return format name, or ``None`` to save as PGM/PPM.""" """Return format name, or ``None`` to save as PGM/PPM."""
return self.format return self.format
def get_command(self, file, **options): def get_command(self, file: str, **options: Any) -> str:
""" """
Returns the command used to display the file. Returns the command used to display the file.
Not implemented in the base class. Not implemented in the base class.
@ -104,15 +106,15 @@ class Viewer:
msg = "unavailable in base viewer" msg = "unavailable in base viewer"
raise NotImplementedError(msg) raise NotImplementedError(msg)
def save_image(self, image): def save_image(self, image: Image.Image) -> str:
"""Save to temporary file and return filename.""" """Save to temporary file and return filename."""
return image._dump(format=self.get_format(image), **self.options) return image._dump(format=self.get_format(image), **self.options)
def show_image(self, image, **options): def show_image(self, image: Image.Image, **options: Any) -> int:
"""Display the given image.""" """Display the given image."""
return self.show_file(self.save_image(image), **options) return self.show_file(self.save_image(image), **options)
def show_file(self, path, **options): def show_file(self, path: str, **options: Any) -> int:
""" """
Display given file. Display given file.
""" """
@ -129,7 +131,7 @@ class WindowsViewer(Viewer):
format = "PNG" format = "PNG"
options = {"compress_level": 1, "save_all": True} options = {"compress_level": 1, "save_all": True}
def get_command(self, file, **options): def get_command(self, file: str, **options: Any) -> str:
return ( return (
f'start "Pillow" /WAIT "{file}" ' f'start "Pillow" /WAIT "{file}" '
"&& ping -n 4 127.0.0.1 >NUL " "&& ping -n 4 127.0.0.1 >NUL "
@ -147,14 +149,14 @@ class MacViewer(Viewer):
format = "PNG" format = "PNG"
options = {"compress_level": 1, "save_all": True} options = {"compress_level": 1, "save_all": True}
def get_command(self, file, **options): def get_command(self, file: str, **options: Any) -> str:
# on darwin open returns immediately resulting in the temp # on darwin open returns immediately resulting in the temp
# file removal while app is opening # file removal while app is opening
command = "open -a Preview.app" command = "open -a Preview.app"
command = f"({command} {quote(file)}; sleep 20; rm -f {quote(file)})&" command = f"({command} {quote(file)}; sleep 20; rm -f {quote(file)})&"
return command return command
def show_file(self, path, **options): def show_file(self, path: str, **options: Any) -> int:
""" """
Display given file. Display given file.
""" """
@ -180,7 +182,11 @@ class UnixViewer(Viewer):
format = "PNG" format = "PNG"
options = {"compress_level": 1, "save_all": True} options = {"compress_level": 1, "save_all": True}
def get_command(self, file, **options): @abc.abstractmethod
def get_command_ex(self, file: str, **options: Any) -> tuple[str, str]:
pass
def get_command(self, file: str, **options: Any) -> str:
command = self.get_command_ex(file, **options)[0] command = self.get_command_ex(file, **options)[0]
return f"({command} {quote(file)}" return f"({command} {quote(file)}"
@ -190,11 +196,11 @@ class XDGViewer(UnixViewer):
The freedesktop.org ``xdg-open`` command. The freedesktop.org ``xdg-open`` command.
""" """
def get_command_ex(self, file, **options): def get_command_ex(self, file: str, **options: Any) -> tuple[str, str]:
command = executable = "xdg-open" command = executable = "xdg-open"
return command, executable return command, executable
def show_file(self, path, **options): def show_file(self, path: str, **options: Any) -> int:
""" """
Display given file. Display given file.
""" """
@ -208,13 +214,15 @@ class DisplayViewer(UnixViewer):
This viewer supports the ``title`` parameter. This viewer supports the ``title`` parameter.
""" """
def get_command_ex(self, file, title=None, **options): def get_command_ex(
self, file: str, title: str | None = None, **options: Any
) -> tuple[str, str]:
command = executable = "display" command = executable = "display"
if title: if title:
command += f" -title {quote(title)}" command += f" -title {quote(title)}"
return command, executable return command, executable
def show_file(self, path, **options): def show_file(self, path: str, **options: Any) -> int:
""" """
Display given file. Display given file.
""" """
@ -231,12 +239,12 @@ class DisplayViewer(UnixViewer):
class GmDisplayViewer(UnixViewer): class GmDisplayViewer(UnixViewer):
"""The GraphicsMagick ``gm display`` command.""" """The GraphicsMagick ``gm display`` command."""
def get_command_ex(self, file, **options): def get_command_ex(self, file: str, **options: Any) -> tuple[str, str]:
executable = "gm" executable = "gm"
command = "gm display" command = "gm display"
return command, executable return command, executable
def show_file(self, path, **options): def show_file(self, path: str, **options: Any) -> int:
""" """
Display given file. Display given file.
""" """
@ -247,12 +255,12 @@ class GmDisplayViewer(UnixViewer):
class EogViewer(UnixViewer): class EogViewer(UnixViewer):
"""The GNOME Image Viewer ``eog`` command.""" """The GNOME Image Viewer ``eog`` command."""
def get_command_ex(self, file, **options): def get_command_ex(self, file: str, **options: Any) -> tuple[str, str]:
executable = "eog" executable = "eog"
command = "eog -n" command = "eog -n"
return command, executable return command, executable
def show_file(self, path, **options): def show_file(self, path: str, **options: Any) -> int:
""" """
Display given file. Display given file.
""" """
@ -266,7 +274,9 @@ class XVViewer(UnixViewer):
This viewer supports the ``title`` parameter. This viewer supports the ``title`` parameter.
""" """
def get_command_ex(self, file, title=None, **options): def get_command_ex(
self, file: str, title: str | None = None, **options: Any
) -> tuple[str, str]:
# note: xv is pretty outdated. most modern systems have # note: xv is pretty outdated. most modern systems have
# imagemagick's display command instead. # imagemagick's display command instead.
command = executable = "xv" command = executable = "xv"
@ -274,7 +284,7 @@ class XVViewer(UnixViewer):
command += f" -name {quote(title)}" command += f" -name {quote(title)}"
return command, executable return command, executable
def show_file(self, path, **options): def show_file(self, path: str, **options: Any) -> int:
""" """
Display given file. Display given file.
""" """
@ -304,7 +314,7 @@ if sys.platform not in ("win32", "darwin"): # unixoids
class IPythonViewer(Viewer): class IPythonViewer(Viewer):
"""The viewer for IPython frontends.""" """The viewer for IPython frontends."""
def show_image(self, image, **options): def show_image(self, image: Image.Image, **options: Any) -> int:
ipython_display(image) ipython_display(image)
return 1 return 1

View File

@ -33,6 +33,7 @@ commands =
[testenv:mypy] [testenv:mypy]
skip_install = true skip_install = true
deps = deps =
ipython
mypy==1.7.1 mypy==1.7.1
numpy numpy
extras = extras =