Format with Black

This commit is contained in:
Hugo 2019-06-13 18:54:57 +03:00
parent 5631718a8d
commit 471220093b
14 changed files with 712 additions and 545 deletions

View File

@ -29,27 +29,26 @@ import PIL
# Add any Sphinx extension module names here, as strings. They can be # Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones. # ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode', extensions = ["sphinx.ext.autodoc", "sphinx.ext.viewcode", "sphinx.ext.intersphinx"]
'sphinx.ext.intersphinx']
# Add any paths that contain templates here, relative to this directory. # Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates'] templates_path = ["_templates"]
# The suffix(es) of source filenames. # The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string: # You can specify multiple suffix as a list of string:
# source_suffix = ['.rst', '.md'] # source_suffix = ['.rst', '.md']
source_suffix = '.rst' source_suffix = ".rst"
# The encoding of source files. # The encoding of source files.
# source_encoding = 'utf-8-sig' # source_encoding = 'utf-8-sig'
# The master toctree document. # The master toctree document.
master_doc = 'index' master_doc = "index"
# General information about the project. # General information about the project.
project = u'Pillow (PIL Fork)' project = u"Pillow (PIL Fork)"
copyright = u'1995-2011 Fredrik Lundh, 2010-2019 Alex Clark and Contributors' copyright = u"1995-2011 Fredrik Lundh, 2010-2019 Alex Clark and Contributors"
author = u'Fredrik Lundh, Alex Clark and Contributors' author = u"Fredrik Lundh, Alex Clark and Contributors"
# The version info for the project you're documenting, acts as replacement for # The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the # |version| and |release|, also used in various other places throughout the
@ -75,7 +74,7 @@ language = None
# List of patterns, relative to source directory, that match files and # List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files. # directories to ignore when looking for source files.
exclude_patterns = ['_build'] exclude_patterns = ["_build"]
# The reST default role (used for this markup: `text`) to use for all # The reST default role (used for this markup: `text`) to use for all
# documents. # documents.
@ -93,7 +92,7 @@ exclude_patterns = ['_build']
# show_authors = False # show_authors = False
# The name of the Pygments (syntax highlighting) style to use. # The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx' pygments_style = "sphinx"
# A list of ignored prefixes for module index sorting. # A list of ignored prefixes for module index sorting.
# modindex_common_prefix = [] # modindex_common_prefix = []
@ -140,7 +139,7 @@ html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
# Add any paths that contain custom static files (such as style sheets) here, # Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files, # relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css". # so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static', 'resources'] html_static_path = ["_static", "resources"]
# Add any extra paths that contain custom files (such as robots.txt or # Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied # .htaccess) here, relative to this directory. These files are copied
@ -203,20 +202,17 @@ html_static_path = ['_static', 'resources']
# html_search_scorer = 'scorer.js' # html_search_scorer = 'scorer.js'
# Output file base name for HTML help builder. # Output file base name for HTML help builder.
htmlhelp_basename = 'PillowPILForkdoc' htmlhelp_basename = "PillowPILForkdoc"
# -- Options for LaTeX output --------------------------------------------- # -- Options for LaTeX output ---------------------------------------------
latex_elements = { latex_elements = {
# The paper size ('letterpaper' or 'a4paper'). # The paper size ('letterpaper' or 'a4paper').
# 'papersize': 'letterpaper', # 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt'). # The font size ('10pt', '11pt' or '12pt').
# 'pointsize': '10pt', # 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble. # Additional stuff for the LaTeX preamble.
# 'preamble': '', # 'preamble': '',
# Latex figure (float) alignment # Latex figure (float) alignment
# 'figure_align': 'htbp', # 'figure_align': 'htbp',
} }
@ -225,8 +221,13 @@ latex_elements = {
# (source start file, target name, title, # (source start file, target name, title,
# author, documentclass [howto, manual, or own class]). # author, documentclass [howto, manual, or own class]).
latex_documents = [ latex_documents = [
(master_doc, 'PillowPILFork.tex', u'Pillow (PIL Fork) Documentation', (
u'Alex Clark', 'manual'), master_doc,
"PillowPILFork.tex",
u"Pillow (PIL Fork) Documentation",
u"Alex Clark",
"manual",
)
] ]
# The name of an image file (relative to this directory) to place at the top of # The name of an image file (relative to this directory) to place at the top of
@ -255,8 +256,7 @@ latex_documents = [
# One entry per manual page. List of tuples # One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section). # (source start file, name, description, authors, manual section).
man_pages = [ man_pages = [
(master_doc, 'pillowpilfork', u'Pillow (PIL Fork) Documentation', (master_doc, "pillowpilfork", u"Pillow (PIL Fork) Documentation", [author], 1)
[author], 1)
] ]
# If true, show URL addresses after external links. # If true, show URL addresses after external links.
@ -269,10 +269,15 @@ man_pages = [
# (source start file, target name, title, author, # (source start file, target name, title, author,
# dir menu entry, description, category) # dir menu entry, description, category)
texinfo_documents = [ texinfo_documents = [
(master_doc, 'PillowPILFork', u'Pillow (PIL Fork) Documentation', (
author, 'PillowPILFork', master_doc,
'Pillow is the friendly PIL fork by Alex Clark and Contributors.', "PillowPILFork",
'Miscellaneous'), u"Pillow (PIL Fork) Documentation",
author,
"PillowPILFork",
"Pillow is the friendly PIL fork by Alex Clark and Contributors.",
"Miscellaneous",
)
] ]
# Documents to append as an appendix to all manuals. # Documents to append as an appendix to all manuals.
@ -289,4 +294,4 @@ texinfo_documents = [
def setup(app): def setup(app):
app.add_javascript('js/script.js') app.add_javascript("js/script.js")

View File

@ -61,8 +61,7 @@ DDS_LUMINANCEA = DDPF_LUMINANCE | DDPF_ALPHAPIXELS
DDS_ALPHA = DDPF_ALPHA DDS_ALPHA = DDPF_ALPHA
DDS_PAL8 = DDPF_PALETTEINDEXED8 DDS_PAL8 = DDPF_PALETTEINDEXED8
DDS_HEADER_FLAGS_TEXTURE = (DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDS_HEADER_FLAGS_TEXTURE = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT
DDSD_PIXELFORMAT)
DDS_HEADER_FLAGS_MIPMAP = DDSD_MIPMAPCOUNT DDS_HEADER_FLAGS_MIPMAP = DDSD_MIPMAPCOUNT
DDS_HEADER_FLAGS_VOLUME = DDSD_DEPTH DDS_HEADER_FLAGS_VOLUME = DDSD_DEPTH
DDS_HEADER_FLAGS_PITCH = DDSD_PITCH DDS_HEADER_FLAGS_PITCH = DDSD_PITCH
@ -94,9 +93,9 @@ DXT5_FOURCC = 0x35545844
def _decode565(bits): def _decode565(bits):
a = ((bits >> 11) & 0x1f) << 3 a = ((bits >> 11) & 0x1F) << 3
b = ((bits >> 5) & 0x3f) << 2 b = ((bits >> 5) & 0x3F) << 2
c = (bits & 0x1f) << 3 c = (bits & 0x1F) << 3
return a, b, c return a, b, c
@ -145,7 +144,7 @@ def _dxt1(data, width, height):
r, g, b = 0, 0, 0 r, g, b = 0, 0, 0
idx = 4 * ((y + j) * width + x + i) idx = 4 * ((y + j) * width + x + i)
ret[idx:idx+4] = struct.pack('4B', r, g, b, 255) ret[idx : idx + 4] = struct.pack("4B", r, g, b, 255)
return bytes(ret) return bytes(ret)
@ -167,7 +166,7 @@ def _dxtc_alpha(a0, a1, ac0, ac1, ai):
elif ac == 6: elif ac == 6:
alpha = 0 alpha = 0
elif ac == 7: elif ac == 7:
alpha = 0xff alpha = 0xFF
else: else:
alpha = ((6 - ac) * a0 + (ac - 1) * a1) // 5 alpha = ((6 - ac) * a0 + (ac - 1) * a1) // 5
@ -180,8 +179,7 @@ def _dxt5(data, width, height):
for y in range(0, height, 4): for y in range(0, height, 4):
for x in range(0, width, 4): for x in range(0, width, 4):
a0, a1, ac0, ac1, c0, c1, code = struct.unpack("<2BHI2HI", a0, a1, ac0, ac1, c0, c1, code = struct.unpack("<2BHI2HI", data.read(16))
data.read(16))
r0, g0, b0 = _decode565(c0) r0, g0, b0 = _decode565(c0)
r1, g1, b1 = _decode565(c1) r1, g1, b1 = _decode565(c1)
@ -202,7 +200,7 @@ def _dxt5(data, width, height):
r, g, b = _c3(r0, r1), _c3(g0, g1), _c3(b0, b1) r, g, b = _c3(r0, r1), _c3(g0, g1), _c3(b0, b1)
idx = 4 * ((y + j) * width + x + i) idx = 4 * ((y + j) * width + x + i)
ret[idx:idx+4] = struct.pack('4B', r, g, b, alpha) ret[idx : idx + 4] = struct.pack("4B", r, g, b, alpha)
return bytes(ret) return bytes(ret)
@ -230,8 +228,7 @@ class DdsImageFile(ImageFile.ImageFile):
# pixel format # pixel format
pfsize, pfflags = struct.unpack("<2I", header.read(8)) pfsize, pfflags = struct.unpack("<2I", header.read(8))
fourcc = header.read(4) fourcc = header.read(4)
bitcount, rmask, gmask, bmask, amask = struct.unpack("<5I", bitcount, rmask, gmask, bmask, amask = struct.unpack("<5I", header.read(20))
header.read(20))
if fourcc == b"DXT1": if fourcc == b"DXT1":
self.decoder = "DXT1" self.decoder = "DXT1"
@ -240,9 +237,7 @@ class DdsImageFile(ImageFile.ImageFile):
else: else:
raise NotImplementedError("Unimplemented pixel format %r" % fourcc) raise NotImplementedError("Unimplemented pixel format %r" % fourcc)
self.tile = [ self.tile = [(self.decoder, (0, 0) + self.size, 0, (self.mode, 0, 1))]
(self.decoder, (0, 0) + self.size, 0, (self.mode, 0, 1))
]
def load_seek(self, pos): def load_seek(self, pos):
pass pass
@ -270,8 +265,8 @@ class DXT5Decoder(ImageFile.PyDecoder):
return 0, 0 return 0, 0
Image.register_decoder('DXT1', DXT1Decoder) Image.register_decoder("DXT1", DXT1Decoder)
Image.register_decoder('DXT5', DXT5Decoder) Image.register_decoder("DXT5", DXT5Decoder)
def _validate(prefix): def _validate(prefix):

View File

@ -10,7 +10,7 @@ import os
import sys import sys
try: try:
MAX_PROCS = int(os.environ.get('MAX_CONCURRENCY', min(4, cpu_count()))) MAX_PROCS = int(os.environ.get("MAX_CONCURRENCY", min(4, cpu_count())))
except NotImplementedError: except NotImplementedError:
MAX_PROCS = None MAX_PROCS = None
@ -26,9 +26,17 @@ def _mp_compile_one(tp):
return return
def _mp_compile(self, sources, output_dir=None, macros=None, def _mp_compile(
include_dirs=None, debug=0, extra_preargs=None, self,
extra_postargs=None, depends=None): sources,
output_dir=None,
macros=None,
include_dirs=None,
debug=0,
extra_preargs=None,
extra_postargs=None,
depends=None,
):
"""Compile one or more source files. """Compile one or more source files.
see distutils.ccompiler.CCompiler.compile for comments. see distutils.ccompiler.CCompiler.compile for comments.
@ -37,7 +45,8 @@ def _mp_compile(self, sources, output_dir=None, macros=None,
# entirely or implement _compile(). # entirely or implement _compile().
macros, objects, extra_postargs, pp_opts, build = self._setup_compile( macros, objects, extra_postargs, pp_opts, build = self._setup_compile(
output_dir, macros, include_dirs, sources, depends, extra_postargs) output_dir, macros, include_dirs, sources, depends, extra_postargs
)
cc_args = self._get_cc_args(pp_opts, debug, extra_preargs) cc_args = self._get_cc_args(pp_opts, debug, extra_preargs)
pool = Pool(MAX_PROCS) pool = Pool(MAX_PROCS)
@ -45,8 +54,7 @@ def _mp_compile(self, sources, output_dir=None, macros=None,
print("Building using %d processes" % pool._processes) print("Building using %d processes" % pool._processes)
except Exception: except Exception:
pass pass
arr = [(self, obj, build, cc_args, extra_postargs, pp_opts) arr = [(self, obj, build, cc_args, extra_postargs, pp_opts) for obj in objects]
for obj in objects]
pool.map_async(_mp_compile_one, arr) pool.map_async(_mp_compile_one, arr)
pool.close() pool.close()
pool.join() pool.join()
@ -56,8 +64,8 @@ def _mp_compile(self, sources, output_dir=None, macros=None,
def install(): def install():
fl_win = sys.platform.startswith('win') fl_win = sys.platform.startswith("win")
fl_cygwin = sys.platform.startswith('cygwin') fl_cygwin = sys.platform.startswith("cygwin")
if fl_win or fl_cygwin: if fl_win or fl_cygwin:
# Windows barfs on multiprocessing installs # Windows barfs on multiprocessing installs
@ -72,11 +80,11 @@ def install():
Pool(2) Pool(2)
CCompiler.compile = _mp_compile CCompiler.compile = _mp_compile
except Exception as msg: except Exception as msg:
print("Exception installing mp_compile, proceeding without:" print("Exception installing mp_compile, proceeding without: %s" % msg)
"%s" % msg)
else: else:
print("Single threaded build, not installing mp_compile:" print(
"%s processes" % MAX_PROCS) "Single threaded build, not installing mp_compile: %s processes" % MAX_PROCS
)
# We monkeypatch Python 2.7 # We monkeypatch Python 2.7

View File

@ -161,12 +161,12 @@ if __name__ == "__main__":
exit_status = 0 exit_status = 0
print("-"*68) print("-" * 68)
print("Pillow", Image.__version__, "TEST SUMMARY ") print("Pillow", Image.__version__, "TEST SUMMARY ")
print("-"*68) print("-" * 68)
print("Python modules loaded from", os.path.dirname(Image.__file__)) print("Python modules loaded from", os.path.dirname(Image.__file__))
print("Binary modules loaded from", os.path.dirname(Image.core.__file__)) print("Binary modules loaded from", os.path.dirname(Image.core.__file__))
print("-"*68) print("-" * 68)
for name, feature in [ for name, feature in [
("pil", "PIL CORE"), ("pil", "PIL CORE"),
("tkinter", "TKINTER"), ("tkinter", "TKINTER"),
@ -180,16 +180,17 @@ if __name__ == "__main__":
("jpg_2000", "OPENJPEG (JPEG2000)"), ("jpg_2000", "OPENJPEG (JPEG2000)"),
("zlib", "ZLIB (PNG/ZIP)"), ("zlib", "ZLIB (PNG/ZIP)"),
("libtiff", "LIBTIFF"), ("libtiff", "LIBTIFF"),
("raqm", "RAQM (Bidirectional Text)") ("raqm", "RAQM (Bidirectional Text)"),
]: ]:
if features.check(name): if features.check(name):
print("---", feature, "support ok") print("---", feature, "support ok")
else: else:
print("***", feature, "support not installed") print("***", feature, "support not installed")
print("-"*68) print("-" * 68)
# use doctest to make sure the test program behaves as documented! # use doctest to make sure the test program behaves as documented!
import doctest import doctest
print("Running selftest:") print("Running selftest:")
status = doctest.testmod(sys.modules[__name__]) status = doctest.testmod(sys.modules[__name__])
if status[0]: if status[0]:

504
setup.py
View File

@ -29,26 +29,81 @@ if sys.platform == "win32" and sys.version_info >= (3, 8):
warnings.warn( warnings.warn(
"Pillow does not yet support Python {}.{} and does not yet provide " "Pillow does not yet support Python {}.{} and does not yet provide "
"prebuilt Windows binaries. We do not recommend building from " "prebuilt Windows binaries. We do not recommend building from "
"source on Windows.".format(sys.version_info.major, "source on Windows.".format(sys.version_info.major, sys.version_info.minor),
sys.version_info.minor), RuntimeWarning,
RuntimeWarning) )
_IMAGING = ("decode", "encode", "map", "display", "outline", "path") _IMAGING = ("decode", "encode", "map", "display", "outline", "path")
_LIB_IMAGING = ( _LIB_IMAGING = (
"Access", "AlphaComposite", "Resample", "Bands", "BcnDecode", "BitDecode", "Access",
"Blend", "Chops", "ColorLUT", "Convert", "ConvertYCbCr", "Copy", "Crop", "AlphaComposite",
"Dib", "Draw", "Effects", "EpsEncode", "File", "Fill", "Filter", "Resample",
"FliDecode", "Geometry", "GetBBox", "GifDecode", "GifEncode", "HexDecode", "Bands",
"Histo", "JpegDecode", "JpegEncode", "Matrix", "ModeFilter", "BcnDecode",
"Negative", "Offset", "Pack", "PackDecode", "Palette", "Paste", "Quant", "BitDecode",
"QuantOctree", "QuantHash", "QuantHeap", "PcdDecode", "PcxDecode", "Blend",
"PcxEncode", "Point", "RankFilter", "RawDecode", "RawEncode", "Storage", "Chops",
"SgiRleDecode", "SunRleDecode", "TgaRleDecode", "TgaRleEncode", "Unpack", "ColorLUT",
"UnpackYCC", "UnsharpMask", "XbmDecode", "XbmEncode", "ZipDecode", "Convert",
"ZipEncode", "TiffDecode", "Jpeg2KDecode", "Jpeg2KEncode", "BoxBlur", "ConvertYCbCr",
"QuantPngQuant", "codec_fd") "Copy",
"Crop",
"Dib",
"Draw",
"Effects",
"EpsEncode",
"File",
"Fill",
"Filter",
"FliDecode",
"Geometry",
"GetBBox",
"GifDecode",
"GifEncode",
"HexDecode",
"Histo",
"JpegDecode",
"JpegEncode",
"Matrix",
"ModeFilter",
"Negative",
"Offset",
"Pack",
"PackDecode",
"Palette",
"Paste",
"Quant",
"QuantOctree",
"QuantHash",
"QuantHeap",
"PcdDecode",
"PcxDecode",
"PcxEncode",
"Point",
"RankFilter",
"RawDecode",
"RawEncode",
"Storage",
"SgiRleDecode",
"SunRleDecode",
"TgaRleDecode",
"TgaRleEncode",
"Unpack",
"UnpackYCC",
"UnsharpMask",
"XbmDecode",
"XbmEncode",
"ZipDecode",
"ZipEncode",
"TiffDecode",
"Jpeg2KDecode",
"Jpeg2KEncode",
"BoxBlur",
"QuantPngQuant",
"codec_fd",
)
DEBUG = False DEBUG = False
@ -61,8 +116,8 @@ class RequiredDependencyException(Exception):
pass pass
PLATFORM_MINGW = 'mingw' in ccompiler.get_default_compiler() PLATFORM_MINGW = "mingw" in ccompiler.get_default_compiler()
PLATFORM_PYPY = hasattr(sys, 'pypy_version_info') PLATFORM_PYPY = hasattr(sys, "pypy_version_info")
def _dbg(s, tp=None): def _dbg(s, tp=None):
@ -77,39 +132,36 @@ def _find_library_dirs_ldconfig():
# Based on ctypes.util from Python 2 # Based on ctypes.util from Python 2
if sys.platform.startswith("linux") or sys.platform.startswith("gnu"): if sys.platform.startswith("linux") or sys.platform.startswith("gnu"):
if struct.calcsize('l') == 4: if struct.calcsize("l") == 4:
machine = os.uname()[4] + '-32' machine = os.uname()[4] + "-32"
else: else:
machine = os.uname()[4] + '-64' machine = os.uname()[4] + "-64"
mach_map = { mach_map = {
'x86_64-64': 'libc6,x86-64', "x86_64-64": "libc6,x86-64",
'ppc64-64': 'libc6,64bit', "ppc64-64": "libc6,64bit",
'sparc64-64': 'libc6,64bit', "sparc64-64": "libc6,64bit",
's390x-64': 'libc6,64bit', "s390x-64": "libc6,64bit",
'ia64-64': 'libc6,IA-64', "ia64-64": "libc6,IA-64",
} }
abi_type = mach_map.get(machine, 'libc6') abi_type = mach_map.get(machine, "libc6")
# Assuming GLIBC's ldconfig (with option -p) # Assuming GLIBC's ldconfig (with option -p)
# Alpine Linux uses musl that can't print cache # Alpine Linux uses musl that can't print cache
args = ['/sbin/ldconfig', '-p'] args = ["/sbin/ldconfig", "-p"]
expr = r'.*\(%s.*\) => (.*)' % abi_type expr = r".*\(%s.*\) => (.*)" % abi_type
env = dict(os.environ) env = dict(os.environ)
env['LC_ALL'] = 'C' env["LC_ALL"] = "C"
env['LANG'] = 'C' env["LANG"] = "C"
elif sys.platform.startswith("freebsd"): elif sys.platform.startswith("freebsd"):
args = ['/sbin/ldconfig', '-r'] args = ["/sbin/ldconfig", "-r"]
expr = r'.* => (.*)' expr = r".* => (.*)"
env = {} env = {}
null = open(os.devnull, 'wb') null = open(os.devnull, "wb")
try: try:
with null: with null:
p = subprocess.Popen(args, p = subprocess.Popen(args, stderr=null, stdout=subprocess.PIPE, env=env)
stderr=null,
stdout=subprocess.PIPE,
env=env)
except OSError: # E.g. command not found except OSError: # E.g. command not found
return [] return []
[data, _] = p.communicate() [data, _] = p.communicate()
@ -130,10 +182,10 @@ def _add_directory(path, subdir, where=None):
subdir = os.path.realpath(subdir) subdir = os.path.realpath(subdir)
if os.path.isdir(subdir) and subdir not in path: if os.path.isdir(subdir) and subdir not in path:
if where is None: if where is None:
_dbg('Appending path %s', subdir) _dbg("Appending path %s", subdir)
path.append(subdir) path.append(subdir)
else: else:
_dbg('Inserting path %s', subdir) _dbg("Inserting path %s", subdir)
path.insert(where, subdir) path.insert(where, subdir)
elif subdir in path and where is not None: elif subdir in path and where is not None:
path.remove(subdir) path.remove(subdir)
@ -142,9 +194,9 @@ def _add_directory(path, subdir, where=None):
def _find_include_file(self, include): def _find_include_file(self, include):
for directory in self.compiler.include_dirs: for directory in self.compiler.include_dirs:
_dbg('Checking for include file %s in %s', (include, directory)) _dbg("Checking for include file %s in %s", (include, directory))
if os.path.isfile(os.path.join(directory, include)): if os.path.isfile(os.path.join(directory, include)):
_dbg('Found %s', include) _dbg("Found %s", include)
return 1 return 1
return 0 return 0
@ -152,10 +204,9 @@ def _find_include_file(self, include):
def _find_library_file(self, library): def _find_library_file(self, library):
ret = self.compiler.find_library_file(self.compiler.library_dirs, library) ret = self.compiler.find_library_file(self.compiler.library_dirs, library)
if ret: if ret:
_dbg('Found library %s at %s', (library, ret)) _dbg("Found library %s at %s", (library, ret))
else: else:
_dbg("Couldn't find library %s in %s", _dbg("Couldn't find library %s in %s", (library, self.compiler.library_dirs))
(library, self.compiler.library_dirs))
return ret return ret
@ -167,18 +218,18 @@ def _cmd_exists(cmd):
def _read(file): def _read(file):
with open(file, 'rb') as fp: with open(file, "rb") as fp:
return fp.read() return fp.read()
def get_version(): def get_version():
version_file = 'src/PIL/_version.py' version_file = "src/PIL/_version.py"
with open(version_file, 'r') as f: with open(version_file, "r") as f:
exec(compile(f.read(), version_file, 'exec')) exec(compile(f.read(), version_file, "exec"))
return locals()['__version__'] return locals()["__version__"]
NAME = 'Pillow' NAME = "Pillow"
PILLOW_VERSION = get_version() PILLOW_VERSION = get_version()
JPEG_ROOT = None JPEG_ROOT = None
JPEG2K_ROOT = None JPEG2K_ROOT = None
@ -191,17 +242,11 @@ LCMS_ROOT = None
def _pkg_config(name): def _pkg_config(name):
try: try:
command_libs = [ command_libs = ["pkg-config", "--libs-only-L", name]
'pkg-config', command_cflags = ["pkg-config", "--cflags-only-I", name]
'--libs-only-L', name,
]
command_cflags = [
'pkg-config',
'--cflags-only-I', name,
]
if not DEBUG: if not DEBUG:
command_libs.append('--silence-errors') command_libs.append("--silence-errors")
command_cflags.append('--silence-errors') command_cflags.append("--silence-errors")
libs = ( libs = (
subprocess.check_output(command_libs) subprocess.check_output(command_libs)
.decode("utf8") .decode("utf8")
@ -221,10 +266,19 @@ def _pkg_config(name):
class pil_build_ext(build_ext): class pil_build_ext(build_ext):
class feature: class feature:
features = ['zlib', 'jpeg', 'tiff', 'freetype', 'lcms', 'webp', features = [
'webpmux', 'jpeg2000', 'imagequant'] "zlib",
"jpeg",
"tiff",
"freetype",
"lcms",
"webp",
"webpmux",
"jpeg2000",
"imagequant",
]
required = {'jpeg', 'zlib'} required = {"jpeg", "zlib"}
def __init__(self): def __init__(self):
for f in self.features: for f in self.features:
@ -242,23 +296,24 @@ class pil_build_ext(build_ext):
feature = feature() feature = feature()
user_options = build_ext.user_options + [ user_options = (
('disable-%s' % x, None, 'Disable support for %s' % x) for x in feature build_ext.user_options
] + [ + [("disable-%s" % x, None, "Disable support for %s" % x) for x in feature]
('enable-%s' % x, None, 'Enable support for %s' % x) for x in feature + [("enable-%s" % x, None, "Enable support for %s" % x) for x in feature]
] + [ + [
('disable-platform-guessing', None, ("disable-platform-guessing", None, "Disable platform guessing on Linux"),
'Disable platform guessing on Linux'), ("debug", None, "Debug logging"),
('debug', None, 'Debug logging') ]
] + [('add-imaging-libs=', None, 'Add libs to _imaging build')] + [("add-imaging-libs=", None, "Add libs to _imaging build")]
)
def initialize_options(self): def initialize_options(self):
self.disable_platform_guessing = None self.disable_platform_guessing = None
self.add_imaging_libs = "" self.add_imaging_libs = ""
build_ext.initialize_options(self) build_ext.initialize_options(self)
for x in self.feature: for x in self.feature:
setattr(self, 'disable_%s' % x, None) setattr(self, "disable_%s" % x, None)
setattr(self, 'enable_%s' % x, None) setattr(self, "enable_%s" % x, None)
def finalize_options(self): def finalize_options(self):
build_ext.finalize_options(self) build_ext.finalize_options(self)
@ -272,16 +327,16 @@ class pil_build_ext(build_ext):
# number of jobs. # number of jobs.
self.parallel = mp_compile.MAX_PROCS self.parallel = mp_compile.MAX_PROCS
for x in self.feature: for x in self.feature:
if getattr(self, 'disable_%s' % x): if getattr(self, "disable_%s" % x):
setattr(self.feature, x, False) setattr(self.feature, x, False)
self.feature.required.discard(x) self.feature.required.discard(x)
_dbg('Disabling %s', x) _dbg("Disabling %s", x)
if getattr(self, 'enable_%s' % x): if getattr(self, "enable_%s" % x):
raise ValueError( raise ValueError(
'Conflicting options: --enable-%s and --disable-%s' % "Conflicting options: --enable-%s and --disable-%s" % (x, x)
(x, x)) )
if getattr(self, 'enable_%s' % x): if getattr(self, "enable_%s" % x):
_dbg('Requiring %s', x) _dbg("Requiring %s", x)
self.feature.required.add(x) self.feature.required.add(x)
def build_extensions(self): def build_extensions(self):
@ -292,34 +347,35 @@ class pil_build_ext(build_ext):
_add_directory(include_dirs, "src/libImaging") _add_directory(include_dirs, "src/libImaging")
pkg_config = None pkg_config = None
if _cmd_exists('pkg-config'): if _cmd_exists("pkg-config"):
pkg_config = _pkg_config pkg_config = _pkg_config
# #
# add configured kits # add configured kits
for root_name, lib_name in dict(JPEG_ROOT="libjpeg", for root_name, lib_name in dict(
JPEG_ROOT="libjpeg",
JPEG2K_ROOT="libopenjp2", JPEG2K_ROOT="libopenjp2",
TIFF_ROOT=("libtiff-5", "libtiff-4"), TIFF_ROOT=("libtiff-5", "libtiff-4"),
ZLIB_ROOT="zlib", ZLIB_ROOT="zlib",
FREETYPE_ROOT="freetype2", FREETYPE_ROOT="freetype2",
LCMS_ROOT="lcms2", LCMS_ROOT="lcms2",
IMAGEQUANT_ROOT="libimagequant" IMAGEQUANT_ROOT="libimagequant",
).items(): ).items():
root = globals()[root_name] root = globals()[root_name]
if root is None and root_name in os.environ: if root is None and root_name in os.environ:
prefix = os.environ[root_name] prefix = os.environ[root_name]
root = (os.path.join(prefix, 'lib'), os.path.join(prefix, 'include')) root = (os.path.join(prefix, "lib"), os.path.join(prefix, "include"))
if root is None and pkg_config: if root is None and pkg_config:
if isinstance(lib_name, tuple): if isinstance(lib_name, tuple):
for lib_name2 in lib_name: for lib_name2 in lib_name:
_dbg('Looking for `%s` using pkg-config.' % lib_name2) _dbg("Looking for `%s` using pkg-config." % lib_name2)
root = pkg_config(lib_name2) root = pkg_config(lib_name2)
if root: if root:
break break
else: else:
_dbg('Looking for `%s` using pkg-config.' % lib_name) _dbg("Looking for `%s` using pkg-config." % lib_name)
root = pkg_config(lib_name) root = pkg_config(lib_name)
if isinstance(root, tuple): if isinstance(root, tuple):
@ -331,20 +387,20 @@ class pil_build_ext(build_ext):
_add_directory(include_dirs, include_root) _add_directory(include_dirs, include_root)
# respect CFLAGS/LDFLAGS # respect CFLAGS/LDFLAGS
for k in ('CFLAGS', 'LDFLAGS'): for k in ("CFLAGS", "LDFLAGS"):
if k in os.environ: if k in os.environ:
for match in re.finditer(r'-I([^\s]+)', os.environ[k]): for match in re.finditer(r"-I([^\s]+)", os.environ[k]):
_add_directory(include_dirs, match.group(1)) _add_directory(include_dirs, match.group(1))
for match in re.finditer(r'-L([^\s]+)', os.environ[k]): for match in re.finditer(r"-L([^\s]+)", os.environ[k]):
_add_directory(library_dirs, match.group(1)) _add_directory(library_dirs, match.group(1))
# include, rpath, if set as environment variables: # include, rpath, if set as environment variables:
for k in ('C_INCLUDE_PATH', 'CPATH', 'INCLUDE'): for k in ("C_INCLUDE_PATH", "CPATH", "INCLUDE"):
if k in os.environ: if k in os.environ:
for d in os.environ[k].split(os.path.pathsep): for d in os.environ[k].split(os.path.pathsep):
_add_directory(include_dirs, d) _add_directory(include_dirs, d)
for k in ('LD_RUN_PATH', 'LIBRARY_PATH', 'LIB'): for k in ("LD_RUN_PATH", "LIBRARY_PATH", "LIB"):
if k in os.environ: if k in os.environ:
for d in os.environ[k].split(os.path.pathsep): for d in os.environ[k].split(os.path.pathsep):
_add_directory(library_dirs, d) _add_directory(library_dirs, d)
@ -362,9 +418,10 @@ class pil_build_ext(build_ext):
elif sys.platform == "cygwin": elif sys.platform == "cygwin":
# pythonX.Y.dll.a is in the /usr/lib/pythonX.Y/config directory # pythonX.Y.dll.a is in the /usr/lib/pythonX.Y/config directory
_add_directory(library_dirs, _add_directory(
os.path.join("/usr/lib", "python%s" % library_dirs,
sys.version[:3], "config")) os.path.join("/usr/lib", "python%s" % sys.version[:3], "config"),
)
elif sys.platform == "darwin": elif sys.platform == "darwin":
# attempt to make sure we pick freetype2 over other versions # attempt to make sure we pick freetype2 over other versions
@ -379,8 +436,11 @@ class pil_build_ext(build_ext):
# if Homebrew is installed, use its lib and include directories # if Homebrew is installed, use its lib and include directories
try: try:
prefix = subprocess.check_output(['brew', '--prefix']).strip( prefix = (
).decode('latin1') subprocess.check_output(["brew", "--prefix"])
.strip()
.decode("latin1")
)
except Exception: except Exception:
# Homebrew not installed # Homebrew not installed
prefix = None prefix = None
@ -389,28 +449,30 @@ class pil_build_ext(build_ext):
if prefix: if prefix:
# add Homebrew's include and lib directories # add Homebrew's include and lib directories
_add_directory(library_dirs, os.path.join(prefix, 'lib')) _add_directory(library_dirs, os.path.join(prefix, "lib"))
_add_directory(include_dirs, os.path.join(prefix, 'include')) _add_directory(include_dirs, os.path.join(prefix, "include"))
ft_prefix = os.path.join(prefix, 'opt', 'freetype') ft_prefix = os.path.join(prefix, "opt", "freetype")
if ft_prefix and os.path.isdir(ft_prefix): if ft_prefix and os.path.isdir(ft_prefix):
# freetype might not be linked into Homebrew's prefix # freetype might not be linked into Homebrew's prefix
_add_directory(library_dirs, os.path.join(ft_prefix, 'lib')) _add_directory(library_dirs, os.path.join(ft_prefix, "lib"))
_add_directory(include_dirs, _add_directory(include_dirs, os.path.join(ft_prefix, "include"))
os.path.join(ft_prefix, 'include'))
else: else:
# fall back to freetype from XQuartz if # fall back to freetype from XQuartz if
# Homebrew's freetype is missing # Homebrew's freetype is missing
_add_directory(library_dirs, "/usr/X11/lib") _add_directory(library_dirs, "/usr/X11/lib")
_add_directory(include_dirs, "/usr/X11/include") _add_directory(include_dirs, "/usr/X11/include")
elif sys.platform.startswith("linux") or \ elif (
sys.platform.startswith("gnu") or \ sys.platform.startswith("linux")
sys.platform.startswith("freebsd"): or sys.platform.startswith("gnu")
or sys.platform.startswith("freebsd")
):
for dirname in _find_library_dirs_ldconfig(): for dirname in _find_library_dirs_ldconfig():
_add_directory(library_dirs, dirname) _add_directory(library_dirs, dirname)
if sys.platform.startswith("linux") and \ if sys.platform.startswith("linux") and os.environ.get(
os.environ.get('ANDROID_ROOT', None): "ANDROID_ROOT", None
):
# termux support for android. # termux support for android.
# system libraries (zlib) are installed in /system/lib # system libraries (zlib) are installed in /system/lib
# headers are at $PREFIX/include # headers are at $PREFIX/include
@ -441,27 +503,26 @@ class pil_build_ext(build_ext):
if sys.platform == "win32": if sys.platform == "win32":
if PLATFORM_MINGW: if PLATFORM_MINGW:
_add_directory(include_dirs, _add_directory(
"C:\\msys64\\mingw32\\include\\libimagequant") include_dirs, "C:\\msys64\\mingw32\\include\\libimagequant"
)
# on Windows, look for the OpenJPEG libraries in the location that # on Windows, look for the OpenJPEG libraries in the location that
# the official installer puts them # the official installer puts them
program_files = os.environ.get('ProgramFiles', '') program_files = os.environ.get("ProgramFiles", "")
best_version = (0, 0) best_version = (0, 0)
best_path = None best_path = None
for name in os.listdir(program_files): for name in os.listdir(program_files):
if name.startswith('OpenJPEG '): if name.startswith("OpenJPEG "):
version = tuple(int(x) for x in version = tuple(int(x) for x in name[9:].strip().split("."))
name[9:].strip().split('.'))
if version > best_version: if version > best_version:
best_version = version best_version = version
best_path = os.path.join(program_files, name) best_path = os.path.join(program_files, name)
if best_path: if best_path:
_dbg('Adding %s to search list', best_path) _dbg("Adding %s to search list", best_path)
_add_directory(library_dirs, os.path.join(best_path, 'lib')) _add_directory(library_dirs, os.path.join(best_path, "lib"))
_add_directory(include_dirs, _add_directory(include_dirs, os.path.join(best_path, "include"))
os.path.join(best_path, 'include'))
# #
# insert new dirs *before* default libs, to avoid conflicts # insert new dirs *before* default libs, to avoid conflicts
@ -475,51 +536,51 @@ class pil_build_ext(build_ext):
feature = self.feature feature = self.feature
if feature.want('zlib'): if feature.want("zlib"):
_dbg('Looking for zlib') _dbg("Looking for zlib")
if _find_include_file(self, "zlib.h"): if _find_include_file(self, "zlib.h"):
if _find_library_file(self, "z"): if _find_library_file(self, "z"):
feature.zlib = "z" feature.zlib = "z"
elif (sys.platform == "win32" and elif sys.platform == "win32" and _find_library_file(self, "zlib"):
_find_library_file(self, "zlib")):
feature.zlib = "zlib" # alternative name feature.zlib = "zlib" # alternative name
if feature.want('jpeg'): if feature.want("jpeg"):
_dbg('Looking for jpeg') _dbg("Looking for jpeg")
if _find_include_file(self, "jpeglib.h"): if _find_include_file(self, "jpeglib.h"):
if _find_library_file(self, "jpeg"): if _find_library_file(self, "jpeg"):
feature.jpeg = "jpeg" feature.jpeg = "jpeg"
elif (sys.platform == "win32" and elif sys.platform == "win32" and _find_library_file(self, "libjpeg"):
_find_library_file(self, "libjpeg")):
feature.jpeg = "libjpeg" # alternative name feature.jpeg = "libjpeg" # alternative name
feature.openjpeg_version = None feature.openjpeg_version = None
if feature.want('jpeg2000'): if feature.want("jpeg2000"):
_dbg('Looking for jpeg2000') _dbg("Looking for jpeg2000")
best_version = None best_version = None
best_path = None best_path = None
# Find the best version # Find the best version
for directory in self.compiler.include_dirs: for directory in self.compiler.include_dirs:
_dbg('Checking for openjpeg-#.# in %s', directory) _dbg("Checking for openjpeg-#.# in %s", directory)
try: try:
listdir = os.listdir(directory) listdir = os.listdir(directory)
except Exception: except Exception:
# WindowsError, FileNotFoundError # WindowsError, FileNotFoundError
continue continue
for name in listdir: for name in listdir:
if name.startswith('openjpeg-') and \ if name.startswith("openjpeg-") and os.path.isfile(
os.path.isfile(os.path.join(directory, name, os.path.join(directory, name, "openjpeg.h")
'openjpeg.h')): ):
_dbg('Found openjpeg.h in %s/%s', (directory, name)) _dbg("Found openjpeg.h in %s/%s", (directory, name))
version = tuple(int(x) for x in name[9:].split('.')) version = tuple(int(x) for x in name[9:].split("."))
if best_version is None or version > best_version: if best_version is None or version > best_version:
best_version = version best_version = version
best_path = os.path.join(directory, name) best_path = os.path.join(directory, name)
_dbg('Best openjpeg version %s so far in %s', _dbg(
(best_version, best_path)) "Best openjpeg version %s so far in %s",
(best_version, best_path),
)
if best_version and _find_library_file(self, 'openjp2'): if best_version and _find_library_file(self, "openjp2"):
# Add the directory to the include path so we can include # Add the directory to the include path so we can include
# <openjpeg.h> rather than having to cope with the versioned # <openjpeg.h> rather than having to cope with the versioned
# include path # include path
@ -528,45 +589,43 @@ class pil_build_ext(build_ext):
# self.compiler.include_dirs. Should investigate how that is # self.compiler.include_dirs. Should investigate how that is
# possible. # possible.
_add_directory(self.compiler.include_dirs, best_path, 0) _add_directory(self.compiler.include_dirs, best_path, 0)
feature.jpeg2000 = 'openjp2' feature.jpeg2000 = "openjp2"
feature.openjpeg_version = '.'.join(str(x) for x in feature.openjpeg_version = ".".join(str(x) for x in best_version)
best_version)
if feature.want('imagequant'): if feature.want("imagequant"):
_dbg('Looking for imagequant') _dbg("Looking for imagequant")
if _find_include_file(self, 'libimagequant.h'): if _find_include_file(self, "libimagequant.h"):
if _find_library_file(self, "imagequant"): if _find_library_file(self, "imagequant"):
feature.imagequant = "imagequant" feature.imagequant = "imagequant"
elif _find_library_file(self, "libimagequant"): elif _find_library_file(self, "libimagequant"):
feature.imagequant = "libimagequant" feature.imagequant = "libimagequant"
if feature.want('tiff'): if feature.want("tiff"):
_dbg('Looking for tiff') _dbg("Looking for tiff")
if _find_include_file(self, 'tiff.h'): if _find_include_file(self, "tiff.h"):
if _find_library_file(self, "tiff"): if _find_library_file(self, "tiff"):
feature.tiff = "tiff" feature.tiff = "tiff"
if (sys.platform in ["win32", "darwin"] and if sys.platform in ["win32", "darwin"] and _find_library_file(
_find_library_file(self, "libtiff")): self, "libtiff"
):
feature.tiff = "libtiff" feature.tiff = "libtiff"
if feature.want('freetype'): if feature.want("freetype"):
_dbg('Looking for freetype') _dbg("Looking for freetype")
if _find_library_file(self, "freetype"): if _find_library_file(self, "freetype"):
# look for freetype2 include files # look for freetype2 include files
freetype_version = 0 freetype_version = 0
for subdir in self.compiler.include_dirs: for subdir in self.compiler.include_dirs:
_dbg('Checking for include file %s in %s', _dbg("Checking for include file %s in %s", ("ft2build.h", subdir))
("ft2build.h", subdir))
if os.path.isfile(os.path.join(subdir, "ft2build.h")): if os.path.isfile(os.path.join(subdir, "ft2build.h")):
_dbg('Found %s in %s', ("ft2build.h", subdir)) _dbg("Found %s in %s", ("ft2build.h", subdir))
freetype_version = 21 freetype_version = 21
subdir = os.path.join(subdir, "freetype2") subdir = os.path.join(subdir, "freetype2")
break break
subdir = os.path.join(subdir, "freetype2") subdir = os.path.join(subdir, "freetype2")
_dbg('Checking for include file %s in %s', _dbg("Checking for include file %s in %s", ("ft2build.h", subdir))
("ft2build.h", subdir))
if os.path.isfile(os.path.join(subdir, "ft2build.h")): if os.path.isfile(os.path.join(subdir, "ft2build.h")):
_dbg('Found %s in %s', ("ft2build.h", subdir)) _dbg("Found %s in %s", ("ft2build.h", subdir))
freetype_version = 21 freetype_version = 21
break break
if freetype_version: if freetype_version:
@ -574,8 +633,8 @@ class pil_build_ext(build_ext):
if subdir: if subdir:
_add_directory(self.compiler.include_dirs, subdir, 0) _add_directory(self.compiler.include_dirs, subdir, 0)
if feature.want('lcms'): if feature.want("lcms"):
_dbg('Looking for lcms') _dbg("Looking for lcms")
if _find_include_file(self, "lcms2.h"): if _find_include_file(self, "lcms2.h"):
if _find_library_file(self, "lcms2"): if _find_library_file(self, "lcms2"):
feature.lcms = "lcms2" feature.lcms = "lcms2"
@ -583,30 +642,34 @@ class pil_build_ext(build_ext):
# alternate Windows name. # alternate Windows name.
feature.lcms = "lcms2_static" feature.lcms = "lcms2_static"
if feature.want('webp'): if feature.want("webp"):
_dbg('Looking for webp') _dbg("Looking for webp")
if (_find_include_file(self, "webp/encode.h") and if _find_include_file(self, "webp/encode.h") and _find_include_file(
_find_include_file(self, "webp/decode.h")): self, "webp/decode.h"
):
# In Google's precompiled zip it is call "libwebp": # In Google's precompiled zip it is call "libwebp":
if _find_library_file(self, "webp"): if _find_library_file(self, "webp"):
feature.webp = "webp" feature.webp = "webp"
elif _find_library_file(self, "libwebp"): elif _find_library_file(self, "libwebp"):
feature.webp = "libwebp" feature.webp = "libwebp"
if feature.want('webpmux'): if feature.want("webpmux"):
_dbg('Looking for webpmux') _dbg("Looking for webpmux")
if (_find_include_file(self, "webp/mux.h") and if _find_include_file(self, "webp/mux.h") and _find_include_file(
_find_include_file(self, "webp/demux.h")): self, "webp/demux.h"
if (_find_library_file(self, "webpmux") and ):
_find_library_file(self, "webpdemux")): if _find_library_file(self, "webpmux") and _find_library_file(
self, "webpdemux"
):
feature.webpmux = "webpmux" feature.webpmux = "webpmux"
if (_find_library_file(self, "libwebpmux") and if _find_library_file(self, "libwebpmux") and _find_library_file(
_find_library_file(self, "libwebpdemux")): self, "libwebpdemux"
):
feature.webpmux = "libwebpmux" feature.webpmux = "libwebpmux"
for f in feature: for f in feature:
if not getattr(feature, f) and feature.require(f): if not getattr(feature, f) and feature.require(f):
if f in ('jpeg', 'zlib'): if f in ("jpeg", "zlib"):
raise RequiredDependencyException(f) raise RequiredDependencyException(f)
raise DependencyException(f) raise DependencyException(f)
@ -640,7 +703,7 @@ class pil_build_ext(build_ext):
defs.append(("HAVE_LIBTIFF", None)) defs.append(("HAVE_LIBTIFF", None))
if sys.platform == "win32": if sys.platform == "win32":
libs.extend(["kernel32", "user32", "gdi32"]) libs.extend(["kernel32", "user32", "gdi32"])
if struct.unpack("h", "\0\1".encode('ascii'))[0] == 1: if struct.unpack("h", "\0\1".encode("ascii"))[0] == 1:
defs.append(("WORDS_BIGENDIAN", None)) defs.append(("WORDS_BIGENDIAN", None))
if sys.platform == "win32" and not (PLATFORM_PYPY or PLATFORM_MINGW): if sys.platform == "win32" and not (PLATFORM_PYPY or PLATFORM_MINGW):
@ -648,10 +711,7 @@ class pil_build_ext(build_ext):
else: else:
defs.append(("PILLOW_VERSION", '"%s"' % PILLOW_VERSION)) defs.append(("PILLOW_VERSION", '"%s"' % PILLOW_VERSION))
exts = [(Extension("PIL._imaging", exts = [(Extension("PIL._imaging", files, libraries=libs, define_macros=defs))]
files,
libraries=libs,
define_macros=defs))]
# #
# additional libraries # additional libraries
@ -659,17 +719,26 @@ class pil_build_ext(build_ext):
if feature.freetype: if feature.freetype:
libs = ["freetype"] libs = ["freetype"]
defs = [] defs = []
exts.append(Extension( exts.append(
"PIL._imagingft", ["src/_imagingft.c"], libraries=libs, Extension(
define_macros=defs)) "PIL._imagingft",
["src/_imagingft.c"],
libraries=libs,
define_macros=defs,
)
)
if feature.lcms: if feature.lcms:
extra = [] extra = []
if sys.platform == "win32": if sys.platform == "win32":
extra.extend(["user32", "gdi32"]) extra.extend(["user32", "gdi32"])
exts.append(Extension("PIL._imagingcms", exts.append(
Extension(
"PIL._imagingcms",
["src/_imagingcms.c"], ["src/_imagingcms.c"],
libraries=[feature.lcms] + extra)) libraries=[feature.lcms] + extra,
)
)
if feature.webp: if feature.webp:
libs = [feature.webp] libs = [feature.webp]
@ -678,18 +747,23 @@ class pil_build_ext(build_ext):
if feature.webpmux: if feature.webpmux:
defs.append(("HAVE_WEBPMUX", None)) defs.append(("HAVE_WEBPMUX", None))
libs.append(feature.webpmux) libs.append(feature.webpmux)
libs.append(feature.webpmux.replace('pmux', 'pdemux')) libs.append(feature.webpmux.replace("pmux", "pdemux"))
exts.append(Extension("PIL._webp", exts.append(
["src/_webp.c"], Extension(
libraries=libs, "PIL._webp", ["src/_webp.c"], libraries=libs, define_macros=defs
define_macros=defs)) )
)
tk_libs = ['psapi'] if sys.platform == 'win32' else [] tk_libs = ["psapi"] if sys.platform == "win32" else []
exts.append(Extension("PIL._imagingtk", exts.append(
Extension(
"PIL._imagingtk",
["src/_imagingtk.c", "src/Tk/tkImaging.c"], ["src/_imagingtk.c", "src/Tk/tkImaging.c"],
include_dirs=['src/Tk'], include_dirs=["src/Tk"],
libraries=tk_libs)) libraries=tk_libs,
)
)
exts.append(Extension("PIL._imagingmath", ["src/_imagingmath.c"])) exts.append(Extension("PIL._imagingmath", ["src/_imagingmath.c"]))
exts.append(Extension("PIL._imagingmorph", ["src/_imagingmorph.c"])) exts.append(Extension("PIL._imagingmorph", ["src/_imagingmorph.c"]))
@ -717,8 +791,7 @@ class pil_build_ext(build_ext):
options = [ options = [
(feature.jpeg, "JPEG"), (feature.jpeg, "JPEG"),
(feature.jpeg2000, "OPENJPEG (JPEG2000)", (feature.jpeg2000, "OPENJPEG (JPEG2000)", feature.openjpeg_version),
feature.openjpeg_version),
(feature.zlib, "ZLIB (PNG/ZIP)"), (feature.zlib, "ZLIB (PNG/ZIP)"),
(feature.imagequant, "LIBIMAGEQUANT"), (feature.imagequant, "LIBIMAGEQUANT"),
(feature.tiff, "LIBTIFF"), (feature.tiff, "LIBTIFF"),
@ -731,9 +804,9 @@ class pil_build_ext(build_ext):
all = 1 all = 1
for option in options: for option in options:
if option[0]: if option[0]:
version = '' version = ""
if len(option) >= 3 and option[2]: if len(option) >= 3 and option[2]:
version = ' (%s)' % option[2] version = " (%s)" % option[2]
print("--- %s support available%s" % (option[1], version)) print("--- %s support available%s" % (option[1], version))
else: else:
print("*** %s support not available" % option[1]) print("*** %s support not available" % option[1])
@ -744,8 +817,10 @@ class pil_build_ext(build_ext):
if not all: if not all:
print("To add a missing option, make sure you have the required") print("To add a missing option, make sure you have the required")
print("library and headers.") print("library and headers.")
print("See https://pillow.readthedocs.io/en/latest/installation." print(
"html#building-from-source") "See https://pillow.readthedocs.io/en/latest/installation."
"html#building-from-source"
)
print("") print("")
print("To check the build, run the selftest.py script.") print("To check the build, run the selftest.py script.")
@ -753,20 +828,21 @@ class pil_build_ext(build_ext):
def debug_build(): def debug_build():
return hasattr(sys, 'gettotalrefcount') return hasattr(sys, "gettotalrefcount")
needs_pytest = {'pytest', 'test', 'ptr'}.intersection(sys.argv) needs_pytest = {"pytest", "test", "ptr"}.intersection(sys.argv)
pytest_runner = ['pytest-runner'] if needs_pytest else [] pytest_runner = ["pytest-runner"] if needs_pytest else []
try: try:
setup(name=NAME, setup(
name=NAME,
version=PILLOW_VERSION, version=PILLOW_VERSION,
description='Python Imaging Library (Fork)', description="Python Imaging Library (Fork)",
long_description=_read('README.rst').decode('utf-8'), long_description=_read("README.rst").decode("utf-8"),
author='Alex Clark (Fork Author)', author="Alex Clark (Fork Author)",
author_email='aclark@aclark.net', author_email="aclark@aclark.net",
url='http://python-pillow.org', url="http://python-pillow.org",
classifiers=[ classifiers=[
"Development Status :: 6 - Mature", "Development Status :: 6 - Mature",
"License :: OSI Approved :: Historical Permission Notice and Disclaimer (HPND)", # noqa: E501 "License :: OSI Approved :: Historical Permission Notice and Disclaimer (HPND)", # noqa: E501
@ -789,11 +865,12 @@ try:
ext_modules=[Extension("PIL._imaging", ["_imaging.c"])], ext_modules=[Extension("PIL._imaging", ["_imaging.c"])],
include_package_data=True, include_package_data=True,
setup_requires=pytest_runner, setup_requires=pytest_runner,
tests_require=['pytest'], tests_require=["pytest"],
packages=["PIL"], packages=["PIL"],
package_dir={'': 'src'}, package_dir={"": "src"},
keywords=["Imaging", ], keywords=["Imaging"],
zip_safe=not (debug_build() or PLATFORM_MINGW), ) zip_safe=not (debug_build() or PLATFORM_MINGW),
)
except RequiredDependencyException as err: except RequiredDependencyException as err:
msg = """ msg = """
@ -803,7 +880,9 @@ a required dependency when compiling Pillow from source.
Please see the install instructions at: Please see the install instructions at:
https://pillow.readthedocs.io/en/latest/installation.html https://pillow.readthedocs.io/en/latest/installation.html
""" % (str(err)) """ % (
str(err)
)
sys.stderr.write(msg) sys.stderr.write(msg)
raise RequiredDependencyException(msg) raise RequiredDependencyException(msg)
except DependencyException as err: except DependencyException as err:
@ -812,6 +891,9 @@ except DependencyException as err:
The headers or library files could not be found for %s, The headers or library files could not be found for %s,
which was requested by the option flag --enable-%s which was requested by the option flag --enable-%s
""" % (str(err), str(err)) """ % (
str(err),
str(err),
)
sys.stderr.write(msg) sys.stderr.write(msg)
raise DependencyException(msg) raise DependencyException(msg)

View File

@ -24,7 +24,7 @@ deps =
[testenv:lint] [testenv:lint]
commands = commands =
black --check --diff src black --check --diff .
flake8 --statistics --count flake8 --statistics --count
check-manifest check-manifest
deps = deps =

View File

@ -6,18 +6,29 @@ import sys
import getopt import getopt
import os import os
from config import (compilers, compiler_from_env, pythons, pyversion_from_env, from config import (
bit_from_env, VIRT_BASE, X64_EXT) compilers,
compiler_from_env,
pythons,
pyversion_from_env,
bit_from_env,
VIRT_BASE,
X64_EXT,
)
def setup_vms(): def setup_vms():
ret = [] ret = []
for py in pythons: for py in pythons:
for arch in ('', X64_EXT): for arch in ("", X64_EXT):
ret.append("virtualenv -p c:/Python%s%s/python.exe --clear %s%s%s" ret.append(
% (py, arch, VIRT_BASE, py, arch)) "virtualenv -p c:/Python%s%s/python.exe --clear %s%s%s"
ret.append(r"%s%s%s\Scripts\pip.exe install pytest pytest-cov" % % (py, arch, VIRT_BASE, py, arch)
(VIRT_BASE, py, arch)) )
ret.append(
r"%s%s%s\Scripts\pip.exe install pytest pytest-cov"
% (VIRT_BASE, py, arch)
)
return "\n".join(ret) return "\n".join(ret)
@ -25,12 +36,13 @@ def run_script(params):
(version, script) = params (version, script) = params
try: try:
print("Running %s" % version) print("Running %s" % version)
filename = 'build_pillow_%s.cmd' % version filename = "build_pillow_%s.cmd" % version
with open(filename, 'w') as f: with open(filename, "w") as f:
f.write(script) f.write(script)
command = ['powershell', "./%s" % filename] command = ["powershell", "./%s" % filename]
proc = subprocess.Popen(command, proc = subprocess.Popen(
command,
stdin=subprocess.PIPE, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, stderr=subprocess.PIPE,
@ -55,7 +67,9 @@ set MPLSRC=%%~dp0\..
set INCLIB=%%~dp0\depends set INCLIB=%%~dp0\depends
set BLDOPT=%s set BLDOPT=%s
cd /D %%MPLSRC%% cd /D %%MPLSRC%%
""" % (op) """ % (
op
)
def footer(): def footer():
@ -66,10 +80,13 @@ exit
def vc_setup(compiler, bit): def vc_setup(compiler, bit):
script = "" script = ""
if compiler['vc_version'] == '2015': if compiler["vc_version"] == "2015":
arch = "x86" if bit == 32 else "x86_amd64" arch = "x86" if bit == 32 else "x86_amd64"
script = r""" script = (
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %s""" % arch r"""
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %s"""
% arch
)
return script return script
@ -77,27 +94,27 @@ def build_one(py_ver, compiler, bit):
# UNDONE virtual envs if we're not running on AppVeyor # UNDONE virtual envs if we're not running on AppVeyor
args = {} args = {}
args.update(compiler) args.update(compiler)
if 'PYTHON' in os.environ: if "PYTHON" in os.environ:
args['python_path'] = "%PYTHON%" args["python_path"] = "%PYTHON%"
else: else:
args['python_path'] = "%s%s\\Scripts" % (VIRT_BASE, py_ver) args["python_path"] = "%s%s\\Scripts" % (VIRT_BASE, py_ver)
args['executable'] = "python.exe" args["executable"] = "python.exe"
if 'EXECUTABLE' in os.environ: if "EXECUTABLE" in os.environ:
args['executable'] = "%EXECUTABLE%" args["executable"] = "%EXECUTABLE%"
args['py_ver'] = py_ver args["py_ver"] = py_ver
if '27' in py_ver: if "27" in py_ver:
args['tcl_ver'] = '85' args["tcl_ver"] = "85"
else: else:
args['tcl_ver'] = '86' args["tcl_ver"] = "86"
if compiler['vc_version'] == '2015': if compiler["vc_version"] == "2015":
args['imaging_libs'] = ' build_ext --add-imaging-libs=msvcrt' args["imaging_libs"] = " build_ext --add-imaging-libs=msvcrt"
else: else:
args['imaging_libs'] = '' args["imaging_libs"] = ""
args['vc_setup'] = vc_setup(compiler, bit) args["vc_setup"] = vc_setup(compiler, bit)
script = r""" script = r"""
setlocal EnableDelayedExpansion setlocal EnableDelayedExpansion
@ -119,34 +136,44 @@ endlocal
def clean(): def clean():
try: try:
shutil.rmtree('../build') shutil.rmtree("../build")
except Exception: except Exception:
# could already be removed # could already be removed
pass pass
run_script(('virtualenvs', setup_vms())) run_script(("virtualenvs", setup_vms()))
def main(op): def main(op):
scripts = [] scripts = []
for py_version, py_info in pythons.items(): for py_version, py_info in pythons.items():
py_compilers = compilers[py_info['compiler']][py_info['vc']] py_compilers = compilers[py_info["compiler"]][py_info["vc"]]
scripts.append((py_version, scripts.append(
"\n".join([header(op), (
build_one(py_version, py_version,
py_compilers[32], 32), "\n".join(
footer()]))) [header(op), build_one(py_version, py_compilers[32], 32), footer()]
),
)
)
scripts.append(("%s%s" % (py_version, X64_EXT), scripts.append(
"\n".join([header(op), (
build_one("%sx64" % py_version, "%s%s" % (py_version, X64_EXT),
py_compilers[64], 64), "\n".join(
footer()]))) [
header(op),
build_one("%sx64" % py_version, py_compilers[64], 64),
footer(),
]
),
)
)
results = map(run_script, scripts) results = map(run_script, scripts)
for (version, status, trace, err) in results: for (version, status, trace, err) in results:
print("Compiled %s: %s" % (version, status and 'ERR' or 'OK')) print("Compiled %s: %s" % (version, status and "ERR" or "OK"))
def run_one(op): def run_one(op):
@ -155,27 +182,28 @@ def run_one(op):
py_version = pyversion_from_env() py_version = pyversion_from_env()
bit = bit_from_env() bit = bit_from_env()
run_script((py_version, run_script(
"\n".join([header(op), (
build_one(py_version, compiler, bit), py_version,
footer()]) "\n".join([header(op), build_one(py_version, compiler, bit), footer()]),
)) )
)
if __name__ == '__main__': if __name__ == "__main__":
opts, args = getopt.getopt(sys.argv[1:], '', ['clean', 'dist', 'wheel']) opts, args = getopt.getopt(sys.argv[1:], "", ["clean", "dist", "wheel"])
opts = dict(opts) opts = dict(opts)
if '--clean' in opts: if "--clean" in opts:
clean() clean()
op = 'install' op = "install"
if '--dist' in opts: if "--dist" in opts:
op = "bdist_wininst --user-access-control=auto" op = "bdist_wininst --user-access-control=auto"
elif '--wheel' in opts: elif "--wheel" in opts:
op = "bdist_wheel" op = "bdist_wheel"
if 'PYTHON' in os.environ: if "PYTHON" in os.environ:
run_one(op) run_one(op)
else: else:
main(op) main(op)

View File

@ -3,8 +3,7 @@ from untar import untar
import os import os
from fetch import fetch from fetch import fetch
from config import (compilers, all_compilers, compiler_from_env, bit_from_env, from config import compilers, all_compilers, compiler_from_env, bit_from_env, libs
libs)
from build import vc_setup from build import vc_setup
@ -12,8 +11,8 @@ def _relpath(*args):
return os.path.join(os.getcwd(), *args) return os.path.join(os.getcwd(), *args)
build_dir = _relpath('build') build_dir = _relpath("build")
inc_dir = _relpath('depends') inc_dir = _relpath("depends")
def check_sig(filename, signame): def check_sig(filename, signame):
@ -32,37 +31,40 @@ def mkdirs():
pass pass
for compiler in all_compilers(): for compiler in all_compilers():
try: try:
os.mkdir(os.path.join(inc_dir, compiler['inc_dir'])) os.mkdir(os.path.join(inc_dir, compiler["inc_dir"]))
except OSError: except OSError:
pass pass
def extract(src, dest): def extract(src, dest):
if '.zip' in src: if ".zip" in src:
return unzip(src, dest) return unzip(src, dest)
if '.tar.gz' in src or '.tgz' in src: if ".tar.gz" in src or ".tgz" in src:
return untar(src, dest) return untar(src, dest)
def extract_libs(): def extract_libs():
for name, lib in libs.items(): for name, lib in libs.items():
filename = lib['filename'] filename = lib["filename"]
if not os.path.exists(filename): if not os.path.exists(filename):
filename = fetch(lib['url']) filename = fetch(lib["url"])
if name == 'openjpeg': if name == "openjpeg":
for compiler in all_compilers(): for compiler in all_compilers():
if not os.path.exists(os.path.join( if not os.path.exists(
build_dir, lib['dir']+compiler['inc_dir'])): os.path.join(build_dir, lib["dir"] + compiler["inc_dir"])
):
extract(filename, build_dir) extract(filename, build_dir)
os.rename(os.path.join(build_dir, lib['dir']), os.rename(
os.path.join( os.path.join(build_dir, lib["dir"]),
build_dir, lib['dir']+compiler['inc_dir'])) os.path.join(build_dir, lib["dir"] + compiler["inc_dir"]),
)
else: else:
extract(filename, build_dir) extract(filename, build_dir)
def extract_openjpeg(compiler): def extract_openjpeg(compiler):
return r""" return (
r"""
rem build openjpeg rem build openjpeg
setlocal setlocal
@echo on @echo on
@ -72,12 +74,15 @@ copy /Y /B openjpeg-2.0.0-win32-x86\include\openjpeg-2.0 %%INCLIB%%\openjpeg-2.
copy /Y /B openjpeg-2.0.0-win32-x86\bin\ %%INCLIB%% copy /Y /B openjpeg-2.0.0-win32-x86\bin\ %%INCLIB%%
copy /Y /B openjpeg-2.0.0-win32-x86\lib\ %%INCLIB%% copy /Y /B openjpeg-2.0.0-win32-x86\lib\ %%INCLIB%%
endlocal endlocal
""" % compiler """
% compiler
)
def cp_tk(ver_85, ver_86): def cp_tk(ver_85, ver_86):
versions = {'ver_85': ver_85, 'ver_86': ver_86} versions = {"ver_85": ver_85, "ver_86": ver_86}
return r""" return (
r"""
mkdir %%INCLIB%%\tcl85\include\X11 mkdir %%INCLIB%%\tcl85\include\X11
copy /Y /B %%BUILD%%\tcl%(ver_85)s\generic\*.h %%INCLIB%%\tcl85\include\ copy /Y /B %%BUILD%%\tcl%(ver_85)s\generic\*.h %%INCLIB%%\tcl85\include\
copy /Y /B %%BUILD%%\tk%(ver_85)s\generic\*.h %%INCLIB%%\tcl85\include\ copy /Y /B %%BUILD%%\tk%(ver_85)s\generic\*.h %%INCLIB%%\tcl85\include\
@ -87,7 +92,9 @@ mkdir %%INCLIB%%\tcl86\include\X11
copy /Y /B %%BUILD%%\tcl%(ver_86)s\generic\*.h %%INCLIB%%\tcl86\include\ copy /Y /B %%BUILD%%\tcl%(ver_86)s\generic\*.h %%INCLIB%%\tcl86\include\
copy /Y /B %%BUILD%%\tk%(ver_86)s\generic\*.h %%INCLIB%%\tcl86\include\ copy /Y /B %%BUILD%%\tk%(ver_86)s\generic\*.h %%INCLIB%%\tcl86\include\
copy /Y /B %%BUILD%%\tk%(ver_86)s\xlib\X11\* %%INCLIB%%\tcl86\include\X11\ copy /Y /B %%BUILD%%\tk%(ver_86)s\xlib\X11\* %%INCLIB%%\tcl86\include\X11\
""" % versions """
% versions
)
def header(): def header():
@ -96,15 +103,21 @@ set MSBUILD=C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe
set CMAKE="cmake.exe" set CMAKE="cmake.exe"
set INCLIB=%~dp0\depends set INCLIB=%~dp0\depends
set BUILD=%~dp0\build set BUILD=%~dp0\build
""" + "\n".join(r'set %s=%%BUILD%%\%s' % (k.upper(), v['dir']) """ + "\n".join(
for (k, v) in libs.items() if v['dir']) r"set %s=%%BUILD%%\%s" % (k.upper(), v["dir"])
for (k, v) in libs.items()
if v["dir"]
)
def setup_compiler(compiler): def setup_compiler(compiler):
return r"""setlocal EnableDelayedExpansion return (
r"""setlocal EnableDelayedExpansion
call "%%ProgramFiles%%\Microsoft SDKs\Windows\%(env_version)s\Bin\SetEnv.Cmd" /Release %(env_flags)s call "%%ProgramFiles%%\Microsoft SDKs\Windows\%(env_version)s\Bin\SetEnv.Cmd" /Release %(env_flags)s
set INCLIB=%%INCLIB%%\%(inc_dir)s set INCLIB=%%INCLIB%%\%(inc_dir)s
""" % compiler # noqa: E501 """ # noqa: E501
% compiler
)
def end_compiler(): def end_compiler():
@ -114,15 +127,18 @@ endlocal
def nmake_openjpeg(compiler, bit): def nmake_openjpeg(compiler, bit):
if compiler['env_version'] == 'v7.0': if compiler["env_version"] == "v7.0":
return "" return ""
atts = {'op_ver': '2.3.1'} atts = {"op_ver": "2.3.1"}
atts.update(compiler) atts.update(compiler)
return r""" return (
r"""
rem build openjpeg rem build openjpeg
setlocal setlocal
""" + vc_setup(compiler, bit) + r""" """
+ vc_setup(compiler, bit)
+ r"""
@echo on @echo on
cd /D %%OPENJPEG%%%(inc_dir)s cd /D %%OPENJPEG%%%(inc_dir)s
@ -133,15 +149,20 @@ copy /Y /B bin\* %%INCLIB%%
mkdir %%INCLIB%%\openjpeg-%(op_ver)s mkdir %%INCLIB%%\openjpeg-%(op_ver)s
copy /Y /B src\lib\openjp2\*.h %%INCLIB%%\openjpeg-%(op_ver)s copy /Y /B src\lib\openjp2\*.h %%INCLIB%%\openjpeg-%(op_ver)s
endlocal endlocal
""" % atts # noqa: E501 """ # noqa: E501
% atts
)
def nmake_libs(compiler, bit): def nmake_libs(compiler, bit):
# undone -- pre, makes, headers, libs # undone -- pre, makes, headers, libs
script = r""" script = (
r"""
rem Build libjpeg rem Build libjpeg
setlocal setlocal
""" + vc_setup(compiler, bit) + r""" """
+ vc_setup(compiler, bit)
+ r"""
cd /D %%JPEG%% cd /D %%JPEG%%
nmake -f makefile.vc setup-vc6 nmake -f makefile.vc setup-vc6
nmake -f makefile.vc clean nmake -f makefile.vc clean
@ -165,7 +186,9 @@ endlocal
rem Build webp rem Build webp
setlocal setlocal
""" + vc_setup(compiler, bit) + r""" """
+ vc_setup(compiler, bit)
+ r"""
cd /D %%WEBP%% cd /D %%WEBP%%
rd /S /Q %%WEBP%%\output\release-static rd /S /Q %%WEBP%%\output\release-static
nmake -f Makefile.vc CFG=release-static RTLIBCFG=static OBJDIR=output all nmake -f Makefile.vc CFG=release-static RTLIBCFG=static OBJDIR=output all
@ -176,7 +199,9 @@ endlocal
rem Build libtiff rem Build libtiff
setlocal setlocal
""" + vc_setup(compiler, bit) + r""" """
+ vc_setup(compiler, bit)
+ r"""
rem do after building jpeg and zlib rem do after building jpeg and zlib
copy %%~dp0\nmake.opt %%TIFF%% copy %%~dp0\nmake.opt %%TIFF%%
@ -188,6 +213,7 @@ copy /Y /B libtiff\*.lib %%INCLIB%%
copy /Y /B libtiff\tiff*.h %%INCLIB%% copy /Y /B libtiff\tiff*.h %%INCLIB%%
endlocal endlocal
""" """
)
return script % compiler return script % compiler
@ -200,36 +226,49 @@ set DefaultPlatformToolset=v100
""" """
properties = r"""/p:Configuration="Release" /p:Platform=%(platform)s""" properties = r"""/p:Configuration="Release" /p:Platform=%(platform)s"""
if bit == 64: if bit == 64:
script += r'copy /Y /B ' +\ script += (
r'"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Lib\x64\*.Lib" ' +\ r"copy /Y /B "
r'%%FREETYPE%%\builds\windows\vc2010' + r'"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Lib\x64\*.Lib" '
+ r"%%FREETYPE%%\builds\windows\vc2010"
)
properties += r" /p:_IsNativeEnvironment=false" properties += r" /p:_IsNativeEnvironment=false"
script += r""" script += (
%%MSBUILD%% %%FREETYPE%%\builds\windows\vc2010\freetype.sln /t:Clean;Build """+properties+r""" /m r"""
%%MSBUILD%% %%FREETYPE%%\builds\windows\vc2010\freetype.sln /t:Clean;Build """
+ properties
+ r""" /m
xcopy /Y /E /Q %%FREETYPE%%\include %%INCLIB%% xcopy /Y /E /Q %%FREETYPE%%\include %%INCLIB%%
""" """
)
freetypeReleaseDir = r"%%FREETYPE%%\objs\%(platform)s\Release" freetypeReleaseDir = r"%%FREETYPE%%\objs\%(platform)s\Release"
script += r""" script += (
copy /Y /B """+freetypeReleaseDir+r"""\freetype.lib %%INCLIB%%\freetype.lib r"""
copy /Y /B """+freetypeReleaseDir+r"""\freetype.dll %%INCLIB%%\..\freetype.dll copy /Y /B """
+ freetypeReleaseDir
+ r"""\freetype.lib %%INCLIB%%\freetype.lib
copy /Y /B """
+ freetypeReleaseDir
+ r"""\freetype.dll %%INCLIB%%\..\freetype.dll
endlocal endlocal
""" """
return script % compiler # noqa: E501 )
return script % compiler
def build_lcms2(compiler): def build_lcms2(compiler):
if compiler['env_version'] == 'v7.1': if compiler["env_version"] == "v7.1":
return build_lcms_71(compiler) return build_lcms_71(compiler)
return build_lcms_70(compiler) return build_lcms_70(compiler)
def build_lcms_70(compiler): def build_lcms_70(compiler):
"""Link error here on x64""" """Link error here on x64"""
if compiler['platform'] == 'x64': if compiler["platform"] == "x64":
return '' return ""
"""Build LCMS on VC2008. This version is only 32bit/Win32""" """Build LCMS on VC2008. This version is only 32bit/Win32"""
return r""" return (
r"""
rem Build lcms2 rem Build lcms2
setlocal setlocal
rd /S /Q %%LCMS%%\Lib rd /S /Q %%LCMS%%\Lib
@ -239,11 +278,14 @@ rd /S /Q %%LCMS%%\Projects\VC%(vc_version)s\Release
xcopy /Y /E /Q %%LCMS%%\include %%INCLIB%% xcopy /Y /E /Q %%LCMS%%\include %%INCLIB%%
copy /Y /B %%LCMS%%\Lib\MS\*.lib %%INCLIB%% copy /Y /B %%LCMS%%\Lib\MS\*.lib %%INCLIB%%
endlocal endlocal
""" % compiler # noqa: E501 """ # noqa: E501
% compiler
)
def build_lcms_71(compiler): def build_lcms_71(compiler):
return r""" return (
r"""
rem Build lcms2 rem Build lcms2
setlocal setlocal
rd /S /Q %%LCMS%%\Lib rd /S /Q %%LCMS%%\Lib
@ -253,21 +295,26 @@ rd /S /Q %%LCMS%%\Projects\VC%(vc_version)s\Release
xcopy /Y /E /Q %%LCMS%%\include %%INCLIB%% xcopy /Y /E /Q %%LCMS%%\include %%INCLIB%%
copy /Y /B %%LCMS%%\Lib\MS\*.lib %%INCLIB%% copy /Y /B %%LCMS%%\Lib\MS\*.lib %%INCLIB%%
endlocal endlocal
""" % compiler # noqa: E501 """ # noqa: E501
% compiler
)
def build_ghostscript(compiler, bit): def build_ghostscript(compiler, bit):
script = r""" script = (
r"""
rem Build gs rem Build gs
setlocal setlocal
""" + vc_setup(compiler, bit) + r""" """
set MSVC_VERSION=""" + { + vc_setup(compiler, bit)
"2010": "90", + r"""
"2015": "14" set MSVC_VERSION="""
}[compiler['vc_version']] + r""" + {"2010": "90", "2015": "14"}[compiler["vc_version"]]
+ r"""
set RCOMP="C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Bin\RC.Exe" set RCOMP="C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Bin\RC.Exe"
cd /D %%GHOSTSCRIPT%% cd /D %%GHOSTSCRIPT%%
""" """
)
if bit == 64: if bit == 64:
script += r""" script += r"""
set WIN64="" set WIN64=""
@ -277,7 +324,7 @@ nmake -f psi/msvc.mak
copy /Y /B bin\ C:\Python27\ copy /Y /B bin\ C:\Python27\
endlocal endlocal
""" """
return script % compiler # noqa: E501 return script % compiler
def add_compiler(compiler, bit): def add_compiler(compiler, bit):
@ -295,17 +342,15 @@ def add_compiler(compiler, bit):
mkdirs() mkdirs()
extract_libs() extract_libs()
script = [header(), script = [header(), cp_tk(libs["tk-8.5"]["version"], libs["tk-8.6"]["version"])]
cp_tk(libs['tk-8.5']['version'],
libs['tk-8.6']['version'])]
if 'PYTHON' in os.environ: if "PYTHON" in os.environ:
add_compiler(compiler_from_env(), bit_from_env()) add_compiler(compiler_from_env(), bit_from_env())
else: else:
# for compiler in all_compilers(): # for compiler in all_compilers():
# add_compiler(compiler) # add_compiler(compiler)
add_compiler(compilers[7.0][2010][32], 32) add_compiler(compilers[7.0][2010][32], 32)
with open('build_deps.cmd', 'w') as f: with open("build_deps.cmd", "w") as f:
f.write("\n".join(script)) f.write("\n".join(script))

View File

@ -1,83 +1,85 @@
import os import os
SF_MIRROR = 'http://iweb.dl.sourceforge.net' SF_MIRROR = "http://iweb.dl.sourceforge.net"
PILLOW_DEPENDS_DIR = 'C:\\pillow-depends\\' PILLOW_DEPENDS_DIR = "C:\\pillow-depends\\"
pythons = {'27': {'compiler': 7, 'vc': 2010}, pythons = {
'pypy2': {'compiler': 7, 'vc': 2010}, "27": {"compiler": 7, "vc": 2010},
'35': {'compiler': 7.1, 'vc': 2015}, "pypy2": {"compiler": 7, "vc": 2010},
'36': {'compiler': 7.1, 'vc': 2015}, "35": {"compiler": 7.1, "vc": 2015},
'37': {'compiler': 7.1, 'vc': 2015}} "36": {"compiler": 7.1, "vc": 2015},
"37": {"compiler": 7.1, "vc": 2015},
}
VIRT_BASE = "c:/vp/" VIRT_BASE = "c:/vp/"
X64_EXT = os.environ.get('X64_EXT', "x64") X64_EXT = os.environ.get("X64_EXT", "x64")
libs = { libs = {
# 'openjpeg': { # 'openjpeg': {
# 'filename': 'openjpeg-2.0.0-win32-x86.zip', # 'filename': 'openjpeg-2.0.0-win32-x86.zip',
# 'version': '2.0' # 'version': '2.0'
# }, # },
'zlib': { "zlib": {
'url': 'http://zlib.net/zlib1211.zip', "url": "http://zlib.net/zlib1211.zip",
'filename': PILLOW_DEPENDS_DIR + 'zlib1211.zip', "filename": PILLOW_DEPENDS_DIR + "zlib1211.zip",
'dir': 'zlib-1.2.11', "dir": "zlib-1.2.11",
}, },
'jpeg': { "jpeg": {
'url': 'http://www.ijg.org/files/jpegsr9c.zip', "url": "http://www.ijg.org/files/jpegsr9c.zip",
'filename': PILLOW_DEPENDS_DIR + 'jpegsr9c.zip', "filename": PILLOW_DEPENDS_DIR + "jpegsr9c.zip",
'dir': 'jpeg-9c', "dir": "jpeg-9c",
}, },
'tiff': { "tiff": {
'url': 'ftp://download.osgeo.org/libtiff/tiff-4.0.10.tar.gz', "url": "ftp://download.osgeo.org/libtiff/tiff-4.0.10.tar.gz",
'filename': PILLOW_DEPENDS_DIR + 'tiff-4.0.10.tar.gz', "filename": PILLOW_DEPENDS_DIR + "tiff-4.0.10.tar.gz",
'dir': 'tiff-4.0.10', "dir": "tiff-4.0.10",
}, },
'freetype': { "freetype": {
'url': 'https://download.savannah.gnu.org/releases/freetype/freetype-2.10.0.tar.gz', # noqa: E501 "url": "https://download.savannah.gnu.org/releases/freetype/freetype-2.10.0.tar.gz", # noqa: E501
'filename': PILLOW_DEPENDS_DIR + 'freetype-2.10.0.tar.gz', "filename": PILLOW_DEPENDS_DIR + "freetype-2.10.0.tar.gz",
'dir': 'freetype-2.10.0', "dir": "freetype-2.10.0",
}, },
'lcms': { "lcms": {
'url': SF_MIRROR+'/project/lcms/lcms/2.7/lcms2-2.7.zip', "url": SF_MIRROR + "/project/lcms/lcms/2.7/lcms2-2.7.zip",
'filename': PILLOW_DEPENDS_DIR + 'lcms2-2.7.zip', "filename": PILLOW_DEPENDS_DIR + "lcms2-2.7.zip",
'dir': 'lcms2-2.7', "dir": "lcms2-2.7",
}, },
'ghostscript': { "ghostscript": {
'url': 'https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs927/ghostscript-9.27.tar.gz', # noqa: E501 "url": "https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs927/ghostscript-9.27.tar.gz", # noqa: E501
'filename': PILLOW_DEPENDS_DIR + 'ghostscript-9.27.tar.gz', "filename": PILLOW_DEPENDS_DIR + "ghostscript-9.27.tar.gz",
'dir': 'ghostscript-9.27', "dir": "ghostscript-9.27",
}, },
'tcl-8.5': { "tcl-8.5": {
'url': SF_MIRROR+'/project/tcl/Tcl/8.5.19/tcl8519-src.zip', "url": SF_MIRROR + "/project/tcl/Tcl/8.5.19/tcl8519-src.zip",
'filename': PILLOW_DEPENDS_DIR + 'tcl8519-src.zip', "filename": PILLOW_DEPENDS_DIR + "tcl8519-src.zip",
'dir': '', "dir": "",
}, },
'tk-8.5': { "tk-8.5": {
'url': SF_MIRROR+'/project/tcl/Tcl/8.5.19/tk8519-src.zip', "url": SF_MIRROR + "/project/tcl/Tcl/8.5.19/tk8519-src.zip",
'filename': PILLOW_DEPENDS_DIR + 'tk8519-src.zip', "filename": PILLOW_DEPENDS_DIR + "tk8519-src.zip",
'dir': '', "dir": "",
'version': '8.5.19', "version": "8.5.19",
}, },
'tcl-8.6': { "tcl-8.6": {
'url': SF_MIRROR+'/project/tcl/Tcl/8.6.9/tcl869-src.zip', "url": SF_MIRROR + "/project/tcl/Tcl/8.6.9/tcl869-src.zip",
'filename': PILLOW_DEPENDS_DIR + 'tcl869-src.zip', "filename": PILLOW_DEPENDS_DIR + "tcl869-src.zip",
'dir': '', "dir": "",
}, },
'tk-8.6': { "tk-8.6": {
'url': SF_MIRROR+'/project/tcl/Tcl/8.6.9/tk869-src.zip', "url": SF_MIRROR + "/project/tcl/Tcl/8.6.9/tk869-src.zip",
'filename': PILLOW_DEPENDS_DIR + 'tk869-src.zip', "filename": PILLOW_DEPENDS_DIR + "tk869-src.zip",
'dir': '', "dir": "",
'version': '8.6.9', "version": "8.6.9",
}, },
'webp': { "webp": {
'url': 'http://downloads.webmproject.org/releases/webp/libwebp-1.0.2.tar.gz', "url": "http://downloads.webmproject.org/releases/webp/libwebp-1.0.2.tar.gz",
'filename': PILLOW_DEPENDS_DIR + 'libwebp-1.0.2.tar.gz', "filename": PILLOW_DEPENDS_DIR + "libwebp-1.0.2.tar.gz",
'dir': 'libwebp-1.0.2', "dir": "libwebp-1.0.2",
}, },
'openjpeg': { "openjpeg": {
'url': 'https://github.com/uclouvain/openjpeg/archive/v2.3.1.tar.gz', "url": "https://github.com/uclouvain/openjpeg/archive/v2.3.1.tar.gz",
'filename': PILLOW_DEPENDS_DIR + 'openjpeg-2.3.1.tar.gz', "filename": PILLOW_DEPENDS_DIR + "openjpeg-2.3.1.tar.gz",
'dir': 'openjpeg-2.3.1', "dir": "openjpeg-2.3.1",
}, },
} }
@ -85,63 +87,63 @@ compilers = {
7: { 7: {
2010: { 2010: {
64: { 64: {
'env_version': 'v7.0', "env_version": "v7.0",
'vc_version': '2010', "vc_version": "2010",
'env_flags': '/x64 /xp', "env_flags": "/x64 /xp",
'inc_dir': 'msvcr90-x64', "inc_dir": "msvcr90-x64",
'platform': 'x64', "platform": "x64",
'webp_platform': 'x64', "webp_platform": "x64",
}, },
32: { 32: {
'env_version': 'v7.0', "env_version": "v7.0",
'vc_version': '2010', "vc_version": "2010",
'env_flags': '/x86 /xp', "env_flags": "/x86 /xp",
'inc_dir': 'msvcr90-x32', "inc_dir": "msvcr90-x32",
'platform': 'Win32', "platform": "Win32",
'webp_platform': 'x86', "webp_platform": "x86",
} },
} }
}, },
7.1: { 7.1: {
2015: { 2015: {
64: { 64: {
'env_version': 'v7.1', "env_version": "v7.1",
'vc_version': '2015', "vc_version": "2015",
'env_flags': '/x64 /vista', "env_flags": "/x64 /vista",
'inc_dir': 'msvcr10-x64', "inc_dir": "msvcr10-x64",
'platform': 'x64', "platform": "x64",
'webp_platform': 'x64', "webp_platform": "x64",
}, },
32: { 32: {
'env_version': 'v7.1', "env_version": "v7.1",
'vc_version': '2015', "vc_version": "2015",
'env_flags': '/x86 /vista', "env_flags": "/x86 /vista",
'inc_dir': 'msvcr10-x32', "inc_dir": "msvcr10-x32",
'platform': 'Win32', "platform": "Win32",
'webp_platform': 'x86', "webp_platform": "x86",
} },
}
} }
},
} }
def pyversion_from_env(): def pyversion_from_env():
py = os.environ['PYTHON'] py = os.environ["PYTHON"]
py_version = '27' py_version = "27"
for k in pythons: for k in pythons:
if k in py: if k in py:
py_version = k py_version = k
break break
if '64' in py: if "64" in py:
py_version = '%s%s' % (py_version, X64_EXT) py_version = "%s%s" % (py_version, X64_EXT)
return py_version return py_version
def compiler_from_env(): def compiler_from_env():
py = os.environ['PYTHON'] py = os.environ["PYTHON"]
for k, v in pythons.items(): for k, v in pythons.items():
if k in py: if k in py:
@ -149,13 +151,13 @@ def compiler_from_env():
break break
bit = bit_from_env() bit = bit_from_env()
return compilers[py_info['compiler']][py_info['vc']][bit] return compilers[py_info["compiler"]][py_info["vc"]][bit]
def bit_from_env(): def bit_from_env():
py = os.environ['PYTHON'] py = os.environ["PYTHON"]
return 64 if '64' in py else 32 return 64 if "64" in py else 32
def all_compilers(): def all_compilers():

View File

@ -5,7 +5,7 @@ import urllib.request
def fetch(url): def fetch(url):
name = urllib.parse.urlsplit(url)[2].split('/')[-1] name = urllib.parse.urlsplit(url)[2].split("/")[-1]
if not os.path.exists(name): if not os.path.exists(name):
print("Fetching", url) print("Fetching", url)
@ -14,10 +14,10 @@ def fetch(url):
except urllib.error.URLError: except urllib.error.URLError:
r = urllib.request.urlopen(url) r = urllib.request.urlopen(url)
content = r.read() content = r.read()
with open(name, 'wb') as fd: with open(name, "wb") as fd:
fd.write(content) fd.write(content)
return name return name
if __name__ == '__main__': if __name__ == "__main__":
fetch(sys.argv[1]) fetch(sys.argv[1])

View File

@ -1,12 +1,14 @@
from fetch import fetch from fetch import fetch
import os import os
if __name__ == '__main__': if __name__ == "__main__":
for version in ['2.7.15', '3.4.4']: for version in ["2.7.15", "3.4.4"]:
for platform in ['', '.amd64']: for platform in ["", ".amd64"]:
for extension in ['', '.asc']: for extension in ["", ".asc"]:
fetch('https://www.python.org/ftp/python/%s/python-%s%s.msi%s' fetch(
% (version, version, platform, extension)) "https://www.python.org/ftp/python/%s/python-%s%s.msi%s"
% (version, version, platform, extension)
)
# find pip, if it's not in the path! # find pip, if it's not in the path!
os.system('pip install virtualenv') os.system("pip install virtualenv")

View File

@ -12,16 +12,14 @@ def test_one(params):
python, architecture = params python, architecture = params
try: try:
print("Running: %s, %s" % params) print("Running: %s, %s" % params)
command = [r'%s\%s%s\Scripts\python.exe' % command = [
(VIRT_BASE, python, architecture), r"%s\%s%s\Scripts\python.exe" % (VIRT_BASE, python, architecture),
'test-installed.py', "test-installed.py",
'--processes=-0', "--processes=-0",
'--process-timeout=30', "--process-timeout=30",
] ]
command.extend(glob.glob('Tests/test*.py')) command.extend(glob.glob("Tests/test*.py"))
proc = subprocess.Popen(command, proc = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
(trace, stderr) = proc.communicate() (trace, stderr) = proc.communicate()
status = proc.returncode status = proc.returncode
print("Done with %s, %s -- %s" % (python, architecture, status)) print("Done with %s, %s -- %s" % (python, architecture, status))
@ -31,16 +29,17 @@ def test_one(params):
return (python, architecture, -1, str(msg)) return (python, architecture, -1, str(msg))
if __name__ == '__main__': if __name__ == "__main__":
os.chdir('..') os.chdir("..")
matrix = [(python, architecture) for python in pythons matrix = [
for architecture in ('', X64_EXT)] (python, architecture) for python in pythons for architecture in ("", X64_EXT)
]
results = map(test_one, matrix) results = map(test_one, matrix)
for (python, architecture, status, trace) in results: for (python, architecture, status, trace) in results:
print("%s%s: %s" % (python, architecture, status and 'ERR' or 'PASS')) print("%s%s: %s" % (python, architecture, status and "ERR" or "PASS"))
res = all(status for (python, architecture, status, trace) in results) res = all(status for (python, architecture, status, trace) in results)
sys.exit(res) sys.exit(res)

View File

@ -3,9 +3,9 @@ import tarfile
def untar(src, dest): def untar(src, dest):
with tarfile.open(src, 'r:gz') as tgz: with tarfile.open(src, "r:gz") as tgz:
tgz.extractall(dest) tgz.extractall(dest)
if __name__ == '__main__': if __name__ == "__main__":
untar(sys.argv[1], sys.argv[2]) untar(sys.argv[1], sys.argv[2])

View File

@ -7,5 +7,5 @@ def unzip(src, dest):
zf.extractall(dest) zf.extractall(dest)
if __name__ == '__main__': if __name__ == "__main__":
unzip(sys.argv[1], sys.argv[2]) unzip(sys.argv[1], sys.argv[2])