Changeset 1281
- Timestamp:
- 08/26/06 03:26:19
- Files:
-
- trunk/cherrypy/__init__.py (modified) (6 diffs)
- trunk/cherrypy/_cpconfig.py (modified) (5 diffs)
- trunk/cherrypy/_cpengine.py (modified) (3 diffs)
- trunk/cherrypy/_cperror.py (modified) (7 diffs)
- trunk/cherrypy/_cprequest.py (modified) (3 diffs)
- trunk/cherrypy/_cpserver.py (modified) (3 diffs)
- trunk/cherrypy/_cptree.py (modified) (1 diff)
- trunk/cherrypy/lib/profiler.py (modified) (1 diff)
- trunk/cherrypy/lib/static.py (modified) (2 diffs)
- trunk/cherrypy/lib/tidy.py (modified) (1 diff)
- trunk/cherrypy/test/benchmark.py (modified) (1 diff)
- trunk/cherrypy/test/test_config.py (modified) (1 diff)
- trunk/cherrypy/test/test_tutorials.py (modified) (1 diff)
- trunk/cherrypy/test/webtest.py (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/cherrypy/__init__.py
r1280 r1281 8 8 9 9 from cherrypy._cperror import HTTPError, HTTPRedirect, InternalRedirect, NotFound 10 from cherrypy._cperror import WrongConfigValue,TimeoutError10 from cherrypy._cperror import TimeoutError 11 11 12 12 from cherrypy import _cptools … … 98 98 99 99 100 def logtime():101 import datetime102 now = datetime.datetime.now()103 import rfc822104 month = rfc822._monthnames[now.month - 1].capitalize()105 return '%02d/%s/%04d:%02d:%02d:%02d' % (106 now.day, month, now.year, now.hour, now.minute, now.second)107 108 109 100 _error_log = _logging.getLogger("cherrypy.error") 110 101 _error_log.setLevel(_logging.DEBUG) … … 134 125 except AttributeError: 135 126 elog = _error_log 136 elog.log(severity, ' '.join(( logtime(), context, msg)))127 elog.log(severity, ' '.join((self.time(), context, msg))) 137 128 138 129 def __call__(self, *args, **kwargs): … … 140 131 141 132 def access(self): 142 """ Default method for logging access"""143 tmpl = '%(h)s %(l)s %(u)s [%(t)s]"%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"'133 """Write to the access log.""" 134 tmpl = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"' 144 135 s = tmpl % {'h': request.remote.name or request.remote.ip, 145 136 'l': '-', 146 137 'u': getattr(request, "login", None) or "-", 147 't': logtime(),138 't': self.time(), 148 139 'r': request.request_line, 149 140 's': response.status.split(" ", 1)[0], … … 156 147 except: 157 148 self.error(traceback=True) 149 150 def time(self): 151 """Return now() in Apache Common Log Format (no timezone).""" 152 import datetime, rfc822 153 now = datetime.datetime.now() 154 month = rfc822._monthnames[now.month - 1].capitalize() 155 return ('[%02d/%s/%04d:%02d:%02d:%02d]' % 156 (now.day, month, now.year, now.hour, now.minute, now.second)) 158 157 159 158 … … 162 161 163 162 # Helper functions for CP apps # 164 165 166 def decorate(func, decorator):167 """168 Return the decorated func. This will automatically copy all169 non-standard attributes (like exposed) to the newly decorated function.170 """171 newfunc = decorator(func)172 for key in dir(func):173 if not hasattr(newfunc, key):174 setattr(newfunc, key, getattr(func, key))175 return newfunc176 177 def decorate_all(obj, decorator):178 """179 Recursively decorate all exposed functions of obj and all of its children,180 grandchildren, etc. If you used to use aspects, you might want to look181 into these. This function modifies obj; there is no return value.182 """183 obj_type = type(obj)184 for key in dir(obj):185 if hasattr(obj_type, key): # only deal with user-defined attributes186 continue187 value = getattr(obj, key)188 if callable(value) and getattr(value, "exposed", False):189 setattr(obj, key, decorate(value, decorator))190 decorate_all(value, decorator)191 192 193 class ExposeItems:194 """195 Utility class that exposes a getitem-aware object. It does not provide196 index() or default() methods, and it does not expose the individual item197 objects - just the list or dict that contains them. User-specific index()198 and default() methods can be implemented by inheriting from this class.199 200 Use case:201 202 from cherrypy import ExposeItems203 ...204 root.foo = ExposeItems(mylist)205 root.bar = ExposeItems(mydict)206 """207 exposed = True208 def __init__(self, items):209 self.items = items210 def __getattr__(self, key):211 return self.items[key]212 163 213 164 trunk/cherrypy/_cpconfig.py
r1278 r1281 12 12 13 13 Global: configuration entries which apply everywhere are stored in 14 cherrypy.config.globalconf. Use the top-level function 'config.update' 15 to modify it. 14 cherrypy.config. 16 15 17 16 Application: entries which apply to each mounted application are stored … … 74 73 The only key that does not exist in a namespace is the "environment" entry. 75 74 This special entry 'imports' other config entries from a template stored in 76 cherrypy. config.environments[environment]. It only applies to globalconf,77 and only when you use "update" to modify globalconf.75 cherrypy._cpconfig.environments[environment]. It only applies to the global 76 config, and only when you use cherrypy.config.update. 78 77 """ 79 78 … … 121 120 122 121 123 default_conf = { 124 'tools.log_tracebacks.on': True, 125 'tools.log_headers.on': True, 126 } 127 128 129 class Config(object): 130 131 globalconf = default_conf.copy() 122 class Config(dict): 123 """The 'global' configuration data for the entire CherryPy process.""" 124 125 defaults = { 126 'tools.log_tracebacks.on': True, 127 'tools.log_headers.on': True, 128 } 129 130 def __init__(self): 131 self.reset() 132 132 133 133 def reset(self): 134 """Reset self .globalconfto default values."""135 self. globalconf.clear()136 self.update(default_conf)134 """Reset self to default values.""" 135 self.clear() 136 dict.update(self, self.defaults) 137 137 138 138 def update(self, conf): 139 """Update self .globalconffrom a dict, file or filename."""139 """Update self from a dict, file or filename.""" 140 140 if isinstance(conf, basestring): 141 # Filename 141 142 if conf not in cherrypy.engine.reload_files: 142 143 cherrypy.engine.reload_files.append(conf) 143 144 conf = _Parser().dict_from_file(conf) 144 145 elif hasattr(conf, 'read'): 146 # Open file object 145 147 conf = _Parser().dict_from_file(conf) 146 148 … … 157 159 conf['tools.staticdir.section'] = "global" 158 160 159 self.globalconf.update(conf) 160 161 _configure_builtin_logging(self.globalconf, cherrypy._error_log) 162 _configure_builtin_logging(self.globalconf, cherrypy._access_log, "log.access_file") 163 164 # Override properties specified in config. 165 gconf = self.globalconf 166 for k in gconf: 167 atoms = k.split(".", 1) 168 namespace = atoms[0] 169 if namespace == "server": 170 setattr(cherrypy.server, atoms[1], gconf[k]) 171 elif namespace == "engine": 172 setattr(cherrypy.engine, atoms[1], gconf[k]) 173 elif namespace == "log": 174 setattr(cherrypy.log, atoms[1], gconf[k]) 175 elif namespace == "error_page": 176 cherrypy.error_page[int(atoms[1])] = gconf[k] 161 # Must use this idiom in order to hit our custom __setitem__. 162 for k, v in conf.iteritems(): 163 self[k] = v 164 165 _configure_builtin_logging(self, cherrypy._error_log) 166 _configure_builtin_logging(self, cherrypy._access_log, "log.access_file") 167 168 def __setitem__(self, k, v): 169 dict.__setitem__(self, k, v) 170 171 # Override object properties if specified in config. 172 atoms = k.split(".", 1) 173 namespace = atoms[0] 174 if namespace == "server": 175 setattr(cherrypy.server, atoms[1], v) 176 elif namespace == "engine": 177 setattr(cherrypy.engine, atoms[1], v) 178 elif namespace == "log": 179 setattr(cherrypy.log, atoms[1], v) 177 180 178 181 def wrap(**kwargs): … … 266 269 value = unrepr(value) 267 270 except Exception, x: 268 msg = (" section: %s, option: %s, value: %s" %271 msg = ("Config error in section: %s, option: %s, value: %s" % 269 272 (repr(section), repr(option), repr(value))) 270 e = cherrypy.WrongConfigValue(msg) 271 e.args += (x.__class__.__name__, x.args) 272 raise e 273 raise ValueError(msg, x.__class__.__name__, x.args) 273 274 result[section][option] = value 274 275 return result trunk/cherrypy/_cpengine.py
r1280 r1281 47 47 response_class = _cprequest.Response 48 48 deadlock_poll_freq = 60 49 autoreload_on = False49 autoreload_on = True 50 50 autoreload_frequency = 1 51 51 … … 173 173 174 174 def restart(self): 175 """Restart the application engine (does n't block)."""175 """Restart the application engine (does not block).""" 176 176 self.stop() 177 177 self.start(blocking=False) … … 216 216 217 217 def monitor(self): 218 """Check timeout on all responses ."""218 """Check timeout on all responses (starts a recurring Timer).""" 219 219 if self.state == STARTED: 220 220 for req, resp in self.servings: trunk/cherrypy/_cperror.py
r1278 r1281 7 7 8 8 9 class WrongConfigValue(Exception):10 """ Happens when a config value can't be parsed, or is otherwise illegal. """11 pass12 13 9 class InternalRedirect(Exception): 14 10 """Exception raised when processing should be handled by a different path. 15 11 16 If you supply a query string, it will bereplace request.params.12 If you supply a query string, it will replace request.params. 17 13 If you omit the query string, the params from the original request will 18 14 remain in effect. … … 46 42 """Exception raised when the request should be redirected. 47 43 48 The new URL must be passed as the first argument to the Exception, e.g.,49 cperror.HTTPRedirect(newUrl). Multiple URLs are allowed. If a URL50 isabsolute, it will be used as-is. If it is relative, it is assumed51 to be relative to the current cherrypy.request.path.44 The new URL must be passed as the first argument to the Exception, 45 e.g., HTTPRedirect(newUrl). Multiple URLs are allowed. If a URL is 46 absolute, it will be used as-is. If it is relative, it is assumed 47 to be relative to the current cherrypy.request.path. 52 48 """ 53 49 … … 86 82 87 83 def set_response(self): 84 """Modify cherrypy.response status, headers, and body to represent self. 85 86 CherryPy uses this internally, but you can also use it to create an 87 HTTPRedirect object and set its output without *raising* the exception. 88 """ 88 89 import cherrypy 89 90 response = cherrypy.response … … 131 132 132 133 def __call__(self): 133 # Allow the exception to be used as a request.handler.134 """Use this exception as a request.handler (raise self).""" 134 135 raise self 135 136 136 137 137 138 class HTTPError(Exception): 138 """ Exception used to return an HTTP error code to the client.139 """ Exception used to return an HTTP error code (4xx-5xx) to the client. 139 140 This exception will automatically set the response status and body. 140 141 … … 151 152 152 153 def set_response(self): 153 """Set cherrypy.response status, headers, and body.""" 154 """Modify cherrypy.response status, headers, and body to represent self. 155 156 CherryPy uses this internally, but you can also use it to create an 157 HTTPError object and set its output without *raising* the exception. 158 """ 154 159 import cherrypy 155 160 … … 189 194 190 195 def __call__(self): 191 # Allow the exception to be used as a request.handler.196 """Use this exception as a request.handler (raise self).""" 192 197 raise self 193 198 194 199 195 200 class NotFound(HTTPError): 196 """ Happens when a URL couldn't be mapped to any class.method"""201 """Exception raised when a URL could not be mapped to any handler (404).""" 197 202 198 203 def __init__(self, path=None): … … 314 319 315 320 def format_exc(exc=None): 316 """ format_exc(exc=None) ->exc (or sys.exc_info if None), formatted."""321 """Return exc (or sys.exc_info if None), formatted.""" 317 322 if exc is None: 318 323 exc = _exc_info() trunk/cherrypy/_cprequest.py
r1280 r1281 41 41 42 42 def __call__(self): 43 """Run self.callback(**self.kwargs).""" 43 44 return self.callback(**self.kwargs) 44 45 … … 102 103 103 104 class LateParamPageHandler(PageHandler): 104 """When passing cherrypy.request.params to the page handler, we do n't105 """When passing cherrypy.request.params to the page handler, we do not 105 106 want to capture that dict too early; we want to give tools like the 106 107 decoding tool a chance to modify the params dict in-between the lookup … … 175 176 def set_conf(): 176 177 """Set cherrypy.request.config.""" 177 base = cherrypy.config. globalconf.copy()178 base = cherrypy.config.copy() 178 179 # Note that we merge the config from each node 179 180 # even if that node was None. trunk/cherrypy/_cpserver.py
r1278 r1281 10 10 11 11 class Server(object): 12 """Manager for a set of HTTP servers.""" 12 """Manager for a set of HTTP servers. 13 14 This is both a container and controller for "HTTP server" objects, 15 which are kept in Server.httpservers, a dictionary of the form: 16 {httpserver: bind_addr} where 'bind_addr' is usually a (host, port) 17 tuple. 18 19 Most often, you will only be starting a single HTTP server. In this 20 common case, you can set attributes (like socket_host and socket_port) 21 on *this* object (which is probably cherrypy.server), and call 22 quickstart. For example: 23 24 cherrypy.server.socket_port = 80 25 cherrypy.server.quickstart() 26 27 But if you need to start more than one HTTP server (to serve on multiple 28 ports, or protocols, etc.), you can manually register each one and then 29 control them all through this object: 30 31 s1 = MyWSGIServer(host='', port=80) 32 s2 = another.HTTPServer(host='localhost', SSL=True) 33 cherrypy.server.httpservers = {s1: ('', 80), s2: ('localhost', 443)} 34 # Note we do not use quickstart when we define our own httpservers 35 cherrypy.server.start() 36 37 Whether you use quickstart(), or define your own httpserver entries and 38 use start(), you'll find that the start, wait, restart, and stop methods 39 work the same way, controlling all registered httpserver objects at once. 40 """ 13 41 14 42 socket_port = 8080 … … 121 149 122 150 def stop(self): 123 """Stop all HTTP server (s)."""151 """Stop all HTTP servers.""" 124 152 for httpserver, bind_addr in self.httpservers.items(): 125 153 try: … … 135 163 136 164 def restart(self): 137 """Restart the HTTP server."""165 """Restart all HTTP servers.""" 138 166 self.stop() 139 167 self.start() trunk/cherrypy/_cptree.py
r1278 r1281 76 76 77 77 78 class Tree :78 class Tree(object): 79 79 """A registry of CherryPy applications, mounted at diverse points. 80 80 trunk/cherrypy/lib/profiler.py
r1274 r1281 52 52 pstats = None 53 53 import warnings 54 msg = ("Your installation of Python does n't have a profile module. "54 msg = ("Your installation of Python does not have a profile module. " 55 55 "If you're on Debian, you can apt-get python2.4-profiler from " 56 56 "non-free in a separate step. See http://www.cherrypy.org/wiki/" trunk/cherrypy/lib/static.py
r1275 r1281 147 147 if not root: 148 148 msg = "Static dir requires an absolute dir (or root)." 149 raise cherrypy.WrongConfigValue(msg)149 raise ValueError(msg) 150 150 dir = os.path.join(root, dir) 151 151 … … 183 183 if not root: 184 184 msg = "Static tool requires an absolute filename (got '%s')." % filename 185 raise cherrypy.WrongConfigValue(msg)185 raise ValueError(msg) 186 186 filename = os.path.join(root, filename) 187 187 trunk/cherrypy/lib/tidy.py
r1243 r1281 11 11 12 12 Note that we use the standalone Tidy tool rather than the python 13 mxTidy module. This is because this module does n't seem to be13 mxTidy module. This is because this module does not seem to be 14 14 stable and it crashes on some HTML pages (which means that the 15 15 server would also crash) trunk/cherrypy/test/benchmark.py
r1278 r1281 5 5 6 6 --null: use a null Request object (to bench the HTTP server only) 7 --notests: start the server but do n't run the tests; this allows7 --notests: start the server but do not run the tests; this allows 8 8 you to check the tested pages with a browser 9 9 --help: show this help message trunk/cherrypy/test/test_config.py
r1278 r1281 88 88 'environment': 'test_suite', 89 89 'autoreload.on': False, 90 # From global conf90 # From global config 91 91 'luxuryyacht': 'throatwobblermangrove', 92 92 # From Root._cp_config trunk/cherrypy/test/test_tutorials.py
r1278 r1281 10 10 def setup_server(): 11 11 12 conf = cherrypy.config. globalconf.copy()12 conf = cherrypy.config.copy() 13 13 14 14 def load_tut_module(name): trunk/cherrypy/test/webtest.py
r1272 r1281 13 13 When an error occurs in the framework, call server_error. It will print 14 14 the traceback to stdout, and keep any assertions you have from running 15 (the assumption is that, if the server errors, the page output w on't be16 of further significance to your tests).15 (the assumption is that, if the server errors, the page output will not 16 be of further significance to your tests). 17 17 """ 18 18 … … 115 115 return test 116 116 else: 117 raise ValueError("do n't know how to make test from: %s" % obj)117 raise ValueError("do not know how to make test from: %s" % obj) 118 118 119 119

