# 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
# 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.
# (I choose the Apache License, because the Python Software Foundation
# requires this license for contributions. See http://www.python.org/psf/contrib/)
Installer for Stackless Python
This distribution helps you to install `Stackless Python <http://www.stackless.com>`_.
Because Stackless Python is a variant of the CPython interpreter,
it can't be installed as a `Python Egg <http://peak.telecommunity.com/DevCenter/PythonEggs>`_.
Fortunately this does not mean that there is no way to install Stackless Python using
commonly used installation methods like
`distribute <http://http://pythonhosted.org/distribute/index.html>`_ or
`pip <http://www.pip-installer.org>`_. It is just a bit involved.
The installation of Stackless Python is a two step
1. Install *stackless-python* (this distribution). It is a very
lightweight "umbrella"-installer and mostly selects
the appropriate "stackless_installer" distribution for the next step.
2. Install a "stackless_installer" distribution
that contains Stackless Python compiled for the current platform.
How does it work in detail?
Usually Python Eggs declare their requirements statically within their egg-info
directory. This helps tools like easy_install and pip to manage dependencies.
Unfortunately the *stackless-python* distribution must compute the requirement
during installation and therefore can't declare the dependency in advance.
Fortunately packaging *stackless-python* as a sdist using the ancient :mod:`distutils` instead
of :mod:`setuptools` helps, because distutils does not create the egg-info structure at
all. During installation, if easy_install or pip encounter such a sdist, they
execute ``setup.py egg-info`` to compute the egg info dynamically.
The *stackless-python* setup.py checks if the current python is suitable
for a Stackless installation and computes the name of the "stackless_installer"
distribution. The name depends on the current platform, the Python version
and on the unicode character size (UCS2 or UCS4). See function :func:`get_stackless_package`
Usually easy_install or pip first install a distribution and then install the requirements
of the distribution. This is fine for run-time requirements. In our case we need the requiremnet
during installation and declare a so called *setup-requirement*. This kind of requirement
gets installed during the installation of a Python-Egg only.
Over time we will need several different "stackless_installer" distributions. One for each
release of Stackless and supported platform. To keep control about the naming of these
distributions and to avoid namespace clutter on PyPi, *stackless-python* uses
a dependency link to download the stackless_installer distributions direct from
a web server.
How to build stackless-python sdist
Run ``python -S setup.py check sdist``. The flag ``-S`` is important, because
it disables :mod:`setuptools` and enforces the fall back to :mod:`distutils`.
from __future__ import absolute_import
from setuptools import setup
from setuptools.command.install_lib import install_lib
from distutils.core import setup
from distutils.command.install_lib import install_lib
from distutils import log
from stackless_python_umbrella import INSTALLER_VERSION, get_dependency_links, get_stackless_package
installerVersionStr = ".".join(map(str,INSTALLER_VERSION))
# the installation of the module stackless_python_umbrella ensures, that
# the install_lib command runs during the installation of this distribution
result = install_lib.run(self)
if not self.dry_run:
dist = get_stackless_package()
from distutils import spawn
cmd = [sys.executable,
"""import sys;from pkg_resources import load_entry_point;sys.exit(load_entry_point('%s', 'console_scripts', 'install-stackless')())""" % dist
spawn.spawn(cmd, search_path=0, verbose=self.verbose, dry_run=self.dry_run)
log.info("Installed Stackless Python")
# various variables for setup(...)
setup_requires = 
dependency_links = 
installer, reqVersion = get_stackless_package()
if installer is not None:
cmdclass['install_lib'] = InstallWithScript
description='Installer for Stackless Python',
setup_requires = setup_requires,
#install_requires = setup_requires, # uncomment to install the installer permanently
requires = , # no requirements
dependency_links = dependency_links,
py_modules = ['stackless_python_umbrella'],
"License :: OSI Approved :: Apache Software License", # for this umbrella installer
"Programming Language :: Python",
"Programming Language :: Python :: Implementation :: Stackless",
"Operating System :: Microsoft :: Windows",
"Operating System :: POSIX :: Linux",
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"Topic :: Software Development :: Interpreters",
license='Apache License, Version 2.0',