| # Copyright 2008 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. |
| |
| """Main program for Gerrit. |
| |
| This is also a template for running a Django app under Google App |
| Engine, especially when using a newer version of Django than provided |
| in the App Engine standard library. |
| |
| The site-specific code is all in other files: urls.py, models.py, |
| views.py, settings.py. |
| """ |
| |
| # Standard Python imports. |
| import os |
| import sys |
| import logging |
| |
| # Log a message each time this module get loaded. |
| logging.info('Loading %s, app version = %s', |
| __name__, os.getenv('CURRENT_VERSION_ID')) |
| |
| # Delete the preloaded copy of Django. |
| for key in [key for key in sys.modules if key.startswith('django')]: |
| del sys.modules[key] |
| |
| # Force sys.path to have our own directory first, so we can import from it. |
| sys.path.insert(0, os.path.abspath(os.path.dirname(__file__))) |
| sys.path.insert(0, os.path.abspath('django.zip')) |
| sys.path.insert(0, os.path.abspath('froofle.zip')) |
| sys.path.insert(0, os.path.abspath('codereview.zip')) |
| |
| # Fail early if we can't import Django. Log identifying information. |
| import django |
| logging.info('django.__file__ = %r, django.VERSION = %r', |
| django.__file__, django.VERSION) |
| assert django.VERSION[0] >= 1,"This Django version is too old" |
| |
| # AppEngine imports. |
| from google.appengine.ext.webapp import util |
| |
| # Helper to enter the debugger. This passes in __stdin__ and |
| # __stdout__, because stdin and stdout are connected to the request |
| # and response streams. You must import this from __main__ to use it. |
| # (I tried to make it universally available via __builtin__, but that |
| # doesn't seem to work for some reason.) |
| def BREAKPOINT(): |
| import pdb |
| p = pdb.Pdb(None, sys.__stdin__, sys.__stdout__) |
| p.set_trace() |
| |
| # Custom Django configuration. |
| from django.conf import settings |
| settings._target = None |
| os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' |
| |
| # Import various parts of Django. |
| import django.core.handlers.wsgi |
| import django.core.signals |
| import django.db |
| import django.dispatch.dispatcher |
| import django.forms |
| |
| # Work-around to avoid warning about django.newforms in djangoforms. |
| django.newforms = django.forms |
| |
| def log_exception(*args, **kwds): |
| """Django signal handler to log an exception.""" |
| cls, err = sys.exc_info()[:2] |
| logging.exception('Exception in request: %s: %s', cls.__name__, err) |
| |
| # Log all exceptions detected by Django. |
| django.core.signals.got_request_exception.connect(log_exception) |
| |
| # Unregister Django's default rollback event handler. |
| django.core.signals.got_request_exception.disconnect( |
| django.db._rollback_on_exception) |
| |
| correct_path = None |
| def real_main(): |
| """Main program. |
| """ |
| global correct_path |
| |
| if correct_path is None: |
| correct_path = list(sys.path) |
| else: |
| sys.path[:] = correct_path |
| |
| application = django.core.handlers.wsgi.WSGIHandler() |
| util.run_wsgi_app(application) |
| |
| def profile_main(): |
| """Main program for profiling. |
| """ |
| import cProfile, pstats, StringIO |
| prof = cProfile.Profile() |
| prof = prof.runctx('real_main()', globals(), locals()) |
| stream = StringIO.StringIO() |
| stats = pstats.Stats(prof, stream=stream) |
| # stats.strip_dirs() # Don't; too many modules are named __init__.py. |
| stats.sort_stats('time') # 'time', 'cumulative' or 'calls' |
| stats.print_stats() # Optional arg: how many to print |
| # The rest is optional. |
| # stats.print_callees() |
| # stats.print_callers() |
| print '\n<hr>' |
| print '<h1>Profile</h1>' |
| print '<pre>' |
| print stream.getvalue()[:1000000] |
| print '</pre>' |
| |
| # Set this to profile_main to enable profiling. |
| main = real_main |
| |
| if __name__ == '__main__': |
| main() |