From a07571494c38056caf4ffcb60b301778744c6aa6 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Sun, 25 Jul 2021 23:31:59 +0300 Subject: [PATCH] Fix PDF (combining accents) and StringIO imports --- app/scodoc/gen_tables.py | 26 +++++++++++++++++++++-- app/scodoc/sco_etape_apogee_view.py | 5 +---- app/scodoc/sco_news.py | 5 +---- app/scodoc/sco_pdf.py | 32 +++++++++++++++-------------- app/scodoc/sco_photos.py | 5 +---- app/scodoc/sco_trombino.py | 5 +---- app/scodoc/sco_trombino_tours.py | 5 +---- app/views/scolar.py | 5 +---- scodoc.py | 4 +++- 9 files changed, 50 insertions(+), 42 deletions(-) diff --git a/app/scodoc/gen_tables.py b/app/scodoc/gen_tables.py index 675122478..b0bb6cc0e 100644 --- a/app/scodoc/gen_tables.py +++ b/app/scodoc/gen_tables.py @@ -78,6 +78,7 @@ class DEFAULT_TABLE_PREFERENCES(object): "SCOLAR_FONT": "Helvetica", # used for PDF, overriden by preferences argument "SCOLAR_FONT_SIZE": 10, "SCOLAR_FONT_SIZE_FOOT": 6, + "bul_pdf_with_background": False, } def __getitem__(self, k): @@ -699,8 +700,8 @@ class SeqGenTable(object): # ----- Exemple d'utilisation minimal. if __name__ == "__main__": - T = GenTable( - rows=[{"nom": "Toto", "age": 26}, {"nom": "Titi", "age": 21}], + T = gen_tables.GenTable( + rows=[{"nom": "Hélène", "age": 26}, {"nom": "Titi&çà§", "age": 21}], columns_ids=("nom", "age"), ) print("--- HTML:") @@ -709,3 +710,24 @@ if __name__ == "__main__": print(T.gen(format="xml")) print("\n--- JSON:") print(T.gen(format="json")) + # Test pdf: + import io + from reportlab.platypus import KeepInFrame + from app.scodoc import sco_preferences, sco_pdf + + preferences = sco_preferences.SemPreferences(None) + T.preferences = preferences + objects = T.gen(format="pdf") + objects = [KeepInFrame(0, 0, objects, mode="shrink")] + doc = io.BytesIO() + document = sco_pdf.BaseDocTemplate(doc) + document.addPageTemplates( + sco_pdf.ScolarsPageTemplate( + document, + ) + ) + document.build(objects) + data = doc.getvalue() + open("/tmp/gen_table.pdf", "wb").write(data) + p = T.make_page(None, format="pdf", REQUEST=None) + open("toto.pdf", "wb").write(p) diff --git a/app/scodoc/sco_etape_apogee_view.py b/app/scodoc/sco_etape_apogee_view.py index 290eceb54..06ed2fc06 100644 --- a/app/scodoc/sco_etape_apogee_view.py +++ b/app/scodoc/sco_etape_apogee_view.py @@ -28,10 +28,7 @@ """ScoDoc : formulaires gestion maquettes Apogee / export resultats """ -try: - from io import StringIO # for Python 3 -except ImportError: - from cStringIO import StringIO # for Python 2 +from io import StringIO from zipfile import ZipFile from flask import url_for, g diff --git a/app/scodoc/sco_news.py b/app/scodoc/sco_news.py index 0c7fe74d9..5ab608d02 100644 --- a/app/scodoc/sco_news.py +++ b/app/scodoc/sco_news.py @@ -31,10 +31,7 @@ import datetime import re import time -try: - from io import StringIO # for Python 3 -except ImportError: - from cStringIO import StringIO # for Python 2 +from io import StringIO from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.header import Header diff --git a/app/scodoc/sco_pdf.py b/app/scodoc/sco_pdf.py index 36b1ad188..2721f9192 100755 --- a/app/scodoc/sco_pdf.py +++ b/app/scodoc/sco_pdf.py @@ -31,17 +31,13 @@ Tout accès à ReportLab doit donc être précédé d'un PDFLOCK.acquire() et terminé par un PDFLOCK.release() """ +import io import time import re import os import unicodedata import traceback -try: - from io import StringIO # for Python 3 -except ImportError: - from cStringIO import StringIO # for Python 2 - import reportlab from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Frame, PageBreak from reportlab.platypus import Table, TableStyle, Image, KeepInFrame @@ -59,7 +55,6 @@ from reportlab.lib.pagesizes import letter, A4, landscape import app.scodoc.sco_utils as scu from app.scodoc.sco_utils import ( CONFIG, - SCO_ENCODING, SCODOC_LOGOS_DIR, LOGOS_IMAGES_ALLOWED_TYPES, ) @@ -78,13 +73,15 @@ DEFAULT_PDF_FOOTER_TEMPLATE = CONFIG.DEFAULT_PDF_FOOTER_TEMPLATE def SU(s): "convert s from string to string suitable for ReportLab" - # A priori inutile en Python 3, mais tester les "combining accents" - return s or "" - # Remplace caractères composés - # eg 'e\xcc\x81' COMBINING ACUTE ACCENT par '\xc3\xa9' LATIN SMALL LETTER E WITH ACUTE - # car les "combining accents" ne sont pas traités par ReportLab mais peuvent - # nous être envoyés par certains navigateurs ou imports - # return unicodedata.normalize("NFC", s) + if not s: + return "" + else: + # Remplace caractères composés + # eg 'e\xcc\x81' COMBINING ACUTE ACCENT par '\xc3\xa9' LATIN SMALL LETTER E WITH ACUTE + # car les "combining accents" ne sont pas traités par ReportLab mais peuvent + # nous être envoyés par certains navigateurs ou imports + # (on en a dans les bases de données) + return unicodedata.normalize("NFC", s) def _splitPara(txt): @@ -189,7 +186,10 @@ class ScolarsPageTemplate(PageTemplate): self.server_name = server_name self.filigranne = filigranne self.footer_template = footer_template - self.with_page_background = self.preferences["bul_pdf_with_background"] + if self.preferences: + self.with_page_background = self.preferences["bul_pdf_with_background"] + else: + self.with_page_background = False self.background_image_filename = None # Our doc is made of a single frame left, top, right, bottom = [float(x) for x in margins] @@ -229,6 +229,8 @@ class ScolarsPageTemplate(PageTemplate): server_url: URL du serveur ScoDoc """ + if not self.preferences: + return canvas.saveState() # ---- Background image if self.background_image_filename and self.with_page_background: @@ -308,7 +310,7 @@ def pdf_basic_page( adding a title if specified. """ StyleSheet = styles.getSampleStyleSheet() - report = StringIO.StringIO() # in-memory document, no disk file + report = io.BytesIO() # in-memory document, no disk file document = BaseDocTemplate(report) document.addPageTemplates( ScolarsPageTemplate( diff --git a/app/scodoc/sco_photos.py b/app/scodoc/sco_photos.py index 807486be3..7ccf159fb 100644 --- a/app/scodoc/sco_photos.py +++ b/app/scodoc/sco_photos.py @@ -51,10 +51,7 @@ import six.moves.urllib.request, six.moves.urllib.error, six.moves.urllib.parse import traceback from PIL import Image as PILImage -try: - from io import StringIO # for Python 3 -except ImportError: - from cStringIO import StringIO # for Python 2 +from io import StringIO import glob from flask import request diff --git a/app/scodoc/sco_trombino.py b/app/scodoc/sco_trombino.py index ec2e10d9e..e603270be 100644 --- a/app/scodoc/sco_trombino.py +++ b/app/scodoc/sco_trombino.py @@ -28,10 +28,7 @@ """Photos: trombinoscopes """ -try: - from io import StringIO # for Python 3 -except ImportError: - from cStringIO import StringIO # for Python 2 +from io import StringIO from zipfile import ZipFile, BadZipfile import reportlab from reportlab.lib.units import cm, mm diff --git a/app/scodoc/sco_trombino_tours.py b/app/scodoc/sco_trombino_tours.py index f6689e279..3e1073ae4 100644 --- a/app/scodoc/sco_trombino_tours.py +++ b/app/scodoc/sco_trombino_tours.py @@ -30,10 +30,7 @@ Modification Jérome Billoue,Vincent Grimaud, IUT de Tours, 2017 """ -try: - from io import StringIO # for Python 3 -except ImportError: - from cStringIO import StringIO # for Python 2 +from io import StringIO from reportlab.lib import colors from reportlab.lib import pagesizes diff --git a/app/views/scolar.py b/app/views/scolar.py index a5b1bb082..2cd85a762 100644 --- a/app/views/scolar.py +++ b/app/views/scolar.py @@ -35,10 +35,7 @@ import sys import time # StringIO => io.StringIO or io.BytesIO for text and data respectively. #py3 -try: - from io import StringIO # for Python 3 -except ImportError: - from cStringIO import StringIO # for Python 2 +from io import StringIO from zipfile import ZipFile import psycopg2 diff --git a/scodoc.py b/scodoc.py index fb2951ae4..cbe5f715a 100755 --- a/scodoc.py +++ b/scodoc.py @@ -24,13 +24,14 @@ import app.utils as utils from config import Config - app = create_app() cli.register(app) @app.shell_context_processor def make_shell_context(): + from app.scodoc import notesdb as ndb + return { "db": db, "User": User, @@ -38,6 +39,7 @@ def make_shell_context(): "UserRole": UserRole, "notes": notes, "scolar": scolar, + "ndb": ndb, "pp": pp, "flask": flask, "current_app": flask.current_app,