~certify-web-dev/twisted/certify-trunk

« back to all changes in this revision

Viewing changes to twisted/web/script.py

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2007-01-17 14:52:35 UTC
  • mfrom: (1.1.5 upstream) (2.1.2 etch)
  • Revision ID: james.westby@ubuntu.com-20070117145235-btmig6qfmqfen0om
Tags: 2.5.0-0ubuntu1
New upstream version, compatible with python2.5.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
 
3
# See LICENSE for details.
 
4
 
 
5
 
 
6
"""I contain PythonScript, which is a very simple python script resource.
 
7
"""
 
8
 
 
9
import server
 
10
import resource
 
11
import html
 
12
import error
 
13
 
 
14
try:
 
15
    import cStringIO as StringIO
 
16
except ImportError:
 
17
    import StringIO
 
18
 
 
19
from twisted.web import http
 
20
from twisted import copyright
 
21
import traceback
 
22
import os
 
23
from twisted.web import resource
 
24
from twisted.web import static
 
25
 
 
26
rpyNoResource = """<p>You forgot to assign to the variable "resource" in your script. For example:</p>
 
27
<pre>
 
28
# MyCoolWebApp.rpy
 
29
 
 
30
import mygreatresource
 
31
 
 
32
resource = mygreatresource.MyGreatResource()
 
33
</pre>
 
34
"""
 
35
 
 
36
class AlreadyCached(Exception):
 
37
    """This exception is raised when a path has already been cached.
 
38
    """
 
39
 
 
40
class CacheScanner:
 
41
    def __init__(self, path, registry):
 
42
        self.path = path
 
43
        self.registry = registry
 
44
        self.doCache = 0
 
45
 
 
46
    def cache(self):
 
47
        c = self.registry.getCachedPath(self.path)
 
48
        if c is not None:
 
49
            raise AlreadyCached(c)
 
50
        self.recache()
 
51
 
 
52
    def recache(self):
 
53
        self.doCache = 1
 
54
 
 
55
noRsrc = error.ErrorPage(500, "Whoops! Internal Error", rpyNoResource)
 
56
 
 
57
def ResourceScript(path, registry):
 
58
    """
 
59
    I am a normal py file which must define a 'resource' global, which should
 
60
    be an instance of (a subclass of) web.resource.Resource; it will be
 
61
    renderred.
 
62
    """
 
63
    cs = CacheScanner(path, registry)
 
64
    glob = {'__file__': path,
 
65
            'resource': noRsrc,
 
66
            'registry': registry,
 
67
            'cache': cs.cache,
 
68
            'recache': cs.recache}
 
69
    try:
 
70
        execfile(path, glob, glob)
 
71
    except AlreadyCached, ac:
 
72
        return ac.args[0]
 
73
    rsrc = glob['resource']
 
74
    if cs.doCache and rsrc is not noRsrc:
 
75
        registry.cachePath(path, rsrc)
 
76
    return rsrc
 
77
 
 
78
def ResourceTemplate(path, registry):
 
79
    from quixote import ptl_compile
 
80
 
 
81
    glob = {'__file__': path,
 
82
            'resource': error.ErrorPage(500, "Whoops! Internal Error",
 
83
                                        rpyNoResource),
 
84
            'registry': registry}
 
85
 
 
86
    e = ptl_compile.compile_template(open(path), path)
 
87
    exec e in glob
 
88
    return glob['resource']
 
89
 
 
90
 
 
91
class ResourceScriptWrapper(resource.Resource):
 
92
 
 
93
    def __init__(self, path, registry=None):
 
94
        resource.Resource.__init__(self)
 
95
        self.path = path
 
96
        self.registry = registry or static.Registry()
 
97
 
 
98
    def render(self, request):
 
99
        res = ResourceScript(self.path, self.registry)
 
100
        return res.render(request)
 
101
 
 
102
    def getChildWithDefault(self, path, request):
 
103
        res = ResourceScript(self.path, self.registry)
 
104
        return res.getChildWithDefault(path, request)
 
105
 
 
106
 
 
107
 
 
108
class ResourceScriptDirectory(resource.Resource):
 
109
    def __init__(self, pathname, registry=None):
 
110
        resource.Resource.__init__(self)
 
111
        self.path = pathname
 
112
        self.registry = registry or static.Registry()
 
113
 
 
114
    def getChild(self, path, request):
 
115
        fn = os.path.join(self.path, path)
 
116
 
 
117
        if os.path.isdir(fn):
 
118
            return ResourceScriptDirectory(fn, self.registry)
 
119
        if os.path.exists(fn):
 
120
            return ResourceScript(fn, self.registry)
 
121
        return error.NoResource()
 
122
 
 
123
    def render(self, request):
 
124
        return error.NoResource().render(request)
 
125
 
 
126
 
 
127
class PythonScript(resource.Resource):
 
128
    """I am an extremely simple dynamic resource; an embedded python script.
 
129
 
 
130
    This will execute a file (usually of the extension '.epy') as Python code,
 
131
    internal to the webserver.
 
132
    """
 
133
    isLeaf = 1
 
134
    def __init__(self, filename, registry):
 
135
        """Initialize me with a script name.
 
136
        """
 
137
        self.filename = filename
 
138
        self.registry = registry
 
139
 
 
140
    def render(self, request):
 
141
        """Render me to a web client.
 
142
 
 
143
        Load my file, execute it in a special namespace (with 'request' and
 
144
        '__file__' global vars) and finish the request.  Output to the web-page
 
145
        will NOT be handled with print - standard output goes to the log - but
 
146
        with request.write.
 
147
        """
 
148
        request.setHeader("x-powered-by","Twisted/%s" % copyright.version)
 
149
        namespace = {'request': request,
 
150
                     '__file__': self.filename,
 
151
                     'registry': self.registry}
 
152
        try:
 
153
            execfile(self.filename, namespace, namespace)
 
154
        except IOError, e:
 
155
            if e.errno == 2: #file not found
 
156
                request.setResponseCode(http.NOT_FOUND)
 
157
                request.write(error.NoResource("File not found.").render(request))
 
158
        except:
 
159
            io = StringIO.StringIO()
 
160
            traceback.print_exc(file=io)
 
161
            request.write(html.PRE(io.getvalue()))
 
162
        request.finish()
 
163
        return server.NOT_DONE_YET