NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

_cpchecker.py (11356B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\lib\cherrypy\_cpchecker.py
      2 import os
      3 import warnings
      4 import cherrypy
      5 from cherrypy._cpcompat import iteritems, copykeys, builtins
      6 
      7 class Checker(object):
      8     on = True
      9 
     10     def __init__(self):
     11         self._populate_known_types()
     12 
     13     def __call__(self):
     14         if self.on:
     15             oldformatwarning = warnings.formatwarning
     16             warnings.formatwarning = self.formatwarning
     17             try:
     18                 for name in dir(self):
     19                     if name.startswith('check_'):
     20                         method = getattr(self, name)
     21                         if method and hasattr(method, '__call__'):
     22                             method()
     23 
     24             finally:
     25                 warnings.formatwarning = oldformatwarning
     26 
     27     def formatwarning(self, message, category, filename, lineno, line = None):
     28         return 'CherryPy Checker:\n%s\n\n' % message
     29 
     30     global_config_contained_paths = False
     31 
     32     def check_app_config_entries_dont_start_with_script_name(self):
     33         for sn, app in cherrypy.tree.apps.items():
     34             if not isinstance(app, cherrypy.Application):
     35                 continue
     36             if not app.config:
     37                 continue
     38             if sn == '':
     39                 continue
     40             sn_atoms = sn.strip('/').split('/')
     41             for key in app.config.keys():
     42                 key_atoms = key.strip('/').split('/')
     43                 if key_atoms[:len(sn_atoms)] == sn_atoms:
     44                     warnings.warn('The application mounted at %r has config entries that start with its script name: %r' % (sn, key))
     45 
     46     def check_site_config_entries_in_app_config(self):
     47         for sn, app in iteritems(cherrypy.tree.apps):
     48             if not isinstance(app, cherrypy.Application):
     49                 continue
     50             msg = []
     51             for section, entries in iteritems(app.config):
     52                 if section.startswith('/'):
     53                     for key, value in iteritems(entries):
     54                         for n in ('engine.', 'server.', 'tree.', 'checker.'):
     55                             if key.startswith(n):
     56                                 msg.append('[%s] %s = %s' % (section, key, value))
     57 
     58             if msg:
     59                 msg.insert(0, 'The application mounted at %r contains the following config entries, which are only allowed in site-wide config. Move them to a [global] section and pass them to cherrypy.config.update() instead of tree.mount().' % sn)
     60                 warnings.warn(os.linesep.join(msg))
     61 
     62     def check_skipped_app_config(self):
     63         for sn, app in cherrypy.tree.apps.items():
     64             if not isinstance(app, cherrypy.Application):
     65                 continue
     66             if not app.config:
     67                 msg = 'The Application mounted at %r has an empty config.' % sn
     68                 if self.global_config_contained_paths:
     69                     msg += ' It looks like the config you passed to cherrypy.config.update() contains application-specific sections. You must explicitly pass application config via cherrypy.tree.mount(..., config=app_config)'
     70                 warnings.warn(msg)
     71                 return
     72 
     73     def check_app_config_brackets(self):
     74         for sn, app in cherrypy.tree.apps.items():
     75             if not isinstance(app, cherrypy.Application):
     76                 continue
     77             if not app.config:
     78                 continue
     79             for key in app.config.keys():
     80                 if key.startswith('[') or key.endswith(']'):
     81                     warnings.warn('The application mounted at %r has config section names with extraneous brackets: %r. Config *files* need brackets; config *dicts* (e.g. passed to tree.mount) do not.' % (sn, key))
     82 
     83     def check_static_paths(self):
     84         request = cherrypy.request
     85         for sn, app in cherrypy.tree.apps.items():
     86             if not isinstance(app, cherrypy.Application):
     87                 continue
     88             request.app = app
     89             for section in app.config:
     90                 request.get_resource(section + '/dummy.html')
     91                 conf = request.config.get
     92                 if conf('tools.staticdir.on', False):
     93                     msg = ''
     94                     root = conf('tools.staticdir.root')
     95                     dir = conf('tools.staticdir.dir')
     96                     if dir is None:
     97                         msg = 'tools.staticdir.dir is not set.'
     98                     else:
     99                         fulldir = ''
    100                         if os.path.isabs(dir):
    101                             fulldir = dir
    102                             if root:
    103                                 msg = 'dir is an absolute path, even though a root is provided.'
    104                                 testdir = os.path.join(root, dir[1:])
    105                                 if os.path.exists(testdir):
    106                                     msg += '\nIf you meant to serve the filesystem folder at %r, remove the leading slash from dir.' % testdir
    107                         elif not root:
    108                             msg = 'dir is a relative path and no root provided.'
    109                         else:
    110                             fulldir = os.path.join(root, dir)
    111                             if not os.path.isabs(fulldir):
    112                                 msg = '%r is not an absolute path.' % fulldir
    113                         if fulldir and not os.path.exists(fulldir):
    114                             if msg:
    115                                 msg += '\n'
    116                             msg += '%r (root + dir) is not an existing filesystem path.' % fulldir
    117                     if msg:
    118                         warnings.warn('%s\nsection: [%s]\nroot: %r\ndir: %r' % (msg,
    119                          section,
    120                          root,
    121                          dir))
    122 
    123     obsolete = {'server.default_content_type': 'tools.response_headers.headers',
    124      'log_access_file': 'log.access_file',
    125      'log_config_options': None,
    126      'log_file': 'log.error_file',
    127      'log_file_not_found': None,
    128      'log_request_headers': 'tools.log_headers.on',
    129      'log_to_screen': 'log.screen',
    130      'show_tracebacks': 'request.show_tracebacks',
    131      'throw_errors': 'request.throw_errors',
    132      'profiler.on': 'cherrypy.tree.mount(profiler.make_app(cherrypy.Application(Root())))'}
    133     deprecated = {}
    134 
    135     def _compat(self, config):
    136         for section, conf in config.items():
    137             if isinstance(conf, dict):
    138                 for k, v in conf.items():
    139                     if k in self.obsolete:
    140                         warnings.warn('%r is obsolete. Use %r instead.\nsection: [%s]' % (k, self.obsolete[k], section))
    141                     elif k in self.deprecated:
    142                         warnings.warn('%r is deprecated. Use %r instead.\nsection: [%s]' % (k, self.deprecated[k], section))
    143 
    144             elif section in self.obsolete:
    145                 warnings.warn('%r is obsolete. Use %r instead.' % (section, self.obsolete[section]))
    146             elif section in self.deprecated:
    147                 warnings.warn('%r is deprecated. Use %r instead.' % (section, self.deprecated[section]))
    148 
    149     def check_compatibility(self):
    150         self._compat(cherrypy.config)
    151         for sn, app in cherrypy.tree.apps.items():
    152             if not isinstance(app, cherrypy.Application):
    153                 continue
    154             self._compat(app.config)
    155 
    156     extra_config_namespaces = []
    157 
    158     def _known_ns(self, app):
    159         ns = ['wsgi']
    160         ns.extend(copykeys(app.toolboxes))
    161         ns.extend(copykeys(app.namespaces))
    162         ns.extend(copykeys(app.request_class.namespaces))
    163         ns.extend(copykeys(cherrypy.config.namespaces))
    164         ns += self.extra_config_namespaces
    165         for section, conf in app.config.items():
    166             is_path_section = section.startswith('/')
    167             if is_path_section and isinstance(conf, dict):
    168                 for k, v in conf.items():
    169                     atoms = k.split('.')
    170                     if len(atoms) > 1:
    171                         if atoms[0] not in ns:
    172                             if atoms[0] == 'cherrypy' and atoms[1] in ns:
    173                                 msg = 'The config entry %r is invalid; try %r instead.\nsection: [%s]' % (k, '.'.join(atoms[1:]), section)
    174                             else:
    175                                 msg = 'The config entry %r is invalid, because the %r config namespace is unknown.\nsection: [%s]' % (k, atoms[0], section)
    176                             warnings.warn(msg)
    177                         elif atoms[0] == 'tools':
    178                             if atoms[1] not in dir(cherrypy.tools):
    179                                 msg = 'The config entry %r may be invalid, because the %r tool was not found.\nsection: [%s]' % (k, atoms[1], section)
    180                                 warnings.warn(msg)
    181 
    182     def check_config_namespaces(self):
    183         for sn, app in cherrypy.tree.apps.items():
    184             if not isinstance(app, cherrypy.Application):
    185                 continue
    186             self._known_ns(app)
    187 
    188     known_config_types = {}
    189 
    190     def _populate_known_types(self):
    191         b = [ x for x in vars(builtins).values() if type(x) is type(str) ]
    192 
    193         def traverse(obj, namespace):
    194             for name in dir(obj):
    195                 if name == 'body_params':
    196                     continue
    197                 vtype = type(getattr(obj, name, None))
    198                 if vtype in b:
    199                     self.known_config_types[namespace + '.' + name] = vtype
    200 
    201         traverse(cherrypy.request, 'request')
    202         traverse(cherrypy.response, 'response')
    203         traverse(cherrypy.server, 'server')
    204         traverse(cherrypy.engine, 'engine')
    205         traverse(cherrypy.log, 'log')
    206 
    207     def _known_types(self, config):
    208         msg = 'The config entry %r in section %r is of type %r, which does not match the expected type %r.'
    209         for section, conf in config.items():
    210             if isinstance(conf, dict):
    211                 for k, v in conf.items():
    212                     if v is not None:
    213                         expected_type = self.known_config_types.get(k, None)
    214                         vtype = type(v)
    215                         if expected_type and vtype != expected_type:
    216                             warnings.warn(msg % (k,
    217                              section,
    218                              vtype.__name__,
    219                              expected_type.__name__))
    220 
    221             else:
    222                 k, v = section, conf
    223                 if v is not None:
    224                     expected_type = self.known_config_types.get(k, None)
    225                     vtype = type(v)
    226                     if expected_type and vtype != expected_type:
    227                         warnings.warn(msg % (k,
    228                          section,
    229                          vtype.__name__,
    230                          expected_type.__name__))
    231 
    232     def check_config_types(self):
    233         self._known_types(cherrypy.config)
    234         for sn, app in cherrypy.tree.apps.items():
    235             if not isinstance(app, cherrypy.Application):
    236                 continue
    237             self._known_types(app.config)
    238 
    239     def check_localhost(self):
    240         for k, v in cherrypy.config.items():
    241             if k == 'server.socket_host' and v == 'localhost':
    242                 warnings.warn("The use of 'localhost' as a socket host can cause problems on newer systems, since 'localhost' can map to either an IPv4 or an IPv6 address. You should use '127.0.0.1' or '[::1]' instead.")