Initial import to Tizen
[profile/ivi/python-twisted.git] / twisted / web / script.py
1 # -*- test-case-name: twisted.web.test.test_script -*-
2 # Copyright (c) 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