Source

slp-installer / C2_win32 / slpInstaller / __init__.py

Full commit
#
# Copyright 2013 Anselm Kruis
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.

"""
Installer for Stackless Python (Windows)

This distribution adds Stackless Python executables to an existing
CPython installation.
"""

from __future__ import absolute_import

import argparse
import sysconfig
import sys
import atexit
from zipfile import PyZipFile
from os.path import join, normpath, dirname, basename, abspath, isdir
from os import remove as os_remove, listdir
import fnmatch
from distutils.file_util import copy_file
from distutils.dir_util import copy_tree, mkpath, remove_tree
from distutils.util import get_platform, byte_compile
from distutils import log
from pkg_resources import (resource_filename, cleanup_resources)

# we need the correct lib directory. The os module works fine
from os import __file__ as os__file__

UCS=2
PLATFORM="win32"
STACKLESS_VERSION = (2,7,4)
INSTALLER_VERSION = (0,1)

INSTALLER_VERSION_STR = ".".join(map(str,STACKLESS_VERSION + INSTALLER_VERSION))

        
def build_pylib_win32(src, zipName, stdArgs):
    log.info("creating library archive %s", zipName)
    if not stdArgs['dry_run']:
        try:
            os_remove(zipName)
        except OSError:
            pass
        # print >> sys.stderr, "Failed to remove %s: %s" % (zipName, e)
        with PyZipFile(zipName, 'w') as myzip:
            myzip.debug = stdArgs['verbose'] >= 2
            myzip.writepy(src)
            for d in listdir(src):
                d=join(src,d)
                if isdir(d):
                    myzip.writepy(d)

def remove_file(path, verbose=1, dry_run=0):
    if verbose >= 1:
        log.info("removing '%s'", path)
    if not dry_run:
        os_remove(path)


def main(args, default="install"):
    
    parser = argparse.ArgumentParser(description='Install or uninstall stackless python')
    parser.add_argument('--verbose', '-v', dest='verbose', action='append_const', const=True, help="run verbosely (default)")
    parser.add_argument('--quiet', '-q', dest='verbose', action='store_const', const=[], default=argparse.SUPPRESS, help="run quietly (turns verbosity off)")
    parser.add_argument('--dry-run', '-n', dest='dry_run', action='store_true', help="don't actually do anything")
    parser.add_argument('command', choices=['install', 'uninstall'], action='store', nargs='?', default=default)
    
    parsed = parser.parse_args(args=args)
    parsed.verbose = 1 if parsed.verbose is None else len(parsed.verbose)
    log.set_verbosity(parsed.verbose)
    
    if get_platform() != PLATFORM:
        raise RuntimeError("This package is for %s only. It does not work on %s" % (PLATFORM, get_platform()))
    currentUcs = 4 if sys.maxunicode >> 16 else 2
    if currentUcs != UCS:
        raise RuntimeError("This package requires ucs%d but your Python interpreter provides ucs%d" % (UCS, currentUcs))

    # standard arguments of various functions from distutils    
    stdArgs = dict(verbose=parsed.verbose, dry_run=parsed.dry_run)
    
    arch = PLATFORM
    assembly="com.stackless.python%s%s" % STACKLESS_VERSION[:2]
    slPythonNames = ('slpython.exe', 'slpythonw.exe')
    pybindest = dirname(abspath(sys.executable))
    zipName=join(pybindest, assembly, "python%s%s.zip" % STACKLESS_VERSION[:2])

    if parsed.command == 'install':
        # get the binary resources
        atexit.register(cleanup_resources)
        src = resource_filename(__name__, arch)
        # copy the files
        copy_tree(src, pybindest, **stdArgs)
                
        # create the library zip archive
        src = resource_filename(__name__, 'Lib')
        build_pylib_win32(src, zipName, stdArgs)
        
    elif parsed.command == 'uninstall':
        # remove the executable and the shared library
        for f in slPythonNames:
            remove_file(join(pybindest, f), **stdArgs)
        remove_tree(join(pybindest, assembly), **stdArgs)
        
    else:
        raise ValueError("Unsupported command: " + parsed.command)


def main_install():
    return main(args=sys.argv[1:], default='install')
def main_uninstall():
    return main(args=sys.argv[1:], default='uninstall')

if __name__ == '__main__':
    sys.exit(main(args=sys.argv[1:]))