source file: /Library/Python/2.3/site-packages/CherryPy-3.0.1-py2.3.egg/cherrypy/_cpchecker.py
file stats: 133 lines, 81 executed: 60.9% covered
   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 app.config:
  38.                 msg = "The Application mounted at %r has an empty config." % sn
  39.                 if self.global_config_contained_paths:
  40.                     msg += (" It looks like the config you passed to "
  41.                             "cherrypy.config.update() contains application-"
  42.                             "specific sections. You must explicitly pass "
  43.                             "application config via "
  44.                             "cherrypy.tree.mount(..., config=app_config)")
  45.                 warnings.warn(msg)
  46.                 return
  47. 
  48.     def check_static_paths(self):
  49.         # Use the dummy Request object in the main thread.
  50.         request = cherrypy.request
  51.         for sn, app in cherrypy.tree.apps.iteritems():
  52.             request.app = app
  53.             for section in app.config:
  54.                 # get_resource will populate request.config
  55.                 request.get_resource(section + "/dummy.html")
  56.                 conf = request.config.get
  57. 
  58.                 if conf("tools.staticdir.on", False):
  59.                     msg = ""
  60.                     root = conf("tools.staticdir.root")
  61.                     dir = conf("tools.staticdir.dir")
  62.                     if dir is None:
  63.                         msg = "tools.staticdir.dir is not set."
  64.                     else:
  65.                         fulldir = ""
  66.                         if os.path.isabs(dir):
  67.                             fulldir = dir
  68.                             if root:
  69.                                 msg = ("dir is an absolute path, even "
  70.                                        "though a root is provided.")
  71.                                 testdir = os.path.join(root, dir[1:])
  72.                                 if os.path.exists(testdir):
  73.                                     msg += ("\nIf you meant to serve the "
  74.                                             "filesystem folder at %r, remove "
  75.                                             "the leading slash from dir." % testdir)
  76.                         else:
  77.                             if not root:
  78.                                 msg = "dir is a relative path and no root provided."
  79.                             else:
  80.                                 fulldir = os.path.join(root, dir)
  81.                                 if not os.path.isabs(fulldir):
  82.                                     msg = "%r is not an absolute path." % fulldir
  83. 
  84.                         if fulldir and not os.path.exists(fulldir):
  85.                             if msg:
  86.                                 msg += "\n"
  87.                             msg += ("%r (root + dir) is not an existing "
  88.                                     "filesystem path." % fulldir)
  89. 
  90.                     if msg:
  91.                         warnings.warn("%s\nsection: [%s]\nroot: %r\ndir: %r"
  92.                                       % (msg, section, root, dir))
  93. 
  94. 
  95.     # -------------------------- Compatibility -------------------------- #
  96. 
  97.     obsolete = {
  98.         'server.default_content_type': 'tools.response_headers.headers',
  99.         'log_access_file': 'log.access_file',
 100.         'log_config_options': None,
 101.         'log_file': 'log.error_file',
 102.         'log_file_not_found': None,
 103.         'log_request_headers': 'tools.log_headers.on',
 104.         'log_to_screen': 'log.screen',
 105.         'show_tracebacks': 'request.show_tracebacks',
 106.         'throw_errors': 'request.throw_errors',
 107.         'profiler.on': ('cherrypy.tree.mount(profiler.make_app('
 108.                         'cherrypy.Application(Root())))'),
 109.         }
 110. 
 111.     deprecated = {}
 112. 
 113.     def _compat(self, config):
 114.         """Process config and warn on each obsolete or deprecated entry."""
 115.         for section, conf in config.iteritems():
 116.             if isinstance(conf, dict):
 117.                 for k, v in conf.iteritems():
 118.                     if k in self.obsolete:
 119.                         warnings.warn("%r is obsolete. Use %r instead.\n"
 120.                                       "section: [%s]" %
 121.                                       (k, self.obsolete[k], section))
 122.                     elif k in self.deprecated:
 123.                         warnings.warn("%r is deprecated. Use %r instead.\n"
 124.                                       "section: [%s]" %
 125.                                       (k, self.deprecated[k], section))
 126.             else:
 127.                 if section in self.obsolete:
 128.                     warnings.warn("%r is obsolete. Use %r instead."
 129.                                   % (section, self.obsolete[section]))
 130.                 elif section in self.deprecated:
 131.                     warnings.warn("%r is deprecated. Use %r instead."
 132.                                   % (section, self.deprecated[section]))
 133. 
 134.     def check_compatibility(self):
 135.         """Process config and warn on each obsolete or deprecated entry."""
 136.         self._compat(cherrypy.config)
 137.         for sn, app in cherrypy.tree.apps.iteritems():
 138.             self._compat(app.config)
 139. 
 140. 
 141.     # ------------------------ Known Namespaces ------------------------ #
 142. 
 143.     extra_config_namespaces = []
 144. 
 145.     def _known_ns(self, config):
 146.         ns = ["wsgi"]
 147.         ns.extend(cherrypy.engine.request_class.namespaces.keys())
 148.         ns.extend(cherrypy.config.namespaces.keys())
 149.         ns += self.extra_config_namespaces
 150. 
 151.         for section, conf in config.iteritems():
 152.             is_path_section = section.startswith("/")
 153.             if is_path_section and isinstance(conf, dict):
 154.                 for k, v in conf.iteritems():
 155.                     atoms = k.split(".")
 156.                     if len(atoms) > 1:
 157.                         if atoms[0] not in ns:
 158.                             if (atoms[0] == "cherrypy" and atoms[1] in ns):
 159.                                 msg = ("The config entry %r is invalid; "
 160.                                        "try %r instead.\nsection: [%s]"
 161.                                        % (k, ".".join(atoms[1:]), section))
 162.                             else:
 163.                                 msg = ("The config entry %r is invalid, because "
 164.                                        "the %r config namespace is unknown.\n"
 165.                                        "section: [%s]" % (k, atoms[0], section))
 166.                             warnings.warn(msg)
 167. 
 168.     def check_config_namespaces(self):
 169.         """Process config and warn on each unknown config namespace."""
 170.         for sn, app in cherrypy.tree.apps.iteritems():
 171.             self._known_ns(app.config)
 172. 
 173. 
 174.     # -------------------------- Config Types -------------------------- #
 175. 
 176.     known_config_types = {}
 177. 
 178.     def _populate_known_types(self):
 179.         import __builtin__
 180.         builtins = [x for x in vars(__builtin__).values()
 181.                     if type(x) is type(str)]
 182. 
 183.         def traverse(obj, namespace):
 184.             for name in dir(obj):
 185.                 vtype = type(getattr(obj, name, None))
 186.                 if vtype in builtins:
 187.                     self.known_config_types[namespace + "." + name] = vtype
 188. 
 189.         traverse(cherrypy.request, "request")
 190.         traverse(cherrypy.response, "response")
 191.         traverse(cherrypy.server, "server")
 192.         traverse(cherrypy.engine, "engine")
 193.         traverse(cherrypy.log, "log")
 194. 
 195.     def _known_types(self, config):
 196.         msg = ("The config entry %r in section %r is of type %r, "
 197.                "which does not match the expected type %r.")
 198. 
 199.         for section, conf in config.iteritems():
 200.             if isinstance(conf, dict):
 201.                 for k, v in conf.iteritems():
 202.                     if v is not None:
 203.                         expected_type = self.known_config_types.get(k, None)
 204.                         vtype = type(v)
 205.                         if expected_type and vtype != expected_type:
 206.                             warnings.warn(msg % (k, section, vtype.__name__,
 207.                                                  expected_type.__name__))
 208.             else:
 209.                 k, v = section, conf
 210.                 if v is not None:
 211.                     expected_type = self.known_config_types.get(k, None)
 212.                     vtype = type(v)
 213.                     if expected_type and vtype != expected_type:
 214.                         warnings.warn(msg % (k, section, vtype.__name__,
 215.                                              expected_type.__name__))
 216. 
 217.     def check_config_types(self):
 218.         """Assert that config values are of the same type as default values."""
 219.         self._known_types(cherrypy.config)
 220.         for sn, app in cherrypy.tree.apps.iteritems():
 221.             self._known_types(app.config)
 222. 
 223.