Logo Search packages:      
Sourcecode: jaxml version File versions  Download package

def jaxml::_TAGGED_document::__init__ (   self  )  [inherited]

Initialize local datas

Definition at line 426 of file jaxml.py.

00426                            :
                """Initialize local datas"""
                # the document itself
                self.__page = []
                self.__pushed = []
                self.__pusheddict = {}
                self.__position = 0

                # Initialise a mapping to implement another templating
                # facility for postprocessing
                self._updatemapping()

                # sets the default indentation string
                self._indentstring()

        def __copy__(self) :
                """Creates a copy of the current document"""
                # create an instance of the same class
                new = self.__class__()

                # copy the "private" members
                new.__page = self.__page[:]
                new.__pushed = self.__pushed[:]
                new.__pusheddict = self.__pusheddict.copy()
                new.__position = self.__position
                new.__indentstring = self.__indentstring
                new.__mapping = self.__mapping.copy()

                # copy the "public" ones which are not callable (shouldn't occur anyway)
                for (key, value) in self.__dict__.items() :
                        if (key[:2] == "__") and (key[-2:] == "__") and not callable(getattr(self, key)) :
                                setattr(new, key, value)
                return new

        def __mul__(self, number) :
                """Allows a document to be repeated

                   number
                        The number of times to repeat the document

                   allows constructs like: mydoc * 3
                """        
                if type(number) != type(1) :
                        raise TypeError, "jaxml.py: __mul__ operation not permitted on these operands."
                if number < 0 :
                        raise ValueError, "jaxml.py: can't repeat a document a negative number of times."

                if number == 0 :
                        # returns an empty document
                        return self.__class__()
                else :
                        # a multiplication is just a big addition...
                        new = self.__copy__()
                        for i in range(number - 1) :
                                new = new + self
                        return new

        def __rmul__(self, number) :
                """Allows a document to be repeated

                   number
                        The number of times to repeat the document

                   allows construts like: 3 * mydoc
                """   
                return self * number

        def __add__(self, other) :
                """Allows two documents to be concatenated

                   other
                        The document or string of text to concatenate to self

                   This is not a real concatenation: the second
                   document (other) is in fact inserted at the current
                   position in the first one (self).

                   Also allows constructs like: mydoc + "some text"
                """
                if (not isinstance(other, _TAGGED_document)) and (type(other) != type("")) :
                        raise TypeError, "jaxml.py: __add__ operation not permitted on these operands."

                # first we make a copy of the original
                new = self.__copy__()

                # we must also "concatenate" our two template mappings
                new.__mapping.update(other.__mapping)

                # then we insert other as a single string of text
                # skipping the last new line character.
                # we use the parent class __str__ method to skip
                # all the leading garbage like XML or HTTP headers.
                # we should insert it as tags + text instead of plain text...
                new._text(_TAGGED_document.__str__(other)[:-1])
                return new

        def __radd__(self, other) :
                """Allows two documents to be concatenated

                   other
                        The document or string of text to which self will be concatenated

                   This is not a real concatenation: the first
                   document (self) is in fact inserted at the current
                   position in the second one (other).

                   Also allows constructs like: "some text" + mydoc
                """
                return other + self

        def __coerce__(self, other) :
                """Try to convert two documents to a common type"""
                if isinstance(other, _TAGGED_document) :
                        # no problem, compatible types
                        return (self, other)
                elif type(other) == type("") :
                        # a string of text must be converted
                        # to self's type
                        new = self.__class__()
                        new._text(other)
                        return (self, new)
                elif type(other) == type(1) :
                        # probably a __mul__ operation
                        return (self, other)
                else :
                        # conversion is impossible
                        return None

        def __getattr__(self, name) :
                """Here's the magic: we create tags on demand

                   name
                        The name of the tag we want to create
                """
                # don't accept __xxxxx names
                # we reserve them for internal or/and future use
                if (name[:2] != "__") :
                        return self.Tag(self, name)

        def __nonzero__(self) :
                """For truth value testing, returns 1 when the document is not empty"""
                if self.__page :
                        return 1
                else :
                        return 0

        def __getitem__(self, key) :
                """returns key's value in the internal mapping"""
                return self.__mapping[key]

        def __setitem__(self, key, value) :
                """sets key's value in the internal mapping"""
                self.__mapping[key] = value

        def __delitem__(self, key) :
                """deletes this key from the internal mapping"""
                del self.__mapping[key]

        def __str__(self) :
                """returns the document as a string of text"""
                outstr = cStringIO.StringIO()
                indentation = ""
                lgindent = len(self.__indentstring)
                lastopened = None
                for (text, arg, offset) in self.__page :
                        if offset == -1 :       # closing tag
                                indentation = indentation[: -lgindent]
                                if text != lastopened :         # normal case
                                        outstr.write("%s</%s>\n" % (indentation, text))
                                else :                  # noting enclosed
                                        outstr.seek(-2, 1)
                                        outstr.write(" />\n")
                                lastopened = None
                        elif offset == 1 :      # opening tag
                                outstr.write("%s<%s%s>\n" % (indentation, text, arg))
                                indentation = indentation + self.__indentstring
                                lastopened = text
                        else :                  # plain text
                                outstr.write("%s%s\n" % (indentation, text))
                                lastopened = None
                outstr.flush()
                retval = outstr.getvalue()
                outstr.close()

                # and now we use the internal mapping
                # to postprocess the document.
                # This may prove to be useful for replacing chars with their
                # equivalent SGML entities for example, or for templating
                # without a template file.
                for (key, value) in self.__mapping.items() :
                        retval = string.replace(retval, key, value)
                return retval

        def __repr__(self) :
                """Returns a printable representation of the document, same as str() for now"""
                # we define it with a 'def' instead of doing __repr__ = __str__ like the previous versions did
                # because we may redefine __str__ in subclasses and don't want to
                # have to redefine __repr__ too.
                #
                # This way it is done once for all:
                return str(self)

        def __adjust_stack(self, offset) :
                """Adjust the stack of pushed positions.

                   offset
                        offset by which adjust the stack
                """
                if self.__pushed :
                        pos, oldoffset = self.__pushed.pop()
                        self.__pushed.append((pos, oldoffset + offset))

        def _tag__(self, tag, arg) :
                self.__page.insert(self.__position, (tag, arg, 1))
                self.__position = self.__position + 1
                self.__page.insert(self.__position, (tag, None, -1))
                self.__adjust_stack(2)

                #
                # Callable interface starts here
        def _push(self, name=None) :
                """Push the current tag's position.

                   useful before a block of nested tags
                   
                   name : can be used to name the pushed position and pop it later directly
                """
                if name :
                        self.__pusheddict[name] = len(self.__pushed)
                self.__pushed.append((self.__position, 0))

        def _pop(self, name=None) :
                """Restore the latest pushed position.

                   useful to get out of a block of nested tags
                   
                   name : can be used to restore a named position, not necessarily the latest.
                """
                if self.__pushed :
                        maxindex = len(self.__pushed) - 1
                        if name :
                                try :
                                        index = self.__pusheddict[name]
                                        del self.__pusheddict[name]
                                except KeyError :        
                                        raise KeyError, "jaxml named position %s doesn't exist" % name
                        else :
                                index = maxindex
                        while maxindex >= index :
                                pos, offset = self.__pushed.pop()
                                self.__position = pos + offset
                                self.__adjust_stack(offset) # we report the offset on previously saved tags
                                maxindex = maxindex - 1

        def _text(self, text):
                """Insert plain text in the document

                   text
                        text to be inserted
                """
                self.__page.insert(self.__position, (str(text), None, 0))
                self.__position = self.__position + 1
                self.__adjust_stack(1)

        def _indentstring(self, newindentstring = "    "):
                """Sets the indentation string for the output (default is 4 space characters)"""
                self.__indentstring = newindentstring

        def _updatemapping(self, newmap = None) :
                """Updates the internal mapping for the new templating facility,
                   and returns the new mapping's content

                   newmap
                        a Python mapping object to initialise or extend the
                        mapping. If None then the mapping is reset to an empty dictionnary
                        which is the default value.
                """        
                if newmap == None :
                        # clears the template mapping
                        self.__mapping = {}
                        return self.__mapping
                elif type(newmap) == type({}) :
                        # update or extend the current mapping
                        self.__mapping.update(newmap)
                        return self.__mapping
                else :
                        raise TypeError, "jaxml.py: _updatemapping's parameter must be a Python mapping object."

        def _output(self, file = "-") :
                """Ouput the page, with indentation.

                   file
                        the optional file object or filename to output to
                        ("-" or None or "" means sys.stdout)
                """
                isopen = 0
                if (type(file) == type("")) or (file is None) :
                        if file and (file != "-") :
                                outf = open(file, "w")
                                isopen = 1
                        else :
                                outf = sys.stdout
                else :
                        outf = file     # we assume it's a file object
                outf.write("%s" % str(self))
                outf.flush()
                if isopen :
                        outf.close()

class XML_document(_TAGGED_document) :


Generated by  Doxygen 1.6.0   Back to index