| 1 |
import os |
|---|
| 2 |
import warnings |
|---|
| 3 |
|
|---|
| 4 |
import cherrypy |
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 |
class Checker(object): |
|---|
| 8 |
|
|---|
| 9 |
global_config_contained_paths = False |
|---|
| 10 |
|
|---|
| 11 |
def __call__(self): |
|---|
| 12 |
oldformatwarning = warnings.formatwarning |
|---|
| 13 |
warnings.formatwarning = self.formatwarning |
|---|
| 14 |
try: |
|---|
| 15 |
for name in dir(self): |
|---|
| 16 |
if name.startswith("check_"): |
|---|
| 17 |
method = getattr(self, name) |
|---|
| 18 |
if method and callable(method): |
|---|
| 19 |
method() |
|---|
| 20 |
finally: |
|---|
| 21 |
warnings.formatwarning = oldformatwarning |
|---|
| 22 |
|
|---|
| 23 |
def formatwarning(self, message, category, filename, lineno): |
|---|
| 24 |
"""Function to format a warning.""" |
|---|
| 25 |
return "CherryPy Checker:\n%s\n\n" % message |
|---|
| 26 |
|
|---|
| 27 |
def check_skipped_app_config(self): |
|---|
| 28 |
for sn, app in cherrypy.tree.apps.iteritems(): |
|---|
| 29 |
if not app.config: |
|---|
| 30 |
msg = "The Application mounted at %r has an empty config." % sn |
|---|
| 31 |
if self.global_config_contained_paths: |
|---|
| 32 |
msg += (" It looks like the config you passed to " |
|---|
| 33 |
"cherrypy.config.update() contains application-" |
|---|
| 34 |
"specific sections. You must explicitly pass " |
|---|
| 35 |
"application config via " |
|---|
| 36 |
"cherrypy.tree.mount(..., config=app_config)") |
|---|
| 37 |
warnings.warn(msg) |
|---|
| 38 |
return |
|---|
| 39 |
|
|---|
| 40 |
def check_static_paths(self): |
|---|
| 41 |
|
|---|
| 42 |
request = cherrypy.request |
|---|
| 43 |
for sn, app in cherrypy.tree.apps.iteritems(): |
|---|
| 44 |
request.app = app |
|---|
| 45 |
for section in app.config: |
|---|
| 46 |
|
|---|
| 47 |
request.get_resource(section + "/dummy.html") |
|---|
| 48 |
conf = request.config.get |
|---|
| 49 |
|
|---|
| 50 |
if conf("tools.staticdir.on", False): |
|---|
| 51 |
msg = "" |
|---|
| 52 |
root = conf("tools.staticdir.root") |
|---|
| 53 |
dir = conf("tools.staticdir.dir") |
|---|
| 54 |
if dir is None: |
|---|
| 55 |
msg = "tools.staticdir.dir is not set." |
|---|
| 56 |
else: |
|---|
| 57 |
fulldir = "" |
|---|
| 58 |
if os.path.isabs(dir): |
|---|
| 59 |
fulldir = dir |
|---|
| 60 |
if root: |
|---|
| 61 |
msg = "dir is an absolute path, even though a root is provided." |
|---|
| 62 |
testdir = os.path.join(root, dir[1:]) |
|---|
| 63 |
if os.path.exists(testdir): |
|---|
| 64 |
msg += ("\nIf you meant to serve the filesystem folder at %r, " |
|---|
| 65 |
"remove the leading slash from dir." % testdir) |
|---|
| 66 |
else: |
|---|
| 67 |
if not root: |
|---|
| 68 |
msg = "dir is a relative path and no root provided." |
|---|
| 69 |
else: |
|---|
| 70 |
fulldir = os.path.join(root, dir) |
|---|
| 71 |
if not os.path.isabs(fulldir): |
|---|
| 72 |
msg = "%r is not an absolute path." % fulldir |
|---|
| 73 |
|
|---|
| 74 |
if fulldir and not os.path.exists(fulldir): |
|---|
| 75 |
if msg: |
|---|
| 76 |
msg += "\n" |
|---|
| 77 |
msg += "%r (root + dir) is not an existing filesystem path." % fulldir |
|---|
| 78 |
|
|---|
| 79 |
if msg: |
|---|
| 80 |
warnings.warn("%s\nsection: [%s]\nroot: %r\ndir: %r" |
|---|
| 81 |
% (msg, section, root, dir)) |
|---|
| 82 |
|
|---|
| 83 |
obsolete = { |
|---|
| 84 |
'server.default_content_type': 'tools.response_headers.headers', |
|---|
| 85 |
'log_access_file': 'log.access_file', |
|---|
| 86 |
'log_config_options': None, |
|---|
| 87 |
'log_file': 'log.error_file', |
|---|
| 88 |
'log_file_not_found': None, |
|---|
| 89 |
'log_request_headers': 'tools.log_headers.on', |
|---|
| 90 |
'log_to_screen': 'log.screen', |
|---|
| 91 |
'show_tracebacks': 'request.show_tracebacks', |
|---|
| 92 |
'throw_errors': 'request.throw_errors', |
|---|
| 93 |
'profiler.on': 'cherrypy.tree.mount(profiler.make_app(cherrypy.Application(Root())))', |
|---|
| 94 |
} |
|---|
| 95 |
|
|---|
| 96 |
deprecated = {} |
|---|
| 97 |
|
|---|
| 98 |
def _compat(self, config): |
|---|
| 99 |
"""Process config and warn on each obsolete or deprecated entry.""" |
|---|
| 100 |
for section, conf in config.iteritems(): |
|---|
| 101 |
if isinstance(conf, dict): |
|---|
| 102 |
for k, v in conf.iteritems(): |
|---|
| 103 |
if k in self.obsolete: |
|---|
| 104 |
warnings.warn("%r is obsolete. Use %r instead.\n" |
|---|
| 105 |
"section: [%s]" % (k, self.obsolete[k], section)) |
|---|
| 106 |
elif k in self.deprecated: |
|---|
| 107 |
warnings.warn("%r is deprecated. Use %r instead.\n" |
|---|
| 108 |
"section: [%s]" % (k, self.deprecated[k], section)) |
|---|
| 109 |
else: |
|---|
| 110 |
if section in self.obsolete: |
|---|
| 111 |
warnings.warn("%r is obsolete. Use %r instead." |
|---|
| 112 |
% (section, self.obsolete[section])) |
|---|
| 113 |
elif section in self.deprecated: |
|---|
| 114 |
warnings.warn("%r is deprecated. Use %r instead." |
|---|
| 115 |
% (section, self.deprecated[section])) |
|---|
| 116 |
|
|---|
| 117 |
def check_compatibility(self): |
|---|
| 118 |
"""Process config and warn on each obsolete or deprecated entry.""" |
|---|
| 119 |
self._compat(cherrypy.config) |
|---|
| 120 |
for sn, app in cherrypy.tree.apps.iteritems(): |
|---|
| 121 |
self._compat(app.config) |
|---|
| 122 |
|
|---|
| 123 |
known_config_namespaces = ["engine", "hooks", "log", "request", |
|---|
| 124 |
"response", "server", "tools", "wsgi"] |
|---|
| 125 |
|
|---|
| 126 |
def _known_ns(self, config): |
|---|
| 127 |
for section, conf in config.iteritems(): |
|---|
| 128 |
is_path_section = section.startswith("/") |
|---|
| 129 |
if is_path_section and isinstance(conf, dict): |
|---|
| 130 |
for k, v in conf.iteritems(): |
|---|
| 131 |
atoms = k.split(".") |
|---|
| 132 |
if len(atoms) > 1: |
|---|
| 133 |
if atoms[0] not in self.known_config_namespaces: |
|---|
| 134 |
if atoms[0] == "cherrypy" and atoms[1] in self.known_config_namespaces: |
|---|
| 135 |
msg = ("The config entry %r is invalid; " |
|---|
| 136 |
"try %r instead.\nsection: [%s]" |
|---|
| 137 |
% (k, ".".join(atoms[1:]), section)) |
|---|
| 138 |
else: |
|---|
| 139 |
msg = ("The config entry %r is invalid, because " |
|---|
| 140 |
"the %r config namespace is unknown.\n" |
|---|
| 141 |
"section: [%s]" % (k, atoms[0], section)) |
|---|
| 142 |
warnings.warn(msg) |
|---|
| 143 |
|
|---|
| 144 |
def check_config_namespaces(self): |
|---|
| 145 |
"""Process config and warn on each unknown config namespace.""" |
|---|
| 146 |
for sn, app in cherrypy.tree.apps.iteritems(): |
|---|
| 147 |
self._known_ns(app.config) |
|---|