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

« back to all changes in this revision

Viewing changes to twisted/web/script.py

  • Committer: Marc Tardif
  • Date: 2010-05-20 19:56:06 UTC
  • Revision ID: marc.tardif@canonical.com-20100520195606-xdrf0ztlxhvwmmzb
Added twisted-web.

Show diffs side-by-side

added added

removed removed

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