thirdparty/google_appengine/google/appengine/tools/dev_appserver_main.py
changeset 109 620f9b141567
child 149 f2e327a7c5de
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thirdparty/google_appengine/google/appengine/tools/dev_appserver_main.py	Tue Aug 26 21:49:54 2008 +0000
@@ -0,0 +1,351 @@
+#!/usr/bin/env python
+#
+# Copyright 2007 Google Inc.
+#
+# 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.
+#
+"""Runs a development application server for an application.
+
+%(script)s [options] <application root>
+
+Application root must be the path to the application to run in this server.
+Must contain a valid app.yaml or app.yml file.
+
+Options:
+  --help, -h                 View this helpful message.
+  --debug, -d                Use debug logging. (Default false)
+  --clear_datastore, -c      Clear the Datastore on startup. (Default false)
+  --address=ADDRESS, -a ADDRESS
+                             Address to which this server should bind. (Default
+                             %(address)s).
+  --port=PORT, -p PORT       Port for the server to run on. (Default %(port)s)
+  --datastore_path=PATH      Path to use for storing Datastore file stub data.
+                             (Default %(datastore_path)s)
+  --history_path=PATH        Path to use for storing Datastore history.
+                             (Default %(history_path)s)
+  --require_indexes          Disallows queries that require composite indexes
+                             not defined in index.yaml.
+  --smtp_host=HOSTNAME       SMTP host to send test mail to.  Leaving this
+                             unset will disable SMTP mail sending.
+                             (Default '%(smtp_host)s')
+  --smtp_port=PORT           SMTP port to send test mail to.
+                             (Default %(smtp_port)s)
+  --smtp_user=USER           SMTP user to connect as.  Stub will only attempt
+                             to login if this field is non-empty.
+                             (Default '%(smtp_user)s').
+  --smtp_password=PASSWORD   Password for SMTP server.
+                             (Default '%(smtp_password)s')
+  --enable_sendmail          Enable sendmail when SMTP not configured.
+                             (Default false)
+  --show_mail_body           Log the body of emails in mail stub.
+                             (Default false)
+  --auth_domain              Authorization domain that this app runs in.
+                             (Default gmail.com)
+  --debug_imports            Enables debug logging for module imports, showing
+                             search paths used for finding modules and any
+                             errors encountered during the import process.
+"""
+
+
+
+import os
+os.environ['TZ'] = 'UTC'
+import time
+if hasattr(time, 'tzset'):
+  time.tzset()
+
+import getopt
+import logging
+import sys
+import traceback
+import tempfile
+
+from google.appengine.api import yaml_errors
+from google.appengine.tools import appcfg
+from google.appengine.tools import dev_appserver
+
+
+DEFAULT_ADMIN_CONSOLE_SERVER = 'appengine.google.com'
+
+ARG_ADDRESS = 'address'
+ARG_ADMIN_CONSOLE_SERVER = 'admin_console_server'
+ARG_ADMIN_CONSOLE_HOST = 'admin_console_host'
+ARG_AUTH_DOMAIN = 'auth_domain'
+ARG_CLEAR_DATASTORE = 'clear_datastore'
+ARG_DATASTORE_PATH = 'datastore_path'
+ARG_DEBUG_IMPORTS = 'debug_imports'
+ARG_ENABLE_SENDMAIL = 'enable_sendmail'
+ARG_SHOW_MAIL_BODY = 'show_mail_body'
+ARG_HISTORY_PATH = 'history_path'
+ARG_LOGIN_URL = 'login_url'
+ARG_LOG_LEVEL = 'log_level'
+ARG_PORT = 'port'
+ARG_REQUIRE_INDEXES = 'require_indexes'
+ARG_SMTP_HOST = 'smtp_host'
+ARG_SMTP_PASSWORD = 'smtp_password'
+ARG_SMTP_PORT = 'smtp_port'
+ARG_SMTP_USER = 'smtp_user'
+ARG_TEMPLATE_DIR = 'template_dir'
+
+
+BASE_PATH = os.path.abspath(
+  os.path.join(os.path.dirname(dev_appserver.__file__), '../../../'))
+
+DEFAULT_ARGS = {
+  ARG_PORT: 8080,
+  ARG_LOG_LEVEL: logging.INFO,
+  ARG_DATASTORE_PATH: os.path.join(tempfile.gettempdir(),
+                                   'dev_appserver.datastore'),
+  ARG_HISTORY_PATH: os.path.join(tempfile.gettempdir(),
+                                 'dev_appserver.datastore.history'),
+  ARG_LOGIN_URL: '/_ah/login',
+  ARG_CLEAR_DATASTORE: False,
+  ARG_REQUIRE_INDEXES: False,
+  ARG_TEMPLATE_DIR: os.path.join(BASE_PATH, 'templates'),
+  ARG_SMTP_HOST: '',
+  ARG_SMTP_PORT: 25,
+  ARG_SMTP_USER: '',
+  ARG_SMTP_PASSWORD: '',
+  ARG_ENABLE_SENDMAIL: False,
+  ARG_SHOW_MAIL_BODY: False,
+  ARG_AUTH_DOMAIN: 'gmail.com',
+  ARG_ADDRESS: 'localhost',
+  ARG_ADMIN_CONSOLE_SERVER: DEFAULT_ADMIN_CONSOLE_SERVER,
+  ARG_ADMIN_CONSOLE_HOST: None,
+}
+
+
+def PrintUsageExit(code):
+  """Prints usage information and exits with a status code.
+
+  Args:
+    code: Status code to pass to sys.exit() after displaying usage information.
+  """
+  render_dict = DEFAULT_ARGS.copy()
+  render_dict['script'] = os.path.basename(sys.argv[0])
+  print sys.modules['__main__'].__doc__ % render_dict
+  sys.stdout.flush()
+  sys.exit(code)
+
+
+def ParseArguments(argv):
+  """Parses command-line arguments.
+
+  Args:
+    argv: Command-line arguments, including the executable name, used to
+      execute this application.
+
+  Returns:
+    Tuple (args, option_dict) where:
+      args: List of command-line arguments following the executable name.
+      option_dict: Dictionary of parsed flags that maps keys from DEFAULT_ARGS
+        to their values, which are either pulled from the defaults, or from
+        command-line flags.
+  """
+  option_dict = DEFAULT_ARGS.copy()
+
+  try:
+    opts, args = getopt.gnu_getopt(
+      argv[1:],
+      'a:cdhp:',
+      [ 'address=',
+        'admin_console_server=',
+        'admin_console_host=',
+        'auth_domain=',
+        'clear_datastore',
+        'datastore_path=',
+        'debug',
+        'debug_imports',
+        'enable_sendmail',
+        'show_mail_body',
+        'help',
+        'history_path=',
+        'port=',
+        'require_indexes',
+        'smtp_host=',
+        'smtp_password=',
+        'smtp_port=',
+        'smtp_user=',
+        'template_dir=',
+      ])
+  except getopt.GetoptError, e:
+    print >>sys.stderr, 'Error: %s' % e
+    PrintUsageExit(1)
+
+  for option, value in opts:
+    if option in ('-h', '--help'):
+      PrintUsageExit(0)
+
+    if option in ('-d', '--debug'):
+      option_dict[ARG_LOG_LEVEL] = logging.DEBUG
+
+    if option in ('-p', '--port'):
+      try:
+        option_dict[ARG_PORT] = int(value)
+        if not (65535 > option_dict[ARG_PORT] > 0):
+          raise ValueError
+      except ValueError:
+        print >>sys.stderr, 'Invalid value supplied for port'
+        PrintUsageExit(1)
+
+    if option in ('-a', '--address'):
+      option_dict[ARG_ADDRESS] = value
+
+    if option == '--datastore_path':
+      option_dict[ARG_DATASTORE_PATH] = value
+
+    if option == '--history_path':
+      option_dict[ARG_HISTORY_PATH] = value
+
+    if option in ('-c', '--clear_datastore'):
+      option_dict[ARG_CLEAR_DATASTORE] = True
+
+    if option == '--require_indexes':
+      option_dict[ARG_REQUIRE_INDEXES] = True
+
+    if option == '--smtp_host':
+      option_dict[ARG_SMTP_HOST] = value
+
+    if option == '--smtp_port':
+      try:
+        option_dict[ARG_SMTP_PORT] = int(value)
+        if not (65535 > option_dict[ARG_SMTP_PORT] > 0):
+          raise ValueError
+      except ValueError:
+        print >>sys.stderr, 'Invalid value supplied for SMTP port'
+        PrintUsageExit(1)
+
+    if option == '--smtp_user':
+      option_dict[ARG_SMTP_USER] = value
+
+    if option == '--smtp_password':
+      option_dict[ARG_SMTP_PASSWORD] = value
+
+    if option == '--enable_sendmail':
+      option_dict[ARG_ENABLE_SENDMAIL] = True
+
+    if option == '--show_mail_body':
+      option_dict[ARG_SHOW_MAIL_BODY] = True
+
+    if option == '--auth_domain':
+      dev_appserver.DEFAULT_ENV['AUTH_DOMAIN'] = value
+
+    if option == '--debug_imports':
+      dev_appserver.HardenedModulesHook.ENABLE_LOGGING = True
+
+    if option == '--template_dir':
+      option_dict[ARG_TEMPLATE_DIR] = value
+
+    if option == '--admin_console_server':
+      option_dict[ARG_ADMIN_CONSOLE_SERVER] = value.strip()
+
+    if option == '--admin_console_host':
+      option_dict[ARG_ADMIN_CONSOLE_HOST] = value
+
+  return args, option_dict
+
+
+def MakeRpcServer(option_dict):
+  """Create a new HttpRpcServer.
+
+  Creates a new HttpRpcServer to check for updates to the SDK.
+
+  Args:
+    option_dict: The dict of command line options.
+
+  Returns:
+    A HttpRpcServer.
+  """
+  server = appcfg.HttpRpcServer(
+      option_dict[ARG_ADMIN_CONSOLE_SERVER],
+      lambda: ('unused_email', 'unused_password'),
+      host_override=option_dict[ARG_ADMIN_CONSOLE_HOST])
+  server.authenticated = True
+  return server
+
+
+def main(argv):
+  """Runs the development application server."""
+  args, option_dict = ParseArguments(argv)
+
+  if len(args) != 1:
+    print >>sys.stderr, 'Invalid arguments'
+    PrintUsageExit(1)
+
+  root_path = args[0]
+  log_level = option_dict[ARG_LOG_LEVEL]
+  port = option_dict[ARG_PORT]
+  datastore_path = option_dict[ARG_DATASTORE_PATH]
+  login_url = option_dict[ARG_LOGIN_URL]
+  template_dir = option_dict[ARG_TEMPLATE_DIR]
+  serve_address = option_dict[ARG_ADDRESS]
+  require_indexes = option_dict[ARG_REQUIRE_INDEXES]
+
+  logging.basicConfig(
+    level=log_level,
+    format='%(levelname)-8s %(asctime)s %(filename)s] %(message)s')
+
+  config = None
+  try:
+    config, matcher = dev_appserver.LoadAppConfig(root_path, {})
+  except yaml_errors.EventListenerError, e:
+    logging.error('Fatal error when loading application configuration:\n' +
+                  str(e))
+    return 1
+  except dev_appserver.InvalidAppConfigError, e:
+    logging.error('Application configuration file invalid:\n%s', e)
+    return 1
+
+  if option_dict[ARG_ADMIN_CONSOLE_SERVER] != '':
+    server = MakeRpcServer(option_dict)
+    update_check = appcfg.UpdateCheck(server, config)
+    update_check.CheckSupportedVersion()
+    if update_check.AllowedToCheckForUpdates():
+      update_check.CheckForUpdates()
+
+  try:
+    dev_appserver.SetupStubs(config.application, **option_dict)
+  except:
+    exc_type, exc_value, exc_traceback = sys.exc_info()
+    logging.error(str(exc_type) + ': ' + str(exc_value))
+    logging.debug(''.join(traceback.format_exception(
+          exc_type, exc_value, exc_traceback)))
+    return 1
+
+  http_server = dev_appserver.CreateServer(root_path,
+                                           login_url,
+                                           port,
+                                           template_dir,
+                                           serve_address=serve_address,
+                                           require_indexes=require_indexes)
+
+  logging.info('Running application %s on port %d: http://%s:%d',
+               config.application, port, serve_address, port)
+  try:
+    try:
+      http_server.serve_forever()
+    except KeyboardInterrupt:
+      logging.info('Server interrupted by user, terminating')
+    except:
+      exc_info = sys.exc_info()
+      info_string = '\n'.join(traceback.format_exception(*exc_info))
+      logging.error('Error encountered:\n%s\nNow terminating.', info_string)
+      return 1
+  finally:
+    http_server.server_close()
+
+  return 0
+
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))