Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!

Bug 532708

Summary: dev-python/pyzmq-14.4.1 - error: each element of 'ext_modules' option must be an Extension instance or 2-tuple
Product: Gentoo Linux Reporter: Greg Turner <gmturner007>
Component: [OLD] DevelopmentAssignee: Python Gentoo Team <python>
Status: RESOLVED FIXED    
Severity: normal CC: alex3255, dustin
Priority: Normal Keywords: PATCH
Version: unspecified   
Hardware: All   
OS: Linux   
URL: http://bugs.python.org/issue23102
See Also: https://bugs.gentoo.org/show_bug.cgi?id=533926
Whiteboard:
Package list:
Runtime testing required: ---
Attachments: pyzmq-14.4.1-use_setuptools_not_distutils.patch
result of: emerge --info > emergeinfo.out
build log
less_confusing_log.txt
pyzmq-14.4.1-import_distutils_after_setuptools_possibly_monkey_patches_it_due_to_nose_usage.patch
distutils_accomodate_extension_ducktypes.patch
distutils_accomodate_distribution_ducktypes.patch

Description Greg Turner 2014-12-16 16:01:43 UTC
Created attachment 391818 [details, diff]
pyzmq-14.4.1-use_setuptools_not_distutils.patch

Not sure what is behind this.  On my system I fail to build pyzmq due to some exception to the effect of "Those things in the ext_modules aren't instances of the Extension class":

This is, according to a quick DuckDuckGo, usually the result of Extension getting pulled in from setuptools -- thus there are two different class objects __name__d Extension floating around, which makes for the seemingly inexplicable failure of the isinstance(foo, Extension) test in distutils (their __repr__ suggests otherwise, making it all the more spooky...  In pdb:

((Pdb)) step
> /usr/lib64/python3.4/distutils/command/build_ext.py(360)check_extensions_list()
-> if not isinstance(ext, tuple) or len(ext) != 2:
((Pdb)) list
355             for i, ext in enumerate(extensions):
356                 if isinstance(ext, Extension):
357                     continue                # OK! (assume type-checking done
358                                             # by Extension constructor)
359  
360  ->             if not isinstance(ext, tuple) or len(ext) != 2:
361                     raise DistutilsSetupError(
362                            "each element of 'ext_modules' option must be an "
363                            "Extension instance or 2-tuple")
364  
365                 ext_name, build_info = ext
((Pdb)) exit
LEAVING RECURSIVE DEBUGGER
(Pdb) extensions
[<distutils.extension.Extension object at 0x7f7fd7e7dd68>, <distutils.extension.Extension object at 0x7f7fd7d2ca90>, <distutils.extension.Extension object at 0x7f7fd2acd0f0>, <distutils.extension.Extension object at 0x7f7fd2ae92e8>, <distutils.extension.Extension object at 0x7f7fd2ae9358>, <distutils.extension.Extension object at 0x7f7fd2ae93c8>, <distutils.extension.Extension object at 0x7f7fd2af2a90>, <distutils.extension.Extension object at 0x7f7fd2af2ac8>, <distutils.extension.Extension object at 0x7f7fd287d198>, <distutils.extension.Extension object at 0x7f7fd2884438>].  WTF, setuptools?)

I was able to work around this with the enclosed patch.  Obviously the patch is not right unless setuptools is added to the dependencies of pyzmq as well.

Didn't even think about upstreaming this -- nobody else seems to have the problem but me so I presume this is both somehow gentoo-specific -- possibly even my-machine-specfic, in some annoying, subtle way I'm too lazy to get to the bottom of).
Comment 1 Greg Turner 2014-12-16 16:11:05 UTC
(In reply to Greg Turner from comment #0)
> (Pdb) extensions
> [<distutils.extension.Extension object at 0x7f7fd7e7dd68>,
> <distutils.extension.Extension object at 0x7f7fd7d2ca90>,
> <distutils.extension.Extension object at 0x7f7fd2acd0f0>,
> <distutils.extension.Extension object at 0x7f7fd2ae92e8>,
> <distutils.extension.Extension object at 0x7f7fd2ae9358>,
> <distutils.extension.Extension object at 0x7f7fd2ae93c8>,
> <distutils.extension.Extension object at 0x7f7fd2af2a90>,
> <distutils.extension.Extension object at 0x7f7fd2af2ac8>,
> <distutils.extension.Extension object at 0x7f7fd287d198>,
> <distutils.extension.Extension object at 0x7f7fd2884438>].  WTF, setuptools?)

maybe setuptools tries to monkey-patch distutils for this, but some load-ordering or module-namespace duplication problem is preventing the correct binding from going to the code object for check_extensions_list... that would be a bug I could report upstream (to setuptools, if I really nailed it), if I could just wrap my head around it.
Comment 2 Jeroen Roovers (RETIRED) gentoo-dev 2014-12-17 06:36:54 UTC
(In reply to Greg Turner from comment #0)
> Not sure what is behind this.  On my system I fail to build pyzmq

1) Please attach the entire build log to this bug report.
2) Please post your `emerge --info' output in a comment.
Comment 3 Greg Turner 2014-12-17 23:24:10 UTC
Created attachment 391896 [details]
result of: emerge --info > emergeinfo.out

(In reply to Jeroen Roovers from comment #2)
> (In reply to Greg Turner from comment #0)
> 2) Please post your `emerge --info' output in a comment.

Heh, you might not like it :)  Well it's less mortifying than it used to be I guess.
Comment 4 Greg Turner 2014-12-17 23:35:35 UTC
Created attachment 391898 [details]
build log

Portage output.  Cut/pasted from the console so I can reverse my patch after the prepare phase (to get back the vanilla, non-working behavior).
Comment 5 Jeroen Roovers (RETIRED) gentoo-dev 2014-12-17 23:53:35 UTC
Still no idea what you're trying to do. You have an original build failure you're not disclosing and now a new build failure that depends on a patch that supposedly fixes the issue you're not disclosing to begin with.
Comment 6 Greg Turner 2014-12-18 02:25:13 UTC
(In reply to Jeroen Roovers from comment #5)
> Still no idea what you're trying to do. You have an original build failure
> you're not disclosing and now a new build failure that depends on a patch
> that supposedly fixes the issue you're not disclosing to begin with.

I reverted the patch I installed in /etc/portage/patches, which fixed the problem for me.  Had I let the build proceed with that patch, it would have succeeded.  The build failure I'm experiencing when using the gx86 ebuild without modification is as seen in the enclosed log.  Sorry for the confusion, I should have just hid the evidence of that since it's not relevant.
Comment 7 Greg Turner 2014-12-18 03:16:29 UTC
Created attachment 391902 [details]
less_confusing_log.txt

OK, sorry.  I get that there's only so much time in a day to triage stuff like this.

Here is a revised log which should clarify both what I was doing when I reversed the patch last time, and that something is not right, at least, on my particular system, when using the vanilla, unpatched, gx86 ebuild.
Comment 8 Greg Turner 2014-12-18 03:28:54 UTC
One other note:

In function `main':
timer_create02m9pb.c:(.text+0x15): undefined reference to `timer_create'

ain't it.  It's like an autotools check -- an expected error occurring as part of the build process.
Comment 9 Jason A. Donenfeld gentoo-dev 2014-12-20 08:56:49 UTC
Same issue with picard:


[ebuild     U  ] media-sound/picard-1.3 [1.2-r1] USE="acoustid cdda nls" 0 KiB

Total: 1 package (1 upgrade), Size of downloads: 0 KiB

Would you like to merge these packages? [Yes/No] 

>>> Verifying ebuild manifests

>>> Emerging (1 of 1) media-sound/picard-1.3::gentoo
 * picard-1.3.tar.gz SHA256 SHA512 WHIRLPOOL size ;-) ...                                                                                                             [ ok ]
>>> Unpacking source...
>>> Unpacking picard-1.3.tar.gz to /var/tmp/portage/media-sound/picard-1.3/work
>>> Source unpacked in /var/tmp/portage/media-sound/picard-1.3/work
>>> Preparing source in /var/tmp/portage/media-sound/picard-1.3/work/picard-1.3 ...
>>> Source prepared.
>>> Configuring source in /var/tmp/portage/media-sound/picard-1.3/work/picard-1.3 ...
>>> Source configured.
>>> Compiling source in /var/tmp/portage/media-sound/picard-1.3/work/picard-1.3 ...
 * Building of media-sound/picard-1.3 with CPython 2.7...
python2.7 setup.py build -b build-2.7
running build
generating scripts/picard from scripts/picard.in
running build_py
creating build-2.7
creating build-2.7/lib.linux-x86_64-2.7
creating build-2.7/lib.linux-x86_64-2.7/picard
copying picard/webservice.py -> build-2.7/lib.linux-x86_64-2.7/picard
copying picard/track.py -> build-2.7/lib.linux-x86_64-2.7/picard
copying picard/tagger.py -> build-2.7/lib.linux-x86_64-2.7/picard
copying picard/similarity.py -> build-2.7/lib.linux-x86_64-2.7/picard
copying picard/script.py -> build-2.7/lib.linux-x86_64-2.7/picard
copying picard/resources.py -> build-2.7/lib.linux-x86_64-2.7/picard
copying picard/releasegroup.py -> build-2.7/lib.linux-x86_64-2.7/picard
copying picard/plugin.py -> build-2.7/lib.linux-x86_64-2.7/picard                                                                                                            
copying picard/metadata.py -> build-2.7/lib.linux-x86_64-2.7/picard                                                                                                          
copying picard/mbxml.py -> build-2.7/lib.linux-x86_64-2.7/picard                                                                                                             
copying picard/log.py -> build-2.7/lib.linux-x86_64-2.7/picard                                                                                                               
copying picard/i18n.py -> build-2.7/lib.linux-x86_64-2.7/picard                                                                                                              
copying picard/file.py -> build-2.7/lib.linux-x86_64-2.7/picard                                                                                                              
copying picard/disc.py -> build-2.7/lib.linux-x86_64-2.7/picard                                                                                                              
copying picard/dataobj.py -> build-2.7/lib.linux-x86_64-2.7/picard
copying picard/config_upgrade.py -> build-2.7/lib.linux-x86_64-2.7/picard
copying picard/config.py -> build-2.7/lib.linux-x86_64-2.7/picard
copying picard/collection.py -> build-2.7/lib.linux-x86_64-2.7/picard
copying picard/cluster.py -> build-2.7/lib.linux-x86_64-2.7/picard
copying picard/album.py -> build-2.7/lib.linux-x86_64-2.7/picard
copying picard/acoustidmanager.py -> build-2.7/lib.linux-x86_64-2.7/picard
copying picard/acoustid.py -> build-2.7/lib.linux-x86_64-2.7/picard
copying picard/__init__.py -> build-2.7/lib.linux-x86_64-2.7/picard
creating build-2.7/lib.linux-x86_64-2.7/picard/browser
copying picard/browser/filelookup.py -> build-2.7/lib.linux-x86_64-2.7/picard/browser
copying picard/browser/browser.py -> build-2.7/lib.linux-x86_64-2.7/picard/browser
copying picard/browser/__init__.py -> build-2.7/lib.linux-x86_64-2.7/picard/browser
creating build-2.7/lib.linux-x86_64-2.7/picard/const
copying picard/const/locales.py -> build-2.7/lib.linux-x86_64-2.7/picard/const
copying picard/const/languages.py -> build-2.7/lib.linux-x86_64-2.7/picard/const
copying picard/const/countries.py -> build-2.7/lib.linux-x86_64-2.7/picard/const
copying picard/const/attributes.py -> build-2.7/lib.linux-x86_64-2.7/picard/const
copying picard/const/__init__.py -> build-2.7/lib.linux-x86_64-2.7/picard/const
creating build-2.7/lib.linux-x86_64-2.7/picard/coverart
copying picard/coverart/utils.py -> build-2.7/lib.linux-x86_64-2.7/picard/coverart
copying picard/coverart/image.py -> build-2.7/lib.linux-x86_64-2.7/picard/coverart
copying picard/coverart/__init__.py -> build-2.7/lib.linux-x86_64-2.7/picard/coverart
creating build-2.7/lib.linux-x86_64-2.7/picard/coverart/providers
copying picard/coverart/providers/whitelist.py -> build-2.7/lib.linux-x86_64-2.7/picard/coverart/providers
copying picard/coverart/providers/caa_release_group.py -> build-2.7/lib.linux-x86_64-2.7/picard/coverart/providers
copying picard/coverart/providers/caa.py -> build-2.7/lib.linux-x86_64-2.7/picard/coverart/providers
copying picard/coverart/providers/amazon.py -> build-2.7/lib.linux-x86_64-2.7/picard/coverart/providers
copying picard/coverart/providers/__init__.py -> build-2.7/lib.linux-x86_64-2.7/picard/coverart/providers
creating build-2.7/lib.linux-x86_64-2.7/picard/formats
copying picard/formats/wav.py -> build-2.7/lib.linux-x86_64-2.7/picard/formats
copying picard/formats/vorbis.py -> build-2.7/lib.linux-x86_64-2.7/picard/formats
copying picard/formats/mp4.py -> build-2.7/lib.linux-x86_64-2.7/picard/formats
copying picard/formats/id3.py -> build-2.7/lib.linux-x86_64-2.7/picard/formats
copying picard/formats/asf.py -> build-2.7/lib.linux-x86_64-2.7/picard/formats
copying picard/formats/apev2.py -> build-2.7/lib.linux-x86_64-2.7/picard/formats
copying picard/formats/__init__.py -> build-2.7/lib.linux-x86_64-2.7/picard/formats
creating build-2.7/lib.linux-x86_64-2.7/picard/formats/mutagenext
copying picard/formats/mutagenext/tak.py -> build-2.7/lib.linux-x86_64-2.7/picard/formats/mutagenext
copying picard/formats/mutagenext/compatid3.py -> build-2.7/lib.linux-x86_64-2.7/picard/formats/mutagenext
copying picard/formats/mutagenext/__init__.py -> build-2.7/lib.linux-x86_64-2.7/picard/formats/mutagenext
creating build-2.7/lib.linux-x86_64-2.7/picard/plugins
copying picard/plugins/__init__.py -> build-2.7/lib.linux-x86_64-2.7/picard/plugins
creating build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/util.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/ui_tagsfromfilenames.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/ui_passworddialog.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/ui_options_tags.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/ui_options_script.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/ui_options_renaming.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/ui_options_releases.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/ui_options_ratings.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/ui_options_plugins.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/ui_options_network.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/ui_options_metadata.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/ui_options_matching.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/ui_options_interface.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/ui_options_general.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/ui_options_folksonomy.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/ui_options_fingerprinting.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/ui_options_cover.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/ui_options_cdlookup_select.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/ui_options_cdlookup.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/ui_options_advanced.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/ui_options_about.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/ui_options.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/ui_infostatus.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/ui_infodialog.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/ui_edittagdialog.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/ui_cdlookup.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/tagsfromfilenames.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/ratingwidget.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/passworddialog.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/metadatabox.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/mainwindow.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/logview.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/itemviews.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/item.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/infostatus.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/infodialog.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/filebrowser.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/edittagdialog.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/coverartbox.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/collectionmenu.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/cdlookup.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
copying picard/ui/__init__.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui
creating build-2.7/lib.linux-x86_64-2.7/picard/ui/options
copying picard/ui/options/tags.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui/options
copying picard/ui/options/scripting.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui/options
copying picard/ui/options/renaming.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui/options
copying picard/ui/options/releases.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui/options
copying picard/ui/options/ratings.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui/options
copying picard/ui/options/plugins.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui/options
copying picard/ui/options/network.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui/options
copying picard/ui/options/metadata.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui/options
copying picard/ui/options/matching.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui/options
copying picard/ui/options/interface.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui/options
copying picard/ui/options/general.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui/options
copying picard/ui/options/folksonomy.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui/options
copying picard/ui/options/fingerprinting.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui/options
copying picard/ui/options/dialog.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui/options
copying picard/ui/options/cover.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui/options
copying picard/ui/options/cdlookup.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui/options
copying picard/ui/options/advanced.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui/options
copying picard/ui/options/about.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui/options
copying picard/ui/options/__init__.py -> build-2.7/lib.linux-x86_64-2.7/picard/ui/options
creating build-2.7/lib.linux-x86_64-2.7/picard/util
copying picard/util/webbrowser2.py -> build-2.7/lib.linux-x86_64-2.7/picard/util
copying picard/util/versions.py -> build-2.7/lib.linux-x86_64-2.7/picard/util
copying picard/util/thread.py -> build-2.7/lib.linux-x86_64-2.7/picard/util
copying picard/util/textencoding.py -> build-2.7/lib.linux-x86_64-2.7/picard/util
copying picard/util/tags.py -> build-2.7/lib.linux-x86_64-2.7/picard/util
copying picard/util/imageinfo.py -> build-2.7/lib.linux-x86_64-2.7/picard/util
copying picard/util/icontheme.py -> build-2.7/lib.linux-x86_64-2.7/picard/util
copying picard/util/filenaming.py -> build-2.7/lib.linux-x86_64-2.7/picard/util
copying picard/util/cdrom.py -> build-2.7/lib.linux-x86_64-2.7/picard/util
copying picard/util/bytes2human.py -> build-2.7/lib.linux-x86_64-2.7/picard/util
copying picard/util/__init__.py -> build-2.7/lib.linux-x86_64-2.7/picard/util
creating build-2.7/lib.linux-x86_64-2.7/picard/util/devutil
copying picard/util/devutil/__init__.py -> build-2.7/lib.linux-x86_64-2.7/picard/util/devutil
warning: build_py: byte-compiling is disabled, skipping.

running build_ext
error: each element of 'ext_modules' option must be an Extension instance or 2-tuple
 * ERROR: media-sound/picard-1.3::gentoo failed (compile phase):
 *   Building failed with CPython 2.7 in distutils_building() function
 * 
 * Call stack:
 *     ebuild.sh, line   93:  Called src_compile
 *   environment, line 4897:  Called distutils_src_compile
 *   environment, line 1208:  Called python_execute_function 'distutils_building'
 *   environment, line 3291:  Called die
 * The specific snippet of code:
 *                       die "${failure_message}";
 * 
 * If you need support, post the output of `emerge --info '=media-sound/picard-1.3::gentoo'`,
 * the complete build log and the output of `emerge -pqv '=media-sound/picard-1.3::gentoo'`.
 * The complete build log is located at '/var/tmp/portage/media-sound/picard-1.3/temp/build.log'.
 * The ebuild environment file is located at '/var/tmp/portage/media-sound/picard-1.3/temp/environment'.
 * Working directory: '/var/tmp/portage/media-sound/picard-1.3/work/picard-1.3'
 * S: '/var/tmp/portage/media-sound/picard-1.3/work/picard-1.3'
Comment 10 Mike Gilbert gentoo-dev 2014-12-20 16:20:34 UTC
I suspect the error about ext_modules is a symptom that is triggered by this error earlier in the log:

cc -c /var/tmp/portage/dev-python/pyzmq-14.4.1/temp/timer_create02m9pb.c -o /var/tmp/portage/dev-python/pyzmq-14.4.1/work/pyzmq-14.4.1-python3_3/temp.linux-x86_64-3.3/scratch/var/tmp/portage/dev-python/pyzmq-14.4.1/temp/timer_create02m9pb.o
cc /var/tmp/portage/dev-python/pyzmq-14.4.1/work/pyzmq-14.4.1-python3_3/temp.linux-x86_64-3.3/scratch/var/tmp/portage/dev-python/pyzmq-14.4.1/temp/timer_create02m9pb.o -o /var/tmp/portage/dev-python/pyzmq-14.4.1/work/pyzmq-14.4.1-python3_3/temp.linux-x86_64-3.3/scratch/a.out
/var/tmp/portage/dev-python/pyzmq-14.4.1/work/pyzmq-14.4.1-python3_3/temp.linux-x86_64-3.3/scratch/var/tmp/portage/dev-python/pyzmq-14.4.1/temp/timer_create02m9pb.o: In function `main':
timer_create02m9pb.c:(.text+0x15): undefined reference to `timer_create'
Comment 11 Mike Gilbert gentoo-dev 2014-12-20 16:27:29 UTC
(In reply to Mike Gilbert from comment #10)

Nevermind; that's just a test to see if we need to link with librt.
Comment 12 Mike Gilbert gentoo-dev 2014-12-20 16:58:02 UTC
Seems to be a bug in setuptools. I bisected it to this changeset.

https://bitbucket.org/pypa/setuptools/commits/dcd552da643c
Comment 13 Mike Gilbert gentoo-dev 2014-12-20 17:13:26 UTC
(In reply to Greg Turner from comment #1)
> maybe setuptools tries to monkey-patch distutils for this, but some
> load-ordering or module-namespace duplication problem is preventing the
> correct binding from going to the code object for check_extensions_list...
> that would be a bug I could report upstream (to setuptools, if I really
> nailed it), if I could just wrap my head around it.

I think you are on the right track here. Just playing with some imports in setup.py:

This works:

import setuptools
from distutils.extension import Extension

This fails:

from distutils.extension import Extension
import setuptools
Comment 14 Mike Gilbert gentoo-dev 2014-12-20 17:58:16 UTC
+  20 Dec 2014; Mike Gilbert <floppym@gentoo.org> pyzmq-14.3.1.ebuild,
+  pyzmq-14.4.0.ebuild, pyzmq-14.4.1.ebuild:
+  Force early import of setuptools to work around bug 532708.

I'll leave this open in case someone figures out the root cause here.
Comment 15 Mike Gilbert gentoo-dev 2014-12-20 19:25:07 UTC
I created an issue for setuptools.

https://bitbucket.org/pypa/setuptools/issue/309
Comment 16 Greg Turner 2014-12-21 00:20:59 UTC
What I find insane about it is that pyzmq very explicitly imports everything from distutils.  Then, Shazam! out of nowhere, setuptools objects appear like a rabbit from an empty hat.

Perhaps the way to fix it, then, is to figure out who is to blame for bringing in setuptools in the first place, say, by running python -v or replacing the first couple lines in all the setuptools modules with a pdb invocation (I recommend against using ipdb here -- it does not play nicely with these modules in my experience).

If the distutils modules are frozen, then you'll have your work cut out for you.  There is a way to "unfreeze" them.  Get in there with your debugger during the import statement, somehow (one way is to monkey patch __import__ in __builtins__ at the pdb  prompt) then, right as it's being imported, blow away the whatever-its-called-now that replaced the module-level __loader__ thingy in recent pythons.  And just wedge an instance of the regular source loader (not exactly loader anymore, but, like I said, whatever-its-called-now that points to the loader) instead, pointing to the real source code you want to see.

Or, maybe s/loader/meta-path-finder/ ?  Something like that works...  But it's nontrivial I'm afraid....

Then, re-import the module, and kill off the debugger.  Next time it's imported, the thing you want to happen will. python -v and a fearless attitude help :)

If nobody beats me to it, I might have time to take a closer look at it tonight, now that we're sure I'm not just a victim of my own rice.
Comment 17 Mike Gilbert gentoo-dev 2014-12-21 06:43:09 UTC
(In reply to Greg Turner from comment #16)
> What I find insane about it is that pyzmq very explicitly imports everything
> from distutils.  Then, Shazam! out of nowhere, setuptools objects appear
> like a rabbit from an empty hat.

On my system, it gets imported by dev-python/nose, which gets imported in pyzmq's setup.py.

% python3.4 setup.py build                      
Traceback (most recent call last):
  File "setup.py", line 55, in <module>
    import nose
  File "/usr/lib64/python3.4/site-packages/nose/__init__.py", line 1, in <module>
    from nose.core import collector, main, run, run_exit, runmodule
  File "/usr/lib64/python3.4/site-packages/nose/core.py", line 11, in <module>
    from nose.config import Config, all_config_files
  File "/usr/lib64/python3.4/site-packages/nose/config.py", line 9, in <module>
    from nose.plugins.manager import NoPlugins
  File "/usr/lib64/python3.4/site-packages/nose/plugins/__init__.py", line 185, in <module>
    from nose.plugins.manager import *
  File "/usr/lib64/python3.4/site-packages/nose/plugins/manager.py", line 418, in <module>
    import pkg_resources
  File "/home/floppym/src/setuptools/pkg_resources.py", line 78, in <module>
    import setuptools._vendor.packaging.version
  File "/home/floppym/src/setuptools/setuptools/__init__.py", line 3, in <module>
    raise Exception("foo")
Exception: foo
Comment 18 Greg Turner 2014-12-22 10:13:36 UTC
OK.  So, here is what I've been able to figure out.  First, setuptools aggressively monkey patches the core distutils module layout.  That's "just how it works."

Setuptools is effectively saying (so I surmise): "hey, we are like a distutils and then some.  So, if you want to import this stuff, congratulations, you have now upgraded your distutils to really be setuptools.  That way, your (presumably setuptools-based) setup.py can use all the fancy Setuptoolsian features but most legacy distutils-based code out there ought to work fine anyhow since we quack like a distutils."

I was previously thinking that, however setuptools is getting involved, must be a bug.  Maybe it is; maybe not.  I'd like to hear your thoughts, Mike et al.

Here's the deal.  Nose has a plugin architecture of some kind, as we can see from the file paths in Mike's stack trace (be advised, I know approximately fuck-all about nose; I'm mostly at peace with my ignorance for now)

Quoting from that manager.py:

:class:`DefaultPluginMananger`
    This is the manager class that will be used by default. If
    setuptools is installed, it is a subclass of
    :class:`EntryPointPluginManager` and :class:`BuiltinPluginManager`;
    otherwise, an alias to :class:`BuiltinPluginManager`.

The corresponding code looks vaguely like:

class BuiltinPluginManager: pass

try:
    import pkg_resources
    class DefaultPluginManager(
        EntryPointPluginManager, BuiltinPluginManager): pass
except ImportError:
    class DefaultPluginManager(BuiltinPluginManager): pass

As can be seen from Mike's stack-trace, pkg_resources (a setuptools module) is what unleashes the monkeys.

So, AFAICS, this comes down to fundamentally differing assumptions about when it's appropriate to monkey-patch distutils:

    pyzmq: Never.  We are using distutils, full stop.
    nose: If setuptools is installed, always, otherwise, never.
    setuptools: Always, on import.  We control the horizontal and the vertical.

Allright, fine.  So.... whose bug is this?

I propose that the bug is mostly in nose, although one could perhaps make compelling arguments that setuptools should do something other than monkey-patch distutils, or that pyzmq should know about nose's behavior and take it into account.

The reason I say so: nose clearly wants to support usage scenarios with and without setuptools.

But nose is sort-of acting as though everyone is using pip+virtualenv -- that is, "Is setuptools around" is a piss-poor way to guess the answer to the question "is setup.py using setuptools?"

Seeking advice/thoughts here...  shall I put this to the nose people, wherever they are to be found?

Meanwhile, I'll post an improved patch here, which works around the problem in pyzmq's setup.py simply by re-ordering the imports.
Comment 19 Greg Turner 2014-12-22 10:22:33 UTC
Created attachment 392216 [details, diff]
pyzmq-14.4.1-import_distutils_after_setuptools_possibly_monkey_patches_it_due_to_nose_usage.patch

A revised setup.py-level work-around which simply re-orders the imports to avoid the problem.
Comment 20 Greg Turner 2014-12-22 11:01:11 UTC
(In reply to Greg Turner from comment #19)
> Created attachment 392216 [details, diff] [details, diff]
> pyzmq-14.4.1-
> import_distutils_after_setuptools_possibly_monkey_patches_it_due_to_nose_usag
> e.patch
> 
> A revised setup.py-level work-around which simply re-orders the imports to
> avoid the problem.

One other note.  Clearly the behavior of setuptools did change.  "import pkg_resources" presumably used not to cause monkey patching distutils; after the commit Mike mentioned above, apparently, it does.

That might be a second bug, depending on whether or not setuptools deliberately decided this was the correct behavior, or not.

Either way, I'd say that, given that some versions of setuptools will monkey patch, and some will not, when pkg_resources is imported, nose should provide some code-path that will avoid importing pkg_resources even if we import nose -- otherwise, nose effectively becomes subtly incompatible with at least the setup.py from pyzmq, and possibly more.

BTW, picard looks to have a somewhat similar etiology although it does not use nose -- like pyzmq, picard does "from distutils.core import Extension".

However, annoyingly, I can't recreate the failure reported by Jason -- the ebuild works, for me, OOTB (nb: my portage tree is a few days out of date by now).  Also somewhat wierdly, Picard is clearly aware of the issue -- it's setup.py says:

try:
    from py2app.build_app import py2app
    do_py2app = True
except ImportError:
    do_py2app = False

# this must be imported *after* py2app, because py2app imports setuptools
# which "patches" (read: screws up) the Extension class
from distutils import log
from distutils.command.build import build
from distutils.command.install import install as install
from distutils.core import setup, Command, Extension
from distutils.dep_util import newer
from distutils.dist import Distribution
from distutils.spawn import find_executable

Maybe if I had py2app installed I would see the failure although this still seems pretty inexplicable to me :/
Comment 21 Greg Turner 2014-12-22 12:53:34 UTC
(In reply to Greg Turner from comment #18)
> Allright, fine.  So.... whose bug is this?

You know, another idea just occurred to me.  The real bug here, when you get down to it, is distutils checking issubclass() in the first place.  It's not pythonic and is leading to a real-world problem -- hence, it's pretty much a bug, de-facto if not de-jure.

Get rid of that check, and this whole mess just vanishes.  Don't know why that didn't occur to me sooner; regardless of who's ultimately "to blame" for this mess, it certainly seems to me that of all the various ways one could attack this problem, loosening up that check would be the least semantically impactful and have the most concise fix.

Unless someone convinces me otherwise, I'll file a cpython bug for this, some time tomorrow.  Whatever function that issubclass check serves can almost surely be achieved with a hasattr() check that allows for duck-typing.
Comment 22 Greg Turner 2014-12-22 22:09:14 UTC
Created attachment 392244 [details, diff]
distutils_accomodate_extension_ducktypes.patch

Here is an alternate fix, which I will probably file as a cpython bug.

If applied to "all" of your gentoo python installations (I applied it, for example, to dev-lang/python:{2.7,3.3,3.4} by placing it in /etc/portage/patches/dev-lang/python/distutils_accomodate_extension_ducktypes.patch and running:

    emerge -1a $(qlist -IeSC dev-lang/python)

), I believe the problem is fixed.

I'd appreciate it, Jason, if you could verify that your picard hasn't magically fixed itself, somehow, and then try this patch in your python installations, and see if the picard issue doesn't disappear as well.
Comment 23 Greg Turner 2014-12-23 06:42:09 UTC
http://bugs.python.org/issue23102
Comment 24 Steve Arnold archtester gentoo-dev 2014-12-27 18:59:21 UTC
*** Bug 533442 has been marked as a duplicate of this bug. ***
Comment 25 Steve Arnold archtester gentoo-dev 2014-12-27 19:48:08 UTC
Just marked a duplicate, but now I'm not so sure...  Tried the patch in comment #22 but still getting the same error installing markdown:

>>> Install markdown-2.5.1 into /var/tmp/portage/dev-python/markdown-2.5.1/image/ category dev-python
 * python3_3: running distutils-r1_run_phase distutils-r1_python_install
/usr/bin/python3.3 setup.py install --root=/var/tmp/portage/dev-python/markdown-2.5.1/image//_python3.3
running install
running build
running build_py
running build_scripts
running build_docs
running install_lib
Traceback (most recent call last):
  File "setup.py", line 249, in <module>
    'Topic :: Text Processing :: Markup :: HTML',
  File "/usr/lib64/python3.3/distutils/core.py", line 148, in setup
    dist.run_commands()
  File "/usr/lib64/python3.3/distutils/dist.py", line 930, in run_commands
    self.run_command(cmd)
  File "/usr/lib64/python3.3/distutils/dist.py", line 949, in run_command
    cmd_obj.run()
  File "/usr/lib64/python3.3/distutils/command/install.py", line 581, in run
    self.run_command(cmd_name)
  File "/usr/lib64/python3.3/distutils/cmd.py", line 313, in run_command
    self.distribution.run_command(command)
  File "/usr/lib64/python3.3/distutils/dist.py", line 947, in run_command
    cmd_obj = self.get_command_obj(command)
  File "/usr/lib64/python3.3/distutils/dist.py", line 822, in get_command_obj
    cmd_obj = self.command_obj[command] = klass(self)
  File "/usr/lib64/python3.3/site-packages/setuptools/__init__.py", line 125, in __init__
    _Command.__init__(self,dist)
  File "/usr/lib64/python3.3/distutils/cmd.py", line 57, in __init__
    raise TypeError("dist must be a Distribution instance")
TypeError: dist must be a Distribution instance
Comment 26 Greg Turner 2014-12-27 19:50:29 UTC
Yes, it is a different bug, with a highly similar etiology.  My patch doesn't address it.
Comment 27 Greg Turner 2014-12-27 20:09:26 UTC
To sum up, perhaps it's worth considering (In reply to Greg Turner from comment #26)
> Yes, it is a different bug, with a highly similar etiology.  My patch
> doesn't address it.

Actually, however, it's so similar, now that I think about it, that perhaps it's sensible to keep #533442 as a duplicate, and to consider this a new sequela of the same bug, for which no work-around currently has been developed.

I'll take a look later and see if I can't think of some way to augment my patch to cover this as well.  The same bug was mentioned by folks on the python (... or was it setuputils?) bugs.
Comment 28 Greg Turner 2014-12-27 20:17:35 UTC
There is a lot of room here for everybody to decide that this is somebody else's bug.

In my experience, when that is the case, it literally almost always occurs, and tends to go on for years.

If somebody wants to prove me wrong, great, color me pleasantly surprised and kudos to whatever project took some proactive steps to make things go smoothly for end users.

But, IMO, Gentoo should not wait for upstream fixes to these problems.

Instead it should develop a hopefully-good-enough-for-now solution, deploy it to end-users, cross it's fingers and pray.  Of course, if it didn't work, or caused regressions, we'd just have to deal with that when it happens, that is the downside of shooting first and asking questions later.

Even so, in this case, I feel it's the right way to go.
Comment 29 Dirkjan Ochtman (RETIRED) gentoo-dev 2014-12-27 20:36:40 UTC
Carrying patches that upstream wants no business with is a really shitty position to be in as a distro; it means forward-porting the patch on any future release, even in small bug-fix-only releases, and forward-porting is often not trivial (particularly not in the case of the whole distutils/setuptools shebang). Meanwhile, we have to do serious effort on each new release; and I'd posit that our packaging gets delayed superlinearly for the amount of effort involved in doing the work.

So, while there may be cases where carrying a patch upstream doesn't want is the right approach, it comes with significant costs that we should also be mindful of.
Comment 30 Steve Arnold archtester gentoo-dev 2014-12-27 22:35:34 UTC
So far no other failures (but still 200+ packages to go) but markdown-2.5* no longer installs correctly (the workaround is to add back the src_prepare sed hack from 2.3.1 and then it installs correctly).
Comment 31 Steve Arnold archtester gentoo-dev 2014-12-27 22:42:15 UTC
Note that markdown 2.5* craps out with or without Greg's patch (and I'm still running a deep world update with the patch applied and no problems so far).
Comment 32 Greg Turner 2014-12-27 22:44:57 UTC
(In reply to Dirkjan Ochtman from comment #29)
> Carrying patches that upstream wants no business with is a really shitty
> position to be in as a distro

Well this is all hypothetical.  If upstreams are responsive, great, problem solved.

Anyhow, I don't think your description quite captures what I'm predicting.

My prediction is not that upstream(s) will reject these contributions, but that everybody will say "yes, somebody really ought to look at this eventually and figure out whose bug this is..." and nothing will happen.

The ebuilds are broken, right now.  Obviosly we have nothing to lose by engineering fixes to the problems and contributing our fixes to the appropriate upstream(s).... sort of like bring a horse to water is never a bad idea.

But, until the horse drinks, we also have very little to lose, given that the result right now in gx86 is an ebuild crash, by fixing the problem in Gentoo, so our users can go on with their work and stop squinting at this bug.

As for the maintenance burden... my one-line patch applies to all python versions since at least 2.7.  That's about ten years of python history.  If, ten years from now, upstreams still haven't gotten around to fixing this, and something breaks, then, I suppose you can say "I told you so" -- but then, so could I :)

Once upstreams take care of it, we just drop our patch.  No big deal.  They surely will, sooner or later, or else the sun will swallow the earth -- either way, this problem is not eternal -- but I predict it might not be short-lived either.
Comment 33 Greg Turner 2014-12-27 22:54:33 UTC
(In reply to Greg Turner from comment #32)
> As for the maintenance burden... my one-line patch applies to all python
> versions since at least 2.7.  That's about ten years of python history.

This is a bit hyperbolic.  It's probably a bit less than ten years (although I wouldn't be surprised if my patch still applied and worked fine in python 2.2), and, presumably my patch will be a bit bigger if I can address the bug #533442 issue as well.
Comment 34 Mike Gilbert gentoo-dev 2014-12-28 06:24:18 UTC
The issue should be resolved in the next setuptools release.

https://bitbucket.org/pypa/setuptools/issue/311

The change in behavior was that pkg_resouces was accidentally changed to import setuptools, which caused setuptools to get imported unintentionally by many packages.
Comment 35 Greg Turner 2014-12-28 09:22:38 UTC
(In reply to Mike Gilbert from comment #34)
> The issue should be resolved in the next setuptools release.
> 
> https://bitbucket.org/pypa/setuptools/issue/311
> 
> The change in behavior was that pkg_resouces was accidentally changed to
> import setuptools, which caused setuptools to get imported unintentionally
> by many packages.

Great news.  Sounds like this will return us to how things were before -- mostly working OOTB.  For the convenience of any hypothetical backporters or casual work-around seekers AFAICS:

https://bitbucket.org/pypa/setuptools/commits/5092bf199e11fb243ab17de33461fea1c6d54ce2/raw/,

https://bitbucket.org/pypa/setuptools/commits/e2181ecd6ccbc67b366a968d968b785b2941b31f/raw/,

and

https://bitbucket.org/pypa/setuptools/commits/f0cc850450fdfb6529676b8aebcf9256bb295700/raw/

are the corresponding commits.

Sorry I haven't gotten to it yet, but I do still intend to try to rev "distutils_accomodate_extension_ducktypes.patch" with a corresponding fix for the Command problem (bug #533442) -- assuming, of course, that I can find a reasonable, low-impact, and frankly low-effort way to do so.
Comment 36 Greg Turner 2014-12-29 11:32:52 UTC
Created attachment 392636 [details, diff]
distutils_accomodate_distribution_ducktypes.patch

Here as promised is the same trick for the very similar bug that's been cropping up, due to distutils.cmd.Command.__init__ checking isinstance(dist, Distribution).

This time, I had to finesse the patch a bit to make it apply in all pythons, but, it does.  Same recipe (put it in /etc/portage/patches/dev-lang/python alongside the other one, and emerge -1a $(qlist -ICSe dev-lang/python) should apply.

Note to folks testing this -- I haven't ported either patch to pypy, so pypy will still suffer from these issues until that changes.  Therefore please test with USE=-python_targets_pypy if pypy is in your PYTHON_TARGETS.
Comment 37 Mike Gilbert gentoo-dev 2014-12-30 03:55:42 UTC
I just added dev-python/setuptools-9.1 to the tree. Please confirm that this resolves the issue with pyzmq.

Regarding your patches for the distutils package: while I do appreciate the effort, we are probably not going to carry them as distro-specific. Please spend that effort getting them applied upstream.
Comment 38 Greg Turner 2014-12-30 11:10:53 UTC
(In reply to Mike Gilbert from comment #37)
> I just added dev-python/setuptools-9.1 to the tree. Please confirm that this
> resolves the issue with pyzmq.
> 
> Regarding your patches for the distutils package: while I do appreciate the
> effort, we are probably not going to carry them as distro-specific. Please
> spend that effort getting them applied upstream.

Can't confirm or disconfirm yet.  Will endeavour to guinea-pig this for you within the next 24 hours.
Comment 39 Greg Turner 2014-12-30 11:56:58 UTC
(In reply to Mike Gilbert from comment #37)
> I just added dev-python/setuptools-9.1 to the tree. Please confirm that this
> resolves the issue with pyzmq.
> 
> Regarding your patches for the distutils package: while I do appreciate the
> effort, we are probably not going to carry them as distro-specific. Please
> spend that effort getting them applied upstream.

I assure you I have zero or, really, negative personal attachment to that outcome, but thanks for the encouraging words.

Assuming the immediate "crisis" is resolved in ~amd64, as far as I'm concerned, I've "done my bit" -- upstream has my patches; they presumably know best whether to pipe them to /dev/null or /usr/bin/hg.
Comment 40 Mike Gilbert gentoo-dev 2014-12-30 16:58:32 UTC
+  30 Dec 2014; Mike Gilbert <floppym@gentoo.org> pyzmq-14.3.1.ebuild,
+  pyzmq-14.4.0.ebuild, pyzmq-14.4.1.ebuild:
+  Remove workaround for bug 532708; issue is resolved in setuptools-9.1.
Comment 41 Greg Turner 2015-01-02 00:37:24 UTC
(In reply to Mike Gilbert from comment #40)
> +  30 Dec 2014; Mike Gilbert <floppym@gentoo.org> pyzmq-14.3.1.ebuild,
> +  pyzmq-14.4.0.ebuild, pyzmq-14.4.1.ebuild:
> +  Remove workaround for bug 532708; issue is resolved in setuptools-9.1.

A bit late, sorry, but I can now confirm that this W4M.  Thanks all!