Download Install Tutorial Docs FAQ Tools WikiLicense Team IRC Planet Involvement Shop Book

root/branches/cherrypy-2.1/cherrypy/_cputil.py

Revision 746 (checked in by rdelon, 3 years ago)

Removing VirtualHostFilter? for the 2.1 release

Line 
1 """
2 Copyright (c) 2004, CherryPy Team (team@cherrypy.org)
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7
8     * Redistributions of source code must retain the above copyright notice,
9       this list of conditions and the following disclaimer.
10     * Redistributions in binary form must reproduce the above copyright notice,
11       this list of conditions and the following disclaimer in the documentation
12       and/or other materials provided with the distribution.
13     * Neither the name of the CherryPy Team nor the names of its contributors
14       may be used to endorse or promote products derived from this software
15       without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
21 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 """
28
29 """
30 A module containing a few utility classes/functions used by CherryPy
31 """
32
33 import sys
34 import traceback
35 import time
36 import cgi
37
38 import cherrypy
39 from cherrypy.lib import cptools
40
41
42 class EmptyClass:
43     """ An empty class """
44     pass
45
46
47 def getObjectTrail():
48     """ Return all objects from the currenct object to cherrypy """
49     root = getattr(cherrypy, 'root', None)
50     if root:
51         objectTrail = [root]
52         # Try object path
53         try:
54             path = cherrypy.request.objectPath or cherrypy.request.path
55         except AttributeError:
56             path = '/'
57         if path:
58             pathList = path.split('/')[1:]
59            
60             # Successively get objects from the path
61             for newObj in pathList:
62                 try:
63                     root = getattr(root, newObj)
64                     objectTrail.append(root)
65                 except AttributeError:
66                     break
67        
68         return objectTrail
69     return None
70
71 def getSpecialAttribute(name):
72     """Return the special attribute. A special attribute is one that
73     applies to all of the children from where it is defined, such as
74     _cpFilterList."""
75    
76     # First, we look in the right-most object if this special attribute is implemented.
77     # If not, then we try the previous object and so on until we reach cherrypy.root
78     # If it's still not there, we use the implementation from this module.
79    
80     objectList = getObjectTrail()
81     if objectList:
82        
83         objectList.reverse()
84         for obj in objectList:
85             attr = getattr(obj, name, None)
86             if attr != None:
87                 return attr
88    
89     try:
90         return globals()[name]
91     except KeyError:
92         msg = "Special attribute %s could not be found" % repr(name)
93         raise cherrypy.HTTPError(500, msg)
94
95 def getSpecialAttributePath(name):
96     """ Return the path to the special attribute """
97     objectList = getObjectTrail()
98     if objectList:
99         pathList = cherrypy.request.objectPath or cherrypy.request.path
100         pathList = pathList.split("/")[1:]
101         for i in xrange(len(objectList) - 1, -1, -1):
102             if hasattr(objectList[i], name):
103                 return "/" + "/".join(pathList[:i] + [name])
104     msg = "Special attribute %s could not be found" % repr(name)
105     raise cherrypy.HTTPError(500, msg)
106
107
108 def logtime():
109     return '%04d/%02d/%02d %02d:%02d:%02d' % time.localtime(time.time())[:6]
110
111 def _cpLogAccess():
112     """ Default method for logging access """
113    
114     tmpl = '%(h)s %(l)s %(u)s [%(t)s] "%(r)s" %(s)s %(b)s'
115     s = tmpl % {'h': cherrypy.request.remoteHost,
116                 'l': '-',
117                 'u': getattr(cherrypy.request, "login", None) or "-",
118                 't': logtime(),
119                 'r': cherrypy.request.requestLine,
120                 's': cherrypy.response.status.split(" ", 1)[0],
121                 'b': cherrypy.response.headerMap.get('Content-Length', '') or "-",
122                 }
123    
124     if cherrypy.config.get('server.logToScreen', True):
125         print s
126    
127     fname = cherrypy.config.get('server.logAccessFile', '')
128     if fname:
129         f = open(fname, 'ab')
130         f.write(s + '\n')
131         f.close()
132
133
134 _log_severity_levels = {0: "INFO", 1: "WARNING", 2: "ERROR"}
135
136 def _cpLogMessage(msg, context = '', severity = 0):
137     """ Default method for logging messages (error log)"""
138    
139     level = _log_severity_levels.get(severity, "UNKNOWN")
140     s = logtime() + ' ' + context + ' ' + level + ' ' + msg
141    
142     if cherrypy.config.get('server.logToScreen', True):
143         print s
144    
145     fname = cherrypy.config.get('server.logFile', '')
146     #logdir = os.path.dirname(fname)
147     #if logdir and not os.path.exists(logdir):
148     #    os.makedirs(logdir)
149     if fname:
150         f = open(fname, 'ab')
151         f.write(s + '\n')
152         f.close()
153
154
155 _HTTPErrorTemplate = '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
156   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
157 <html>
158 <head>
159     <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
160     <title>%(status)s</title>
161     <style type="text/css">
162     #poweredBy {
163         margin-top: 20px;
164         border-top: 2px solid black;
165         font-style: italic;
166     }
167
168     #traceback {
169         color: red;
170     }
171     </style>
172 </head>
173     <body>
174         <h2>%(status)s</h2>
175         <p>%(message)s</p>
176         <pre id="traceback">%(traceback)s</pre>
177     <div id="poweredBy">
178     <span>Powered by <a href="Cherrypy">http://www.cherrypy.org">Cherrypy %(version)s</a></span>
179     </div>
180     </body>
181 </html>
182 '''
183
184 def getErrorPage(status, **kwargs):
185     """Return an HTML page, containing a pretty error response.
186     
187     status should be an int or a str.
188     kwargs will be interpolated into the page template.
189     """
190    
191     code, reason, message = cptools.validStatus(status)
192    
193     # We can't use setdefault here, because some
194     # callers send None for kwarg values.
195     if kwargs.get('status') is None:
196         kwargs['status'] = "%s %s" % (code, reason)
197     if kwargs.get('message') is None:
198         kwargs['message'] = message
199     if kwargs.get('traceback') is None:
200         kwargs['traceback'] = ''
201     if kwargs.get('version') is None:
202         kwargs['version'] = cherrypy.__version__
203     for k, v in kwargs.iteritems():
204         if v is None:
205             kwargs[k] = ""
206         else:
207             kwargs[k] = cgi.escape(kwargs[k])
208    
209     template = _HTTPErrorTemplate
210     errorPageFile = cherrypy.config.get('errorPage.%s' % code, '')
211     if errorPageFile:
212         try:
213             template = file(errorPageFile, 'rb').read()
214         except:
215             m = kwargs['message']
216             if m:
217                 m += "<br />"
218             m += ("In addition, the custom error page "
219                   "failed:\n<br />%s" % (sys.exc_info()[1]))
220             kwargs['message'] = m
221    
222     return template % kwargs
223
224 def formatExc(exc=None):
225     """formatExc(exc=None) -> exc (or sys.exc_info if None), formatted."""
226     if exc is None:
227         exc = sys.exc_info()
228    
229     if exc == (None, None, None):
230         return ""
231     return "".join(traceback.format_exception(*exc))
232
233 def _cpOnError():
234     """ Default _cpOnError method """
235     cherrypy.HTTPError(500).set_response()
236
237 _cpFilterList = []
238
239 # Filters that are always included
240 from cherrypy.lib.filter import baseurlfilter, cachefilter, \
241     decodingfilter, encodingfilter, gzipfilter, logdebuginfofilter, \
242     staticfilter, nsgmlsfilter, tidyfilter, \
243     xmlrpcfilter, sessionauthenticatefilter, \
244     sessionfilter
245
246 # this contains the classes for each filter type
247 # we do not store the instances here because the test
248 # suite must reinitilize the filters without restarting
249 # the server
250 _cpDefaultFilterClasses = {
251     'BaseUrlFilter'      : baseurlfilter.BaseUrlFilter,
252     'CacheFilter'        : cachefilter.CacheFilter,
253     'DecodingFilter'     : decodingfilter.DecodingFilter,
254     'EncodingFilter'     : encodingfilter.EncodingFilter,
255     'GzipFilter'         : gzipfilter.GzipFilter,
256     'LogDebugInfoFilter' : logdebuginfofilter.LogDebugInfoFilter,
257     'NsgmlsFilter'       : nsgmlsfilter.NsgmlsFilter,
258     'SessionAuthenticateFilter' : sessionauthenticatefilter.SessionAuthenticateFilter,
259     'SessionFilter'      : sessionfilter.SessionFilter,
260     'StaticFilter'       : staticfilter.StaticFilter,
261     'TidyFilter'         : tidyfilter.TidyFilter,
262     'XmlRpcFilter'       : xmlrpcfilter.XmlRpcFilter,
263 }
264
265 # this is where the actuall filter instances are first stored
266 _cpDefaultFilterInstances = {}
267
268 # These are in order for a reason!
269 # They must be strings matching keys in _cpDefaultFilterClasses
270 __cpDefaultInputFilters = [
271     'CacheFilter',
272     'LogDebugInfoFilter',
273     'BaseUrlFilter',
274     'DecodingFilter',
275     'SessionFilter',
276     'SessionAuthenticateFilter',
277     'StaticFilter',
278     'NsgmlsFilter',
279     'TidyFilter',
280     'XmlRpcFilter',
281 ]
282
283 __cpDefaultOutputFilters = [
284     'XmlRpcFilter',
285     'EncodingFilter',
286     'TidyFilter',
287     'NsgmlsFilter',
288     'LogDebugInfoFilter',
289     'GzipFilter',
290     'SessionFilter',
291     'CacheFilter',
292 ]
293
294 # these are the lists cp internally uses to access the filters
295 # they are populated when _cpInitDefaultFilters is called
296 _cpDefaultInputFilterList  = []
297 _cpDefaultOutputFilterList = []
298
299 # initilize the default filters
300 def _cpInitDefaultFilters():
301     global _cpDefaultInputFilterList, _cpDefaultOutputFilterList
302     global _cpDefaultFilterInstances
303     _cpDefaultInputFilterList  = []
304     _cpDefaultOutputFilterList = []
305     _cpDefaultFilterInstances = {}
306    
307     for filterName in __cpDefaultInputFilters:
308         filterClass = _cpDefaultFilterClasses[filterName]
309         filterInstance = _cpDefaultFilterInstances[filterName] = filterClass()
310         _cpDefaultInputFilterList.append(filterInstance)
311    
312     for filterName in __cpDefaultOutputFilters:
313         filterClass = _cpDefaultFilterClasses[filterName]
314         filterInstance = _cpDefaultFilterInstances.setdefault(filterName, filterClass())
315         _cpDefaultOutputFilterList.append(filterInstance)
316
317 def _cpInitUserDefinedFilters():
318     filtersRoot = cherrypy.config.get('server.filtersRoot', [])
319     inputFiltersDict = cherrypy.config.get('server.inputFiltersDict', {})
320     outputFiltersDict = cherrypy.config.get('server.outputFiltersDict', {})
321    
322     if len(filtersRoot) == 0:
323         return
324
325     sys.path.extend(filtersRoot)
326        
327     for filterName, filterClassname in inputFiltersDict.items():
328         filterModule = __import__(filterName, globals(),  locals(), [])
329         filterClass = getattr(filterModule, filterClassname, None)
330         filterInstance = filterClass()
331         _cpDefaultInputFilterList.append(filterInstance)
332
333     for filterName, filterClassname in outputFiltersDict.items():
334         filterModule = __import__(filterName, globals(),  locals(), [])
335         filterClass = getattr(filterModule, filterClassname, None)
336         filterInstance = filterClass()
337         _cpDefaultOutputFilterList.append(filterInstance)
338
339     # Avoid pollution of the system path
340     for path in filtersRoot:
341         sys.path.remove(path)
342
343
344 # public domain "unrepr" implementation, found on the web and then improved.
345 import compiler
346
347 def getObj(s):
348     s = "a=" + s
349     p = compiler.parse(s)
350     return p.getChildren()[1].getChildren()[0].getChildren()[1]
351
352
353 class UnknownType(Exception):
354    
355     # initialize the built-in filters
356     for n in xrange(len(_cpDefaultInputFilterList)):
357         try:
358             _cpDefaultInputFilterList[n] = _cpDefaultInputFilterList[n]()
359         except:
360             pass
361    
362     for n in xrange(len(_cpDefaultOutputFilterList)):
363         try:
364             _cpDefaultOutputFilterList[n] = _cpDefaultOutputFilterList[n]()
365         except:
366             pass
367
368
369 class Builder:
370    
371     def build(self, o):
372         m = getattr(self, 'build_' + o.__class__.__name__, None)
373         if m is None:
374             raise UnknownType(o.__class__.__name__)
375         return m(o)
376    
377     def build_List(self, o):
378         return map(self.build, o.getChildren())
379    
380     def build_Const(self, o):
381         return o.value
382    
383     def build_Dict(self, o):
384         d = {}
385         i = iter(map(self.build, o.getChildren()))
386         for el in i:
387             d[el] = i.next()
388         return d
389    
390     def build_Tuple(self, o):
391         return tuple(self.build_List(o))
392    
393     def build_Name(self, o):
394         if o.name == 'None':
395             return None
396         if o.name == 'True':
397             return True
398         if o.name == 'False':
399             return False
400        
401         # See if the Name is a package or module
402         try:
403             return modules(o.name)
404         except ImportError:
405             pass
406        
407         raise UnknownType(o.name)
408    
409     def build_Add(self, o):
410         real, imag = map(self.build_Const, o.getChildren())
411         try:
412             real = float(real)
413         except TypeError:
414             raise UnknownType('Add')
415         if not isinstance(imag, complex) or imag.real != 0.0:
416             raise UnknownType('Add')
417         return real+imag
418    
419     def build_Getattr(self, o):
420         parent = self.build(o.expr)
421         return getattr(parent, o.attrname)
422
423
424 def unrepr(s):
425     if not s:
426         return s
427     try:
428         return Builder().build(getObj(s))
429     except:
430         raise cherrypy.WrongUnreprValue(repr(s))
431
432 def modules(modulePath):
433     """Load a module and retrieve a reference to that module."""
434     try:
435         mod = sys.modules[modulePath]
436         if mod is None:
437             raise KeyError()
438     except KeyError:
439         # The last [''] is important.
440         mod = __import__(modulePath, globals(), locals(), [''])
441     return mod
442
443 def attributes(fullAttributeName):
444     """Load a module and retrieve an attribute of that module."""
445    
446     # Parse out the path, module, and attribute
447     lastDot = fullAttributeName.rfind(u".")
448     attrName = fullAttributeName[lastDot + 1:]
449     modPath = fullAttributeName[:lastDot]
450    
451     aMod = modules(modPath)
452     # Let an AttributeError propagate outward.
453     try:
454         attr = getattr(aMod, attrName)
455     except AttributeError:
456         raise AttributeError("'%s' object has no attribute '%s'"
457                              % (modPath, attrName))
458    
459     # Return a reference to the attribute.
460     return attr
Note: See TracBrowser for help on using the browser.

Hosted by WebFaction

Log in as guest/cpguest to create tickets