def apply_data(self, object): if not self.form: if not hasattr(self.req, 'form'): # no existing form, so need to create one, # form has to be saved back to request object # so that error page can access it if need be self.form = util.FieldStorage(self.req, keep_blank_values=1) self.req.form = self.form else: self.form = self.req.form return util.apply_fs_data(object, self.form, req=self.req)
def run(self, vars={}, flush=0): code, req = self.code, self.req # does this code use session? session = None if "session" in code.co_names: if not hasattr(req, 'session'): # no existing session, so need to create one, # session has to be saved back to request object # to avoid deadlock if error page tries to use it req.session = session = Session.Session(req) # does this code use form? form = None if "form" in code.co_names: if not hasattr(req, 'form'): # no existing form, so need to create one, # form has to be saved back to request object # so that error page can access it if need be form = util.FieldStorage(req, keep_blank_values=1) req.form = form else: form = req.form # create psp interface object psp = PSPInterface(req, self.filename, form) try: global_scope = globals().copy() global_scope.update({"req":req, "form":form, "psp":psp}) # strictly speaking, session attribute only needs # to be populated if referenced, but historically # code has always populated it even if None, so # preserve that just in case changing it breaks # some users code if hasattr(req, 'session'): global_scope.update({"session":req.session}) else: global_scope.update({"session":None}) global_scope.update(self.vars) # passed in __init__() global_scope.update(vars) # passed in run() try: exec code in global_scope if flush: req.flush() # the mere instantiation of a session changes it # (access time), so it *always* has to be saved if hasattr(req, 'session'): req.session.save() except: et, ev, etb = sys.exc_info() if psp.error_page: # run error page psp.error_page.run({"exception": (et, ev, etb)}, flush) else: raise et, ev, etb finally: # if session was created here, unlock it and don't leave # it behind in request object in unlocked state as it # will just cause problems if then used by subsequent code if session is not None: session.unlock() del req.session
def publish_object(req, object): if callable(object): # To publish callables, we call them an recursively publish the result # of the call (as done by util.apply_fs_data) req.form = util.FieldStorage(req, keep_blank_values=1) return publish_object(req,util.apply_fs_data(object, req.form, req=req)) # TODO : we removed this as of mod_python 3.2, let's see if we can put it back # in mod_python 3.3 # elif hasattr(object,'__iter__'): # # # To publish iterables, we recursively publish each item # # This way, generators can be published # result = False # for item in object: # result |= publish_object(req,item) # return result # else: if object is None: # Nothing to publish return False elif isinstance(object,UnicodeType): # We've got an Unicode string to publish, so we have to encode # it to bytes. We try to detect the character encoding # from the Content-Type header if req._content_type_set: charset = re_charset.search(req.content_type) if charset: charset = charset.group(1) else: # If no character encoding was set, we use UTF8 charset = 'UTF8' req.content_type += '; charset=UTF8' else: # If no character encoding was set, we use UTF8 charset = 'UTF8' result = object.encode(charset) else: charset = None result = str(object) if not req._content_type_set: # make an attempt to guess content-type # we look for a </HTML in the last 100 characters. # re.search works OK with a negative start index (it starts from 0 # in that case) if re_html.search(result,len(result)-100): req.content_type = 'text/html' else: req.content_type = 'text/plain' if charset is not None: req.content_type += '; charset=%s'%charset # Write result even if req.method is 'HEAD' as Apache # will discard the final output anyway. Truncating # output here if req.method is 'HEAD' is likely the # wrong thing to do as it may cause problems for any # output filters. See MODPYTHON-105 for details. We # also do not flush output as that will prohibit use # of 'CONTENT_LENGTH' filter to add 'Content-Length' # header automatically. See MODPYTHON-107 for details. req.write(result, 0) return True