plone.recipe.zope2instance: install() method in __init__.py uses mkzopeinstance.exe instead of mkzopeinstance-script.py on Windows (fix included)

Bug #462731 reported by kleist
8
This bug affects 1 person
Affects Status Importance Assigned to Milestone
collective.buildout
Fix Released
Undecided
Unassigned
Nominated for Trunk by kleist

Bug Description

Windows 7 (amd64), Python 2.6.2 (32 bit)

I was trying the "coredev" buildout for Plone 4 (http://svn.plone.org/svn/plone/buildouts/plone-coredev/branches/4.0),
Zope was successfully built using MinGW. Later on, I got this error:

--------------------------------------------------------------------------------------
Generated script 'E:\\buildout\\plone4coredev\\bin\\mkzopeinstance'.
Generated script 'E:\\buildout\\plone4coredev\\bin\\runzope'.
  File "E:\buildout\plone4coredev\bin\mkzopeinstance.exe", line 1
SyntaxError: Non-ASCII character '\x90' in file E:\buildout\plone4coredev\bin\mkzopeinstance.exe on line 1, but no encoding declared;
see http://www.python.org/peps/pep-0263.html for details
While:
  Installing instance.

An internal error occured due to a bug in either zc.buildout or in a
recipe being used:
Traceback (most recent call last):
  File "e:\buildout\plone4coredev\eggs\zc.buildout-1.4.1-py2.6.egg\zc\buildout\buildout.py", line 1659, in main
    getattr(buildout, command)(args)
  File "e:\buildout\plone4coredev\eggs\zc.buildout-1.4.1-py2.6.egg\zc\buildout\buildout.py", line 532, in install
    installed_files = self[part]._call(recipe.install)
  File "e:\buildout\plone4coredev\eggs\zc.buildout-1.4.1-py2.6.egg\zc\buildout\buildout.py", line 1203, in _call
    return f()
  File "e:\buildout\plone4coredev\src\plone.recipe.zope2instance\src\plone\recipe\zope2instance\__init__.py", line 88, in install
    ) == 0
AssertionError
--------------------------------------------------------------------------------------

Obviously, os.spawnl() tries to start "mkzopeinstance.exe" as a python script instead of "mkzopeinstance-script.py".

The cause seems to be that when the "mkzopeinstance" variable is defined (the first leg, after "if not self.zope2_location:"),
the *first* element in the tuple returned by zc.buildout.easy_install.scripts() is used. However, the _script() method in "easy_install.py" returns the Windows script (ending with "-script.py") in the *second* element.

After changing line 68 in "...\zope2instance\__init__.py" from ")[0]" to ")[1]" everything works fine.

So now I'm the first man on the planet who actually has tested the Plone 4 coredev buildout on Windows?!

Tags: windows
Revision history for this message
Martin Aspeli (optilude) wrote :

Changing that to "1" is probably not the correct solution. That means you're now testing that the program returned an error code of 1 instead of 0 (which is what it does when it runs successfully).

Revision history for this message
kleist (kleist) wrote :

I didn't mean that "0": But the last one here...

        if not self.zope2_location:
            # If we have an egg install, make sure the Zope2 scripts we need
            # are actually installed.
            mkzopeinstance = zc.buildout.easy_install.scripts(
                [('mkzopeinstance', 'Zope2.utilities.mkzopeinstance', 'main')],
                ws, options['executable'], options['bin-directory'],
                )[0]

... that picks the *first* element instead of the *second* from the list returned by scripts() in http://svn.zope.org/zc.buildout/trunk/src/zc/buildout/easy_install.py?rev=103354&view=auto.

I do realize that simply changing [0] to [1] isn't the solution, it simply works for me since my desktop is Windows (yes: I'm a Linux hippie gone bad... Windows 7 is simply too nice to resist). One would need a test of "sys.platform" to decide which element to pick.

Revision history for this message
Charlie_X (charlie) wrote :

I can confirm the same behaviour on Windows XP and Windows Server 2003 and the workaround does not work. Would it be an idea to use subprocess instead of os.spawnl ?

Revision history for this message
kleist (kleist) wrote :

Are you sure that you have modified "plone\recipe\zope2instance\__init__.py",
line 68 in the method install(),
changed ")[0]" to ")[1]"
?

Revision history for this message
Charlie_X (charlie) wrote :

Sorry, you're right that does get things to work. Not sure of the other side effects for other systems.

Revision history for this message
kleist (kleist) wrote :

I've fixed bug here:

http://dev.plone.org/collective/changeset/103895/buildout/plone.recipe.zope2instance/trunk/src/plone/recipe/zope2instance/__init__.py

Since this is my first non-translation commit to the collective, please bear with me if I've not yet grokked the procedure.

The code contains a Python 2.5 construct (the ternary operator), this should be safe since Plone 3 uses a pinned version of the recipe?

Revision history for this message
kleist (kleist) wrote :

Uh oh... I'm not allowed to use Python 2.5 features yet: http://dev.plone.org/collective/changeset/103900

Revision history for this message
Hanno Schlichting (hannosch) wrote :

Using Python 2.5 or 2.6 constructs in the zope2instance trunk version is perfectly fine. It requires Zope 2.12 which itself only runs on Python 2.5 and 2.6.

Revision history for this message
Charlie_X (charlie) wrote :

You could just cast the boolean IS_WIN to an integer. However, in the interests of intelligibilty I suggest you spell out what needs changing for windows installs and why. What does this parameter do?

if IS_WIN:
    # we need the second parameter from the result of the easy_install on windows.

How many parameters does the easy_install return?

Revision history for this message
kleist (kleist) wrote :
Revision history for this message
Charlie_X (charlie) wrote :

It currently doesn't run because you've defined IS_WIN in the class scope - it's only available as self.IS_WIN. Just move the definition outside of the class and things are fine.

FWIW an alternative to the ternary operator that works for any version of Python would be "IS_WIN and 1 or 0"

Revision history for this message
kleist (kleist) wrote :

Thanks Charlie, that was really a stupid mistake. Fixed now.

Given the blessing of Hanno, I'll stay with the new ternary operator because I don't like the potentially error prone "and-or trick":

http://diveintopython.org/power_of_introspection/and_or.html#d0e9975

Revision history for this message
Charlie_X (charlie) wrote :

Personally I much prefer the "a is True and x or b" approach over the ternary operator which is an sugary tidbit for C programmers... ;-)

I can understand it biting people - only until you realise that you have to work with booleans - but I find it more pythonic and generic: it matches perfectly extensive if clauses both in Python and in database queries but also parallels some other "resolving" functions such as min() and max() and is useful in TALES. Coincidentally the new formlib-based folder view in CMF 2.2 has a collection of what I think are similar implementations.

I'll add the usual caveat that as soon as you find yourself being too clever with any of this take a deep breath and write it out in full. It's Python so at most it will be only one extra line of code which probably replaces the explanatory comment you put there to remind you why you used the shortcut!

But nice to have the buildout working.

kleist (kleist)
description: updated
Revision history for this message
Asigot (heywyn) wrote :
Changed in collective.buildout:
status: New → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.