Exemple #1
0
    def read(self, *a):
        """Read data"""
        logmgr_flog()

        data = self.f.read(*a)
        self.offset.extend(accumulate(len(m)+1 for m in data.split('\n')))
        return data
Exemple #2
0
def ensurefileobj(source):
    """Return a file(-like) object, regardless if it's a another
       file-object, a filename, or a string

       :param source: filename, file-like object, or string
       :return: StringIO or file-like object
    """
    logmgr_flog()

    # StringIO support:
    if hasattr(source, 'getvalue') and hasattr(source, 'tell'):
        # we return the source
        return source
    elif isinstance(source, (str, bytes)):
        if is_xml(source):
            return StringIO(source)
        else:
            # source isn't a file-like object nor starts with XML structure
            # so it has to be a filename
            try:
                res = StringIO(open(source, 'r').read())
            except FileNotFoundError as err: # pylint:disable=undefined-variable
                raise DMFileNotFoundError("Could not find file {!r}.".format(err.filename),
                                          err.filename, ReturnCodes.E_FILE_NOT_FOUND)
            # pylint: enable=undefined-variable

            return res
Exemple #3
0
    def replace_entities(self):
        """This function replaces entities in the StringIO buffer
        """
        logmgr_flog()

        self._buffer.seek(self._offset)
        self._buffer = replaceinstream(self._buffer, preserve_entities)
Exemple #4
0
    def create_group(self):
        """Creates the docmanager group element"""
        logmgr_flog()

        #search the info-element if not exists raise an error
        info = self.__tree.find("//d:info", namespaces=NS)
        # TODO: We need to check for a --force option
        if info is None:
            log.debug("No <info> element found!")
            pos = findinfo_pos(self.__root)
            log.debug("Using position %d", pos)
            info = etree.Element("{%s}info" % NS["d"])
            info.tail = '\n'
            info.text = '\n'
            self.__root.insert(pos, info)

            log.debug("Adding <info> element in '%s'", self.filename)

        log.debug("Adding <dm:docmanager> to <info>")
        # dm = etree.Element("{%s}docmanager" % NS["dm"])
        # self.__docmanager = info.insert(0, dm)
        self.__docmanager = etree.SubElement(info,
                                             "{{{dm}}}docmanager".format(**NS),
                                             nsmap={'dm': NS['dm']},
                                            )
Exemple #5
0
    def set(self, pairs):
        """Sets the key as element and value as content

           :param key:    name of the element
           :param value:  value that this element will contain

           If key="foo" and value="bar" you will get:
            <foo>bar</foo>
           whereas foo belongs to the DocManager namespace
        """
        logmgr_flog()

        #import pdb
        #pdb.set_trace()

        dm = self.__docmanager
        dmelem = list()
        lastnode = dm

        for key in pairs:
            elemlist = key.split("/")

            for e in elemlist:
                name = "dm:" + e

                dmelem.append(name)
                node = dm.find("/".join(dmelem), namespaces=NS)

                if node is None:
                    node = etree.SubElement(lastnode, "{{{dm}}}{key}".format(key=e, **NS))

                lastnode = node
                node.text = ""

            node.text = pairs[key]
Exemple #6
0
    def delete(self, key, condition=None):
        """Deletes an element inside docmanager element

        :param str key: element name to delete
        :param str condition: the condition for the deletion (the var condition has to be equal with the property value)
        :return boolean: True = success | False = no property has been deleted
        """
        logmgr_flog()

        key = key.split("/")
        lastnode = None

        key_handler = self.__docmanager.find("dm:{}".format(key[0]), namespaces=NS)

        for idx, prop in enumerate(key):
            if lastnode is not None:
                key_handler = lastnode.find("dm:{}".format(prop), namespaces=NS)

            lastnode = key_handler

            if key_handler is None:
                break

            if idx == len(key)-1:
                if condition is not None:
                    if condition != key_handler.text:
                        break

                key_handler.getparent().remove(key_handler)
                return True

        return False
Exemple #7
0
def compilestarttag(roottag=None):
    """Compile a regular expression for start tags like <article> or
       <d:book> with or without any  attributes

       :param str roottag: Name of roottag or None, for a general tag
       :return: a pattern object
       :rtype: _sre.SRE_Pattern
    """
    logmgr_flog()

    # Taken from the xmllib.py
    # http://code.metager.de/source/xref/python/jython/lib-python/2.7/xmllib.py
    _S = '[ \t\r\n]+'                       # white space
    _opS = '[ \t\r\n]*'                     # optional white space
    _Name = '[a-zA-Z_:][-a-zA-Z0-9._:]*'    # valid XML name
    _QStr = "(?:'[^']*'|\"[^\"]*\")"        # quoted XML string
    attrfind = re.compile(
        _S + '(?P<name>' + _Name + ')'
        '(' + _opS + '=' + _opS +
        '(?P<value>' + _QStr + '|[-a-zA-Z0-9.:+*%?!\(\)_#=~]+))?')
    starttagend = re.compile(_opS + '(?P<slash>/?)>')
    if roottag:
        root = '<(?P<tagname>' + roottag + ')'
    else:
        root = '<(?P<tagname>' + _Name + ')'
    return re.compile(root + '(?P<attrs>(?:' + attrfind.pattern + ')*)' +
                      starttagend.pattern)
Exemple #8
0
    def indent_dm(self):
        """Indents only dm:docmanager element and its children"""
        logmgr_flog()

        dmindent='    '
        dm = self.__tree.find("//dm:docmanager",
                              namespaces=NS)
        log.debug("dm is %s", dm)
        if dm is None:
            return
        log.debug("-----")
        info = dm.getparent() #.getprevious()
        log.info("info: %s", info)
        prev = info.getprevious()
        log.info("prev: %s", prev)
        parent = info.getparent()
        log.info("parent of info: %s", parent)
        log.info("child of info: %s", info.getchildren())

        if info.tail is None:
            info.tail = ""

        infoindent = "".join(info.tail.split('\n'))
        prev = dm.getprevious()
        #log.info("prev: %s", prev)
        if prev is not None:
            log.info("prev: %s", prev)
            prev.tail = '\n' + infoindent
        indent=self.get_indentation(dm.getprevious())
        dm.text = '\n' + indent + '    '
        dm.tail = '\n' + infoindent
        for node in dm.iterchildren():
            i = dmindent if node.getnext() is not None else ''
            node.tail = '\n' + indent + i
Exemple #9
0
    def set(self, arguments):
        """Set key/value pairs from arguments

        :param list arguments: List of arguments with key=value pairs
        """
        logmgr_flog()

        # count all valid and invalid xml files
        validfiles, invalidfiles = self.get_files_status(self.__xml)

        # split key and value
        args = [i.split("=") for i in arguments]

        # iter through all key and values
        for f in self.__files:
            if "error" in self.__xml[f]:
                print("[ {} ] {} -> {}".format(red("error"), f,
                                               red(self.__xml[f]['errorstr'])))
            else:
                for arg in args:
                    try:
                        key, value = arg

                        if key == "languages":
                            value = value.split(",")
                            value = ",".join(
                                self.remove_duplicate_langcodes(value))

                        log.debug(
                            "[%s] Trying to set value for property "
                            "%r to %r.", f, key, value)

                        if self.__args.bugtracker:
                            self.__xml[f]["handler"].set(
                                {"bugtracker/" + key: value})
                        else:
                            self.__xml[f]["handler"].set({key: value})
                    except ValueError:
                        log.error('Invalid usage. '
                                  'Set values with the following format: '
                                  'property=value')
                        sys.exit(ReturnCodes.E_INVALID_USAGE_KEYVAL)

                print("[ {} ] Set data for file {}.".format(green("ok"), f))

        # save the changes
        for f in self.__files:
            if "error" not in self.__xml[f]:
                log.debug("[%s] Trying to save the changes.", f)
                self.__xml[f]["handler"].write()

        # print the statistics output
        print(
            "\nWrote {} valid XML file{} and skipped {} XML file{} due to errors."
            .format(green(validfiles), '' if validfiles == 1 else 's',
                    red(invalidfiles), '' if invalidfiles == 1 else 's'))

        if invalidfiles > 0:
            sys.exit(ReturnCodes.E_SOME_FILES_WERE_INVALID)
Exemple #10
0
    def startDTD(self,  doctype, publicID, systemID): # pylint:disable=unused-argument
        """Signals the start of an DTD declaration

        :param  doctype: name of the root element
        :param publicID: public identifier (or empty)
        :param systemID: system identifier (or empty)
        """
        logmgr_flog()
Exemple #11
0
    def setDocumentLocator(self, locator):
        """Called by the parser to give the application a locator for
           locating the origin of document events.

        :param LocatingWrapper loc: LocatingWrapper object
        """
        logmgr_flog()

        self.loc = locator
Exemple #12
0
    def delete(self, arguments):
        """Delete a property

        :param list arguments:
        """
        logmgr_flog()

        # statistics variables
        file_errors = 0
        props_failed = 0
        props_deleted = 0

        # delete the properties
        for f in self.__files:
            if "error" in self.__xml[f]:
                print("[{}] {} -> {}".format(red(" error "), f,
                                             red(self.__xml[f]["errorstr"])))
                file_errors += 1
            else:
                failed_properties = list()

                for arg in arguments:
                    cond = None
                    prop = arg
                    pos = arg.find("=")

                    # look if there is condition
                    if pos != -1:
                        prop = arg[:pos]
                        cond = arg[pos + 1:]

                    if not self.__xml[f]["handler"].delete(prop, cond):
                        failed_properties.append(arg)
                        props_failed += 1
                    else:
                        props_deleted += 1

                if not failed_properties:
                    print("[{}] {}".format(green(" ok "), f))
                else:
                    print("[{}] {} -> Couldn't delete these properties: {}".
                          format(yellow(" info "), f,
                                 ", ".join(failed_properties)))

        # save changes
        for f in self.__files:
            if "error" not in self.__xml[f]:
                self.__xml[f]["handler"].write()

        # print statistics
        print("")
        print(
            "Deleted successfully {} propert{}, {} propert{} couldn't be deleted, and {} {} invalid."
            .format(green(props_deleted), 'ies' if props_deleted != 1 else 'y',
                    yellow(props_failed), 'ies' if props_failed != 1 else 'y',
                    red(file_errors),
                    'files were' if file_errors != 1 else 'file was'))
Exemple #13
0
def recover_entities(text):
    """Recover any preserved entities in text

    :param str text: the text that should recover entities
    :return: the recovered text
    :rtype: str
    """
    logmgr_flog()

    return STEN.sub(txt2ent, text)
Exemple #14
0
    def where(self, locator):
        """Returns the offset from line and column

        :param locator: locator object
        :return: offset
        :rtype:  int
        """
        logmgr_flog()

        return self.offset[locator.getLineNumber() - 1] + locator.getColumnNumber()
Exemple #15
0
    def parse(self):
        logmgr_flog()

        action = self.__args.action
        if hasattr(self, action) and getattr(self, action) is not None:
            log.debug("Action.__init__: %s", self.__args)
            return getattr(self, action)(self.__args.properties)
        else:
            log.error("Method \"%s\" is not implemented.", action)
            sys.exit(ReturnCodes.E_METHOD_NOT_IMPLEMENTED)
Exemple #16
0
def preserve_entities(text):
    """Preserve any entities in text

    :param str text: the text that should preserve entities
    :return: the preserved text
    :rtype: str
    """
    logmgr_flog()

    return ENTS.sub(ent2txt, text)
Exemple #17
0
def txt2ent(match):
    """Replace any [[[text]]] -> &text;

    :param _sre.SRE_Match match: match object from re
    :return: replaced string
    :rtype: str
    """
    logmgr_flog()

    if match:
        return "&{};".format(match.group(2))
Exemple #18
0
    def check_root_element(self):
        """Checks if root element is valid"""
        logmgr_flog()

        tag = etree.QName(self.__root.tag)
        if tag.localname not in VALIDROOTS:
            raise DMInvalidXMLRootElement("Cannot add info element to file %r. "
                                          "This file does not contain a valid "
                                          "DocBook 5 root element. Found %s",
                                          self._filename, localname(self.__root.tag),
                                          ReturnCodes.E_INVALID_ROOT_ELEMENT)
Exemple #19
0
def check_root_element(rootelem, etree):
    """Checks if root element is valid

    :param object: root element (object)
    :param object: etree element (etree object)"""
    logmgr_flog()

    tag = etree.QName(rootelem.tag)
    if tag.localname not in VALIDROOTS:
        raise DMInvalidXMLRootElement("Cannot add info element to %s. "
                                      "Not a valid root element." % tag.localname,
                                      ReturnCodes.E_INVALID_ROOT_ELEMENT)
Exemple #20
0
    def get_all(self):
        """Returns all keys and values in a docmanager xml file
        """
        logmgr_flog()

        ret = OrderedDict()
        for idx, i in enumerate(self.__docmanager.iter()):
            # we want to skip the "docmanager" element here
            if idx:
                xpath = get_property_xpath(i)
                ret[xpath] = i.text

        return ret
Exemple #21
0
def localname(tag):
    """Returns the local name of an element

    :param str tag: Usually in the form of {http://docbook.org/ns/docbook}article
    :return:  local name
    :rtype:  str
    """
    logmgr_flog()

    m = NAMESPACE_REGEX.search(tag)
    if m:
        return m.groupdict()['local']
    else:
        return tag
Exemple #22
0
def get_namespace(tag):
    """Returns the namespace of an element

    :param str tag: Usually in the form of {http://docbook.org/ns/docbook}article
    :return:        namespace of the element
    :rtype:         str
    """
    logmgr_flog()

    m = NAMESPACE_REGEX.search(tag)
    if m:
        return m.groupdict()['ns']
    else:
        return ''
Exemple #23
0
    def get_indentation(self, node, indentation=""):
        """Calculates indentation level

        :param lxml.etree._Element node: node where to start
        :param str indentation: Additional indentation
        """
        logmgr_flog()
        
        indent = ""
        if node is not None:
            indent = "".join(["".join(n.tail.split("\n"))
                          for n in node.iterancestors()
                            if n.tail is not None ])
        return indent+indentation
Exemple #24
0
def ent2txt(match, start="[[[", end="]]]"):
    """Replace any &text; -> [[[text]]]

    :param _sre.SRE_Match match: match object from re
    :param str start: Start string of entity replacement
    :param str end:   end string
    :return: replaced string
    :rtype: str
    """
    logmgr_flog()

    if match:
        return "{}{}{}".format(start,
                               match.group(2),
                               end)
Exemple #25
0
    def endElement(self, name):
        """Signals the end of an element in non-namespace mode

        :param str name:  XML 1.0 Name of the element
        """
        logmgr_flog()

        eline = self.loc.getLineNumber()
        ecol = self.loc.getColumnNumber()
        last = self.locstm.where(self.loc)
        pos = self.pos(line=eline, col=ecol, offset=last)

        # save the position of an end tag and add '/' in front of the
        # name to distinguish it from a start tag
        self.context.append(["/%s" % name, pos])
Exemple #26
0
def findinfo_pos(root):
    """Find the position where to insert the <info> element

    :return: position where to insert <info>
    :rtype: int
    """
    logmgr_flog()

    titles = root.xpath("(d:title|d:subtitle|d:titleabbrev)[last()]",
                        namespaces=NS)
    if not titles:
        # Just in case we didn't find any titles at all, return null
        return 0

    return root.index(titles[0]) + 1
Exemple #27
0
    def comment(self, text): # pylint: disable=unused-argument
        """Signals an XML comment

        :param str text: text content of the XML comment
        """
        logmgr_flog()

        ctxlen = len(self.context)
        # We are only interested in the first two start tags
        if ctxlen:
            current = self.locstm.where(self.loc)
            pos = self.pos(self.loc.getLineNumber(), \
                           self.loc.getColumnNumber(), \
                           current)
            self.context.append(["-- comment", pos])
Exemple #28
0
    def startElement(self, name, attrs):
        """Signals the start of an element in non-namespace mode

        :param str name:  XML 1.0 Name of the element
        :param Attributes attrs: attributes of the current element
        """
        logmgr_flog()

        ctxlen = len(self.context)
        # We are only interested in the first two start tags
        if ctxlen < 2:
            current = self.locstm.where(self.loc)
            pos = self.pos(self.loc.getLineNumber(), \
                         self.loc.getColumnNumber(), \
                         current)
            self.context.append(["%s" % name, pos])
Exemple #29
0
    def is_prop_set(self, prop):
        """
        Checks if a property is set in an XML element

        :param str prop: the property

        :return: if property is set
        :rtype: bool
        """
        logmgr_flog()

        element = self.__docmanager.find("./dm:{}".format(prop), namespaces=NS)
        if element is not None:
            return True

        return False
Exemple #30
0
    def processingInstruction(self, target, data):
        """Receive notification of a processing instruction (PI)

        :param str target: the target of the PI
        :param str data:   the data of the PI
        """
        logmgr_flog()

        ctxlen = len(self.context)
        # Only append PIs when it's NOT before start-tag
        if ctxlen:
            current = self.locstm.where(self.loc)
            pos = self.pos(self.loc.getLineNumber(), \
                            self.loc.getColumnNumber(), \
                            current)
            self.context.append(["?%s" % target, pos])