thirdparty/google_appengine/google/appengine/tools/dev_appserver_main.py
changeset 1278 a7766286a7be
parent 828 f5fd65cc3bf3
child 2172 ac7bd3b467ff
equal deleted inserted replaced
1277:5c931bd3dc1e 1278:a7766286a7be
    63 from google.appengine.tools import os_compat
    63 from google.appengine.tools import os_compat
    64 
    64 
    65 import getopt
    65 import getopt
    66 import logging
    66 import logging
    67 import os
    67 import os
       
    68 import re
    68 import sys
    69 import sys
    69 import traceback
    70 import traceback
    70 import tempfile
    71 import tempfile
    71 
    72 
    72 from google.appengine.api import yaml_errors
    73 
    73 from google.appengine.tools import appcfg
    74 def SetGlobals():
    74 from google.appengine.tools import appengine_rpc
    75   """Set various global variables involving the 'google' package.
    75 from google.appengine.tools import dev_appserver
    76 
       
    77   This function should not be called until sys.path has been properly set.
       
    78   """
       
    79   global yaml_errors, appcfg, appengine_rpc, dev_appserver, os_compat
       
    80   from google.appengine.api import yaml_errors
       
    81   from google.appengine.tools import appcfg
       
    82   from google.appengine.tools import appengine_rpc
       
    83   from google.appengine.tools import dev_appserver
       
    84   from google.appengine.tools import os_compat
       
    85 
    76 
    86 
    77 
    87 
    78 DEFAULT_ADMIN_CONSOLE_SERVER = 'appengine.google.com'
    88 DEFAULT_ADMIN_CONSOLE_SERVER = 'appengine.google.com'
    79 
    89 
    80 ARG_ADDRESS = 'address'
    90 ARG_ADDRESS = 'address'
    96 ARG_SMTP_PORT = 'smtp_port'
   106 ARG_SMTP_PORT = 'smtp_port'
    97 ARG_SMTP_USER = 'smtp_user'
   107 ARG_SMTP_USER = 'smtp_user'
    98 ARG_STATIC_CACHING = 'static_caching'
   108 ARG_STATIC_CACHING = 'static_caching'
    99 ARG_TEMPLATE_DIR = 'template_dir'
   109 ARG_TEMPLATE_DIR = 'template_dir'
   100 
   110 
   101 
   111 SDK_PATH = os.path.dirname(
   102 BASE_PATH = os.path.abspath(
   112              os.path.dirname(
   103   os.path.join(os.path.dirname(dev_appserver.__file__), '../../../'))
   113                os.path.dirname(
       
   114                  os.path.dirname(os_compat.__file__)
       
   115                )
       
   116              )
       
   117            )
   104 
   118 
   105 DEFAULT_ARGS = {
   119 DEFAULT_ARGS = {
   106   ARG_PORT: 8080,
   120   ARG_PORT: 8080,
   107   ARG_LOG_LEVEL: logging.INFO,
   121   ARG_LOG_LEVEL: logging.INFO,
   108   ARG_DATASTORE_PATH: os.path.join(tempfile.gettempdir(),
   122   ARG_DATASTORE_PATH: os.path.join(tempfile.gettempdir(),
   110   ARG_HISTORY_PATH: os.path.join(tempfile.gettempdir(),
   124   ARG_HISTORY_PATH: os.path.join(tempfile.gettempdir(),
   111                                  'dev_appserver.datastore.history'),
   125                                  'dev_appserver.datastore.history'),
   112   ARG_LOGIN_URL: '/_ah/login',
   126   ARG_LOGIN_URL: '/_ah/login',
   113   ARG_CLEAR_DATASTORE: False,
   127   ARG_CLEAR_DATASTORE: False,
   114   ARG_REQUIRE_INDEXES: False,
   128   ARG_REQUIRE_INDEXES: False,
   115   ARG_TEMPLATE_DIR: os.path.join(BASE_PATH, 'templates'),
   129   ARG_TEMPLATE_DIR: os.path.join(SDK_PATH, 'templates'),
   116   ARG_SMTP_HOST: '',
   130   ARG_SMTP_HOST: '',
   117   ARG_SMTP_PORT: 25,
   131   ARG_SMTP_PORT: 25,
   118   ARG_SMTP_USER: '',
   132   ARG_SMTP_USER: '',
   119   ARG_SMTP_PASSWORD: '',
   133   ARG_SMTP_PASSWORD: '',
   120   ARG_ENABLE_SENDMAIL: False,
   134   ARG_ENABLE_SENDMAIL: False,
   123   ARG_ADDRESS: 'localhost',
   137   ARG_ADDRESS: 'localhost',
   124   ARG_ADMIN_CONSOLE_SERVER: DEFAULT_ADMIN_CONSOLE_SERVER,
   138   ARG_ADMIN_CONSOLE_SERVER: DEFAULT_ADMIN_CONSOLE_SERVER,
   125   ARG_ADMIN_CONSOLE_HOST: None,
   139   ARG_ADMIN_CONSOLE_HOST: None,
   126   ARG_STATIC_CACHING: True,
   140   ARG_STATIC_CACHING: True,
   127 }
   141 }
       
   142 
       
   143 API_PATHS = {'1':
       
   144              {'google': (),
       
   145               'antlr3': ('lib', 'antlr3'),
       
   146               'django': ('lib', 'django'),
       
   147               'webob': ('lib', 'webob'),
       
   148               'yaml': ('lib', 'yaml', 'lib'),
       
   149               }
       
   150              }
       
   151 
       
   152 DEFAULT_API_VERSION = '1'
       
   153 
       
   154 API_PATHS['test'] = API_PATHS[DEFAULT_API_VERSION].copy()
       
   155 API_PATHS['test']['_test'] = ('nonexistent', 'test', 'path')
       
   156 
       
   157 
       
   158 def SetPaths(app_config_path):
       
   159   """Set the interpreter to use the specified API version.
       
   160 
       
   161   The app.yaml file is scanned for the api_version field and the value is
       
   162   extracted. With that information, the paths in API_PATHS are added to the
       
   163   front of sys.paths to make sure that they take precedent over any other paths
       
   164   to older versions of a package. All modules for each package set are cleared
       
   165   out of sys.modules to make sure only the newest version is used.
       
   166 
       
   167   Args:
       
   168     - app_config_path: Path to the app.yaml file.
       
   169   """
       
   170   api_version_re = re.compile(r'api_version:\s*(?P<api_version>[\w.]{1,32})')
       
   171   api_version = None
       
   172   app_config_file = open(app_config_path, 'r')
       
   173   try:
       
   174     for line in app_config_file:
       
   175       re_match = api_version_re.match(line)
       
   176       if re_match:
       
   177         api_version = re_match.group('api_version')
       
   178         break
       
   179   finally:
       
   180     app_config_file.close()
       
   181 
       
   182   if api_version is None:
       
   183     logging.error("Application configuration file missing an 'api_version' "
       
   184                   "value:\n%s" % app_config_path)
       
   185     sys.exit(1)
       
   186   if api_version not in API_PATHS:
       
   187     logging.error("Value of %r for 'api_version' from the application "
       
   188                   "configuration file is not valid:\n%s" %
       
   189                     (api_version, app_config_path))
       
   190     sys.exit(1)
       
   191 
       
   192   if api_version == DEFAULT_API_VERSION:
       
   193     return DEFAULT_API_VERSION
       
   194 
       
   195   sdk_path = os.path.dirname(
       
   196       os.path.dirname(
       
   197         os.path.dirname(
       
   198           os.path.dirname(os_compat.__file__)
       
   199           )
       
   200         )
       
   201       )
       
   202   for pkg_name, path_parts in API_PATHS[api_version].iteritems():
       
   203     for name in sys.modules.keys():
       
   204       if name == pkg_name or name.startswith('%s.' % pkg_name):
       
   205         del sys.modules[name]
       
   206     pkg_path = os.path.join(sdk_path, *path_parts)
       
   207     sys.path.insert(0, pkg_path)
       
   208 
       
   209   return api_version
   128 
   210 
   129 
   211 
   130 def PrintUsageExit(code):
   212 def PrintUsageExit(code):
   131   """Prints usage information and exits with a status code.
   213   """Prints usage information and exits with a status code.
   132 
   214 
   203 
   285 
   204     if option in ('-a', '--address'):
   286     if option in ('-a', '--address'):
   205       option_dict[ARG_ADDRESS] = value
   287       option_dict[ARG_ADDRESS] = value
   206 
   288 
   207     if option == '--datastore_path':
   289     if option == '--datastore_path':
   208       option_dict[ARG_DATASTORE_PATH] = value
   290       option_dict[ARG_DATASTORE_PATH] = os.path.abspath(value)
   209 
   291 
   210     if option == '--history_path':
   292     if option == '--history_path':
   211       option_dict[ARG_HISTORY_PATH] = value
   293       option_dict[ARG_HISTORY_PATH] = os.path.abspath(value)
   212 
   294 
   213     if option in ('-c', '--clear_datastore'):
   295     if option in ('-c', '--clear_datastore'):
   214       option_dict[ARG_CLEAR_DATASTORE] = True
   296       option_dict[ARG_CLEAR_DATASTORE] = True
   215 
   297 
   216     if option == '--require_indexes':
   298     if option == '--require_indexes':
   239 
   321 
   240     if option == '--show_mail_body':
   322     if option == '--show_mail_body':
   241       option_dict[ARG_SHOW_MAIL_BODY] = True
   323       option_dict[ARG_SHOW_MAIL_BODY] = True
   242 
   324 
   243     if option == '--auth_domain':
   325     if option == '--auth_domain':
   244       dev_appserver.DEFAULT_ENV['AUTH_DOMAIN'] = value
   326       option_dict['_DEFAULT_ENV_AUTH_DOMAIN'] = value
   245 
   327 
   246     if option == '--debug_imports':
   328     if option == '--debug_imports':
   247       dev_appserver.HardenedModulesHook.ENABLE_LOGGING = True
   329       option_dict['_ENABLE_LOGGING'] = True
   248 
   330 
   249     if option == '--template_dir':
   331     if option == '--template_dir':
   250       option_dict[ARG_TEMPLATE_DIR] = value
   332       option_dict[ARG_TEMPLATE_DIR] = value
   251 
   333 
   252     if option == '--admin_console_server':
   334     if option == '--admin_console_server':
   289   if len(args) != 1:
   371   if len(args) != 1:
   290     print >>sys.stderr, 'Invalid arguments'
   372     print >>sys.stderr, 'Invalid arguments'
   291     PrintUsageExit(1)
   373     PrintUsageExit(1)
   292 
   374 
   293   root_path = args[0]
   375   root_path = args[0]
       
   376   for suffix in ('yaml', 'yml'):
       
   377     path = os.path.join(root_path, 'app.%s' % suffix)
       
   378     if os.path.exists(path):
       
   379       api_version = SetPaths(path)
       
   380       break
       
   381   else:
       
   382     logging.error("Application configuration file not found in %s" % root_path)
       
   383     return 1
       
   384 
       
   385   SetGlobals()
       
   386   dev_appserver.API_VERSION = api_version
       
   387 
       
   388   if '_DEFAULT_ENV_AUTH_DOMAIN' in option_dict:
       
   389     auth_domain = option_dict['_DEFAULT_ENV_AUTH_DOMAIN']
       
   390     dev_appserver.DEFAULT_ENV['AUTH_DOMAIN'] = auth_domain
       
   391   if '_ENABLE_LOGGING' in option_dict:
       
   392     enable_logging = option_dict['_ENABLE_LOGGING']
       
   393     dev_appserver.HardenedModulesHook.ENABLE_LOGGING = enable_logging
       
   394 
   294   log_level = option_dict[ARG_LOG_LEVEL]
   395   log_level = option_dict[ARG_LOG_LEVEL]
   295   port = option_dict[ARG_PORT]
   396   port = option_dict[ARG_PORT]
   296   datastore_path = option_dict[ARG_DATASTORE_PATH]
   397   datastore_path = option_dict[ARG_DATASTORE_PATH]
   297   login_url = option_dict[ARG_LOGIN_URL]
   398   login_url = option_dict[ARG_LOGIN_URL]
   298   template_dir = option_dict[ARG_TEMPLATE_DIR]
   399   template_dir = option_dict[ARG_TEMPLATE_DIR]
   333 
   434 
   334   http_server = dev_appserver.CreateServer(root_path,
   435   http_server = dev_appserver.CreateServer(root_path,
   335                                            login_url,
   436                                            login_url,
   336                                            port,
   437                                            port,
   337                                            template_dir,
   438                                            template_dir,
       
   439                                            sdk_dir=SDK_PATH,
   338                                            serve_address=serve_address,
   440                                            serve_address=serve_address,
   339                                            require_indexes=require_indexes,
   441                                            require_indexes=require_indexes,
   340                                            static_caching=static_caching)
   442                                            static_caching=static_caching)
   341 
   443 
   342   logging.info('Running application %s on port %d: http://%s:%d',
   444   logging.info('Running application %s on port %d: http://%s:%d',
   357   return 0
   459   return 0
   358 
   460 
   359 
   461 
   360 if __name__ == '__main__':
   462 if __name__ == '__main__':
   361   sys.exit(main(sys.argv))
   463   sys.exit(main(sys.argv))
       
   464 else:
       
   465   SetGlobals()