DebugAppServer.py :  » Web-Frameworks » Webware » Webware-1.0.2 » WebKit » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Web Frameworks » Webware 
Webware » Webware 1.0.2 » WebKit » DebugAppServer.py
#!/usr/bin/env python

"""DebugAppServer

`DebugAppServer` executes all requests within the main thread, allowing
servlets to be easily debugged using any Python debugger. The drawback is
that only one request can be processed at a time using this approach.

Also, exceptions are not caught and gracefully handled with an HTML error
page. Instead, the exceptions rise uncaught which allows the debugger to
trap them so you can inspect the program.

To use, simply run "python Launch.py DebugAppServer" using whatever debugging
environment you prefer.

Caveats:

This app server supports the AutoReload feature but not for Python's standard
modules or WebKit or WebKit's dependencies (MiscUtils, WebUtils and TaskKit).
Even with that limitation, auto-reload is still useful because if you modify
any module in your site, the auto-reload will happen. Note that the app server
*will* restart when the aformentioned modules are modified, but the modules
won't actually be reloaded.

Currently the session sweeper is still run within a separate thread, and
a "close thread" is started up by the AppServer base class, but neither
of these two extra threads should pose any problems debugging servlets.

Tested on:
  - WingIDE on Windows, http://wingware.com/
  - PythonWin
  - JEdit with the JPyDbg plugin, on Windows

"""

import sys

from Common import *
import ThreadedAppServer, Profiler

# We are going to replace ThreadedAppServer with our own class,
# so we need to save a reference to the original class.
OriginalThreadedAppServer = ThreadedAppServer.ThreadedAppServer

# We want the Python debugger to trap the exceptions, not WebKit
ThreadedAppServer.doesRunHandleExceptions = False


class DebugAppServer(OriginalThreadedAppServer):
  """Single-threaded AppServer for debugging purposes.

  We are piggybacking on 99% of the code in ThreadedAppServer. Our
  trick is to replace the request queue with a dummy object that
  executes requests immediately instead of pushing them onto a queue
  to be handled by other threads.

  """


  ## Init ##

  _excludePrefixes = 'WebKit MiscUtils WebUtils TaskKit'.split()

  def __init__(self, path=None):
    """Initialize DebugAppServer."""
    # Initialize the base class
    OriginalThreadedAppServer.__init__(self, path)
    # Replace the request queue with a dummy object that merely
    # runs request handlers as soon as they are "pushed"
    self._requestQueue = DummyRequestQueue()
    print 'You are running the debugging app server.'

  def config(self):
    """Return default configuration."""
    # Force ThreadedAppServer to create an empty thread pool by hacking
    # the settings to zero. This is not strictly necessary to do.
    if self._config is None:
      OriginalThreadedAppServer.config(self)
      self.setSetting('StartServerThreads', 0)
      self.setSetting('MaxServerThreads', 0)
      self.setSetting('MinServerThreads', 0)
    return self._config


  ## Overridden methods ##

  def mainloop(self):
    """Main loop for Windows.

    This is needed for COM support on Windows, because special thread
    initialization is required on any thread that runs servlets, in
    this case the main thread itself.

    """
    self.initThread()
    try:
      OriginalThreadedAppServer.mainloop(self)
    finally:
      self.delThread()

  def createApplication(self):
    """Create and return an application object. Invoked by __init__."""
    return DebugApplication(server=self)

  def restart(self):
    # The normal restart technique is to exit the application
    # with a special exit code and let an exta-process script
    # start the app server up again. That works poorly for a
    # debugging environment which is attached to a particular process.
    Profiler.reset()
    self.initiateShutdown()
    self._closeThread.join()
    sys.stdout.flush()
    sys.stderr.flush()
    self._imp.delModules(includePythonModules=False,
      excludePrefixes=self._excludePrefixes)
    raise ThreadedAppServer.RestartAppServerError


from Application import Application


class DebugApplication(Application):
  """This is a modified Application class for debugging."""


  ## Overridden methods ##

  # Don't handle exceptions gracefully because we want
  # them to rise uncaught so the debugger will kick in.

  # @@ 2005-07-15 CE: This works well for exceptions within responding to
  # a request, but for problems during importing a servlet, the exception
  # gets printed to console and the debugger does not kick in.

  def handleException(self):
    """Handle exception.

    This should only be used in cases where there is no transaction object,
    for example if an exception occurs when attempting to save a session
    to disk.

    """
    raise

  def handleExceptionInTransaction(self, excInfo, transaction):
    """Handle exception with info.

    Raises exception `excInfo` (as returned by ``sys.exc_info()``)
    that was generated by `transaction`.

    """
    raise


class DummyRequestQueue:
  """This is a dummy replacement for the request queue.

  It merely executes handlers as soon as they are "pushed".

  """


  ## Overridden methods ##

  def put(self, handler):
    handler.handleRequest()
    handler.close()


## Globals ##

# Replace ThreadedAppServer class in the ThreadedAppServer module with our
# DebugAppServer.  This seems like an awful hack, but it works and
# requires less code duplication than other approaches I could think of, and
# required a very minimal amount of modification to ThreadedAppServer.py.
ThreadedAppServer.ThreadedAppServer = DebugAppServer

# Grab the main function from ThreadedAppServer -- it has been "tricked"
# into using DebugAppServer instead.
main = ThreadedAppServer.main

# Tweak ThreadedAppServer so that it never runs the main loop in a thread:
def runMainLoopInThread():
  return 0
ThreadedAppServer.runMainLoopInThread = runMainLoopInThread
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.