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

Changeset 1083

Show
Ignore:
Timestamp:
05/01/06 18:58:58
Author:
fumanchu
Message:

Objects on the CP tree may now possess a _cp_config attribute, which replaces _cp_tools, _cp_on_error, and _cp_filters. The Request object now keeps its own 'config' attribute (recalculated whenever object_path changes) which mixes _cp_config settings with settings in cherrypy.config. Every tool now has a merged_args method, which is used to pass arguments to the wrapped callable.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/cherrypy/_cprequest.py

    r1082 r1083  
    8383     
    8484    def _run(self): 
    85         conf = cherrypy.config.get 
    86          
    8785        try: 
    8886            # This has to be done very early in the request process, 
     
    9088            # right away. 
    9189            self.process_request_line() 
    92             self.dispatch = conf("dispatch") or _cputil.dispatch 
     90            self.dispatch = self.config.get("dispatch") or _cputil.dispatch 
    9391            self.hooks.setup() 
    9492             
     
    127125            raise 
    128126        except: 
    129             if conf("server.throw_errors", False): 
     127            if cherrypy.config.get("server.throw_errors", False): 
    130128                raise 
    131129            self.handle_error(sys.exc_info()) 
     130     
     131    def _get_object_path(self): 
     132        return self._object_path 
     133    def _set_object_path(self, value): 
     134        self._object_path = value 
     135        self.config = cherrypy.config.request_config() 
     136         
     137        # Get all 'tools.*' config entries as a {toolname: {k: v}} dict. 
     138        self.toolmap = {} 
     139        for k, v in self.config.iteritems(): 
     140            atoms = k.split(".") 
     141            namespace = atoms.pop(0) 
     142            if namespace == "tools": 
     143                toolname = atoms.pop(0) 
     144                bucket = self.toolmap.setdefault(toolname, {}) 
     145                bucket[".".join(atoms)] = v 
     146    object_path = property(_get_object_path, _set_object_path, 
     147                           doc="The path to the rendered resource.") 
    132148     
    133149    def process_request_line(self): 
  • trunk/cherrypy/config.py

    r1082 r1083  
    151151        return result 
    152152 
    153 def current_config(path=None): 
    154     """Return all configs in effect for the given path in a single dict.""" 
    155     if path is None: 
    156         try: 
    157             path = cherrypy.request.object_path 
    158         except AttributeError: 
    159             # There's no request.object_path yet, so use the global settings. 
    160             path = "global" 
    161      
    162     result = {} 
    163     result.update(configs.get("global", {})) 
     153def request_config(): 
     154    """Return all configs in effect for the current request in a single dict.""" 
     155    path = cherrypy.request.object_path 
     156    mounted_app_roots = cherrypy.tree.mount_points.values() 
     157     
     158    # Convert the path into a list of names 
     159    if (not path) or path == "*": 
     160        nameList = [] 
     161    else: 
     162        nameList = path.strip('/').split('/') 
     163    nameList.append('index') 
     164     
    164165    curpath = "" 
    165     for b in path.split('/'): 
    166         if curpath == "/": 
    167             curpath = "" 
    168         curpath = "/".join((curpath, b)) 
    169         result.update(configs.get(curpath, {})) 
    170     return result 
     166    node = cherrypy.root 
     167    conf = getattr(node, "_cp_config", {}).copy() 
     168    conf.update(configs.get("/", {})) 
     169    for name in nameList: 
     170        # Get _cp_config attached to each node on the cherrypy tree. 
     171        objname = name.replace('.', '_') 
     172        node = getattr(node, objname, None) 
     173        if node is not None: 
     174            if node in mounted_app_roots: 
     175                # Dump and start over. This inefficiency should disappear 
     176                # once we make cherrypy.localroot (specific to each request). 
     177                conf = {} 
     178            conf.update(getattr(node, "_cp_config", {})) 
     179         
     180        # Get values from cherrypy.config for this path. 
     181        curpath = "/".join((curpath, name)) 
     182        conf.update(configs.get(curpath, {})) 
     183     
     184    base = configs.get("global", {}).copy() 
     185    base.update(conf) 
     186    return base 
     187 
     188 
     189def request_config_section(key): 
     190    """Return the (longest) path where the given key is defined (or None).""" 
     191    path = cherrypy.request.object_path 
     192    mounted_app_roots = cherrypy.tree.mount_points.values() 
     193     
     194    # Convert the path into a list of names 
     195    if (not path) or path == "*": 
     196        nameList = [] 
     197    else: 
     198        nameList = path.strip('/').split('/') 
     199    nameList.append('index') 
     200     
     201    foundpath = None 
     202     
     203    curpath = "" 
     204    node = cherrypy.root 
     205    if key in getattr(node, "_cp_config", {}) or key in configs.get("/", {}): 
     206        foundpath = "/" 
     207    for name in nameList: 
     208        # Get _cp_config attached to each node on the cherrypy tree. 
     209        objname = name.replace('.', '_') 
     210        node = getattr(node, objname, None) 
     211        if node is not None: 
     212            if node in mounted_app_roots: 
     213                # Dump and start over. This inefficiency should disappear 
     214                # once we make cherrypy.localroot (specific to each request). 
     215                foundpath = None 
     216            if key in getattr(node, "_cp_config", {}): 
     217                foundpath = curpath or "/" 
     218         
     219        # Get values from cherrypy.config for this path. 
     220        curpath = "/".join((curpath, name)) 
     221        if key in configs.get(curpath, {}): 
     222            foundpath = curpath 
     223     
     224    if foundpath is None: 
     225        foundpath = configs.get("global", {}).get(key) 
     226    return foundpath 
    171227 
    172228 
  • trunk/cherrypy/lib/caching.py

    r1075 r1083  
    2727     
    2828    def _key(self): 
    29         return cherrypy.config.get("hooks.cache.key", cherrypy.request.browser_url) 
     29        return cherrypy.request.config.get("tools.caching.key", cherrypy.request.browser_url) 
    3030    key = property(_key) 
    3131     
    3232    def _maxobjsize(self): 
    33         return cherrypy.config.get("hooks.cache.maxobjsize", 100000) 
     33        return cherrypy.request.config.get("tools.caching.maxobjsize", 100000) 
    3434    maxobjsize = property(_maxobjsize) 
    3535     
    3636    def _maxsize(self): 
    37         return cherrypy.config.get("hooks.cache.maxsize", 10000000) 
     37        return cherrypy.request.config.get("tools.caching.maxsize", 10000000) 
    3838    maxsize = property(_maxsize) 
    3939     
    4040    def _maxobjects(self): 
    41         return cherrypy.config.get("hooks.cache.maxobjects", 1000) 
     41        return cherrypy.request.config.get("tools.caching.maxobjects", 1000) 
    4242    maxobjects = property(_maxobjects) 
    4343     
     
    8484            # add to the expirationQueue & cache 
    8585            try: 
    86                 expirationTime = time.time() + cherrypy.config.get("hooks.cache.delay", 600) 
     86                expirationTime = time.time() + cherrypy.request.config.get("tools.caching.delay", 600) 
    8787                objKey = self.key 
    8888                self.expirationQueue.put((expirationTime, objSize, objKey)) 
     
    149149    return wrapper 
    150150 
    151 def setup(conf): 
     151def setup(): 
    152152    """Hook caching into cherrypy.request using the given conf.""" 
     153    conf = cherrypy.request.toolmap.get("caching", {}) 
    153154    if not getattr(cherrypy, "_cache", None): 
    154155        init(conf.get("class", None)) 
  • trunk/cherrypy/test/test_core.py

    r1082 r1083  
    105105         
    106106        class Error: 
    107             _cp_tools = [tools.ErrorRedirect("/errpage")] 
     107            _cp_config = {"tools.err_redirect.on": True, 
     108                          "tools.err_redirect.url": "/errpage", 
     109                          } 
    108110             
    109111            def index(self): 
  • trunk/cherrypy/test/test_custom_filters.py

    r1082 r1083  
    2525     
    2626    class NumTool(tools.Tool): 
    27         def setup(self, conf): 
     27        def setup(self): 
    2828            def makemap(): 
    29                 m = conf.get("map", {}) 
     29                m = self.merged_args().get("map", {}) 
    3030                cherrypy.request.numerify_map = m.items() 
    3131            cherrypy.request.hooks.attach('on_start_resource', makemap) 
     
    5454            self.ended[cherrypy.request.counter] = True 
    5555         
    56         def setup(self, conf=None): 
     56        def setup(self): 
    5757            cherrypy.request.counter = self.counter = self.counter + 1 
    5858            self.ended[cherrypy.request.counter] = False 
     
    8383     
    8484    # METHOD ONE: 
    85     # Use _cp_tools 
     85    # Use _cp_config 
    8686    class Demo(Test): 
    8787         
    88         _cp_tools = [tools.nadsat] 
     88        _cp_config = {"tools.nadsat.on": True} 
    8989         
    9090        def index(self): 
  • trunk/cherrypy/tools.py

    r1082 r1083  
    4747    def setup(self): 
    4848        """Run tool.setup(conf) for each tool specified in current config.""" 
    49         toolconf = tool_config() 
    50          
    5149        g = globals() 
    52         for toolname, conf in toolconf.iteritems(): 
     50        for toolname, conf in cherrypy.request.toolmap.iteritems(): 
    5351            if conf.get("on", False): 
    54                 del conf["on"] 
    55                 tool = g.get(toolname) 
    56                 if tool: 
    57                     tool.setup(conf) 
    58          
    59         # Run _cp_tools setup functions. They should be run 
    60         # in order: first from root to leaf, then in the order 
    61         # given within each _cp_tools list. However, if the 
    62         # same tool is mentioned twice, the one farthest from 
    63         # the root should be used. This allows a leaf node to 
    64         # override parent nodes and order. 
    65         mounted_app_roots = cherrypy.tree.mount_points.values() 
    66         objectList = _cputil.get_object_trail() 
    67         objectList.reverse() 
    68          
    69         # Collect toolsets (up to the app root). 
    70         toolsets = [] 
    71         for objname, obj in objectList: 
    72             toolset = getattr(obj, "_cp_tools", []) 
    73             if toolset: 
    74                 toolsets.append(toolset) 
    75             if obj in mounted_app_roots: 
    76                 break 
    77          
    78         # Now reverse (and de-dupe) the tool list, and call each setup 
    79         toolsets.reverse() 
    80         seen = {} 
    81         for toolset in toolsets: 
    82             for tool in toolset: 
    83                 obj_id = id(tool) 
    84                 if obj_id not in seen: 
    85                     seen[obj_id] = None 
    86                     tool.setup(toolconf.get(tool.name, {})) 
     52                tool = g[toolname] 
     53                tool.setup() 
    8754     
    8855    def run(self, point, *args, **kwargs): 
     
    10673                callback(*args, **kwargs) 
    10774 
    108 def tool_config(): 
    109     """Return all 'tools.*' config entries as a {toolname: {k: v}} dict.""" 
    110     toolmap = {} 
    111     for k, v in cherrypy.config.current_config().iteritems(): 
    112         atoms = k.split(".") 
    113         namespace = atoms.pop(0) 
    114         if namespace == "tools": 
    115             toolname = atoms.pop(0) 
    116             bucket = toolmap.setdefault(toolname, {}) 
    117             bucket[".".join(atoms)] = v 
    118     return toolmap 
    119  
    120 def merged_config(toolname, d): 
    121     """Merge arguments from tool config into another dict.""" 
    122     mergedkw = d.copy() 
    123     mergedkw.update(tool_config().get(toolname, {})) 
    124     if "on" in mergedkw: 
    125         del mergedkw["on"] 
    126     return mergedkw 
    127  
    12875 
    12976class Tool(object): 
     77    """A registered function for use with CherryPy request-processing hooks.""" 
    13078     
    13179    def __init__(self, point, callable, name=None): 
     
    14189        return self.callable(*args, **kwargs) 
    14290     
     91    def merged_args(self, d=None): 
     92        conf = cherrypy.request.toolmap.get(self.name, {}).copy() 
     93        conf.update(d or {}) 
     94        if "on" in conf: 
     95            del conf["on"] 
     96        return conf 
     97     
    14398    def wrap(self, *args, **kwargs): 
    14499        """Make a decorator for this tool. 
     
    153108        def deco(f): 
    154109            def wrapper(*a, **kw): 
    155                 self.callable(*args, **merged_config(self.name, kwargs)) 
     110                self.callable(*args, **self.merged_args(kwargs)) 
    156111                return f(*a, **kw) 
    157112            return wrapper 
    158113        return deco 
    159114     
    160     def setup(self, conf=None): 
    161         """Hook this tool into cherrypy.request using the given conf
     115    def setup(self): 
     116        """Hook this tool into cherrypy.request
    162117         
    163118        The standard CherryPy request object will automatically call this 
    164119        method when the tool is "turned on" in config. 
    165120        """ 
     121        conf = self.merged_args() 
    166122        cherrypy.request.hooks.attach(self.point, self.callable, conf) 
    167123 
     
    185141        """ 
    186142        def wrapper(*a, **kw): 
    187             handled = self.callable(*args, **merged_config(self.name, kwargs)) 
     143            handled = self.callable(*args, **self.merged_args(kwargs)) 
    188144            if not handled: 
    189145                raise cherrypy.NotFound() 
     
    204160        def deco(f): 
    205161            def wrapper(*a, **kw): 
    206                 handled = self.callable(*args, **merged_config(self.name, kwargs)) 
     162                handled = self.callable(*args, **self.merged_args(kwargs)) 
    207163                if handled: 
    208164                    return cherrypy.response.body 
     
    212168        return deco 
    213169     
    214     def setup(self, conf=None): 
    215         """Hook this tool into cherrypy.request using the given conf
     170    def setup(self): 
     171        """Hook this tool into cherrypy.request
    216172         
    217173        The standard CherryPy request object will automatically call this 
    218174        method when the tool is "turned on" in config. 
    219175        """ 
    220         conf = conf or {} 
    221176        def wrapper(): 
    222             if self.callable(**conf): 
     177            if self.callable(**self.merged_args()): 
    223178                cherrypy.request.dispatch = None 
    224179        # Don't pass conf (or our wrapper will get wrapped!) 
     
    232187        Tool.__init__(self, None, callable, name) 
    233188     
    234     def setup(self, conf=None): 
    235         """Hook this tool into cherrypy.request using the given conf
     189    def setup(self): 
     190        """Hook this tool into cherrypy.request
    236191         
    237192        The standard CherryPy request object will automatically call this 
     
    239194        """ 
    240195        def wrapper(): 
    241             self.callable(**conf
     196            self.callable(**self.merged_args()
    242197        cherrypy.request.error_response = wrapper 
    243198 
     
    253208log_tracebacks = Tool('before_error_response', cptools.log_traceback) 
    254209log_headers = Tool('before_error_response', cptools.log_request_headers) 
    255  
    256 _redirect = cptools.redirect 
    257 class ErrorRedirect(Tool): 
    258     """Tool to redirect on error.""" 
    259      
    260     def __init__(self, url): 
    261         Tool.__init__(self, None, _redirect, "ErrorRedirect") 
    262         self.url = url 
    263      
    264     def setup(self, conf=None): 
    265         """Hook this tool into cherrypy.request using the given conf. 
    266          
    267         The standard CherryPy request object will automatically call this 
    268         method when the tool is "turned on" in config. 
    269         """ 
    270         c = {'url': self.url} 
    271         c.update(conf or {}) 
    272         def wrapper(): 
    273             self.callable(**c) 
    274         cherrypy.request.error_response = wrapper 
    275  
     210err_redirect = ErrorTool(cptools.redirect, 'err_redirect') 
    276211del cptools 
    277212 
     
    284219from cherrypy.lib import static 
    285220class _StaticDirTool(MainTool): 
    286     def setup(self, conf=None): 
     221    def setup(self): 
    287222        """Hook this tool into cherrypy.request using the given conf.""" 
    288         # Stick the section where "dir" was defined into the params 
    289         conf = conf or {} 
    290         conf['section'] = cherrypy.config.get('tools.staticdir.dir', 
    291                                               return_section=True) 
    292         MainTool.setup(self, conf) 
     223        # Stick the section where "dir" was defined into the params. 
     224        conf = self.merged_args() 
     225        conf['section'] = cherrypy.config.request_config_section('tools.staticdir.dir') 
     226        def wrapper(): 
     227            if self.callable(**conf): 
     228                cherrypy.request.dispatch = None 
     229        # Don't pass conf (or our wrapper will get wrapped!) 
     230        cherrypy.request.hooks.attach(self.point, wrapper) 
    293231staticdir = _StaticDirTool(static.staticdir) 
    294232staticfile = MainTool(static.staticfile) 
     
    306244        def deco(f): 
    307245            def wrapper(*a, **kw): 
     246                conf = cherrypy.request.toolmap.get(self.name, {}).copy() 
     247                conf.update(kwargs) 
     248                 
    308249                s = cherrypy.request._session = _sessions.Session() 
    309                 for k, v in merged_config(self.name, kwargs).iteritems(): 
     250                for k, v in conf.iteritems(): 
    310251                    setattr(s, str(k), v) 
    311252                s.init() 
     
    320261        return deco 
    321262     
    322     def setup(self, conf=None): 
     263    def setup(self): 
    323264        """Hook this tool into cherrypy.request using the given conf. 
    324265         
     
    326267        method when the tool is "turned on" in config. 
    327268        """ 
    328         conf = conf or {} 
    329269        def init(): 
     270            conf = cherrypy.request.toolmap.get(self.name, {}) 
     271             
    330272            s = cherrypy.request._session = _sessions.Session() 
    331273            for k, v in conf.iteritems(): 
     
    368310         
    369311        body = handler(*(vpath + rpcparams), **request.params) 
    370         conf = tool_config().get("xmlrpc", {}) 
     312        conf = cherrypy.request.toolmap.get("xmlrpc", {}) 
    371313        _xmlrpc.respond(body, 
    372314                        conf.get('encoding', 'utf-8'), 
    373315                        conf.get('allow_none', 0)) 
    374316     
    375     def setup(self, conf=None): 
     317    def setup(self): 
    376318        """Hook this tool into cherrypy.request using the given conf.""" 
    377319        cherrypy.request.dispatch = self.dispatch 

Hosted by WebFaction

Log in as guest/cpguest to create tickets