This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Import errors in email.message.py
Type: crash Stage:
Components: Library (Lib) Versions: Python 2.6
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: barry Nosy List: JohnJackson, amaury.forgeotdarc, barry, gpolo, kiilerix, zhirsch
Priority: low Keywords: patch

Created on 2008-04-12 05:37 by JohnJackson, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
test_mailbox.py JohnJackson, 2008-04-14 21:48 Sample code for issue 2622
emailcasings.patch kiilerix, 2008-04-25 14:44 Fix old email casings in std lib
emailcasings2.patch kiilerix, 2009-06-23 23:44 Updated fix for 2.6 for old email casings
Messages (18)
msg65391 - (view) Author: John Jackson (JohnJackson) Date: 2008-04-12 05:37
In email.message.py there are two import errors:
line 128 from email.Generator import Generator
should be 
  from email.generator import Generator
line 784 from email.Iterators import walk
should be 
  from email.iterators import walk
msg65419 - (view) Author: Guilherme Polo (gpolo) * (Python committer) Date: 2008-04-12 21:03
You may not like the naming applied there, but surely it is not a import
error. Can you actually manage to get an ImportError ?
msg65429 - (view) Author: John Jackson (JohnJackson) Date: 2008-04-13 00:21
Yes. If the code is used to build a standalone application with py2app 
on the Mac, here's the end of the stack trace:
  File "controller.pyo", line 17, in <module>
  File "readMail.pyo", line 15, in <module>
  File "mailbox.pyo", line 1294, in <module>
  File "email/__init__.pyo", line 79, in __getattr__
  File "email/message.pyo", line 86, in <module>
  File "email/message.pyo", line 784, in Message
  File "email/__init__.pyo", line 79, in __getattr__
ImportError: No module named iterators
msg65430 - (view) Author: Guilherme Polo (gpolo) * (Python committer) Date: 2008-04-13 00:36
Can you send a sample code that reproduces that ?
msg65459 - (view) Author: John Jackson (JohnJackson) Date: 2008-04-14 04:18
I'll put one together.
msg65484 - (view) Author: John Jackson (JohnJackson) Date: 2008-04-14 21:48
Attached is a sample code that reproduces the problem under python 2.5 on 
Mac OS 10.4.11. See file for instructions on how to reproduce the issue.
msg65782 - (view) Author: Mads Kiilerich (kiilerix) * Date: 2008-04-25 13:57
AFA I understand it the ImportError comes when running a py2exe/app'ed
package where iterators.py hasn't been included.

I was just about to file a report about (I think) the same issue, seen
on XP when py2exe'ing code using the email module.

Exactly the same problem with a good(?) explanation can be found on
http://mail.python.org/pipermail/spambayes/2007-December/021485.html

The problem comes because the real module names now are lowercase, and
email/__init__.py plays tricks with _LOWERNAMES in order to keep the old
uppercase names working. The problem is that the email lib itself uses
the old (deprecated?) non-existing name.

IMHO the solution is to use right-cased names. I have (only) tested it
by changing the single reference to email.Iterators. I think this is a
safe bugfix which should be included in 2.5 ASAP.

A workaround is to import email.iterators from some other code or to
tell py2exe/pyapp explicitly include the modules in the package.
msg65784 - (view) Author: Mads Kiilerich (kiilerix) * Date: 2008-04-25 14:44
This patch seems to fix the issue for me.

The easiest way to verify might be to create another patch and compare
them...
msg65785 - (view) Author: Barry A. Warsaw (barry) * (Python committer) Date: 2008-04-25 15:30
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Apr 25, 2008, at 10:44 AM, Mads Kiilerich wrote:

>
> Mads Kiilerich <mads@kiilerich.com> added the comment:
>
> This patch seems to fix the issue for me.
>
> The easiest way to verify might be to create another patch and compare
> them...

The patch looks pretty good, +1.  The only part I'm not so sure about  
is the renaming in test_email.py since test_email_renamed.py is  
supposed to use the new names while test_email.py (in 2.5 at least) is  
supposed to test the backward compatible names.

- -Barry

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.8 (Darwin)

iQCVAwUBSBH5BnEjvBPtnXfVAQJJNAP/VEIyMvObRz9SH5EL4Tu4KuVay5C/vvxC
AvlfRrmCNJXXRdU2ZfmiSG357Zc3JfRLhxZBSVpuMQidictxUZttcnqoFlwS2Edu
VwXWtihGjMncn4qdR2IlwEUitG6eSJlrsbo+RtaDSFXlWNyzA83O3mBffeIn8vYn
FLILF8aVaQQ=
=nxt/
-----END PGP SIGNATURE-----
msg65795 - (view) Author: Mads Kiilerich (kiilerix) * Date: 2008-04-25 17:04
OK. I had assumed that backward compatibility was tested in the _renamed
tests, so that these tests one day could be dropped together with
backward compatibility. I didn't notice that my search'n'replaces showed
me that I was wrong.

But a bugfix in a stable release really shouldn't change any tests
unless the tests are wrong. And I can't come up with a reasonable new
test. It could perhaps be tested that all modules could be py2exe'ed and
imported individually with automatic dependency resolving... But such a
test doesn't belong in the test suite.

I suggest that my patch is applied without the test cleanup.
msg65800 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2008-04-25 17:37
> But such a test doesn't belong in the test suite.

py2exe uses the "modulefinder" module to find dependencies.

I tried this command::

    ./python -m modulefinder Lib\email\message.py

And among the output, there is::

    ....
    ? email.Generator imported from __main__, email.message
    ? email.Iterators imported from __main__, email.message
    ....

It surely can be turned into a unit test. For example::

    import email.message
    filename = email.message.__file__
    if filename.endswith(".pyc"):
        filename = filename[:-1]

    import modulefinder
    mf=modulefinder.ModuleFinder()
    mf.run_script(filename)
    assert "email.Generator" not in mf.any_missing()
msg65849 - (view) Author: Mads Kiilerich (kiilerix) * Date: 2008-04-26 16:40
Testing that email.message doesn't use the "wrong" casing
email.Generator isn't enough. That would just test that this patch has
been applied. It must also be tested that no other modules uses the
wrong casing of email.Generator. Or other email packages. Or any other
packages at all.

IMHO the "right" test would be to test that modulefinder can find all
relevant modules in all cases. The problem is that it gives irrelevant
warnings.

I tested with some shell hacking to find all modulefinder failures which
could be found with another casing:

find * -name '*.py'|sed 's,\.py$,,g;s,/,.,g;s,\.__init__$,,g' >
/tmp/all_fs_modules
for a in $(find * -name '*.py'); do echo $a; python -m modulefinder $a;
echo; done > /tmp/all_referenced_modules
for a in $(grep ^? /tmp/all_referenced_modules|sed 's,^\? \(.*\)
imported from .*,\1,g'|sort|uniq); do grep -i "^$a"'$'
/tmp/all_fs_modules; done > /tmp/referenced_existing_ignorecased

email.base64mime
email.charset
email.encoders
email.errors
email.generator
email.header
email.iterators
email.message
email.parser
email.quoprimime
email.utils
ftplib

- where the last hit comes from bogus regexp matching. The test takes
long time to run as it is. That could probably be improved. But still I
think this is to be compared with "lint"-like tools which should be run
reguarly but isn't suitable for unit tests.

I feel ashamed for arguing against introducing a test. I think I do that
because I think that this isn't a "normal" bug and thus isn't suitable
for unit testing. 

The email module itself really is fully backwards compatible. And
modulefinder does a good job doing what it does and can't be blamed for
not figuring the email hackery out. The problem comes when a third
external modules puts things together and they doesn't fit together as
one could expect.

Also, currently both casings works and should work. Using the old casing
isn't a "bug bug", but it has consequences which IMHO is enough to call
it a bug and fix it.

Perhaps Python could have a standard way markup of deprecated functions
so that it could be checked that the standard librarary didn't use them.
msg87666 - (view) Author: Zach Hirsch (zhirsch) Date: 2009-05-13 02:35
I'm not sure if this is the same problem, but it seems related.  I can
get the same ImportError without involving py2exe or modulefinder:

Python 2.5.4 (r254:67916, Feb 18 2009, 03:00:47) 
[GCC 4.3.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> import email.message
>>> sys.modules = sys.modules.copy()
>>> msg = email.message.Message()
>>> msg['From'] = 'foo@bar.com'
>>> msg.as_string()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.5/email/message.py", line 128, in as_string
    from email.Generator import Generator
  File "/usr/lib/python2.5/email/__init__.py", line 80, in __getattr__
    mod = sys.modules[self.__name__]
KeyError: 'email.generator'

If the "sys.modules = sys.modules.copy()" line is left out, everything
works as expected.
msg89443 - (view) Author: John Jackson (JohnJackson) Date: 2009-06-17 04:25
Also occurs in 2.6...
msg89648 - (view) Author: Barry A. Warsaw (barry) * (Python committer) Date: 2009-06-23 21:51
The patch looks pretty good, except that you should not change
test_email.py.  It specifically tests the old names, while
test_email_renamed.py tests the new names.

There's no point in fixing Python 2.5 since there won't be another
maintenance release of that version.  It probably also does not make
sense to change Python 3.x.  You should fix Python 2.6 though.

In the trunk, we should remove all the old names for good.
msg89652 - (view) Author: Mads Kiilerich (kiilerix) * Date: 2009-06-23 23:44
I have updated the patch. (Applied to 2.6 where it seems like some
casings had been fixed, so I dropped all the rejects. Changes to
test_email.py has been.)
msg89662 - (view) Author: Barry A. Warsaw (barry) * (Python committer) Date: 2009-06-24 13:03
Looks good; feel free to commit.
msg90594 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2009-07-16 22:50
applied with r37952 (trunk), r37953 (2.6) and r37978 (py3k, docstrings 
only). Thanks for the patch!
History
Date User Action Args
2022-04-11 14:56:33adminsetgithub: 46874
2009-07-16 22:50:57amaury.forgeotdarcsetstatus: open -> closed
resolution: accepted -> fixed
messages: + msg90594
2009-06-24 13:03:52barrysetmessages: + msg89662
versions: - Python 2.5
2009-06-23 23:44:39kiilerixsetfiles: + emailcasings2.patch

messages: + msg89652
2009-06-23 21:51:05barrysetresolution: accepted
messages: + msg89648
2009-06-17 04:25:39JohnJacksonsetmessages: + msg89443
versions: + Python 2.6
2009-05-13 02:35:39zhirschsetnosy: + zhirsch
messages: + msg87666
2008-04-26 16:40:46kiilerixsetmessages: + msg65849
2008-04-25 17:37:59amaury.forgeotdarcsetnosy: + amaury.forgeotdarc
messages: + msg65800
2008-04-25 17:04:18kiilerixsetmessages: + msg65795
2008-04-25 15:30:18barrysetmessages: + msg65785
2008-04-25 14:44:39kiilerixsetfiles: + emailcasings.patch
keywords: + patch
messages: + msg65784
2008-04-25 13:57:59kiilerixsetnosy: + kiilerix
messages: + msg65782
2008-04-14 21:48:36JohnJacksonsetfiles: + test_mailbox.py
messages: + msg65484
2008-04-14 04:18:03JohnJacksonsetmessages: + msg65459
2008-04-13 00:36:15gpolosetmessages: + msg65430
2008-04-13 00:21:52JohnJacksonsetmessages: + msg65429
2008-04-12 21:44:27georg.brandlsetpriority: low
assignee: barry
nosy: + barry
2008-04-12 21:03:28gpolosetnosy: + gpolo
messages: + msg65419
2008-04-12 05:37:51JohnJacksoncreate