Пример #1
0
    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()
Пример #2
0
 def unmutate(self,mobj):
     p = mobj.extra.split('.')
     klass = util.get_class_from_name(p[1],p[0],
                                      xml_pickle.getParanoia())		
     return klass(mobj.obj)
Пример #3
0
    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()
Пример #4
0
def _thing_from_dom(dom_node, container=None, paranoia=1):
    "Converts an [xml_pickle] DOM tree to a 'native' Python object"
    for node in subnodes(dom_node):
        if node.nodeName == "PyObject":
            container = unpickle_instance(node, paranoia)
            # do we need to unmutate it? (check for type= being set --
            # will only be set for mutated objects)
            if node.getAttribute('type'):
                # get unmutator by type=
                klass = node.getAttribute('type')
                if mutate.can_unmutate(klass, container):
                    # note -- 'extra' isn't handled (yet) at the toplevel
                    container = mutate.unmutate(klass, container, paranoia,
                                                None)

            try:
                id = node.getAttribute('id')
                visited[id] = container
            except KeyError:
                pass

        elif node.nodeName in ['attr', 'item', 'key', 'val']:
            node_family = node.getAttribute('family')
            node_type = node.getAttribute('type')
            node_name = node.getAttribute('name')

            # check refid first (if present, type is type of referenced object)
            ref_id = node.getAttribute('refid')

            if len(ref_id):  # might be empty or None
                if node.nodeName == 'attr':
                    setattr(container, node_name, visited[ref_id])
                else:
                    container.append(visited[ref_id])

                # done, skip rest of block
                continue

            # if we didn't find a family tag, guess (do after refid check --
            # old pickles will set type="ref" which _fix_family can't handle)
            node_family = _fix_family(node_family, node_type)

            node_valuetext = get_node_valuetext(node)

            # step 1 - set node_val to basic thing
            #if node_name == '__parent__' and getExcludeParentAttr():
            #	continue	# Do not pickle xml_objectify bookkeeping attribute
            if node_family == 'none':
                node_val = None
            elif node_family == 'atom':
                node_val = node_valuetext
            elif node_family == 'seq':
                # seq must exist in visited{} before we unpickle subitems,
                # in order to handle self-references
                seq = []
                _save_obj_with_id(node, seq)
                node_val = _thing_from_dom(node, seq, paranoia)
            elif node_family == 'map':
                # map must exist in visited{} before we unpickle subitems,
                # in order to handle self-references
                map = {}
                _save_obj_with_id(node, map)
                node_val = _thing_from_dom(node, map, paranoia)
            elif node_family == 'obj':
                node_val = unpickle_instance(node, paranoia)
            elif node_family == 'lang':
                # lang is a special type - we don't know how to unpickle
                # a generic 'lang' object, so we have to handle the specific
                # types here instead of in the block below
                #
                # In the future, this might be expanded to include
                # other languages, but for now, only Python is supported.
                if node_type == 'function':
                    node_val = unpickle_function(node.getAttribute('module'),
                                                 node.getAttribute('class'),
                                                 paranoia)
                elif node_type == 'class':
                    node_val = get_class_from_name(node.getAttribute('class'),
                                                   node.getAttribute('module'),
                                                   paranoia)
                else:
                    raise XMLUnpicklingError, "Unknown lang type %s" % node_type
            elif node_family == 'uniq':
                # uniq is another special type that is handled here instead
                # of below.

                # Gnosis-1.0.6 encoded functions/classes as 'uniq' instead
                # of 'lang' -- accept these for backward compatibility.
                if node_type == 'function':
                    node_val = unpickle_function(node.getAttribute('module'),
                                                 node.getAttribute('class'),
                                                 paranoia)
                elif node_type == 'class':
                    node_val = get_class_from_name(node.getAttribute('class'),
                                                   node.getAttribute('module'),
                                                   paranoia)
                elif node_type == 'True':
                    node_val = TRUE_VALUE
                elif node_type == 'False':
                    node_val = FALSE_VALUE
                else:
                    raise XMLUnpicklingError, "Unknown uniq type %s" % node_type
            else:
                raise XMLUnpicklingError, "UNKNOWN family %s,%s,%s" % (
                    node_family, node_type, node_name)

            # step 2 - take basic thing and make exact thing
            # Note there are several NOPs here since node_val has been decided
            # above for certain types. However, I left them in since I think it's
            # clearer to show all cases being handled (easier to see the pattern
            # when doing later maintenance).

            if node_type == 'None':
                node_val = None
            elif node_type == 'numeric':
                #node_val = safe_eval(node_val)
                node_val = to_number(node_val)
            elif node_type == 'string':
                node_val = node_val
            elif node_type == 'list':
                node_val = node_val
            elif node_type == 'tuple':
                # subtlety - if tuples could self-reference, this would be wrong
                # since the self ref points to a list, yet we're making it into
                # a tuple. it appears however that self-referencing tuples aren't
                # really all that legal (regular pickle can't handle them), so
                # this shouldn't be a practical problem.
                node_val = tuple(node_val)
            elif node_type == 'dict':
                node_val = node_val
            elif node_type == 'function':
                node_val = node_val
            elif node_type == 'class':
                node_val = node_val
            elif node_type == 'True':
                node_val = node_val
            elif node_type == 'False':
                node_val = node_val
            elif mutate.can_unmutate(node_type, node_val):
                mextra = node.getAttribute('extra')
                node_val = mutate.unmutate(node_type, node_val, paranoia,
                                           mextra)
            elif node_type == 'PyObject':
                node_val = node_val
            #elif ext.can_handle_xml(node_type,node_valuetext):
            #	node_val = ext.xml_to_obj(node_type, node_valuetext, paranoia)
            else:
                raise XMLUnpicklingError, "Unknown type %s,%s" % (node,
                                                                  node_type)

            if node.nodeName == 'attr':
                setattr(container, node_name, node_val)
            else:
                container.append(node_val)

            _save_obj_with_id(node, node_val)

        elif node.nodeName == 'entry':
            keyval = _thing_from_dom(node, [], paranoia)
            key, val = keyval[0], keyval[1]
            container[key] = val
            # <entry> has no id for refchecking

        else:
            raise XMLUnpicklingError, \
                  "element %s is not in PyObjects.dtd" % node.nodeName

    return container
Пример #5
0
def _thing_from_dom(dom_node, container=None, paranoia=1):
    "Converts an [xml_pickle] DOM tree to a 'native' Python object"
    for node in subnodes(dom_node):
        if node.nodeName == "PyObject":
            container = unpickle_instance(node, paranoia)
            # do we need to unmutate it? (check for type= being set --
            # will only be set for mutated objects)
            if node.getAttribute('type'):
                # get unmutator by type=
                klass = node.getAttribute('type')
                if mutate.can_unmutate(klass,container):
                    # note -- 'extra' isn't handled (yet) at the toplevel
                    container = mutate.unmutate(klass,container,paranoia,None)

            try:
                id = node.getAttribute('id')
                visited[id] = container
            except KeyError:
                pass

        elif node.nodeName in ['attr','item','key','val']:
            node_family = node.getAttribute('family')
            node_type = node.getAttribute('type')
            node_name = node.getAttribute('name')

            # check refid first (if present, type is type of referenced object)
            ref_id = node.getAttribute('refid')
                
            if len(ref_id):	 # might be empty or None
                if node.nodeName == 'attr':
                    setattr(container, node_name, visited[ref_id])
                else:
                    container.append(visited[ref_id])

                # done, skip rest of block
                continue

            # if we didn't find a family tag, guess (do after refid check --
            # old pickles will set type="ref" which _fix_family can't handle)
            node_family = _fix_family(node_family,node_type)

            node_valuetext = get_node_valuetext(node)

            # step 1 - set node_val to basic thing
            #if node_name == '__parent__' and getExcludeParentAttr():
            #	continue	# Do not pickle xml_objectify bookkeeping attribute
            if node_family == 'none':
                node_val = None
            elif node_family == 'atom':
                node_val = node_valuetext
            elif node_family == 'seq':
                # seq must exist in visited{} before we unpickle subitems,
                # in order to handle self-references
                seq = []
                _save_obj_with_id(node,seq)
                node_val = _thing_from_dom(node,seq,paranoia)
            elif node_family == 'map':
                # map must exist in visited{} before we unpickle subitems,
                # in order to handle self-references
                map = {}
                _save_obj_with_id(node,map)
                node_val = _thing_from_dom(node,map,paranoia)
            elif node_family == 'obj':
                node_val = unpickle_instance(node, paranoia)
            elif node_family == 'lang':
                # lang is a special type - we don't know how to unpickle
                # a generic 'lang' object, so we have to handle the specific
                # types here instead of in the block below
                #
                # In the future, this might be expanded to include
                # other languages, but for now, only Python is supported.
                if node_type == 'function':
                    node_val = unpickle_function(node.getAttribute('module'),
                                                 node.getAttribute('class'),
                                                 paranoia)
                elif node_type == 'class':
                    node_val = get_class_from_name(node.getAttribute('class'),
                                                   node.getAttribute('module'),
                                                   paranoia)
                else:
                    raise XMLUnpicklingError, "Unknown lang type %s" % node_type					
            elif node_family == 'uniq':
                # uniq is another special type that is handled here instead
                # of below.

                # Gnosis-1.0.6 encoded functions/classes as 'uniq' instead
                # of 'lang' -- accept these for backward compatibility.
                if node_type == 'function':
                    node_val = unpickle_function(node.getAttribute('module'),
                                                 node.getAttribute('class'),
                                                 paranoia)
                elif node_type == 'class':
                    node_val = get_class_from_name(node.getAttribute('class'),
                                                   node.getAttribute('module'),
                                                   paranoia)
                elif node_type == 'True':
                    node_val = TRUE_VALUE
                elif node_type == 'False':
                    node_val = FALSE_VALUE
                else:
                    raise XMLUnpicklingError, "Unknown uniq type %s" % node_type
            else:
                raise XMLUnpicklingError, "UNKNOWN family %s,%s,%s" % (node_family,node_type,node_name)

            # step 2 - take basic thing and make exact thing
            # Note there are several NOPs here since node_val has been decided
            # above for certain types. However, I left them in since I think it's
            # clearer to show all cases being handled (easier to see the pattern
            # when doing later maintenance).
            
            if node_type == 'None':
                node_val = None
            elif node_type == 'numeric':
                #node_val = safe_eval(node_val)
                node_val = to_number(node_val)
            elif node_type == 'string':
                node_val = node_val
            elif node_type == 'list':
                node_val = node_val
            elif node_type == 'tuple':
                # subtlety - if tuples could self-reference, this would be wrong
                # since the self ref points to a list, yet we're making it into
                # a tuple. it appears however that self-referencing tuples aren't
                # really all that legal (regular pickle can't handle them), so
                # this shouldn't be a practical problem.
                node_val = tuple(node_val)
            elif node_type == 'dict':
                node_val = node_val
            elif node_type == 'function':
                node_val = node_val
            elif node_type == 'class':
                node_val = node_val
            elif node_type == 'True':
                node_val = node_val
            elif node_type == 'False':
                node_val = node_val
            elif mutate.can_unmutate(node_type,node_val):
                mextra = node.getAttribute('extra')
                node_val = mutate.unmutate(node_type,node_val,paranoia,
                                           mextra)
            elif node_type == 'PyObject':
                node_val = node_val
            #elif ext.can_handle_xml(node_type,node_valuetext):
            #	node_val = ext.xml_to_obj(node_type, node_valuetext, paranoia)
            else:
                raise XMLUnpicklingError, "Unknown type %s,%s" % (node,node_type)

            if node.nodeName == 'attr':
                setattr(container,node_name,node_val)
            else:
                container.append(node_val)

            _save_obj_with_id(node,node_val)

        elif node.nodeName == 'entry':
            keyval = _thing_from_dom(node, [], paranoia)
            key, val = keyval[0], keyval[1]
            container[key] = val
            # <entry> has no id for refchecking

        else:
            raise XMLUnpicklingError, \
                  "element %s is not in PyObjects.dtd" % node.nodeName

    return container