[Zope-dev] Windows Installer for Zope 2.9+

Tim Peters tim.peters at gmail.com
Fri Dec 9 22:19:57 EST 2005


...

[Sidnei da Silva]
> Simplifying a lot what the existing Zope 2 installer does, it
> basically creates a 'software home', a default 'instance home' and
> registers the services. All but the first part is done manually for
> Zope 3, so I can see the lack of glow there.

There's also that Zope2 sticks Python inside of Zope, but Zope3 sticks
Zope inside of Python.  A consequence is that you can't install more
than one instance of Zope3 under a single Windows account, but can
install any number of Zope2s.  In the other direction, it's always a
puzzle for Zope2 Windows users to figure out how to give their Zope
access to packages installed in their (own, separate) Python.  For
Zope3 that's a no-brainer.

> Supposing there is a existing python installation, how difficult is it
> to get a distutils-based windows installer to be extracted to a random
> directory outside site-packages?

distutils has no support for that.

> My guess is that it's basically unzip it.

What are you trying to accomplish?  (I know you're trying to push code
into some directory other than under Lib/site-packages, but I don't
know which code or why.)

> If that's the case, we can simplify the Zope 2 inno installer to:
>
> 1. include a distutils-based windows installer for the Zope 2 source
> 2. include some setup scripts
>
> Then on installation
>
> 1. find or install according python

Note that Zope also needs pywin32 to be installed.

> 2. unpack the distutils-based windows installer into Program
>   Files\Zope

OK, so you're trying to preserve that ... what?  You're neither
sticking Python inside Zope nor Zope inside Python?

BTW,  _how_ do you unpack this at install time?  You can't, for
example, assume that a Windows box has any unzip utility (let alone
some specific one).  So this part would probably be simpler if you
point Inno at a Zope tree and let _it_ package it and unpack it. 
Maybe the way to get such a tree is to build a distutils installer for
Zope and run it on your own box, pointing Inno at the tree it creates,
then throw the distutils installer away <0.3 wink>.

> 3. create a default 'instance home', pointing to the installed python

An instance home _certainly_ doesn't belong inside the user's Python
-- but maybe I don't know what you mean by these words (I'm probably
misreading "pointing to").  It should be possible to create any number
of distinct instance homes.

> 4. register the services
>
> Steps 2-4 are reasonably simple to me, the tricky one is 1.

Maybe somone will hit me for this ;-), but we have Inno code for #1 in
one of our other installers.  It goes like this:

[Code]
var
    // Path to the user's Python installation, found from the registry.
    // Procedure SetPythonInstallPath deduces this.
    gPythonInstallPath: String;

function InitializeSetup(): boolean;
begin
    gPythonInstallPath := '';   // don't know yet
    Result := True;
end;

...

// Look up Python's install path in the registry.  Use HKCU first, because
// a "user-only" instance is supposed to take precedence.  If no Python is
// installed, this will leave gPythonInstallPath as an empty string.
procedure SetPythonInstallPath();
begin
    RegQueryStringValue(HKCU,
        'Software\Python\PythonCore\2.4\InstallPath',
         '',
         gPythonInstallPath);
    if gPythonInstallPath = '' then // not in HKCU, so try HKLM
        RegQueryStringValue(HKLM,
            'Software\Python\PythonCore\2.4\InstallPath',
            '',
            gPythonInstallPath);
end;

// Expose gPythonInstallPath to {code:...} clauses.
function GetPythonDir(Default: String): String;
begin
    Result := gPythonInstallPath;
end;

...

procedure SetupDependencies();
var
    PythonSetupFile: String;
    PyWin32SetupFile: String;
...
begin
    PythonSetupFile := 'python-2.4.2.msi';
    PyWin32SetupFile := 'pywin32-205.win32-py2.4.exe';
...
    // Setup python, unless it is already installed.
    SetPythonInstallPath();
    if gPythonInstallPath = '' then begin
        if not ShellExec('open', ExpandConstant('{tmp}\files\' +
PythonSetupFile),
                         '', '', SW_SHOW, ewWaitUntilTerminated, ErrorCode) then
               FatalError('Unable to install python');
        // Try again to find the install path.
        SetPythonInstallPath();
        if gPythonInstallPath = '' then
            // This shouldn't happen ... but if it does, we dare not leave this
            // variable empty:  the installer blithely goes on to copy files
            // into the Windows system32 directory if we do.  That should never
            // be allowed.
            gPythonInstallPath := ExpandConstant('{tmp}\NoPython\');
    end;

    // Setup pywin32
    if not Exec(ExpandConstant('{tmp}\files\' + PyWin32SetupFile), '', '',
                     SW_SHOW, ewWaitUntilTerminated, ErrorCode) then
                FatalError('Unable to install PythonWin32');

...

The key is that the Python installer creates a registry entry, so you
can guess whether Python is installed by looking at that.  Note that
this Inno code doesn't try to do silent installs -- and it always runs
the pywin32 installer.


More information about the Zope-Dev mailing list