From 9240ec96c06c702a27f58021b634851cfa7b6491 Mon Sep 17 00:00:00 2001 From: Joey Marianer Date: Tue, 19 Aug 2025 22:01:07 -0700 Subject: [PATCH] Allow pyright to "see" core properly Without this change, the following file raises errors (in strict mode) and reveals the type as "Unknown". After this change, the type is correctly revealed as "ImagingCore". # pyright: strict from PIL import Image img = Image.new('RGB', (10, 10)) data = img.getdata() reveal_type(data) --- src/PIL/Image.py | 61 +++++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/src/PIL/Image.py b/src/PIL/Image.py index b7c185e0d..d8b523826 100644 --- a/src/PIL/Image.py +++ b/src/PIL/Image.py @@ -86,38 +86,41 @@ WARN_POSSIBLE_FORMATS: bool = False MAX_IMAGE_PIXELS: int | None = int(1024 * 1024 * 1024 // 4 // 3) -try: - # If the _imaging C module is not present, Pillow will not load. - # Note that other modules should not refer to _imaging directly; - # import Image and use the Image.core variable instead. - # Also note that Image.core is not a publicly documented interface, - # and should be considered private and subject to change. +if TYPE_CHECKING: from . import _imaging as core +else: + try: + # If the _imaging C module is not present, Pillow will not load. + # Note that other modules should not refer to _imaging directly; + # import Image and use the Image.core variable instead. + # Also note that Image.core is not a publicly documented interface, + # and should be considered private and subject to change. + from . import _imaging as core - if __version__ != getattr(core, "PILLOW_VERSION", None): - msg = ( - "The _imaging extension was built for another version of Pillow or PIL:\n" - f"Core version: {getattr(core, 'PILLOW_VERSION', None)}\n" - f"Pillow version: {__version__}" - ) - raise ImportError(msg) + if __version__ != getattr(core, "PILLOW_VERSION", None): + msg = ( + "The _imaging extension was built for another version of Pillow or PIL:\n" + f"Core version: {getattr(core, 'PILLOW_VERSION', None)}\n" + f"Pillow version: {__version__}" + ) + raise ImportError(msg) -except ImportError as v: - core = DeferredError.new(ImportError("The _imaging C module is not installed.")) - # Explanations for ways that we know we might have an import error - if str(v).startswith("Module use of python"): - # The _imaging C module is present, but not compiled for - # the right version (windows only). Print a warning, if - # possible. - warnings.warn( - "The _imaging extension was built for another version of Python.", - RuntimeWarning, - ) - elif str(v).startswith("The _imaging extension"): - warnings.warn(str(v), RuntimeWarning) - # Fail here anyway. Don't let people run with a mostly broken Pillow. - # see docs/porting.rst - raise + except ImportError as v: + core = DeferredError.new(ImportError("The _imaging C module is not installed.")) + # Explanations for ways that we know we might have an import error + if str(v).startswith("Module use of python"): + # The _imaging C module is present, but not compiled for + # the right version (windows only). Print a warning, if + # possible. + warnings.warn( + "The _imaging extension was built for another version of Python.", + RuntimeWarning, + ) + elif str(v).startswith("The _imaging extension"): + warnings.warn(str(v), RuntimeWarning) + # Fail here anyway. Don't let people run with a mostly broken Pillow. + # see docs/porting.rst + raise #