def get_node_valuetext(node): "Get text from node, whether in value=, or in element body." # we know where the text is, based on whether there is # a value= attribute. ie. pickler can place it in either # place (based on user preference) and unpickler doesn't care if node._attrs.has_key('value'): # text in tag ttext = node.getAttribute('value') return unsafe_string(ttext) else: # text in body node.normalize() try: btext = node.childNodes[0].nodeValue except: btext = '' return unsafe_content(btext)
def reduce(self, name, bodytext): #dbg("ABOUT TO REDUCE %s %s"%(name,str(self.elem_stk[-1]))) dbg("ABOUT TO REDUCE %s" % (name)) self.prstk() elem = self.elem_stk.pop() refid = elem[4].get('refid') if refid: obj = self.visited[refid] #dbg("GOT REF %s,%s"%(str(refid),obj)) self.val_stk.append((elem[0], elem[3], obj)) dbg("<<<<<<<<<<<< REDUCED") self.prstk() self.nr_objs += 1 return if elem[4].get('value'): valuetext = unsafe_string(elem[4].get('value')) else: valuetext = unsafe_content(bodytext) #valuetext = elem[4].get('value') or bodytext if name in ['attr', 'key', 'val', 'item']: # step 1 -- convert family -> basic_type family = elem[1] if family == 'atom': dbg("** ATOM") obj = valuetext elif family == 'none': dbg("** NONE") obj = None elif family == 'seq': dbg("** SEQ") obj = elem[5] while self.val_stk[-1][0] != 'STOP': obj.insert(0, self.val_stk.pop()[2]) self.val_stk.pop() # pop STOP elif family == 'map': dbg("** MAP") obj = elem[5] while self.val_stk[-1][0] != 'STOP': e = self.val_stk.pop() obj[e[2][0]] = e[2][1] self.val_stk.pop() # pop STOP elif family == 'obj': dbg("** OBJ") obj = self.unpickle_instance(elem) elif family == 'lang': if elem[2] == 'function': obj = unpickle_function(elem[4].get('module'), elem[4].get('class'), self.paranoia) elif elem[2] == 'class': obj = get_class_from_name(elem[4].get('class'), elem[4].get('module'), self.paranoia) else: raise XMLUnpicklingError, \ "Unknown lang type %s" % elem[2] elif family == 'uniq': # uniq is a special type - we don't know how to unpickle # a generic 'uniq' object, so we have to handle the specific # types here instead of in the block below # Gnosis-1.0.6 and earlier encoded functions/classes # as 'uniq' instead of 'lang' -- accept those encodings # for backward compatibility if elem[2] == 'function': obj = unpickle_function(elem[4].get('module'), elem[4].get('class'), self.paranoia) elif elem[2] == 'class': obj = get_class_from_name(elem[4].get('class'), elem[4].get('module'), self.paranoia) elif elem[2] == 'True': obj = TRUE_VALUE elif elem[2] == 'False': obj = FALSE_VALUE else: raise XMLUnpicklingError, \ "Unknown uniq type %s" % elem[2] else: raise XMLUnpicklingError, \ "UNKNOWN family %s,%s,%s" % \ (family,elem[2],elem[3]) # step 2 -- convert basic -> specific type # (many of these are NOPs, but included for clarity) if elem[2] == 'numeric': dbg("** NUMERIC") #if obj.isdigit(): # obj = string.atoi(obj) #else: # obj = eval(obj) obj = to_number(obj) elif elem[2] == 'string': dbg("** STRING") obj = obj elif elem[2] == 'None': obj = obj elif elem[2] in ['tuple', 'list']: dbg("** TUPLE/LIST") if elem[2] != 'list': obj = tuple(obj) else: obj = obj elif elem[2] == 'dict': obj = obj elif elem[2] == 'PyObject': obj = obj elif elem[2] == 'function': obj = obj elif elem[2] == 'class': obj = obj elif elem[2] == 'True': obj = obj elif elem[2] == 'False': obj = obj elif mutate.can_unmutate(elem[2], obj): mextra = elem[4].get('extra') obj = mutate.unmutate(elem[2], obj, self.paranoia, mextra) #elif xmlext.can_handle_xml(elem[1],valuetext): # obj = xmlext.xml_to_obj(elem[1],valuetext,self.paranoia) else: self.prstk(1) raise XMLUnpicklingError, \ "UNHANDLED elem %s"%elem[2] # push on stack and save obj ref self.val_stk.append((elem[0], elem[3], obj)) self.save_obj_id(obj, elem) self.nr_objs += 1 elif name == 'entry': e1 = self.val_stk.pop() e2 = self.val_stk.pop() if e1[0] == 'val': ent = ((elem[0], elem[3], (e2[2], e1[2]))) else: ent = ((elem[0], elem[3], (e1[2], e2[2]))) # <entry> actually has no id self.save_obj_id(ent, elem) self.val_stk.append(ent) elif name == 'PyObject': obj = self.unpickle_instance(elem) # do we need to unmutate it? (check for type= being set - # will only be set for mutated objects) if elem[2] is not None and len(elem[2]): if mutate.can_unmutate(elem[2], obj): # note -- 'extra' isn't handled (yet) at the toplevel obj = mutate.unmutate(elem[2], obj, self.paranoia, None) self.val_stk.append((elem[0], elem[3], obj)) self.save_obj_id(obj, elem) self.nr_objs += 1 else: raise str("UNHANDLED name %s" % name) dbg("<<<<<<<<<<<< REDUCED") self.prstk()
def reduce(self,name,bodytext): #dbg("ABOUT TO REDUCE %s %s"%(name,str(self.elem_stk[-1]))) dbg("ABOUT TO REDUCE %s"%(name)) self.prstk() elem = self.elem_stk.pop() refid = elem[4].get('refid') if refid: obj = self.visited[refid] #dbg("GOT REF %s,%s"%(str(refid),obj)) self.val_stk.append((elem[0],elem[3],obj)) dbg("<<<<<<<<<<<< REDUCED") self.prstk() self.nr_objs += 1 return if elem[4].get('value'): valuetext = unsafe_string(elem[4].get('value')) else: valuetext = unsafe_content(bodytext) #valuetext = elem[4].get('value') or bodytext if name in ['attr','key','val','item']: # step 1 -- convert family -> basic_type family = elem[1] if family == 'atom': dbg("** ATOM") obj = valuetext elif family == 'none': dbg("** NONE") obj = None elif family == 'seq': dbg("** SEQ") obj = elem[5] while self.val_stk[-1][0] != 'STOP': obj.insert(0,self.val_stk.pop()[2]) self.val_stk.pop() # pop STOP elif family == 'map': dbg("** MAP") obj = elem[5] while self.val_stk[-1][0] != 'STOP': e = self.val_stk.pop() obj[e[2][0]] = e[2][1] self.val_stk.pop() # pop STOP elif family == 'obj': dbg("** OBJ") obj = self.unpickle_instance(elem) elif family == 'lang': if elem[2] == 'function': obj = unpickle_function(elem[4].get('module'), elem[4].get('class'), self.paranoia) elif elem[2] == 'class': obj = get_class_from_name(elem[4].get('class'), elem[4].get('module'), self.paranoia) else: raise XMLUnpicklingError, \ "Unknown lang type %s" % elem[2] elif family == 'uniq': # uniq is a special type - we don't know how to unpickle # a generic 'uniq' object, so we have to handle the specific # types here instead of in the block below # Gnosis-1.0.6 and earlier encoded functions/classes # as 'uniq' instead of 'lang' -- accept those encodings # for backward compatibility if elem[2] == 'function': obj = unpickle_function(elem[4].get('module'), elem[4].get('class'), self.paranoia) elif elem[2] == 'class': obj = get_class_from_name(elem[4].get('class'), elem[4].get('module'), self.paranoia) elif elem[2] == 'True': obj = TRUE_VALUE elif elem[2] == 'False': obj = FALSE_VALUE else: raise XMLUnpicklingError, \ "Unknown uniq type %s" % elem[2] else: raise XMLUnpicklingError, \ "UNKNOWN family %s,%s,%s" % \ (family,elem[2],elem[3]) # step 2 -- convert basic -> specific type # (many of these are NOPs, but included for clarity) if elem[2] == 'numeric': dbg("** NUMERIC") #if obj.isdigit(): # obj = string.atoi(obj) #else: # obj = eval(obj) obj = to_number(obj) elif elem[2] == 'string': dbg("** STRING") obj = obj elif elem[2] == 'None': obj = obj elif elem[2] in ['tuple','list']: dbg("** TUPLE/LIST") if elem[2] != 'list': obj = tuple(obj) else: obj = obj elif elem[2] == 'dict': obj = obj elif elem[2] == 'PyObject': obj = obj elif elem[2] == 'function': obj = obj elif elem[2] == 'class': obj = obj elif elem[2] == 'True': obj = obj elif elem[2] == 'False': obj = obj elif mutate.can_unmutate(elem[2],obj): mextra = elem[4].get('extra') obj = mutate.unmutate(elem[2],obj,self.paranoia,mextra) #elif xmlext.can_handle_xml(elem[1],valuetext): # obj = xmlext.xml_to_obj(elem[1],valuetext,self.paranoia) else: self.prstk(1) raise XMLUnpicklingError, \ "UNHANDLED elem %s"%elem[2] # push on stack and save obj ref self.val_stk.append((elem[0],elem[3],obj)) self.save_obj_id(obj,elem) self.nr_objs += 1 elif name == 'entry': e1 = self.val_stk.pop() e2 = self.val_stk.pop() if e1[0] == 'val': ent = ((elem[0],elem[3],(e2[2],e1[2]))) else: ent = ((elem[0],elem[3],(e1[2],e2[2]))) # <entry> actually has no id self.save_obj_id(ent,elem) self.val_stk.append(ent) elif name == 'PyObject': obj = self.unpickle_instance(elem) # do we need to unmutate it? (check for type= being set - # will only be set for mutated objects) if elem[2] is not None and len(elem[2]): if mutate.can_unmutate(elem[2],obj): # note -- 'extra' isn't handled (yet) at the toplevel obj = mutate.unmutate(elem[2],obj,self.paranoia,None) self.val_stk.append((elem[0],elem[3],obj)) self.save_obj_id(obj,elem) self.nr_objs += 1 else: raise str("UNHANDLED name %s"%name) dbg("<<<<<<<<<<<< REDUCED") self.prstk()