Add Python 3.2 support #35

merged 61 commits into from Jan 10, 2013

5 participants


Adds support for Python 3.2 and removing support for Pythons older than 2.6.

This is a second pull request, which is rebased off of python-imaging/Pillow's master.

fluggo and others added some commits Oct 10, 2012
@fluggo fluggo py3k: Use string methods instead of string module
First, we go for the obvious stuff. The string module methods are gone in
3.0, so we translate them to the appropriate methods on the string class.
@fluggo fluggo py3k: Update exception usage to modern syntax 7857579
@fluggo fluggo py3k: Get to run under python3
First real fix: open the temp file in text mode.
@fluggo fluggo py3k: Modernize type declarations
This updates several Python type definitions and uses to bring us closer
to Python 3 compatibility. This includes:

* Replacing staticforward and statichere with static. These were a hack for
  old compilers and are not supported/needed anymore.
* Using Py_TYPE() instead of ob_type; ob_type is hidden in Py3.
* Replacing getattr with getters/setters. getattr is sort-of supported in
  Py3, but Py_FindMethod is not. So we just use the newer
  methods/getsetters mechanisms and start using PyType_Ready everywhere.
* Use PyVarObject_HEAD_INIT for types, since types are PyVarObject.
* Use PyMODINIT_FUNC for module initialization functions.

There are some tab/space issues in this commit. I'm set for spaces; the
source is a little schizo.
@fluggo fluggo py3k: Use new buffer protocol
Other ports have taken advantage of the fact that Python 3 has wrappers for
the old buffer protocol, but there's a significant disadvantage: you can't
let the buffered object know when you're done with it.

Since Python 2.6 supports the new protocol, we just go ahead and move to
@fluggo fluggo py3k: Remove HAVE_UNICODE from _imagingft
I'm pretty sure this preserves the intent of the code. HAVE_UNICODE is now
assumed, and PyString is only used if we're not in Py3k.

Since this is the only file that uses PyUnicode, I'm going to go ahead and
#define PyUnicode and PyBytes back to PyString for 2.6, and explicitly
change out every call so I have to check them all.
@fluggo fluggo py3k: Fix strict aliasing slip-up in _imaging
Python 3 enables C's strict aliasing rules for the first time, which means
you need to be careful about the ways you reference pointers. Here, we're
using a char[4] as an INT32, so we cast between them using a union.
@fluggo fluggo py3k: Add module initialization and unicode/bytes int/long thunks
This commit:

* Adds Python 3 module initialization functions. I split out the main init
  of each module into a static setup_module function.
* Adds a py3.h which unifies int/long in Python 3 and unicode/bytes in
  Python 2. _imagingft.c unfortunately looks a little kludgy after this
  because it was already using PyUnicode functions, and I had to mix and
  match there manually.

With this commit, the modules all build successfully under Python 3.

What this commit does NOT do is patch all of the uses of PyArg_ParseTuple
and Py_BuildValue, which all need to be checked for proper use of bytes
and unicode codes. It also does not let run yet, because there
are probably hundreds of issues to fix in the Python code itself.
@fluggo fluggo py3k: Fix strict aliasing warnings under Python 3 4459715
@fluggo fluggo py3k: Use "y#" code in PyArg_ParseTuple where we expect byte data
This commit also renames some functions from "fromstring" and the like to
"frombytes". I'll probably need to come back later and update any
references to "string," here or in the docs.

I also noticed that encode allocates some data for certain codecs, but
never frees them. That would be a good bug to fix. I fixed the one where it
outright stole a pointer from Python.
@fluggo fluggo py3k: Backport Gohlke's tests to run on 2.6/2.7
Most of the differences are in tobytes/tostring naming and expected
behavior of the bytes() constructor. The latter was usually easy to fix
with the right bytes literal.

This is a good preview of what will have to happen in the Python 3 code.
@fluggo fluggo py3k: Import Christoph Gohlke's test suite
This is Christoph Gohlke's test suite from his personal PIL package found

This is just to bring it in as a separate commit. Future commits will align
it with Pillow.
@fluggo fluggo FIX: Handle long values in _imaging getink
This gets the putdata test case to run correctly under 2.6/2.7. It fixes an
issue where the value 0xFFFFFFFF (which is long in old Python) isn't
recognized and putdata tries to parse it as a tuple.

The original fix comes from Christoph Gohlke. It was adapted to work in
both 2.* and 3.*.
@fluggo fluggo py3k: Provide the missing pngtest_bad.png.base64
This is from This was
missing from Gohlke's tests. With this file, I see 79 tests and no failures
on my setup from 2.6/2.7.
@fluggo fluggo py3k: Remove callable() function
callable(c) is isinstance(x, collections.Callable) in py3k.
@fluggo fluggo py3k: Fix up uses of dictionary views, ranges, and has_key()
y.has_key(x) is gone (use x in y), and keys(), values(), items(), and
range() all return views.

Some iterables needed to be packed into lists, either because the code
expected a list (such as "range(256) * 3") or because the original
collection was being modified (automatic global declarations).

The Tiff ImageFileDictionary is a special case and will be dealt with in
another commit.
@fluggo fluggo py3k: Rewrite dictionary support for Tiff ImageFileDictionary
This commit brings in the collections.MutableMapping mixin to provide full
dictionary support for ImageFileDictionary.
@fluggo fluggo py3k: map and filter to list comprehensions
What's really going on is that map() and filter() return iterators in py3k.
I've just gone ahead and turned them all into list comprehensions, because
I find them much easier to read.
@fluggo fluggo py3k: Add true Unicode support to OleFileIO
The day has arrived when Python provides an official way to handle Unicode
@fluggo fluggo py3k: __nonzero__ is now __bool__ eed042f
@fluggo fluggo py3k: Use isinstance for numbers and sequences
operator.isNumberType() and .isSequenceType() go away in py3k.
@fluggo fluggo py3k: Import reduce function
reduce() is no longer a built-in function in py3k.
@fluggo fluggo py3k: print is a function
Seriously, if you didn't know that, you've been in a freaking cave, man.
@fluggo fluggo py3k: Remove tuples in parameter lists
Py3k no longer supports unpacking tuples in the parameters.
@fluggo fluggo py3k: Use relative imports
In py3k, imports are absolute unless using the "from . import" syntax.

This commit also solves a recursive import between Image, ImageColor, and
ImagePalette by delay-importing ImagePalette in Image.

I'm not too keen on this commit because the syntax is ugly. I might go back
and prefer the prettier "from PIL import".
@fluggo fluggo py3k: sys.maxint renamed to sys.maxsize a453007
@fluggo fluggo py3k: Convert backticks to repr()
Backticks are no longer valid syntax for repr().
@fluggo fluggo py3k: Remove Image types import
For awhile now, str == type("") and so on. So we use the appropriate int,
str, basestring, or tuple type where applicable.
@fluggo fluggo py3k: __builtin__ module is now builtins fa348ee
@fluggo fluggo py3k: Tkinter module is now tkinter dda0e9a
@fluggo fluggo py3k: Convert StringIO.StringIO to io.BytesIO
io.BytesIO is already in 2.6. Some of the more obvious bytes literals are
marked in this commit.
@fluggo fluggo py3k: Integer long literals are no longer valid syntax e2283c6
@fluggo fluggo py3k: Change apply() to unpacking syntax
apply() is no longer available in py3k.
@fluggo fluggo py3k: 2to3's "idiom" filter
This is, I guess, a few things the Python devs were just fed up with.

* "while 1" is now "while True"
* Types are compared with isinstance instead of ==
* Sort a list in one go with sorted()

My own twist is to also replace type('') with str, type(()) with tuple,
type([]) with list, type(1) with int, and type(5000.0) with float.
@fluggo fluggo py3k: Map long type to int
int() is really now long() in py3k, but to avoid breaking 2.6/2.7, we leave
the integer types where they are and just map long to int in py3k.

Also, pretty proud of myself for finding an easy way of detecting py3k.
@fluggo fluggo py3k: Sort by key, not cmp
Py3k only supports key because it's more efficient. Not even sure 2to3
checks for this.
@fluggo fluggo py3k: Type coercion is gone
Types aren't automatically converted for operations for you.
@fluggo fluggo py3k: Publish both frombytes and fromstring in C modules for old Python
To ease the transition, frombytes and tobytes need to be declared in both
@fluggo fluggo py3k: The big push
There are two main issues fixed with this commit:

* bytes vs. str: All file, image, and palette data are now handled as
  bytes. A new _binary module consolidates the hacks needed to do this
  across Python versions. tostring/fromstring methods have been renamed to
  tobytes/frombytes, but the Python 2.6/2.7 versions alias them to the old
  names for compatibility. Users should move to tobytes/frombytes.

  One other potentially-breaking change is that text data in image files
  (such as tags, comments) are now explicitly handled with a specific
  character encoding in mind. This works well with the Unicode str in
  Python 3, but may trip up old code expecting a straight byte-for-byte
  translation to a Python string. This also required a change to Gohlke's
  tags tests (in Tests/ to expect Unicode strings from
  the code.

* True div vs. floor div: Many division operations used the "/" operator
  to do floor division, which is now the "//" operator in Python 3. These
  were fixed.

As of this commit, on the first pass, I have one failing test (improper
handling of a slice object in a C module, in Python 3,
and three that that I haven't tried running yet (test_imagegl,
test_imagegrab, and test_imageqt). I also haven't tested anything on
Windows. All but the three skipped tests run flawlessly against Pythons
2.6 and 2.7.
@cgohlke cgohlke py3k: Allow slicing for paths
This is Gohlke's fix for two issues: negative indexes on paths were not
resolved to the correct index, and path slicing didn't work.

His fix for slicing is related to the one found at:

With this commit, all 79 tests (82 minus the three skipped ones) run
successfully on Python 2.6.8, Python 2.7.3rc2, and Python 3.2.3.
@fluggo fluggo py3k: Remove ancient Python hacks a8599e8
@fluggo fluggo py3k: FIX: Bad upside-down check in BmpImagePlugin 254f0cf
@fluggo fluggo py3k: FIX: TGA missing o8 declaration
Plus, TGA was eligible for a round-trip test in test_imagefile. It has one
@fluggo fluggo py3k: Get rid of _ParserFile; io.BytesIO does its job 63be4a1
@fluggo fluggo py3k: Actually fix the EPS encoder
The EPS encoder wasn't part of Gohlke's test suite, so the previous "fixes"
there were only expected syntactic ones. This gives a cleaner fix to the

The decoder doesn't work in round-trip due to a missing eps_decoder method
on the core module, but it's clear it worked at some point.
@fluggo fluggo py3k: Add PCX to roundtrip test
For some reason, the PCX codec round-trips now.
@fluggo fluggo py3k: Add Photoshop sanity check 9921d83
@fluggo fluggo py3k: Add .FLI sanity check, and fix palette bytes bug 6765b8e
@fluggo fluggo py3k: Rewrite PdfImagePlugin into something more legible
After adding all the encode() calls, the PDF plugin (and a few others)
became much harder to read. This should be much easier on the eyes.
@fluggo fluggo py3k: Add TarIO test
Not too convinced of the size fix. While it works against my file, I'm not
sure someone would have accidentally been an index off and not noticed.
@fluggo fluggo py3k: Add XPM read test
This test includes an XPM file with transparency.
@fluggo fluggo py3k: Add Windows icon sanity test 848579a
@fluggo fluggo py3k: Remove use_2to3 from
This is unnecessary now.
@fluggo fluggo py3k: inquiry is now lenfunc
This fixes a build warning on 64-bit machines.
@fluggo fluggo py3k: Issue warnings when using the old fromstring/tostring
...although, you have to turn on deprecation warnings specifically in order
to get them.
@kmike kmike Fix tox test running: port to Python 3; make it clear Pyt…
…hon 2.5 is no longer supported (its support is broken in many ways in this branch); remove bundled module (it is in stdlib since forever); remove extra stuff from tox.ini
@fluggo fluggo Update the manifest to include a lot of missing files 67a131a
@manisandro manisandro Make pysane Python3-compatible e84cc92
@fluggo fluggo Set up Sane error object as exception instead of string
String exceptions don't work anymore.
@fluggo fluggo Handle Sane option strings as Unicode strings
The Sane documentation seems to imply that these option strings contain
Latin-1 text, not byte data, so we decode it and present it to the user
that way.
Bryant Mairs Modified map.c to fix some MSVC10 compilation errors. 9f82f02
@aclark4life aclark4life merged commit b48257e into python-pillow:master Jan 10, 2013
Pillow member

Thanks! \O/


I rebased to let you automatically merge, but thinking back on it, it probably should just have been merged manually. The git history gets uglier when I do stuff like that.

Pillow member

I thought rebase made git history cleaner? In any event, I'm not too concerned at this point. I'm willing to do a manual merge if it's absolutely necessary though.


Eh, the damage is done now. I realize what I should have done-- merged from your master instead of rebase off of it. I've done a lot of offline work with git, but not enough online to know what to do in these situations.

But yes, the problem that I have now is that I have three masters in my own repository, and people are branching off of them. I need to do something to fix that.

Pillow member

Gotcha. Well let me know what you'd like me to do if anything. I'm not terribly concerned about people branching off your repos because they can just redo their work here as needed.

Pillow member

Any idea why this test fails with:

running test_file_fli ...
Tests/ im = failed:
Traceback (most recent call last):
  File "Tests/", line 10, in test_sanity
    im =
  File "/Users/aclark/Developer/python-imaging/Pillow/PIL/", line 2007, in open
    raise IOError("cannot identify image file")


Pillow member

Thanks I'll try

Pillow member


> /Users/aclark/Developer/python-imaging/Pillow/PIL/
-> return factory(fp, filename)
SyntaxError: not an FLI/FLC file
Pillow member

Looks like this check fails for some reason: (I tried with another fli, same problem). OK I'll stop bothering you now :-) I have a ticket open to track this #74

Pillow member

Thanks, fixed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment