pywx.py :  » Network » PyWX » PyWX-1.0b2 » pywx-lib » 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 » Network » PyWX 
PyWX » PyWX 1.0b2 » pywx lib » pywx.py
# $Id: pywx.py,v 1.1 2002/12/12 18:09:54 titus Exp $

###
### See included file COPYRIGHT for copyright and license information.
###

# Should we use a custom version of execfile() that caches the
# compiled code in memory?  Warning: This may not be thread safe!!!
UseCachingExec = 0

import sys, traceback, os, string, stat
import Ns, ns_setup

Ns.Log(Ns.Debug, '**** importing pywx.py')


if UseCachingExec:
    Ns.Log(Ns.Debug, 'Using the caching version of execfile.')
    import ns_codecache
    execfile = ns_codecache.execfile
else:
    Ns.Log(Ns.Debug, 'Using the standard (non-caching) version of execfile.')


# This default can be overridden in the AOLserver configuration file;
# see INSTALL:
default_exception_html = """\
<html>
<title>Internal Server Error</title>
<body bgcolor=white>
<h2>Internal Server Error</h2>
There was an error processing your request.  Our web administrators
have been notified.  Sorry for the inconvenience.
</body>
</html>
"""

# This default can be overridden in the AOLserver configuration file;
# see INSTALL:
default_exception_log = """\
Python exception: Unhandled exception running %(url)s.  Traceback:
%(exc_text)s"""


class ScriptError(Exception):
    """An error that gets special handling by PyWX.

    Any exceptions derived from this class get special handling by
    PyWX.  If such an exception is caught by PyWX (implying that the
    application script didn't handle it internally), then PyWX calls
    the exception's __call__ method with the arguments (conn, url).
    Derived classes should usually override this method do do whatever
    custom actions they want--for example, redirecting the client to
    an error page, printing a customized error page, etc.

    In some cases it might be enough for a derived class to override
    just the format strings.

    """

    # These format strings are taken from the AOLserver configuration
    # file if available; otherwise the defaults defined above are
    # used.

    # format string for the output to the client:
    exception_html = (
        Ns.ConfigGetValue('ns/environment/python', 'ExceptionHTMLFmt')
        or default_exception_html
        )

    # format string for output to the nsd log:
    exception_log = (
        Ns.ConfigGetValue('ns/environment/python', 'ExceptionLogFmt')
        or default_exception_log
        )

    def __call__(self, conn, url):
        fmt_dict = {
            'url' : url,
            # Don't store sys.exc_info() to local variables because it
            # causes a reference loop:
            'exc_text' : string.join(
                apply(traceback.format_exception, sys.exc_info()),
                '',
                ),
            }
        conn.ReturnHtml(500, self.exception_html % fmt_dict)
        Ns.Log(Ns.Error, self.exception_log % fmt_dict)


def clear_namespace(d):
    """Clear d, which is a dict that was used as a namespace.

    Any code objects defined by the script refer back to the global
    dictionary, namely d--creating a reference cycle.  So d itself
    will not be freed as long as any of those code objects is alive.
    Call this routine to clear d explicitly to try to break the
    reference cycles.

    But it's more complicated even that that.  Code objects implicitly
    refer to the global namespace to look up, e.g., modules.
    Therefore destructors will fail if the modules they depend on have
    already been deleted from d.  There doesn't seem to be a general
    way to solve this problem.  We imitate the code in
    _PyModule_Clear(), which first deletes identifiers that start with
    a single underscore, then everything else (but leaving
    __builtins__ intact).

    We ignore the theoretical but perverse possibility that an object
    destructor might itself delete another object from its global
    namespace.

    """

    # First delete identifiers that start with a single underscore:
    for k in d.keys():
        if k[0] == '_' and k[1] != '_':
            del d[k]

    # Now delete everything else except __builtins__:
    for k in d.keys():
        # One of the earlier destructors could have already deleted k
        if k != '__builtins__':
            del d[k]
    # Leave __builtins__ in place for the same reason the Python
    # module cleanup code does--which, as I understand, is that a code
    # object might still exist but not be referenced in the d
    # namespace.


def runscript(conn):
    """Run a python script."""

    url = conn.request.url

    # see if file exists:
    script = Ns.UrlToFile(conn.Server(), url)
    try:
        os.stat(script)
    except OSError:
        conn.ReturnNotFound()
    else:
        # Fool script into thinking that it is running as __main__.
        # __persistdict__ is in __builtins__, which is attached
        # automatically by execfile and therefore accessable.
        d = {'__name__' : '__main__'}
        try:
            try:
                execfile(script, d)
            except ScriptError, e:
                # If there was a script-defined exception, process it
                # now, before its global dictionary is decimated:
                e(conn, url)
        finally:
            clear_namespace(d)


def cgi_runscript(conn):
    """Run a python script in a CGI environment.

    This function does not attach stdio; that has to be done at the
    C++ level (i.e., via the AttachStdio config directive).

    """

    url = conn.request.url
    pageroot = Ns.PageRoot(conn.Server())

    #  Bah!  It's not that easy.  To wit, from the
    #  AOLserver nscgi sources we learn:
    #
    #  1. Path is UrlToFile up to the URL prefix.
    #  2. SCRIPTNAME is the URL prefix
    #  3. PATH_INFO is everything past SCRIPT_NAME
    ns_setup.setup_cgi_env(url)
    Ns.Log(Ns.Debug, '++++ start python: ' + os.environ['SCRIPT_NAME'])
    try:
        # see if file exists:
        os.stat(pageroot + os.environ['SCRIPT_NAME'])
    except OSError:
        conn.ReturnNotFound()
    else:
        # Error handling is done in the function who called us.
        execfile(pageroot + os.environ['SCRIPT_NAME'])

    Ns.Log(Ns.Debug, '++++ done python: ' + os.environ['SCRIPT_NAME'])


def run_map(setup_strings, callable):
    conn = Ns.GetConn()
    url = conn.request.url
    Ns.Log(Ns.Debug, '++++ start python: ' + url)

    # Execute request, catching any exceptions:
    try:
        try:
            d = {} # Dictionary to use
            for s in setup_strings:
                Ns.Log(Ns.Debug, 'Executing setup string "%s"' % s)
                exec s in d
            eval(callable, d)(conn)
        except SystemExit:
            # This indicates a normal exit() call--needn't print exception.
            pass
        except ScriptError, e:
            e(conn, url)
    except:
        # This outside try block catches unrecognized exceptions,
        # including any exceptions raised within the user's custom
        # error handler.  Use ScriptError to log:
        ScriptError()(conn, url)

    clear_namespace(d)
    Ns.Log(Ns.Debug, '++++ done python: ' + url)


# Right now there is no difference between these two functions:
thread_run_map = run_map


# Old method of invoking PyWX; still used in 00-python.tcl.
def fulfill_request():
    conn = Ns.GetConn()
    url = conn.request.url
    Ns.Log(Ns.Debug, '++++ start python: ' + url)

    # Execute request, catching any exceptions:
    try:
        try:
            runscript(conn)
        except SystemExit:
            # This indicates a normal exit() call--needn't print exception.
            pass
        except ScriptError, e:
            e(conn, url)
    except:
        # This outside try block catches unrecognized exceptions,
        # including any exceptions raised within the user's custom
        # error handler.  Use ScriptError to log:
        ScriptError()(conn, url)

    Ns.Log(Ns.Debug, '++++ done python: ' + url)


# This routine is currently non-functional.  It should probably be
# rewritten to be a substitute for runscript(). ###
def fulfill_cgi_request():
    conn = Ns.GetConn()
    url = conn.request.url
    pageroot = Ns.PageRoot(conn.Server())

    #
    #  Bah!  It's not that easy.  To wit, from the
    #  AOLserver nscgi sources we learn:
    #
    #  1. Path is UrlToFile up to the URL prefix.
    #  2. SCRIPTNAME is the URL prefix
    #  3. PATH_INFO is everything past SCRIPT_NAME
    ns_setup.setup_cgi_env(url)
    Ns.Log(Ns.Debug, '++++ start python: ' + os.environ['SCRIPT_NAME'])
    try:
        # see if file exists:
        os.stat(pageroot + os.environ['SCRIPT_NAME'])
    except OSError:
        conn.ReturnNotFound()
    else:
        # let python do its own error handling
        prepare_and_runscript(conn, pageroot + os.environ['SCRIPT_NAME'], url)

    Ns.Log(Ns.Debug, '++++ done python: ' + os.environ['SCRIPT_NAME'])


www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.