Changeset 1602
- Timestamp:
- 01/20/07 02:03:09
- Files:
-
- trunk/cherrypy/__init__.py (modified) (1 diff)
- trunk/cherrypy/_cprequest.py (modified) (3 diffs)
- trunk/cherrypy/lib/http.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/cherrypy/__init__.py
r1601 r1602 5 5 from urlparse import urljoin as _urljoin 6 6 7 from cherrypy._cperror import HTTPError, HTTPRedirect, InternalRedirect, NotFound, CherryPyException 8 from cherrypy._cperror import TimeoutError 7 8 class _AttributeDocstrings(type): 9 """Metaclass for declaring docstrings for class attributes.""" 10 # The full docstring for this type is down in the __init__ method so 11 # that it doesn't show up in help() for every consumer class. 12 13 def __init__(cls, name, bases, dct): 14 '''Metaclass for declaring docstrings for class attributes. 15 16 Base Python doesn't provide any syntax for setting docstrings on 17 'data attributes' (non-callables). This metaclass allows class 18 definitions to follow the declaration of a data attribute with 19 a docstring for that attribute; the attribute docstring will be 20 popped from the class dict and folded into the class docstring. 21 22 The naming convention for attribute docstrings is: <attrname> + "__doc". 23 For example: 24 25 class Thing(object): 26 """A thing and its properties.""" 27 28 __metaclass__ = cherrypy._AttributeDocstrings 29 30 height = 50 31 height__doc = """The height of the Thing in inches.""" 32 33 In which case, help(Thing) starts like this: 34 35 >>> help(mod.Thing) 36 Help on class Thing in module pkg.mod: 37 38 class Thing(__builtin__.object) 39 | A thing and its properties. 40 | 41 | height [= 50]: 42 | The height of the Thing in inches. 43 | 44 45 The benefits of this approach over hand-edited class docstrings: 46 1. Places the docstring nearer to the attribute declaration. 47 2. Makes attribute docs more uniform ("name (default): doc"). 48 3. Reduces mismatches of attribute _names_ between 49 the declaration and the documentation. 50 4. Reduces mismatches of attribute default _values_ between 51 the declaration and the documentation. 52 53 The benefits of a metaclass approach over other approaches: 54 1. Simpler ("less magic") than interface-based solutions. 55 2. __metaclass__ can be specified at the module global level 56 for classic classes. 57 58 The type of the attribute is intentionally not included, because 59 that's not How Python Works. Quack. 60 ''' 61 62 newdoc = [cls.__doc__ or ""] 63 64 dctnames = dct.keys() 65 dctnames.sort() 66 67 for name in dctnames: 68 if name.endswith("__doc"): 69 # Remove the magic doc attribute. 70 if hasattr(cls, name): 71 delattr(cls, name) 72 73 # Get an inspect-style docstring if possible (usually so). 74 val = dct[name] 75 try: 76 import inspect 77 val = inspect.getdoc(property(doc=val)).strip() 78 except: 79 pass 80 81 # Indent the docstring. 82 val = '\n'.join([' ' + line.rstrip() 83 for line in val.split('\n')]) 84 85 # Get the default value. 86 attrname = name[:-5] 87 try: 88 attrval = getattr(cls, attrname) 89 except AttributeError: 90 attrval = "missing" 91 92 # Add the complete attribute docstring to our list. 93 newdoc.append("%s [= %r]:\n%s" % (attrname, attrval, val)) 94 95 # Add our list of new docstrings to the class docstring. 96 cls.__doc__ = "\n\n".join(newdoc) 97 98 99 from cherrypy._cperror import HTTPError, HTTPRedirect, InternalRedirect 100 from cherrypy._cperror import NotFound, CherryPyException, TimeoutError 9 101 10 102 from cherrypy import _cpdispatch as dispatch trunk/cherrypy/_cprequest.py
r1592 r1602 14 14 15 15 class Hook(object): 16 """A callback and its metadata: failsafe, priority, and kwargs. 17 18 failsafe: If True, the callback is guaranteed to run even if other 19 callbacks from the same call point raise exceptions. 20 priority: Defines the order of execution for a list of Hooks. 21 Defaults to 50. Priority numbers should be limited to the 22 closed interval [0, 100], but values outside this range are 23 acceptable, as are fractional values. 24 """ 16 """A callback and its metadata: failsafe, priority, and kwargs.""" 17 18 __metaclass__ = cherrypy._AttributeDocstrings 19 20 callback = None 21 callback__doc = """The bare callable that this Hook object is wrapping. 22 This will be called when the Hook is called.""" 23 24 failsafe = False 25 failsafe__doc = """If True, the callback is guaranteed to run even if 26 other callbacks from the same call point raise exceptions.""" 27 28 priority = 50 29 priority__doc = """Defines the order of execution for a list of Hooks. 30 Priority numbers should be limited to the closed interval [0, 100], but 31 values outside this range are acceptable, as are fractional values.""" 32 33 kwargs = {} 34 kwargs__doc = """A set of keyword arguments that will be passed 35 to the callable on each call.""" 25 36 26 37 def __init__(self, callback, failsafe=None, priority=None, **kwargs): … … 142 153 """ 143 154 155 __metaclass__ = cherrypy._AttributeDocstrings 156 144 157 prev = None 158 prev__doc = """ 159 The previous Request object (if any). This should be None 160 unless we are processing an InternalRedirect.""" 145 161 146 162 # Conversation/connection attributes 147 163 local = http.Host("localhost", 80) 164 local__doc = \ 165 "An http.Host(ip, port, hostname) object for the server socket." 166 148 167 remote = http.Host("localhost", 1111) 168 remote__doc = \ 169 "An http.Host(ip, port, hostname) object for the client socket." 170 149 171 scheme = "http" 172 scheme__doc = """ 173 The protocol used between client and server. In most cases, 174 this will be either 'http' or 'https'.""" 175 150 176 server_protocol = "HTTP/1.1" 177 server_protocol__doc = """ 178 The HTTP version for which the HTTP server is at least 179 conditionally compliant.""" 180 151 181 base = "" 182 base__doc = """The 'base' (scheme + host) portion of the requested URL.""" 152 183 153 184 # Request-Line attributes 154 185 request_line = "" 186 request_line__doc = """ 187 The complete Request Line received from the client. This is a 188 single string consisting of the request method, URI, and protocol 189 version (joined by spaces). Any final CRLF is removed.""" 190 155 191 method = "GET" 192 method__doc = """ 193 Indicates the HTTP method to be performed on the resource identified 194 by the Request-URI. Common methods include GET, HEAD, POST, PUT, and 195 DELETE. CherryPy allows any extension method; however, various HTTP 196 servers and gateways may restrict the set of allowable methods. 197 CherryPy applications SHOULD restrict the set (on a per-URI basis).""" 198 156 199 query_string = "" 200 query_string__doc = """ 201 The query component of the Request-URI, a string of information to be 202 interpreted by the resource. The query portion of a URI follows the 203 path component, and is spearated by a '?'. For example, the URI 204 'http://www.cherrypy.org/wiki?a=3&b=4' has the query component, 205 'a=3&b=4'.""" 206 157 207 protocol = (1, 1) 208 protocol__doc = """The HTTP protocol version corresponding to the set 209 of features which should be allowed in the response. If BOTH 210 the client's request message AND the server's level of HTTP 211 compliance is HTTP/1.1, this attribute will be the tuple (1, 1). 212 If either is 1.0, this attribute will be the tuple (1, 0). 213 Lower HTTP protocol versions are not explicitly supported.""" 214 158 215 params = {} 216 params__doc = """ 217 A dict which combines query string (GET) and request entity (POST) 218 variables. This is populated in two stages: GET params are added 219 before the 'on_start_resource' hook, and POST params are added 220 between the 'before_request_body' and 'before_handler' hooks.""" 159 221 160 222 # Message attributes 161 223 header_list = [] 224 header_list__doc = """ 225 A list of the HTTP request headers as (name, value) tuples. 226 In general, you should use request.headers (a dict) instead.""" 227 162 228 headers = http.HeaderMap() 163 229 cookie = Cookie.SimpleCookie() 230 164 231 rfile = None 232 rfile__doc = """ 233 If the request included an entity (body), it will be available 234 as a stream in this attribute. However, the rfile will normally 235 be read for you between the 'before_request_body' hook and the 236 'before_handler' hook, and the resulting string is placed into 237 either request.params or the request.body attribute. 238 239 You may disable the automatic consumption of the rfile by setting 240 request.process_request_body to False, either in config for the desired 241 path, or in an 'on_start_resource' or 'before_request_body' hook. 242 243 WARNING: In almost every case, you should not attempt to read from the 244 rfile stream after CherryPy's automatic mechanism has read it. If you 245 turn off the automatic parsing of rfile, you should read exactly the 246 number of bytes specified in request.headers['Content-Length']. 247 Ignoring either of these warnings may result in a hung request thread 248 or in corruption of the next (pipelined) request. 249 """ 250 165 251 process_request_body = True 252 process_request_body__doc = """ 253 If True, the rfile (if any) is automatically read and parsed, 254 and the result placed into request.params or request.body.""" 255 166 256 methods_with_bodies = ("POST", "PUT") 257 methods_with_bodies__doc = """ 258 A sequence of HTTP methods for which CherryPy will automatically 259 attempt to read a body from the rfile.""" 260 167 261 body = None 262 body__doc = """ 263 If the request Content-Type is 'application/x-www-form-urlencoded' 264 or multipart, this will be None. Otherwise, this will contain the 265 request entity body as a string; this value is set between the 266 'before_request_body' and 'before_handler' hooks (assuming that 267 process_request_body is True).""" 168 268 169 269 # Dispatch attributes 170 270 dispatch = cherrypy.dispatch.Dispatcher() 271 171 272 script_name = "" 273 script_name__doc = """ 274 The 'mount point' of the application which is handling this request.""" 275 172 276 path_info = "/" 277 path_info__doc = """ 278 The 'relative path' portion of the Request-URI. This is relative 279 to the script_name ('mount point') of the application which is 280 handling this request.""" 281 173 282 app = None 283 app__doc = """The Application object which is handling this request.""" 284 174 285 handler = None 286 handler__doc = """ 287 The function, method, or other callable which CherryPy will call to 288 produce the response. The discovery of the handler and the arguments 289 it will receive are determined by the request.dispatch object. 290 By default, the handler is discovered by walking a tree of objects 291 starting at request.app.root, and is then passed all HTTP params 292 (from the query string and POST body) as keyword arguments.""" 293 175 294 toolmaps = {} 295 toolmaps__doc = """ 296 A nested dict of all Toolboxes and Tools in effect for this request, 297 of the form: {Toolbox.namespace: {Tool.name: config dict}}.""" 298 176 299 config = None 300 config__doc = """ 301 A flat dict of all configuration entries which apply to the 302 current request. These entries are collected from global config, 303 application config (based on request.path_info), and from handler 304 config (exactly how is governed by the request.dispatch object in 305 effect for this request; by default, handler config can be attached 306 anywhere in the tree between request.app.root and the final handler, 307 and inherits downward).""" 308 177 309 is_index = None 310 is_index__doc = """ 311 This will be True if the current request is mapped to an 'index' 312 resource handler (or a 'default' handler if path_info ends with 313 a slash). The value may be used to automatically redirect the 314 user-agent to a 'more canonical' URL which either adds or removes 315 the trailing slash. See cherrypy.tools.trailing_slash.""" 178 316 179 317 hooks = HookMap(hookpoints) 180 318 181 319 error_response = cherrypy.HTTPError(500).set_response 320 error_response__doc = """ 321 The callable which will handle unexpected errors during request 322 processing. By default, it uses HTTPError(500) to return an error 323 response to the user-agent.""" 324 182 325 error_page = {} 326 error_page__doc = """ 327 A dict of {error code: response filename} pairs. The named response 328 files should be Python string-formatting templates, and can expect by 329 default to receive the keyword-formatted values 'status', 'message', 330 'traceback', and 'version'. The set of keyword values can be extended 331 by overriding HTTPError.set_response.""" 332 183 333 show_tracebacks = True 334 show_tracebacks__doc = """ 335 If True, unexpected errors encountered during request processing will 336 include a traceback in the response body.""" 337 184 338 throws = (KeyboardInterrupt, SystemExit, cherrypy.InternalRedirect) 339 throws__doc = """The sequence of exceptions which Request.run does not trap.""" 340 185 341 throw_errors = False 342 throw_errors__doc = """ 343 If True, Request.run will not trap any errors (except HTTPRedirect and 344 HTTPError, which are more properly called 'exceptions', not errors).""" 186 345 187 346 namespaces = {"hooks": hooks_namespace, … … 191 350 # "tools": See _cptools.Toolbox 192 351 } 352 namespaces__doc = """ 353 A dict of config namespace names and handlers. Each config entry must 354 begin with a namespace name; the corresponding namespace handler will 355 be called once for each config entry in that namespace, and will be 356 passed two arguments: the config key (with the namespace removed) 357 and the config value. 358 359 Namespace handlers may be any Python callable; they may also be 360 Python 2.5-style 'context managers', in which case their __enter__ 361 method should return a callable to be used as the handler. 362 See cherrypy.tools (the Toolbox class) for an example. 363 364 Namespaces may be added at the class level and will be inherited 365 by all Request instances. 366 """ 193 367 194 368 def __init__(self, local_host, remote_host, scheme="http", trunk/cherrypy/lib/http.py
r1533 r1602 449 449 name = ip 450 450 self.name = name 451 452 def __repr__(self): 453 return "http.Host(%r, %r, %r)" % (self.ip, self.port, self.name)

