commit python-relatorio for openSUSE:Factory
Hello community, here is the log from the commit of package python-relatorio for openSUSE:Factory checked in at 2019-07-31 14:36:54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-relatorio (Old) and /work/SRC/openSUSE:Factory/.python-relatorio.new.4126 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "python-relatorio" Wed Jul 31 14:36:54 2019 rev:8 rq:720017 version:0.9.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-relatorio/python-relatorio.changes 2019-07-08 15:11:04.543348006 +0200 +++ /work/SRC/openSUSE:Factory/.python-relatorio.new.4126/python-relatorio.changes 2019-07-31 14:36:57.817847138 +0200 @@ -1,0 +2,13 @@ +Wed Jul 31 09:24:57 UTC 2019 - Tomáš Chvátal <tchvatal@suse.com> + +- Run tests +- Run fdupes + +------------------------------------------------------------------- +Tue Jul 30 18:41:41 UTC 2019 - Axel Braun <axel.braun@gmx.de> + +- version 0.9.0 + * Support out parameter of render + * Write opendocument stream directly to the ZipFile + +------------------------------------------------------------------- Old: ---- relatorio-0.8.1.tar.gz New: ---- relatorio-0.9.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-relatorio.spec ++++++ --- /var/tmp/diff_new_pack.sP44MG/_old 2019-07-31 14:36:58.733846620 +0200 +++ /var/tmp/diff_new_pack.sP44MG/_new 2019-07-31 14:36:58.733846620 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-relatorio # -# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. # Copyright (c) 2016-2019 Dr. Axel Braun # # All modifications and additions to the file contributed by third parties @@ -13,32 +13,31 @@ # license that conforms to the Open Source Definition (Version 1.9) # published by the Open Source Initiative. -# Please submit bugfixes or comments via http://bugs.opensuse.org/ +# Please submit bugfixes or comments via https://bugs.opensuse.org/ # %{?!python_module:%define python_module() python-%{**} python3-%{**}} -%bcond_with tests %define mod_name relatorio Name: python-relatorio -Version: 0.8.1 +Version: 0.9.0 Release: 0 Summary: Python module to create reports from Python objects -License: GPL-3.0+ +License: GPL-3.0-or-later Group: Productivity/Office/Management -Url: https://pypi.python.org/pypi/relatorio +URL: https://pypi.python.org/pypi/relatorio Source: https://pypi.io/packages/source/r/%{mod_name}/%{mod_name}-%{version}.tar.gz BuildRequires: %{python_module Genshi} BuildRequires: %{python_module lxml} -# It requires different magic for tests https://github.com/ahupp/python-magic -#BuildRequires: %{python_module magic} +BuildRequires: %{python_module python-magic} BuildRequires: %{python_module setuptools} +BuildRequires: fdupes BuildRequires: python-rpm-macros Requires: python-Genshi Requires: python-PyYAML Requires: python-lxml -Requires: python-magic Requires: python-pycha +Requires: python-python-magic BuildArch: noarch %python_subpackages @@ -55,11 +54,10 @@ %install %python_install +%python_expand %fdupes %{buildroot}%{$python_sitelib} -%if %{with tests} %check %python_exec setup.py test -%endif %files %{python_files} %license LICENSE ++++++ relatorio-0.8.1.tar.gz -> relatorio-0.9.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/relatorio-0.8.1/.drone.yml new/relatorio-0.9.0/.drone.yml --- old/relatorio-0.8.1/.drone.yml 2018-08-18 13:27:26.000000000 +0200 +++ new/relatorio-0.9.0/.drone.yml 2019-07-29 15:52:57.000000000 +0200 @@ -17,8 +17,6 @@ include: - IMAGE: python:2.7 TOXENV: py27 - - IMAGE: python:3.4 - TOXENV: py34 - IMAGE: python:3.5 TOXENV: py35 - IMAGE: python:3.6 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/relatorio-0.8.1/.hgtags new/relatorio-0.9.0/.hgtags --- old/relatorio-0.8.1/.hgtags 2018-09-30 14:43:38.000000000 +0200 +++ new/relatorio-0.9.0/.hgtags 2019-07-29 16:01:09.000000000 +0200 @@ -25,3 +25,4 @@ 8ee1d7515d35918944151d3a44003063e1ab6a18 0.7.1 0775b131b51d40c2147b1ae104f760698a8d9f9e 0.8.0 a9a586fec08da03f86ec781472a981949d4c455a 0.8.1 +a0cf6c5a86e3eaf125a96f942f64114b326dba3b 0.9.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/relatorio-0.8.1/CHANGES new/relatorio-0.9.0/CHANGES --- old/relatorio-0.8.1/CHANGES 2018-09-30 14:42:26.000000000 +0200 +++ new/relatorio-0.9.0/CHANGES 2019-07-29 15:55:56.000000000 +0200 @@ -1,3 +1,7 @@ +0.9.0 - 20190729 +* Support out parameter of render +* Write opendocument stream directly to the ZipFile + 0.8.1 - 20180930 * Add support for Python 3.7 * Escape invalid XML characters diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/relatorio-0.8.1/PKG-INFO new/relatorio-0.9.0/PKG-INFO --- old/relatorio-0.8.1/PKG-INFO 2018-09-30 14:44:06.000000000 +0200 +++ new/relatorio-0.9.0/PKG-INFO 2019-07-29 16:02:35.000000000 +0200 @@ -1,12 +1,13 @@ -Metadata-Version: 1.1 +Metadata-Version: 2.1 Name: relatorio -Version: 0.8.1 +Version: 0.9.0 Summary: A templating library able to output odt and pdf files Home-page: http://relatorio.tryton.org/ -Author: Cedric Krier -Author-email: cedric.krier@b2ck.com +Author: Nicolas Evrard +Author-email: nicolas.evrard@b2ck.com +Maintainer: Cedric Krier +Maintainer-email: cedric.krier@b2ck.com License: GPL License -Description-Content-Type: UNKNOWN Description: Relatorio ========= @@ -31,3 +32,5 @@ Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Topic :: Text Processing +Provides-Extra: fodt +Provides-Extra: chart diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/relatorio-0.8.1/doc/conf.py new/relatorio-0.9.0/doc/conf.py --- old/relatorio-0.8.1/doc/conf.py 2018-08-18 13:27:26.000000000 +0200 +++ new/relatorio-0.9.0/doc/conf.py 2019-07-29 15:57:29.000000000 +0200 @@ -48,9 +48,9 @@ # built documents. # # The short X.Y version. -version = '0.8' +version = '0.9' # The full version, including alpha/beta/rc tags. -release = '0.8.1' +release = '0.9.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. Binary files old/relatorio-0.8.1/examples/big.odt and new/relatorio-0.9.0/examples/big.odt differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/relatorio-0.8.1/examples/demo_context.py new/relatorio-0.9.0/examples/demo_context.py --- old/relatorio-0.8.1/examples/demo_context.py 2018-08-18 13:27:26.000000000 +0200 +++ new/relatorio-0.9.0/examples/demo_context.py 2018-11-09 16:41:53.000000000 +0100 @@ -1,3 +1,4 @@ +from __future__ import print_function from os.path import abspath, join, dirname from relatorio import Report @@ -6,9 +7,9 @@ # PDF if __name__ == '__main__': - print "generating output_basic.pdf... ", + print("generating output_basic.pdf... ", end='') report = Report(abspath(join(dirname(__file__), 'basic.tex')), 'application/pdf') content = report(o=inv).render().getvalue() open(join(dirname(__file__), 'output_basic.pdf'), 'wb').write(content) - print "done" + print("done") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/relatorio-0.8.1/examples/demo_odf.py new/relatorio-0.9.0/examples/demo_odf.py --- old/relatorio-0.8.1/examples/demo_odf.py 2018-08-18 13:27:26.000000000 +0200 +++ new/relatorio-0.9.0/examples/demo_odf.py 2018-11-09 22:48:09.000000000 +0100 @@ -1,3 +1,4 @@ +from __future__ import print_function from os.path import abspath, join, dirname from relatorio import Report from relatorio.templates import opendocument @@ -12,21 +13,21 @@ if __name__ == '__main__': pwd = dirname(__file__) # ODT - print "generating output_basic.odt... ", + print("generating output_basic.odt... ", end='') report = Report(abspath(join(dirname(__file__), 'basic.odt')), ODT_MIME) content = report(o=inv).render().getvalue() open(join(pwd, 'output_basic.odt'), 'wb').write(content) - print "done" + print("done") # we could also use an opendocument template directly - print "generating output_template_basic.odt... ", + print("generating output_template_basic.odt... ", end='') template = opendocument.Template(source='', filepath=abspath(join(pwd, 'basic.odt'))) content = template.generate(o=inv).render().getvalue() open(join(pwd, 'output_template_basic.odt'), 'wb').write(content) - print "done" + print("done") - print "generating output_complicated.odt... ", + print("generating output_complicated.odt... ", end='') # Add a chart to the invoice inv['chart'] = ( Report(abspath(join(pwd, 'pie_chart')), 'image/png'), 'image/png') @@ -34,35 +35,41 @@ try: content = report(o=inv).render().getvalue() except NotImplementedError: - print "skipped" + print("skipped") else: open(join(pwd, 'output_complicated.odt'), 'wb').write(content) - print "done" + print("done") - print "generating output_columns.odt... ", + print("generating output_columns.odt... ", end='') report = Report(abspath(join(pwd, 'columns.odt')), ODT_MIME) lst = [[], ['i'], ['a', 'b'], [1, 2, 3], ['I', 'II', 'III', 'IV']] titles = ['first', 'second', 'third', 'fourth'] content = report(titles=titles, lst=lst).render().getvalue() open(join(pwd, 'output_columns.odt'), 'wb').write(content) - print "done" + print("done") # ODS - print "generating output_pivot.ods... ", + print("generating output_pivot.ods... ", end='') report = Report(abspath(join(pwd, 'pivot.ods')), ODS_MIME) content = report(o=inv).render().getvalue() open(join(pwd, 'output_pivot.ods'), 'wb').write(content) - print "done" + print("done") - print "generating output_sheets.ods... ", + print("generating output_sheets.ods... ", end='') report = Report(abspath(join(pwd, 'demo_sheets.ods')), ODS_MIME) content = report(lst=lst).render().getvalue() open(join(pwd, 'output_sheets.ods'), 'wb').write(content) - print "done" + print("done") # ODP - print "generating output_presentation.odp... ", + print("generating output_presentation.odp... ", end='') report = Report(abspath(join(pwd, 'presentation.odp')), ODP_MIME) content = report(o=inv).render().getvalue() open(join(pwd, 'output_presentation.odp'), 'wb').write(content) - print "done" + print("done") + + # Big document + print("generating output_big.odt... ", end='') + report = Report(abspath(join(pwd, 'big.odt')), ODT_MIME) + content = report().render(out=open(join(pwd, 'output_big.odt'), 'wb')) + print("done") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/relatorio-0.8.1/examples/demo_repository.py new/relatorio-0.9.0/examples/demo_repository.py --- old/relatorio-0.8.1/examples/demo_repository.py 2018-08-18 13:27:26.000000000 +0200 +++ new/relatorio-0.9.0/examples/demo_repository.py 2018-11-09 16:41:53.000000000 +0100 @@ -1,3 +1,4 @@ +from __future__ import print_function import relatorio from common import Invoice, inv from os.path import join, dirname @@ -25,8 +26,8 @@ ('pivot', '.ods'), ('presentation', '.odp')): filename = 'output_%s%s' % (report_name, ext) - print "generating '%s'..." % filename, + print("generating '%s'..." % filename, end='') report, mimetype, desc = repository.by_id(Invoice, report_name) data = report(o=inv).render().getvalue() open(join(dirname(__file__), filename), 'wb').write(data) - print "done" + print("done") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/relatorio-0.8.1/relatorio/__init__.py new/relatorio-0.9.0/relatorio/__init__.py --- old/relatorio-0.8.1/relatorio/__init__.py 2018-08-18 13:27:26.000000000 +0200 +++ new/relatorio-0.9.0/relatorio/__init__.py 2019-07-29 15:56:20.000000000 +0200 @@ -12,5 +12,5 @@ from .reporting import MIMETemplateLoader, ReportRepository, Report from . import templates -__version__ = '0.8.1' +__version__ = '0.9.0' __all__ = ['MIMETemplateLoader', 'ReportRepository', 'Report', 'templates'] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/relatorio-0.8.1/relatorio/templates/base.py new/relatorio-0.9.0/relatorio/templates/base.py --- old/relatorio-0.8.1/relatorio/templates/base.py 2018-08-18 13:27:26.000000000 +0200 +++ new/relatorio-0.9.0/relatorio/templates/base.py 2018-11-09 22:48:09.000000000 +0100 @@ -31,7 +31,8 @@ def render(self, method=None, encoding='utf-8', out=None, **kwargs): "calls the serializer to render the template" - return self.serializer(self.events) + return self.serializer( + self.events, method=method, encoding=encoding, out=out) def serialize(self, method='xml', **kwargs): "generates the bitstream corresponding to the template" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/relatorio-0.8.1/relatorio/templates/chart.py new/relatorio-0.9.0/relatorio/templates/chart.py --- old/relatorio-0.8.1/relatorio/templates/chart.py 2018-08-18 13:27:26.000000000 +0200 +++ new/relatorio-0.9.0/relatorio/templates/chart.py 2018-11-09 22:48:09.000000000 +0100 @@ -68,10 +68,13 @@ def __init__(self): self.text_serializer = genshi.output.TextSerializer() - def __call__(self, stream): + def __call__(self, stream, method=None, encoding='utf-8', out=None): if not PYCHA_TYPE: raise NotImplementedError - result = BytesIO() + if out is None: + result = BytesIO() + else: + result = out yml = StringIO(_encode(self.text_serializer(stream))) chart_yaml = yaml.load(yml.read()) chart_info = chart_yaml['chart'] @@ -95,6 +98,8 @@ elif chart_type == 'svg': surface.finish() - return result + if out is None: + return result + MIMETemplateLoader.add_factory('chart', Template, Template.id_function) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/relatorio-0.8.1/relatorio/templates/opendocument.py new/relatorio-0.9.0/relatorio/templates/opendocument.py --- old/relatorio-0.8.1/relatorio/templates/opendocument.py 2018-08-18 13:27:26.000000000 +0200 +++ new/relatorio-0.9.0/relatorio/templates/opendocument.py 2019-07-29 16:00:49.000000000 +0200 @@ -28,6 +28,7 @@ import base64 import mimetypes +import sys import time import urllib import zipfile @@ -114,9 +115,8 @@ class ImageHref: "A class used to add images in the odf zipfile" - def __init__(self, zfile, manifest, context): - self.zip = zfile - self.manifest = manifest + def __init__(self, serializer, context): + self.serializer = serializer self.context = context.copy() def __call__(self, expr): @@ -132,9 +132,7 @@ name = md5(file_content).hexdigest() path = 'Pictures/%s%s' % ( name, mimetypes.guess_extension(mimetype)) - if path not in self.zip.namelist(): - self.zip.writestr(path, file_content) - self.manifest.add_file_entry(path, mimetype) + self.serializer.add_file(path, file_content, mimetype) return {'{http://www.w3.org/1999/xlink}href': path} @@ -264,6 +262,7 @@ self.inner_docs = [] self.has_col_loop = False self._source = None + self._files = set() super(Template, self).__init__(source, filepath, filename, loader, encoding, lookup, allow_exec) @@ -312,6 +311,7 @@ parsed = [] for fpath, fparsed in content_files + styles_files: + self._files.add(fpath) parsed.append((genshi.core.PI, ('relatorio', fpath), None)) parsed += fparsed @@ -408,12 +408,11 @@ % (self.filepath, expr) elif expr != statement.text and statement.tag == text_a: warn_msg = "url and text do not match in %s: %s != %s" \ - % (self.filepath, expr, - statement.text.encode('utf-8')) + % (self.filepath, expr, statement.text) if warn_msg: if directive is not None and not is_opening: warn_msg += " corresponding to opening tag '%s'" \ - % opened_tags[-1].text + % opened_tags[-1][0].text warnings.warn(warn_msg) if directive in GENSHI_CLOSING_DIRECTIVE: @@ -822,10 +821,8 @@ def generate(self, *args, **kwargs): "creates the RelatorioStream." - serializer = OOSerializer(self._source) - kwargs['__relatorio_make_href'] = ImageHref(serializer.outzip, - serializer.manifest, - kwargs) + serializer = OOSerializer(self._source, self._files) + kwargs['__relatorio_make_href'] = ImageHref(serializer, kwargs) kwargs['__relatorio_make_dimension'] = ImageDimension(self.namespaces) kwargs['__relatorio_guess_type'] = self._guess_type kwargs['__relatorio_escape_invalid_chars'] = escape_xml_invalid_chars @@ -848,6 +845,7 @@ col_filter = Transformer('//repeat[namespace-uri()="%s"]' % RELATORIO_URI) col_filter = col_filter.apply(transformation) + # Must consume the stream to fill counter stream = Stream(list(stream), self.serializer) | col_filter return RelatorioStream(stream, serializer) @@ -1041,40 +1039,115 @@ return val -class OOSerializer: +class _AbstractZipWriteSplitStream(object): + def __init__(self, zipfile, chunksize=64): + self.zipfile = zipfile + self.chunksize = chunksize - def __init__(self, source): - self.inzip = get_zip_file(source) - self.manifest = Manifest(self.inzip.read(MANIFEST)) - self.meta = Meta(self.inzip.read(META)) - self.new_oo = BytesIO() - self.outzip = zipfile.ZipFile( - self.new_oo, mode='w', compression=zipfile.ZIP_DEFLATED) - self.xml_serializer = genshi.output.XMLSerializer() + def open(self, zinfo): + raise NotImplementedError + + def close(self): + raise NotImplementedError def __call__(self, stream): - files = {} for kind, data, pos in stream: if kind == genshi.core.PI and data[0] == 'relatorio': - stream_for = data[1] + self.open(data[1]) continue - files.setdefault(stream_for, []).append((kind, data, pos)) + yield kind, data, pos + self.close() + + def write(self, data): + raise NotImplementedError + + +if sys.version_info >= (3, 6): + class _ZipWriteSplitStream(_AbstractZipWriteSplitStream): + def __init__(self, *args, **kwargs): + super(_ZipWriteSplitStream, self).__init__(*args, **kwargs) + self._fp = None + self._buffer = [] + self._zinfo = None + + def open(self, zinfo): + if self._fp: + self.close() + self._zinfo = zinfo + self._fp = None + + def close(self): + self.flush() + self._fp.close() + self._zinfo = None + self._fp = None + + def write(self, data): + self._buffer.append(data) + if len(self._buffer) > self.chunksize: + self.flush() + + def flush(self): + if not self._fp: + self._fp = self.zipfile.open(self._zinfo, mode='w') + self._fp.write(b''.join(self._buffer)) + self._buffer.clear() +else: + class _ZipWriteSplitStream(_AbstractZipWriteSplitStream): + def __init__(self, *args, **kwargs): + super(_ZipWriteSplitStream, self).__init__(*args, **kwargs) + self._fp = None + self._zinfo = None + + def open(self, zinfo): + if self._fp: + self.close() + self._zinfo = zinfo + self._fp = BytesIO() + + def close(self): + self._fp.seek(0) + self.zipfile.writestr(self._zinfo, self._fp.read()) + self._zinfo = None + self._fp = None + + def write(self, data): + self._fp.write(data) + +class OOSerializer: + + def __init__(self, source, files, chunksize=64): + self.inzip = get_zip_file(source) + self.manifest = Manifest(self.inzip.read(MANIFEST)) + self.meta = Meta(self.inzip.read(META)) + self.xml_serializer = genshi.output.XMLSerializer() + self._files = files + self.chunksize = chunksize + self.outzip = None + self._deferred = None + + def __call__(self, stream, method=None, encoding='utf-8', out=None): + if out is None: + result = BytesIO() + else: + result = out + self.outzip = zipfile.ZipFile( + result, mode='w', compression=zipfile.ZIP_DEFLATED) + self._deferred = [] + files = {} now = time.localtime()[:6] manifest_info = None for f_info in self.inzip.infolist(): if f_info.filename.startswith('ObjectReplacements'): continue - elif f_info.filename in files: - stream = files[f_info.filename] + elif f_info.filename in self._files: # create a new file descriptor, copying some attributes from # the original file new_info = zipfile.ZipInfo(f_info.filename, now) for attr in ('compress_type', 'flag_bits', 'create_system'): setattr(new_info, attr, getattr(f_info, attr)) - serialized_stream = output_encode(self.xml_serializer(stream), - encoding='utf-8') - self.outzip.writestr(new_info, serialized_stream) + files[f_info.filename] = new_info elif f_info.filename == MANIFEST: manifest_info = f_info elif f_info.filename == META: @@ -1083,12 +1156,29 @@ self.manifest.remove_file_entry(f_info.filename) else: self.outzip.writestr(f_info, self.inzip.read(f_info.filename)) + + writer = _ZipWriteSplitStream(self.outzip, self.chunksize) + output_encode( + self.xml_serializer(writer(stream)), encoding=encoding, out=writer) + + for args in self._deferred: + self.add_file(*args) self.manifest.remove_file_entry(THUMBNAILS + '/') if manifest_info: self.outzip.writestr(manifest_info, str(self.manifest)) self.inzip.close() self.outzip.close() - return self.new_oo + if out is None: + return result + + def add_file(self, path, content, mimetype): + if self.outzip and path not in self.outzip.namelist(): + try: + self.outzip.writestr(path, content) + self.manifest.add_file_entry(path, mimetype) + except ValueError: + self._deferred.append((path, content, mimetype)) + MIMETemplateLoader.add_factory('oo.org', Template) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/relatorio-0.8.1/relatorio/templates/pdf.py new/relatorio-0.9.0/relatorio/templates/pdf.py --- old/relatorio-0.8.1/relatorio/templates/pdf.py 2018-08-18 13:27:26.000000000 +0200 +++ new/relatorio-0.9.0/relatorio/templates/pdf.py 2018-11-09 22:48:09.000000000 +0100 @@ -48,23 +48,30 @@ class PDFSerializer: def __init__(self): - self.working_dir = tempfile.mkdtemp(prefix='relatorio') - self.tex_file = os.path.join(self.working_dir, 'report.tex') - self.pdf_file = os.path.join(self.working_dir, 'report.pdf') self.text_serializer = genshi.output.TextSerializer() - def __call__(self, stream): - tex_file = open(self.tex_file, 'w') - tex_file.write(_encode(self.text_serializer(stream))) - tex_file.close() + def __call__(self, stream, method=None, encoding='utf-8', out=None): + if out is None: + result = BytesIO() + else: + result = out + working_dir = tempfile.mkdtemp(prefix='relatorio') + tex_file = os.path.join(working_dir, 'report.tex') + pdf_file = os.path.join(working_dir, 'report.pdf') + + with open(tex_file, 'w') as fp: + fp.write(_encode(self.text_serializer(stream))) subprocess.check_call([TEXEXEC, '--purge', 'report.tex'], - cwd=self.working_dir) + cwd=working_dir) + + with open(pdf_file, 'r') as fp: + result.write(fp.read()) + + shutil.rmtree(working_dir, ignore_errors=True) - pdf = BytesIO() - pdf.write(open(self.pdf_file, 'r').read()) + if out is None: + return result - shutil.rmtree(self.working_dir, ignore_errors=True) - return pdf MIMETemplateLoader.add_factory('pdf', Template) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/relatorio-0.8.1/relatorio/tests/test_odt.py new/relatorio-0.9.0/relatorio/tests/test_odt.py --- old/relatorio-0.8.1/relatorio/tests/test_odt.py 2018-08-18 13:27:26.000000000 +0200 +++ new/relatorio-0.9.0/relatorio/tests/test_odt.py 2019-07-29 16:00:49.000000000 +0200 @@ -230,6 +230,49 @@ self.assertTrue(last_row_node.get("value") .startswith('__relatorio_store_col_count')) + @unittest.skipIf( + not getattr(unittest.TestCase, 'assertWarnsRegex', None), + "assertWarns not supported") + def test_statement_no_text_warning(self): + "Test warning for missing statement text" + xml = b'''<xml xmlns:text="urn:text" xmlns:xlink="urn:xlink"> + <text:a xlink:href="relatorio://content:foo"></text:a> + </xml>''' + + with self.assertWarnsRegex( + UserWarning, r"No statement text in '.*' for 'content:foo'"): + self.oot.insert_directives(xml) + + @unittest.skipIf( + not getattr(unittest.TestCase, 'assertWarnsRegex', None), + "assertWarns not supported") + def test_statement_missmatch_text_warning(self): + "Test warning for missing statement text" + xml = b'''<xml xmlns:text="urn:text" xmlns:xlink="urn:xlink"> + <text:a xlink:href="relatorio://content:foo">content:bar</text:a> + </xml>''' + + with self.assertWarnsRegex( + UserWarning, + r"url and text do not match in .*: " + "content:foo != content:bar"): + self.oot.insert_directives(xml) + + @unittest.skipIf( + not getattr(unittest.TestCase, 'assertWarnsRegex', None), + "assertWarns not supported") + def test_statement_text_warning_closing(self): + "Test warning for statement text in closing" + xml = b'''<xml xmlns:text="urn:text" xmlns:xlink="urn:xlink"> + <text:a xlink:href="relatorio://with foo='test'">with foo='test'</text:a> + <text:a xlink:href="relatorio:///with"></text:a> + </xml>''' + + with self.assertWarnsRegex( + UserWarning, + r".* corresponding to opening tag 'with foo='test'"): + self.oot.insert_directives(xml) + def test_text_outside_p(self): "Testing that the tail text of a directive node is handled properly" xml = b'''<xml xmlns:text="urn:text" xmlns:xlink="urn:xlink"> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/relatorio-0.8.1/relatorio.egg-info/PKG-INFO new/relatorio-0.9.0/relatorio.egg-info/PKG-INFO --- old/relatorio-0.8.1/relatorio.egg-info/PKG-INFO 2018-09-30 14:44:06.000000000 +0200 +++ new/relatorio-0.9.0/relatorio.egg-info/PKG-INFO 2019-07-29 16:02:34.000000000 +0200 @@ -1,12 +1,13 @@ -Metadata-Version: 1.1 +Metadata-Version: 2.1 Name: relatorio -Version: 0.8.1 +Version: 0.9.0 Summary: A templating library able to output odt and pdf files Home-page: http://relatorio.tryton.org/ -Author: Cedric Krier -Author-email: cedric.krier@b2ck.com +Author: Nicolas Evrard +Author-email: nicolas.evrard@b2ck.com +Maintainer: Cedric Krier +Maintainer-email: cedric.krier@b2ck.com License: GPL License -Description-Content-Type: UNKNOWN Description: Relatorio ========= @@ -31,3 +32,5 @@ Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Topic :: Text Processing +Provides-Extra: fodt +Provides-Extra: chart diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/relatorio-0.8.1/relatorio.egg-info/SOURCES.txt new/relatorio-0.9.0/relatorio.egg-info/SOURCES.txt --- old/relatorio-0.8.1/relatorio.egg-info/SOURCES.txt 2018-09-30 14:44:06.000000000 +0200 +++ new/relatorio-0.9.0/relatorio.egg-info/SOURCES.txt 2019-07-29 16:02:35.000000000 +0200 @@ -28,6 +28,7 @@ doc/relatorio_basic.png examples/basic.odt examples/basic.tex +examples/big.odt examples/bouteille.png examples/columns.odt examples/common.py
participants (1)
-
root