Skip to content

Commit

Permalink
Fix multisegment imports in some Python 2 revisions.
Browse files Browse the repository at this point in the history
I discovered upon deploying waitress 0.8.4 in production that there was
an issue with waitress.runner whereby __import__ would raise the
following error:

    TypeError: Item in ``fromlist'' not a string

The error didn't manifest itself under Python 2.6.8 (which is what the
test suite was ran against), but did manifest itself under 2.6.6 (the
version I was using in production). I believe this is a consequence of
the use of the unicode_literals feature import, which is required so
that it can run on both Python 2 and Python 3.

While I was able to reproduce the error reliably, I wasn't able to track
down of any mention of this issue in the NEWS file. I think it was
silently fixed some time between the release of 2.6.6 and 2.6.8.

Given this is something of a weird, obscure bug, I've included
documentation of the issue in the resolve() function as the need for the
cast is non-obvious.
  • Loading branch information
kgaughan committed May 27, 2013
1 parent 0592917 commit 72cfa09
Showing 1 changed file with 13 additions and 2 deletions.
15 changes: 13 additions & 2 deletions waitress/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,19 @@ def match(obj_name):

def resolve(module_name, object_name):
"""Resolve a named object in a module."""
obj = __import__(module_name, fromlist=[object_name.split('.', 1)[0]])
for segment in object_name.split('.'):
# We cast each segments due to an issue that has been found to manifest
# in Python 2.6.6, but not 2.6.8, and may affect other revisions of Python
# 2.6 and 2.7, whereby ``__import__`` chokes if the list passed in the
# ``fromlist`` argument are unicode strings rather than 8-bit strings.
# The error triggered is "TypeError: Item in ``fromlist '' not a string".
# My guess is that this was fixed by checking against ``basestring``
# rather than ``str`` sometime between the release of 2.6.6 and 2.6.8,
# but I've yet to go over the commits. I know, however, that the NEWS
# file makes no mention of such a change to the behaviour of
# ``__import__``.
segments = [str(segment) for segment in object_name.split('.')]
obj = __import__(module_name, fromlist=segments[:1])
for segment in segments:
obj = getattr(obj, segment)
return obj

Expand Down

0 comments on commit 72cfa09

Please sign in to comment.