[arch-commits] Commit in gimp-help/repos/community-any (4 files)
Allan McRae
allan at gemini.archlinux.org
Wed Mar 2 07:52:59 UTC 2022
Date: Wednesday, March 2, 2022 @ 07:52:59
Author: allan
Revision: 1139316
archrelease: copy trunk to community-any
Added:
gimp-help/repos/community-any/PKGBUILD
(from rev 1139315, gimp-help/trunk/PKGBUILD)
gimp-help/repos/community-any/gimp-help-2.10.0-python3.patch
(from rev 1139315, gimp-help/trunk/gimp-help-2.10.0-python3.patch)
Deleted:
gimp-help/repos/community-any/PKGBUILD
gimp-help/repos/community-any/gimp-help-2.10.0-python3.patch
--------------------------------+
PKGBUILD | 138 +-
gimp-help-2.10.0-python3.patch | 1950 +++++++++++++++++++--------------------
2 files changed, 1044 insertions(+), 1044 deletions(-)
Deleted: PKGBUILD
===================================================================
--- PKGBUILD 2022-03-02 07:20:19 UTC (rev 1139315)
+++ PKGBUILD 2022-03-02 07:52:59 UTC (rev 1139316)
@@ -1,69 +0,0 @@
-# Maintainer: Muflone http://www.muflone.com/contacts/english/
-# Contributor: Piotr Rogoża <rogoza dot piotr at gmail dot com>
-
-pkgbase=gimp-help
-pkgver=2.10.0
-pkgrel=4
-arch=('any')
-url='https://docs.gimp.org/'
-license=('GPL' 'LGPL')
-makedepends=('python' 'docbook-xsl')
-options=(!strip !zipman)
-source=("https://ftp.gimp.org/pub/gimp/help/${pkgbase}-${pkgver}.tar.bz2"
- "gimp-help-2.10.0-python3.patch")
-sha256sums=('03804fed071b49e5810edd8327868659dfd9932fbf34d34189d56bd0ad539118'
- '955a8599f6908b989252a63ea3227198ff9880f30fc254fccc5128a6a745d599')
-
-_languages=(
- 'ca "Catalan"'
- 'da "Danish"'
- 'de "German"'
- 'el "Greek"'
- 'en "English"'
- 'en_GB "English (United Kingdom)"'
- 'es "Spanish"'
- 'fi "Finnish"'
- 'fr "French"'
- 'it "Italian"'
- 'ja "Japanese"'
- 'ko "Korean"'
- 'nl "Dutch"'
- 'nn "Norwegian"'
- 'pt_BR "Brazilian Portuguese"'
- 'ro "Romanian"'
- 'ru "Russian"'
- 'zh_CN "Chinese (simplified)"'
-)
-
-_package() {
- _locale="$1"
- _language="$2"
- pkgdesc="${_language} help files for Gimp"
- install -dm755 "${pkgdir}/usr/share/gimp/2.0/help/${_locale}"
- cp -rL "${srcdir}/${pkgbase}-${pkgver}/html/${_locale}" \
- "${pkgdir}/usr/share/gimp/2.0/help"
-}
-
-prepare() {
- cd "${pkgbase}-${pkgver}"
- sed -e '1s/python$/python2/' -i "tools/xml2po.py"
- # Python 3 (FS#70078 https://bugs.archlinux.org/task/70078 )
- patch -Np1 -i "${srcdir}/gimp-help-2.10.0-python3.patch"
-}
-
-build(){
- cd "${pkgbase}-${pkgver}"
- ./configure --prefix=/usr --without-gimp
- make
-}
-
-for _lang in "${_languages[@]}"
-do
- _locale=${_lang%% *}
- _pkgname=${pkgbase}-${_locale,,}
-
- pkgname+=(${_pkgname})
- eval "package_${_pkgname}() {
- _package ${_lang}
- }"
-done
Copied: gimp-help/repos/community-any/PKGBUILD (from rev 1139315, gimp-help/trunk/PKGBUILD)
===================================================================
--- PKGBUILD (rev 0)
+++ PKGBUILD 2022-03-02 07:52:59 UTC (rev 1139316)
@@ -0,0 +1,69 @@
+# Maintainer: Muflone http://www.muflone.com/contacts/english/
+# Contributor: Piotr Rogoża <rogoza dot piotr at gmail dot com>
+
+pkgbase=gimp-help
+pkgver=2.10.0
+pkgrel=4
+arch=('any')
+url='https://docs.gimp.org/'
+license=('GPL' 'LGPL')
+makedepends=('python' 'docbook-xsl')
+options=(!strip !zipman)
+source=("https://ftp.gimp.org/pub/gimp/help/${pkgbase}-${pkgver}.tar.bz2"
+ "gimp-help-2.10.0-python3.patch")
+sha256sums=('03804fed071b49e5810edd8327868659dfd9932fbf34d34189d56bd0ad539118'
+ '955a8599f6908b989252a63ea3227198ff9880f30fc254fccc5128a6a745d599')
+
+_languages=(
+ 'ca "Catalan"'
+ 'da "Danish"'
+ 'de "German"'
+ 'el "Greek"'
+ 'en "English"'
+ 'en_GB "English (United Kingdom)"'
+ 'es "Spanish"'
+ 'fi "Finnish"'
+ 'fr "French"'
+ 'it "Italian"'
+ 'ja "Japanese"'
+ 'ko "Korean"'
+ 'nl "Dutch"'
+ 'nn "Norwegian"'
+ 'pt_BR "Brazilian Portuguese"'
+ 'ro "Romanian"'
+ 'ru "Russian"'
+ 'zh_CN "Chinese (simplified)"'
+)
+
+_package() {
+ _locale="$1"
+ _language="$2"
+ pkgdesc="${_language} help files for Gimp"
+ install -dm755 "${pkgdir}/usr/share/gimp/2.0/help/${_locale}"
+ cp -rL "${srcdir}/${pkgbase}-${pkgver}/html/${_locale}" \
+ "${pkgdir}/usr/share/gimp/2.0/help"
+}
+
+prepare() {
+ cd "${pkgbase}-${pkgver}"
+ sed -e '1s/python$/python2/' -i "tools/xml2po.py"
+ # Python 3 (FS#70078 https://bugs.archlinux.org/task/70078 )
+ patch -Np1 -i "${srcdir}/gimp-help-2.10.0-python3.patch"
+}
+
+build(){
+ cd "${pkgbase}-${pkgver}"
+ ./configure --prefix=/usr --without-gimp
+ make
+}
+
+for _lang in "${_languages[@]}"
+do
+ _locale=${_lang%% *}
+ _pkgname=${pkgbase}-${_locale,,}
+
+ pkgname+=(${_pkgname})
+ eval "package_${_pkgname}() {
+ _package ${_lang}
+ }"
+done
Deleted: gimp-help-2.10.0-python3.patch
===================================================================
--- gimp-help-2.10.0-python3.patch 2022-03-02 07:20:19 UTC (rev 1139315)
+++ gimp-help-2.10.0-python3.patch 2022-03-02 07:52:59 UTC (rev 1139316)
@@ -1,975 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Jacob Boerema <jgboerema at gmail.com>
-Date: Thu, 4 Feb 2021 15:31:12 -0500
-Subject: [PATCH 1/3] tools: start migration to python3 by running 2to3
-
-(cherry picked from commit c5079e972d62858eead44c9029d276d456daf90d)
----
- tools/xml2po.py | 14 ++++++------
- tools/xml2po/__init__.py | 40 +++++++++++++++++-----------------
- tools/xml2po/modes/docbook.py | 20 ++++++++---------
- tools/xml2po/modes/gimphelp.py | 14 ++++++------
- 4 files changed, 44 insertions(+), 44 deletions(-)
-
-diff --git a/tools/xml2po.py b/tools/xml2po.py
-index 037e61f27..b3e110dc3 100755
---- a/tools/xml2po.py
-+++ b/tools/xml2po.py
-@@ -41,9 +41,9 @@ NULL_STRING = '/dev/null'
- if not os.path.exists('/dev/null'): NULL_STRING = 'NUL'
-
- def usage (with_help = False):
-- print >> sys.stderr, "Usage: %s [OPTIONS] [XMLFILE]..." % (sys.argv[0])
-+ print("Usage: %s [OPTIONS] [XMLFILE]..." % (sys.argv[0]), file=sys.stderr)
- if with_help:
-- print >> sys.stderr, """
-+ print("""
- OPTIONS may be some of:
- -a --automatic-tags Automatically decides if tags are to be considered
- "final" or not
-@@ -72,7 +72,7 @@ EXAMPLES:
- using -p option for each XML file:
- %(command)s -p de.po chapter1.xml > chapter1.de.xml
- %(command)s -p de.po chapter2.xml > chapter2.de.xml
--""" % {'command': sys.argv[0]}
-+""" % {'command': sys.argv[0]}, file=sys.stderr)
-
-
- def main(argv):
-@@ -148,7 +148,7 @@ def main(argv):
- sys.exit(0)
-
- if operation == 'update' and output != "-":
-- print >> sys.stderr, "Option '-o' is not yet supported when updating translations directly. Ignoring this option."
-+ print("Option '-o' is not yet supported when updating translations directly. Ignoring this option.", file=sys.stderr)
-
- # Treat remaining arguments as XML files
- filenames = []
-@@ -158,16 +158,16 @@ def main(argv):
- try:
- xml2po_main = Main(default_mode, operation, output, options)
- except IOError:
-- print >> sys.stderr, "Error: cannot open file %s for writing." % (output)
-+ print("Error: cannot open file %s for writing." % (output), file=sys.stderr)
- sys.exit(5)
-
- if operation == 'merge':
- if len(filenames) > 1:
-- print >> sys.stderr, "Error: You can merge translations with only one XML file at a time."
-+ print("Error: You can merge translations with only one XML file at a time.", file=sys.stderr)
- sys.exit(2)
-
- if not mofile:
-- print >> sys.stderr, "Error: You must specify MO file when merging translations."
-+ print("Error: You must specify MO file when merging translations.", file=sys.stderr)
- sys.exit(3)
-
- xml2po_main.merge(mofile, filenames[0])
-diff --git a/tools/xml2po/__init__.py b/tools/xml2po/__init__.py
-index eec197947..7a07eb226 100644
---- a/tools/xml2po/__init__.py
-+++ b/tools/xml2po/__init__.py
-@@ -86,14 +86,14 @@ class MessageOutput:
- self.messages.append(t)
- if spacepreserve:
- self.nowrap[t] = True
-- if t in self.linenos.keys():
-+ if t in list(self.linenos.keys()):
- self.linenos[t].append((self.filename, tag, lineno))
- else:
- self.linenos[t] = [ (self.filename, tag, lineno) ]
- if (not self.do_translations) and comment and not t in self.comments:
- self.comments[t] = comment
- else:
-- if t in self.linenos.keys():
-+ if t in list(self.linenos.keys()):
- self.linenos[t].append((self.filename, tag, lineno))
- else:
- self.linenos[t] = [ (self.filename, tag, lineno) ]
-@@ -166,7 +166,7 @@ class XMLDocument(object):
- elif node.isText():
- if node.isBlankNode():
- if self.app.options.get('expand_entities') or \
-- (not (node.prev and not node.prev.isBlankNode() and node.next and not node.next.isBlankNode()) ):
-+ (not (node.prev and not node.prev.isBlankNode() and node.__next__ and not node.next.isBlankNode()) ):
- #print >>sys.stderr, "BLANK"
- node.setContent('')
- else:
-@@ -176,7 +176,7 @@ class XMLDocument(object):
- child = node.children
- while child:
- self.normalizeNode(child)
-- child = child.next
-+ child = child.__next__
-
- def normalizeString(self, text, spacepreserve = False):
- """Normalizes string to be used as key for gettext lookup.
-@@ -200,7 +200,7 @@ class XMLDocument(object):
- tree = ctxt.doc()
- newnode = tree.getRootElement()
- except:
-- print >> sys.stderr, """Error while normalizing string as XML:\n"%s"\n""" % (text)
-+ print("""Error while normalizing string as XML:\n"%s"\n""" % (text), file=sys.stderr)
- return text
-
- self.normalizeNode(newnode)
-@@ -209,7 +209,7 @@ class XMLDocument(object):
- child = newnode.children
- while child:
- result += child.serialize('utf-8')
-- child = child.next
-+ child = child.__next__
-
- result = re.sub('^ ','', result)
- result = re.sub(' $','', result)
-@@ -235,7 +235,7 @@ class XMLDocument(object):
- ctxt.parseDocument()
- tree = ctxt.doc()
- if next:
-- newnode = tree.children.next
-+ newnode = tree.children.__next__
- else:
- newnode = tree.children
-
-@@ -243,7 +243,7 @@ class XMLDocument(object):
- child = newnode.children
- while child:
- result += child.serialize('utf-8')
-- child = child.next
-+ child = child.__next__
- tree.freeDoc()
- return result
-
-@@ -262,7 +262,7 @@ class XMLDocument(object):
- result += child.content.decode('utf-8')
- else:
- result += self.myAttributeSerialize(child)
-- child = child.next
-+ child = child.__next__
- else:
- result = node.serialize('utf-8')
- return result
-@@ -338,7 +338,7 @@ class XMLDocument(object):
- pass
-
- if not newnode:
-- print >> sys.stderr, """Error while parsing translation as XML:\n"%s"\n""" % (text.encode('utf-8'))
-+ print("""Error while parsing translation as XML:\n"%s"\n""" % (text.encode('utf-8')), file=sys.stderr)
- return
-
- newelem = newnode.getRootElement()
-@@ -346,13 +346,13 @@ class XMLDocument(object):
- if newelem and newelem.children:
- free = node.children
- while free:
-- next = free.next
-+ next = free.__next__
- free.unlinkNode()
- free = next
-
- if node:
- copy = newelem.copyNodeList()
-- next = node.next
-+ next = node.__next__
- node.replaceNode(newelem.copyNodeList())
- node.next = next
-
-@@ -377,7 +377,7 @@ class XMLDocument(object):
- if child.isText() and child.content.strip() != '':
- return True
- else:
-- child = child.next
-+ child = child.__next__
- return False
-
-
-@@ -441,7 +441,7 @@ class XMLDocument(object):
- outtxt += '<%s>%s</%s>' % (starttag, content, endtag)
- else:
- outtxt += self.doSerialize(child)
-- child = child.next
-+ child = child.__next__
-
- if self.app.operation == 'merge':
- norm_outtxt = self.normalizeString(outtxt, self.app.isSpacePreserveNode(node))
-@@ -521,7 +521,7 @@ class XMLDocument(object):
- outtxt = ''
- while child:
- outtxt += self.doSerialize(child)
-- child = child.next
-+ child = child.__next__
- return outtxt
-
- def xml_error_handler(arg, ctxt):
-@@ -565,7 +565,7 @@ class Main(object):
- try:
- doc = XMLDocument(xmlfile, self)
- except Exception as e:
-- print >> sys.stderr, "Unable to parse XML file '%s': %s" % (xmlfile, str(e))
-+ print("Unable to parse XML file '%s': %s" % (xmlfile, str(e)), file=sys.stderr)
- sys.exit(1)
- self.current_mode.preProcessXml(doc.doc, self.msg)
- doc.generate_messages()
-@@ -578,13 +578,13 @@ class Main(object):
- try:
- doc = XMLDocument(xmlfile, self)
- except Exception as e:
-- print >> sys.stderr, str(e)
-+ print(str(e), file=sys.stderr)
- sys.exit(1)
-
- try:
- mfile = open(mofile, "rb")
- except:
-- print >> sys.stderr, "Can't open MO file '%s'." % (mofile)
-+ print("Can't open MO file '%s'." % (mofile), file=sys.stderr)
- self.gt = gettext.GNUTranslations(mfile)
- self.gt.add_fallback(NoneTranslations())
- # Has preProcessXml use cases for merge?
-@@ -607,7 +607,7 @@ class Main(object):
- try:
- doc = XMLDocument(xmlfile, self)
- except Exception as e:
-- print >> sys.stderr, str(e)
-+ print(str(e), file=sys.stderr)
- sys.exit(1)
- doc.generate_messages()
-
-@@ -615,7 +615,7 @@ class Main(object):
- try:
- doc = XMLDocument(origxml, self)
- except Exception as e:
-- print >> sys.stderr, str(e)
-+ print(str(e), file=sys.stderr)
- sys.exit(1)
- doc.generate_messages()
- self.output_po()
-diff --git a/tools/xml2po/modes/docbook.py b/tools/xml2po/modes/docbook.py
-index 276a9d9bb..5658ffc1a 100644
---- a/tools/xml2po/modes/docbook.py
-+++ b/tools/xml2po/modes/docbook.py
-@@ -43,7 +43,7 @@ try:
- except ImportError:
- from md5 import new as md5_new
-
--from basic import basicXmlMode
-+from .basic import basicXmlMode
-
- class docbookXmlMode(basicXmlMode):
- """Class for special handling of DocBook document types.
-@@ -95,7 +95,7 @@ class docbookXmlMode(basicXmlMode):
- ret = self._find_articleinfo(child)
- if ret:
- return ret
-- child = child.next
-+ child = child.__next__
- return None
-
- def _find_lastcopyright(self, node):
-@@ -131,7 +131,7 @@ class docbookXmlMode(basicXmlMode):
- hash = self._md5_for_file(fullpath)
- else:
- hash = "THIS FILE DOESN'T EXIST"
-- print >>sys.stderr, "Warning: image file '%s' not found." % fullpath
-+ print("Warning: image file '%s' not found." % fullpath, file=sys.stderr)
-
- msg.outputMessage("@@image: '%s'; md5=%s" % (attr, hash), node.lineNo(),
- "When image changes, this message will be marked fuzzy or untranslated for you.\n"+
-@@ -140,7 +140,7 @@ class docbookXmlMode(basicXmlMode):
- child = node.children
- while child:
- self._output_images(child,msg)
-- child = child.next
-+ child = child.__next__
-
-
- def preProcessXml(self, doc, msg):
-@@ -157,7 +157,7 @@ class docbookXmlMode(basicXmlMode):
- root = doc.getRootElement()
- # DocBook documents can be something other than article, handle that as well in the future
- while root and root.name != 'article' and root.name != 'book':
-- root = root.next
-+ root = root.__next__
- if root and (root.name == 'article' or root.name == 'book'):
- root.setProp('lang', language)
- else:
-@@ -198,10 +198,10 @@ class docbookXmlMode(basicXmlMode):
- # Perform some tests when ran standalone
- if __name__ == '__main__':
- test = docbookXmlMode()
-- print "Ignored tags : " + repr(test.getIgnoredTags())
-- print "Final tags : " + repr(test.getFinalTags())
-- print "Space-preserve tags: " + repr(test.getSpacePreserveTags())
-+ print("Ignored tags : " + repr(test.getIgnoredTags()))
-+ print("Final tags : " + repr(test.getFinalTags()))
-+ print("Space-preserve tags: " + repr(test.getSpacePreserveTags()))
-
-- print "Credits from string: '%s'" % test.getStringForTranslators()
-- print "Explanation for credits:\n\t'%s'" % test.getCommentForTranslators()
-+ print("Credits from string: '%s'" % test.getStringForTranslators())
-+ print("Explanation for credits:\n\t'%s'" % test.getCommentForTranslators())
-
-diff --git a/tools/xml2po/modes/gimphelp.py b/tools/xml2po/modes/gimphelp.py
-index 24d4154e6..d72f518ee 100644
---- a/tools/xml2po/modes/gimphelp.py
-+++ b/tools/xml2po/modes/gimphelp.py
-@@ -31,7 +31,7 @@ try:
- except ImportError:
- from md5 import new as md5_new
-
--from docbook import docbookXmlMode
-+from .docbook import docbookXmlMode
-
- class gimphelpXmlMode(docbookXmlMode):
- """Class for special handling of gimp-help DocBook document types.
-@@ -81,7 +81,7 @@ class gimphelpXmlMode(docbookXmlMode):
- child = node.children
- while child:
- self._output_images(child,msg)
-- child = child.next
-+ child = child.__next__
-
- def preProcessXml(self, doc, msg):
- """Add additional messages of interest here."""
-@@ -91,10 +91,10 @@ class gimphelpXmlMode(docbookXmlMode):
- # Perform some tests when ran standalone
- if __name__ == '__main__':
- test = gimphelpXmlMode()
-- print "Ignored tags : " + repr(test.getIgnoredTags())
-- print "Final tags : " + repr(test.getFinalTags())
-- print "Space-preserve tags: " + repr(test.getSpacePreserveTags())
-+ print("Ignored tags : " + repr(test.getIgnoredTags()))
-+ print("Final tags : " + repr(test.getFinalTags()))
-+ print("Space-preserve tags: " + repr(test.getSpacePreserveTags()))
-
-- print "Credits from string: '%s'" % test.getStringForTranslators()
-- print "Explanation for credits:\n\t'%s'" % test.getCommentForTranslators()
-+ print("Credits from string: '%s'" % test.getStringForTranslators())
-+ print("Explanation for credits:\n\t'%s'" % test.getCommentForTranslators())
-
---
-2.29.2
-
-
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Jacob Boerema <jgboerema at gmail.com>
-Date: Mon, 29 Mar 2021 17:51:48 -0400
-Subject: [PATCH 2/3] tools: complete port of xml2po to python3
-
-Also:
-- Let it work correctly on Windows by setting encoding for
- stdout and stderr to utf-8.
-- Fix setting correct timezone in po files.
-- Better error handling.
-- Detect errors in tags in the translated xml text.
-
-(cherry picked from commit 299cfb7150857f0045ae42978d8ed917b4b0e4ff)
----
- tools/xml2po.py | 19 +++-
- tools/xml2po/__init__.py | 189 +++++++++++++++++++++++++--------
- tools/xml2po/modes/gimphelp.py | 2 +-
- 3 files changed, 163 insertions(+), 47 deletions(-)
-
-diff --git a/tools/xml2po.py b/tools/xml2po.py
-index b3e110dc3..ef8d725da 100755
---- a/tools/xml2po.py
-+++ b/tools/xml2po.py
-@@ -1,4 +1,4 @@
--#!/usr/bin/env python2
-+#!/usr/bin/env python3
- # -*- encoding: utf-8 -*-
- # Copyright (c) 2004, 2005, 2006 Danilo Šegan <danilo at gnome.org>.
- # Copyright (c) 2009 Claude Paroz <claude at 2xlibre.net>.
-@@ -21,7 +21,7 @@
- #
-
- # xml2po -- translate XML documents
--VERSION = "0.18.0 (patched by GIMP Documentation Team)"
-+VERSION = "0.19.0 (patched by GIMP Documentation Team)"
-
- # Versioning system (I use this for a long time, so lets explain it to
- # those Linux-versioning-scheme addicts):
-@@ -37,11 +37,13 @@ import os
- import getopt
- import tempfile
-
-+DEBUG_VERBOSITY = 0
-+
- NULL_STRING = '/dev/null'
- if not os.path.exists('/dev/null'): NULL_STRING = 'NUL'
-
- def usage (with_help = False):
-- print("Usage: %s [OPTIONS] [XMLFILE]..." % (sys.argv[0]), file=sys.stderr)
-+ print(f"Usage: {sys.argv[0]} [OPTIONS] [XMLFILE]...", file=sys.stderr)
- if with_help:
- print("""
- OPTIONS may be some of:
-@@ -86,6 +88,11 @@ def main(argv):
-
- from xml2po import Main
-
-+
-+ # Make sure stdout and stderr output utf-8 even on Windows where it's not the default
-+ sys.stdout = open(sys.stdout.fileno(), 'w', encoding='utf-8', closefd=False)
-+ sys.stderr = open(sys.stderr.fileno(), 'w', encoding='utf-8', closefd=False)
-+
- # Default parameters
- default_mode = 'docbook'
- operation = 'pot' # 'pot', 'merge', 'update'
-@@ -136,6 +143,8 @@ def main(argv):
- operation = 'merge'
- if 'translationlanguage' not in options:
- options['translationlanguage'] = os.path.split(os.path.splitext(pofile)[0])[1]
-+ if DEBUG_VERBOSITY > 0:
-+ print(f"Converting {pofile} to {mofile_tmppath} using msgfmt")
- os.system("msgfmt -o %s %s >%s" % (mofile_tmppath, pofile, NULL_STRING)) and sys.exit(7)
- mofile = mofile_tmppath
- elif opt in ('-o', '--output'):
-@@ -170,6 +179,10 @@ def main(argv):
- print("Error: You must specify MO file when merging translations.", file=sys.stderr)
- sys.exit(3)
-
-+ if DEBUG_VERBOSITY > 0:
-+ print(f"Merge mo file {mofile} with {filenames[0]}")
-+ if pofile:
-+ xml2po_main.pofile = pofile
- xml2po_main.merge(mofile, filenames[0])
-
- elif operation == 'update':
-diff --git a/tools/xml2po/__init__.py b/tools/xml2po/__init__.py
-index 7a07eb226..42fa81f39 100644
---- a/tools/xml2po/__init__.py
-+++ b/tools/xml2po/__init__.py
-@@ -26,6 +26,7 @@ import tempfile
- import gettext
- import libxml2
-
-+DEBUG_VERBOSITY = 0
- NULL_STRING = '/dev/null'
- if not os.path.exists('/dev/null'): NULL_STRING = 'NUL'
-
-@@ -86,14 +87,14 @@ class MessageOutput:
- self.messages.append(t)
- if spacepreserve:
- self.nowrap[t] = True
-- if t in list(self.linenos.keys()):
-+ if t in self.linenos.keys():
- self.linenos[t].append((self.filename, tag, lineno))
- else:
- self.linenos[t] = [ (self.filename, tag, lineno) ]
- if (not self.do_translations) and comment and not t in self.comments:
- self.comments[t] = comment
- else:
-- if t in list(self.linenos.keys()):
-+ if t in self.linenos.keys():
- self.linenos[t].append((self.filename, tag, lineno))
- else:
- self.linenos[t] = [ (self.filename, tag, lineno) ]
-@@ -101,7 +102,11 @@ class MessageOutput:
- self.comments[t] = comment
-
- def outputHeader(self, out):
-- import time
-+ from datetime import datetime
-+ # Using time.strftime was not working correctly for me: instead of a
-+ # timezone offset a timezone name was added. This fixes it.
-+ dt = datetime.now()
-+ tz = dt.astimezone().tzinfo
- out.write("""msgid ""
- msgstr ""
- "Project-Id-Version: PACKAGE VERSION\\n"
-@@ -113,7 +118,7 @@ msgstr ""
- "Content-Type: text/plain; charset=UTF-8\\n"
- "Content-Transfer-Encoding: 8bit\\n"
-
--""" % (time.strftime("%Y-%m-%d %H:%M%z")))
-+""" % (dt.astimezone(tz).strftime("%Y-%m-%d %H:%M%z")))
-
- def outputAll(self, out):
- self.outputHeader(out)
-@@ -138,6 +143,7 @@ msgstr ""
-
- class XMLDocument(object):
- def __init__(self, filename, app):
-+ self.filename = filename
- self.app = app
- self.expand_entities = self.app.options.get('expand_entities')
- self.ignored_tags = self.app.current_mode.getIgnoredTags()
-@@ -145,7 +151,13 @@ class XMLDocument(object):
- ctxt.lineNumbers(1)
- if self.app.options.get('expand_all_entities'):
- ctxt.replaceEntities(1)
-- ctxt.parseDocument()
-+
-+ try:
-+ ctxt.parseDocument()
-+ except Exception as e:
-+ print("Error parsing XML file '%s': %s" % (filename, str(e)), file=sys.stderr)
-+ sys.exit(1)
-+
- self.doc = ctxt.doc()
- if self.doc.name != filename:
- raise Exception("Error: I tried to open '%s' but got '%s' -- how did that happen?" % (filename, self.doc.name))
-@@ -166,22 +178,23 @@ class XMLDocument(object):
- elif node.isText():
- if node.isBlankNode():
- if self.app.options.get('expand_entities') or \
-- (not (node.prev and not node.prev.isBlankNode() and node.__next__ and not node.next.isBlankNode()) ):
-- #print >>sys.stderr, "BLANK"
-+ (not (node.prev and not node.prev.isBlankNode() and node.next and not node.next.isBlankNode()) ):
- node.setContent('')
- else:
-- node.setContent(re.sub('\s+',' ', node.content))
-+ node.setContent(re.sub(r'\s+',' ', node.content))
-
- elif node.children and node.type == 'element':
- child = node.children
- while child:
-+ nextchild = child.next
- self.normalizeNode(child)
-- child = child.__next__
-+ child = nextchild
-
- def normalizeString(self, text, spacepreserve = False):
- """Normalizes string to be used as key for gettext lookup.
-
- Removes all unnecessary whitespace."""
-+ mytext = text
- if spacepreserve:
- return text
- try:
-@@ -203,13 +216,20 @@ class XMLDocument(object):
- print("""Error while normalizing string as XML:\n"%s"\n""" % (text), file=sys.stderr)
- return text
-
-+ # Not sure if saving the doc here is really necessary. It was one of the
-+ # things done in debugging and don't want to spend time now to check if
-+ # we can remove it.
-+ save_doc = self.doc
-+ self.doc = ctxt.doc()
- self.normalizeNode(newnode)
-+ self.doc = save_doc
-
- result = ''
- child = newnode.children
- while child:
-+ nextchild = child.next
- result += child.serialize('utf-8')
-- child = child.__next__
-+ child = nextchild
-
- result = re.sub('^ ','', result)
- result = re.sub(' $','', result)
-@@ -235,15 +255,16 @@ class XMLDocument(object):
- ctxt.parseDocument()
- tree = ctxt.doc()
- if next:
-- newnode = tree.children.__next__
-+ newnode = tree.children.next
- else:
- newnode = tree.children
-
- result = ''
- child = newnode.children
- while child:
-+ nextchild = child.next
- result += child.serialize('utf-8')
-- child = child.__next__
-+ child = nextchild
- tree.freeDoc()
- return result
-
-@@ -252,6 +273,7 @@ class XMLDocument(object):
- result = ''
- if node.children:
- child = node.children
-+ nextchild = child.next
- while child:
- if child.type=='text':
- result += self.doc.encodeEntitiesReentrant(child.content)
-@@ -262,7 +284,7 @@ class XMLDocument(object):
- result += child.content.decode('utf-8')
- else:
- result += self.myAttributeSerialize(child)
-- child = child.__next__
-+ child = nextchild
- else:
- result = node.serialize('utf-8')
- return result
-@@ -308,11 +330,81 @@ class XMLDocument(object):
- return None
-
- def replaceAttributeContentsWithText(self, node, text):
-- node.setContent(text)
-+ try:
-+ node.setContent(text.decode('utf-8'))
-+ except TypeError:
-+ sys.stderr.write("--> replaceAttributeContentsWithText: Failed to decode text to utf-8.")
-+ sys.exit(1)
-+
-+ def CheckMatchedTags(self, text):
-+ stack = []
-+ textblock = text
-+
-+ log=sys.stdout
-+
-+ # It might be even better to do the below with regex, see e.g.
-+ # https://datadependence.com/2016/03/find-unclosed-tags-using-stacks/
-+ # However I'm not sure it really matters that much since the text
-+ # blocks usually are fairly small and most don't have a lot of tags.
-+ start_tag = textblock.find('<')
-+ while start_tag > -1:
-+ textblock = textblock[start_tag+1:]
-+ end_tag = textblock.find('>')
-+ if end_tag > -1:
-+ # Found left and right brackets: grab tag
-+ tag = textblock[: end_tag]
-+ # Check that it's not a tag that closes itself and comment tags starting with <!
-+ if textblock[end_tag-1] != '/' and textblock[0] != '!':
-+ # Tag can have multiple elements inside, watch for first space
-+ space = tag.find(' ')
-+ if space > -1:
-+ tag = tag[: space]
-+
-+ open_tag = (len(tag) > 0 and tag[0] != '/')
-+ if open_tag:
-+ # Add tag to stack
-+ stack.append(tag)
-+ else:
-+ tag = tag[1:]
-+ if len(stack) == 0:
-+ pass
-+ else:
-+ if stack[-1] == tag:
-+ # Close the block
-+ stack.pop()
-+ else:
-+ print(f"\n========================", file=log)
-+ print(f"Source xml: {self.filename}", file=log)
-+ print(f"Source po : {self.app.pofile}", file=log)
-+ print(f"Translated msgstr:\n{text}\n", file=log)
-+ print(f"WARNING: Found closing tag [{tag}], however we expected [{stack[0]}].", file=log)
-+ print(f"Remaining tags: {str(stack)}", file=log)
-+ if tag in stack:
-+ stack.remove(tag)
-+ print(" Assuming incorrect tag order, found and removed tag from the stack", file=log)
-+ print(f"========================\n", file=log)
-+ textblock = textblock[end_tag+1:]
-+ start_tag = textblock.find('<')
-+ else:
-+ start_tag = -1
-+
-+
-+ if len(stack):
-+ print(f"\n========================", file=log)
-+ print(f"Source xml: {self.filename}", file=log)
-+ print(f"Source po : {self.app.pofile}", file=log)
-+ print(f"ERROR: Found unmatched tags in po msgstr:\n{text}\n", file=log)
-+ print(f"Tags not matched: {str(stack)}", file=log)
-+ print(f"========================\n", file=log)
-+ return False
-+ return True
-
- def replaceNodeContentsWithText(self, node, text):
- """Replaces all subnodes of a node with contents of text treated as XML."""
-
-+ if not self.CheckMatchedTags(text):
-+ return
-+
- if node.children:
- starttag = self.startTagForNode(node)
- endtag = self.endTagForNode(node)
-@@ -326,7 +418,7 @@ class XMLDocument(object):
- pass
-
- content = '<%s>%s</%s>' % (starttag, text, endtag)
-- tmp = tmp + content.encode('utf-8')
-+ tmp = tmp + content
-
- newnode = None
- try:
-@@ -338,7 +430,9 @@ class XMLDocument(object):
- pass
-
- if not newnode:
-- print("""Error while parsing translation as XML:\n"%s"\n""" % (text.encode('utf-8')), file=sys.stderr)
-+ print(f"\n--> Error parsing translation as XML:\n{text}")
-+ # See: https://gitlab.gnome.org/GNOME/libxml2/-/issues/64
-+ print("--> Note: this might be caused by a bug in libxml2.\n")
- return
-
- newelem = newnode.getRootElement()
-@@ -346,15 +440,14 @@ class XMLDocument(object):
- if newelem and newelem.children:
- free = node.children
- while free:
-- next = free.__next__
-+ nextchild = free.next
- free.unlinkNode()
-- free = next
-+ free = nextchild
-
- if node:
-- copy = newelem.copyNodeList()
-- next = node.__next__
-+ nextnode = node.next
- node.replaceNode(newelem.copyNodeList())
-- node.next = next
-+ node.__next__ = nextnode
-
- else:
- # In practice, this happens with tags such as "<para> </para>" (only whitespace in between)
-@@ -374,10 +467,11 @@ class XMLDocument(object):
- return True
- child = node.children
- while child:
-+ nextchild = child.next
- if child.isText() and child.content.strip() != '':
- return True
- else:
-- child = child.__next__
-+ child = nextchild
- return False
-
-
-@@ -432,6 +526,10 @@ class XMLDocument(object):
-
- child = node.children
- while child:
-+ # Although I do not know why, child or child.next gets changed inside the if part below.
-+ # This makes child.next fail when it shouldn't. That's why we store nextchild here
-+ # before going into the if and use that at the end of the loop
-+ nextchild = child.next
- if (self.isFinalNode(child)) or (child.type == 'element' and self.worthOutputting(child)):
- myrepl.append(self.processElementTag(child, myrepl, True))
- outtxt += '<placeholder-%d/>' % (len(myrepl))
-@@ -441,20 +539,20 @@ class XMLDocument(object):
- outtxt += '<%s>%s</%s>' % (starttag, content, endtag)
- else:
- outtxt += self.doSerialize(child)
-- child = child.__next__
-+ child = nextchild
-
- if self.app.operation == 'merge':
- norm_outtxt = self.normalizeString(outtxt, self.app.isSpacePreserveNode(node))
- translation = self.app.getTranslation(norm_outtxt)
- else:
-- translation = outtxt.decode('utf-8')
-+ translation = outtxt
-
- starttag = self.startTagForNode(node)
- endtag = self.endTagForNode(node)
-
- worth = self.worthOutputting(node)
- if not translation:
-- translation = outtxt.decode('utf-8')
-+ translation = outtxt
- if worth and self.app.options.get('mark_untranslated'):
- node.setLang('C')
-
-@@ -463,7 +561,7 @@ class XMLDocument(object):
- # repl[0] may contain translated attributes with
- # non-ASCII chars, so implicit conversion to <str> may fail
- replacement = '<%s>%s</%s>' % \
-- (repl[0].decode('utf-8'), repl[3], repl[2])
-+ (repl[0], repl[3], repl[2])
- translation = translation.replace('<placeholder-%d/>' % (i+1), replacement)
-
- if worth:
-@@ -479,7 +577,7 @@ class XMLDocument(object):
- def isExternalGeneralParsedEntity(self, node):
- try:
- # it would be nice if debugDumpNode could use StringIO, but it apparently cannot
-- tmp = tempfile.TemporaryFile()
-+ tmp = tempfile.TemporaryFile(encoding='utf-8')
- node.debugDumpNode(tmp,0)
- tmp.seek(0)
- tmpstr = tmp.read()
-@@ -507,25 +605,31 @@ class XMLDocument(object):
- if self.isExternalGeneralParsedEntity(node):
- return node.serialize('utf-8')
- else:
-- return self.stringForEntity(node) #content #content #serialize("utf-8")
-- elif node.type == 'entity_decl':
-+ return self.stringForEntity(node)
-+ elif node.type == 'entity_decl --> serialize':
- return node.serialize('utf-8') #'<%s>%s</%s>' % (startTagForNode(node), node.content, node.name)
- elif node.type == 'text':
-- return node.serialize('utf-8')
-+ nodetext = node.serialize('utf-8')
-+ return nodetext
- elif node.type == 'element':
- repl = []
- (starttag, content, endtag, translation) = self.processElementTag(node, repl, True)
-- return '<%s>%s</%s>' % (starttag, content, endtag)
-+ return '<%s>%s</%s>' % (starttag, content.encode('utf-8'), endtag)
- else:
- child = node.children
- outtxt = ''
- while child:
-+ # Not sure if the same problem with using next.child happens here too
-+ # but we will use nextchild here too just to be sure
-+ nextchild = child.next
- outtxt += self.doSerialize(child)
-- child = child.__next__
-+ child = nextchild
- return outtxt
-
--def xml_error_handler(arg, ctxt):
-+def xml_error_handler(ctxt, error):
- #deactivate error messages from the validation
-+ if DEBUG_VERBOSITY > 0:
-+ print(f"--> xml_error_handler: {error}")
- pass
-
- class Main(object):
-@@ -538,11 +642,11 @@ class Main(object):
- self.current_mode = self.load_mode(mode)()
- # Prepare output
- if operation == 'update':
-- self.out = tempfile.TemporaryFile()
-+ self.out = tempfile.TemporaryFile(encoding='utf-8')
- elif output == '-':
- self.out = sys.stdout
- else:
-- self.out = file(output, 'w')
-+ self.out = open(output, 'w', encoding='utf-8', buffering=1)
-
- def load_mode(self, modename):
- try:
-@@ -565,7 +669,7 @@ class Main(object):
- try:
- doc = XMLDocument(xmlfile, self)
- except Exception as e:
-- print("Unable to parse XML file '%s': %s" % (xmlfile, str(e)), file=sys.stderr)
-+ print("Error parsing XML file '%s': %s" % (xmlfile, str(e)), file=sys.stderr)
- sys.exit(1)
- self.current_mode.preProcessXml(doc.doc, self.msg)
- doc.generate_messages()
-@@ -578,13 +682,13 @@ class Main(object):
- try:
- doc = XMLDocument(xmlfile, self)
- except Exception as e:
-- print(str(e), file=sys.stderr)
-+ print("Error parsing XML file '%s': %s" % (xmlfile, str(e)), file=sys.stderr)
- sys.exit(1)
--
- try:
- mfile = open(mofile, "rb")
- except:
-- print("Can't open MO file '%s'." % (mofile), file=sys.stderr)
-+ print("Error opening MO file '%s': %s." % (mofile, str(e)), file=sys.stderr)
-+ sys.exit(1)
- self.gt = gettext.GNUTranslations(mfile)
- self.gt.add_fallback(NoneTranslations())
- # Has preProcessXml use cases for merge?
-@@ -607,7 +711,7 @@ class Main(object):
- try:
- doc = XMLDocument(xmlfile, self)
- except Exception as e:
-- print(str(e), file=sys.stderr)
-+ print("Error parsing XML file '%s': %s" % (xmlfile, str(e)), file=sys.stderr)
- sys.exit(1)
- doc.generate_messages()
-
-@@ -615,7 +719,7 @@ class Main(object):
- try:
- doc = XMLDocument(origxml, self)
- except Exception as e:
-- print(str(e), file=sys.stderr)
-+ print("Error parsing XML file '%s': %s" % (origxml, str(e)), file=sys.stderr)
- sys.exit(1)
- doc.generate_messages()
- self.output_po()
-@@ -646,11 +750,10 @@ class Main(object):
-
- text should be a string to look for.
- """
-- #print >>sys.stderr,"getTranslation('%s')" % (text.encode('utf-8'))
- if not text or text.strip() == '':
- return text
- if self.gt:
-- res = self.gt.ugettext(text.decode('utf-8'))
-+ res = self.gt.gettext(text)
- return res
-
- return text
-diff --git a/tools/xml2po/modes/gimphelp.py b/tools/xml2po/modes/gimphelp.py
-index d72f518ee..0e7e31c73 100644
---- a/tools/xml2po/modes/gimphelp.py
-+++ b/tools/xml2po/modes/gimphelp.py
-@@ -81,7 +81,7 @@ class gimphelpXmlMode(docbookXmlMode):
- child = node.children
- while child:
- self._output_images(child,msg)
-- child = child.__next__
-+ child = child.next
-
- def preProcessXml(self, doc, msg):
- """Add additional messages of interest here."""
---
-2.29.2
-
-
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Jacob Boerema <jgboerema at gmail.com>
-Date: Mon, 29 Mar 2021 17:55:35 -0400
-Subject: [PATCH 3/3] tools: also update docbook.py to python3.
-
-(cherry picked from commit b2d8952713245cbec4fef5b613b984549ca2b2fd)
----
- tools/xml2po/modes/docbook.py | 10 +++++-----
- 1 file changed, 5 insertions(+), 5 deletions(-)
-
-diff --git a/tools/xml2po/modes/docbook.py b/tools/xml2po/modes/docbook.py
-index 5658ffc1a..ed395080e 100644
---- a/tools/xml2po/modes/docbook.py
-+++ b/tools/xml2po/modes/docbook.py
-@@ -95,7 +95,7 @@ class docbookXmlMode(basicXmlMode):
- ret = self._find_articleinfo(child)
- if ret:
- return ret
-- child = child.__next__
-+ child = child.next
- return None
-
- def _find_lastcopyright(self, node):
-@@ -140,7 +140,7 @@ class docbookXmlMode(basicXmlMode):
- child = node.children
- while child:
- self._output_images(child,msg)
-- child = child.__next__
-+ child = child.next
-
-
- def preProcessXml(self, doc, msg):
-@@ -157,7 +157,7 @@ class docbookXmlMode(basicXmlMode):
- root = doc.getRootElement()
- # DocBook documents can be something other than article, handle that as well in the future
- while root and root.name != 'article' and root.name != 'book':
-- root = root.__next__
-+ root = root.next
- if root and (root.name == 'article' or root.name == 'book'):
- root.setProp('lang', language)
- else:
-@@ -184,7 +184,7 @@ class docbookXmlMode(basicXmlMode):
- else:
- ai.addChild(copy)
- if match.group(3):
-- copy.newChild(None, "year", match.group(3).encode('utf-8'))
-+ copy.newChild(None, "year", match.group(3))
- if match.group(1) and match.group(2):
- holder = match.group(1)+"(%s)" % match.group(2)
- elif match.group(1):
-@@ -193,7 +193,7 @@ class docbookXmlMode(basicXmlMode):
- holder = match.group(2)
- else:
- holder = "???"
-- copy.newChild(None, "holder", holder.encode('utf-8'))
-+ copy.newChild(None, "holder", holder)
-
- # Perform some tests when ran standalone
- if __name__ == '__main__':
---
-2.31.1
-
Copied: gimp-help/repos/community-any/gimp-help-2.10.0-python3.patch (from rev 1139315, gimp-help/trunk/gimp-help-2.10.0-python3.patch)
===================================================================
--- gimp-help-2.10.0-python3.patch (rev 0)
+++ gimp-help-2.10.0-python3.patch 2022-03-02 07:52:59 UTC (rev 1139316)
@@ -0,0 +1,975 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Jacob Boerema <jgboerema at gmail.com>
+Date: Thu, 4 Feb 2021 15:31:12 -0500
+Subject: [PATCH 1/3] tools: start migration to python3 by running 2to3
+
+(cherry picked from commit c5079e972d62858eead44c9029d276d456daf90d)
+---
+ tools/xml2po.py | 14 ++++++------
+ tools/xml2po/__init__.py | 40 +++++++++++++++++-----------------
+ tools/xml2po/modes/docbook.py | 20 ++++++++---------
+ tools/xml2po/modes/gimphelp.py | 14 ++++++------
+ 4 files changed, 44 insertions(+), 44 deletions(-)
+
+diff --git a/tools/xml2po.py b/tools/xml2po.py
+index 037e61f27..b3e110dc3 100755
+--- a/tools/xml2po.py
++++ b/tools/xml2po.py
+@@ -41,9 +41,9 @@ NULL_STRING = '/dev/null'
+ if not os.path.exists('/dev/null'): NULL_STRING = 'NUL'
+
+ def usage (with_help = False):
+- print >> sys.stderr, "Usage: %s [OPTIONS] [XMLFILE]..." % (sys.argv[0])
++ print("Usage: %s [OPTIONS] [XMLFILE]..." % (sys.argv[0]), file=sys.stderr)
+ if with_help:
+- print >> sys.stderr, """
++ print("""
+ OPTIONS may be some of:
+ -a --automatic-tags Automatically decides if tags are to be considered
+ "final" or not
+@@ -72,7 +72,7 @@ EXAMPLES:
+ using -p option for each XML file:
+ %(command)s -p de.po chapter1.xml > chapter1.de.xml
+ %(command)s -p de.po chapter2.xml > chapter2.de.xml
+-""" % {'command': sys.argv[0]}
++""" % {'command': sys.argv[0]}, file=sys.stderr)
+
+
+ def main(argv):
+@@ -148,7 +148,7 @@ def main(argv):
+ sys.exit(0)
+
+ if operation == 'update' and output != "-":
+- print >> sys.stderr, "Option '-o' is not yet supported when updating translations directly. Ignoring this option."
++ print("Option '-o' is not yet supported when updating translations directly. Ignoring this option.", file=sys.stderr)
+
+ # Treat remaining arguments as XML files
+ filenames = []
+@@ -158,16 +158,16 @@ def main(argv):
+ try:
+ xml2po_main = Main(default_mode, operation, output, options)
+ except IOError:
+- print >> sys.stderr, "Error: cannot open file %s for writing." % (output)
++ print("Error: cannot open file %s for writing." % (output), file=sys.stderr)
+ sys.exit(5)
+
+ if operation == 'merge':
+ if len(filenames) > 1:
+- print >> sys.stderr, "Error: You can merge translations with only one XML file at a time."
++ print("Error: You can merge translations with only one XML file at a time.", file=sys.stderr)
+ sys.exit(2)
+
+ if not mofile:
+- print >> sys.stderr, "Error: You must specify MO file when merging translations."
++ print("Error: You must specify MO file when merging translations.", file=sys.stderr)
+ sys.exit(3)
+
+ xml2po_main.merge(mofile, filenames[0])
+diff --git a/tools/xml2po/__init__.py b/tools/xml2po/__init__.py
+index eec197947..7a07eb226 100644
+--- a/tools/xml2po/__init__.py
++++ b/tools/xml2po/__init__.py
+@@ -86,14 +86,14 @@ class MessageOutput:
+ self.messages.append(t)
+ if spacepreserve:
+ self.nowrap[t] = True
+- if t in self.linenos.keys():
++ if t in list(self.linenos.keys()):
+ self.linenos[t].append((self.filename, tag, lineno))
+ else:
+ self.linenos[t] = [ (self.filename, tag, lineno) ]
+ if (not self.do_translations) and comment and not t in self.comments:
+ self.comments[t] = comment
+ else:
+- if t in self.linenos.keys():
++ if t in list(self.linenos.keys()):
+ self.linenos[t].append((self.filename, tag, lineno))
+ else:
+ self.linenos[t] = [ (self.filename, tag, lineno) ]
+@@ -166,7 +166,7 @@ class XMLDocument(object):
+ elif node.isText():
+ if node.isBlankNode():
+ if self.app.options.get('expand_entities') or \
+- (not (node.prev and not node.prev.isBlankNode() and node.next and not node.next.isBlankNode()) ):
++ (not (node.prev and not node.prev.isBlankNode() and node.__next__ and not node.next.isBlankNode()) ):
+ #print >>sys.stderr, "BLANK"
+ node.setContent('')
+ else:
+@@ -176,7 +176,7 @@ class XMLDocument(object):
+ child = node.children
+ while child:
+ self.normalizeNode(child)
+- child = child.next
++ child = child.__next__
+
+ def normalizeString(self, text, spacepreserve = False):
+ """Normalizes string to be used as key for gettext lookup.
+@@ -200,7 +200,7 @@ class XMLDocument(object):
+ tree = ctxt.doc()
+ newnode = tree.getRootElement()
+ except:
+- print >> sys.stderr, """Error while normalizing string as XML:\n"%s"\n""" % (text)
++ print("""Error while normalizing string as XML:\n"%s"\n""" % (text), file=sys.stderr)
+ return text
+
+ self.normalizeNode(newnode)
+@@ -209,7 +209,7 @@ class XMLDocument(object):
+ child = newnode.children
+ while child:
+ result += child.serialize('utf-8')
+- child = child.next
++ child = child.__next__
+
+ result = re.sub('^ ','', result)
+ result = re.sub(' $','', result)
+@@ -235,7 +235,7 @@ class XMLDocument(object):
+ ctxt.parseDocument()
+ tree = ctxt.doc()
+ if next:
+- newnode = tree.children.next
++ newnode = tree.children.__next__
+ else:
+ newnode = tree.children
+
+@@ -243,7 +243,7 @@ class XMLDocument(object):
+ child = newnode.children
+ while child:
+ result += child.serialize('utf-8')
+- child = child.next
++ child = child.__next__
+ tree.freeDoc()
+ return result
+
+@@ -262,7 +262,7 @@ class XMLDocument(object):
+ result += child.content.decode('utf-8')
+ else:
+ result += self.myAttributeSerialize(child)
+- child = child.next
++ child = child.__next__
+ else:
+ result = node.serialize('utf-8')
+ return result
+@@ -338,7 +338,7 @@ class XMLDocument(object):
+ pass
+
+ if not newnode:
+- print >> sys.stderr, """Error while parsing translation as XML:\n"%s"\n""" % (text.encode('utf-8'))
++ print("""Error while parsing translation as XML:\n"%s"\n""" % (text.encode('utf-8')), file=sys.stderr)
+ return
+
+ newelem = newnode.getRootElement()
+@@ -346,13 +346,13 @@ class XMLDocument(object):
+ if newelem and newelem.children:
+ free = node.children
+ while free:
+- next = free.next
++ next = free.__next__
+ free.unlinkNode()
+ free = next
+
+ if node:
+ copy = newelem.copyNodeList()
+- next = node.next
++ next = node.__next__
+ node.replaceNode(newelem.copyNodeList())
+ node.next = next
+
+@@ -377,7 +377,7 @@ class XMLDocument(object):
+ if child.isText() and child.content.strip() != '':
+ return True
+ else:
+- child = child.next
++ child = child.__next__
+ return False
+
+
+@@ -441,7 +441,7 @@ class XMLDocument(object):
+ outtxt += '<%s>%s</%s>' % (starttag, content, endtag)
+ else:
+ outtxt += self.doSerialize(child)
+- child = child.next
++ child = child.__next__
+
+ if self.app.operation == 'merge':
+ norm_outtxt = self.normalizeString(outtxt, self.app.isSpacePreserveNode(node))
+@@ -521,7 +521,7 @@ class XMLDocument(object):
+ outtxt = ''
+ while child:
+ outtxt += self.doSerialize(child)
+- child = child.next
++ child = child.__next__
+ return outtxt
+
+ def xml_error_handler(arg, ctxt):
+@@ -565,7 +565,7 @@ class Main(object):
+ try:
+ doc = XMLDocument(xmlfile, self)
+ except Exception as e:
+- print >> sys.stderr, "Unable to parse XML file '%s': %s" % (xmlfile, str(e))
++ print("Unable to parse XML file '%s': %s" % (xmlfile, str(e)), file=sys.stderr)
+ sys.exit(1)
+ self.current_mode.preProcessXml(doc.doc, self.msg)
+ doc.generate_messages()
+@@ -578,13 +578,13 @@ class Main(object):
+ try:
+ doc = XMLDocument(xmlfile, self)
+ except Exception as e:
+- print >> sys.stderr, str(e)
++ print(str(e), file=sys.stderr)
+ sys.exit(1)
+
+ try:
+ mfile = open(mofile, "rb")
+ except:
+- print >> sys.stderr, "Can't open MO file '%s'." % (mofile)
++ print("Can't open MO file '%s'." % (mofile), file=sys.stderr)
+ self.gt = gettext.GNUTranslations(mfile)
+ self.gt.add_fallback(NoneTranslations())
+ # Has preProcessXml use cases for merge?
+@@ -607,7 +607,7 @@ class Main(object):
+ try:
+ doc = XMLDocument(xmlfile, self)
+ except Exception as e:
+- print >> sys.stderr, str(e)
++ print(str(e), file=sys.stderr)
+ sys.exit(1)
+ doc.generate_messages()
+
+@@ -615,7 +615,7 @@ class Main(object):
+ try:
+ doc = XMLDocument(origxml, self)
+ except Exception as e:
+- print >> sys.stderr, str(e)
++ print(str(e), file=sys.stderr)
+ sys.exit(1)
+ doc.generate_messages()
+ self.output_po()
+diff --git a/tools/xml2po/modes/docbook.py b/tools/xml2po/modes/docbook.py
+index 276a9d9bb..5658ffc1a 100644
+--- a/tools/xml2po/modes/docbook.py
++++ b/tools/xml2po/modes/docbook.py
+@@ -43,7 +43,7 @@ try:
+ except ImportError:
+ from md5 import new as md5_new
+
+-from basic import basicXmlMode
++from .basic import basicXmlMode
+
+ class docbookXmlMode(basicXmlMode):
+ """Class for special handling of DocBook document types.
+@@ -95,7 +95,7 @@ class docbookXmlMode(basicXmlMode):
+ ret = self._find_articleinfo(child)
+ if ret:
+ return ret
+- child = child.next
++ child = child.__next__
+ return None
+
+ def _find_lastcopyright(self, node):
+@@ -131,7 +131,7 @@ class docbookXmlMode(basicXmlMode):
+ hash = self._md5_for_file(fullpath)
+ else:
+ hash = "THIS FILE DOESN'T EXIST"
+- print >>sys.stderr, "Warning: image file '%s' not found." % fullpath
++ print("Warning: image file '%s' not found." % fullpath, file=sys.stderr)
+
+ msg.outputMessage("@@image: '%s'; md5=%s" % (attr, hash), node.lineNo(),
+ "When image changes, this message will be marked fuzzy or untranslated for you.\n"+
+@@ -140,7 +140,7 @@ class docbookXmlMode(basicXmlMode):
+ child = node.children
+ while child:
+ self._output_images(child,msg)
+- child = child.next
++ child = child.__next__
+
+
+ def preProcessXml(self, doc, msg):
+@@ -157,7 +157,7 @@ class docbookXmlMode(basicXmlMode):
+ root = doc.getRootElement()
+ # DocBook documents can be something other than article, handle that as well in the future
+ while root and root.name != 'article' and root.name != 'book':
+- root = root.next
++ root = root.__next__
+ if root and (root.name == 'article' or root.name == 'book'):
+ root.setProp('lang', language)
+ else:
+@@ -198,10 +198,10 @@ class docbookXmlMode(basicXmlMode):
+ # Perform some tests when ran standalone
+ if __name__ == '__main__':
+ test = docbookXmlMode()
+- print "Ignored tags : " + repr(test.getIgnoredTags())
+- print "Final tags : " + repr(test.getFinalTags())
+- print "Space-preserve tags: " + repr(test.getSpacePreserveTags())
++ print("Ignored tags : " + repr(test.getIgnoredTags()))
++ print("Final tags : " + repr(test.getFinalTags()))
++ print("Space-preserve tags: " + repr(test.getSpacePreserveTags()))
+
+- print "Credits from string: '%s'" % test.getStringForTranslators()
+- print "Explanation for credits:\n\t'%s'" % test.getCommentForTranslators()
++ print("Credits from string: '%s'" % test.getStringForTranslators())
++ print("Explanation for credits:\n\t'%s'" % test.getCommentForTranslators())
+
+diff --git a/tools/xml2po/modes/gimphelp.py b/tools/xml2po/modes/gimphelp.py
+index 24d4154e6..d72f518ee 100644
+--- a/tools/xml2po/modes/gimphelp.py
++++ b/tools/xml2po/modes/gimphelp.py
+@@ -31,7 +31,7 @@ try:
+ except ImportError:
+ from md5 import new as md5_new
+
+-from docbook import docbookXmlMode
++from .docbook import docbookXmlMode
+
+ class gimphelpXmlMode(docbookXmlMode):
+ """Class for special handling of gimp-help DocBook document types.
+@@ -81,7 +81,7 @@ class gimphelpXmlMode(docbookXmlMode):
+ child = node.children
+ while child:
+ self._output_images(child,msg)
+- child = child.next
++ child = child.__next__
+
+ def preProcessXml(self, doc, msg):
+ """Add additional messages of interest here."""
+@@ -91,10 +91,10 @@ class gimphelpXmlMode(docbookXmlMode):
+ # Perform some tests when ran standalone
+ if __name__ == '__main__':
+ test = gimphelpXmlMode()
+- print "Ignored tags : " + repr(test.getIgnoredTags())
+- print "Final tags : " + repr(test.getFinalTags())
+- print "Space-preserve tags: " + repr(test.getSpacePreserveTags())
++ print("Ignored tags : " + repr(test.getIgnoredTags()))
++ print("Final tags : " + repr(test.getFinalTags()))
++ print("Space-preserve tags: " + repr(test.getSpacePreserveTags()))
+
+- print "Credits from string: '%s'" % test.getStringForTranslators()
+- print "Explanation for credits:\n\t'%s'" % test.getCommentForTranslators()
++ print("Credits from string: '%s'" % test.getStringForTranslators())
++ print("Explanation for credits:\n\t'%s'" % test.getCommentForTranslators())
+
+--
+2.29.2
+
+
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Jacob Boerema <jgboerema at gmail.com>
+Date: Mon, 29 Mar 2021 17:51:48 -0400
+Subject: [PATCH 2/3] tools: complete port of xml2po to python3
+
+Also:
+- Let it work correctly on Windows by setting encoding for
+ stdout and stderr to utf-8.
+- Fix setting correct timezone in po files.
+- Better error handling.
+- Detect errors in tags in the translated xml text.
+
+(cherry picked from commit 299cfb7150857f0045ae42978d8ed917b4b0e4ff)
+---
+ tools/xml2po.py | 19 +++-
+ tools/xml2po/__init__.py | 189 +++++++++++++++++++++++++--------
+ tools/xml2po/modes/gimphelp.py | 2 +-
+ 3 files changed, 163 insertions(+), 47 deletions(-)
+
+diff --git a/tools/xml2po.py b/tools/xml2po.py
+index b3e110dc3..ef8d725da 100755
+--- a/tools/xml2po.py
++++ b/tools/xml2po.py
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python2
++#!/usr/bin/env python3
+ # -*- encoding: utf-8 -*-
+ # Copyright (c) 2004, 2005, 2006 Danilo Šegan <danilo at gnome.org>.
+ # Copyright (c) 2009 Claude Paroz <claude at 2xlibre.net>.
+@@ -21,7 +21,7 @@
+ #
+
+ # xml2po -- translate XML documents
+-VERSION = "0.18.0 (patched by GIMP Documentation Team)"
++VERSION = "0.19.0 (patched by GIMP Documentation Team)"
+
+ # Versioning system (I use this for a long time, so lets explain it to
+ # those Linux-versioning-scheme addicts):
+@@ -37,11 +37,13 @@ import os
+ import getopt
+ import tempfile
+
++DEBUG_VERBOSITY = 0
++
+ NULL_STRING = '/dev/null'
+ if not os.path.exists('/dev/null'): NULL_STRING = 'NUL'
+
+ def usage (with_help = False):
+- print("Usage: %s [OPTIONS] [XMLFILE]..." % (sys.argv[0]), file=sys.stderr)
++ print(f"Usage: {sys.argv[0]} [OPTIONS] [XMLFILE]...", file=sys.stderr)
+ if with_help:
+ print("""
+ OPTIONS may be some of:
+@@ -86,6 +88,11 @@ def main(argv):
+
+ from xml2po import Main
+
++
++ # Make sure stdout and stderr output utf-8 even on Windows where it's not the default
++ sys.stdout = open(sys.stdout.fileno(), 'w', encoding='utf-8', closefd=False)
++ sys.stderr = open(sys.stderr.fileno(), 'w', encoding='utf-8', closefd=False)
++
+ # Default parameters
+ default_mode = 'docbook'
+ operation = 'pot' # 'pot', 'merge', 'update'
+@@ -136,6 +143,8 @@ def main(argv):
+ operation = 'merge'
+ if 'translationlanguage' not in options:
+ options['translationlanguage'] = os.path.split(os.path.splitext(pofile)[0])[1]
++ if DEBUG_VERBOSITY > 0:
++ print(f"Converting {pofile} to {mofile_tmppath} using msgfmt")
+ os.system("msgfmt -o %s %s >%s" % (mofile_tmppath, pofile, NULL_STRING)) and sys.exit(7)
+ mofile = mofile_tmppath
+ elif opt in ('-o', '--output'):
+@@ -170,6 +179,10 @@ def main(argv):
+ print("Error: You must specify MO file when merging translations.", file=sys.stderr)
+ sys.exit(3)
+
++ if DEBUG_VERBOSITY > 0:
++ print(f"Merge mo file {mofile} with {filenames[0]}")
++ if pofile:
++ xml2po_main.pofile = pofile
+ xml2po_main.merge(mofile, filenames[0])
+
+ elif operation == 'update':
+diff --git a/tools/xml2po/__init__.py b/tools/xml2po/__init__.py
+index 7a07eb226..42fa81f39 100644
+--- a/tools/xml2po/__init__.py
++++ b/tools/xml2po/__init__.py
+@@ -26,6 +26,7 @@ import tempfile
+ import gettext
+ import libxml2
+
++DEBUG_VERBOSITY = 0
+ NULL_STRING = '/dev/null'
+ if not os.path.exists('/dev/null'): NULL_STRING = 'NUL'
+
+@@ -86,14 +87,14 @@ class MessageOutput:
+ self.messages.append(t)
+ if spacepreserve:
+ self.nowrap[t] = True
+- if t in list(self.linenos.keys()):
++ if t in self.linenos.keys():
+ self.linenos[t].append((self.filename, tag, lineno))
+ else:
+ self.linenos[t] = [ (self.filename, tag, lineno) ]
+ if (not self.do_translations) and comment and not t in self.comments:
+ self.comments[t] = comment
+ else:
+- if t in list(self.linenos.keys()):
++ if t in self.linenos.keys():
+ self.linenos[t].append((self.filename, tag, lineno))
+ else:
+ self.linenos[t] = [ (self.filename, tag, lineno) ]
+@@ -101,7 +102,11 @@ class MessageOutput:
+ self.comments[t] = comment
+
+ def outputHeader(self, out):
+- import time
++ from datetime import datetime
++ # Using time.strftime was not working correctly for me: instead of a
++ # timezone offset a timezone name was added. This fixes it.
++ dt = datetime.now()
++ tz = dt.astimezone().tzinfo
+ out.write("""msgid ""
+ msgstr ""
+ "Project-Id-Version: PACKAGE VERSION\\n"
+@@ -113,7 +118,7 @@ msgstr ""
+ "Content-Type: text/plain; charset=UTF-8\\n"
+ "Content-Transfer-Encoding: 8bit\\n"
+
+-""" % (time.strftime("%Y-%m-%d %H:%M%z")))
++""" % (dt.astimezone(tz).strftime("%Y-%m-%d %H:%M%z")))
+
+ def outputAll(self, out):
+ self.outputHeader(out)
+@@ -138,6 +143,7 @@ msgstr ""
+
+ class XMLDocument(object):
+ def __init__(self, filename, app):
++ self.filename = filename
+ self.app = app
+ self.expand_entities = self.app.options.get('expand_entities')
+ self.ignored_tags = self.app.current_mode.getIgnoredTags()
+@@ -145,7 +151,13 @@ class XMLDocument(object):
+ ctxt.lineNumbers(1)
+ if self.app.options.get('expand_all_entities'):
+ ctxt.replaceEntities(1)
+- ctxt.parseDocument()
++
++ try:
++ ctxt.parseDocument()
++ except Exception as e:
++ print("Error parsing XML file '%s': %s" % (filename, str(e)), file=sys.stderr)
++ sys.exit(1)
++
+ self.doc = ctxt.doc()
+ if self.doc.name != filename:
+ raise Exception("Error: I tried to open '%s' but got '%s' -- how did that happen?" % (filename, self.doc.name))
+@@ -166,22 +178,23 @@ class XMLDocument(object):
+ elif node.isText():
+ if node.isBlankNode():
+ if self.app.options.get('expand_entities') or \
+- (not (node.prev and not node.prev.isBlankNode() and node.__next__ and not node.next.isBlankNode()) ):
+- #print >>sys.stderr, "BLANK"
++ (not (node.prev and not node.prev.isBlankNode() and node.next and not node.next.isBlankNode()) ):
+ node.setContent('')
+ else:
+- node.setContent(re.sub('\s+',' ', node.content))
++ node.setContent(re.sub(r'\s+',' ', node.content))
+
+ elif node.children and node.type == 'element':
+ child = node.children
+ while child:
++ nextchild = child.next
+ self.normalizeNode(child)
+- child = child.__next__
++ child = nextchild
+
+ def normalizeString(self, text, spacepreserve = False):
+ """Normalizes string to be used as key for gettext lookup.
+
+ Removes all unnecessary whitespace."""
++ mytext = text
+ if spacepreserve:
+ return text
+ try:
+@@ -203,13 +216,20 @@ class XMLDocument(object):
+ print("""Error while normalizing string as XML:\n"%s"\n""" % (text), file=sys.stderr)
+ return text
+
++ # Not sure if saving the doc here is really necessary. It was one of the
++ # things done in debugging and don't want to spend time now to check if
++ # we can remove it.
++ save_doc = self.doc
++ self.doc = ctxt.doc()
+ self.normalizeNode(newnode)
++ self.doc = save_doc
+
+ result = ''
+ child = newnode.children
+ while child:
++ nextchild = child.next
+ result += child.serialize('utf-8')
+- child = child.__next__
++ child = nextchild
+
+ result = re.sub('^ ','', result)
+ result = re.sub(' $','', result)
+@@ -235,15 +255,16 @@ class XMLDocument(object):
+ ctxt.parseDocument()
+ tree = ctxt.doc()
+ if next:
+- newnode = tree.children.__next__
++ newnode = tree.children.next
+ else:
+ newnode = tree.children
+
+ result = ''
+ child = newnode.children
+ while child:
++ nextchild = child.next
+ result += child.serialize('utf-8')
+- child = child.__next__
++ child = nextchild
+ tree.freeDoc()
+ return result
+
+@@ -252,6 +273,7 @@ class XMLDocument(object):
+ result = ''
+ if node.children:
+ child = node.children
++ nextchild = child.next
+ while child:
+ if child.type=='text':
+ result += self.doc.encodeEntitiesReentrant(child.content)
+@@ -262,7 +284,7 @@ class XMLDocument(object):
+ result += child.content.decode('utf-8')
+ else:
+ result += self.myAttributeSerialize(child)
+- child = child.__next__
++ child = nextchild
+ else:
+ result = node.serialize('utf-8')
+ return result
+@@ -308,11 +330,81 @@ class XMLDocument(object):
+ return None
+
+ def replaceAttributeContentsWithText(self, node, text):
+- node.setContent(text)
++ try:
++ node.setContent(text.decode('utf-8'))
++ except TypeError:
++ sys.stderr.write("--> replaceAttributeContentsWithText: Failed to decode text to utf-8.")
++ sys.exit(1)
++
++ def CheckMatchedTags(self, text):
++ stack = []
++ textblock = text
++
++ log=sys.stdout
++
++ # It might be even better to do the below with regex, see e.g.
++ # https://datadependence.com/2016/03/find-unclosed-tags-using-stacks/
++ # However I'm not sure it really matters that much since the text
++ # blocks usually are fairly small and most don't have a lot of tags.
++ start_tag = textblock.find('<')
++ while start_tag > -1:
++ textblock = textblock[start_tag+1:]
++ end_tag = textblock.find('>')
++ if end_tag > -1:
++ # Found left and right brackets: grab tag
++ tag = textblock[: end_tag]
++ # Check that it's not a tag that closes itself and comment tags starting with <!
++ if textblock[end_tag-1] != '/' and textblock[0] != '!':
++ # Tag can have multiple elements inside, watch for first space
++ space = tag.find(' ')
++ if space > -1:
++ tag = tag[: space]
++
++ open_tag = (len(tag) > 0 and tag[0] != '/')
++ if open_tag:
++ # Add tag to stack
++ stack.append(tag)
++ else:
++ tag = tag[1:]
++ if len(stack) == 0:
++ pass
++ else:
++ if stack[-1] == tag:
++ # Close the block
++ stack.pop()
++ else:
++ print(f"\n========================", file=log)
++ print(f"Source xml: {self.filename}", file=log)
++ print(f"Source po : {self.app.pofile}", file=log)
++ print(f"Translated msgstr:\n{text}\n", file=log)
++ print(f"WARNING: Found closing tag [{tag}], however we expected [{stack[0]}].", file=log)
++ print(f"Remaining tags: {str(stack)}", file=log)
++ if tag in stack:
++ stack.remove(tag)
++ print(" Assuming incorrect tag order, found and removed tag from the stack", file=log)
++ print(f"========================\n", file=log)
++ textblock = textblock[end_tag+1:]
++ start_tag = textblock.find('<')
++ else:
++ start_tag = -1
++
++
++ if len(stack):
++ print(f"\n========================", file=log)
++ print(f"Source xml: {self.filename}", file=log)
++ print(f"Source po : {self.app.pofile}", file=log)
++ print(f"ERROR: Found unmatched tags in po msgstr:\n{text}\n", file=log)
++ print(f"Tags not matched: {str(stack)}", file=log)
++ print(f"========================\n", file=log)
++ return False
++ return True
+
+ def replaceNodeContentsWithText(self, node, text):
+ """Replaces all subnodes of a node with contents of text treated as XML."""
+
++ if not self.CheckMatchedTags(text):
++ return
++
+ if node.children:
+ starttag = self.startTagForNode(node)
+ endtag = self.endTagForNode(node)
+@@ -326,7 +418,7 @@ class XMLDocument(object):
+ pass
+
+ content = '<%s>%s</%s>' % (starttag, text, endtag)
+- tmp = tmp + content.encode('utf-8')
++ tmp = tmp + content
+
+ newnode = None
+ try:
+@@ -338,7 +430,9 @@ class XMLDocument(object):
+ pass
+
+ if not newnode:
+- print("""Error while parsing translation as XML:\n"%s"\n""" % (text.encode('utf-8')), file=sys.stderr)
++ print(f"\n--> Error parsing translation as XML:\n{text}")
++ # See: https://gitlab.gnome.org/GNOME/libxml2/-/issues/64
++ print("--> Note: this might be caused by a bug in libxml2.\n")
+ return
+
+ newelem = newnode.getRootElement()
+@@ -346,15 +440,14 @@ class XMLDocument(object):
+ if newelem and newelem.children:
+ free = node.children
+ while free:
+- next = free.__next__
++ nextchild = free.next
+ free.unlinkNode()
+- free = next
++ free = nextchild
+
+ if node:
+- copy = newelem.copyNodeList()
+- next = node.__next__
++ nextnode = node.next
+ node.replaceNode(newelem.copyNodeList())
+- node.next = next
++ node.__next__ = nextnode
+
+ else:
+ # In practice, this happens with tags such as "<para> </para>" (only whitespace in between)
+@@ -374,10 +467,11 @@ class XMLDocument(object):
+ return True
+ child = node.children
+ while child:
++ nextchild = child.next
+ if child.isText() and child.content.strip() != '':
+ return True
+ else:
+- child = child.__next__
++ child = nextchild
+ return False
+
+
+@@ -432,6 +526,10 @@ class XMLDocument(object):
+
+ child = node.children
+ while child:
++ # Although I do not know why, child or child.next gets changed inside the if part below.
++ # This makes child.next fail when it shouldn't. That's why we store nextchild here
++ # before going into the if and use that at the end of the loop
++ nextchild = child.next
+ if (self.isFinalNode(child)) or (child.type == 'element' and self.worthOutputting(child)):
+ myrepl.append(self.processElementTag(child, myrepl, True))
+ outtxt += '<placeholder-%d/>' % (len(myrepl))
+@@ -441,20 +539,20 @@ class XMLDocument(object):
+ outtxt += '<%s>%s</%s>' % (starttag, content, endtag)
+ else:
+ outtxt += self.doSerialize(child)
+- child = child.__next__
++ child = nextchild
+
+ if self.app.operation == 'merge':
+ norm_outtxt = self.normalizeString(outtxt, self.app.isSpacePreserveNode(node))
+ translation = self.app.getTranslation(norm_outtxt)
+ else:
+- translation = outtxt.decode('utf-8')
++ translation = outtxt
+
+ starttag = self.startTagForNode(node)
+ endtag = self.endTagForNode(node)
+
+ worth = self.worthOutputting(node)
+ if not translation:
+- translation = outtxt.decode('utf-8')
++ translation = outtxt
+ if worth and self.app.options.get('mark_untranslated'):
+ node.setLang('C')
+
+@@ -463,7 +561,7 @@ class XMLDocument(object):
+ # repl[0] may contain translated attributes with
+ # non-ASCII chars, so implicit conversion to <str> may fail
+ replacement = '<%s>%s</%s>' % \
+- (repl[0].decode('utf-8'), repl[3], repl[2])
++ (repl[0], repl[3], repl[2])
+ translation = translation.replace('<placeholder-%d/>' % (i+1), replacement)
+
+ if worth:
+@@ -479,7 +577,7 @@ class XMLDocument(object):
+ def isExternalGeneralParsedEntity(self, node):
+ try:
+ # it would be nice if debugDumpNode could use StringIO, but it apparently cannot
+- tmp = tempfile.TemporaryFile()
++ tmp = tempfile.TemporaryFile(encoding='utf-8')
+ node.debugDumpNode(tmp,0)
+ tmp.seek(0)
+ tmpstr = tmp.read()
+@@ -507,25 +605,31 @@ class XMLDocument(object):
+ if self.isExternalGeneralParsedEntity(node):
+ return node.serialize('utf-8')
+ else:
+- return self.stringForEntity(node) #content #content #serialize("utf-8")
+- elif node.type == 'entity_decl':
++ return self.stringForEntity(node)
++ elif node.type == 'entity_decl --> serialize':
+ return node.serialize('utf-8') #'<%s>%s</%s>' % (startTagForNode(node), node.content, node.name)
+ elif node.type == 'text':
+- return node.serialize('utf-8')
++ nodetext = node.serialize('utf-8')
++ return nodetext
+ elif node.type == 'element':
+ repl = []
+ (starttag, content, endtag, translation) = self.processElementTag(node, repl, True)
+- return '<%s>%s</%s>' % (starttag, content, endtag)
++ return '<%s>%s</%s>' % (starttag, content.encode('utf-8'), endtag)
+ else:
+ child = node.children
+ outtxt = ''
+ while child:
++ # Not sure if the same problem with using next.child happens here too
++ # but we will use nextchild here too just to be sure
++ nextchild = child.next
+ outtxt += self.doSerialize(child)
+- child = child.__next__
++ child = nextchild
+ return outtxt
+
+-def xml_error_handler(arg, ctxt):
++def xml_error_handler(ctxt, error):
+ #deactivate error messages from the validation
++ if DEBUG_VERBOSITY > 0:
++ print(f"--> xml_error_handler: {error}")
+ pass
+
+ class Main(object):
+@@ -538,11 +642,11 @@ class Main(object):
+ self.current_mode = self.load_mode(mode)()
+ # Prepare output
+ if operation == 'update':
+- self.out = tempfile.TemporaryFile()
++ self.out = tempfile.TemporaryFile(encoding='utf-8')
+ elif output == '-':
+ self.out = sys.stdout
+ else:
+- self.out = file(output, 'w')
++ self.out = open(output, 'w', encoding='utf-8', buffering=1)
+
+ def load_mode(self, modename):
+ try:
+@@ -565,7 +669,7 @@ class Main(object):
+ try:
+ doc = XMLDocument(xmlfile, self)
+ except Exception as e:
+- print("Unable to parse XML file '%s': %s" % (xmlfile, str(e)), file=sys.stderr)
++ print("Error parsing XML file '%s': %s" % (xmlfile, str(e)), file=sys.stderr)
+ sys.exit(1)
+ self.current_mode.preProcessXml(doc.doc, self.msg)
+ doc.generate_messages()
+@@ -578,13 +682,13 @@ class Main(object):
+ try:
+ doc = XMLDocument(xmlfile, self)
+ except Exception as e:
+- print(str(e), file=sys.stderr)
++ print("Error parsing XML file '%s': %s" % (xmlfile, str(e)), file=sys.stderr)
+ sys.exit(1)
+-
+ try:
+ mfile = open(mofile, "rb")
+ except:
+- print("Can't open MO file '%s'." % (mofile), file=sys.stderr)
++ print("Error opening MO file '%s': %s." % (mofile, str(e)), file=sys.stderr)
++ sys.exit(1)
+ self.gt = gettext.GNUTranslations(mfile)
+ self.gt.add_fallback(NoneTranslations())
+ # Has preProcessXml use cases for merge?
+@@ -607,7 +711,7 @@ class Main(object):
+ try:
+ doc = XMLDocument(xmlfile, self)
+ except Exception as e:
+- print(str(e), file=sys.stderr)
++ print("Error parsing XML file '%s': %s" % (xmlfile, str(e)), file=sys.stderr)
+ sys.exit(1)
+ doc.generate_messages()
+
+@@ -615,7 +719,7 @@ class Main(object):
+ try:
+ doc = XMLDocument(origxml, self)
+ except Exception as e:
+- print(str(e), file=sys.stderr)
++ print("Error parsing XML file '%s': %s" % (origxml, str(e)), file=sys.stderr)
+ sys.exit(1)
+ doc.generate_messages()
+ self.output_po()
+@@ -646,11 +750,10 @@ class Main(object):
+
+ text should be a string to look for.
+ """
+- #print >>sys.stderr,"getTranslation('%s')" % (text.encode('utf-8'))
+ if not text or text.strip() == '':
+ return text
+ if self.gt:
+- res = self.gt.ugettext(text.decode('utf-8'))
++ res = self.gt.gettext(text)
+ return res
+
+ return text
+diff --git a/tools/xml2po/modes/gimphelp.py b/tools/xml2po/modes/gimphelp.py
+index d72f518ee..0e7e31c73 100644
+--- a/tools/xml2po/modes/gimphelp.py
++++ b/tools/xml2po/modes/gimphelp.py
+@@ -81,7 +81,7 @@ class gimphelpXmlMode(docbookXmlMode):
+ child = node.children
+ while child:
+ self._output_images(child,msg)
+- child = child.__next__
++ child = child.next
+
+ def preProcessXml(self, doc, msg):
+ """Add additional messages of interest here."""
+--
+2.29.2
+
+
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Jacob Boerema <jgboerema at gmail.com>
+Date: Mon, 29 Mar 2021 17:55:35 -0400
+Subject: [PATCH 3/3] tools: also update docbook.py to python3.
+
+(cherry picked from commit b2d8952713245cbec4fef5b613b984549ca2b2fd)
+---
+ tools/xml2po/modes/docbook.py | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/tools/xml2po/modes/docbook.py b/tools/xml2po/modes/docbook.py
+index 5658ffc1a..ed395080e 100644
+--- a/tools/xml2po/modes/docbook.py
++++ b/tools/xml2po/modes/docbook.py
+@@ -95,7 +95,7 @@ class docbookXmlMode(basicXmlMode):
+ ret = self._find_articleinfo(child)
+ if ret:
+ return ret
+- child = child.__next__
++ child = child.next
+ return None
+
+ def _find_lastcopyright(self, node):
+@@ -140,7 +140,7 @@ class docbookXmlMode(basicXmlMode):
+ child = node.children
+ while child:
+ self._output_images(child,msg)
+- child = child.__next__
++ child = child.next
+
+
+ def preProcessXml(self, doc, msg):
+@@ -157,7 +157,7 @@ class docbookXmlMode(basicXmlMode):
+ root = doc.getRootElement()
+ # DocBook documents can be something other than article, handle that as well in the future
+ while root and root.name != 'article' and root.name != 'book':
+- root = root.__next__
++ root = root.next
+ if root and (root.name == 'article' or root.name == 'book'):
+ root.setProp('lang', language)
+ else:
+@@ -184,7 +184,7 @@ class docbookXmlMode(basicXmlMode):
+ else:
+ ai.addChild(copy)
+ if match.group(3):
+- copy.newChild(None, "year", match.group(3).encode('utf-8'))
++ copy.newChild(None, "year", match.group(3))
+ if match.group(1) and match.group(2):
+ holder = match.group(1)+"(%s)" % match.group(2)
+ elif match.group(1):
+@@ -193,7 +193,7 @@ class docbookXmlMode(basicXmlMode):
+ holder = match.group(2)
+ else:
+ holder = "???"
+- copy.newChild(None, "holder", holder.encode('utf-8'))
++ copy.newChild(None, "holder", holder)
+
+ # Perform some tests when ran standalone
+ if __name__ == '__main__':
+--
+2.31.1
+
More information about the arch-commits
mailing list