Ejemplo n.º 1
0
            def _create_api_server(self, request_data, storage_path, options,
                                   configuration):
                # sandbox._create_dispatcher returns a singleton dispatcher instance made in sandbox
                self._dispatcher = sandbox._create_dispatcher(
                    configuration, options)
                # the dispatcher may have passed environment variables, it should be propagated
                env_vars = self._dispatcher._configuration.modules[
                    0]._app_info_external.env_variables or EnvironmentVariables(
                    )
                for module in configuration.modules:
                    module_name = module._module_name
                    if module_name == 'default' or module_name is None:
                        module_settings = 'DJANGO_SETTINGS_MODULE'
                    else:
                        module_settings = '%s_DJANGO_SETTINGS_MODULE' % module_name
                    if module_settings in env_vars:
                        module_env_vars = module.env_variables or EnvironmentVariables(
                        )
                        module_env_vars['DJANGO_SETTINGS_MODULE'] = env_vars[
                            module_settings]

                        old_env_vars = module._app_info_external.env_variables
                        new_env_vars = EnvironmentVariables.Merge(
                            module_env_vars, old_env_vars)
                        module._app_info_external.env_variables = new_env_vars
                self._dispatcher._configuration = configuration
                self._dispatcher._port = options.port
                self._dispatcher._host = options.host

                # Because the dispatcher is a singleton, we need to set the threadsafe override here
                # depending on what was passed to the runserver command. This entire file really needs rebuilding
                # we have way too many hacks in here!
                self._dispatcher._module_to_threadsafe_override[
                    configuration.modules[0].
                    module_name] = options.threadsafe_override

                self._dispatcher.request_data = request_data
                request_data._dispatcher = self._dispatcher

                sandbox._API_SERVER._host = options.api_host
                sandbox._API_SERVER.bind_addr = (options.api_host,
                                                 options.api_port)

                from google.appengine.api import apiproxy_stub_map
                task_queue = apiproxy_stub_map.apiproxy.GetStub('taskqueue')
                # Make sure task running is enabled (it's disabled in the sandbox by default)
                if not task_queue._auto_task_running:
                    task_queue._auto_task_running = True
                    task_queue.StartBackgroundExecution()

                return sandbox._API_SERVER
Ejemplo n.º 2
0
def activate(sandbox_name, add_sdk_to_path=False, new_env_vars=None, **overrides):
    """Context manager for command-line scripts started outside of dev_appserver.

    :param sandbox_name: str, one of 'local', 'remote' or 'test'
    :param add_sdk_to_path: bool, optionally adds the App Engine SDK to sys.path
    :param options_override: an options structure to pass down to dev_appserver setup

    Available sandboxes:

      local: Adds libraries specified in app.yaml to the path and initializes local service stubs as though
             dev_appserver were running.

      remote: Adds libraries specified in app.yaml to the path and initializes remote service stubs.

      test: Adds libraries specified in app.yaml to the path and sets up no service stubs. Use this
            with `google.appengine.ext.testbed` to provide isolation for tests.

    Example usage:

        import djangae.sandbox as sandbox

        with sandbox.activate('local'):
            from django.core.management import execute_from_command_line
            execute_from_command_line(sys.argv)

    """
    if sandbox_name not in SANDBOXES:
        raise RuntimeError('Unknown sandbox "{}"'.format(sandbox_name))

    project_root = environment.get_application_root()

   # Store our original sys.path before we do anything, this must be tacked
    # onto the end of the other paths so we can access globally installed things (e.g. ipdb etc.)
    original_path = sys.path[:]

    # Setup paths as though we were running dev_appserver. This is similar to
    # what the App Engine script wrappers do.
    if add_sdk_to_path:
        try:
            import wrapper_util  # Already on sys.path
        except ImportError:
            sys.path[0:0] = [_find_sdk_from_path()]
            import wrapper_util
    else:
        try:
            import wrapper_util
        except ImportError:
            raise RuntimeError("Couldn't find a recent enough Google App Engine SDK, make sure you are using at least 1.9.6")

    sdk_path = _find_sdk_from_python_path()
    _PATHS = wrapper_util.Paths(sdk_path)

    project_paths = [] # Paths under the application root
    system_paths = [] # All other paths
    app_root = environment.get_application_root()

    # We need to look at the original path, and make sure that any paths
    # which are under the project root are first, then any other paths
    # are added after the SDK ones
    for path in _PATHS.scrub_path(_SCRIPT_NAME, original_path):
        if commonprefix([app_root, path]) == app_root:
            project_paths.append(path)
        else:
            system_paths.append(path)

    # We build a list of SDK paths, and add any additional ones required for
    # the oauth client
    appengine_paths = _PATHS.script_paths(_SCRIPT_NAME)
    for path in _PATHS.oauth_client_extra_paths:
        if path not in appengine_paths:
            appengine_paths.append(path)

    # Now, we make sure that paths within the project take precedence, followed
    # by the SDK, then finally any paths from the system Python (for stuff like
    # ipdb etc.)
    sys.path = (
        project_paths +
        appengine_paths +
        system_paths
    )

    # Gotta set the runtime properly otherwise it changes appengine imports, like wepapp
    # when you are not running dev_appserver
    import yaml
    with open(os.path.join(project_root, 'app.yaml'), 'r') as app_yaml:
        app_yaml = yaml.load(app_yaml)
        os.environ['APPENGINE_RUNTIME'] = app_yaml.get('runtime', '')

    # Initialize as though `dev_appserver.py` is about to run our app, using all the
    # configuration provided in app.yaml.
    import google.appengine.tools.devappserver2.application_configuration as application_configuration
    import google.appengine.tools.devappserver2.python.sandbox as sandbox
    import google.appengine.tools.devappserver2.devappserver2 as devappserver2
    import google.appengine.tools.devappserver2.wsgi_request_info as wsgi_request_info
    import google.appengine.ext.remote_api.remote_api_stub as remote_api_stub
    import google.appengine.api.apiproxy_stub_map as apiproxy_stub_map

    gae_args = [
        s for s in sys.argv
        if any(s.lstrip('--').startswith(gae_option) for gae_option in WHITELISTED_DEV_APPSERVER_OPTIONS)
    ]

    # The argparser is the easiest way to get the default options.
    options = devappserver2.PARSER.parse_args([project_root] + gae_args)
    options.enable_task_running = False # Disable task running by default, it won't work without a running server
    options.skip_sdk_update_check = True

    for option in overrides:
        if not hasattr(options, option):
            raise ValueError("Unrecognized sandbox option: {}".format(option))

        setattr(options, option, overrides[option])

    configuration = application_configuration.ApplicationConfiguration(options.config_paths, app_id=options.app_id)

    # Enable built-in libraries from app.yaml without enabling the full sandbox.
    module = configuration.modules[0]
    for l in sandbox._enable_libraries(module.normalized_libraries):
        sys.path.insert(1, l)

    # Propagate provided environment variables to the sandbox.
    # This is required for the runserver management command settings flag,
    # which sets an environment variable needed by Django.
    from google.appengine.api.appinfo import EnvironmentVariables
    old_env_vars = module.env_variables if module.env_variables else {}
    if new_env_vars is None:
        new_env_vars = {}
    module._app_info_external.env_variables = EnvironmentVariables.Merge(
        old_env_vars,
        new_env_vars,
    )

    try:
        global _OPTIONS
        global _CONFIG
        _CONFIG = configuration
        _OPTIONS = options # Store the options globally so they can be accessed later
        kwargs = dict(
            devappserver2=devappserver2,
            configuration=configuration,
            options=options,
            wsgi_request_info=wsgi_request_info,
            remote_api_stub=remote_api_stub,
            apiproxy_stub_map=apiproxy_stub_map,
        )
        with SANDBOXES[sandbox_name](**kwargs):
            yield

    finally:
        sys.path = original_path
Ejemplo n.º 3
0
            def _set_dispatcher(self, dispatcher):
                """
                    Ignore explicit setting of _dispatcher, use our own
                """

                if dispatcher is None:
                    # Allow wiping the patched dispatcher
                    self._patched_dispatcher = None
                    return

                if self._patched_dispatcher:
                    # We already created the dispatcher, ignore further sets
                    logging.warning("Attempted to set _dispatcher twice")
                    return


                # When the dispatcher is created this property is set so we use it
                # to construct *our* dispatcher
                configuration = dispatcher._configuration

                # We store options in .start() so it's available here
                options = self.options

                # sandbox._create_dispatcher returns a singleton dispatcher instance made in sandbox
                self._patched_dispatcher = sandbox._create_dispatcher(
                    configuration,
                    options
                )

                # the dispatcher may have passed environment variables, it should be propagated
                env_vars = self._dispatcher._configuration.modules[0]._app_info_external.env_variables or EnvironmentVariables()
                for module in configuration.modules:
                    module_name = module._module_name
                    if module_name == 'default' or module_name is None:
                        module_settings = 'DJANGO_SETTINGS_MODULE'
                    else:
                        module_settings = '%s_DJANGO_SETTINGS_MODULE' % module_name
                    if module_settings in env_vars:
                        module_env_vars = module.env_variables or EnvironmentVariables()
                        module_env_vars['DJANGO_SETTINGS_MODULE'] = env_vars[module_settings]

                        old_env_vars = module._app_info_external.env_variables
                        new_env_vars = EnvironmentVariables.Merge(module_env_vars, old_env_vars)
                        module._app_info_external.env_variables = new_env_vars
                self._dispatcher._configuration = configuration
                self._dispatcher._port = options.port
                self._dispatcher._host = options.host

                # Because the dispatcher is a singleton, we need to set the threadsafe override here
                # depending on what was passed to the runserver command. This entire file really needs rebuilding
                # we have way too many hacks in here!
                self._dispatcher._module_to_threadsafe_override[
                    configuration.modules[0].module_name
                ] = options.threadsafe_override

#                self._dispatcher.request_data = request_data
#                request_data._dispatcher = self._dispatcher

                sandbox._API_SERVER._host = options.api_host
                sandbox._API_SERVER.bind_addr = (options.api_host, options.api_port)

                from google.appengine.api import apiproxy_stub_map
                task_queue = apiproxy_stub_map.apiproxy.GetStub('taskqueue')
                # Make sure task running is enabled (it's disabled in the sandbox by default)
                if not task_queue._auto_task_running:
                    task_queue._auto_task_running = True
                    task_queue.StartBackgroundExecution()