1
# -*- test-case-name: twisted.web.test.test_script -*-
2
# Copyright (c) 2001-2009 Twisted Matrix Laboratories.
3
# See LICENSE for details.
6
I contain PythonScript, which is a very simple python script resource.
12
import cStringIO as StringIO
16
from twisted import copyright
17
from twisted.web import http, server, static, resource, html
20
rpyNoResource = """<p>You forgot to assign to the variable "resource" in your script. For example:</p>
24
import mygreatresource
26
resource = mygreatresource.MyGreatResource()
30
class AlreadyCached(Exception):
31
"""This exception is raised when a path has already been cached.
35
def __init__(self, path, registry):
37
self.registry = registry
41
c = self.registry.getCachedPath(self.path)
43
raise AlreadyCached(c)
49
noRsrc = resource.ErrorPage(500, "Whoops! Internal Error", rpyNoResource)
51
def ResourceScript(path, registry):
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
57
cs = CacheScanner(path, registry)
58
glob = {'__file__': path,
62
'recache': cs.recache}
64
execfile(path, glob, glob)
65
except AlreadyCached, ac:
67
rsrc = glob['resource']
68
if cs.doCache and rsrc is not noRsrc:
69
registry.cachePath(path, rsrc)
72
def ResourceTemplate(path, registry):
73
from quixote import ptl_compile
75
glob = {'__file__': path,
76
'resource': resource.ErrorPage(500, "Whoops! Internal Error",
80
e = ptl_compile.compile_template(open(path), path)
82
return glob['resource']
85
class ResourceScriptWrapper(resource.Resource):
87
def __init__(self, path, registry=None):
88
resource.Resource.__init__(self)
90
self.registry = registry or static.Registry()
92
def render(self, request):
93
res = ResourceScript(self.path, self.registry)
94
return res.render(request)
96
def getChildWithDefault(self, path, request):
97
res = ResourceScript(self.path, self.registry)
98
return res.getChildWithDefault(path, request)
102
class ResourceScriptDirectory(resource.Resource):
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}.
109
@ivar path: A C{str} giving the filesystem path in which children will be
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.
115
def __init__(self, pathname, registry=None):
116
resource.Resource.__init__(self)
118
self.registry = registry or static.Registry()
120
def getChild(self, path, request):
121
fn = os.path.join(self.path, path)
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()
129
def render(self, request):
130
return resource.NoResource().render(request)
133
class PythonScript(resource.Resource):
134
"""I am an extremely simple dynamic resource; an embedded python script.
136
This will execute a file (usually of the extension '.epy') as Python code,
137
internal to the webserver.
140
def __init__(self, filename, registry):
141
"""Initialize me with a script name.
143
self.filename = filename
144
self.registry = registry
146
def render(self, request):
147
"""Render me to a web client.
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
154
request.setHeader("x-powered-by","Twisted/%s" % copyright.version)
155
namespace = {'request': request,
156
'__file__': self.filename,
157
'registry': self.registry}
159
execfile(self.filename, namespace, namespace)
161
if e.errno == 2: #file not found
162
request.setResponseCode(http.NOT_FOUND)
163
request.write(resource.NoResource("File not found.").render(request))
165
io = StringIO.StringIO()
166
traceback.print_exc(file=io)
167
request.write(html.PRE(io.getvalue()))
169
return server.NOT_DONE_YET