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

root/branches/cherrypy-3.0.x/cherrypy/_cpchecker.py

Revision 1714 (checked in by fumanchu, 1 year ago)

Fix for checker breakage when using grafted WSGI apps.

  • Property svn:eol-style set to native
Line 
1 import os
2 import warnings
3
4 import cherrypy
5
6
7 class Checker(object):
8    
9     on = True
10    
11     def __init__(self):
12         self._populate_known_types()
13    
14     def __call__(self):
15         """Run all check_* methods."""
16         if self.on:
17             oldformatwarning = warnings.formatwarning
18             warnings.formatwarning = self.formatwarning
19             try:
20                 for name in dir(self):
21                     if name.startswith("check_"):
22                         method = getattr(self, name)
23                         if method and callable(method):
24                             method()
25             finally:
26                 warnings.formatwarning = oldformatwarning
27    
28     def formatwarning(self, message, category, filename, lineno):
29         """Function to format a warning."""
30         return "CherryPy Checker:\n%s\n\n" % message
31    
32     # This value should be set inside _cpconfig.
33     global_config_contained_paths = False
34    
35     def check_skipped_app_config(self):
36         for sn, app in cherrypy.tree.apps.iteritems():
37             if not isinstance(app, cherrypy.Application):
38                 continue
39             if not app.config:
40                 msg = "The Application mounted at %r has an empty config." % sn
41                 if self.global_config_contained_paths:
42                     msg += (" It looks like the config you passed to "
43                             "cherrypy.config.update() contains application-"
44                             "specific sections. You must explicitly pass "
45                             "application config via "
46                             "cherrypy.tree.mount(..., config=app_config)")
47                 warnings.warn(msg)
48                 return
49    
50     def check_static_paths(self):
51         # Use the dummy Request object in the main thread.
52         request = cherrypy.request
53         for sn, app in cherrypy.tree.apps.iteritems():
54             if not isinstance(app, cherrypy.Application):
55                 continue
56             request.app = app
57             for section in app.config:
58                 # get_resource will populate request.config
59                 request.get_resource(section + "/dummy.html")
60                 conf = request.config.get
61                
62                 if conf("tools.staticdir.on", False):
63                     msg = ""
64                     root = conf("tools.staticdir.root")
65                     dir = conf("tools.staticdir.dir")
66                     if dir is None:
67                         msg = "tools.staticdir.dir is not set."
68                     else:
69                         fulldir = ""
70                         if os.path.isabs(dir):
71                             fulldir = dir
72                             if root:
73                                 msg = ("dir is an absolute path, even "
74                                        "though a root is provided.")
75                                 testdir = os.path.join(root, dir[1:])
76                                 if os.path.exists(testdir):
77                                     msg += ("\nIf you meant to serve the "
78                                             "filesystem folder at %r, remove "
79                                             "the leading slash from dir." % testdir)
80                         else:
81                             if not root:
82                                 msg = "dir is a relative path and no root provided."
83                             else:
84                                 fulldir = os.path.join(root, dir)
85                                 if not os.path.isabs(fulldir):
86                                     msg = "%r is not an absolute path." % fulldir
87                        
88                         if fulldir and not os.path.exists(fulldir):
89                             if msg:
90                                 msg += "\n"
91                             msg += ("%r (root + dir) is not an existing "
92                                     "filesystem path." % fulldir)
93                    
94                     if msg:
95                         warnings.warn("%s\nsection: [%s]\nroot: %r\ndir: %r"
96                                       % (msg, section, root, dir))
97    
98    
99     # -------------------------- Compatibility -------------------------- #
100    
101     obsolete = {
102         'server.default_content_type': 'tools.response_headers.headers',
103         'log_access_file': 'log.access_file',
104         'log_config_options': None,
105         'log_file': 'log.error_file',
106         'log_file_not_found': None,
107         'log_request_headers': 'tools.log_headers.on',
108         'log_to_screen': 'log.screen',
109         'show_tracebacks': 'request.show_tracebacks',
110         'throw_errors': 'request.throw_errors',
111         'profiler.on': ('cherrypy.tree.mount(profiler.make_app('
112                         'cherrypy.Application(Root())))'),
113         }
114    
115     deprecated = {}
116    
117     def _compat(self, config):
118         """Process config and warn on each obsolete or deprecated entry."""
119         for section, conf in config.iteritems():
120             if isinstance(conf, dict):
121                 for k, v in conf.iteritems():
122                     if k in self.obsolete:
123                         warnings.warn("%r is obsolete. Use %r instead.\n"
124                                       "section: [%s]" %
125                                       (k, self.obsolete[k], section))
126                     elif k in self.deprecated:
127                         warnings.warn("%r is deprecated. Use %r instead.\n"
128                                       "section: [%s]" %
129                                       (k, self.deprecated[k], section))
130             else:
131                 if section in self.obsolete:
132                     warnings.warn("%r is obsolete. Use %r instead."
133                                   % (section, self.obsolete[section]))
134                 elif section in self.deprecated:
135                     warnings.warn("%r is deprecated. Use %r instead."
136                                   % (section, self.deprecated[section]))
137    
138     def check_compatibility(self):
139         """Process config and warn on each obsolete or deprecated entry."""
140         self._compat(cherrypy.config)
141         for sn, app in cherrypy.tree.apps.iteritems():
142             if not isinstance(app, cherrypy.Application):
143                 continue
144             self._compat(app.config)
145    
146    
147     # ------------------------ Known Namespaces ------------------------ #
148    
149     extra_config_namespaces = []
150    
151     def _known_ns(self, config):
152         ns = ["wsgi"]
153         ns.extend(cherrypy.engine.request_class.namespaces.keys())
154         ns.extend(cherrypy.config.namespaces.keys())
155         ns += self.extra_config_namespaces
156        
157         for section, conf in config.iteritems():
158             is_path_section = section.startswith("/")
159             if is_path_section and isinstance(conf, dict):
160                 for k, v in conf.iteritems():
161                     atoms = k.split(".")
162                     if len(atoms) > 1:
163                         if atoms[0] not in ns:
164                             # Spit out a special warning if a known
165                             # namespace is preceded by "cherrypy."
166                             if (atoms[0] == "cherrypy" and atoms[1] in ns):
167                                 msg = ("The config entry %r is invalid; "
168                                        "try %r instead.\nsection: [%s]"
169                                        % (k, ".".join(atoms[1:]), section))
170                             else:
171                                 msg = ("The config entry %r is invalid, because "
172                                        "the %r config namespace is unknown.\n"
173                                        "section: [%s]" % (k, atoms[0], section))
174                             warnings.warn(msg)
175                         elif atoms[0] == "tools":
176                             if atoms[1] not in dir(cherrypy.tools):
177                                 msg = ("The config entry %r may be invalid, "
178                                        "because the %r tool was not found.\n"
179                                        "section: [%s]" % (k, atoms[1], section))
180                                 warnings.warn(msg)
181    
182     def check_config_namespaces(self):
183         """Process config and warn on each unknown config namespace."""
184         for sn, app in cherrypy.tree.apps.iteritems():
185             if not isinstance(app, cherrypy.Application):
186                 continue
187             self._known_ns(app.config)
188    
189    
190     # -------------------------- Config Types -------------------------- #
191    
192     known_config_types = {}
193    
194     def _populate_known_types(self):
195         import __builtin__
196         builtins = [x for x in vars(__builtin__).values()
197                     if type(x) is type(str)]
198        
199         def traverse(obj, namespace):
200             for name in dir(obj):
201                 vtype = type(getattr(obj, name, None))
202                 if vtype in builtins:
203                     self.known_config_types[namespace + "." + name] = vtype
204        
205         traverse(cherrypy.request, "request")
206         traverse(cherrypy.response, "response")
207         traverse(cherrypy.server, "server")
208         traverse(cherrypy.engine, "engine")
209         traverse(cherrypy.log, "log")
210    
211     def _known_types(self, config):
212         msg = ("The config entry %r in section %r is of type %r, "
213                "which does not match the expected type %r.")
214        
215         for section, conf in config.iteritems():
216             if isinstance(conf, dict):
217                 for k, v in conf.iteritems():
218                     if v is not None:
219                         expected_type = self.known_config_types.get(k, None)
220                         vtype = type(v)
221                         if expected_type and vtype != expected_type:
222                             warnings.warn(msg % (k, section, vtype.__name__,
223                                                  expected_type.__name__))
224             else:
225                 k, v = section, conf
226                 if v is not None:
227                     expected_type = self.known_config_types.get(k, None)
228                     vtype = type(v)
229                     if expected_type and vtype != expected_type:
230                         warnings.warn(msg % (k, section, vtype.__name__,
231                                              expected_type.__name__))
232    
233     def check_config_types(self):
234         """Assert that config values are of the same type as default values."""
235         self._known_types(cherrypy.config)
236         for sn, app in cherrypy.tree.apps.iteritems():
237             if not isinstance(app, cherrypy.Application):
238                 continue
239             self._known_types(app.config)
240
241
Note: See TracBrowser for help on using the browser.

Hosted by WebFaction

Log in as guest/cpguest to create tickets