📄 importer.py
字号:
# vim: set sw=4 expandtab : # # Copyright 2004 Apache Software Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you # may not use this file except in compliance with the License. You # may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. See the License for the specific language governing # permissions and limitations under the License. # # Originally developed by Gregory Trubetskoy. # # The code in this file originally donated by Graham Dumpleton. # # $Id: importer.py 481741 2006-12-03 09:14:06Z grahamd $from mod_python import apachefrom mod_python import publisherimport osimport sysimport newimport typesimport pdbimport impimport md5import timeimport stringimport StringIOimport tracebackimport cgitry: import threadingexcept: import dummy_threading as threading# Define a transient per request modules cache. This is# not the same as the true global modules cache used by# the module importer. Instead, the per request modules# cache is where references to modules loaded in order# to satisfy the requirements of a specific request are# stored for the life of that request. Such a cache is# required to ensure that two distinct bits of code that# load the same module do in fact use the same instance# of the module and that an update of the code for a# module on disk doesn't cause the latter handler code# to load its own separate instance. This is in part# necessary because the module loader does not reload a# module on top of the old module, but loads the new# instance into a clean module.class _module_cache(dict): pass_request_modules_cache = {}def _cleanup_request_modules_cache(thread=None): thread = thread or threading.currentThread() _request_modules_cache.pop(thread, None)def _setup_request_modules_cache(req=None): thread = threading.currentThread() if not _request_modules_cache.has_key(thread): _request_modules_cache[thread] = _module_cache() _request_modules_cache[thread].generation = 0 _request_modules_cache[thread].ctime = 0 if req: req.register_cleanup(_cleanup_request_modules_cache, thread)def _get_request_modules_cache(): thread = threading.currentThread() return _request_modules_cache.get(thread, None)def request_modules_graph(verbose=0): output = StringIO.StringIO() modules = _get_request_modules_cache() print >> output, 'digraph REQUEST {' print >> output, 'node [shape=box];' for module in modules.values(): name = module.__name__ filename = module.__file__ if verbose: cache = module.__mp_info__.cache ctime = time.asctime(time.localtime(cache.ctime)) mtime = time.asctime(time.localtime(cache.mtime)) atime = time.asctime(time.localtime(cache.atime)) generation = cache.generation direct = cache.direct indirect = cache.indirect path = module.__mp_path__ message = '%s [label="%s\\nmtime = %s\\nctime = %s\\natime = %s\\n' message += 'generation = %d, direct = %d, indirect = %d\\n' message += 'path = %s"];' print >> output, message % (name, filename, mtime, ctime, atime, \ generation, direct, indirect, path) else: message = '%s [label="%s"];' print >> output, message % (name, filename) children = module.__mp_info__.children for child_name in children: print >> output, '%s -> %s' % (name, child_name) print >> output, '}' return output.getvalue()apache.request_modules_graph = request_modules_graph# Define a transient per request cache into which# the currently active configuration and handler root# directory pertaining to a request is stored. This is# done so that it can be accessed directly from the# module importer function to obtain configuration# settings indicating if logging and module reloading is# enabled and to determine where to look for modules._current_cache = {}def _setup_current_cache(config, options, directory): thread = threading.currentThread() if directory: directory = os.path.normpath(directory) cache = _current_cache.get(thread, (None, None, None)) if config is None and options is None: del _current_cache[thread] else: _current_cache[thread] = (config, options, directory) return cachedef get_current_config(): thread = threading.currentThread() config, options, directory = _current_cache.get(thread, (apache.main_server.get_config(), None, None)) return configdef get_current_options(): thread = threading.currentThread() config, options, directory = _current_cache.get(thread, (None, apache.main_server.get_options(), None)) return optionsdef get_handler_root(): thread = threading.currentThread() config, options, directory = _current_cache.get(thread, (None, None, None)) return directoryapache.get_current_config = get_current_configapache.get_current_options = get_current_optionsapache.get_handler_root = get_handler_root# Define an alternate implementation of the module# importer system and substitute it for the standard one# in the 'mod_python.apache' module.apache.ximport_module = apache.import_moduledef _parent_context(): # Determine the enclosing module which has called # this function. From that module, return the info # stashed in it by the module importer system. try: raise Exception except: parent = sys.exc_info()[2].tb_frame.f_back while (parent and parent.f_globals.has_key('__file__') and parent.f_globals['__file__'] == __file__): parent = parent.f_back if parent and parent.f_globals.has_key('__mp_info__'): parent_info = parent.f_globals['__mp_info__'] parent_path = parent.f_globals['__mp_path__'] return (parent_info, parent_path) return (None, None)def _find_module(module_name, path): # Search the specified path for a Python code module # of the specified name. Note that only Python code # files with a '.py' extension will be used. Python # packages will be ignored. for directory in path: if directory is not None: if directory == '~': root = get_handler_root() if root is not None: directory = root elif directory[:2] == '~/': root = get_handler_root() if root is not None: directory = os.path.join(root, directory[2:]) file = os.path.join(directory, module_name) + '.py' if os.path.exists(file): return filedef import_module(module_name, autoreload=None, log=None, path=None): file = None import_path = [] # Deal with explicit references to a code file. # Allow some shortcuts for referring to code file # relative to handler root or directory of parent # module. Those relative to parent module are not # allowed if parent module not imported using this # module importing system. if os.path.isabs(module_name): file = module_name elif module_name[:2] == '~/': directory = get_handler_root() if directory is not None: file = os.path.join(directory, module_name[2:]) elif module_name[:2] == './': (parent_info, parent_path) = _parent_context() if parent_info is not None: directory = os.path.dirname(parent_info.file) file = os.path.join(directory, module_name[2:]) elif module_name[:3] == '../': (parent_info, parent_path) = _parent_context() if parent_info is not None: directory = os.path.dirname(parent_info.file) file = os.path.join(directory, module_name) if file is None: # If not an explicit file reference, it is a # module name. Determine the list of directories # that need to be searched for a module code # file. These directories will be, the directory # of the parent if also imported using this # importer and any specified search path. search_path = [] if path is not None: search_path.extend(path) (parent_info, parent_path) = _parent_context() if parent_info is not None: directory = os.path.dirname(parent_info.file) search_path.append(directory) if parent_path is not None: search_path.extend(parent_path) options = get_current_options() if options.has_key('mod_python.importer.path'): directory = eval(options['mod_python.importer.path']) search_path.extend(directory) # Attempt to find the code file for the module # if we have directories to actually search. if search_path: file = _find_module(module_name, search_path) else: # For module imported using explicit path, the # path argument becomes the special embedded # search path for 'import' statement executed # within that module. if path is not None: import_path = path # Was a Python code file able to be identified. if file is not None: # Use the module importing and caching system # to load the code from the specified file. return _global_modules_cache.import_module(file, autoreload, \ log, import_path) else: # If a module code file could not be found, # defer to the standard Python module importer. # We should always end up here if the request # was for a package. return __import__(module_name, {}, {}, ['*'])apache.import_module = import_moduleclass _CacheInfo: def __init__(self, label, file, mtime): self.label = label self.file = file self.mtime = mtime self.module = None self.instance = 0 self.generation = 0 self.children = {} self.path = [] self.atime = 0 self.ctime = 0 self.direct = 0 self.indirect = 0 self.reload = 0 self.lock = threading.Lock()class _InstanceInfo: def __init__(self, label, file, cache): self.label = label self.file = file self.cache = cache self.children = {}class _ModuleCache: _prefix = "_mp_" def __init__(self): self._cache = {} self._lock1 = threading.Lock() self._lock2 = threading.Lock() self._generation = 0 self._frozen = False self._directories = {} def _log_notice(self, msg): pid = os.getpid() name = apache.interpreter flags = apache.APLOG_NOERRNO|apache.APLOG_NOTICE text = "mod_python (pid=%d, interpreter=%s): %s" % (pid, `name`, msg) apache.main_server.log_error(text, flags) def _log_warning(self, msg): pid = os.getpid() name = apache.interpreter flags = apache.APLOG_NOERRNO|apache.APLOG_WARNING text = "mod_python (pid=%d, interpreter=%s): %s" % (pid, `name`, msg) apache.main_server.log_error(text, flags) def _log_exception(self): pid = os.getpid() name = apache.interpreter flags = apache.APLOG_NOERRNO|apache.APLOG_ERR msg = 'Application error' text = "mod_python (pid=%d, interpreter=%s): %s" % (pid, `name`, msg) apache.main_server.log_error(text, flags) etype, evalue, etb = sys.exc_info() for text in traceback.format_exception(etype, evalue, etb): apache.main_server.log_error(text[:-1], flags) etb = None def cached_modules(self): self._lock1.acquire() try: return self._cache.keys() finally: self._lock1.release() def module_info(self, label): self._lock1.acquire() try: return self._cache[label] finally: self._lock1.release() def freeze_modules(self): self._frozen = True
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -