diff -Nru rubber-1.4/data/_rubber rubber-1.5.1/data/_rubber --- rubber-1.4/data/_rubber 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/data/_rubber 2018-09-12 19:40:33.000000000 +0000 @@ -24,7 +24,6 @@ {-z,--gzip}'[compress the final document]' \ '(- *)'{-h,--help}'[show help]' \ '--into=[go to directory DIR before compiling]:directory:_files -/' \ - {-l,--landscape}'[change paper orientation (if relevant)]' \ {-n,--maxerr}'=[display at most NUM errors]:num' \ \*{-m,--module}'=[use module]:module:($_rubber_modules)' \ '--only=[only include the specified SOURCES]:sources' \ diff -Nru rubber-1.4/debian/changelog rubber-1.5.1/debian/changelog --- rubber-1.4/debian/changelog 2018-05-07 13:15:34.000000000 +0000 +++ rubber-1.5.1/debian/changelog 2018-09-17 20:14:54.000000000 +0000 @@ -1,3 +1,40 @@ +rubber (1.5.1-1) unstable; urgency=high + + * New upstream release. + Solves problems w/ non-UTF-8 characters in log files. + Closes: #907988. + + [ Nicolas Boulenguez ] + * Let uscan detect versions with three components. + * Standards-Version: 4.2.1. + + -- Hilmar Preuße Mon, 17 Sep 2018 22:14:54 +0200 + +rubber (1.5-1) unstable; urgency=medium + + * New upstream release, ported to python3. + - Removed patches included in upstream. + + Bugfixes: + - Fix stacktrace when parsing BibTeX errors (LP: #1533723). + - Use open mode r+ for /dev/null instead of rw (LP: #1543622) + - Always give a relative source path to fig2dev (Closes: #345954). + - Detect "Missing character" messages in log files (Closes: #384155). + - Update hooks for all parsers (Closes: #813855, LP: #1470988). + - Accept uppercase image extensions (LP: #1583475). + Patch from Matthias Goldhoorn . + + [ Nicolas Boulenguez ] + * Standards-Version: 4.2.0. Rules-Requires-Root: no. + Stop installing NEWS as changelog. + * Update list of Suggests, shorten for readability in aptitude. + + [ OndÅ™ej Nový ] + * d/tests: Use AUTOPKGTEST_TMP instead of ADTTMP + * Convert git repository from git-dpm to gbp layout + + -- Hilmar Preuße Fri, 31 Aug 2018 23:59:52 +0200 + rubber (1.4-3) unstable; urgency=medium * Remove Suggestion of sam2p (Closes: #824118) and any other diff -Nru rubber-1.4/debian/control rubber-1.5.1/debian/control --- rubber-1.4/debian/control 2018-05-07 13:15:34.000000000 +0000 +++ rubber-1.5.1/debian/control 2018-09-17 20:11:09.000000000 +0000 @@ -6,25 +6,36 @@ Build-Depends: debhelper (>= 11), dh-python, - python, + python3, texinfo, texlive-latex-base, -Standards-Version: 4.1.4 +Standards-Version: 4.2.1 +Rules-Requires-Root: no Vcs-Browser: https://salsa.debian.org/python-team/applications/rubber Vcs-Git: https://salsa.debian.org/python-team/applications/rubber.git Homepage: https://launchpad.net/rubber Package: rubber Architecture: all -Depends: ${python:Depends}, ${misc:Depends}, texlive-latex-base -Suggests: imagemagick - ,texlive-binaries - ,texlive-extra-utils - ,texlive-latex-extra - ,texlive-latex-recommended - ,texlive-omega - ,texlive-pictures - ,transfig +Depends: ${python3:Depends}, ${misc:Depends}, texlive-latex-base +Suggests: + asymptote, + biber, + imagemagick, + python-prompt-toolkit, + python-pygments, + python3-prompt-toolkit, + python3-pygments, + r-cran-knitr, + texlive-bibtex-extra, + texlive-binaries, + texlive-extra-utils, + texlive-latex-extra, + texlive-latex-recommended, + texlive-metapost, + texlive-omega, + texlive-pictures, + transfig, Description: automated system for building LaTeX documents This is a building system for LaTeX documents. It is based on a routine that runs just as many compilations as necessary. The module system provides a @@ -35,21 +46,16 @@ including graphics/graphicx with automatic conversion between various graphics formats and Metapost compilation. . - Some optional parts require the installation of suggested Debian packages. - . - graphics conversion: imagemagick - . - aleph, metapost: texlive-binaries - . - pythontex: texlive-extra-utils - . - cweb, minitoc, moreverb, multibib, nomencl, ntheorem: texlive-latex-extra - . - beamer, index, listings: texlive-latex-recommended - . - omega: texlive-omega - . - gnuplottex: texlive-pictures - . - conversion from XFig format: transfig -# hyperref, makeidx, natbib, verbatim: texlive-latex-base (via Depends) + Some optional parts require the installation of suggested Debian packages: + imagemagick (graphics conversion), + r-cran-knitr, + texlive-bibtex-extra (biblatex), + texlive-binaries (aleph), + texlive-latex-extra (cweb, minitoc, moreverb, multibib, nomencl, ntheorem), + texlive-latex-recommended (beamer, index, listings), + texlive-pictures (gnuplottex), + transfig (conversion from XFig format). + . + pythontex from texlive-extra-utils requires + either python3-prompt-toolkit and python3-pygments, + or python-prompt-toolkit and python-pygments for Python2 code. diff -Nru rubber-1.4/debian/copyright rubber-1.5.1/debian/copyright --- rubber-1.4/debian/copyright 2018-05-07 13:15:34.000000000 +0000 +++ rubber-1.5.1/debian/copyright 2018-09-17 20:03:11.000000000 +0000 @@ -5,8 +5,9 @@ Files: * Copyright: 2002-2011 Emmanuel Beffara - 2012-2015 Hilmar Preuße - 2015-2015 Sebastian Kapfer + 2012-2018 Hilmar Preuße + 2015-2018 Sebastian Kapfer + 2016-2018 Nicolas Boulenguez License: GPL-2+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff -Nru rubber-1.4/debian/patches/01_accurate_log.diff rubber-1.5.1/debian/patches/01_accurate_log.diff --- rubber-1.4/debian/patches/01_accurate_log.diff 2018-05-07 13:15:34.000000000 +0000 +++ rubber-1.5.1/debian/patches/01_accurate_log.diff 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -From 8871e6d40213b63668f34bcd148c30a36a79933a Mon Sep 17 00:00:00 2001 -From: Nicolas Boulenguez -Date: Sun, 11 Oct 2015 15:04:34 +0100 -Subject: more accurate log messages when deciding whether to rebuild some file - - -diff --git a/src/depend.py b/src/depend.py -index 7fa3095..9b0395d 100644 ---- a/src/depend.py -+++ b/src/depend.py -@@ -56,7 +56,7 @@ class Node (object): - # only for the second build during this rubber run, we want to skip - # recompiling based on MD5 hashes. for the first build, only the - # date counts. -- self.md5_for_source[name] = "UNKNOWN" -+ self.md5_for_source[name] = None - - def remove_source (self, name): - """ -@@ -104,15 +104,21 @@ class Node (object): - # FIXME complain if source has been modified in an unplanned way - # NB: we ignore the case source.date == None (missing dependency) here. - # NB2: to be extra correct, equal (disk-precision) timestamps trigger a recompile. -- if source.date is not None and source.date >= self.date: -- if self.md5_for_source.has_key (source_name): -- if self.md5_for_source[source_name] == rubber.util.md5_file (source_name): -- msg.debug(_("while making %s: contents of %s unchanged, ignoring mtime") % (self.products[0], source_name), pkg="depend") -- continue -- msg.debug(_("while making %s: contents of dependency %s changed, rebuilding") % (self.products[0], source_name), pkg="depend") -- return True -- msg.debug(_("while making %s: timestamp of dependency %s changed, rebuilding") % (self.products[0], source_name), pkg="depend") -+ if source.date == None: -+ msg.debug(_("Not rebuilding %s from %s: unknown source timestamp") % (self.products[0], source_name), pkg="depend") -+ elif source.date < self.date: -+ msg.debug(_("Not rebuilding %s from %s: up to date") % (self.products[0], source_name), pkg="depend") -+ elif not self.md5_for_source.has_key (source_name): -+ msg.debug(_("Rebuilding %s from %s: outdated, source not tracked") % (self.products[0], source_name), pkg="depend") - return True -+ elif self.md5_for_source [source_name] == None: -+ msg.debug(_("Rebuilding %s from %s: outdated, previous source unknown") % (self.products[0], source_name), pkg="depend") -+ return True -+ elif self.md5_for_source [source_name] != rubber.util.md5_file (source_name): -+ msg.debug(_("Rebuilding %s from %s: outdated, source really modified") % (self.products[0], source_name), pkg="depend") -+ return True -+ else: -+ msg.debug(_("Not rebuilding %s from %s: outdated, but source unmodified") % (self.products[0], source_name), pkg="depend") - return False - - def make (self, force=False): --- -cgit v0.10.2 - diff -Nru rubber-1.4/debian/patches/02_bibtex_stacktrace.diff rubber-1.5.1/debian/patches/02_bibtex_stacktrace.diff --- rubber-1.4/debian/patches/02_bibtex_stacktrace.diff 2018-05-07 13:15:34.000000000 +0000 +++ rubber-1.5.1/debian/patches/02_bibtex_stacktrace.diff 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -From 78e6130ccedde9ec833ed5b2d6f415bbde38f144 Mon Sep 17 00:00:00 2001 -From: Sebastian Kapfer -Date: Thu, 14 Jan 2016 11:01:08 +0100 -Subject: fix stacktrace when parsing a BibTeX error lacking a line number - (modified from Emmanuel) - - -diff --git a/src/biblio.py b/src/biblio.py -index 6843e80..0c67582 100644 ---- a/src/biblio.py -+++ b/src/biblio.py -@@ -81,16 +81,17 @@ class BibToolDep (rubber.depend.Node): - filename = filename[:-4] - - filename = self.find_bib (filename) or filename -- line = int (m.group ("line")) - - d = { - "pkg": "bibtex", - "kind": "error", - "file": filename, -- "line": line, - "text": text - } - -+ if m.group ("line"): -+ d["line"] = int (m.group ("line")) -+ - yield d - - last_line = line --- -cgit v0.10.2 - diff -Nru rubber-1.4/debian/patches/04_r+for_dev_null.diff rubber-1.5.1/debian/patches/04_r+for_dev_null.diff --- rubber-1.4/debian/patches/04_r+for_dev_null.diff 2018-05-07 13:15:34.000000000 +0000 +++ rubber-1.5.1/debian/patches/04_r+for_dev_null.diff 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -From 428807ccb78fcc8c7dbcdf4233848ad31d63b2f1 Mon Sep 17 00:00:00 2001 -From: Sebastian Kapfer -Date: Wed, 10 Feb 2016 01:44:52 +0100 -Subject: use open mode r+ for /dev/null instead of rw - - -diff --git a/src/util.py b/src/util.py -index 295a261..ef332d5 100644 ---- a/src/util.py -+++ b/src/util.py -@@ -409,7 +409,7 @@ devnull_fp = None - def devnull (): - global devnull_fp - if not devnull_fp: -- devnull_fp = open(os.devnull, 'rw') -+ devnull_fp = open(os.devnull, 'r+') - return devnull_fp - - def explode_path (name = "PATH"): --- -cgit v0.10.2 - diff -Nru rubber-1.4/debian/patches/05_uppercase_filename_extensions_for_graphics.diff rubber-1.5.1/debian/patches/05_uppercase_filename_extensions_for_graphics.diff --- rubber-1.4/debian/patches/05_uppercase_filename_extensions_for_graphics.diff 2018-05-07 13:15:34.000000000 +0000 +++ rubber-1.5.1/debian/patches/05_uppercase_filename_extensions_for_graphics.diff 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -From 0b20135d0f372a78472a4e1304b99a46d3c19745 Mon Sep 17 00:00:00 2001 -From: Matthias Goldhoorn -Date: Thu, 19 May 2016 11:13:31 +0200 -Subject: graphics: accept uppercase filename extensions too. - -The latex graphics include accepts uppercase filename extensions. -This patch auto-generate all uppercase filename extensions from the -given hashes. - -diff --git a/src/latex_modules/graphics.py b/src/latex_modules/graphics.py -index f961a23..79d3b8a 100644 ---- a/src/latex_modules/graphics.py -+++ b/src/latex_modules/graphics.py -@@ -61,8 +61,13 @@ class Module (rubber.module_interface.Module): - self.prefixes = [os.path.join(x, '') for x in document.env.path] - self.files = [] - -- # I take dvips as the default, but it is not portable. -+ #Latex accepts upper and lowercase filename extensions -+ # to keep the above lists clean we auto-generate the -+ # uppercase versions of the extensions automatically -+ for engine,suffixes in drv_suffixes.iteritems(): -+ suffixes += [x.upper() for x in suffixes] - -+ # I take dvips as the default, but it is not portable. - if document.vars['engine'] == 'pdfTeX' and document.products[0][-4:] == '.pdf': - self.suffixes = drv_suffixes['pdftex'] - elif document.vars['engine'] == 'VTeX': --- -cgit v0.10.2 - diff -Nru rubber-1.4/debian/patches/06_typo-manpage.diff rubber-1.5.1/debian/patches/06_typo-manpage.diff --- rubber-1.4/debian/patches/06_typo-manpage.diff 2018-05-07 13:15:34.000000000 +0000 +++ rubber-1.5.1/debian/patches/06_typo-manpage.diff 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -Desription: trivial typo spotted by lintian -Author: Nicolas Boulenguez - ---- a/doc/man-en/rubber-info.1.in -+++ b/doc/man-en/rubber-info.1.in -@@ -39,7 +39,7 @@ - that the document depends on and that Rubber cannot rebuild. - .TP - .B \-\-errors --Extract from the log file the list of errors that occured during the last -+Extract from the log file the list of errors that occurred during the last - compilation. - .TP - .B \-h, \-\-help diff -Nru rubber-1.4/debian/patches/series rubber-1.5.1/debian/patches/series --- rubber-1.4/debian/patches/series 2018-05-07 13:15:34.000000000 +0000 +++ rubber-1.5.1/debian/patches/series 2018-09-17 20:03:11.000000000 +0000 @@ -1,6 +1 @@ -01_accurate_log.diff -02_bibtex_stacktrace.diff 03_no_sam2p.diff -04_r+for_dev_null.diff -05_uppercase_filename_extensions_for_graphics.diff -06_typo-manpage.diff diff -Nru rubber-1.4/debian/rubber.docs rubber-1.5.1/debian/rubber.docs --- rubber-1.4/debian/rubber.docs 2018-05-07 13:15:34.000000000 +0000 +++ rubber-1.5.1/debian/rubber.docs 2018-09-17 20:03:11.000000000 +0000 @@ -1 +1,2 @@ +NEWS README diff -Nru rubber-1.4/debian/rules rubber-1.5.1/debian/rules --- rubber-1.4/debian/rules 2018-05-07 13:15:34.000000000 +0000 +++ rubber-1.5.1/debian/rules 2018-09-17 20:03:11.000000000 +0000 @@ -4,13 +4,8 @@ # adaptation: (c) 2002--2006 by Emmanuel Beffara. %: setup.cfg - dh $@ --buildsystem=pybuild --with python2 + dh $@ --buildsystem=pybuild --with python3 setup.cfg: ln -s debian/$@ # This symlink is listed by debian/clean. - -# Install NEWS as upstream changelog. -.PHONY: override_dh_installchangelogs -override_dh_installchangelogs: - dh_installchangelogs NEWS diff -Nru rubber-1.4/debian/tests/basic rubber-1.5.1/debian/tests/basic --- rubber-1.4/debian/tests/basic 2018-05-07 13:15:34.000000000 +0000 +++ rubber-1.5.1/debian/tests/basic 2018-09-17 20:03:11.000000000 +0000 @@ -1,6 +1,6 @@ #!/bin/sh set -C -e -f -u -cd "$ADTTMP" +cd "$AUTOPKGTEST_TMP" cat > foo.tex < Set the maximum number of displayed errors. By default, up to 10 errors are reported, saying @@ -496,17 +489,6 @@ specified file have changed. The file name ends at the first space. .TP -.BI paper \ -Specify options related to paper size. -Currently they are used to give -.I \-t -options to -.B dvips -and -.I \-p -options to -.BR dvipdfm . -.TP .BI path \ Adds the specified directory to the search path for TeX (and Rubber). The name of the directory is everything that follows the spaces after "path". diff -Nru rubber-1.4/doc/man-en/rubber-info.1.in rubber-1.5.1/doc/man-en/rubber-info.1.in --- rubber-1.4/doc/man-en/rubber-info.1.in 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/doc/man-en/rubber-info.1.in 2018-09-12 19:40:33.000000000 +0000 @@ -39,7 +39,7 @@ that the document depends on and that Rubber cannot rebuild. .TP .B \-\-errors -Extract from the log file the list of errors that occured during the last +Extract from the log file the list of errors that occurred during the last compilation. .TP .B \-h, \-\-help diff -Nru rubber-1.4/doc/man-fr/rubber.1.in rubber-1.5.1/doc/man-fr/rubber.1.in --- rubber-1.4/doc/man-fr/rubber.1.in 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/doc/man-fr/rubber.1.in 2018-09-12 19:40:33.000000000 +0000 @@ -123,13 +123,6 @@ Le document temporaire est nommé rubtmpX.tex, où X est un nombre tel qu’aucun fichier de ce nom n’existe au départ. .TP -.B \-l, \-\-landscape -Produit un document orienté en paysage. -Cette option n’a d’effet qu’avec -.B dvips -et -.BR dvipdfm . -.TP .BI \-n,\ \-\-maxerr \ Définit le nombre maximum d’erreurs affichées. Par défaut, au plus 10 erreurs sont rapportées, l’option @@ -509,17 +502,6 @@ fichier spécifié a changé. Le nom de fichier se termine au premier espace sur la ligne. .TP -.BI paper \ -Spécifie des options relatives à la taille du papier. -Pour le moment, ces options sont passées sous forme d’options -.I \-t -à -.B dvips -ou -.I \-p -à -.BR dvipdfm . -.TP .BI path \ Ajoute le répertoire spécifié au chemin de recherche de TeX (et de Rubber). Le nom du répertoire est tout le texte qui suit les espaces après « path ». diff -Nru rubber-1.4/doc/rubber.texi.in rubber-1.5.1/doc/rubber.texi.in --- rubber-1.4/doc/rubber.texi.in 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/doc/rubber.texi.in 2018-09-12 19:40:33.000000000 +0000 @@ -65,6 +65,7 @@ * Directives:: Directives in LaTeX comments. * Modules:: List of standard modules. * Graphics:: Support for graphics conversion. +* Encoding:: Encoding issues. * Index:: Directive and modules index. @end menu @@ -215,11 +216,6 @@ on standard output. The temporary document is named @file{rubtmpX.tex}, where @file{X} is a number such that no file of that name exists initially. -@item -l -@itemx --landscape -Specify that the final document should use landscape orientation. This is -relevant only when using @command{dvips} or @command{dvipdfm}. - @item -n @itemx --maxerr Set the maximum number of displayed errors. By default, up to 10 errors are @@ -436,11 +432,6 @@ specified file have changed. In case the file or command contains spaces, they must be enclosed within double or single quotes. -@item paper -Specify options related to paper size. Currently they are used to give -@option{-t} options to @command{dvips} and @option{-p} options to -@command{dvipdfm}. - @item path Adds the specified directory to the search path for TeX (and Rubber). The name of the directory is everything that follows the spaces after @@ -536,10 +527,6 @@ @item line The current line number in the current file (this is set during parsing). -@item paper -The paper size to use when compiling. This is used by post-processors like -@command{dvips} or @command{dvipdfm}. - @item path The path name of the main output file. @@ -799,12 +786,6 @@ behaviour: @ftable @command -@item paper -Specify options related to paper size. Currently they are used to give -@option{-t} options to @command{dvips} and @option{-p} options to -@command{dvipdfm}. The command-line option @option{--landscape} is equivalent -to the directive @samp{paper landscape}. - @item dvipdfm.options @itemx dvips.options Pass the specified options to the driver. The argument is a space-separated @@ -995,7 +976,7 @@ @command{epstopdf}. @end table -@node rules.ini, Index, Standard rules, Graphics +@node rules.ini, Encoding, Standard rules, Graphics @section Syntax of @command{rules.ini} The rules file has a format in the style of Wind*ws INI files. The lines that @@ -1037,9 +1018,110 @@ 0 and 12. @end table +@node Encoding, Index, rules.ini, Top +@chapter Encoding issues + +@menu +* Design choices about encoding:: Design choices about input and output encoding +* Conversion to UTF-8:: Conversion of legacy sources to UTF-8 +* Non UTF-8 sources:: Handling of unconverted legacy sources +@end menu + +@node Design choices about encoding, Conversion to UTF-8, Encoding, Encoding +@section Design choices about input and output encoding. + +Since version 1.5, rubber decodes @file{.tex} sources and log files +with the UTF-8 encoding. +Legacy 8-bits encodings are quite common, +but can easily be converted, +and should become rare now that the LaTeX community recommends UTF-8 +for new documents. + +For data exchanged with the underlying operating system, +like arguments received from the command line, +paths passed to subprocesses +or messages displayed on the console, +it makes sense that rubber uses the system default encoding: +generally UTF-8, +a code page depending on local settings on Windows. + +In the rare cases where it converts auxiliary files by itself, rubber +simply avoids to decode, and only deals with bytes between 0 and 127. + +@node Conversion to UTF-8, Non UTF-8 sources, Design choices about encoding, Encoding +@section Conversion of legacy sources to UTF-8 + +Most text editors allow you to explicitly select this encoding for +newly created files. + +An existing source with any other encoding can be converted, either by +selecting the appropriate option when saving from your favorite +editor, or with a dedicated tool. +For example, the following commands translate @file{doc.tex} from the +@option{latin1} encoding. +@example +cp doc.tex doc.tex.bak +iconv doc.tex.bak -f latin1 -o doc.tex -t utf-8 +@end example +You should then update the @code{inputenc} line, +check that the compilation goes well, +and finally remove the @file{doc.tex.bak} backup. + +Legacy US-ASCII sources, only containing bytes betwen 0 and 127 and +relying on TeX constructs like @code{\'e} to encode local characters, +are valid UTF-8 sources, and will be decoded correctly. No conversion +is needed. + +More generally, conversion from usual (8-bits, US-ASCII-compatible) +encodings will only replace bytes from 128 to 255 with new UTF-8 byte +sequences, but US-ASCII bytes will remain unchanged. + +@node Non UTF-8 sources, Encoding, Conversion to UTF-8, Encoding +@section Handling of unconverted legacy sources + +For various reasons, some sources cannot be converted. +Rubber attempts to deal with them, +but the result will never be perfect. + +Accurate detection of the source encoding is not as easy as it seems. +An @code{inputenc} command anywhere in an included @file{.tex} source +can affect remaining bytes in all including files. +Its arguments can be generated, +or depend on the result of a test. +In other words, rubber would need a full TeX interpreter, +including features that the author now consider as bugs, +like tolerating encoding errors inside comments. + +Instead, rubber translates +bytes from 0 to 127 to the right ASCII character, +most bytes from 128 to 255 to the Unicode replacement character + (often displayed as an empty square), +and rare sequences of such bytes as random non-ASCII characters. + +All encodings encountered in the TeX world share the +property that a byte between 0 and 127 anywhere in the file always +represents a single US-ASCII character, and that such characters +cannot be represented by another byte sequence. +Since rubber searches for TeX commands expressed with such characters, +it will most of the time be able to work even if it ignores all other bytes. + +Non-ASCII characters will look ugly in log messages displayed on the +screen, and this is acceptable. + +Real problems may occur when commands intended for cooperation with +the underlying operating system, +like @code{\includegraphics} or @code{\input}, +receive arguments, like paths, containing non-ASCII characters. + +These characters will be decoded incorrectly, resulting in various +problems later (no file found with the given path, for example). +This problem is not specific to rubber, +and such path arguments should always be formed of ASCII characters, +ideally roman letters, decimal digits and a dot for the extension. + @c --- Indices --- -@node Index, Directive index, rules.ini, Top +@node Index, Directive index, Encoding, Top @chapter Index @menu diff -Nru rubber-1.4/.gitignore rubber-1.5.1/.gitignore --- rubber-1.4/.gitignore 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/.gitignore 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -Makefile -settings.py -*.pyc -src/version.py -build -build-stamp -in diff -Nru rubber-1.4/NEWS rubber-1.5.1/NEWS --- rubber-1.4/NEWS 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/NEWS 2018-09-12 19:40:33.000000000 +0000 @@ -1,3 +1,31 @@ +Version 1.5.1 (2018-09-12) + + Fix two severe regressions in the python3 port. + + Bugfixes: + - Restore support for 8-bits encoded .tex sources (Debian: #907937, #907988). + - Fix many crashing log/warning/error messages. + +Version 1.5 (2018-08-06) + + This version requires Python3. + + It assumes that all files are encoded in utf-8. This should not + cause new problems, previous versions were silently assuming ASCII. + + Features: + - Remove support for selection of paper size and orientation. + - Prohibit onchange directive unless --unsafe mode. + + Bugfixes: + - Fix stacktrace when parsing BibTeX errors (LP: #1533723). + - Use open mode r+ for /dev/null instead of rw (LP: #1543622) + - Always give a relative source path to fig2dev (Debian: #345954). + - Detect "Missing character" messages in log files (Debian: #384155). + - Update hooks for all parsers (Debian: #813855, LP: #1470988). + - Accept uppercase image extensions (LP: #1583475). + Patch from Matthias Goldhoorn . + Version 1.4 (2015-12-11) This version of Rubber officially requires Python 2.6 and up. diff -Nru rubber-1.4/README rubber-1.5.1/README --- rubber-1.4/README 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/README 2018-09-12 19:40:33.000000000 +0000 @@ -13,37 +13,37 @@ * Installation -Running Rubber just requires Python version 2.6 or newer. Of course it won't +Running Rubber just requires Python 3.5. Of course it won't be of much use without a working LaTeX environment (Rubber is known to work on TeXLive and VTeX on various flavors of Unix including Darwin and Cygwin, any feedback is welcome about other systems). For compilation, you will need the Python Distutils, which are usually included -in development packages (in Debian, this is the python-dev package). To build +in development packages (in Debian, this is the python3-dev package). To build the documentation, you need texinfo (Debian package: texinfo). To compile and install Rubber, just follow the usual procedure: -# python2 setup.py --help -# python2 setup.py install -# python2 setup.py clean --all +# python3 setup.py --help +# python3 setup.py install +# python3 setup.py clean --all Some useful options to setup.py include: Disabling info docs: -# python2 setup.py build --info=False install +# python3 setup.py build --info=False install and similar for --html, --man, --pdf. Changing the installation path for manpages: -# python2 setup.py install --mandir=/path/to/man/pages +# python3 setup.py install --mandir=/path/to/man/pages Installing to a staging directory instead of the root/prefix: -# python2 setup.py install --root=/staging/directory +# python3 setup.py install --root=/staging/directory Note that if you need build and install to be two different steps (for example when building packages for distribution purposes), @@ -64,8 +64,8 @@ Finally, invoke -# python2 setup.py build -# python2 setup.py install --root=/staging/directory +# python3 setup.py build +# python3 setup.py install --root=/staging/directory * Usage @@ -79,12 +79,13 @@ * Author Rubber was originally written by Emmanuel Beffara . -It is currently maintained by Sebastian Kapfer . +It is currently maintained by Sebastian Kapfer +and Nicolas Boulenguez . Its homepage can be found at https://launchpad.net/rubber. Thanks to all those who provided testing, comments and suggestions, and re-thanks to those who wrote patches and bugfixes. -Any kind of feedback is appreciated, in order to make this program as useful, -robust and powerful as possible. +Any kind of feedback is appreciated, in order to make this program as useful +and robust as possible. diff -Nru rubber-1.4/rubber rubber-1.5.1/rubber --- rubber-1.4/rubber 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/rubber 2018-09-12 19:40:33.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # (c) Sebastian Kapfer, 2015 # vim: et:ts=4 import sys diff -Nru rubber-1.4/rubber-info rubber-1.5.1/rubber-info --- rubber-1.4/rubber-info 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/rubber-info 2018-09-12 19:40:33.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # (c) Sebastian Kapfer, 2015 # vim: et:ts=4 import sys diff -Nru rubber-1.4/rubber-pipe rubber-1.5.1/rubber-pipe --- rubber-1.4/rubber-pipe 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/rubber-pipe 2018-09-12 19:40:33.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # (c) Sebastian Kapfer, 2015 # vim: et:ts=4 import sys diff -Nru rubber-1.4/setup.py rubber-1.5.1/setup.py --- rubber-1.4/setup.py 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/setup.py 2018-09-12 19:40:33.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # vim: et:ts=4 # # This is the setup script for Rubber. It acts both as a part of the @@ -46,11 +46,11 @@ pdf = True txt = False user_options = distutils.command.build.build.user_options + [ - ("man=", None, "build Manpages [{}]".format (info)), - ("info=", None, "build Info documentation [{}]".format (info)), - ("html=", None, "format HTML documentation [{}]".format (html)), - ("pdf=", None, "format PDF documentation [{}]".format (pdf)), - ("txt=", None, "format plain text documentation [{}]".format (txt)), + ("man=", None, "build Manpages [{default}]".format (default=man)), + ("info=", None, "build Info documentation [{default}]".format (default=info)), + ("html=", None, "format HTML documentation [{default}]".format (default=html)), + ("pdf=", None, "format PDF documentation [{default}]".format (default=pdf)), + ("txt=", None, "format plain text documentation [{default}]".format (default=txt)), ] def finalize_options (self): @@ -68,8 +68,9 @@ def repl (match_object): return subs [match_object.group (1)] def func (in_path, out_path): - with open (in_path) as in_file: - with open (out_path, "w") as out_file: + # Rubber sources are encoded in utf_8. + with open (in_path, encoding='utf-8') as in_file: + with open (out_path, "w", encoding='utf-8') as out_file: for in_line in in_file: out_line = pattern.sub (repl, in_line) out_file.write (out_line) @@ -103,9 +104,9 @@ infodir = "$base/info" docdir = "$base/share/doc/rubber" user_options = distutils.command.install.install.user_options + [ - ("mandir=", None, "installation directory for manual pages [{}]".format (mandir)), - ("infodir=", None, "installation directory for info manuals [{}]".format (infodir)), - ("docdir=", None, "installation directory for other documentation [{}]".format (docdir)), + ("mandir=", None, "installation directory for manual pages [{default}]".format (default=mandir)), + ("infodir=", None, "installation directory for info manuals [{default}]".format (default=infodir)), + ("docdir=", None, "installation directory for other documentation [{default}]".format (default=docdir)), ] def finalize_options (self): @@ -230,10 +231,10 @@ "rubber-info", "rubber-pipe", ), - cmdclass = { c : globals () [c] for c in ( - "build", - "install", - "clean", - "tar", - )}, + cmdclass = { + "build": build, + "install": install, + "clean": clean, + "tar": tar, + }, ) diff -Nru rubber-1.4/src/biblio.py rubber-1.5.1/src/biblio.py --- rubber-1.4/src/biblio.py 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/src/biblio.py 2018-09-12 19:40:33.000000000 +0000 @@ -11,7 +11,6 @@ import rubber.depend import os, os.path import re -import string import subprocess class BibToolDep (rubber.depend.Node): @@ -57,7 +56,7 @@ Read the log file, identify error messages and report them. """ try: - log = open (self.blg, "r") + log = open (self.blg, encoding='utf_8', errors='replace') except: msg.warn (_("cannot open BibTeX logfile: %s") % self.blg, pkg="biblio") return @@ -81,16 +80,17 @@ filename = filename[:-4] filename = self.find_bib (filename) or filename - line = int (m.group ("line")) d = { "pkg": "bibtex", "kind": "error", "file": filename, - "line": line, "text": text } + if m.group ("line"): + d["line"] = int (m.group ("line")) + yield d last_line = line @@ -154,7 +154,7 @@ self.tool = tool def hook_bibliography (self, loc, bibs): - for name in string.split (bibs, ","): + for name in bibs.split (","): filename = self.find_bib (name) if filename is not None: self.db[name] = filename diff -Nru rubber-1.4/src/cmdline.py rubber-1.5.1/src/cmdline.py --- rubber-1.4/src/cmdline.py 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/src/cmdline.py 2018-09-12 19:40:33.000000000 +0000 @@ -9,7 +9,6 @@ import os import os.path import sys -import string from getopt import getopt, GetoptError import shutil import tempfile @@ -77,7 +76,6 @@ --inplace compile the documents from their source directory --into=DIR go to directory DIR before compiling --jobname=NAME set the job name for the first target - -l, --landscape change paper orientation (if relevant) -n, --maxerr=NUM display at most NUM errors (default: 10) -m, --module=MOD[:OPTS] use module MOD (with options OPTS) --only=SOURCES only include the specified SOURCES @@ -110,7 +108,7 @@ opts, args = getopt( cmdline, "I:bc:de:fhklm:n:o:pqr:SsvW:z", ["bzip2", "cache", "clean", "command=", "epilogue=", "force", "gzip", - "help", "inplace", "into=", "jobname=", "keep", "landscape", "maxerr=", + "help", "inplace", "into=", "jobname=", "keep", "maxerr=", "module=", "only=", "post=", "pdf", "ps", "quiet", "read=", "readopts=", "src-specials", "shell-escape", "synctex", "unsafe", "short", "texpath=", "verbose", "version", @@ -128,7 +126,7 @@ if opt == "--cache": # unimplemented option (harmless) self.ignored_option (opt) - elif opt == "--readopts": + elif opt in ("--readopts", "-l", "--landscape" ): # undocumented option which is no longer supported self.illegal_option (opt) @@ -170,20 +168,18 @@ self.place = arg elif opt == "--jobname": self.jobname = arg - elif opt in ("-l", "--landscape"): - self.prologue.append("paper landscape") elif opt in ("-n", "--maxerr"): self.max_errors = int(arg) elif opt in ("-m", "--module"): self.prologue.append("module " + - string.replace(arg, ":", " ", 1)) + arg.replace(":", " ", 1)) elif opt == "--only": self.include_only = arg.split(",") elif opt in ("-o", "--post"): if self.rubber_mode == "info": self.illegal_option (opt) self.epilogue.append("module " + - string.replace(arg, ":", " ", 1)) + arg.replace(":", " ", 1)) elif opt in ("-d", "--pdf"): if using_dvips: self.epilogue.append("module ps2pdf") @@ -301,7 +297,6 @@ msg.path = self.place self.place = os.path.abspath(self.place) - global rubber msg.log (_("This is Rubber version %s.") % rubber_version) for srcname in args: @@ -324,9 +319,11 @@ # in case of build mode, preprocessors will be run as part of # prepare_source. env = self.env = Environment () - self.env.is_in_unsafe_mode_ = self.unsafe src = self.prepare_source (src) + # safe mode is off during the prologue + self.env.is_in_unsafe_mode_ = True + if self.include_only is not None: env.main.includeonly (self.include_only) @@ -349,6 +346,9 @@ env.main.command(cmd[0], cmd[1:], {'file': 'command line'}) env.main.vars = saved_vars + # safe mode is enforced for anything that comes from the .tex file + self.env.is_in_unsafe_mode_ = self.unsafe + env.main.parse() saved_vars = env.main.vars @@ -477,7 +477,6 @@ -h, --help display this help --into=DIR go to directory DIR before compiling -k, --keep keep the temporary files after compiling - -l, --landscape change paper orientation (if relevant) -n, --maxerr=NUM display at most NUM errors (default: 10) -m, --module=MOD[:OPTS] use module MOD (with options OPTS) --only=SOURCES only include the specified SOURCES @@ -527,7 +526,7 @@ self.pipe_tempfile = srcfile.name # copy stdin into the tempfile msg.progress (_("saving the input in %s") % self.pipe_tempfile) - shutil.copyfileobj (sys.stdin, srcfile) + shutil.copyfileobj (sys.stdin.buffer, srcfile) except IOError: msg.error (_("cannot create temporary file for the main LaTeX source")) rubber.util.abort_generic_error () @@ -543,8 +542,8 @@ filename = env.final.products[0] try: # dump the results on standard output - with open (filename, "r") as output: - shutil.copyfileobj (output, sys.stdout) + with open (filename, "rb") as output: + shutil.copyfileobj (output, sys.stdout.buffer) except IOError: msg.error (_("error copying the product '%s' to stdout") % filename) rubber.util.abort_generic_error () @@ -598,8 +597,8 @@ def process_source (self, env): if self.info_action == "deps": from rubber.depend import Leaf - deps = [ k for k,n in env.depends.iteritems () if type (n) is Leaf ] - rubber.util.stdout_write (string.join (deps)) + deps = [ k for k,n in env.depends.items () if type (n) is Leaf ] + rubber.util.stdout_write (" ".join (deps)) elif self.info_action == "rules": seen = {} @@ -607,13 +606,13 @@ while len(next) > 0: node = next[0] next = next[1:] - if seen.has_key(node): + if node in seen: continue seen[node] = None if len(node.sources) == 0: continue - print ("\n%s:" % string.join(node.products)) - print (string.join(node.sources)) + print ("\n%s:" % " ".join (node.products)) + print (" ".join (node.sources)) next.extend(node.source_nodes()) else: self.info_log (self.info_action) diff -Nru rubber-1.4/src/converters/eps_gz.py rubber-1.5.1/src/converters/eps_gz.py --- rubber-1.4/src/converters/eps_gz.py 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/src/converters/eps_gz.py 2018-09-12 19:40:33.000000000 +0000 @@ -7,7 +7,7 @@ from rubber import _, msg import rubber.depend -from gzip import GzipFile +import gzip import re re_bbox = re.compile("%[%\w]*BoundingBox:") @@ -28,10 +28,20 @@ single line. """ msg.progress(_("extracting bounding box from %s") % self.source) - with GzipFile(self.source) as source: + # Binary mode causes no decoding errors, but makes + # difficult in Python to split UTF-8 input in lines. + + # Usual TeX encodings and UTF-8 share the property + # that we can search for an ASCII pattern, and avoid + # data corruption if other bytes are copied unchanged, + # whichever character they represent. + + # Any 8-bit character has the advantage over UTF-8 + # that it never causes UnicodeDecodeError. + with gzip.open(self.source, mode='rt', encoding='latin_1') as source: for line in source: if re_bbox.match(line): - with open(self.target, "w") as target: + with open(self.target, 'w', encoding='latin_1') as target: target.write(line) return True msg.error(_("no bounding box was found in %s!") % self.source) diff -Nru rubber-1.4/src/converters/fig2dev.py rubber-1.5.1/src/converters/fig2dev.py --- rubber-1.4/src/converters/fig2dev.py 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/src/converters/fig2dev.py 2018-09-12 19:40:33.000000000 +0000 @@ -4,6 +4,7 @@ Conversion of XFig graphics into various formats. """ +import os.path from rubber.util import prog_available from rubber.depend import Shell @@ -11,6 +12,11 @@ return prog_available('fig2dev') def convert (source, target, context, set): + + # The source path is embedded by fig2dev into the target, + # causing problem with LaTeX and non-ASCII characters. + # Always give a relative path. + if target[-2:] != '_t': # Here we assume the target has an extension of a standard form, i.e. @@ -20,7 +26,7 @@ # used, that is for eps, pdf and png). language = target[target.rfind('.')+1:] - result = Shell (set, ['fig2dev', '-L', language, source, target]) + result = Shell (set, ['fig2dev', '-L', language, os.path.relpath (source), target]) result.add_product (target) result.add_source (source) return result @@ -51,12 +57,12 @@ language = 'pstex' image_file = base_name + '.eps' - temp = Shell (set, ['fig2dev', '-L', language, source, image_file]) + temp = Shell (set, ['fig2dev', '-L', language, os.path.relpath (source), image_file]) temp.add_product (image_file) temp.add_source (source) result = Shell (set, ['fig2dev', '-L', language + '_t', - '-p', image_reference, source, target]) + '-p', image_reference, os.path.relpath (source), target]) result.add_product (target) result.add_source (source) result.add_source (image_file) diff -Nru rubber-1.4/src/converters/latex.py rubber-1.5.1/src/converters/latex.py --- rubber-1.4/src/converters/latex.py 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/src/converters/latex.py 2018-09-12 19:40:33.000000000 +0000 @@ -11,7 +11,6 @@ import os, os.path, sys, imp import re -import string from rubber import _ from rubber.util import * @@ -41,14 +40,11 @@ """ return self.objects[name] - def __contains__ (self, other): - return other in self.objects - - def has_key (self, name): + def __contains__ (self, name): """ Check if a given module is loaded. """ - return self.objects.has_key(name) + return name in self.objects def register (self, name, context={}): """ @@ -57,7 +53,7 @@ load it, initialise it (using the context passed as optional argument) and run any delayed commands for it. """ - if self.has_key(name): + if name in self: msg.debug(_("module %s already registered") % name, pkg='latex') return 2 @@ -109,7 +105,7 @@ # Run any delayed commands. - if self.commands.has_key(name): + if name in self.commands: for (cmd, args, vars) in self.commands[name]: msg.push_pos(vars) try: @@ -138,10 +134,10 @@ Send a command to a particular module. If this module is not loaded, store the command so that it will be sent when the module is register. """ - if self.objects.has_key(mod): + if mod in self.objects: self.objects[mod].command(cmd, args) else: - if not self.commands.has_key(mod): + if mod not in self.commands: self.commands[mod] = [] self.commands[mod].append((cmd, args, self.env.vars)) @@ -184,7 +180,7 @@ """ self.lines = None try: - with open (name) as fp: + with open (name, encoding='utf_8', errors='replace') as fp: line = fp.readline () if not line or not re_loghead.match (line): msg.log (_('empty log'), pkg='latex') @@ -222,7 +218,7 @@ # sometimes issues warnings (like undefined references) in the # form of errors... - if string.find(line, "pdfTeX warning") == -1: + if line.find("pdfTeX warning") == -1: return 1 return 0 @@ -291,7 +287,7 @@ m = re_cseq.match(line) if m: seq = m.group("seq") - if cseqs.has_key(seq): + if seq in cseqs: error = None else: cseqs[seq] = None @@ -303,7 +299,7 @@ if m: parsing = 0 skipping = 1 - pdfTeX = string.find(line, "pdfTeX warning") != -1 + pdfTeX = line.find("pdfTeX warning") != -1 if error is not None and ((pdfTeX and warnings) or (errors and not pdfTeX)): if pdfTeX: d = { @@ -320,7 +316,7 @@ m = re_ignored.search(error) if m: d["file"] = last_file - if d.has_key("code"): + if "code" in d: del d["code"] d.update( m.groupdict() ) elif pos[-1] is None: @@ -354,7 +350,7 @@ } continue - if len(line) > 0 and line[0] == "!": + if line.startswith ('!'): error = line[2:] parsing = 1 continue @@ -367,11 +363,16 @@ if line[:17] == "Output written on": continue + if line.startswith ('Missing character: '): + error = line + parsing = 0 + continue + # Long warnings if prefix is not None: if line[:len(prefix)] == prefix: - text.append(string.strip(line[len(prefix):])) + text.append(line[len(prefix):].strip()) else: text = " ".join(text) m = re_online.search(text) @@ -515,7 +516,7 @@ if match is None: return True - vars = dict(self.latex_dep.vars.items()) + vars = self.latex_dep.vars.to_dict () vars['line'] = self.pos_line args = parse_line(match.group("arg"), vars) @@ -532,11 +533,11 @@ self.pos_char += match.end() return -class EndDocument: +class EndDocument (Exception): """ This is the exception raised when \\end{document} is found. """ pass -class EndInput: +class EndInput (Exception): """ This is the exception raised when \\endinput is found. """ pass @@ -572,7 +573,6 @@ self.vars = Variables(env.vars, { "program": "latex", "engine": "TeX", - "paper": "", "arguments": [], "src-specials": "", "source": None, @@ -588,6 +588,7 @@ # the initial hooks: + self.hooks_version = 0 self.hooks = { "begin": ("a", self.h_begin), "end": ("a", self.h_end), @@ -616,7 +617,6 @@ self.end_hooks = { "document": self.h_end_document } - self.hooks_changed = True self.include_only = {} @@ -743,12 +743,11 @@ the included sources. """ parser = SourceParser(file, self) - parser.set_hooks(self.hooks.keys()) - self.hooks_changed = False + hooks_version = -1 while True: - if self.hooks_changed: + if hooks_version != self.hooks_version: parser.set_hooks(self.hooks.keys()) - self.hooks_changed = False + hooks_version = self.hooks_version token = parser.next_hook() if token.cat == EOF: break @@ -770,7 +769,7 @@ This method is called when an included file is processed. The argument must be a valid file name. """ - if self.processed_sources.has_key(path): + if path in self.processed_sources: msg.debug(_("%s already parsed") % path, pkg='latex') return self.processed_sources[path] = None @@ -783,11 +782,8 @@ msg.log(_("parsing %s") % path, pkg='latex') self.vars = Variables(saved_vars, { "file": path, "line": None }) - file = open(path) - try: + with open (path, encoding='utf_8', errors='replace') as file: self.parse_file(file) - finally: - file.close() finally: self.vars = saved_vars @@ -844,22 +840,22 @@ pos = self.vars # Calls to this method are actually translated into calls to "do_*" # methods, except for calls to module directives. - lst = string.split(cmd, ".", 1) + lst = cmd.split(".", 1) #try: if len(lst) > 1: self.modules.command(lst[0], lst[1], args) elif not hasattr(self, "do_" + cmd): - msg.warn(_("unknown directive '%s'") % cmd, **pos) + msg.warn(_("unknown directive '%s'") % cmd, **pos.to_dict()) else: msg.log(_("directive: %s") % ' '.join([cmd]+args), pkg='latex') getattr(self, "do_" + cmd)(*args) #except TypeError: - # msg.warn(_("wrong syntax for '%s'") % cmd, **pos) + # msg.warn(_("wrong syntax for '%s'") % cmd, **pos.to_dict()) def do_alias (self, name, val): - if self.hooks.has_key(val): + if val in self.hooks: self.hooks[name] = self.hooks[val] - self.hooks_changed = True + self.hooks_version += 1 def do_clean (self, *args): for file in args: @@ -871,7 +867,7 @@ if file: self.add_source(file) else: - msg.warn(_("dependency '%s' not found") % arg, **self.vars) + msg.warn(_("dependency '%s' not found") % arg, **self.vars.to_dict ()) def do_make (self, file, *args): vars = { "target": file } @@ -884,7 +880,7 @@ break args = args[2:] if len(args) != 0: - msg.error(_("invalid syntax for 'make'"), **self.vars) + msg.error(_("invalid syntax for 'make'"), **self.vars.to_dict()) return self.env.conv_set(file, vars) @@ -892,11 +888,14 @@ self.modules.register (mod, context = {'arg':mod, 'opt':opt}) def do_onchange (self, file, cmd): + if not self.env.is_in_unsafe_mode_: + msg.warn (_("Rubber directive 'onchange' is valid only in unsafe mode")) + return self.onchange_cmd[file] = cmd self.onchange_md5[file] = md5_file(file) def do_paper (self, arg): - self.vars["paper"] = arg + msg.warn (_("Rubber directive 'paper' is no longer supported")) def do_path (self, name): self.env.path.append(name) @@ -906,7 +905,7 @@ try: self.vars = Variables (self.vars, { "file": name, "line": None }) - with open(name) as file: + with open (name, encoding='utf_8', errors='replace') as file: lineno = 0 for line in file: lineno += 1 @@ -917,14 +916,14 @@ lst = parse_line(line, self.vars) self.command(lst[0], lst[1:]) except IOError: - msg.warn(_("cannot read option file %s") % name, **self.vars) + msg.warn(_("cannot read option file %s") % name, **self.vars.to_dict()) finally: self.vars = saved_vars def do_rules (self, file): name = self.env.find_file(file) if name is None: - msg.warn(_("cannot read rule file %s") % file, **self.vars) + msg.warn(_("cannot read rule file %s") % file, **self.vars.to_dict()) else: self.env.converter.read_ini(name) @@ -941,7 +940,7 @@ return self.vars[name] = val except KeyError: - msg.warn(_("unknown variable: %s") % name, **self.vars) + msg.warn(_("unknown variable: %s") % name, **self.vars.to_dict()) def do_shell_escape (self): self.env.doc_requires_shell_ = True @@ -953,7 +952,7 @@ try: self.vars[name] = list(val) except KeyError: - msg.warn(_("unknown variable: %s") % name, **self.vars) + msg.warn(_("unknown variable: %s") % name, **self.vars.to_dict()) def do_produce (self, *args): for arg in args: @@ -967,7 +966,7 @@ def hook_macro (self, name, format, fun): self.hooks[name] = (format, fun) - self.hooks_changed = True + self.hooks_version += 1 def hook_begin (self, name, fun): self.begin_hooks[name] = fun @@ -978,11 +977,11 @@ # Now the macro handlers: def h_begin (self, loc, env): - if self.begin_hooks.has_key(env): + if env in self.begin_hooks: self.begin_hooks[env](loc) def h_end (self, loc, env): - if self.end_hooks.has_key(env): + if env in self.end_hooks: self.end_hooks[env](loc) def h_pdfoutput (self, loc): @@ -1041,7 +1040,7 @@ source in a way very similar to \\input, except that LaTeX also creates .aux files for them, so we have to notice this. """ - if self.include_only and not self.include_only.has_key(filename): + if self.include_only and filename not in self.include_only: return file, _ = self.input_file(filename, loc) if file: @@ -1080,7 +1079,7 @@ unless there is a supporting module in the current directory, otherwise it is treated as a package. """ - for name in string.split(names, ","): + for name in names.split(","): name = name.strip() if name == '': continue # \usepackage{a,} file = self.env.find_file(name + ".sty") @@ -1217,7 +1216,7 @@ paths.append("." + p[len(prefix):]) else: paths.append(p) - inputs = string.join(paths, ":") + inputs = ":".join (paths) if inputs == "": env = {} @@ -1225,7 +1224,7 @@ inputs = inputs + ":" + os.getenv("TEXINPUTS", "") env = {"TEXINPUTS": inputs} - self.env.execute(cmd, env, kpse=1) + self.env.execute (cmd, env) if not self.parse_log (): msg.error(_("Running %s failed.") % cmd[0]) @@ -1353,7 +1352,7 @@ 'file': filename, 'line': None }) lineno = 0 - with open(filename) as file: + with open(filename, encoding='latin_1') as file: for line in file: line = line.strip() lineno = lineno + 1 diff -Nru rubber-1.4/src/converters/mpost.py rubber-1.5.1/src/converters/mpost.py --- rubber-1.4/src/converters/mpost.py 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/src/converters/mpost.py 2018-09-12 19:40:33.000000000 +0000 @@ -9,7 +9,7 @@ """ import os, os.path -import re, string +import re from rubber.util import _ from rubber.util import * @@ -40,7 +40,7 @@ The read() method in LogCheck checks that the log is produced by TeX, here we check that it is produced by MetaPost. """ - with open (name) as file: + with open (name, encoding='utf_8', errors='replace') as file: line = file.readline() if not line or line.find("This is MetaPost,") == -1: return 1 @@ -78,9 +78,9 @@ yield err continue - # read mpxerr.tex to read line unmbers from it + # read mpxerr.tex to read line numbers from it - with open(os.path.join(self.pwd, "mpxerr.tex")) as tex_file: + with open(os.path.join(self.pwd, "mpxerr.tex"), encoding='utf_8', errors='replace') as tex_file: tex = tex_file.readlines() # get the name of the mpxNNN.tex source @@ -131,7 +131,7 @@ if self.env.path == [""]: self.penv = {} else: - path = string.join(self.env.path, ":") + path = ':'.join (self.env.path) self.penv = { "TEXINPUTS": "%s:%s" % (path, os.getenv("TEXINPUTS", "")), "MPINPUTS": "%s:%s" % (path, os.getenv("MPINPUTS", "")) } @@ -149,7 +149,9 @@ elif not os.path.exists(file): return self.add_source (file) - with open(file) as fd: + # In case UnicodeDecodeError, at worst a .mp file will + # not be found. + with open (file, encoding='utf_8', errors='replace') as fd: for line in fd: m = re_input.search(line) if m: @@ -162,7 +164,7 @@ """ msg.progress(_("running Metapost on %s") % msg.simplify(self.base + ".mp")) - if self.env.execute(self.cmd, self.penv, pwd=self.cmd_pwd, kpse=1) == 0: + if self.env.execute (self.cmd, self.penv, pwd=self.cmd_pwd) == 0: return True # This creates a log file that has the same aspect as TeX logs. diff -Nru rubber-1.4/src/convert.py rubber-1.5.1/src/convert.py --- rubber-1.4/src/convert.py 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/src/convert.py 2018-09-12 19:40:33.000000000 +0000 @@ -4,7 +4,7 @@ """ import re, imp, os.path -from ConfigParser import * +from configparser import ConfigParser from rubber.util import _, msg import rubber.util @@ -217,7 +217,7 @@ candidates.sort() for cost, source, target, rule in candidates: - instance = rubber.util.Variables(context, dict(rule)) + instance = rubber.util.Variables(context, rule.to_dict()) instance['source'] = source instance['target'] = target if check is not None and not check(instance): diff -Nru rubber-1.4/src/depend.py rubber-1.5.1/src/depend.py --- rubber-1.4/src/depend.py 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/src/depend.py 2018-09-12 19:40:33.000000000 +0000 @@ -47,7 +47,7 @@ Register a new source for this node. If the source is unknown, a leaf node is made for it. """ - if not self.set.has_key(name): + if name not in self.set: self.set[name] = Leaf(self.set, name) if name not in self.sources: self.sources.append(name) @@ -56,14 +56,14 @@ # only for the second build during this rubber run, we want to skip # recompiling based on MD5 hashes. for the first build, only the # date counts. - self.md5_for_source[name] = "UNKNOWN" + self.md5_for_source[name] = None def remove_source (self, name): """ Remove a source for this node. """ self.sources.remove (name) - if self.md5_for_source.has_key (name): + if name in self.md5_for_source: del self.md5_for_source[name] def add_product (self, name): @@ -104,15 +104,21 @@ # FIXME complain if source has been modified in an unplanned way # NB: we ignore the case source.date == None (missing dependency) here. # NB2: to be extra correct, equal (disk-precision) timestamps trigger a recompile. - if source.date is not None and source.date >= self.date: - if self.md5_for_source.has_key (source_name): - if self.md5_for_source[source_name] == rubber.util.md5_file (source_name): - msg.debug(_("while making %s: contents of %s unchanged, ignoring mtime") % (self.products[0], source_name), pkg="depend") - continue - msg.debug(_("while making %s: contents of dependency %s changed, rebuilding") % (self.products[0], source_name), pkg="depend") - return True - msg.debug(_("while making %s: timestamp of dependency %s changed, rebuilding") % (self.products[0], source_name), pkg="depend") + if source.date == None: + msg.debug(_("Not rebuilding %s from %s: unknown source timestamp") % (self.products[0], source_name), pkg="depend") + elif source.date < self.date: + msg.debug(_("Not rebuilding %s from %s: up to date") % (self.products[0], source_name), pkg="depend") + elif source_name not in self.md5_for_source: + msg.debug(_("Rebuilding %s from %s: outdated, source not tracked") % (self.products[0], source_name), pkg="depend") return True + elif self.md5_for_source [source_name] == None: + msg.debug(_("Rebuilding %s from %s: outdated, previous source unknown") % (self.products[0], source_name), pkg="depend") + return True + elif self.md5_for_source [source_name] != rubber.util.md5_file (source_name): + msg.debug(_("Rebuilding %s from %s: outdated, source really modified") % (self.products[0], source_name), pkg="depend") + return True + else: + msg.debug(_("Not rebuilding %s from %s: outdated, but source unmodified") % (self.products[0], source_name), pkg="depend") return False def make (self, force=False): @@ -282,7 +288,7 @@ self.add_product (product) def run (self): - self.stdout = open(self.products[0], 'w') + self.stdout = open(self.products[0], 'bw') ret = super (Pipe, self).run () self.stdout.close() return ret diff -Nru rubber-1.4/src/dvip_tool.py rubber-1.5.1/src/dvip_tool.py --- rubber-1.4/src/dvip_tool.py 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/src/dvip_tool.py 2018-09-12 19:40:33.000000000 +0000 @@ -23,7 +23,6 @@ # from rubber.depend.Shell instead of rubber.depend.Node. product_extension = { 'dvips':'ps', 'dvipdfm':'pdf' } -paper_selection_option = { 'dvips':'-t', 'dvipdfm':'-p' } class Module (rubber.depend.Node, rubber.module_interface.Module): # This class may not be instantiated directly, only subclassed. @@ -55,13 +54,11 @@ if tool == 'dvips' and self.doc.vars ['engine'] == 'Omega': tool = 'odvips' cmd = [ tool ] - for opt in self.doc.vars['paper'].split (): - cmd.extend ((paper_selection_option [self.tool], opt)) cmd.extend (self.extra_args) cmd.append (self.source) # run - if self.doc.env.execute (cmd, kpse=1) != 0: + if self.doc.env.execute (cmd) != 0: msg.error (_('%s failed on %s') % (tool, self.source)) return False return True diff -Nru rubber-1.4/src/environment.py rubber-1.5.1/src/environment.py --- rubber-1.4/src/environment.py 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/src/environment.py 2018-09-12 19:40:33.000000000 +0000 @@ -7,8 +7,8 @@ building process. """ -import os, os.path, sys, subprocess, thread -import re, string +import os, os.path, sys, subprocess +import re from subprocess import Popen from rubber.util import _ @@ -17,8 +17,6 @@ import rubber.depend from rubber.convert import Converter -re_kpse = re.compile("kpathsea: Running (?P[^ ]*).* (?P[^ ]*)$") - class Environment: """ This class contains all state information related to the building process @@ -30,12 +28,6 @@ reference directory for compilation, by default it is the current working directory. """ - self.kpse_msg = { - "mktextfm" : _("making font metrics for \\g"), - "mktexmf" : _("making font \\g"), - "mktexpk" : _("making bitmap for font \\g") - } - if cwd is None: cwd = os.getcwd() self.vars = Variables(items = { 'cwd': cwd, '_environment': self }) self.path = [cwd] @@ -47,7 +39,6 @@ self.converter = Converter(self.depends) self.converter.read_ini (os.path.join (rubber.__path__[0], 'rules.ini')) - self.is_in_unsafe_mode_ = False self.doc_requires_shell_ = False self.synctex = False self.main = None @@ -94,12 +85,12 @@ # Define a check function, according to preferences. - if self.conv_prefs.has_key(t): + if t in self.conv_prefs: prefs = self.conv_prefs[t] def do_check (vars, prefs=prefs): if prefs is not None: for key, val in prefs.items(): - if not (vars.has_key(key) and vars[key] == val): + if not (key in vars and vars[key] == val): return 0 return 1 else: @@ -134,18 +125,15 @@ """ return self.converter.may_produce(name) - def execute (self, prog, env={}, pwd=None, out=None, kpse=0): + def execute (self, prog, env={}, pwd=None, out=None): """ Silently execute an external program. The `prog' argument is the list of arguments for the program, `prog[0]' is the program name. The `env' argument is a dictionary with definitions that should be added to the environment when running the program. The standard output is passed - line by line to the `out' function (or discarded by default). If the - optional argument `kpse' is true, the error output is parsed and - messages from Kpathsea are processed (to indicate e.g. font - compilation), otherwise the error output is kept untouched. + line by line to the `out' function (or discarded by default). """ - msg.info(_("executing: %s") % string.join(prog)) + msg.info(_("executing: %s") % " ".join (prog)) if pwd: msg.log(_(" in directory %s") % pwd) if env != {}: @@ -160,32 +148,13 @@ for (key,val) in env.items(): penv[key] = val - if kpse: - stderr = subprocess.PIPE - else: - stderr = None - process = Popen(prog, executable = progname, env = penv, cwd = pwd, stdin = devnull(), stdout = subprocess.PIPE, - stderr = stderr) - - if kpse: - def parse_kpse (): - for line in process.stderr: - line = line.rstrip() - match = re_kpse.match(line) - if not match: - continue - cmd = match.group("cmd") - if self.kpse_msg.has_key(cmd): - msg.progress(match.expand(self.kpse_msg[cmd])) - else: - msg.progress(_("kpathsea running %s") % cmd) - thread.start_new_thread(parse_kpse, ()) + stderr = None) if out is not None: for line in process.stdout: diff -Nru rubber-1.4/src/latex_modules/biblatex.py rubber-1.5.1/src/latex_modules/biblatex.py --- rubber-1.4/src/latex_modules/biblatex.py 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/src/latex_modules/biblatex.py 2018-09-12 19:40:33.000000000 +0000 @@ -104,7 +104,7 @@ current_bib = None try: - log = open (self.blg, "r") + log = open (self.blg, encoding='utf_8', errors='replace') except: msg.warn (_("cannot open Biber logfile: %s") % self.blg, pkg="biblatex") return diff -Nru rubber-1.4/src/latex_modules/graphics.py rubber-1.5.1/src/latex_modules/graphics.py --- rubber-1.4/src/latex_modules/graphics.py 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/src/latex_modules/graphics.py 2018-09-12 19:40:33.000000000 +0000 @@ -16,7 +16,7 @@ """ import os, os.path -import string, re +import re from rubber import _, msg from rubber.util import parse_keyval @@ -61,8 +61,13 @@ self.prefixes = [os.path.join(x, '') for x in document.env.path] self.files = [] - # I take dvips as the default, but it is not portable. + #Latex accepts upper and lowercase filename extensions + # to keep the above lists clean we auto-generate the + # uppercase versions of the extensions automatically + for engine,suffixes in drv_suffixes.items(): + suffixes += [x.upper() for x in suffixes] + # I take dvips as the default, but it is not portable. if document.vars['engine'] == 'pdfTeX' and document.products[0][-4:] == '.pdf': self.suffixes = drv_suffixes['pdftex'] elif document.vars['engine'] == 'VTeX': @@ -76,7 +81,7 @@ opts = parse_keyval(context['opt']) for opt in opts.keys(): - if drv_suffixes.has_key(opt): + if opt in drv_suffixes: self.suffixes = drv_suffixes[opt] document.vars['graphics_suffixes'] = self.suffixes @@ -129,7 +134,7 @@ self.doc.add_source(file) self.files.append(node) else: - msg.warn(_("graphics `%s' not found") % name, **dict(loc)) + msg.warn(_("graphics `%s' not found") % name, **loc.to_dict()) def hook_graphicspath (self, loc, arg): # The argument of \graphicspath is a list (in the sense of TeX) of @@ -143,13 +148,13 @@ def hook_declareExtensions (self, loc, list): for suffix in list.split(","): - self.suffixes.insert(0, string.strip(suffix)) + self.suffixes.insert(0, suffix.strip()) def hook_declareRule (self, loc, ext, type, read, command): if read in self.suffixes: return self.suffixes.insert(0, read) - msg.log("*** FIXME *** rule %s -> %s [%s]" % (string.strip (ext), read, type), pkg='graphics') + msg.log("*** FIXME *** rule %s -> %s [%s]" % (ext.strip (), read, type), pkg='graphics') # module interface diff -Nru rubber-1.4/src/latex_modules/minitoc.py rubber-1.5.1/src/latex_modules/minitoc.py --- rubber-1.4/src/latex_modules/minitoc.py 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/src/latex_modules/minitoc.py 2018-09-12 19:40:33.000000000 +0000 @@ -17,6 +17,7 @@ from rubber import _, msg from rubber.util import verbose_remove import rubber.module_interface +import rubber.util class Module (rubber.module_interface.Module): def __init__ (self, document, context): @@ -24,8 +25,15 @@ def clean (self): if os.path.exists (self.maf): - with open (self.maf, "r") as list: + # Report any decoding error instead of erasing random files. + try: + with open (self.maf, encoding='utf_8') as list: for name in list: name = name.rstrip () verbose_remove (name, pkg = "minitoc") verbose_remove (self.maf, pkg = "minitoc") + except UnicodeDecodeError: + msg.error (_('Failed to decode file {aux} generated by {pkg} LaTeX package.') + .format (aux = self.maf, pkg = 'minitoc'), + pkg = 'minitoc') + rubber.util.abort_generic_error () diff -Nru rubber-1.4/src/latex_modules/ps2pdf.py rubber-1.5.1/src/latex_modules/ps2pdf.py --- rubber-1.4/src/latex_modules/ps2pdf.py 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/src/latex_modules/ps2pdf.py 2018-09-12 19:40:33.000000000 +0000 @@ -19,8 +19,6 @@ ps = env.final.products[0] pdf = ps[:-2] + 'pdf' cmd = ['ps2pdf'] - for opt in document.vars['paper'].split(): - cmd.append('-sPAPERSIZE=' + opt) cmd.extend([ps, pdf]) dep = Shell (env.depends, cmd) dep.add_product (pdf) diff -Nru rubber-1.4/src/tex.py rubber-1.5.1/src/tex.py --- rubber-1.4/src/tex.py 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/src/tex.py 2018-09-12 19:40:33.000000000 +0000 @@ -6,8 +6,8 @@ Classes and functions from this module can be used without Rubber. """ -import codecs, re -from StringIO import StringIO +import re +from io import StringIO # The catcodes @@ -152,7 +152,7 @@ """ Return the catcode of a character. """ - if self.catcodes.has_key(char): + if char in self.catcodes: return self.catcodes[char] else: return OTHER @@ -385,18 +385,14 @@ tokens. This advantage of this method is that is is much faster than reading tokens one by one. """ - def __init__ (self, input, coding=None): + def __init__ (self, input): """ - Initialise the parser with a file as input. If the argument 'coding' - is used, then the input is translated from this coding to Unicode - before parsing. If 'input' is None, then input can only be provided by + Initialise the parser with a file as input. + If 'input' is None, then input can only be provided by the 'put_token' and 'put_list' methods. """ super (Parser, self).__init__() - if coding is None: - self.input = input - else: - self.input = codecs.lookup(coding).streamreader(input) + self.input = input self.line = "" self.pos_line = 1 self.pos_char = 1 diff -Nru rubber-1.4/src/util.py rubber-1.5.1/src/util.py --- rubber-1.4/src/util.py 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/src/util.py 2018-09-12 19:40:33.000000000 +0000 @@ -10,7 +10,7 @@ import os, stat, time import errno import imp -import re, string +import re import shutil from string import whitespace import sys @@ -63,8 +63,8 @@ if text[0:13] == "LaTeX Error: ": text = text[13:] self(0, self.format_pos(info, text)) - if info.has_key("code") and info["code"] and not self.short: - if info.has_key("macro"): + if "code" in info and info["code"] and not self.short: + if "macro" in info: del info["macro"] self(0, self.format_pos(info, _("leading text: ") + info["code"])) @@ -99,26 +99,26 @@ the dictionary given as first argument. """ if len(self.pos) > 0: - if where is None or not where.has_key("file"): + if where is None or "file" not in where: where = self.pos[-1] elif where is None or where == {}: return text - if where.has_key("file") and where["file"] is not None: + if "file" in where and where["file"] is not None: pos = self.simplify(where["file"]) - if where.has_key("line") and where["line"]: + if "line" in where and where["line"]: pos = "%s:%d" % (pos, int(where["line"])) - if where.has_key("last"): + if "last" in where: if where["last"] != where["line"]: pos = "%s-%d" % (pos, int(where["last"])) pos = pos + ": " else: pos = "" - if where.has_key("macro"): + if "macro" in where: text = "%s (in macro %s)" % (text, where["macro"]) - if where.has_key("page"): + if "page" in where: text = "%s (page %d)" % (text, int(where["page"])) - if where.has_key("pkg"): + if "pkg" in where: text = "[%s] %s" % (where["pkg"], text) return pos + text @@ -150,7 +150,7 @@ """ try: m = hashlib.md5() - with open(fname) as file: + with open(fname, 'rb') as file: for line in file: m.update(line) return m.digest() @@ -189,7 +189,7 @@ val, str = match_brace(str) dict[d["key"]] = val else: - dict[d["key"]] = string.strip(d["val"]) + dict[d["key"]] = d["val"].strip() return dict def match_brace (str): @@ -223,7 +223,7 @@ """ pathsep = ";" if os.name == "nt" else ":" fileext = ".exe" if os.name == "nt" else "" - if checked_progs.has_key(prog): + if prog in checked_progs: return checked_progs[prog] for path in os.getenv("PATH").split(pathsep): file = os.path.join(path, prog) + fileext @@ -238,13 +238,11 @@ #-- Variable handling --{{{1 -import UserDict - -class Variables (UserDict.DictMixin): +class Variables: """ This class represent an environment containing variables. It can be accessed as a dictionary, except that every key must be declared using the - method 'new_key' before it can be accessed for reading or writing. + constructor. Environments are stacked, i.e. each environment can have a parent environment that contains other variables. The variables declared in an @@ -269,10 +267,10 @@ """ object = self while object is not None: - if object.dict.has_key(key): + if key in object.dict: return object.dict[key] object = object.parent - raise KeyError + raise KeyError (key) def __setitem__ (self, key, value): """ @@ -282,31 +280,33 @@ """ object = self while object is not None: - if object.dict.has_key(key): + if key in object.dict: object.dict[key] = value return object = object.parent - raise KeyError + raise KeyError (key) - def keys (self): + def to_dict (self): """ - Return the set of keys defined in this environment and its parents. + Construct a dict with the same keys and values, + that can be modified independently of self and its parents. """ - if self.parent is None: - return set(self.dict.keys()) - else: - return set(self.parent.keys()) | set(self.dict.keys()) + result = {} + object = self + while object is not None: + for key, value in object.dict.items(): + if key not in result: + result[key] = value + object = object.parent + return result - def new_key (self, key, value): - """ - Declare a new variable with an initial value in the current - environment. If the variable already exists in this environment, - raises 'KeyError'. If the variable exists in a parent environment, it - is hidden by the new variable. - """ - if self.dict.has_key(key): - raise KeyError - self.dict[key] = value + def __contains__ (self, key): + object = self + while object is not None: + if key in object.dict: + return True + object = object.parent + return False #-- Parsing commands --{{{1 @@ -379,7 +379,7 @@ # Append the variable or its name. if dict: - if dict.has_key(name): + if name in dict: arg = arg + str(dict[name]) # Send a warning for undefined variables ? else: @@ -409,7 +409,7 @@ def devnull (): global devnull_fp if not devnull_fp: - devnull_fp = open(os.devnull, 'rw') + devnull_fp = open(os.devnull, 'r+') return devnull_fp def explode_path (name = "PATH"): @@ -456,14 +456,14 @@ msg.log (_("error removing '{filename}': {strerror}").format ( \ filename=msg.simplify (path), strerror=e.strerror), **kwargs) return - msg.log (_("removing {}").format (msg.simplify (path)), **kwargs) + msg.log (_("removing {filename}").format (filename=msg.simplify (path)), **kwargs) def verbose_rmtree (tree): """ Remove a directory and notify the user of it. This is meant for --clean; failures are ignored. """ - msg.log (_("removing tree {}").format (msg.simplify (tree))) + msg.log (_("removing tree {dirname}").format (dirname=msg.simplify (tree))) # FIXME proper error reporting shutil.rmtree (tree, ignore_errors=True) diff -Nru rubber-1.4/tests/bibtex-no-line-no/doc.tex rubber-1.5.1/tests/bibtex-no-line-no/doc.tex --- rubber-1.4/tests/bibtex-no-line-no/doc.tex 1970-01-01 00:00:00.000000000 +0000 +++ rubber-1.5.1/tests/bibtex-no-line-no/doc.tex 2018-09-12 19:40:33.000000000 +0000 @@ -0,0 +1,5 @@ +\documentclass{minimal} +\bibliographystyle{plain} +\begin{document} +Lorem ipsum +\end{document} diff -Nru rubber-1.4/tests/bibtex-no-line-no/fragment rubber-1.5.1/tests/bibtex-no-line-no/fragment --- rubber-1.4/tests/bibtex-no-line-no/fragment 1970-01-01 00:00:00.000000000 +0000 +++ rubber-1.5.1/tests/bibtex-no-line-no/fragment 2018-09-12 19:40:33.000000000 +0000 @@ -0,0 +1,6 @@ +# rubber should detect a syntax error (code 2). +# previous version failed with a stacktrace (exit (1) by Python) +ret=0 +rubber doc 2>/dev/null || ret=$? +[ $ret = 2 ] +rubber --clean doc diff -Nru rubber-1.4/tests/fig2dev-path/doc.tex rubber-1.5.1/tests/fig2dev-path/doc.tex --- rubber-1.4/tests/fig2dev-path/doc.tex 1970-01-01 00:00:00.000000000 +0000 +++ rubber-1.5.1/tests/fig2dev-path/doc.tex 2018-09-12 19:40:33.000000000 +0000 @@ -0,0 +1,6 @@ +\documentclass{article} +\usepackage{graphics} +\begin{document} +Lorem +\includegraphics{figure.eps} +\end{document} diff -Nru rubber-1.4/tests/fig2dev-path/figure.fig rubber-1.5.1/tests/fig2dev-path/figure.fig --- rubber-1.4/tests/fig2dev-path/figure.fig 1970-01-01 00:00:00.000000000 +0000 +++ rubber-1.5.1/tests/fig2dev-path/figure.fig 2018-09-12 19:40:33.000000000 +0000 @@ -0,0 +1,10 @@ +#FIG 3.2 Produced by xfig version 3.2.5c +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 4950 3675 456 456 4950 3675 4875 4125 diff -Nru rubber-1.4/tests/fig2dev-path/fragment rubber-1.5.1/tests/fig2dev-path/fragment --- rubber-1.4/tests/fig2dev-path/fragment 1970-01-01 00:00:00.000000000 +0000 +++ rubber-1.5.1/tests/fig2dev-path/fragment 2018-09-12 19:40:33.000000000 +0000 @@ -0,0 +1,5 @@ +rubber doc.tex +status=0 +grep fig2dev-path figure.eps || status=$? +test $status = 1 # No match. +rubber doc.tex --clean diff -Nru rubber-1.4/tests/fig2dev-path-inplace/doc.tex rubber-1.5.1/tests/fig2dev-path-inplace/doc.tex --- rubber-1.4/tests/fig2dev-path-inplace/doc.tex 1970-01-01 00:00:00.000000000 +0000 +++ rubber-1.5.1/tests/fig2dev-path-inplace/doc.tex 2018-09-12 19:40:33.000000000 +0000 @@ -0,0 +1,6 @@ +\documentclass{article} +\usepackage{graphics} +\begin{document} +Lorem +\includegraphics{figure.eps} +\end{document} diff -Nru rubber-1.4/tests/fig2dev-path-inplace/figure.fig rubber-1.5.1/tests/fig2dev-path-inplace/figure.fig --- rubber-1.4/tests/fig2dev-path-inplace/figure.fig 1970-01-01 00:00:00.000000000 +0000 +++ rubber-1.5.1/tests/fig2dev-path-inplace/figure.fig 2018-09-12 19:40:33.000000000 +0000 @@ -0,0 +1,10 @@ +#FIG 3.2 Produced by xfig version 3.2.5c +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 4950 3675 456 456 4950 3675 4875 4125 diff -Nru rubber-1.4/tests/fig2dev-path-inplace/fragment rubber-1.5.1/tests/fig2dev-path-inplace/fragment --- rubber-1.4/tests/fig2dev-path-inplace/fragment 1970-01-01 00:00:00.000000000 +0000 +++ rubber-1.5.1/tests/fig2dev-path-inplace/fragment 2018-09-12 19:40:33.000000000 +0000 @@ -0,0 +1,7 @@ +mkdir inplace +mv doc.tex figure.fig inplace +rubber --inplace inplace/doc.tex +[ -r inplace/figure.eps ] +rubber --inplace --clean inplace/doc.tex +mv inplace/doc.tex inplace/figure.fig . +rmdir inplace diff -Nru rubber-1.4/tests/fig2dev-path-into/doc.tex rubber-1.5.1/tests/fig2dev-path-into/doc.tex --- rubber-1.4/tests/fig2dev-path-into/doc.tex 1970-01-01 00:00:00.000000000 +0000 +++ rubber-1.5.1/tests/fig2dev-path-into/doc.tex 2018-09-12 19:40:33.000000000 +0000 @@ -0,0 +1,6 @@ +\documentclass{article} +\usepackage{graphics} +\begin{document} +Lorem +\includegraphics{figure.eps} +\end{document} diff -Nru rubber-1.4/tests/fig2dev-path-into/figure.fig rubber-1.5.1/tests/fig2dev-path-into/figure.fig --- rubber-1.4/tests/fig2dev-path-into/figure.fig 1970-01-01 00:00:00.000000000 +0000 +++ rubber-1.5.1/tests/fig2dev-path-into/figure.fig 2018-09-12 19:40:33.000000000 +0000 @@ -0,0 +1,10 @@ +#FIG 3.2 Produced by xfig version 3.2.5c +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 4950 3675 456 456 4950 3675 4875 4125 diff -Nru rubber-1.4/tests/fig2dev-path-into/fragment rubber-1.5.1/tests/fig2dev-path-into/fragment --- rubber-1.4/tests/fig2dev-path-into/fragment 1970-01-01 00:00:00.000000000 +0000 +++ rubber-1.5.1/tests/fig2dev-path-into/fragment 2018-09-12 19:40:33.000000000 +0000 @@ -0,0 +1,7 @@ +mkdir blarz +rubber --into blarz doc.tex +status=0 +grep fig2dev-path figure.eps || status=$? +test $status = 1 # No match. +rubber --into blarz doc.tex --clean +rmdir blarz diff -Nru rubber-1.4/tests/hooks-input-file/bar.tex rubber-1.5.1/tests/hooks-input-file/bar.tex --- rubber-1.4/tests/hooks-input-file/bar.tex 1970-01-01 00:00:00.000000000 +0000 +++ rubber-1.5.1/tests/hooks-input-file/bar.tex 2018-09-12 19:40:33.000000000 +0000 @@ -0,0 +1 @@ +\usepackage{graphicx} diff -Nru rubber-1.4/tests/hooks-input-file/doc.tex rubber-1.5.1/tests/hooks-input-file/doc.tex --- rubber-1.4/tests/hooks-input-file/doc.tex 1970-01-01 00:00:00.000000000 +0000 +++ rubber-1.5.1/tests/hooks-input-file/doc.tex 2018-09-12 19:40:33.000000000 +0000 @@ -0,0 +1,9 @@ +\documentclass{article} +% When a document class or external file modifies the hook list, +% check that the main parser updates its regexp. +% Bug-Debian: https://bugs.debian.org/813855 +% Bug-Ubuntu: https://bugs.launchpad.net/rubber/+bug/1470988 +\input{bar} +\begin{document} +\includegraphics{foo} +\end{document} diff -Nru rubber-1.4/tests/hooks-input-file/foo.fig rubber-1.5.1/tests/hooks-input-file/foo.fig --- rubber-1.4/tests/hooks-input-file/foo.fig 1970-01-01 00:00:00.000000000 +0000 +++ rubber-1.5.1/tests/hooks-input-file/foo.fig 2018-09-12 19:40:33.000000000 +0000 @@ -0,0 +1,10 @@ +#FIG 3.2 Produced by xfig version 3.2.5c +Landscape +Center +Metric +A4 +100.00 +Single +-2 +1200 2 +1 4 0 1 0 7 50 -1 -1 0.000 1 0.0000 742 1417 456 456 495 1035 990 1800 diff -Nru rubber-1.4/tests/inputenc-latin1/doc.tex rubber-1.5.1/tests/inputenc-latin1/doc.tex --- rubber-1.4/tests/inputenc-latin1/doc.tex 1970-01-01 00:00:00.000000000 +0000 +++ rubber-1.5.1/tests/inputenc-latin1/doc.tex 2018-09-12 19:40:33.000000000 +0000 @@ -0,0 +1,7 @@ +\documentclass{article} +\usepackage[latin1]{inputenc} +\begin{document} +{\'e} é + +{\'E} É +\end{document} diff -Nru rubber-1.4/tests/inputenc-latin9/doc.tex rubber-1.5.1/tests/inputenc-latin9/doc.tex --- rubber-1.4/tests/inputenc-latin9/doc.tex 1970-01-01 00:00:00.000000000 +0000 +++ rubber-1.5.1/tests/inputenc-latin9/doc.tex 2018-09-12 19:40:33.000000000 +0000 @@ -0,0 +1,9 @@ +\documentclass{article} +\usepackage[latin9]{inputenc} +\begin{document} +{\oe} ½ + +{\OE} ¼ + +{\"Y} ¾ +\end{document} diff -Nru rubber-1.4/tests/inputenc-utf8/doc.tex rubber-1.5.1/tests/inputenc-utf8/doc.tex --- rubber-1.4/tests/inputenc-utf8/doc.tex 1970-01-01 00:00:00.000000000 +0000 +++ rubber-1.5.1/tests/inputenc-utf8/doc.tex 2018-09-12 19:40:33.000000000 +0000 @@ -0,0 +1,19 @@ +\documentclass{article} +\usepackage[utf8]{inputenc} +\begin{document} +{\'e} é + +{\'E} É + +{\oe} Å“ + +{\OE} Å’ + +{\"Y} Ÿ + +{\ss} ß + +{\textcopyright} © + +{\`A} À +\end{document} diff -Nru rubber-1.4/tests/landscape/arguments rubber-1.5.1/tests/landscape/arguments --- rubber-1.4/tests/landscape/arguments 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/tests/landscape/arguments 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ ---landscape diff -Nru rubber-1.4/tests/landscape/doc.tex rubber-1.5.1/tests/landscape/doc.tex --- rubber-1.4/tests/landscape/doc.tex 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/tests/landscape/doc.tex 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -\documentclass{article} -\begin{document} -Lorem -\end{document} diff -Nru rubber-1.4/tests/landscape/expected rubber-1.5.1/tests/landscape/expected --- rubber-1.4/tests/landscape/expected 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/tests/landscape/expected 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -doc.dvi diff -Nru rubber-1.4/tests/parser/fragment rubber-1.5.1/tests/parser/fragment --- rubber-1.4/tests/parser/fragment 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/tests/parser/fragment 2018-09-12 19:40:33.000000000 +0000 @@ -1 +1 @@ -python parser.py +PYTHONPATH=.. $python parser.py diff -Nru rubber-1.4/tests/parser/parser.py rubber-1.5.1/tests/parser/parser.py --- rubber-1.4/tests/parser/parser.py 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/tests/parser/parser.py 2018-09-12 19:40:33.000000000 +0000 @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim: noet:ts=4 from rubber.tex import * import unittest diff -Nru rubber-1.4/tests/run.sh rubber-1.5.1/tests/run.sh --- rubber-1.4/tests/run.sh 2015-12-11 21:59:25.000000000 +0000 +++ rubber-1.5.1/tests/run.sh 2018-09-12 19:40:33.000000000 +0000 @@ -5,7 +5,7 @@ SOURCE_DIR="$(cd ..; pwd)" tmpdir=tmp -python=python2 +python=python3 set -e # Stop at first failure.