From 878881b1b9997cb9891ce03590f0e988f955d930 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 20 Dec 2016 07:40:06 -0800 Subject: [PATCH 1/4] Fix Access to be reloaded if the python interpreter is restarted when embedded. Fixes #2268. --- Tests/test_image_access.py | 34 +++++++++++++++++++++++++++++++++- libImaging/Access.c | 2 +- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/Tests/test_image_access.py b/Tests/test_image_access.py index 005bd5d35..92e8913a8 100644 --- a/Tests/test_image_access.py +++ b/Tests/test_image_access.py @@ -7,7 +7,7 @@ except ImportError: pass from PIL import Image - +import sys class AccessTest(PillowTestCase): # initial value @@ -249,5 +249,37 @@ class TestCffi(AccessTest): self.assertEqual(px[i, 0], 0) +class TestEmbeddable(unittest.TestCase): + @unittest.skipIf(not sys.platform.startswith('win32'), "requires Windows") + def test_embeddable(self): + import subprocess + from distutils import ccompiler + + with open('embed_pil.c', 'w') as fh: + fh.write(""" +#include "Python.h" + +int main(int argc, char* argv[]) +{ + Py_SetPythonHome( "%s" ); + + Py_InitializeEx( 0 ); + Py_DECREF(PyImport_ImportModule( "PIL.Image" )); + Py_Finalize(); + + Py_InitializeEx( 0 ); + Py_DECREF(PyImport_ImportModule( "PIL.Image" )); + Py_Finalize(); + + return 0; +} + """ % sys.prefix.replace('\\', '\\\\')) + + compiler = ccompiler.new_compiler() + objects = compiler.compile(['embed_pil.c']) + compiler.link_executable(objects, 'embed_pil') + + subprocess.call(['embed_pil.exe']) + if __name__ == '__main__': unittest.main() diff --git a/libImaging/Access.c b/libImaging/Access.c index 059f2aaeb..292968f1c 100644 --- a/libImaging/Access.c +++ b/libImaging/Access.c @@ -32,7 +32,7 @@ add_item(const char* mode) { UINT32 i = hash(mode); /* printf("hash %s => %d\n", mode, i); */ - if (access_table[i].mode) { + if (access_table[i].mode && strcmp(access_table[i].mode, mode) != 0) { fprintf(stderr, "AccessInit: hash collision: %d for both %s and %s\n", i, mode, access_table[i].mode); exit(1); From 6c1f923368d2ad2dacb5b02f82aeedd39f016441 Mon Sep 17 00:00:00 2001 From: Eric Soroos Date: Wed, 11 Jan 2017 14:12:31 -0800 Subject: [PATCH 2/4] fixed test on python27 OMM --- Tests/test_image_access.py | 40 +++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/Tests/test_image_access.py b/Tests/test_image_access.py index 92e8913a8..d27a0f2e5 100644 --- a/Tests/test_image_access.py +++ b/Tests/test_image_access.py @@ -250,10 +250,14 @@ class TestCffi(AccessTest): class TestEmbeddable(unittest.TestCase): - @unittest.skipIf(not sys.platform.startswith('win32'), "requires Windows") + @unittest.skipIf(not sys.platform.startswith('win32') or + sys.version_info[:2] in ((3, 3), (3, 4)), + "requires Python 2.7 or >=3.5 for Windows") def test_embeddable(self): import subprocess - from distutils import ccompiler + import ctypes + import setuptools + from distutils import ccompiler, sysconfig with open('embed_pil.c', 'w') as fh: fh.write(""" @@ -261,25 +265,43 @@ class TestEmbeddable(unittest.TestCase): int main(int argc, char* argv[]) { - Py_SetPythonHome( "%s" ); + char *home = "%s"; +#if PY_MAJOR_VERSION >= 3 + wchar_t *whome = Py_DecodeLocale(home, NULL); + Py_SetPythonHome(whome); +#else + Py_SetPythonHome(home); +#endif - Py_InitializeEx( 0 ); - Py_DECREF(PyImport_ImportModule( "PIL.Image" )); + Py_InitializeEx(0); + Py_DECREF(PyImport_ImportModule("PIL.Image")); Py_Finalize(); - Py_InitializeEx( 0 ); - Py_DECREF(PyImport_ImportModule( "PIL.Image" )); + Py_InitializeEx(0); + Py_DECREF(PyImport_ImportModule("PIL.Image")); Py_Finalize(); +#if PY_MAJOR_VERSION >= 3 + PyMem_RawFree(whome); +#endif + return 0; -} +} """ % sys.prefix.replace('\\', '\\\\')) compiler = ccompiler.new_compiler() + compiler.add_include_dir(sysconfig.get_python_inc()) + compiler.add_library_dir(sysconfig.get_config_var('LIBDIR')) objects = compiler.compile(['embed_pil.c']) compiler.link_executable(objects, 'embed_pil') - subprocess.call(['embed_pil.exe']) + # do not display the Windows Error Reporting dialog + ctypes.windll.kernel32.SetErrorMode(0x0002) + + process = subprocess.Popen(['embed_pil.exe']) + process.communicate() + self.assertEqual(process.returncode, 0) + if __name__ == '__main__': unittest.main() From 1c7e8a18d5f0d8061f270883d4dba3439fa4f206 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Wed, 11 Jan 2017 15:45:19 -0800 Subject: [PATCH 3/4] fix for appveyor environment? --- Tests/test_image_access.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Tests/test_image_access.py b/Tests/test_image_access.py index d27a0f2e5..676042a41 100644 --- a/Tests/test_image_access.py +++ b/Tests/test_image_access.py @@ -8,6 +8,7 @@ except ImportError: from PIL import Image import sys +import os class AccessTest(PillowTestCase): # initial value @@ -291,17 +292,22 @@ int main(int argc, char* argv[]) compiler = ccompiler.new_compiler() compiler.add_include_dir(sysconfig.get_python_inc()) - compiler.add_library_dir(sysconfig.get_config_var('LIBDIR')) + + libdir = sysconfig.get_config_var('LIBDIR') or sysconfig.get_python_inc().replace('include', 'libs') + print (libdir) + compiler.add_library_dir(libdir) objects = compiler.compile(['embed_pil.c']) compiler.link_executable(objects, 'embed_pil') + + env = os.environ.copy() + env["PATH"] = sys.prefix + ';' + env["PATH"] # do not display the Windows Error Reporting dialog ctypes.windll.kernel32.SetErrorMode(0x0002) - process = subprocess.Popen(['embed_pil.exe']) + process = subprocess.Popen(['embed_pil.exe'], env=env) process.communicate() self.assertEqual(process.returncode, 0) - if __name__ == '__main__': unittest.main() From fe0a33173bb9a025ea4d0a76c05d76f3992eb55c Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 3 Apr 2017 11:17:30 -0700 Subject: [PATCH 4/4] Give up on appveyor for now, disable test --- Tests/test_image_access.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Tests/test_image_access.py b/Tests/test_image_access.py index 676042a41..87387bff1 100644 --- a/Tests/test_image_access.py +++ b/Tests/test_image_access.py @@ -1,4 +1,4 @@ -from helper import unittest, PillowTestCase, hopper +from helper import unittest, PillowTestCase, hopper, on_appveyor try: from PIL import PyAccess @@ -252,7 +252,9 @@ class TestCffi(AccessTest): class TestEmbeddable(unittest.TestCase): @unittest.skipIf(not sys.platform.startswith('win32') or - sys.version_info[:2] in ((3, 3), (3, 4)), + sys.version_info[:2] in ((3, 3), (3, 4)) or + on_appveyor(), # failing on appveyor when run from + # subprocess, not from shell "requires Python 2.7 or >=3.5 for Windows") def test_embeddable(self): import subprocess