Package: matplotlib Version: 1.5.2~rc2-1 Severity: wishlist Tags: patch upstream User: reproducible-builds@lists.alioth.debian.org Usertags: toolchain X-Debbugs-Cc: reproducible-builds@lists.alioth.debian.org
Dear Maintainer, While working on the "reproducible builds" effort [1], we have noticed that some packages (like python-shapely) use matplotlib in their building process, leading to unreproducible builds (due to the timestamps inserted in PS/PDF files). To solve this kind of issues, it would be nice to make matplotlib support the SOURCE_DATE_EPOCH environment variable [2], so that the sources last modification date can be used for the timestamps in these PS and PDF files. See the attached patch for a proposed solution. Regards, Alexis Bienvenüe. [1] https://wiki.debian.org/ReproducibleBuilds [2] https://reproducible-builds.org/specs/source-date-epoch/
diff -Nru matplotlib-1.5.2~rc2/debian/changelog matplotlib-1.5.2~rc2/debian/changelog --- matplotlib-1.5.2~rc2/debian/changelog 2016-05-30 20:36:55.000000000 +0200 +++ matplotlib-1.5.2~rc2/debian/changelog 2016-06-14 19:42:45.000000000 +0200 @@ -1,3 +1,9 @@ +matplotlib (1.5.2~rc2-1.0~reproducible1) UNRELEASED; urgency=medium + + * Reproducible PS/PDF output, using SOURCE_DATE_EPOCH (when set) + + -- Alexis Bienvenüe <p...@passoire.fr> Tue, 14 Jun 2016 19:42:45 +0200 + matplotlib (1.5.2~rc2-1) unstable; urgency=medium [ Sandro Tosi ] diff -Nru matplotlib-1.5.2~rc2/debian/patches/honour-SOURCE_DATE_EPOCH.patch matplotlib-1.5.2~rc2/debian/patches/honour-SOURCE_DATE_EPOCH.patch --- matplotlib-1.5.2~rc2/debian/patches/honour-SOURCE_DATE_EPOCH.patch 1970-01-01 01:00:00.000000000 +0100 +++ matplotlib-1.5.2~rc2/debian/patches/honour-SOURCE_DATE_EPOCH.patch 2016-06-14 23:27:09.000000000 +0200 @@ -0,0 +1,99 @@ +Description: Honour SOURCE_DATE_EPOCH + Honour the SOURCE_DATE_EPOCH environment variable, to build timestamps + in PS/PDF outputs. This allows reproducible output. + See https://reproducible-builds.org/specs/source-date-epoch/ +Author: Alexis Bienvenüe <p...@passoire.fr> + +Index: matplotlib-1.5.2~rc2/lib/matplotlib/backends/backend_pdf.py +=================================================================== +--- matplotlib-1.5.2~rc2.orig/lib/matplotlib/backends/backend_pdf.py ++++ matplotlib-1.5.2~rc2/lib/matplotlib/backends/backend_pdf.py +@@ -23,7 +23,7 @@ import numpy as np + from matplotlib.externals.six import unichr + + +-from datetime import datetime ++from datetime import datetime, tzinfo, timedelta + from math import ceil, cos, floor, pi, sin + + import matplotlib +@@ -134,6 +134,20 @@ def _string_escape(match): + assert False + + ++# tzinfo class for UTC ++class UTCtimezone(tzinfo): ++ """UTC""" ++ ++ def utcoffset(self, dt): ++ return timedelta(0) ++ ++ def tzname(self, dt): ++ return "UTC" ++ ++ def dst(self, dt): ++ return timedelta(0) ++ ++ + def pdfRepr(obj): + """Map Python objects to PDF syntax.""" + +@@ -201,10 +215,14 @@ def pdfRepr(obj): + # A date. + elif isinstance(obj, datetime): + r = obj.strftime('D:%Y%m%d%H%M%S') +- if time.daylight: +- z = time.altzone ++ z = obj.utcoffset() ++ if z is not None: ++ z = z.seconds + else: +- z = time.timezone ++ if time.daylight: ++ z = time.altzone ++ else: ++ z = time.timezone + if z == 0: + r += 'Z' + elif z < 0: +@@ -457,10 +475,19 @@ class PdfFile(object): + self.writeObject(self.rootObject, root) + + revision = '' ++ # get source date from SOURCE_DATE_EPOCH, if set ++ # See https://reproducible-builds.org/specs/source-date-epoch/ ++ source_date_epoch = os.getenv("SOURCE_DATE_EPOCH") ++ if source_date_epoch: ++ source_date = datetime.utcfromtimestamp(int(source_date_epoch)) ++ source_date = source_date.replace(tzinfo=UTCtimezone()) ++ else: ++ source_date = datetime.today() ++ + self.infoDict = { + 'Creator': 'matplotlib %s, http://matplotlib.org' % __version__, + 'Producer': 'matplotlib pdf backend%s' % revision, +- 'CreationDate': datetime.today() ++ 'CreationDate': source_date + } + + self.fontNames = {} # maps filenames to internal font names +Index: matplotlib-1.5.2~rc2/lib/matplotlib/backends/backend_ps.py +=================================================================== +--- matplotlib-1.5.2~rc2.orig/lib/matplotlib/backends/backend_ps.py ++++ matplotlib-1.5.2~rc2/lib/matplotlib/backends/backend_ps.py +@@ -1126,7 +1126,14 @@ class FigureCanvasPS(FigureCanvasBase): + if title: print("%%Title: "+title, file=fh) + print(("%%Creator: matplotlib version " + +__version__+", http://matplotlib.org/"), file=fh) +- print("%%CreationDate: "+time.ctime(time.time()), file=fh) ++ # get source date from SOURCE_DATE_EPOCH, if set ++ # See https://reproducible-builds.org/specs/source-date-epoch/ ++ source_date_epoch = os.getenv("SOURCE_DATE_EPOCH") ++ if source_date_epoch: ++ source_date = time.asctime(time.gmtime(int(source_date_epoch))) ++ else: ++ source_date = time.ctime() ++ print("%%CreationDate: "+source_date, file=fh) + print("%%Orientation: " + orientation, file=fh) + if not isEPSF: print("%%DocumentPaperSizes: "+papertype, file=fh) + print("%%%%BoundingBox: %d %d %d %d" % bbox, file=fh) diff -Nru matplotlib-1.5.2~rc2/debian/patches/series matplotlib-1.5.2~rc2/debian/patches/series --- matplotlib-1.5.2~rc2/debian/patches/series 2016-05-30 20:36:55.000000000 +0200 +++ matplotlib-1.5.2~rc2/debian/patches/series 2016-06-14 19:40:12.000000000 +0200 @@ -5,3 +5,4 @@ 0005-bts800803-disable-the-GitHub-Fork-Me-ribbon.patch 0006-bts800803-dont-use-the-Raleway-font-from-the-Google-.patch 0007-bts800803-remote-the-Google-Analytics-tracking.patch +honour-SOURCE_DATE_EPOCH.patch
_______________________________________________ Reproducible-builds mailing list Reproducible-builds@lists.alioth.debian.org http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/reproducible-builds