|
Packit Service |
76cb02 |
#
|
|
Packit Service |
76cb02 |
# Attempt to analyse a dblatex failure occured on a Debian platform.
|
|
Packit Service |
76cb02 |
#
|
|
Packit Service |
76cb02 |
# Author: Andreas Hoenen
|
|
Packit Service |
76cb02 |
#
|
|
Packit Service |
76cb02 |
import subprocess
|
|
Packit Service |
76cb02 |
import sys
|
|
Packit Service |
76cb02 |
import apt
|
|
Packit Service |
76cb02 |
import os
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
from dbtexmf.core.error import ErrorHandler
|
|
Packit Service |
76cb02 |
from dbtexmf.core.imagedata import ImageConverter
|
|
Packit Service |
76cb02 |
from dbtexmf.core.dbtex import DbTexCommand
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
class AptSilentProgress(apt.progress.text.OpProgress):
|
|
Packit Service |
76cb02 |
"""
|
|
Packit Service |
76cb02 |
Avoid the annoying progress messages when building the apt cache:
|
|
Packit Service |
76cb02 |
Reading package lists... Done
|
|
Packit Service |
76cb02 |
Building dependency tree
|
|
Packit Service |
76cb02 |
Reading state information... Done
|
|
Packit Service |
76cb02 |
Building data structures... Done
|
|
Packit Service |
76cb02 |
"""
|
|
Packit Service |
76cb02 |
def __init__(self, outfile=None):
|
|
Packit Service |
76cb02 |
pass
|
|
Packit Service |
76cb02 |
def done(self):
|
|
Packit Service |
76cb02 |
pass
|
|
Packit Service |
76cb02 |
def update(self, percent=None):
|
|
Packit Service |
76cb02 |
pass
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
class DebianHandler(ErrorHandler):
|
|
Packit Service |
76cb02 |
def __init__(self):
|
|
Packit Service |
76cb02 |
ErrorHandler.__init__(self)
|
|
Packit Service |
76cb02 |
self.object = None
|
|
Packit Service |
76cb02 |
self.aptcache = None
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
def signal(self, failed_object, *args, **kwargs):
|
|
Packit Service |
76cb02 |
self.object = failed_object
|
|
Packit Service |
76cb02 |
if not self.aptcache:
|
|
Packit Service |
76cb02 |
self.aptcache = apt.Cache(progress=AptSilentProgress())
|
|
Packit Service |
76cb02 |
if (isinstance(self.object, DbTexCommand)):
|
|
Packit Service |
76cb02 |
error_handled = self._check_dbtexrun()
|
|
Packit Service |
76cb02 |
elif (isinstance(self.object, ImageConverter)):
|
|
Packit Service |
76cb02 |
error_handled = self._check_imagerun(*args)
|
|
Packit Service |
76cb02 |
else:
|
|
Packit Service |
76cb02 |
error_handled = False
|
|
Packit Service |
76cb02 |
if not error_handled:
|
|
Packit Service |
76cb02 |
super(DebianHandler, self).signal(failed_object, *args, **kwargs)
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
def _check_dbtexrun(self):
|
|
Packit Service |
76cb02 |
# First, check the XML input sanity
|
|
Packit Service |
76cb02 |
if (self._check_input()):
|
|
Packit Service |
76cb02 |
return True
|
|
Packit Service |
76cb02 |
# Check that all the required utilities are there
|
|
Packit Service |
76cb02 |
if (self._check_dependencies()):
|
|
Packit Service |
76cb02 |
return True
|
|
Packit Service |
76cb02 |
# Check some alternative reasons
|
|
Packit Service |
76cb02 |
if (self._check_cyrillic()):
|
|
Packit Service |
76cb02 |
return True
|
|
Packit Service |
76cb02 |
return False
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
def _check_imagerun(self, cmd):
|
|
Packit Service |
76cb02 |
"""
|
|
Packit Service |
76cb02 |
In case of failed image converter calls check on dependency problems.
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
In Debian dblatex package dependencies on image converters are not
|
|
Packit Service |
76cb02 |
absolute, as image conversion is not dblatex's core functionality.
|
|
Packit Service |
76cb02 |
Thus the converters may be not installed. Therefore check for each one:
|
|
Packit Service |
76cb02 |
If it is used but missing, dump an appropriate hint.
|
|
Packit Service |
76cb02 |
"""
|
|
Packit Service |
76cb02 |
aptcache = self.aptcache
|
|
Packit Service |
76cb02 |
warn_msgs = []
|
|
Packit Service |
76cb02 |
if ((cmd.startswith('convert') or cmd.find('&& convert') > -1)
|
|
Packit Service |
76cb02 |
and not aptcache['graphicsmagick-imagemagick-compat'].is_installed
|
|
Packit Service |
76cb02 |
and not aptcache['imagemagick'].is_installed):
|
|
Packit Service |
76cb02 |
warn_msgs.append('For image conversion one of Debian packages'
|
|
Packit Service |
76cb02 |
+ ' graphicsmagick-imagemagick-compat')
|
|
Packit Service |
76cb02 |
warn_msgs.append('or imagemagick is needed')
|
|
Packit Service |
76cb02 |
if ((cmd.startswith('epstopdf') or cmd.find('&& epstopdf') > -1)
|
|
Packit Service |
76cb02 |
and not aptcache['ghostscript'].is_installed):
|
|
Packit Service |
76cb02 |
warn_msgs.append('For image conversion Debian package ghostscript'
|
|
Packit Service |
76cb02 |
+ ' is needed')
|
|
Packit Service |
76cb02 |
if ((cmd.startswith('fig2dev') or cmd.find('&& fig2dev') > -1)
|
|
Packit Service |
76cb02 |
and not aptcache['transfig'].is_installed):
|
|
Packit Service |
76cb02 |
warn_msgs.append('For image conversion Debian package transfig is'
|
|
Packit Service |
76cb02 |
+ ' needed')
|
|
Packit Service |
76cb02 |
if ((cmd.startswith('inkscape') or cmd.find('&& inkscape') > -1)
|
|
Packit Service |
76cb02 |
and not aptcache['inkscape'].is_installed):
|
|
Packit Service |
76cb02 |
warn_msgs.append('For image conversion Debian package inkscape is'
|
|
Packit Service |
76cb02 |
+ ' needed')
|
|
Packit Service |
76cb02 |
if warn_msgs:
|
|
Packit Service |
76cb02 |
print >> sys.stderr, "\n" + "\n".join(warn_msgs) + "\n"
|
|
Packit Service |
76cb02 |
return True
|
|
Packit Service |
76cb02 |
else:
|
|
Packit Service |
76cb02 |
return False
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
def _check_input(self):
|
|
Packit Service |
76cb02 |
"""
|
|
Packit Service |
76cb02 |
In case of failed processing try to validate the input.
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
As invalid DocBook sometimes results in strange TeX error messages, a
|
|
Packit Service |
76cb02 |
hint about the failure cause may be helpful.
|
|
Packit Service |
76cb02 |
Post failure validation is a convenience function and thus works in
|
|
Packit Service |
76cb02 |
a best effort approach, that is it will silently skip any problems,
|
|
Packit Service |
76cb02 |
e.g. the external validation program xmllint not installed.
|
|
Packit Service |
76cb02 |
"""
|
|
Packit Service |
76cb02 |
obj = self.object.run
|
|
Packit Service |
76cb02 |
nulldev0 = open(os.devnull, "r")
|
|
Packit Service |
76cb02 |
nulldev1 = open(os.devnull, "w")
|
|
Packit Service |
76cb02 |
try:
|
|
Packit Service |
76cb02 |
rc = subprocess.Popen(['xmllint', '--noout', '--postvalid',
|
|
Packit Service |
76cb02 |
'--xinclude', obj.input],
|
|
Packit Service |
76cb02 |
stdin=nulldev0,
|
|
Packit Service |
76cb02 |
stderr=nulldev1,
|
|
Packit Service |
76cb02 |
stdout=nulldev1).wait()
|
|
Packit Service |
76cb02 |
except:
|
|
Packit Service |
76cb02 |
rc = -1
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
nulldev0.close()
|
|
Packit Service |
76cb02 |
nulldev1.close()
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
if rc == 3 or rc == 4:
|
|
Packit Service |
76cb02 |
print >> sys.stderr
|
|
Packit Service |
76cb02 |
print >> sys.stderr, 'A possible reason for transformation',
|
|
Packit Service |
76cb02 |
print >> sys.stderr, 'failure is invalid DocBook'
|
|
Packit Service |
76cb02 |
print >> sys.stderr, '(as reported by xmllint)'
|
|
Packit Service |
76cb02 |
print >> sys.stderr
|
|
Packit Service |
76cb02 |
return True
|
|
Packit Service |
76cb02 |
else:
|
|
Packit Service |
76cb02 |
return False
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
def _check_dependencies(self):
|
|
Packit Service |
76cb02 |
"""
|
|
Packit Service |
76cb02 |
In case of failed processing check on dependency problems.
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
For not commonly used dblatex functionality the Debian package
|
|
Packit Service |
76cb02 |
dependencies are not absolute, thus the functionality may be not
|
|
Packit Service |
76cb02 |
installed. Therefore check for each one:
|
|
Packit Service |
76cb02 |
If it is used but a needed dependency is missing, dump an appropriate
|
|
Packit Service |
76cb02 |
hint.
|
|
Packit Service |
76cb02 |
"""
|
|
Packit Service |
76cb02 |
obj = self.object.run
|
|
Packit Service |
76cb02 |
aptcache = self.aptcache
|
|
Packit Service |
76cb02 |
warn_msgs = []
|
|
Packit Service |
76cb02 |
if obj.backend == 'xetex':
|
|
Packit Service |
76cb02 |
for debian_pkg in 'texlive-xetex', 'lmodern':
|
|
Packit Service |
76cb02 |
if not aptcache[debian_pkg].is_installed:
|
|
Packit Service |
76cb02 |
warn_msgs.append('For xetex backend Debian package '
|
|
Packit Service |
76cb02 |
+ debian_pkg + ' is needed')
|
|
Packit Service |
76cb02 |
if obj.input_format == 'sgml':
|
|
Packit Service |
76cb02 |
for debian_pkg in 'docbook', 'opensp':
|
|
Packit Service |
76cb02 |
if not aptcache[debian_pkg].is_installed:
|
|
Packit Service |
76cb02 |
warn_msgs.append('For SGML documents Debian package '
|
|
Packit Service |
76cb02 |
+ debian_pkg + ' is needed')
|
|
Packit Service |
76cb02 |
if obj.runtex.texer.encoding == 'utf8':
|
|
Packit Service |
76cb02 |
debian_pkg = 'texlive-lang-cyrillic'
|
|
Packit Service |
76cb02 |
if not aptcache[debian_pkg].is_installed:
|
|
Packit Service |
76cb02 |
warn_msgs.append('For utf8 encoding Debian package '
|
|
Packit Service |
76cb02 |
+ debian_pkg + ' is needed')
|
|
Packit Service |
76cb02 |
if warn_msgs:
|
|
Packit Service |
76cb02 |
print >> sys.stderr, "\n" + "\n".join(warn_msgs) + "\n"
|
|
Packit Service |
76cb02 |
return True
|
|
Packit Service |
76cb02 |
else:
|
|
Packit Service |
76cb02 |
return False
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
def _check_cyrillic(self):
|
|
Packit Service |
76cb02 |
obj = self.object.run
|
|
Packit Service |
76cb02 |
"""
|
|
Packit Service |
76cb02 |
In case of failed processing check on the "cyrillic scenario":
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
Transforming cyrillic documents will fail when neither using the
|
|
Packit Service |
76cb02 |
XeTeX backend nor setting option latex.unicode.use
|
|
Packit Service |
76cb02 |
In this case a hint to XeTeX (as the preferred way) may be helpful.
|
|
Packit Service |
76cb02 |
Post failure validation is a convenience function and thus works in
|
|
Packit Service |
76cb02 |
a best effort approach, that is it will silently skip any problems.
|
|
Packit Service |
76cb02 |
"""
|
|
Packit Service |
76cb02 |
# This kind of error cannot occur with backends that natively support
|
|
Packit Service |
76cb02 |
# Unicode
|
|
Packit Service |
76cb02 |
if obj.backend == 'xetex':
|
|
Packit Service |
76cb02 |
return False
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
try:
|
|
Packit Service |
76cb02 |
for log_entry in obj.runtex.texer.tex.log.get_errors():
|
|
Packit Service |
76cb02 |
if (log_entry['text']
|
|
Packit Service |
76cb02 |
== r'Undefined control sequence \cyrchar.'):
|
|
Packit Service |
76cb02 |
print >> sys.stderr
|
|
Packit Service |
76cb02 |
print >> sys.stderr, 'Transformation failure',
|
|
Packit Service |
76cb02 |
print >> sys.stderr, 'might be caused by handling a',
|
|
Packit Service |
76cb02 |
print >> sys.stderr, 'cyrillic document'
|
|
Packit Service |
76cb02 |
print >> sys.stderr, 'without the XeTeX backend'
|
|
Packit Service |
76cb02 |
print >> sys.stderr
|
|
Packit Service |
76cb02 |
return True
|
|
Packit Service |
76cb02 |
except:
|
|
Packit Service |
76cb02 |
pass
|
|
Packit Service |
76cb02 |
return False
|
|
Packit Service |
76cb02 |
|