Blame itstool.in

Packit Service 7b8cfb
#!@PYTHON@ -s
Packit Service 7b8cfb
#
Packit Service 7b8cfb
# Copyright (c) 2010-2018 Shaun McCance <shaunm@gnome.org>
Packit Service 7b8cfb
#
Packit Service 7b8cfb
# ITS Tool program is free software: you can redistribute it and/or modify
Packit Service 7b8cfb
# it under the terms of the GNU General Public License as published by the
Packit Service 7b8cfb
# Free Software Foundation, either version 3 of the License, or (at your
Packit Service 7b8cfb
# option) any later version.
Packit Service 7b8cfb
#
Packit Service 7b8cfb
# ITS Tool is distributed in the hope that it will be useful, but WITHOUT
Packit Service 7b8cfb
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
Packit Service 7b8cfb
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
Packit Service 7b8cfb
# for more details.
Packit Service 7b8cfb
#
Packit Service 7b8cfb
# You should have received a copy of the GNU General Public License along
Packit Service 7b8cfb
# with ITS Tool; if not, write to the Free Software Foundation, 59 Temple
Packit Service 7b8cfb
# Place, Suite 330, Boston, MA  0211-1307  USA.
Packit Service 7b8cfb
#
Packit Service 7b8cfb
from __future__ import print_function
Packit Service 7b8cfb
from __future__ import unicode_literals
Packit Service 7b8cfb
Packit Service 7b8cfb
VERSION="@VERSION@"
Packit Service 7b8cfb
DATADIR="@DATADIR@"
Packit Service 7b8cfb
Packit Service 7b8cfb
import gettext
Packit Service 7b8cfb
import hashlib
Packit Service 7b8cfb
import libxml2
Packit Service 7b8cfb
import optparse
Packit Service 7b8cfb
import os
Packit Service 7b8cfb
import os.path
Packit Service 7b8cfb
import re
Packit Service 7b8cfb
import sys
Packit Service 7b8cfb
import time
Packit Service 7b8cfb
import io
Packit Service 7b8cfb
Packit Service 7b8cfb
PY3 = sys.version_info[0] == 3
Packit Service 7b8cfb
if PY3:
Packit Service 7b8cfb
    string_types = str,
Packit Service 7b8cfb
    def ustr(s, encoding=None):
Packit Service 7b8cfb
        if isinstance(s, str):
Packit Service 7b8cfb
            return s
Packit Service 7b8cfb
        elif encoding:
Packit Service 7b8cfb
            return str(s, encoding)
Packit Service 7b8cfb
        else:
Packit Service 7b8cfb
            return str(s)
Packit Service 7b8cfb
    ustr_type = str
Packit Service 7b8cfb
else:
Packit Service 7b8cfb
    string_types = basestring,
Packit Service 7b8cfb
    ustr = ustr_type = unicode
Packit Service 7b8cfb
Packit Service 7b8cfb
NS_ITS = 'http://www.w3.org/2005/11/its'
Packit Service 7b8cfb
NS_ITST = 'http://itstool.org/extensions/'
Packit Service 7b8cfb
NS_BLANK = 'http://itstool.org/extensions/blank/'
Packit Service 7b8cfb
NS_XLINK = 'http://www.w3.org/1999/xlink'
Packit Service 7b8cfb
NS_XML = 'http://www.w3.org/XML/1998/namespace'
Packit Service 7b8cfb
Packit Service 7b8cfb
class NoneTranslations:
Packit Service 7b8cfb
    def gettext(self, message):
Packit Service 7b8cfb
        return None
Packit Service 7b8cfb
Packit Service 7b8cfb
    def lgettext(self, message):
Packit Service 7b8cfb
        return None
Packit Service 7b8cfb
Packit Service 7b8cfb
    def ngettext(self, msgid1, msgid2, n):
Packit Service 7b8cfb
        return None
Packit Service 7b8cfb
Packit Service 7b8cfb
    def lngettext(self, msgid1, msgid2, n):
Packit Service 7b8cfb
        return None
Packit Service 7b8cfb
Packit Service 7b8cfb
    def ugettext(self, message):
Packit Service 7b8cfb
        return None
Packit Service 7b8cfb
Packit Service 7b8cfb
    def ungettext(self, msgid1, msgid2, n):
Packit Service 7b8cfb
        return None
Packit Service 7b8cfb
Packit Service 7b8cfb
Packit Service 7b8cfb
class MessageList (object):
Packit Service 7b8cfb
    def __init__ (self):
Packit Service 7b8cfb
        self._messages = []
Packit Service 7b8cfb
        self._by_node = {}
Packit Service 7b8cfb
        self._has_credits = False
Packit Service 7b8cfb
Packit Service 7b8cfb
    def add_message (self, message, node):
Packit Service 7b8cfb
        self._messages.append (message)
Packit Service 7b8cfb
        if node is not None:
Packit Service 7b8cfb
            self._by_node[node] = message
Packit Service 7b8cfb
Packit Service 7b8cfb
    def add_credits(self):
Packit Service 7b8cfb
        if self._has_credits:
Packit Service 7b8cfb
            return
Packit Service 7b8cfb
        msg = Message()
Packit Service 7b8cfb
        msg.set_context('_')
Packit Service 7b8cfb
        msg.add_text('translator-credits')
Packit Service 7b8cfb
        msg.add_comment(Comment('Put one translator per line, in the form NAME <EMAIL>, YEAR1, YEAR2'))
Packit Service 7b8cfb
        self._messages.append(msg)
Packit Service 7b8cfb
        self._has_credits = True
Packit Service 7b8cfb
Packit Service 7b8cfb
    def get_message_by_node (self, node):
Packit Service 7b8cfb
        return self._by_node.get(node, None)
Packit Service 7b8cfb
Packit Service 7b8cfb
    def get_nodes_with_messages (self):
Packit Service 7b8cfb
        return list(self._by_node.keys())
Packit Service 7b8cfb
Packit Service 7b8cfb
    def output (self, out):
Packit Service 7b8cfb
        msgs = []
Packit Service 7b8cfb
        msgdict = {}
Packit Service 7b8cfb
        for msg in self._messages:
Packit Service 7b8cfb
            key = (msg.get_context(), msg.get_string())
Packit Service 7b8cfb
            if key in msgdict:
Packit Service 7b8cfb
                for source in msg.get_sources():
Packit Service 7b8cfb
                    msgdict[key].add_source(source)
Packit Service 7b8cfb
                for marker in msg.get_markers():
Packit Service 7b8cfb
                    msgdict[key].add_marker(marker)
Packit Service 7b8cfb
                for comment in msg.get_comments():
Packit Service 7b8cfb
                    msgdict[key].add_comment(comment)
Packit Service 7b8cfb
                for idvalue in msg.get_id_values():
Packit Service 7b8cfb
                    msgdict[key].add_id_value(idvalue)
Packit Service 7b8cfb
                if msg.get_preserve_space():
Packit Service 7b8cfb
                    msgdict[key].set_preserve_space()
Packit Service 7b8cfb
                if msg.get_locale_filter() is not None:
Packit Service 7b8cfb
                    locale = msgdict[key].get_locale_filter()
Packit Service 7b8cfb
                    if locale is not None:
Packit Service 7b8cfb
                        msgdict[key].set_locale_filter('%s, %s' % (locale, msg.get_locale_filter()))
Packit Service 7b8cfb
                    else:
Packit Service 7b8cfb
                        msgdict[key].set_locale_filter(msg.get_locale_filter())
Packit Service 7b8cfb
Packit Service 7b8cfb
            else:
Packit Service 7b8cfb
                msgs.append(msg)
Packit Service 7b8cfb
                msgdict[key] = msg
Packit Service 7b8cfb
        out.write('msgid ""\n')
Packit Service 7b8cfb
        out.write('msgstr ""\n')
Packit Service 7b8cfb
        out.write('"Project-Id-Version: PACKAGE VERSION\\n"\n')
Packit Service 7b8cfb
        out.write('"POT-Creation-Date: %s\\n"\n' % time.strftime("%Y-%m-%d %H:%M%z"))
Packit Service 7b8cfb
        out.write('"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n"\n')
Packit Service 7b8cfb
        out.write('"Last-Translator: FULL NAME <EMAIL@ADDRESS>\\n"\n')
Packit Service 7b8cfb
        out.write('"Language-Team: LANGUAGE <LL@li.org>\\n"\n')
Packit Service 7b8cfb
        out.write('"MIME-Version: 1.0\\n"\n')
Packit Service 7b8cfb
        out.write('"Content-Type: text/plain; charset=UTF-8\\n"\n')
Packit Service 7b8cfb
        out.write('"Content-Transfer-Encoding: 8bit\\n"\n')
Packit Service 7b8cfb
        out.write('\n')
Packit Service 7b8cfb
        for msg in msgs:
Packit Service 7b8cfb
            out.write(msg.format())
Packit Service 7b8cfb
            out.write('\n')
Packit Service 7b8cfb
Packit Service 7b8cfb
Packit Service 7b8cfb
class Comment (object):
Packit Service 7b8cfb
    def __init__ (self, text):
Packit Service 7b8cfb
        self._text = ustr(text)
Packit Service 7b8cfb
        assert(text is not None)
Packit Service 7b8cfb
        self._markers = []
Packit Service 7b8cfb
Packit Service 7b8cfb
    def add_marker (self, marker):
Packit Service 7b8cfb
        self._markers.append(marker)
Packit Service 7b8cfb
Packit Service 7b8cfb
    def get_markers (self):
Packit Service 7b8cfb
        return self._markers
Packit Service 7b8cfb
Packit Service 7b8cfb
    def get_text (self):
Packit Service 7b8cfb
        return self._text
Packit Service 7b8cfb
Packit Service 7b8cfb
    def format (self):
Packit Service 7b8cfb
        ret = ''
Packit Service 7b8cfb
        markers = {}
Packit Service 7b8cfb
        for marker in self._markers:
Packit Service 7b8cfb
            if marker not in markers:
Packit Service 7b8cfb
                ret += '#. (itstool) comment: ' + marker + '\n'
Packit Service 7b8cfb
                markers[marker] = marker
Packit Service 7b8cfb
        if '\n' in self._text:
Packit Service 7b8cfb
            doadd = False
Packit Service 7b8cfb
            for line in self._text.split('\n'):
Packit Service 7b8cfb
                if line != '':
Packit Service 7b8cfb
                    doadd = True
Packit Service 7b8cfb
                if not doadd:
Packit Service 7b8cfb
                    continue
Packit Service 7b8cfb
                ret += '#. %s\n' % line
Packit Service 7b8cfb
        else:
Packit Service 7b8cfb
            text = self._text
Packit Service 7b8cfb
            while len(text) > 72:
Packit Service 7b8cfb
                j = text.rfind(' ', 0, 72)
Packit Service 7b8cfb
                if j == -1:
Packit Service 7b8cfb
                    j = text.find(' ')
Packit Service 7b8cfb
                if j == -1:
Packit Service 7b8cfb
                    break
Packit Service 7b8cfb
                ret += '#. %s\n' % text[:j]
Packit Service 7b8cfb
                text = text[j+1:]
Packit Service 7b8cfb
            ret += '#. %s\n' % text
Packit Service 7b8cfb
        return ret
Packit Service 7b8cfb
Packit Service 7b8cfb
Packit Service 7b8cfb
class Placeholder (object):
Packit Service 7b8cfb
    def __init__ (self, node):
Packit Service 7b8cfb
        self.node = node
Packit Service 7b8cfb
        self.name = ustr(node.name, 'utf-8')
Packit Service 7b8cfb
Packit Service 7b8cfb
Packit Service 7b8cfb
class Message (object):
Packit Service 7b8cfb
    def __init__ (self):
Packit Service 7b8cfb
        self._message = []
Packit Service 7b8cfb
        self._empty = True
Packit Service 7b8cfb
        self._ctxt = None
Packit Service 7b8cfb
        self._placeholders = []
Packit Service 7b8cfb
        self._sources = []
Packit Service 7b8cfb
        self._markers = []
Packit Service 7b8cfb
        self._id_values = []
Packit Service 7b8cfb
        self._locale_filter = None
Packit Service 7b8cfb
        self._comments = []
Packit Service 7b8cfb
        self._preserve = False
Packit Service 7b8cfb
Packit Service 7b8cfb
    def __repr__(self):
Packit Service 7b8cfb
        if self._empty:
Packit Service 7b8cfb
            return "Empty message"
Packit Service 7b8cfb
        return self.get_string()
Packit Service 7b8cfb
Packit Service 7b8cfb
    def escape (self, text):
Packit Service 7b8cfb
        return text.replace('\\','\\\\').replace('"', "\\\"").replace("\n","\\n").replace("\t","\\t")
Packit Service 7b8cfb
Packit Service 7b8cfb
    def add_text (self, text):
Packit Service 7b8cfb
        if len(self._message) == 0 or not(isinstance(self._message[-1], string_types)):
Packit Service 7b8cfb
            self._message.append('')
Packit Service 7b8cfb
        if not isinstance(text, ustr_type):
Packit Service 7b8cfb
            text = ustr(text, 'utf-8')
Packit Service 7b8cfb
        self._message[-1] += text.replace('&', '&').replace('<', '<').replace('>', '>')
Packit Service 7b8cfb
        if re.sub('\s+', ' ', text).strip() != '':
Packit Service 7b8cfb
            self._empty = False
Packit Service 7b8cfb
Packit Service 7b8cfb
    def add_entity_ref (self, name):
Packit Service 7b8cfb
        self._message.append('&' + name + ';')
Packit Service 7b8cfb
        self._empty = False
Packit Service 7b8cfb
Packit Service 7b8cfb
    def add_placeholder (self, node):
Packit Service 7b8cfb
        holder = Placeholder(node)
Packit Service 7b8cfb
        self._placeholders.append(holder)
Packit Service 7b8cfb
        self._message.append(holder)
Packit Service 7b8cfb
Packit Service 7b8cfb
    def get_placeholder (self, name):
Packit Service 7b8cfb
        placeholder = 1
Packit Service 7b8cfb
        for holder in self._placeholders:
Packit Service 7b8cfb
            holdername = '%s-%i' % (holder.name, placeholder)
Packit Service 7b8cfb
            if holdername == ustr(name, 'utf-8'):
Packit Service 7b8cfb
                return holder
Packit Service 7b8cfb
            placeholder += 1
Packit Service 7b8cfb
Packit Service 7b8cfb
    def add_start_tag (self, node):
Packit Service 7b8cfb
        if len(self._message) == 0 or not(isinstance(self._message[-1], string_types)):
Packit Service 7b8cfb
            self._message.append('')
Packit Service 7b8cfb
        if node.ns() is not None and node.ns().name is not None:
Packit Service 7b8cfb
            self._message[-1] += ('<%s:%s' % (ustr(node.ns().name, 'utf-8'), ustr(node.name, 'utf-8')))
Packit Service 7b8cfb
        else:
Packit Service 7b8cfb
            self._message[-1] += ('<%s' % ustr(node.name, 'utf-8'))
Packit Service 7b8cfb
        for prop in xml_attr_iter(node):
Packit Service 7b8cfb
            name = prop.name
Packit Service 7b8cfb
            if prop.ns() is not None:
Packit Service 7b8cfb
                name = prop.ns().name + ':' + name
Packit Service 7b8cfb
            atval = prop.content
Packit Service 7b8cfb
            if not isinstance(atval, ustr_type):
Packit Service 7b8cfb
                atval = ustr(atval, 'utf-8')
Packit Service 7b8cfb
            atval = atval.replace('&', '&').replace('<', '<').replace('>', '>').replace('"', '"')
Packit Service 7b8cfb
            self._message += " %s=\"%s\"" % (name, atval)
Packit Service 7b8cfb
        if node.children is not None:
Packit Service 7b8cfb
            self._message[-1] += '>'
Packit Service 7b8cfb
        else:
Packit Service 7b8cfb
            self._message[-1] += '/>'
Packit Service 7b8cfb
Packit Service 7b8cfb
    def add_end_tag (self, node):
Packit Service 7b8cfb
        if node.children is not None:
Packit Service 7b8cfb
            if len(self._message) == 0 or not(isinstance(self._message[-1], string_types)):
Packit Service 7b8cfb
                self._message.append('')
Packit Service 7b8cfb
            if node.ns() is not None and node.ns().name is not None:
Packit Service 7b8cfb
                self._message[-1] += ('</%s:%s>' % (ustr(node.ns().name, 'utf-8'), ustr(node.name, 'utf-8')))
Packit Service 7b8cfb
            else:
Packit Service 7b8cfb
                self._message[-1] += ('</%s>' % ustr(node.name, 'utf-8'))
Packit Service 7b8cfb
Packit Service 7b8cfb
    def is_empty (self):
Packit Service 7b8cfb
        return self._empty
Packit Service 7b8cfb
Packit Service 7b8cfb
    def get_context (self):
Packit Service 7b8cfb
        return self._ctxt
Packit Service 7b8cfb
Packit Service 7b8cfb
    def set_context (self, ctxt):
Packit Service 7b8cfb
        self._ctxt = ctxt
Packit Service 7b8cfb
Packit Service 7b8cfb
    def add_source (self, source):
Packit Service 7b8cfb
        if not isinstance(source, ustr_type):
Packit Service 7b8cfb
            source = ustr(source, 'utf-8')
Packit Service 7b8cfb
        self._sources.append(source)
Packit Service 7b8cfb
Packit Service 7b8cfb
    def get_sources (self):
Packit Service 7b8cfb
        return self._sources
Packit Service 7b8cfb
Packit Service 7b8cfb
    def add_marker (self, marker):
Packit Service 7b8cfb
        if not isinstance(marker, ustr_type):
Packit Service 7b8cfb
            marker = ustr(marker, 'utf-8')
Packit Service 7b8cfb
        self._markers.append(marker)
Packit Service 7b8cfb
Packit Service 7b8cfb
    def get_markers (self):
Packit Service 7b8cfb
        return self._markers
Packit Service 7b8cfb
Packit Service 7b8cfb
    def add_id_value(self, id_value):
Packit Service 7b8cfb
        self._id_values.append(id_value)
Packit Service 7b8cfb
Packit Service 7b8cfb
    def get_id_values(self):
Packit Service 7b8cfb
        return self._id_values
Packit Service 7b8cfb
Packit Service 7b8cfb
    def add_comment (self, comment):
Packit Service 7b8cfb
        if comment is not None:
Packit Service 7b8cfb
            self._comments.append(comment)
Packit Service 7b8cfb
Packit Service 7b8cfb
    def get_comments (self):
Packit Service 7b8cfb
        return self._comments
Packit Service 7b8cfb
Packit Service 7b8cfb
    def get_string (self):
Packit Service 7b8cfb
        message = ''
Packit Service 7b8cfb
        placeholder = 1
Packit Service 7b8cfb
        for msg in self._message:
Packit Service 7b8cfb
            if isinstance(msg, string_types):
Packit Service 7b8cfb
                message += msg
Packit Service 7b8cfb
            elif isinstance(msg, Placeholder):
Packit Service 7b8cfb
                message += '<_:%s-%i/>' % (msg.name, placeholder)
Packit Service 7b8cfb
                placeholder += 1
Packit Service 7b8cfb
        if not self._preserve:
Packit Service 7b8cfb
            message = re.sub('\s+', ' ', message).strip()
Packit Service 7b8cfb
        return message
Packit Service 7b8cfb
Packit Service 7b8cfb
    def get_preserve_space (self):
Packit Service 7b8cfb
        return self._preserve
Packit Service 7b8cfb
Packit Service 7b8cfb
    def set_preserve_space (self, preserve=True):
Packit Service 7b8cfb
        self._preserve = preserve
Packit Service 7b8cfb
Packit Service 7b8cfb
    def get_locale_filter(self):
Packit Service 7b8cfb
        return self._locale_filter
Packit Service 7b8cfb
Packit Service 7b8cfb
    def set_locale_filter(self, locale):
Packit Service 7b8cfb
        self._locale_filter = locale
Packit Service 7b8cfb
Packit Service 7b8cfb
    def format (self):
Packit Service 7b8cfb
        ret = ''
Packit Service 7b8cfb
        markers = {}
Packit Service 7b8cfb
        for marker in self._markers:
Packit Service 7b8cfb
            if marker not in markers:
Packit Service 7b8cfb
                ret += '#. (itstool) path: ' + marker + '\n'
Packit Service 7b8cfb
                markers[marker] = marker
Packit Service 7b8cfb
        for idvalue in self._id_values:
Packit Service 7b8cfb
            ret += '#. (itstool) id: ' + idvalue + '\n'
Packit Service 7b8cfb
        if self._locale_filter is not None:
Packit Service 7b8cfb
            ret += '#. (itstool) ' + self._locale_filter[1] + ' locale: ' + self._locale_filter[0] + '\n'
Packit Service 7b8cfb
        comments = []
Packit Service 7b8cfb
        commentsdict = {}
Packit Service 7b8cfb
        for comment in self._comments:
Packit Service 7b8cfb
            key = comment.get_text()
Packit Service 7b8cfb
            if key in commentsdict:
Packit Service 7b8cfb
                for marker in comment.get_markers():
Packit Service 7b8cfb
                    commentsdict[key].add_marker(marker)
Packit Service 7b8cfb
            else:
Packit Service 7b8cfb
                comments.append(comment)
Packit Service 7b8cfb
                commentsdict[key] = comment
Packit Service 7b8cfb
        for i in range(len(comments)):
Packit Service 7b8cfb
            if i != 0:
Packit Service 7b8cfb
                ret += '#.\n'
Packit Service 7b8cfb
            ret += comments[i].format()
Packit Service 7b8cfb
        for source in self._sources:
Packit Service 7b8cfb
            ret += '#: %s\n' % source
Packit Service 7b8cfb
        if self._preserve:
Packit Service 7b8cfb
            ret += '#, no-wrap\n'
Packit Service 7b8cfb
        if self._ctxt is not None:
Packit Service 7b8cfb
            ret += 'msgctxt "%s"\n' % self._ctxt
Packit Service 7b8cfb
        message = self.get_string()
Packit Service 7b8cfb
        if self._preserve:
Packit Service 7b8cfb
            ret += 'msgid ""\n'
Packit Service 7b8cfb
            lines = message.split('\n')
Packit Service 7b8cfb
            for line, no in zip(lines, list(range(len(lines)))):
Packit Service 7b8cfb
                if no == len(lines) - 1:
Packit Service 7b8cfb
                    ret += '"%s"\n' % self.escape(line)
Packit Service 7b8cfb
                else:
Packit Service 7b8cfb
                    ret += '"%s\\n"\n' % self.escape(line)
Packit Service 7b8cfb
        else:
Packit Service 7b8cfb
            ret += 'msgid "%s"\n' % self.escape(message)
Packit Service 7b8cfb
        ret += 'msgstr ""\n'
Packit Service 7b8cfb
        return ret
Packit Service 7b8cfb
Packit Service 7b8cfb
Packit Service 7b8cfb
def xml_child_iter (node):
Packit Service 7b8cfb
    child = node.children
Packit Service 7b8cfb
    while child is not None:
Packit Service 7b8cfb
        yield child
Packit Service 7b8cfb
        child = child.next
Packit Service 7b8cfb
Packit Service 7b8cfb
def xml_attr_iter (node):
Packit Service 7b8cfb
    attr = node.get_properties()
Packit Service 7b8cfb
    while attr is not None:
Packit Service 7b8cfb
        yield attr
Packit Service 7b8cfb
        attr = attr.next
Packit Service 7b8cfb
Packit Service 7b8cfb
def xml_is_ns_name (node, ns, name):
Packit Service 7b8cfb
    if node.type != 'element':
Packit Service 7b8cfb
        return False
Packit Service 7b8cfb
    return node.name == name and node.ns() is not None and node.ns().content == ns
Packit Service 7b8cfb
Packit Service 7b8cfb
def xml_get_node_path(node):
Packit Service 7b8cfb
    # The built-in nodePath() method only does numeric indexes
Packit Service 7b8cfb
    # when necessary for disambiguation. For various reasons,
Packit Service 7b8cfb
    # we prefer always using indexes.
Packit Service 7b8cfb
    name = node.name
Packit Service 7b8cfb
    if node.ns() is not None and node.ns().name is not None:
Packit Service 7b8cfb
        name = node.ns().name + ':' + name
Packit Service 7b8cfb
    if node.type == 'attribute':
Packit Service 7b8cfb
        name = '@' + name
Packit Service 7b8cfb
    name = '/' + name
Packit Service 7b8cfb
    if node.type == 'element' and node.parent.type == 'element':
Packit Service 7b8cfb
        count = 1
Packit Service 7b8cfb
        prev = node.previousElementSibling()
Packit Service 7b8cfb
        while prev is not None:
Packit Service 7b8cfb
            if prev.name == node.name:
Packit Service 7b8cfb
                if prev.ns() is None:
Packit Service 7b8cfb
                    if node.ns() is None:
Packit Service 7b8cfb
                        count += 1
Packit Service 7b8cfb
                else:
Packit Service 7b8cfb
                    if node.ns() is not None:
Packit Service 7b8cfb
                        if prev.ns().name == node.ns().name:
Packit Service 7b8cfb
                            count += 1
Packit Service 7b8cfb
            prev = prev.previousElementSibling()
Packit Service 7b8cfb
        name = '%s[%i]' % (name, count)
Packit Service 7b8cfb
    if node.parent.type == 'element':
Packit Service 7b8cfb
        name = xml_get_node_path(node.parent) + name
Packit Service 7b8cfb
    return name
Packit Service 7b8cfb
Packit Service 7b8cfb
def xml_error_catcher(doc, error):
Packit Service 7b8cfb
    doc._xml_err += " %s" % error
Packit Service 7b8cfb
Packit Service 7b8cfb
def fix_node_ns (node, nsdefs):
Packit Service 7b8cfb
    childnsdefs = nsdefs.copy()
Packit Service 7b8cfb
    nsdef = node.nsDefs()
Packit Service 7b8cfb
    while nsdef is not None:
Packit Service 7b8cfb
        nextnsdef = nsdef.next
Packit Service 7b8cfb
        if nsdef.name in nsdefs and nsdefs[nsdef.name] == nsdef.content:
Packit Service 7b8cfb
            node.removeNsDef(nsdef.content)
Packit Service 7b8cfb
        else:
Packit Service 7b8cfb
            childnsdefs[nsdef.name] = nsdef.content
Packit Service 7b8cfb
        nsdef = nextnsdef
Packit Service 7b8cfb
    for child in xml_child_iter(node):
Packit Service 7b8cfb
        if child.type == 'element':
Packit Service 7b8cfb
            fix_node_ns(child, childnsdefs)
Packit Service 7b8cfb
Packit Service 7b8cfb
Packit Service 7b8cfb
class LocNote (object):
Packit Service 7b8cfb
    def __init__(self, locnote=None, locnoteref=None, locnotetype=None, space=False):
Packit Service 7b8cfb
        self.locnote = locnote
Packit Service 7b8cfb
        self.locnoteref = locnoteref
Packit Service 7b8cfb
        self.locnotetype = locnotetype
Packit Service 7b8cfb
        if self.locnotetype != 'alert':
Packit Service 7b8cfb
            self.locnotetype = 'description'
Packit Service 7b8cfb
        self._preserve_space=space
Packit Service 7b8cfb
Packit Service 7b8cfb
    def __repr__(self):
Packit Service 7b8cfb
        if self.locnote is not None:
Packit Service 7b8cfb
            if self._preserve_space:
Packit Service 7b8cfb
                return self.locnote
Packit Service 7b8cfb
            else:
Packit Service 7b8cfb
                return re.sub('\s+', ' ', self.locnote).strip()
Packit Service 7b8cfb
        elif self.locnoteref is not None:
Packit Service 7b8cfb
            return '(itstool) link: ' + re.sub('\s+', ' ', self.locnoteref).strip()
Packit Service 7b8cfb
        return ''
Packit Service 7b8cfb
Packit Service 7b8cfb
Packit Service 7b8cfb
class Document (object):
Packit Service 7b8cfb
    def __init__ (self, filename, messages, load_dtd=False, keep_entities=False):
Packit Service 7b8cfb
        self._xml_err = ''
Packit Service 7b8cfb
        libxml2.registerErrorHandler(xml_error_catcher, self)
Packit Service 7b8cfb
        try:
Packit Service 7b8cfb
            ctxt = libxml2.createFileParserCtxt(filename)
Packit Service 7b8cfb
        except:
Packit Service 7b8cfb
            sys.stderr.write('Error: cannot open XML file %s\n' % filename)
Packit Service 7b8cfb
            sys.exit(1)
Packit Service 7b8cfb
        ctxt.lineNumbers(1)
Packit Service 7b8cfb
        self._load_dtd = load_dtd
Packit Service 7b8cfb
        self._keep_entities = keep_entities
Packit Service 7b8cfb
        if load_dtd:
Packit Service 7b8cfb
            ctxt.loadSubset(1)
Packit Service 7b8cfb
        if keep_entities:
Packit Service 7b8cfb
            ctxt.loadSubset(1)
Packit Service 7b8cfb
            ctxt.ctxtUseOptions(libxml2.XML_PARSE_DTDLOAD)
Packit Service 7b8cfb
            ctxt.replaceEntities(0)
Packit Service 7b8cfb
        else:
Packit Service 7b8cfb
            ctxt.replaceEntities(1)
Packit Service 7b8cfb
        ctxt.parseDocument()
Packit Service 7b8cfb
        self._filename = filename
Packit Service 7b8cfb
        self._doc = ctxt.doc()
Packit Service 7b8cfb
        self._localrules = []
Packit Service 7b8cfb
        def pre_process (node):
Packit Service 7b8cfb
            for child in xml_child_iter(node):
Packit Service 7b8cfb
                if xml_is_ns_name(child, 'http://www.w3.org/2001/XInclude', 'include'):
Packit Service 7b8cfb
                    if child.nsProp('parse', None) == 'text':
Packit Service 7b8cfb
                        child.xincludeProcessTree()
Packit Service 7b8cfb
                elif xml_is_ns_name(child, NS_ITS, 'rules'):
Packit Service 7b8cfb
                    if child.hasNsProp('href', NS_XLINK):
Packit Service 7b8cfb
                        href = child.nsProp('href', NS_XLINK)
Packit Service 7b8cfb
                        fileref = os.path.join(os.path.dirname(filename), href)
Packit Service 7b8cfb
                        if not os.path.exists(fileref):
Packit Service 7b8cfb
                            if opts.itspath is not None:
Packit Service 7b8cfb
                                for pathdir in opts.itspath:
Packit Service 7b8cfb
                                    fileref = os.path.join(pathdir, href)
Packit Service 7b8cfb
                                    if os.path.exists(fileref):
Packit Service 7b8cfb
                                        break
Packit Service 7b8cfb
                        if not os.path.exists(fileref):
Packit Service 7b8cfb
                            sys.stderr.write('Error: Could not locate ITS file %s\n' % href)
Packit Service 7b8cfb
                            sys.exit(1)
Packit Service 7b8cfb
                        hctxt = libxml2.createFileParserCtxt(fileref)
Packit Service 7b8cfb
                        hctxt.replaceEntities(1)
Packit Service 7b8cfb
                        hctxt.parseDocument()
Packit Service 7b8cfb
                        root = hctxt.doc().getRootElement()
Packit Service 7b8cfb
                        version = None
Packit Service 7b8cfb
                        if root.hasNsProp('version', None):
Packit Service 7b8cfb
                            version = root.nsProp('version', None)
Packit Service 7b8cfb
                        else:
Packit Service 7b8cfb
                            sys.stderr.write('Warning: ITS file %s missing version attribute\n' %
Packit Service 7b8cfb
                                             os.path.basename(href))
Packit Service 7b8cfb
                        if version is not None and version not in ('1.0', '2.0'):
Packit Service 7b8cfb
                            sys.stderr.write('Warning: Skipping ITS file %s with unknown version %s\n' %
Packit Service 7b8cfb
                                             (os.path.basename(href), root.nsProp('version', None)))
Packit Service 7b8cfb
                        else:
Packit Service 7b8cfb
                            self._localrules.append(root)
Packit Service 7b8cfb
                    version = None
Packit Service 7b8cfb
                    if child.hasNsProp('version', None):
Packit Service 7b8cfb
                        version = child.nsProp('version', None)
Packit Service 7b8cfb
                    else:
Packit Service 7b8cfb
                        root = child.doc.getRootElement()
Packit Service 7b8cfb
                        if root.hasNsProp('version', NS_ITS):
Packit Service 7b8cfb
                            version = root.nsProp('version', NS_ITS)
Packit Service 7b8cfb
                        else:
Packit Service 7b8cfb
                            sys.stderr.write('Warning: Local ITS rules missing version attribute\n')
Packit Service 7b8cfb
                    if version is not None and version not in ('1.0', '2.0'):
Packit Service 7b8cfb
                        sys.stderr.write('Warning: Skipping local ITS rules with unknown version %s\n' %
Packit Service 7b8cfb
                                         version)
Packit Service 7b8cfb
                    else:
Packit Service 7b8cfb
                        self._localrules.append(child)
Packit Service 7b8cfb
                pre_process(child)
Packit Service 7b8cfb
        pre_process(self._doc)
Packit Service 7b8cfb
        try:
Packit Service 7b8cfb
            self._check_errors()
Packit Service 7b8cfb
        except libxml2.parserError as e:
Packit Service 7b8cfb
            sys.stderr.write('Error: Could not parse document:\n%s\n' % ustr(e))
Packit Service 7b8cfb
            sys.exit(1)
Packit Service 7b8cfb
        self._msgs = messages
Packit Service 7b8cfb
        self._its_translate_nodes = {}
Packit Service 7b8cfb
        self._its_within_text_nodes = {}
Packit Service 7b8cfb
        self._its_locale_filters = {}
Packit Service 7b8cfb
        self._its_id_values = {}
Packit Service 7b8cfb
        self._its_loc_notes = {}
Packit Service 7b8cfb
        self._its_preserve_space_nodes = {}
Packit Service 7b8cfb
        self._itst_drop_nodes = {}
Packit Service 7b8cfb
        self._itst_contexts = {}
Packit Service 7b8cfb
        self._its_lang = {}
Packit Service 7b8cfb
        self._itst_lang_attr = {}
Packit Service 7b8cfb
        self._itst_credits = None
Packit Service 7b8cfb
        self._its_externals = {}
Packit Service 7b8cfb
Packit Service 7b8cfb
    def __del__ (self):
Packit Service 7b8cfb
        self._doc.freeDoc()
Packit Service 7b8cfb
Packit Service 7b8cfb
    def _check_errors(self):
Packit Service 7b8cfb
        if self._xml_err:
Packit Service 7b8cfb
            raise libxml2.parserError(self._xml_err)
Packit Service 7b8cfb
Packit Service 7b8cfb
    def register_its_params(self, xpath, rules, params={}):
Packit Service 7b8cfb
        for child in xml_child_iter(rules):
Packit Service 7b8cfb
            if xml_is_ns_name(child, NS_ITS, 'param'):
Packit Service 7b8cfb
                name = child.nsProp('name', None)
Packit Service 7b8cfb
                if name in params:
Packit Service 7b8cfb
                    value = params[name]
Packit Service 7b8cfb
                else:
Packit Service 7b8cfb
                    value = child.getContent()
Packit Service 7b8cfb
                xpath.xpathRegisterVariable(name, None, value)
Packit Service 7b8cfb
Packit Service 7b8cfb
    def apply_its_rule(self, rule, xpath):
Packit Service 7b8cfb
        if rule.type != 'element':
Packit Service 7b8cfb
            return
Packit Service 7b8cfb
        if xml_is_ns_name(rule, NS_ITS, 'translateRule'):
Packit Service 7b8cfb
            if rule.nsProp('selector', None) is not None:
Packit Service 7b8cfb
                for node in self._try_xpath_eval(xpath, rule.nsProp('selector', None)):
Packit Service 7b8cfb
                    self._its_translate_nodes[node] = rule.nsProp('translate', None)
Packit Service 7b8cfb
        elif xml_is_ns_name(rule, NS_ITS, 'withinTextRule'):
Packit Service 7b8cfb
            if rule.nsProp('selector', None) is not None:
Packit Service 7b8cfb
                for node in self._try_xpath_eval(xpath, rule.nsProp('selector', None)):
Packit Service 7b8cfb
                    self._its_within_text_nodes[node] = rule.nsProp('withinText', None)
Packit Service 7b8cfb
        elif xml_is_ns_name(rule, NS_ITST, 'preserveSpaceRule'):
Packit Service 7b8cfb
            if rule.nsProp('selector', None) is not None:
Packit Service 7b8cfb
                for node in self._try_xpath_eval(xpath, rule.nsProp('selector', None)):
Packit Service 7b8cfb
                    val = rule.nsProp('preserveSpace', None)
Packit Service 7b8cfb
                    if val == 'yes':
Packit Service 7b8cfb
                        self._its_preserve_space_nodes[node] = 'preserve'
Packit Service 7b8cfb
        elif xml_is_ns_name(rule, NS_ITS, 'preserveSpaceRule'):
Packit Service 7b8cfb
            if rule.nsProp('selector', None) is not None:
Packit Service 7b8cfb
                for node in self._try_xpath_eval(xpath, rule.nsProp('selector', None)):
Packit Service 7b8cfb
                    self._its_preserve_space_nodes[node] = rule.nsProp('space', None)
Packit Service 7b8cfb
        elif xml_is_ns_name(rule, NS_ITS, 'localeFilterRule'):
Packit Service 7b8cfb
            if rule.nsProp('selector', None) is not None:
Packit Service 7b8cfb
                if rule.hasNsProp('localeFilterList', None):
Packit Service 7b8cfb
                    lst = rule.nsProp('localeFilterList', None)
Packit Service 7b8cfb
                else:
Packit Service 7b8cfb
                    lst = '*'
Packit Service 7b8cfb
                if rule.hasNsProp('localeFilterType', None):
Packit Service 7b8cfb
                    typ = rule.nsProp('localeFilterType', None)
Packit Service 7b8cfb
                else:
Packit Service 7b8cfb
                    typ = 'include'
Packit Service 7b8cfb
                for node in self._try_xpath_eval(xpath, rule.nsProp('selector', None)):
Packit Service 7b8cfb
                    self._its_locale_filters[node] = (lst, typ)
Packit Service 7b8cfb
        elif xml_is_ns_name(rule, NS_ITST, 'dropRule'):
Packit Service 7b8cfb
            if rule.nsProp('selector', None) is not None:
Packit Service 7b8cfb
                for node in self._try_xpath_eval(xpath, rule.nsProp('selector', None)):
Packit Service 7b8cfb
                    self._itst_drop_nodes[node] = rule.nsProp('drop', None)
Packit Service 7b8cfb
        elif xml_is_ns_name(rule, NS_ITS, 'idValueRule'):
Packit Service 7b8cfb
            sel = rule.nsProp('selector', None)
Packit Service 7b8cfb
            idv = rule.nsProp('idValue', None)
Packit Service 7b8cfb
            if sel is not None and idv is not None:
Packit Service 7b8cfb
                for node in self._try_xpath_eval(xpath, sel):
Packit Service 7b8cfb
                    try:
Packit Service 7b8cfb
                        oldnode = xpath.contextNode()
Packit Service 7b8cfb
                    except:
Packit Service 7b8cfb
                        oldnode = None
Packit Service 7b8cfb
                    xpath.setContextNode(node)
Packit Service 7b8cfb
                    idvalue = self._try_xpath_eval(xpath, idv)
Packit Service 7b8cfb
                    if isinstance(idvalue, string_types):
Packit Service 7b8cfb
                        self._its_id_values[node] = idvalue
Packit Service 7b8cfb
                    else:
Packit Service 7b8cfb
                        for val in idvalue:
Packit Service 7b8cfb
                            self._its_id_values[node] = val.content
Packit Service 7b8cfb
                            break
Packit Service 7b8cfb
                    xpath.setContextNode(oldnode)
Packit Service 7b8cfb
            pass
Packit Service 7b8cfb
        elif xml_is_ns_name(rule, NS_ITST, 'contextRule'):
Packit Service 7b8cfb
            if rule.nsProp('selector', None) is not None:
Packit Service 7b8cfb
                for node in self._try_xpath_eval(xpath, rule.nsProp('selector', None)):
Packit Service 7b8cfb
                    if rule.hasNsProp('context', None):
Packit Service 7b8cfb
                        self._itst_contexts[node] = rule.nsProp('context', None)
Packit Service 7b8cfb
                    elif rule.hasNsProp('contextPointer', None):
Packit Service 7b8cfb
                        try:
Packit Service 7b8cfb
                            oldnode = xpath.contextNode()
Packit Service 7b8cfb
                        except:
Packit Service 7b8cfb
                            oldnode = None
Packit Service 7b8cfb
                        xpath.setContextNode(node)
Packit Service 7b8cfb
                        ctxt = self._try_xpath_eval(xpath, rule.nsProp('contextPointer', None))
Packit Service 7b8cfb
                        if isinstance(ctxt, string_types):
Packit Service 7b8cfb
                            self._itst_contexts[node] = ctxt
Packit Service 7b8cfb
                        else:
Packit Service 7b8cfb
                            for ctxt in ctxt:
Packit Service 7b8cfb
                                self._itst_contexts[node] = ctxt.content
Packit Service 7b8cfb
                                break
Packit Service 7b8cfb
                        xpath.setContextNode(oldnode)
Packit Service 7b8cfb
        elif xml_is_ns_name(rule, NS_ITS, 'locNoteRule'):
Packit Service 7b8cfb
            locnote = None
Packit Service 7b8cfb
            notetype = rule.nsProp('locNoteType', None)
Packit Service 7b8cfb
            for child in xml_child_iter(rule):
Packit Service 7b8cfb
                if xml_is_ns_name(child, NS_ITS, 'locNote'):
Packit Service 7b8cfb
                    locnote = LocNote(locnote=child.content, locnotetype=notetype)
Packit Service 7b8cfb
                    break
Packit Service 7b8cfb
            if locnote is None:
Packit Service 7b8cfb
                if rule.hasNsProp('locNoteRef', None):
Packit Service 7b8cfb
                    locnote = LocNote(locnoteref=rule.nsProp('locNoteRef', None), locnotetype=notetype)
Packit Service 7b8cfb
            if rule.nsProp('selector', None) is not None:
Packit Service 7b8cfb
                for node in self._try_xpath_eval(xpath, rule.nsProp('selector', None)):
Packit Service 7b8cfb
                    if locnote is not None:
Packit Service 7b8cfb
                        self._its_loc_notes.setdefault(node, []).append(locnote)
Packit Service 7b8cfb
                    else:
Packit Service 7b8cfb
                        if rule.hasNsProp('locNotePointer', None):
Packit Service 7b8cfb
                            sel = rule.nsProp('locNotePointer', None)
Packit Service 7b8cfb
                            ref = False
Packit Service 7b8cfb
                        elif rule.hasNsProp('locNoteRefPointer', None):
Packit Service 7b8cfb
                            sel = rule.nsProp('locNoteRefPointer', None)
Packit Service 7b8cfb
                            ref = True
Packit Service 7b8cfb
                        else:
Packit Service 7b8cfb
                            continue
Packit Service 7b8cfb
                        try:
Packit Service 7b8cfb
                            oldnode = xpath.contextNode()
Packit Service 7b8cfb
                        except:
Packit Service 7b8cfb
                            oldnode = None
Packit Service 7b8cfb
                        xpath.setContextNode(node)
Packit Service 7b8cfb
                        note = self._try_xpath_eval(xpath, sel)
Packit Service 7b8cfb
                        if isinstance(note, string_types):
Packit Service 7b8cfb
                            if ref:
Packit Service 7b8cfb
                                nodenote = LocNote(locnoteref=note, locnotetype=notetype)
Packit Service 7b8cfb
                            else:
Packit Service 7b8cfb
                                nodenote = LocNote(locnote=note, locnotetype=notetype)
Packit Service 7b8cfb
                            self._its_loc_notes.setdefault(node, []).append(nodenote)
Packit Service 7b8cfb
                        else:
Packit Service 7b8cfb
                            for note in note:
Packit Service 7b8cfb
                                if ref:
Packit Service 7b8cfb
                                    nodenote = LocNote(locnoteref=note.content, locnotetype=notetype)
Packit Service 7b8cfb
                                else:
Packit Service 7b8cfb
                                    nodenote = LocNote(locnote=note.content, locnotetype=notetype,
Packit Service 7b8cfb
                                                       space=self.get_preserve_space(note))
Packit Service 7b8cfb
                                self._its_loc_notes.setdefault(node, []).append(nodenote)
Packit Service 7b8cfb
                                break
Packit Service 7b8cfb
                        xpath.setContextNode(oldnode)
Packit Service 7b8cfb
        elif xml_is_ns_name(rule, NS_ITS, 'langRule'):
Packit Service 7b8cfb
            if rule.nsProp('selector', None) is not None and rule.nsProp('langPointer', None) is not None:
Packit Service 7b8cfb
                for node in self._try_xpath_eval(xpath, rule.nsProp('selector', None)):
Packit Service 7b8cfb
                    try:
Packit Service 7b8cfb
                        oldnode = xpath.contextNode()
Packit Service 7b8cfb
                    except:
Packit Service 7b8cfb
                        oldnode = None
Packit Service 7b8cfb
                    xpath.setContextNode(node)
Packit Service 7b8cfb
                    res = self._try_xpath_eval(xpath, rule.nsProp('langPointer', None))
Packit Service 7b8cfb
                    if len(res) > 0:
Packit Service 7b8cfb
                        self._its_lang[node] = res[0].content
Packit Service 7b8cfb
                    # We need to construct language attributes, not just read
Packit Service 7b8cfb
                    # language information. Technically, langPointer could be
Packit Service 7b8cfb
                    # any XPath expression. But if it looks like an attribute
Packit Service 7b8cfb
                    # accessor, just use the attribute name.
Packit Service 7b8cfb
                    if rule.nsProp('langPointer', None)[0] == '@':
Packit Service 7b8cfb
                        self._itst_lang_attr[node] = rule.nsProp('langPointer', None)[1:]
Packit Service 7b8cfb
                    xpath.setContextNode(oldnode)
Packit Service 7b8cfb
        elif xml_is_ns_name(rule, NS_ITST, 'credits'):
Packit Service 7b8cfb
            if rule.nsProp('appendTo', None) is not None:
Packit Service 7b8cfb
                for node in self._try_xpath_eval(xpath, rule.nsProp('appendTo', None)):
Packit Service 7b8cfb
                    self._itst_credits = (node, rule)
Packit Service 7b8cfb
                    break
Packit Service 7b8cfb
        elif (xml_is_ns_name(rule, NS_ITS, 'externalResourceRefRule') or
Packit Service 7b8cfb
              xml_is_ns_name(rule, NS_ITST, 'externalRefRule')):
Packit Service 7b8cfb
            sel = rule.nsProp('selector', None)
Packit Service 7b8cfb
            if xml_is_ns_name(rule, NS_ITS, 'externalResourceRefRule'):
Packit Service 7b8cfb
                ptr = rule.nsProp('externalResourceRefPointer', None)
Packit Service 7b8cfb
            else:
Packit Service 7b8cfb
                ptr = rule.nsProp('refPointer', None)
Packit Service 7b8cfb
            if sel is not None and ptr is not None:
Packit Service 7b8cfb
                for node in self._try_xpath_eval(xpath, sel):
Packit Service 7b8cfb
                    try:
Packit Service 7b8cfb
                        oldnode = xpath.contextNode()
Packit Service 7b8cfb
                    except:
Packit Service 7b8cfb
                        oldnode = None
Packit Service 7b8cfb
                    xpath.setContextNode(node)
Packit Service 7b8cfb
                    res = self._try_xpath_eval(xpath, ptr)
Packit Service 7b8cfb
                    if len(res) > 0:
Packit Service 7b8cfb
                        self._its_externals[node] = res[0].content
Packit Service 7b8cfb
                    xpath.setContextNode(oldnode)
Packit Service 7b8cfb
Packit Service 7b8cfb
    def apply_its_rules(self, builtins, params={}):
Packit Service 7b8cfb
        if builtins:
Packit Service 7b8cfb
            dirs = []
Packit Service 7b8cfb
            ddir = os.getenv('XDG_DATA_HOME', '')
Packit Service 7b8cfb
            if ddir == '':
Packit Service 7b8cfb
                ddir = os.path.join(os.path.expanduser('~'), '.local', 'share')
Packit Service 7b8cfb
            dirs.append(ddir)
Packit Service 7b8cfb
            ddir = os.getenv('XDG_DATA_DIRS', '')
Packit Service 7b8cfb
            if ddir == '':
Packit Service 7b8cfb
                if DATADIR not in ('/usr/local/share', '/usr/share'):
Packit Service 7b8cfb
                    ddir += DATADIR + ':'
Packit Service 7b8cfb
                ddir += '/usr/local/share:/usr/share'
Packit Service 7b8cfb
            dirs.extend(ddir.split(':'))
Packit Service 7b8cfb
            ddone = {}
Packit Service 7b8cfb
            for ddir in dirs:
Packit Service 7b8cfb
                itsdir = os.path.join(ddir, 'itstool', 'its')
Packit Service 7b8cfb
                if not os.path.exists(itsdir):
Packit Service 7b8cfb
                    continue
Packit Service 7b8cfb
                for dfile in os.listdir(itsdir):
Packit Service 7b8cfb
                    if dfile.endswith('.its'):
Packit Service 7b8cfb
                        if not ddone.get(dfile, False):
Packit Service 7b8cfb
                            self.apply_its_file(os.path.join(itsdir, dfile), params=params)
Packit Service 7b8cfb
                            ddone[dfile] = True
Packit Service 7b8cfb
        self.apply_local_its_rules(params=params)
Packit Service 7b8cfb
Packit Service 7b8cfb
    def apply_its_file(self, filename, params={}):
Packit Service 7b8cfb
        doc = libxml2.parseFile(filename)
Packit Service 7b8cfb
        root = doc.getRootElement()
Packit Service 7b8cfb
        if not xml_is_ns_name(root, NS_ITS, 'rules'):
Packit Service 7b8cfb
            return
Packit Service 7b8cfb
        version = None
Packit Service 7b8cfb
        if root.hasNsProp('version', None):
Packit Service 7b8cfb
            version = root.nsProp('version', None)
Packit Service 7b8cfb
        else:
Packit Service 7b8cfb
            sys.stderr.write('Warning: ITS file %s missing version attribute\n' %
Packit Service 7b8cfb
                             os.path.basename(filename))
Packit Service 7b8cfb
        if version is not None and version not in ('1.0', '2.0'):
Packit Service 7b8cfb
            sys.stderr.write('Warning: Skipping ITS file %s with unknown version %s\n' %
Packit Service 7b8cfb
                             (os.path.basename(filename), root.nsProp('version', None)))
Packit Service 7b8cfb
            return
Packit Service 7b8cfb
        matched = True
Packit Service 7b8cfb
        for match in xml_child_iter(root):
Packit Service 7b8cfb
            if xml_is_ns_name(match, NS_ITST, 'match'):
Packit Service 7b8cfb
                matched = False
Packit Service 7b8cfb
                xpath = self._doc.xpathNewContext()
Packit Service 7b8cfb
                par = match
Packit Service 7b8cfb
                nss = {}
Packit Service 7b8cfb
                while par is not None:
Packit Service 7b8cfb
                    nsdef = par.nsDefs()
Packit Service 7b8cfb
                    while nsdef is not None:
Packit Service 7b8cfb
                        if nsdef.name is not None:
Packit Service 7b8cfb
                            if nsdef.name not in nss:
Packit Service 7b8cfb
                                nss[nsdef.name] = nsdef.content
Packit Service 7b8cfb
                                xpath.xpathRegisterNs(nsdef.name, nsdef.content)
Packit Service 7b8cfb
                        nsdef = nsdef.next
Packit Service 7b8cfb
                    par = par.parent
Packit Service 7b8cfb
                if match.hasNsProp('selector', None):
Packit Service 7b8cfb
                    if len(self._try_xpath_eval(xpath, match.nsProp('selector', None))) > 0:
Packit Service 7b8cfb
                        matched = True
Packit Service 7b8cfb
                        break
Packit Service 7b8cfb
        if matched == False:
Packit Service 7b8cfb
            return
Packit Service 7b8cfb
        for rule in xml_child_iter(root):
Packit Service 7b8cfb
            xpath = self._doc.xpathNewContext()
Packit Service 7b8cfb
            par = match
Packit Service 7b8cfb
            nss = {}
Packit Service 7b8cfb
            while par is not None:
Packit Service 7b8cfb
                nsdef = par.nsDefs()
Packit Service 7b8cfb
                while nsdef is not None:
Packit Service 7b8cfb
                    if nsdef.name is not None:
Packit Service 7b8cfb
                        if nsdef.name not in nss:
Packit Service 7b8cfb
                            nss[nsdef.name] = nsdef.content
Packit Service 7b8cfb
                            xpath.xpathRegisterNs(nsdef.name, nsdef.content)
Packit Service 7b8cfb
                    nsdef = nsdef.next
Packit Service 7b8cfb
                par = par.parent
Packit Service 7b8cfb
            self.register_its_params(xpath, root, params=params)
Packit Service 7b8cfb
            self.apply_its_rule(rule, xpath)
Packit Service 7b8cfb
Packit Service 7b8cfb
    def apply_local_its_rules(self, params={}):
Packit Service 7b8cfb
        for rules in self._localrules:
Packit Service 7b8cfb
            def reg_ns(xpath, node):
Packit Service 7b8cfb
                if node.parent is not None:
Packit Service 7b8cfb
                    reg_ns(xpath, node.parent)
Packit Service 7b8cfb
                nsdef = node.nsDefs()
Packit Service 7b8cfb
                while nsdef is not None:
Packit Service 7b8cfb
                    if nsdef.name is not None:
Packit Service 7b8cfb
                        xpath.xpathRegisterNs(nsdef.name, nsdef.content)
Packit Service 7b8cfb
                    nsdef = nsdef.next
Packit Service 7b8cfb
            xpath = self._doc.xpathNewContext()
Packit Service 7b8cfb
            reg_ns(xpath, rules)
Packit Service 7b8cfb
            self.register_its_params(xpath, rules, params=params)
Packit Service 7b8cfb
            for rule in xml_child_iter(rules):
Packit Service 7b8cfb
                if rule.type != 'element':
Packit Service 7b8cfb
                    continue
Packit Service 7b8cfb
                if rule.nsDefs() is not None:
Packit Service 7b8cfb
                    rule_xpath = self._doc.xpathNewContext()
Packit Service 7b8cfb
                    reg_ns(rule_xpath, rule)
Packit Service 7b8cfb
                    self.register_its_params(rule_xpath, rules, params=params)
Packit Service 7b8cfb
                else:
Packit Service 7b8cfb
                    rule_xpath = xpath
Packit Service 7b8cfb
                self.apply_its_rule(rule, rule_xpath)
Packit Service 7b8cfb
Packit Service 7b8cfb
    def _append_credits(self, parent, node, trdata):
Packit Service 7b8cfb
        if xml_is_ns_name(node, NS_ITST, 'for-each'):
Packit Service 7b8cfb
            select = node.nsProp('select', None)
Packit Service 7b8cfb
            if select == 'years':
Packit Service 7b8cfb
                for year in trdata[2].split(','):
Packit Service 7b8cfb
                    for child in xml_child_iter(node):
Packit Service 7b8cfb
                        self._append_credits(parent, child, trdata + (year.strip(),))
Packit Service 7b8cfb
        elif xml_is_ns_name(node, NS_ITST, 'value-of'):
Packit Service 7b8cfb
            select = node.nsProp('select', None)
Packit Service 7b8cfb
            val = None
Packit Service 7b8cfb
            if select == 'name':
Packit Service 7b8cfb
                val = trdata[0]
Packit Service 7b8cfb
            elif select == 'email':
Packit Service 7b8cfb
                val = trdata[1]
Packit Service 7b8cfb
            elif select == 'years':
Packit Service 7b8cfb
                val = trdata[2]
Packit Service 7b8cfb
            elif select == 'year' and len(trdata) == 4:
Packit Service 7b8cfb
                val = trdata[3]
Packit Service 7b8cfb
            if val is not None:
Packit Service 7b8cfb
                if not PY3:
Packit Service 7b8cfb
                    val = val.encode('utf-8')
Packit Service 7b8cfb
                parent.addContent(val)
Packit Service 7b8cfb
        else:
Packit Service 7b8cfb
            newnode = node.copyNode(2)
Packit Service 7b8cfb
            parent.addChild(newnode)
Packit Service 7b8cfb
            for child in xml_child_iter(node):
Packit Service 7b8cfb
                self._append_credits(newnode, child, trdata)
Packit Service 7b8cfb
Packit Service 7b8cfb
    def merge_credits(self, translations, language, node):
Packit Service 7b8cfb
        if self._itst_credits is None:
Packit Service 7b8cfb
            return
Packit Service 7b8cfb
        # Dear Python, please implement pgettext.
Packit Service 7b8cfb
        # http://bugs.python.org/issue2504
Packit Service 7b8cfb
        # Sincerely, Shaun
Packit Service 7b8cfb
        trans = translations.ugettext('_\x04translator-credits')
Packit Service 7b8cfb
        if trans is None or trans == 'translator-credits':
Packit Service 7b8cfb
            return
Packit Service 7b8cfb
        regex = re.compile('(.*) \<(.*)\>, (.*)')
Packit Service 7b8cfb
        for credit in trans.split('\n'):
Packit Service 7b8cfb
            match = regex.match(credit)
Packit Service 7b8cfb
            if not match:
Packit Service 7b8cfb
                continue
Packit Service 7b8cfb
            trdata = match.groups()
Packit Service 7b8cfb
            for node in xml_child_iter(self._itst_credits[1]):
Packit Service 7b8cfb
                self._append_credits(self._itst_credits[0], node, trdata)
Packit Service 7b8cfb
Packit Service 7b8cfb
    def join_translations(self, translations, node=None, strict=False):
Packit Service 7b8cfb
        is_root = False
Packit Service 7b8cfb
        if node is None:
Packit Service 7b8cfb
            is_root = True
Packit Service 7b8cfb
            self.generate_messages(comments=False)
Packit Service 7b8cfb
            node = self._doc.getRootElement()
Packit Service 7b8cfb
        if node is None or node.type != 'element':
Packit Service 7b8cfb
            return
Packit Service 7b8cfb
        if self.get_itst_drop(node) == 'yes':
Packit Service 7b8cfb
            prev = node.prev
Packit Service 7b8cfb
            node.unlinkNode()
Packit Service 7b8cfb
            node.freeNode()
Packit Service 7b8cfb
            if prev is not None and prev.isBlankNode():
Packit Service 7b8cfb
                prev.unlinkNode()
Packit Service 7b8cfb
                prev.freeNode()
Packit Service 7b8cfb
            return
Packit Service 7b8cfb
        msg = self._msgs.get_message_by_node(node)
Packit Service 7b8cfb
        if msg is None:
Packit Service 7b8cfb
            self.translate_attrs(node, node)
Packit Service 7b8cfb
            children = [child for child in xml_child_iter(node)]
Packit Service 7b8cfb
            for child in children:
Packit Service 7b8cfb
                self.join_translations(translations, node=child, strict=strict)
Packit Service 7b8cfb
        else:
Packit Service 7b8cfb
            prevnode = None
Packit Service 7b8cfb
            if node.prev is not None and node.prev.type == 'text':
Packit Service 7b8cfb
                prevtext = node.prev.content
Packit Service 7b8cfb
                if re.sub('\s+', '', prevtext) == '':
Packit Service 7b8cfb
                    prevnode = node.prev
Packit Service 7b8cfb
            for lang in sorted(list(translations.keys()), reverse=True):
Packit Service 7b8cfb
                locale = self.get_its_locale_filter(node)
Packit Service 7b8cfb
                lmatch = match_locale_list(locale[0], lang)
Packit Service 7b8cfb
                if (locale[1] == 'include' and not lmatch) or (locale[1] == 'exclude' and lmatch):
Packit Service 7b8cfb
                    continue
Packit Service 7b8cfb
                newnode = self.get_translated(node, translations[lang], strict=strict, lang=lang)
Packit Service 7b8cfb
                if newnode != node:
Packit Service 7b8cfb
                    newnode.setProp('xml:lang', lang)
Packit Service 7b8cfb
                    node.addNextSibling(newnode)
Packit Service 7b8cfb
                    if prevnode is not None:
Packit Service 7b8cfb
                        node.addNextSibling(prevnode.copyNode(0))
Packit Service 7b8cfb
        if is_root:
Packit Service 7b8cfb
            # Because of the way we create nodes and rewrite the document,
Packit Service 7b8cfb
            # we end up with lots of redundant namespace definitions. We
Packit Service 7b8cfb
            # kill them off in one fell swoop at the end.
Packit Service 7b8cfb
            fix_node_ns(node, {})
Packit Service 7b8cfb
            self._check_errors()
Packit Service 7b8cfb
Packit Service 7b8cfb
    def merge_translations(self, translations, language, node=None, strict=False):
Packit Service 7b8cfb
        is_root = False
Packit Service 7b8cfb
        if node is None:
Packit Service 7b8cfb
            is_root = True
Packit Service 7b8cfb
            self.generate_messages(comments=False)
Packit Service 7b8cfb
            node = self._doc.getRootElement()
Packit Service 7b8cfb
        if node is None or node.type != 'element':
Packit Service 7b8cfb
            return
Packit Service 7b8cfb
        drop = False
Packit Service 7b8cfb
        locale = self.get_its_locale_filter(node)
Packit Service 7b8cfb
        if locale[1] == 'include':
Packit Service 7b8cfb
            if locale[0] != '*':
Packit Service 7b8cfb
                if not match_locale_list(locale[0], language):
Packit Service 7b8cfb
                    drop = True
Packit Service 7b8cfb
        elif locale[1] == 'exclude':
Packit Service 7b8cfb
            if match_locale_list(locale[0], language):
Packit Service 7b8cfb
                drop = True
Packit Service 7b8cfb
        if self.get_itst_drop(node) == 'yes' or drop:
Packit Service 7b8cfb
            prev = node.prev
Packit Service 7b8cfb
            node.unlinkNode()
Packit Service 7b8cfb
            node.freeNode()
Packit Service 7b8cfb
            if prev is not None and prev.isBlankNode():
Packit Service 7b8cfb
                prev.unlinkNode()
Packit Service 7b8cfb
                prev.freeNode()
Packit Service 7b8cfb
            return
Packit Service 7b8cfb
        if is_root:
Packit Service 7b8cfb
            self.merge_credits(translations, language, node)
Packit Service 7b8cfb
        msg = self._msgs.get_message_by_node(node)
Packit Service 7b8cfb
        if msg is None:
Packit Service 7b8cfb
            self.translate_attrs(node, node)
Packit Service 7b8cfb
            children = [child for child in xml_child_iter(node)]
Packit Service 7b8cfb
            for child in children:
Packit Service 7b8cfb
                self.merge_translations(translations, language, node=child, strict=strict)
Packit Service 7b8cfb
        else:
Packit Service 7b8cfb
            newnode = self.get_translated(node, translations, strict=strict, lang=language)
Packit Service 7b8cfb
            if newnode != node:
Packit Service 7b8cfb
                self.translate_attrs(node, newnode)
Packit Service 7b8cfb
                node.replaceNode(newnode)
Packit Service 7b8cfb
        if is_root:
Packit Service 7b8cfb
            # Apply language attributes to untranslated nodes. We don't do
Packit Service 7b8cfb
            # this before processing, because then these attributes would
Packit Service 7b8cfb
            # be copied into the new nodes. We apply the attribute without
Packit Service 7b8cfb
            # checking whether it was translated, because any that were will
Packit Service 7b8cfb
            # just be floating around, unattached to a document.
Packit Service 7b8cfb
            for lcnode in self._msgs.get_nodes_with_messages():
Packit Service 7b8cfb
                attr = self._itst_lang_attr.get(lcnode)
Packit Service 7b8cfb
                if attr is None:
Packit Service 7b8cfb
                    continue
Packit Service 7b8cfb
                origlang = None
Packit Service 7b8cfb
                lcpar = lcnode
Packit Service 7b8cfb
                while lcpar is not None:
Packit Service 7b8cfb
                    origlang = self._its_lang.get(lcpar)
Packit Service 7b8cfb
                    if origlang is not None:
Packit Service 7b8cfb
                        break
Packit Service 7b8cfb
                    lcpar = lcpar.parent
Packit Service 7b8cfb
                if origlang is not None:
Packit Service 7b8cfb
                    lcnode.setProp(attr, origlang)
Packit Service 7b8cfb
            # And then set the language attribute on the root node.
Packit Service 7b8cfb
            if language is not None:
Packit Service 7b8cfb
                attr = self._itst_lang_attr.get(node)
Packit Service 7b8cfb
                if attr is not None:
Packit Service 7b8cfb
                    node.setProp(attr, language)
Packit Service 7b8cfb
            # Because of the way we create nodes and rewrite the document,
Packit Service 7b8cfb
            # we end up with lots of redundant namespace definitions. We
Packit Service 7b8cfb
            # kill them off in one fell swoop at the end.
Packit Service 7b8cfb
            fix_node_ns(node, {})
Packit Service 7b8cfb
            self._check_errors()
Packit Service 7b8cfb
Packit Service 7b8cfb
    def translate_attrs(self, oldnode, newnode):
Packit Service 7b8cfb
        trans_attrs = [attr for attr in xml_attr_iter(oldnode) if self._its_translate_nodes.get(attr, 'no') == 'yes']
Packit Service 7b8cfb
        for attr in trans_attrs:
Packit Service 7b8cfb
            srccontent = attr.get_content()
Packit Service 7b8cfb
            if not PY3:
Packit Service 7b8cfb
                srccontent = srccontent.decode('utf-8')
Packit Service 7b8cfb
            newcontent = translations.ugettext(srccontent)
Packit Service 7b8cfb
            if newcontent:
Packit Service 7b8cfb
                if not PY3:
Packit Service 7b8cfb
                    newcontent = newcontent.encode('utf-8')
Packit Service 7b8cfb
                newnode.setProp(attr.name, newcontent)
Packit Service 7b8cfb
Packit Service 7b8cfb
    def get_translated (self, node, translations, strict=False, lang=None):
Packit Service 7b8cfb
        msg = self._msgs.get_message_by_node(node)
Packit Service 7b8cfb
        if msg is None:
Packit Service 7b8cfb
            return node
Packit Service 7b8cfb
        msgstr = msg.get_string()
Packit Service 7b8cfb
        # Dear Python, please implement pgettext.
Packit Service 7b8cfb
        # http://bugs.python.org/issue2504
Packit Service 7b8cfb
        # Sincerely, Shaun
Packit Service 7b8cfb
        if msg.get_context() is not None:
Packit Service 7b8cfb
            msgstr = msg.get_context() + '\x04' + msgstr
Packit Service 7b8cfb
        trans = translations.ugettext(msgstr)
Packit Service 7b8cfb
        if trans is None:
Packit Service 7b8cfb
            return node
Packit Service 7b8cfb
        nss = {}
Packit Service 7b8cfb
        def reg_ns(node, nss):
Packit Service 7b8cfb
            if node.parent is not None:
Packit Service 7b8cfb
                reg_ns(node.parent, nss)
Packit Service 7b8cfb
            nsdef = node.nsDefs()
Packit Service 7b8cfb
            while nsdef is not None:
Packit Service 7b8cfb
                nss[nsdef.name] = nsdef.content
Packit Service 7b8cfb
                nsdef = nsdef.next
Packit Service 7b8cfb
        reg_ns(node, nss)
Packit Service 7b8cfb
        nss['_'] = NS_BLANK
Packit Service 7b8cfb
        try:
Packit Service 7b8cfb
            blurb = node.doc.intSubset().serialize('utf-8')
Packit Service 7b8cfb
        except Exception:
Packit Service 7b8cfb
            blurb = ''
Packit Service 7b8cfb
        blurb += '<' + ustr(node.name, 'utf-8')
Packit Service 7b8cfb
        for nsname in list(nss.keys()):
Packit Service 7b8cfb
            if nsname is None:
Packit Service 7b8cfb
                blurb += ' xmlns="%s"' % nss[nsname]
Packit Service 7b8cfb
            else:
Packit Service 7b8cfb
                blurb += ' xmlns:%s="%s"' % (nsname, nss[nsname])
Packit Service 7b8cfb
        blurb += '>%s</%s>' % (trans, ustr(node.name, 'utf-8'))
Packit Service 7b8cfb
        if not PY3:
Packit Service 7b8cfb
            blurb = blurb.encode('utf-8')
Packit Service 7b8cfb
        ctxt = libxml2.createDocParserCtxt(blurb)
Packit Service 7b8cfb
        if self._load_dtd:
Packit Service 7b8cfb
            ctxt.loadSubset(1)
Packit Service 7b8cfb
        if self._keep_entities:
Packit Service 7b8cfb
            ctxt.loadSubset(1)
Packit Service 7b8cfb
            ctxt.ctxtUseOptions(libxml2.XML_PARSE_DTDLOAD)
Packit Service 7b8cfb
            ctxt.replaceEntities(0)
Packit Service 7b8cfb
        else:
Packit Service 7b8cfb
            ctxt.replaceEntities(1)
Packit Service 7b8cfb
        ctxt.parseDocument()
Packit Service 7b8cfb
        trnode = ctxt.doc().getRootElement()
Packit Service 7b8cfb
        try:
Packit Service 7b8cfb
            self._check_errors()
Packit Service 7b8cfb
        except libxml2.parserError:
Packit Service 7b8cfb
            if strict:
Packit Service 7b8cfb
                raise
Packit Service 7b8cfb
            else:
Packit Service 7b8cfb
                sys.stderr.write('Warning: Could not merge %stranslation for msgid:\n%s\n' % (
Packit Service 7b8cfb
                        (lang + ' ') if lang is not None else '',
Packit Service 7b8cfb
                        msgstr.encode('utf-8')))
Packit Service 7b8cfb
                self._xml_err = ''
Packit Service 7b8cfb
                return node
Packit Service 7b8cfb
        def scan_node(node):
Packit Service 7b8cfb
            children = [child for child in xml_child_iter(node)]
Packit Service 7b8cfb
            for child in children:
Packit Service 7b8cfb
                if child.type != 'element':
Packit Service 7b8cfb
                    continue
Packit Service 7b8cfb
                if child.ns() is not None and child.ns().content == NS_BLANK:
Packit Service 7b8cfb
                    ph_node = msg.get_placeholder(child.name).node
Packit Service 7b8cfb
                    if self.has_child_elements(ph_node):
Packit Service 7b8cfb
                        self.merge_translations(translations, None, ph_node, strict=strict)
Packit Service 7b8cfb
                        newnode = ph_node.copyNode(1)
Packit Service 7b8cfb
                        newnode.setTreeDoc(self._doc)
Packit Service 7b8cfb
                        child.replaceNode(newnode)
Packit Service 7b8cfb
                    else:
Packit Service 7b8cfb
                        repl = self.get_translated(ph_node, translations, strict=strict, lang=lang)
Packit Service 7b8cfb
                        child.replaceNode(repl)
Packit Service 7b8cfb
                scan_node(child)
Packit Service 7b8cfb
        try:
Packit Service 7b8cfb
            scan_node(trnode)
Packit Service 7b8cfb
        except:
Packit Service 7b8cfb
            if strict:
Packit Service 7b8cfb
                raise
Packit Service 7b8cfb
            else:
Packit Service 7b8cfb
                sys.stderr.write('Warning: Could not merge %stranslation for msgid:\n%s\n' % (
Packit Service 7b8cfb
                    (lang + ' ') if lang is not None else '',
Packit Service 7b8cfb
                    msgstr.encode('utf-8')))
Packit Service 7b8cfb
                self._xml_err = ''
Packit Service 7b8cfb
                ctxt.doc().freeDoc()
Packit Service 7b8cfb
                return node
Packit Service 7b8cfb
        retnode = node.copyNode(2)
Packit Service 7b8cfb
        retnode.setTreeDoc(self._doc)
Packit Service 7b8cfb
        for child in xml_child_iter(trnode):
Packit Service 7b8cfb
            newnode = child.copyNode(1)
Packit Service 7b8cfb
            newnode.setTreeDoc(self._doc)
Packit Service 7b8cfb
            retnode.addChild(newnode)
Packit Service 7b8cfb
Packit Service 7b8cfb
        ctxt.doc().freeDoc()
Packit Service 7b8cfb
        return retnode
Packit Service 7b8cfb
Packit Service 7b8cfb
    def generate_messages(self, comments=True):
Packit Service 7b8cfb
        if self._itst_credits is not None:
Packit Service 7b8cfb
            self._msgs.add_credits()
Packit Service 7b8cfb
        for child in xml_child_iter(self._doc):
Packit Service 7b8cfb
            if child.type == 'element':
Packit Service 7b8cfb
                self.generate_message(child, None, comments=comments)
Packit Service 7b8cfb
                break
Packit Service 7b8cfb
Packit Service 7b8cfb
    def generate_message (self, node, msg, comments=True, path=None):
Packit Service 7b8cfb
        if node.type in ('text', 'cdata') and msg is not None:
Packit Service 7b8cfb
            msg.add_text(node.content)
Packit Service 7b8cfb
            return
Packit Service 7b8cfb
        if node.type == 'entity_ref':
Packit Service 7b8cfb
            msg.add_entity_ref(node.name);
Packit Service 7b8cfb
        if node.type != 'element':
Packit Service 7b8cfb
            return
Packit Service 7b8cfb
        if node.hasNsProp('drop', NS_ITST) and node.nsProp('drop', NS_ITST) == 'yes':
Packit Service 7b8cfb
            return
Packit Service 7b8cfb
        if self._itst_drop_nodes.get(node, 'no') == 'yes':
Packit Service 7b8cfb
            return
Packit Service 7b8cfb
        locfil = self.get_its_locale_filter(node)
Packit Service 7b8cfb
        if locfil == ('', 'include') or locfil == ('*', 'exclude'):
Packit Service 7b8cfb
            return
Packit Service 7b8cfb
        if path is None:
Packit Service 7b8cfb
            path = ''
Packit Service 7b8cfb
        translate = self.get_its_translate(node)
Packit Service 7b8cfb
        withinText = False
Packit Service 7b8cfb
        if translate == 'no':
Packit Service 7b8cfb
            if msg is not None:
Packit Service 7b8cfb
                msg.add_placeholder(node)
Packit Service 7b8cfb
            is_unit = False
Packit Service 7b8cfb
            msg = None
Packit Service 7b8cfb
        else:
Packit Service 7b8cfb
            is_unit = msg is None or self.is_translation_unit(node)
Packit Service 7b8cfb
            if is_unit:
Packit Service 7b8cfb
                if msg is not None:
Packit Service 7b8cfb
                    msg.add_placeholder(node)
Packit Service 7b8cfb
                msg = Message()
Packit Service 7b8cfb
                ctxt = None
Packit Service 7b8cfb
                if node.hasNsProp('context', NS_ITST):
Packit Service 7b8cfb
                    ctxt = node.nsProp('context', NS_ITST)
Packit Service 7b8cfb
                if ctxt is None:
Packit Service 7b8cfb
                    ctxt = self._itst_contexts.get(node)
Packit Service 7b8cfb
                if ctxt is not None:
Packit Service 7b8cfb
                    msg.set_context(ctxt)
Packit Service 7b8cfb
                idvalue = self.get_its_id_value(node)
Packit Service 7b8cfb
                if idvalue is not None:
Packit Service 7b8cfb
                    basename = os.path.basename(self._filename)
Packit Service 7b8cfb
                    msg.add_id_value(basename + '#' + idvalue)
Packit Service 7b8cfb
                if self.get_preserve_space(node):
Packit Service 7b8cfb
                    msg.set_preserve_space()
Packit Service 7b8cfb
                if self.get_its_locale_filter(node) != ('*', 'include'):
Packit Service 7b8cfb
                    msg.set_locale_filter(self.get_its_locale_filter(node))
Packit Service 7b8cfb
                msg.add_source('%s:%i' % (self._doc.name, node.lineNo()))
Packit Service 7b8cfb
                msg.add_marker('%s/%s' % (ustr(node.parent.name, 'utf-8'), ustr(node.name, 'utf-8')))
Packit Service 7b8cfb
            else:
Packit Service 7b8cfb
                withinText = True
Packit Service 7b8cfb
                msg.add_start_tag(node)
Packit Service 7b8cfb
Packit Service 7b8cfb
        if not withinText:
Packit Service 7b8cfb
            # Add msg for translatable node attributes
Packit Service 7b8cfb
            for attr in xml_attr_iter(node):
Packit Service 7b8cfb
                if self._its_translate_nodes.get(attr, 'no') == 'yes':
Packit Service 7b8cfb
                    attr_msg = Message()
Packit Service 7b8cfb
                    if self.get_preserve_space(attr):
Packit Service 7b8cfb
                        attr_msg.set_preserve_space()
Packit Service 7b8cfb
                    attr_msg.add_source('%s:%i' % (self._doc.name, node.lineNo()))
Packit Service 7b8cfb
                    attr_msg.add_marker('%s/%s@%s' % (node.parent.name, node.name, attr.name))
Packit Service 7b8cfb
                    attr_msg.add_text(attr.content)
Packit Service 7b8cfb
                    if comments:
Packit Service 7b8cfb
                        for locnote in self.get_its_loc_notes(attr):
Packit Service 7b8cfb
                            comment = Comment(locnote)
Packit Service 7b8cfb
                            comment.add_marker ('%s/%s@%s' % (
Packit Service 7b8cfb
                                    node.parent.name, node.name, attr.name))
Packit Service 7b8cfb
                            attr_msg.add_comment(comment)
Packit Service 7b8cfb
                    self._msgs.add_message(attr_msg, attr)
Packit Service 7b8cfb
Packit Service 7b8cfb
        if comments and msg is not None:
Packit Service 7b8cfb
            cnode = node
Packit Service 7b8cfb
            while cnode is not None:
Packit Service 7b8cfb
                hasnote = False
Packit Service 7b8cfb
                for locnote in self.get_its_loc_notes(cnode, inherit=(not withinText)):
Packit Service 7b8cfb
                    comment = Comment(locnote)
Packit Service 7b8cfb
                    if withinText:
Packit Service 7b8cfb
                        comment.add_marker('.%s/%s' % (path, cnode.name))
Packit Service 7b8cfb
                    msg.add_comment(comment)
Packit Service 7b8cfb
                    hasnote = True
Packit Service 7b8cfb
                if hasnote or not is_unit:
Packit Service 7b8cfb
                    break
Packit Service 7b8cfb
                cnode = cnode.parent
Packit Service 7b8cfb
Packit Service 7b8cfb
        self.generate_external_resource_message(node)
Packit Service 7b8cfb
        for attr in xml_attr_iter(node):
Packit Service 7b8cfb
            self.generate_external_resource_message(attr)
Packit Service 7b8cfb
            idvalue = self.get_its_id_value(attr)
Packit Service 7b8cfb
            if idvalue is not None:
Packit Service 7b8cfb
                basename = os.path.basename(self._filename)
Packit Service 7b8cfb
                msg.add_id_value(basename + '#' + idvalue)
Packit Service 7b8cfb
Packit Service 7b8cfb
        if withinText:
Packit Service 7b8cfb
            path = path + '/' + node.name
Packit Service 7b8cfb
        for child in xml_child_iter(node):
Packit Service 7b8cfb
            self.generate_message(child, msg, comments=comments, path=path)
Packit Service 7b8cfb
Packit Service 7b8cfb
        if translate:
Packit Service 7b8cfb
            if is_unit and not msg.is_empty():
Packit Service 7b8cfb
                self._msgs.add_message(msg, node)
Packit Service 7b8cfb
            elif msg is not None:
Packit Service 7b8cfb
                msg.add_end_tag(node)
Packit Service 7b8cfb
Packit Service 7b8cfb
    def generate_external_resource_message(self, node):
Packit Service 7b8cfb
        if node not in self._its_externals:
Packit Service 7b8cfb
            return
Packit Service 7b8cfb
        resref = self._its_externals[node]
Packit Service 7b8cfb
        if node.type == 'element':
Packit Service 7b8cfb
            translate = self.get_its_translate(node)
Packit Service 7b8cfb
            marker = '%s/%s' % (node.parent.name, node.name)
Packit Service 7b8cfb
        else:
Packit Service 7b8cfb
            translate = self.get_its_translate(node.parent)
Packit Service 7b8cfb
            marker = '%s/%s/@%s' % (node.parent.parent.name, node.parent.name, node.name)
Packit Service 7b8cfb
        if translate == 'no':
Packit Service 7b8cfb
            return
Packit Service 7b8cfb
        msg = Message()
Packit Service 7b8cfb
        try:
Packit Service 7b8cfb
            fullfile = os.path.join(os.path.dirname(self._filename), resref)
Packit Service 7b8cfb
            filefp = open(fullfile, 'rb')
Packit Service 7b8cfb
            filemd5 = hashlib.md5(filefp.read()).hexdigest()
Packit Service 7b8cfb
            filefp.close()
Packit Service 7b8cfb
        except Exception:
Packit Service 7b8cfb
            filemd5 = '__failed__'
Packit Service 7b8cfb
        txt = "external ref='%s' md5='%s'" % (resref, filemd5)
Packit Service 7b8cfb
        msg.set_context('_')
Packit Service 7b8cfb
        msg.add_text(txt)
Packit Service 7b8cfb
        msg.add_source('%s:%i' % (self._doc.name, node.lineNo()))
Packit Service 7b8cfb
        msg.add_marker(marker)
Packit Service 7b8cfb
        msg.add_comment(Comment('This is a reference to an external file such as an image or'
Packit Service 7b8cfb
                                ' video. When the file changes, the md5 hash will change to'
Packit Service 7b8cfb
                                ' let you know you need to update your localized copy. The'
Packit Service 7b8cfb
                                ' msgstr is not used at all. Set it to whatever you like'
Packit Service 7b8cfb
                                ' once you have updated your copy of the file.'))
Packit Service 7b8cfb
        self._msgs.add_message(msg, None)
Packit Service 7b8cfb
Packit Service 7b8cfb
    def is_translation_unit (self, node):
Packit Service 7b8cfb
        return self.get_its_within_text(node) != 'yes'
Packit Service 7b8cfb
Packit Service 7b8cfb
    def has_child_elements(self, node):
Packit Service 7b8cfb
        return len([child for child in xml_child_iter(node) if child.type=='element'])
Packit Service 7b8cfb
Packit Service 7b8cfb
    def get_preserve_space (self, node):
Packit Service 7b8cfb
        while node.type in ('attribute', 'element'):
Packit Service 7b8cfb
            if node.getSpacePreserve() == 1:
Packit Service 7b8cfb
                return True
Packit Service 7b8cfb
            if node in self._its_preserve_space_nodes:
Packit Service 7b8cfb
                return (self._its_preserve_space_nodes[node] == 'preserve')
Packit Service 7b8cfb
            node = node.parent
Packit Service 7b8cfb
        return False
Packit Service 7b8cfb
Packit Service 7b8cfb
    def get_its_translate(self, node):
Packit Service 7b8cfb
        val = None
Packit Service 7b8cfb
        if node.hasNsProp('translate', NS_ITS):
Packit Service 7b8cfb
            val = node.nsProp('translate', NS_ITS)
Packit Service 7b8cfb
        elif xml_is_ns_name(node, NS_ITS, 'span') and node.hasNsProp('translate', None):
Packit Service 7b8cfb
            val = node.nsProp('translate', None)
Packit Service 7b8cfb
        elif node in self._its_translate_nodes:
Packit Service 7b8cfb
            val = self._its_translate_nodes[node]
Packit Service 7b8cfb
        if val is not None:
Packit Service 7b8cfb
            return val
Packit Service 7b8cfb
        if node.type == 'attribute':
Packit Service 7b8cfb
            return 'no'
Packit Service 7b8cfb
        if node.parent.type == 'element':
Packit Service 7b8cfb
            return self.get_its_translate(node.parent)
Packit Service 7b8cfb
        return 'yes'
Packit Service 7b8cfb
Packit Service 7b8cfb
    def get_its_within_text(self, node):
Packit Service 7b8cfb
        if node.hasNsProp('withinText', NS_ITS):
Packit Service 7b8cfb
            val = node.nsProp('withinText', NS_ITS)
Packit Service 7b8cfb
        elif xml_is_ns_name(node, NS_ITS, 'span') and node.hasNsProp('withinText', None):
Packit Service 7b8cfb
            val = node.nsProp('withinText', None)
Packit Service 7b8cfb
        else:
Packit Service 7b8cfb
            return self._its_within_text_nodes.get(node, 'no')
Packit Service 7b8cfb
        if val in ('yes', 'nested'):
Packit Service 7b8cfb
            return val
Packit Service 7b8cfb
        return 'no'
Packit Service 7b8cfb
Packit Service 7b8cfb
    def get_its_locale_filter(self, node):
Packit Service 7b8cfb
        if node.hasNsProp('localeFilterList', NS_ITS) or node.hasNsProp('localeFilterType', NS_ITS):
Packit Service 7b8cfb
            if node.hasNsProp('localeFilterList', NS_ITS):
Packit Service 7b8cfb
                lst = node.nsProp('localeFilterList', NS_ITS)
Packit Service 7b8cfb
            else:
Packit Service 7b8cfb
                lst = '*'
Packit Service 7b8cfb
            if node.hasNsProp('localeFilterType', NS_ITS):
Packit Service 7b8cfb
                typ = node.nsProp('localeFilterType', NS_ITS)
Packit Service 7b8cfb
            else:
Packit Service 7b8cfb
                typ = 'include'
Packit Service 7b8cfb
            return (lst, typ)
Packit Service 7b8cfb
        if (xml_is_ns_name(node, NS_ITS, 'span') and
Packit Service 7b8cfb
            (node.hasNsProp('localeFilterList', None) or node.hasNsProp('localeFilterType', None))):
Packit Service 7b8cfb
            if node.hasNsProp('localeFilterList', None):
Packit Service 7b8cfb
                lst = node.nsProp('localeFilterList', None)
Packit Service 7b8cfb
            else:
Packit Service 7b8cfb
                lst = '*'
Packit Service 7b8cfb
            if node.hasNsProp('localeFilterType', None):
Packit Service 7b8cfb
                typ = node.nsProp('localeFilterType', None)
Packit Service 7b8cfb
            else:
Packit Service 7b8cfb
                typ = 'include'
Packit Service 7b8cfb
            return (lst, typ)
Packit Service 7b8cfb
        if node in self._its_locale_filters:
Packit Service 7b8cfb
            return self._its_locale_filters[node]
Packit Service 7b8cfb
        if node.parent.type == 'element':
Packit Service 7b8cfb
            return self.get_its_locale_filter(node.parent)
Packit Service 7b8cfb
        return ('*', 'include')
Packit Service 7b8cfb
Packit Service 7b8cfb
    def get_itst_drop(self, node):
Packit Service 7b8cfb
        if node.hasNsProp('drop', NS_ITST) and node.nsProp('drop', NS_ITST) == 'yes':
Packit Service 7b8cfb
            return 'yes'
Packit Service 7b8cfb
        if self._itst_drop_nodes.get(node, 'no') == 'yes':
Packit Service 7b8cfb
            return 'yes'
Packit Service 7b8cfb
        return 'no'
Packit Service 7b8cfb
Packit Service 7b8cfb
    def get_its_id_value(self, node):
Packit Service 7b8cfb
        if node.hasNsProp('id', NS_XML):
Packit Service 7b8cfb
            return node.nsProp('id', NS_XML)
Packit Service 7b8cfb
        return self._its_id_values.get(node, None)
Packit Service 7b8cfb
Packit Service 7b8cfb
    def get_its_loc_notes(self, node, inherit=True):
Packit Service 7b8cfb
        ret = []
Packit Service 7b8cfb
        if node.hasNsProp('locNote', NS_ITS) or node.hasNsProp('locNoteRef', NS_ITS) or node.hasNsProp('locNoteType', NS_ITS):
Packit Service 7b8cfb
            notetype = node.nsProp('locNoteType', NS_ITS)
Packit Service 7b8cfb
            if node.hasNsProp('locNote', NS_ITS):
Packit Service 7b8cfb
                ret.append(LocNote(locnote=node.nsProp('locNote', NS_ITS), locnotetype=notetype))
Packit Service 7b8cfb
            elif node.hasNsProp('locNoteRef', NS_ITS):
Packit Service 7b8cfb
                ret.append(LocNote(locnoteref=node.nsProp('locNoteRef', NS_ITS), locnotetype=notetype))
Packit Service 7b8cfb
        elif  xml_is_ns_name(node, NS_ITS, 'span'):
Packit Service 7b8cfb
            if node.hasNsProp('locNote', None) or node.hasNsProp('locNoteRef', None) or node.hasNsProp('locNoteType', None):
Packit Service 7b8cfb
                notetype = node.nsProp('locNoteType', None)
Packit Service 7b8cfb
                if node.hasNsProp('locNote', None):
Packit Service 7b8cfb
                    ret.append(LocNote(locnote=node.nsProp('locNote', None), locnotetype=notetype))
Packit Service 7b8cfb
                elif node.hasNsProp('locNoteRef', None):
Packit Service 7b8cfb
                    ret.append(LocNote(locnoteref=node.nsProp('locNoteRef', None), locnotetype=notetype))
Packit Service 7b8cfb
        for locnote in reversed(self._its_loc_notes.get(node, [])):
Packit Service 7b8cfb
            ret.append(locnote)
Packit Service 7b8cfb
        if (len(ret) == 0 and inherit and
Packit Service 7b8cfb
            node.type != 'attribute' and node.parent is not None and node.parent.type == 'element'):
Packit Service 7b8cfb
            return self.get_its_loc_notes(node.parent)
Packit Service 7b8cfb
        return ret
Packit Service 7b8cfb
Packit Service 7b8cfb
    def output_test_data(self, category, out, node=None):
Packit Service 7b8cfb
        if node is None:
Packit Service 7b8cfb
            node = self._doc.getRootElement()
Packit Service 7b8cfb
        compval = ''
Packit Service 7b8cfb
        if category == 'translate':
Packit Service 7b8cfb
            compval = 'translate="%s"' % self.get_its_translate(node)
Packit Service 7b8cfb
        elif category == 'withinText':
Packit Service 7b8cfb
            if node.type != 'attribute':
Packit Service 7b8cfb
                compval = 'withinText="%s"' % self.get_its_within_text(node)
Packit Service 7b8cfb
        elif category == 'localeFilter':
Packit Service 7b8cfb
            compval = 'localeFilterList="%s"\tlocaleFilterType="%s"' % self.get_its_locale_filter(node)
Packit Service 7b8cfb
        elif category == 'locNote':
Packit Service 7b8cfb
            val = self.get_its_loc_notes(node)
Packit Service 7b8cfb
            if len(val) > 0:
Packit Service 7b8cfb
                if val[0].locnote is not None:
Packit Service 7b8cfb
                    compval = 'locNote="%s"\tlocNoteType="%s"' % (ustr(val[0]), val[0].locnotetype)
Packit Service 7b8cfb
                elif val[0].locnoteref is not None:
Packit Service 7b8cfb
                    compval = 'locNoteRef="%s"\tlocNoteType="%s"' % (val[0].locnoteref, val[0].locnotetype)
Packit Service 7b8cfb
        elif category == 'externalResourceRef':
Packit Service 7b8cfb
            val = self._its_externals.get(node, '')
Packit Service 7b8cfb
            if val != '':
Packit Service 7b8cfb
                compval = 'externalResourceRef="%s"' % val
Packit Service 7b8cfb
        elif category == 'idValue':
Packit Service 7b8cfb
            val = self.get_its_id_value(node)
Packit Service 7b8cfb
            if val is not None:
Packit Service 7b8cfb
                compval = 'idValue="%s"' % val
Packit Service 7b8cfb
        elif category == 'preserveSpace':
Packit Service 7b8cfb
            if self.get_preserve_space(node):
Packit Service 7b8cfb
                compval = 'space="preserve"'
Packit Service 7b8cfb
            else:
Packit Service 7b8cfb
                compval = 'space="default"'
Packit Service 7b8cfb
        else:
Packit Service 7b8cfb
            sys.stderr.write('Error: Unrecognized category %s\n' % category)
Packit Service 7b8cfb
            sys.exit(1)
Packit Service 7b8cfb
        if compval != '':
Packit Service 7b8cfb
            out.write('%s\t%s\r\n' % (xml_get_node_path(node), compval))
Packit Service 7b8cfb
        else:
Packit Service 7b8cfb
            out.write('%s\r\n' % (xml_get_node_path(node)))
Packit Service 7b8cfb
        for attr in sorted(xml_attr_iter(node), key=ustr):
Packit Service 7b8cfb
            self.output_test_data(category, out, attr)
Packit Service 7b8cfb
        for child in xml_child_iter(node):
Packit Service 7b8cfb
            if child.type == 'element':
Packit Service 7b8cfb
                self.output_test_data(category, out, child)
Packit Service 7b8cfb
Packit Service 7b8cfb
    @staticmethod
Packit Service 7b8cfb
    def _try_xpath_eval (xpath, expr):
Packit Service 7b8cfb
        try:
Packit Service 7b8cfb
            return xpath.xpathEval(expr)
Packit Service 7b8cfb
        except:
Packit Service 7b8cfb
            sys.stderr.write('Warning: Invalid XPath: %s\n' % expr)
Packit Service 7b8cfb
            return []
Packit Service 7b8cfb
Packit Service 7b8cfb
def match_locale_list(extranges, locale):
Packit Service 7b8cfb
    if extranges.strip() == '':
Packit Service 7b8cfb
        return False
Packit Service 7b8cfb
    for extrange in [extrange.strip() for extrange in extranges.split(',')]:
Packit Service 7b8cfb
        if match_locale(extrange, locale):
Packit Service 7b8cfb
            return True
Packit Service 7b8cfb
    return False
Packit Service 7b8cfb
Packit Service 7b8cfb
def match_locale(extrange, locale):
Packit Service 7b8cfb
    # Extended filtering for extended language ranges as
Packit Service 7b8cfb
    # defined by RFC4647, part of BCP47.
Packit Service 7b8cfb
    # http://tools.ietf.org/html/rfc4647#section-3.3.2
Packit Service 7b8cfb
    rangelist = [x.lower() for x in extrange.split('-')]
Packit Service 7b8cfb
    localelist = [x.lower() for x in locale.split('-')]
Packit Service 7b8cfb
    if rangelist[0] not in ('*', localelist[0]):
Packit Service 7b8cfb
        return False
Packit Service 7b8cfb
    rangei = localei = 0
Packit Service 7b8cfb
    while rangei < len(rangelist):
Packit Service 7b8cfb
        if rangelist[rangei] == '*':
Packit Service 7b8cfb
            rangei += 1
Packit Service 7b8cfb
            continue
Packit Service 7b8cfb
        if localei >= len(localelist):
Packit Service 7b8cfb
            return False
Packit Service 7b8cfb
        if rangelist[rangei] in ('*', localelist[localei]):
Packit Service 7b8cfb
            rangei += 1
Packit Service 7b8cfb
            localei += 1
Packit Service 7b8cfb
            continue
Packit Service 7b8cfb
        if len(localelist[localei]) == 1:
Packit Service 7b8cfb
            return False
Packit Service 7b8cfb
        localei += 1
Packit Service 7b8cfb
    return True
Packit Service 7b8cfb
Packit Service 7b8cfb
_locale_pattern = re.compile('([a-zA-Z0-9-]+)(_[A-Za-z0-9]+)?(@[A-Za-z0-9]+)?(\.[A-Za-z0-9]+)?')
Packit Service 7b8cfb
def convert_locale (locale):
Packit Service 7b8cfb
    # Automatically convert POSIX-style locales to BCP47
Packit Service 7b8cfb
    match = _locale_pattern.match(locale)
Packit Service 7b8cfb
    if match is None:
Packit Service 7b8cfb
        return locale
Packit Service 7b8cfb
    ret = match.group(1).lower()
Packit Service 7b8cfb
    variant = match.group(3)
Packit Service 7b8cfb
    if variant == '@cyrillic':
Packit Service 7b8cfb
        ret += '-Cyrl'
Packit Service 7b8cfb
        variant = None
Packit Service 7b8cfb
    if variant == '@devanagari':
Packit Service 7b8cfb
        ret += '-Deva'
Packit Service 7b8cfb
        variant = None
Packit Service 7b8cfb
    elif variant == '@latin':
Packit Service 7b8cfb
        ret += '-Latn'
Packit Service 7b8cfb
        variant = None
Packit Service 7b8cfb
    elif variant == '@shaw':
Packit Service 7b8cfb
        ret += '-Shaw'
Packit Service 7b8cfb
        variant = None
Packit Service 7b8cfb
    if match.group(2) is not None:
Packit Service 7b8cfb
        ret += '-' + match.group(2)[1:].upper()
Packit Service 7b8cfb
    if variant is not None and variant != '@euro':
Packit Service 7b8cfb
        ret += '-' + variant[1:].lower()
Packit Service 7b8cfb
    return ret
Packit Service 7b8cfb
Packit Service 7b8cfb
Packit Service 7b8cfb
if __name__ == '__main__':
Packit Service 7b8cfb
    options = optparse.OptionParser()
Packit Service 7b8cfb
    options.set_usage('\n  itstool [OPTIONS] [XMLFILES]\n' +
Packit Service 7b8cfb
                      '  itstool -m <MOFILE> [OPTIONS] [XMLFILES]\n' +
Packit Service 7b8cfb
                      '  itstool -j <XMLFILE> [OPTIONS] [MOFILES]')
Packit Service 7b8cfb
    options.add_option('-i', '--its',
Packit Service 7b8cfb
                       action='append',
Packit Service 7b8cfb
                       dest='itsfile',
Packit Service 7b8cfb
                       metavar='ITS',
Packit Service 7b8cfb
                       help='Load the ITS rules in the file ITS (can specify multiple times)')
Packit Service 7b8cfb
    options.add_option('-l', '--lang',
Packit Service 7b8cfb
                       dest='lang',
Packit Service 7b8cfb
                       default=None,
Packit Service 7b8cfb
                       metavar='LANGUAGE',
Packit Service 7b8cfb
                       help='Explicitly set the language code for output file')
Packit Service 7b8cfb
    options.add_option('-j', '--join',
Packit Service 7b8cfb
                       dest='join',
Packit Service 7b8cfb
                       metavar='FILE',
Packit Service 7b8cfb
                       help='Join multiple MO files with the XML file FILE and output XML file')
Packit Service 7b8cfb
    options.add_option('-m', '--merge',
Packit Service 7b8cfb
                       dest='merge',
Packit Service 7b8cfb
                       metavar='FILE',
Packit Service 7b8cfb
                       help='Merge from a PO or MO file FILE and output XML files')
Packit Service 7b8cfb
    options.add_option('-n', '--no-builtins',
Packit Service 7b8cfb
                       action='store_true',
Packit Service 7b8cfb
                       dest='nobuiltins',
Packit Service 7b8cfb
                       default=False,
Packit Service 7b8cfb
                       help='Do not apply the built-in ITS rules')
Packit Service 7b8cfb
    options.add_option('-o', '--output',
Packit Service 7b8cfb
                       dest='output',
Packit Service 7b8cfb
                       default=None,
Packit Service 7b8cfb
                       metavar='OUT',
Packit Service 7b8cfb
                       help='Output PO files to file OUT or XML files in directory OUT')
Packit Service 7b8cfb
    options.add_option('--path',
Packit Service 7b8cfb
                       action='append',
Packit Service 7b8cfb
                       dest='itspath',
Packit Service 7b8cfb
                       default=None,
Packit Service 7b8cfb
                       metavar='PATHS',
Packit Service 7b8cfb
                       help='Extra path where ITS files may be found (can specify multiple times)')
Packit Service 7b8cfb
    options.add_option('-s', '--strict',
Packit Service 7b8cfb
                       action='store_true',
Packit Service 7b8cfb
                       dest='strict',
Packit Service 7b8cfb
                       default=False,
Packit Service 7b8cfb
                       help='Exit with error when PO files contain broken XML')
Packit Service 7b8cfb
    options.add_option('-d', '--load-dtd',
Packit Service 7b8cfb
                       action='store_true',
Packit Service 7b8cfb
                       dest='load_dtd',
Packit Service 7b8cfb
                       default=False,
Packit Service 7b8cfb
                       help='Load external DTDs used by input XML')
Packit Service 7b8cfb
    options.add_option('-k', '--keep-entities',
Packit Service 7b8cfb
                       action='store_true',
Packit Service 7b8cfb
                       dest='keep_entities',
Packit Service 7b8cfb
                       default=False,
Packit Service 7b8cfb
                       help='Keep entity reference unexpanded')
Packit Service 7b8cfb
    options.add_option('-p', '--param',
Packit Service 7b8cfb
                       action='append',
Packit Service 7b8cfb
                       dest='params',
Packit Service 7b8cfb
                       default=[],
Packit Service 7b8cfb
                       nargs=2,
Packit Service 7b8cfb
                       metavar='NAME VALUE',
Packit Service 7b8cfb
                       help='Define the ITS parameter NAME to the value VALUE (can specify multiple times)')
Packit Service 7b8cfb
    options.add_option('-t', '--test',
Packit Service 7b8cfb
                       dest='test',
Packit Service 7b8cfb
                       default=None,
Packit Service 7b8cfb
                       metavar='CATEGORY',
Packit Service 7b8cfb
                       help='Generate conformance test output for CATEGORY')
Packit Service 7b8cfb
    options.add_option('-v', '--version',
Packit Service 7b8cfb
                       action='store_true',
Packit Service 7b8cfb
                       dest='version',
Packit Service 7b8cfb
                       default=False,
Packit Service 7b8cfb
                       help='Print itstool version and exit')
Packit Service 7b8cfb
    (opts, args) = options.parse_args(sys.argv)
Packit Service 7b8cfb
Packit Service 7b8cfb
    if opts.version:
Packit Service 7b8cfb
        print('itstool %s' % VERSION)
Packit Service 7b8cfb
        sys.exit(0)
Packit Service 7b8cfb
Packit Service 7b8cfb
    params = {}
Packit Service 7b8cfb
    for name, value in opts.params:
Packit Service 7b8cfb
        params[name] = value
Packit Service 7b8cfb
Packit Service 7b8cfb
    if opts.merge is None and opts.join is None:
Packit Service 7b8cfb
        messages = MessageList()
Packit Service 7b8cfb
        for filename in args[1:]:
Packit Service 7b8cfb
            doc = Document(filename, messages, load_dtd=opts.load_dtd, keep_entities=opts.keep_entities)
Packit Service 7b8cfb
            doc.apply_its_rules(not(opts.nobuiltins), params=params)
Packit Service 7b8cfb
            if opts.itsfile is not None:
Packit Service 7b8cfb
                for itsfile in opts.itsfile:
Packit Service 7b8cfb
                    doc.apply_its_file(itsfile, params=params)
Packit Service 7b8cfb
            if opts.test is None:
Packit Service 7b8cfb
                doc.generate_messages()
Packit Service 7b8cfb
        if opts.output is None or opts.output == '-':
Packit Service 7b8cfb
            out = sys.stdout
Packit Service 7b8cfb
        else:
Packit Service 7b8cfb
            try:
Packit Service 7b8cfb
                out = io.open(opts.output, 'wt', encoding='utf-8')
Packit Service 7b8cfb
            except:
Packit Service 7b8cfb
                sys.stderr.write('Error: Cannot write to file %s\n' % opts.output)
Packit Service 7b8cfb
                sys.exit(1)
Packit Service 7b8cfb
        if opts.test is not None:
Packit Service 7b8cfb
            doc.output_test_data(opts.test, out)
Packit Service 7b8cfb
        else:
Packit Service 7b8cfb
            messages.output(out)
Packit Service 7b8cfb
            out.flush()
Packit Service 7b8cfb
    elif opts.merge is not None:
Packit Service 7b8cfb
        try:
Packit Service 7b8cfb
            translations = gettext.GNUTranslations(open(opts.merge, 'rb'))
Packit Service 7b8cfb
        except:
Packit Service 7b8cfb
            sys.stderr.write('Error: cannot open mo file %s\n' % opts.merge)
Packit Service 7b8cfb
            sys.exit(1)
Packit Service 7b8cfb
        if PY3:
Packit Service 7b8cfb
            translations.ugettext = translations.gettext
Packit Service 7b8cfb
        translations.add_fallback(NoneTranslations())
Packit Service 7b8cfb
        if opts.lang is None:
Packit Service 7b8cfb
            opts.lang = convert_locale(os.path.splitext(os.path.basename(opts.merge))[0])
Packit Service 7b8cfb
        if opts.output is None:
Packit Service 7b8cfb
            out = './'
Packit Service 7b8cfb
        elif os.path.isdir(opts.output):
Packit Service 7b8cfb
            out = opts.output
Packit Service 7b8cfb
        elif len(args) == 2:
Packit Service 7b8cfb
            if opts.output == '-':
Packit Service 7b8cfb
                out = sys.stdout
Packit Service 7b8cfb
            else:
Packit Service 7b8cfb
                out = open(opts.output, 'wb')
Packit Service 7b8cfb
        else:
Packit Service 7b8cfb
            sys.stderr.write('Error: Non-directory output for multiple files\n')
Packit Service 7b8cfb
            sys.exit(1)
Packit Service 7b8cfb
        for filename in args[1:]:
Packit Service 7b8cfb
            messages = MessageList()
Packit Service 7b8cfb
            doc = Document(filename, messages, load_dtd=opts.load_dtd, keep_entities=opts.keep_entities)
Packit Service 7b8cfb
            doc.apply_its_rules(not(opts.nobuiltins), params=params)
Packit Service 7b8cfb
            if opts.itsfile is not None:
Packit Service 7b8cfb
                for itsfile in opts.itsfile:
Packit Service 7b8cfb
                    doc.apply_its_file(itsfile, params=params)
Packit Service 7b8cfb
            try:
Packit Service 7b8cfb
                doc.merge_translations(translations, opts.lang, strict=opts.strict)
Packit Service 7b8cfb
            except Exception as e:
Packit Service 7b8cfb
                raise
Packit Service 7b8cfb
                sys.stderr.write('Error: Could not merge translations:\n%s\n' % ustr(e))
Packit Service 7b8cfb
                sys.exit(1)
Packit Service 7b8cfb
            serialized = doc._doc.serialize('utf-8')
Packit Service 7b8cfb
            if PY3:
Packit Service 7b8cfb
                # For some reason, under py3, our serialized data is returns as a str.
Packit Service 7b8cfb
                # Let's encode it to bytes
Packit Service 7b8cfb
                serialized = serialized.encode('utf-8')
Packit Service 7b8cfb
            fout = out
Packit Service 7b8cfb
            fout_is_str = isinstance(fout, string_types)
Packit Service 7b8cfb
            if fout_is_str:
Packit Service 7b8cfb
                fout = open(os.path.join(fout, os.path.basename(filename)), 'wb')
Packit Service 7b8cfb
            fout.write(serialized)
Packit Service 7b8cfb
            fout.flush()
Packit Service 7b8cfb
            if fout_is_str:
Packit Service 7b8cfb
                fout.close()
Packit Service 7b8cfb
    elif opts.join is not None:
Packit Service 7b8cfb
        translations = {}
Packit Service 7b8cfb
        for filename in args[1:]:
Packit Service 7b8cfb
            try:
Packit Service 7b8cfb
                thistr = gettext.GNUTranslations(open(filename, 'rb'))
Packit Service 7b8cfb
            except:
Packit Service 7b8cfb
                sys.stderr.write('Error: cannot open mo file %s\n' % filename)
Packit Service 7b8cfb
                sys.exit(1)
Packit Service 7b8cfb
            thistr.add_fallback(NoneTranslations())
Packit Service 7b8cfb
            if PY3:
Packit Service 7b8cfb
                thistr.ugettext = thistr.gettext
Packit Service 7b8cfb
            lang = convert_locale(os.path.splitext(os.path.basename(filename))[0])
Packit Service 7b8cfb
            translations[lang] = thistr
Packit Service 7b8cfb
        if opts.output is None:
Packit Service 7b8cfb
            out = sys.stdout
Packit Service 7b8cfb
        elif os.path.isdir(opts.output):
Packit Service 7b8cfb
            out = open(os.path.join(opts.output, os.path.basename(filename)), 'wb')
Packit Service 7b8cfb
        else:
Packit Service 7b8cfb
            out = open(opts.output, 'wb')
Packit Service 7b8cfb
        messages = MessageList()
Packit Service 7b8cfb
        doc = Document(opts.join, messages)
Packit Service 7b8cfb
        doc.apply_its_rules(not(opts.nobuiltins), params=params)
Packit Service 7b8cfb
        if opts.itsfile is not None:
Packit Service 7b8cfb
            for itsfile in opts.itsfile:
Packit Service 7b8cfb
                doc.apply_its_file(itsfile, params=params)
Packit Service 7b8cfb
        doc.join_translations(translations, strict=opts.strict)
Packit Service 7b8cfb
        serialized = doc._doc.serialize('utf-8')
Packit Service 7b8cfb
        if PY3:
Packit Service 7b8cfb
            # For some reason, under py3, our serialized data is returns as a str.
Packit Service 7b8cfb
            # Let's encode it to bytes
Packit Service 7b8cfb
            serialized = serialized.encode('utf-8')
Packit Service 7b8cfb
        out.write(serialized)
Packit Service 7b8cfb
        out.flush()