def import_module(module_name, req=None, path=None): """ Get the module to handle the request. If autoreload is on, then the module will be reloaded if it has changed since the last import. """ # Get options debug, autoreload = 0, 1 if req: config = req.get_config() debug = config.has_key("PythonDebug") if config.has_key("PythonAutoReload"): autoreload = int(config["PythonAutoReload"]) # (Re)import if sys.modules.has_key(module_name): # The module has been imported already module = sys.modules[module_name] # but is it in the path? file = module.__dict__.get("__file__") if not file or (path and not os.path.dirname(file) in path): raise SERVER_RETURN, HTTP_NOT_FOUND if autoreload: oldmtime = module.__dict__.get("__mtime__", 0) mtime = module_mtime(module) else: mtime, oldmtime = 0, 0 else: mtime, oldmtime = 0, -1 if mtime > oldmtime: # Import the module if debug: s = 'mod_python: (Re)importing %s from %s' % (module_name, path) _apache.log_error(s, APLOG_NOERRNO|APLOG_NOTICE) parts = string.split(module_name, '.') for i in range(len(parts)): f, p, d = imp.find_module(parts[i], path) try: mname = string.join(parts[:i+1], ".") module = imp.load_module(mname, f, p, d) finally: if f: f.close() if hasattr(module, "__path__"): path = module.__path__ if mtime == 0: mtime = module_mtime(module) module.__mtime__ = mtime return module
def ReportError(self, etype, evalue, etb, req=None, filter=None, srv=None, phase="N/A", hname="N/A", debug=0): """ This function is only used when debugging is on. It sends the output similar to what you'd see when using Python interactively to the browser """ try: # try/finally try: # try/except if str(etype) == "exceptions.IOError" \ and str(evalue)[:5] == "Write": # if this is an IOError while writing to client, # it is probably better not to try to write to the cleint # even if debug is on. debug = 0 # write to log for e in traceback.format_exception(etype, evalue, etb): s = "%s %s: %s" % (phase, hname, e[:-1]) if req: req.log_error(s, APLOG_NOERRNO|APLOG_ERR) else: _apache.log_error(s, APLOG_NOERRNO|APLOG_ERR, srv) if not debug or not req: return HTTP_INTERNAL_SERVER_ERROR else: # write to client req.status = HTTP_INTERNAL_SERVER_ERROR req.content_type = 'text/html' s = '\n<pre>\nMod_python error: "%s %s"\n\n' % (phase, hname) for e in traceback.format_exception(etype, evalue, etb): s = s + cgi.escape(e) + '\n' s = s + "</pre>\n" if filter: filter.write(s) filter.flush() else: req.write(s) return DONE except: # last try traceback.print_exc() sys.stderr.flush() finally: # erase the traceback etb = None
def ReportError(self, etype, evalue, etb, req=None, filter=None, srv=None, phase="N/A", hname="N/A", debug=0): """ This function is only used when debugging is on. It sends the output similar to what you'd see when using Python interactively to the browser """ try: # try/finally try: # try/except if str(etype) == "exceptions.IOError" \ and str(evalue)[:5] == "Write": # if this is an IOError while writing to client, # it is probably better not to try to write to the cleint # even if debug is on. debug = 0 # write to log for e in traceback.format_exception(etype, evalue, etb): s = "%s %s: %s" % (phase, hname, e[:-1]) if req: req.log_error(s, APLOG_ERR) else: _apache.log_error(s, APLOG_ERR, srv) if not debug or not req: return HTTP_INTERNAL_SERVER_ERROR else: # write to client req.status = HTTP_INTERNAL_SERVER_ERROR req.content_type = 'text/html' s = '\n<pre>\nMod_python error: "%s %s"\n\n' % (phase, hname) for e in traceback.format_exception(etype, evalue, etb): s = s + escape(e) + '\n' s = s + "</pre>\n" if filter: filter.write(s) filter.flush() else: req.write(s) return DONE except: # last try traceback.print_exc() sys.stderr.flush() finally: # erase the traceback etb = None
def ReportError(self, req, etype, evalue, etb, htype="N/A", hname="N/A", debug=0): """ This function is only used when debugging is on. It sends the output similar to what you'd see when using Python interactively to the browser """ try: if str(etype) == "exceptions.IOError" \ and str(evalue)[:5] == "Write": # if this is an IOError while writing to client, # it is probably better not to try to write to the cleint # even if debug is on. debug = 0 # write to log for e in traceback.format_exception(etype, evalue, etb): s = "%s %s: %s" % (htype, hname, e[:-1]) _apache.log_error(s, APLOG_NOERRNO|APLOG_ERR, req.server) if not debug: return HTTP_INTERNAL_SERVER_ERROR else: # write to client req.content_type = 'text/plain' req.send_http_header() s = '\nMod_python error: "%s %s"\n\n' % (htype, hname) for e in traceback.format_exception(etype, evalue, etb): s = s + e + '\n' req.write(s) return DONE finally: # erase the traceback etb = None
def import_module(module_name, autoreload=1, log=0, path=None): """ Get the module to handle the request. If autoreload is on, then the module will be reloaded if it has changed since the last import. """ # nlehuen: this is a big lock, we'll have to refine it later to get better performance. # For now, we'll concentrate on thread-safety. imp.acquire_lock() try: # (Re)import if sys.modules.has_key(module_name): # The module has been imported already module = sys.modules[module_name] # but is it in the path? file = module.__dict__.get("__file__") # the "and not" part of this condition is to prevent execution # of arbitrary already imported modules, such as os. The # reason we use startswith as opposed to exact match is that # modules inside packages are actually in subdirectories. if not file or (path and not filter(file.startswith, path)): # there is a script by this name already imported, but it's in # a different directory, therefore it's a different script mtime, oldmtime = 0, -1 elif autoreload: oldmtime = module.__dict__.get("__mtime__", 0) mtime = module_mtime(module) else: mtime, oldmtime = 0, 0 else: mtime, oldmtime = 0, -1 if mtime != oldmtime: # Import the module if log: if path: s = "mod_python: (Re)importing module '%s' with path set to '%s'" % (module_name, path) else: s = "mod_python: (Re)importing module '%s'" % module_name _apache.log_error(s, APLOG_NOERRNO|APLOG_NOTICE) parent = None parts = module_name.split('.') for i in range(len(parts)): f, p, d = imp.find_module(parts[i], path) try: mname = ".".join(parts[:i+1]) module = imp.load_module(mname, f, p, d) if parent: setattr(parent,parts[i],module) parent = module finally: if f: f.close() if hasattr(module, "__path__"): path = module.__path__ if mtime == 0: mtime = module_mtime(module) module.__mtime__ = mtime return module finally: imp.release_lock()
def FilterDispatch(self, filter): req = filter.req # config config = req.get_config() debug = int(config.get("PythonDebug", 0)) try: # add the directory to pythonpath if # not there yet, or evaluate pythonpath # and set sys.path to resulting value # if not already done if config.has_key("PythonPath"): _path_cache_lock.acquire() try: pathstring = config["PythonPath"] if not _path_cache.has_key(pathstring): newpath = eval(pathstring) _path_cache[pathstring] = None sys.path[:] = newpath finally: _path_cache_lock.release() else: if filter.dir and (filter.dir not in sys.path): sys.path[:0] = [filter.dir] if not callable(filter.handler): # split module::handler l = filter.handler.split('::', 1) module_name = l[0] if len(l) == 1: # no oject, provide default if filter.is_input: object_str = "inputfilter" else: object_str = "outputfilter" else: object_str = l[1] # import module module = import_module(module_name, autoreload=int(config.get("PythonAutoReload", 1)), log=debug) # find the object object = resolve_object(module, object_str, arg=filter, silent=0) else: object = filter.handler # Only permit debugging using pdb if Apache has # actually been started in single process mode. pdb_debug = int(config.get("PythonEnablePdb", "0")) one_process = exists_config_define("ONE_PROCESS") if pdb_debug and one_process: # Don't use pdb.runcall() as it results in # a bogus 'None' response when pdb session # is quit. With this code the exception # marking that the session has been quit is # propogated back up and it is obvious in # the error message what actually occurred. debugger = pdb.Pdb() debugger.reset() sys.settrace(debugger.trace_dispatch) try: result = object(filter) finally: debugger.quitting = 1 sys.settrace(None) else: result = object(filter) # always flush the filter. without a FLUSH or EOS bucket, # the content is never written to the network. # XXX an alternative is to tell the user to flush() always if not filter.closed: filter.flush() except SERVER_RETURN, value: # SERVER_RETURN indicates a non-local abort from below # with value as (result, status) or (result, None) or result try: if len(value.args) == 2: (result, status) = value.args if status: req.status = status else: result = value.args[0] if type(result) != type(7): s = "Value raised with SERVER_RETURN is invalid. It is a " s = s + "%s, but it must be a tuple or an int." % type(result) _apache.log_error(s, APLOG_NOERRNO|APLOG_ERR, req.server) return except: pass
def import_module(module_name, config=None, path=None): """ Get the module to handle the request. If autoreload is on, then the module will be reloaded if it has changed since the last import. """ # Get options debug, autoreload = 0, 1 if config: debug = config.has_key("PythonDebug") if config.has_key("PythonAutoReload"): autoreload = int(config["PythonAutoReload"]) # (Re)import if sys.modules.has_key(module_name): # The module has been imported already module = sys.modules[module_name] # but is it in the path? file = module.__dict__.get("__file__") # the "and not" part of this condition is to prevent execution # of arbitrary already imported modules, such as os. the # not-so-obvious filter(lambda...) call means: # return entries from path (which is a list) which fully match at # beginning the dirname of file. E.g. if file is /a/b/c/d.py, a path # of /a/b/c will pass, because the file is below the /a/b/c path, but # path of /a/b/c/g will not pass. if (not file or path and not filter(lambda a: os.path.dirname(file).find(a) == 0, path)): raise SERVER_RETURN, HTTP_NOT_FOUND if autoreload: oldmtime = module.__dict__.get("__mtime__", 0) mtime = module_mtime(module) else: mtime, oldmtime = 0, 0 else: mtime, oldmtime = 0, -1 if mtime > oldmtime: # Import the module if debug: if path: s = "mod_python: (Re)importing module '%s' with path set to '%s'" % (module_name, path) else: s = "mod_python: (Re)importing module '%s'" % module_name _apache.log_error(s, APLOG_NOERRNO|APLOG_NOTICE) parts = module_name.split('.') for i in range(len(parts)): f, p, d = imp.find_module(parts[i], path) try: mname = ".".join(parts[:i+1]) module = imp.load_module(mname, f, p, d) finally: if f: f.close() if hasattr(module, "__path__"): path = module.__path__ if mtime == 0: mtime = module_mtime(module) module.__mtime__ = mtime return module
def HandlerDispatch(self, req): """ This is the handler dispatcher. """ # be cautious result = HTTP_INTERNAL_SERVER_ERROR # config config = req.get_config() debug = config.has_key("PythonDebug") try: hlist = req.hlist while hlist.handler: # split module::handler l = hlist.handler.split('::', 1) module_name = l[0] if len(l) == 1: # no oject, provide default object_str = req.phase[len("python"):].lower() else: object_str = l[1] # add the directory to pythonpath if # not there yet, or pythonpath specified if config.has_key("PythonPath"): # we want to do as little evaling as possible, # so we remember the path in un-evaled form and # compare it global _path pathstring = config["PythonPath"] if pathstring != _path: _path = pathstring newpath = eval(pathstring) if sys.path != newpath: sys.path[:] = newpath else: dir = hlist.directory if dir not in sys.path: sys.path[:0] = [dir] # import module module = import_module(module_name, config) # find the object object = resolve_object(module, object_str, arg=req, silent=hlist.silent) if object: # call the object if config.has_key("PythonEnablePdb"): result = pdb.runcall(object, req) else: result = object(req) assert (type(result) == type(int())), \ "Handler '%s' returned invalid return code." % hlist.handler # stop cycling through handlers if result != OK: break elif hlist.silent: result = DECLINED hlist.next() except SERVER_RETURN, value: # SERVER_RETURN indicates an abort from below # with value as (result, status) or (result, None) or result try: if len(value.args) == 2: (result, status) = value.args if status: req.status = status else: result = value.args[0] if type(result) != type(7): s = "Value raised with SERVER_RETURN is invalid. It is a " s = s + "%s, but it must be a tuple or an int." % type(result) _apache.log_error(s, APLOG_NOERRNO|APLOG_ERR, req.server) return HTTP_INTERNAL_SERVER_ERROR except: pass
def FilterDispatch(self, filter): req = filter.req # config config = req.get_config() debug = config.has_key("PythonDebug") try: # split module::handler l = filter.handler.split('::', 1) module_name = l[0] if len(l) == 1: # no oject, provide default if filter.is_input: object_str = "inputfilter" else: object_str = "outputfilter" else: object_str = l[1] # add the directory to pythonpath if # not there yet, or pythonpath specified if config.has_key("PythonPath"): # we want to do as little evaling as possible, # so we remember the path in un-evaled form and # compare it global _path pathstring = config["PythonPath"] if pathstring != _path: _path = pathstring newpath = eval(pathstring) if sys.path != newpath: sys.path[:] = newpath else: if filter.dir not in sys.path: sys.path[:0] = [filter.dir] # import module module = import_module(module_name, config) # find the object object = resolve_object(module, object_str, arg=filter, silent=0) if object: # call the object if config.has_key("PythonEnablePdb"): pdb.runcall(object, filter) else: object(filter) # always flush the filter. without a FLUSH or EOS bucket, # the content is never written to the network. # XXX an alternative is to tell the user to flush() always filter.flush() except SERVER_RETURN, value: # SERVER_RETURN indicates a non-local abort from below # with value as (result, status) or (result, None) or result try: if len(value.args) == 2: (result, status) = value.args if status: req.status = status else: result = value.args[0] if type(result) != type(7): s = "Value raised with SERVER_RETURN is invalid. It is a " s = s + "%s, but it must be a tuple or an int." % type(result) _apache.log_error(s, APLOG_NOERRNO|APLOG_ERR, req.server) return except: pass
def FilterDispatch(self, fltr): req = fltr.req # config config, debug = req.get_config(), False if "PythonDebug" in config: debug = config["PythonDebug"] == "1" try: # split module::handler l = fltr.handler.split('::', 1) module_name = l[0] if len(l) == 1: # no oject, provide default if fltr.is_input: obj_str = "inputfilter" else: obj_str = "outputfilter" else: obj_str = l[1] # add the directory to pythonpath if # not there yet, or evaluate pythonpath # and set sys.path to resulting value # if not already done if "PythonPath" in config: _path_cache_lock.acquire() try: pathstring = config["PythonPath"] if pathstring not in _path_cache: newpath = eval(pathstring) _path_cache[pathstring] = None sys.path[:] = newpath finally: _path_cache_lock.release() else: if fltr.dir: _path_cache_lock.acquire() try: if fltr.dir not in sys.path: sys.path[:0] = [fltr.dir] finally: _path_cache_lock.release() # import module autoreload = True if "PythonAutoReload" in config: autoreload = config["PythonAutoReload"] == "1" module = import_module(module_name, autoreload=autoreload, log=debug) # find the object obj = resolve_object(module, obj_str, arg=fltr, silent=0) # Only permit debugging using pdb if Apache has # actually been started in single process mode. pdb_debug = False if "PythonEnablePdb" in config: pdb_debug = config["PythonEnablePdb"] == "1" if pdb_debug and exists_config_define("ONE_PROCESS"): # Don't use pdb.runcall() as it results in # a bogus 'None' response when pdb session # is quit. With this code the exception # marking that the session has been quit is # propogated back up and it is obvious in # the error message what actually occurred. debugger = pdb.Pdb() debugger.reset() sys.settrace(debugger.trace_dispatch) try: result = obj(fltr) finally: debugger.quitting = 1 sys.settrace(None) else: result = obj(fltr) # always flush the filter. without a FLUSH or EOS bucket, # the content is never written to the network. # XXX an alternative is to tell the user to flush() always if not fltr.closed: fltr.flush() except SERVER_RETURN as value: # SERVER_RETURN indicates a non-local abort from below # with value as (result, status) or (result, None) or result try: if len(value.args) == 2: (result, status) = value.args if status: req.status = status else: result = value.args[0] if result.__class__ is not int: s = "Value raised with SERVER_RETURN is invalid. It is a " s = s + "%s, but it must be a tuple or an int." % result.__class__ _apache.log_error(s, APLOG_ERR, req.server) return except: pass except: # Error (usually parsing) try: exc_type, exc_value, exc_traceback = sys.exc_info() fltr.disable() result = self.ReportError(exc_type, exc_value, exc_traceback, req=req, filter=fltr, phase=fltr.name, hname=fltr.handler, debug=debug) finally: exc_traceback = None return OK
def import_module(module_name, autoreload=1, log=0, path=None): """ Get the module to handle the request. If autoreload is on, then the module will be reloaded if it has changed since the last import. """ # nlehuen: this is a big lock, we'll have to refine it later to get better performance. # For now, we'll concentrate on thread-safety. #PyS60:imp.acquire_lock() try: # (Re)import if sys.modules.has_key(module_name): # The module has been imported already module = sys.modules[module_name] # but is it in the path? file = module.__dict__.get("__file__") # the "and not" part of this condition is to prevent execution # of arbitrary already imported modules, such as os. The # reason we use startswith as opposed to exact match is that # modules inside packages are actually in subdirectories. if not file or (path and not filter(file.startswith, path)): # there is a script by this name already imported, but it's in # a different directory, therefore it's a different script mtime, oldmtime = 0, -1 elif autoreload: oldmtime = module.__dict__.get("__mtime__", 0) mtime = module_mtime(module) else: mtime, oldmtime = 0, 0 else: mtime, oldmtime = 0, -1 if mtime != oldmtime: # Import the module if log: if path: s = "mod_python: (Re)importing module '%s' with path set to '%s'" % ( module_name, path) else: s = "mod_python: (Re)importing module '%s'" % module_name _apache.log_error(s, APLOG_NOERRNO | APLOG_NOTICE) parent = None parts = module_name.split('.') for i in range(len(parts)): f, p, d = imp.find_module(parts[i], path) try: mname = ".".join(parts[:i + 1]) module = imp.load_module(mname, f, p, d) if parent: setattr(parent, parts[i], module) parent = module finally: if f: f.close() if hasattr(module, "__path__"): path = module.__path__ if mtime == 0: mtime = module_mtime(module) module.__mtime__ = mtime return module finally: #PyS60:imp.release_lock() pass
def FilterDispatch(self, filter): req = filter.req # config config = req.get_config() debug = int(config.get("PythonDebug", 0)) try: # add the directory to pythonpath if # not there yet, or evaluate pythonpath # and set sys.path to resulting value # if not already done if config.has_key("PythonPath"): _path_cache_lock.acquire() try: pathstring = config["PythonPath"] if not _path_cache.has_key(pathstring): newpath = eval(pathstring) _path_cache[pathstring] = None sys.path[:] = newpath finally: _path_cache_lock.release() else: if filter.dir and (filter.dir not in sys.path): sys.path[:0] = [filter.dir] if not callable(filter.handler): # split module::handler l = filter.handler.split('::', 1) module_name = l[0] if len(l) == 1: # no oject, provide default if filter.is_input: object_str = "inputfilter" else: object_str = "outputfilter" else: object_str = l[1] # import module module = import_module(module_name, autoreload=int( config.get("PythonAutoReload", 1)), log=debug) # find the object object = resolve_object(module, object_str, arg=filter, silent=0) else: object = filter.handler # Only permit debugging using pdb if Apache has # actually been started in single process mode. pdb_debug = int(config.get("PythonEnablePdb", "0")) one_process = exists_config_define("ONE_PROCESS") if pdb_debug and one_process: # Don't use pdb.runcall() as it results in # a bogus 'None' response when pdb session # is quit. With this code the exception # marking that the session has been quit is # propogated back up and it is obvious in # the error message what actually occurred. debugger = pdb.Pdb() debugger.reset() sys.settrace(debugger.trace_dispatch) try: result = object(filter) finally: debugger.quitting = 1 sys.settrace(None) else: result = object(filter) # always flush the filter. without a FLUSH or EOS bucket, # the content is never written to the network. # XXX an alternative is to tell the user to flush() always if not filter.closed: filter.flush() except SERVER_RETURN, value: # SERVER_RETURN indicates a non-local abort from below # with value as (result, status) or (result, None) or result try: if len(value.args) == 2: (result, status) = value.args if status: req.status = status else: result = value.args[0] if type(result) != type(7): s = "Value raised with SERVER_RETURN is invalid. It is a " s = s + "%s, but it must be a tuple or an int." % type( result) _apache.log_error(s, APLOG_NOERRNO | APLOG_ERR, req.server) return except: pass
def import_module(module_name, autoreload=1, log=0, path=None): """ Get the module to handle the request. If autoreload is on, then the module will be reloaded if it has changed since the last import. """ # nlehuen: this is a big lock, we'll have to refine it later to get better performance. # For now, we'll concentrate on thread-safety. # (Re)import if module_name in sys.modules: # The module has been imported already module = sys.modules[module_name] oldmtime, mtime = 0, 0 if autoreload: # but is it in the path? try: file = module.__dict__["__file__"] except KeyError: file = None # the "and not" part of this condition is to prevent execution # of arbitrary already imported modules, such as os. The # reason we use startswith as opposed to exact match is that # modules inside packages are actually in subdirectories. if not file or (path and not list(filter(file.startswith, path))): # there is a script by this name already imported, but it's in # a different directory, therefore it's a different script mtime, oldmtime = 0, -1 # trigger import else: try: last_check = module.__dict__["__mtime_check__"] except KeyError: last_check = 0 if (time.time() - last_check) > 1: oldmtime = module.__dict__.get("__mtime__", 0) mtime = module_mtime(module) else: pass else: mtime, oldmtime = 0, -1 if mtime != oldmtime: # Import the module if log: if path: s = "mod_python: (Re)importing module '%s' with path set to '%s'" % ( module_name, path) else: s = "mod_python: (Re)importing module '%s'" % module_name _apache.log_error(s, APLOG_NOTICE) parent = None module = importlib.import_module(module_name) if mtime == 0: mtime = module_mtime(module) module.__mtime__ = mtime return module
def Dispatch(self, _req, htype): """ This is the handler dispatcher. """ # be cautious result, handler = HTTP_INTERNAL_SERVER_ERROR, "" # is there a Request object for this request? if not _req._Request: _req._Request = Request(_req) req = _req._Request # config config = _req.get_config() debug = config.has_key("PythonDebug") try: # cycle through the handlers dirs = _req.get_all_dirs() hstack = self.HStack(_req) handler = hstack.pop() while handler: # split module::handler l = string.split(handler, '::', 1) module_name = l[0] if len(l) == 1: # no oject, provide default object_str = string.lower(htype[len("python"):]) else: object_str = l[1] # add the direcotry to pythonpath if # not there yet, or pythonpath specified if config.has_key("PythonPath"): # we want to do as little evaling as possible, # so we remember the path in un-evaled form and # compare it global _path pathstring = config["PythonPath"] if pathstring != _path: _path = pathstring newpath = eval(pathstring) if sys.path != newpath: sys.path[:] = newpath else: if config.has_key("PythonHandlerModule"): dir = _req.get_all_dirs()["PythonHandlerModule"] else: dir = _req.get_all_dirs()[htype] if dir not in sys.path: sys.path[:0] = [dir] # import module module = import_module(module_name, _req) # find the object silent = config.has_key("PythonHandlerModule") object = resolve_object(req, module, object_str, silent) if object: # call the object if config.has_key("PythonEnablePdb"): result = pdb.runcall(object, req) else: result = object(req) # stop cycling through handlers if result != OK: break elif silent: result = DECLINED handler = hstack.pop() except SERVER_RETURN, value: # SERVER_RETURN indicates a non-local abort from below # with value as (result, status) or (result, None) or result try: if len(value.args) == 2: (result, status) = value.args if status: _req.status = status else: result = value.args[0] if type(result) != type(7): s = "Value raised with SERVER_RETURN is invalid. It is a " s = s + "%s, but it must be a tuple or an int." % type(result) _apache.log_error(s, APLOG_NOERRNO|APLOG_ERR, _req.server) return HTTP_INTERNAL_SERVER_ERROR except: pass