|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- # -*- test-case-name: twisted.web.test.test_script -*-
- # Copyright (c) Twisted Matrix Laboratories.
- # See LICENSE for details.
-
- """
- I contain PythonScript, which is a very simple python script resource.
- """
-
-
- import os
- import traceback
- from io import StringIO
-
- from twisted import copyright
- from twisted.python.compat import execfile, networkString
- from twisted.python.filepath import _coerceToFilesystemEncoding
- from twisted.web import http, resource, server, static, util
-
- rpyNoResource = """<p>You forgot to assign to the variable "resource" in your script. For example:</p>
- <pre>
- # MyCoolWebApp.rpy
-
- import mygreatresource
-
- resource = mygreatresource.MyGreatResource()
- </pre>
- """
-
-
- class AlreadyCached(Exception):
- """
- This exception is raised when a path has already been cached.
- """
-
-
- class CacheScanner:
- def __init__(self, path, registry):
- self.path = path
- self.registry = registry
- self.doCache = 0
-
- def cache(self):
- c = self.registry.getCachedPath(self.path)
- if c is not None:
- raise AlreadyCached(c)
- self.recache()
-
- def recache(self):
- self.doCache = 1
-
-
- noRsrc = resource._UnsafeErrorPage(500, "Whoops! Internal Error", rpyNoResource)
-
-
- def ResourceScript(path, registry):
- """
- I am a normal py file which must define a 'resource' global, which should
- be an instance of (a subclass of) web.resource.Resource; it will be
- renderred.
- """
- cs = CacheScanner(path, registry)
- glob = {
- "__file__": _coerceToFilesystemEncoding("", path),
- "resource": noRsrc,
- "registry": registry,
- "cache": cs.cache,
- "recache": cs.recache,
- }
- try:
- execfile(path, glob, glob)
- except AlreadyCached as ac:
- return ac.args[0]
- rsrc = glob["resource"]
- if cs.doCache and rsrc is not noRsrc:
- registry.cachePath(path, rsrc)
- return rsrc
-
-
- def ResourceTemplate(path, registry):
- from quixote import ptl_compile # type: ignore[import]
-
- glob = {
- "__file__": _coerceToFilesystemEncoding("", path),
- "resource": resource._UnsafeErrorPage(
- 500, "Whoops! Internal Error", rpyNoResource
- ),
- "registry": registry,
- }
-
- with open(path) as f: # Not closed by quixote as of 2.9.1
- e = ptl_compile.compile_template(f, path)
- code = compile(e, "<source>", "exec")
- eval(code, glob, glob)
- return glob["resource"]
-
-
- class ResourceScriptWrapper(resource.Resource):
- def __init__(self, path, registry=None):
- resource.Resource.__init__(self)
- self.path = path
- self.registry = registry or static.Registry()
-
- def render(self, request):
- res = ResourceScript(self.path, self.registry)
- return res.render(request)
-
- def getChildWithDefault(self, path, request):
- res = ResourceScript(self.path, self.registry)
- return res.getChildWithDefault(path, request)
-
-
- class ResourceScriptDirectory(resource.Resource):
- """
- L{ResourceScriptDirectory} is a resource which serves scripts from a
- filesystem directory. File children of a L{ResourceScriptDirectory} will
- be served using L{ResourceScript}. Directory children will be served using
- another L{ResourceScriptDirectory}.
-
- @ivar path: A C{str} giving the filesystem path in which children will be
- looked up.
-
- @ivar registry: A L{static.Registry} instance which will be used to decide
- how to interpret scripts found as children of this resource.
- """
-
- def __init__(self, pathname, registry=None):
- resource.Resource.__init__(self)
- self.path = pathname
- self.registry = registry or static.Registry()
-
- def getChild(self, path, request):
- fn = os.path.join(self.path, path)
-
- if os.path.isdir(fn):
- return ResourceScriptDirectory(fn, self.registry)
- if os.path.exists(fn):
- return ResourceScript(fn, self.registry)
- return resource._UnsafeNoResource()
-
- def render(self, request):
- return resource._UnsafeNoResource().render(request)
-
-
- class PythonScript(resource.Resource):
- """
- I am an extremely simple dynamic resource; an embedded python script.
-
- This will execute a file (usually of the extension '.epy') as Python code,
- internal to the webserver.
- """
-
- isLeaf = True
-
- def __init__(self, filename, registry):
- """
- Initialize me with a script name.
- """
- self.filename = filename
- self.registry = registry
-
- def render(self, request):
- """
- Render me to a web client.
-
- Load my file, execute it in a special namespace (with 'request' and
- '__file__' global vars) and finish the request. Output to the web-page
- will NOT be handled with print - standard output goes to the log - but
- with request.write.
- """
- request.setHeader(
- b"x-powered-by", networkString("Twisted/%s" % copyright.version)
- )
- namespace = {
- "request": request,
- "__file__": _coerceToFilesystemEncoding("", self.filename),
- "registry": self.registry,
- }
- try:
- execfile(self.filename, namespace, namespace)
- except OSError as e:
- if e.errno == 2: # file not found
- request.setResponseCode(http.NOT_FOUND)
- request.write(
- resource._UnsafeNoResource("File not found.").render(request)
- )
- except BaseException:
- io = StringIO()
- traceback.print_exc(file=io)
- output = util._PRE(io.getvalue())
- output = output.encode("utf8")
- request.write(output)
- request.finish()
- return server.NOT_DONE_YET
|