1. Waldemar Kornewald
  2. djangoappengine


djangoappengine / boot.py

import logging
import os
import sys

PROJECT_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
DATA_ROOT = os.path.join(PROJECT_DIR, '.gaedata')

# Overrides for os.environ
env_ext = {'DJANGO_SETTINGS_MODULE': 'settings'}

def setup_env():
    """Configures app engine environment for command-line apps."""
    # Try to import the appengine code from the system path.
        from google.appengine.api import apiproxy_stub_map
    except ImportError:
        for k in [k for k in sys.modules if k.startswith('google')]:
            del sys.modules[k]

        # Not on the system path. Build a list of alternative paths where it
        # may be. First look within the project for a local copy, then look for
        # where the Mac OS SDK installs it.
        paths = [os.path.join(PROJECT_DIR, '.google_appengine'),
        for path in os.environ.get('PATH', '').split(os.pathsep):
            path = path.rstrip(os.sep)
            if path.endswith('google_appengine'):
        if os.name in ('nt', 'dos'):
            path = r'%(PROGRAMFILES)s\Google\google_appengine' % os.environ
        # Loop through all possible paths and look for the SDK dir.
        sdk_path = None
        for path in paths:
            if not path:
            path = os.path.expanduser(path)
            path = os.path.realpath(path)
            if os.path.exists(path):
                sdk_path = path
        if sdk_path is None:
            # The SDK could not be found in any known location.
            sys.stderr.write('The Google App Engine SDK could not be found!\n'
                             "Make sure it's accessible via your PATH "
                             "environment and called google_appengine.\n")
        # Add the SDK and the libraries within it to the system path.
        extra_paths = [sdk_path]
        lib = os.path.join(sdk_path, 'lib')
        # Automatically add all packages in the SDK's lib folder:
        for name in os.listdir(lib):
            root = os.path.join(lib, name)
            subdir = name
            # Package can be under 'lib/<pkg>/<pkg>/' or 'lib/<pkg>/lib/<pkg>/'
            detect = (os.path.join(root, subdir), os.path.join(root, 'lib', subdir))
            for path in detect:
                if os.path.isdir(path):
                if name == 'webapp2':
        sys.path = extra_paths + sys.path
        from google.appengine.api import apiproxy_stub_map

    from .utils import have_appserver
    if have_appserver:
        # App Engine's threading.local is broken
    elif not os.path.exists(DATA_ROOT):

    if not have_appserver:
        # Patch Django to support loading management commands from zip files
        from django.core import management
        management.find_commands = find_commands

def find_commands(management_dir):
    Given a path to a management directory, returns a list of all the command
    names that are available.
    This version works for django deployments which are file based or
    contained in a ZIP (in sys.path).

    Returns an empty list if no commands are defined.
    import pkgutil
    return [modname for importer, modname, ispkg in pkgutil.iter_modules(
                [os.path.join(management_dir, 'commands')]) if not ispkg]

def setup_threading():
    if sys.version_info >= (2, 7):
    # XXX: On Python 2.5 GAE's threading.local doesn't work correctly with subclassing
        from django.utils._threading_local import local
        import threading
        threading.local = local
    except ImportError:

def setup_logging():
    # Fix Python 2.6 logging module
    logging.logMultiprocessing = 0

    # Enable logging
    level = logging.DEBUG
    from .utils import have_appserver
    if have_appserver:
        # We can't import settings at this point when running a normal
        # manage.py command because this module gets imported from settings.py
        from django.conf import settings
        if not settings.DEBUG:
            level = logging.INFO

def setup_project():
    from .utils import have_appserver, on_production_server
    if have_appserver:
        # This fixes a pwd import bug for os.path.expanduser()
        env_ext['HOME'] = PROJECT_DIR

    # The dev_appserver creates a sandbox which restricts access to certain
    # modules and builtins in order to emulate the production environment.
    # Here we get the subprocess module back into the dev_appserver sandbox.
    # This module is just too important for development.
    # Also we add the compiler/parser module back and enable https connections
    # (seem to be broken on Windows because the _ssl module is disallowed).
    if not have_appserver:
        from google.appengine.tools import dev_appserver
            # Backup os.environ. It gets overwritten by the dev_appserver,
            # but it's needed by the subprocess module.
            env = dev_appserver.DEFAULT_ENV
            dev_appserver.DEFAULT_ENV = os.environ.copy()
            # Backup the buffer() builtin. The subprocess in Python 2.5 on
            # Linux and OS X uses needs it, but the dev_appserver removes it.
            dev_appserver.buffer = buffer
        except AttributeError:
            logging.warn('Could not patch the default environment. '
                         'The subprocess module will not work correctly.')

            # Allow importing compiler/parser, _ssl (for https),
            # _io for Python 2.7 io support on OS X
                ('parser', '_ssl', '_io'))
        except AttributeError:
            logging.warn('Could not patch modules whitelist. '
                         'The compiler and parser modules will not work and '
                         'SSL support is disabled.')
    elif not on_production_server:
            # Restore the real subprocess module
            from google.appengine.api.mail_stub import subprocess
            sys.modules['subprocess'] = subprocess
            # Re-inject the buffer() builtin into the subprocess module
            from google.appengine.tools import dev_appserver
            subprocess.buffer = dev_appserver.buffer
        except Exception, e:
            logging.warn('Could not add the subprocess module to the sandbox: %s' % e)


    extra_paths = [PROJECT_DIR, os.path.join(os.path.dirname(__file__), 'lib')]
    zip_packages_dir = os.path.join(PROJECT_DIR, 'zip-packages')

    # We support zipped packages in the common and project folders.
    if os.path.isdir(zip_packages_dir):
        for zip_package in os.listdir(zip_packages_dir):
            extra_paths.append(os.path.join(zip_packages_dir, zip_package))

    # App Engine causes main.py to be reloaded if an exception gets raised
    # on the first request of a main.py instance, so don't call setup_project()
    # multiple times. We ensure this indirectly by checking if we've already
    # modified sys.path, already.
    if len(sys.path) < len(extra_paths) or \
            sys.path[:len(extra_paths)] != extra_paths:
        for path in extra_paths:
            while path in sys.path:
        sys.path = extra_paths + sys.path