diff --git a/app/but/bulletin_but_pdf.py b/app/but/bulletin_but_pdf.py
index 8a87f9005..29b9d6749 100644
--- a/app/but/bulletin_but_pdf.py
+++ b/app/but/bulletin_but_pdf.py
@@ -6,15 +6,13 @@
"""Génération bulletin BUT au format PDF standard
"""
+from reportlab.lib.colors import blue
+from reportlab.lib.units import cm, mm
from reportlab.platypus import Paragraph, Spacer
-from app.scodoc.sco_pdf import blue, cm, mm
-
+from app.scodoc.sco_bulletins_standard import BulletinGeneratorStandard
from app.scodoc import gen_tables
from app.scodoc.sco_codes_parcours import UE_SPORT
-from app.scodoc.sco_utils import fmt_note
-
-from app.scodoc.sco_bulletins_standard import BulletinGeneratorStandard
class BulletinGeneratorStandardBUT(BulletinGeneratorStandard):
diff --git a/app/scodoc/sco_bulletins_legacy.py b/app/scodoc/sco_bulletins_legacy.py
index 7d570d07d..314abb0db 100644
--- a/app/scodoc/sco_bulletins_legacy.py
+++ b/app/scodoc/sco_bulletins_legacy.py
@@ -34,17 +34,19 @@
CE FORMAT N'EVOLUERA PLUS ET EST CONSIDERE COMME OBSOLETE.
"""
+from reportlab.lib.colors import Color, blue
+from reportlab.lib.units import cm, mm
+from reportlab.platypus import Paragraph, Spacer, Table
-import app.scodoc.sco_utils as scu
-from app.scodoc.sco_permissions import Permission
-from app.scodoc import sco_formsemestre
-from app.scodoc import sco_pdf
-from app.scodoc.sco_pdf import Color, Paragraph, Spacer, Table
-from app.scodoc.sco_pdf import blue, cm, mm
-from app.scodoc.sco_pdf import SU
-from app.scodoc import sco_preferences
from app.scodoc import sco_bulletins_generator
from app.scodoc import sco_bulletins_pdf
+from app.scodoc import sco_formsemestre
+from app.scodoc.sco_permissions import Permission
+from app.scodoc import sco_pdf
+from app.scodoc.sco_pdf import SU
+from app.scodoc import sco_preferences
+import app.scodoc.sco_utils as scu
+
# Important: Le nom de la classe ne doit pas changer (bien le choisir), car il sera stocké en base de données (dans les préférences)
class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
diff --git a/app/scodoc/sco_bulletins_ucac.py b/app/scodoc/sco_bulletins_ucac.py
index 2114c60ad..fc49ffd9c 100644
--- a/app/scodoc/sco_bulletins_ucac.py
+++ b/app/scodoc/sco_bulletins_ucac.py
@@ -32,16 +32,12 @@ On redéfini la table centrale du bulletin de note et hérite de tout le reste d
E. Viennet, juillet 2011
"""
+from reportlab.lib.colors import Color
+from reportlab.lib.units import mm
-import app.scodoc.sco_utils as scu
-from app.scodoc.sco_pdf import blue, cm, mm
-from app.scodoc.sco_pdf import Color, Paragraph, Spacer, Table
-
-from app.scodoc import sco_preferences
-
-from app.scodoc import sco_bulletins_generator
from app.scodoc import sco_bulletins_standard
-from app.scodoc import gen_tables
+from app.scodoc import sco_preferences
+import app.scodoc.sco_utils as scu
class BulletinGeneratorUCAC(sco_bulletins_standard.BulletinGeneratorStandard):
diff --git a/app/scodoc/sco_pdf.py b/app/scodoc/sco_pdf.py
index 19a778144..2f468ccfc 100755
--- a/app/scodoc/sco_pdf.py
+++ b/app/scodoc/sco_pdf.py
@@ -44,22 +44,17 @@ import traceback
import unicodedata
import reportlab
-from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Frame, PageBreak
-from reportlab.platypus import Table, TableStyle, Image, KeepInFrame
+from reportlab.pdfgen import canvas
+from reportlab.platypus import Paragraph, Frame
from reportlab.platypus.flowables import Flowable
from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate
-from reportlab.lib.styles import getSampleStyleSheet
from reportlab.rl_config import defaultPageSize # pylint: disable=no-name-in-module
from reportlab.lib.units import inch, cm, mm
-from reportlab.lib.colors import pink, black, red, blue, green, magenta, red
-from reportlab.lib.colors import Color
-from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_CENTER, TA_JUSTIFY
from reportlab.lib import styles
-from reportlab.lib.pagesizes import letter, A4, landscape
+
from flask import g
-import app.scodoc.sco_utils as scu
from app.scodoc.sco_utils import CONFIG
from app import log
from app.scodoc.sco_exceptions import ScoGenError, ScoValueError
@@ -89,6 +84,12 @@ def SU(s):
return s
+def get_available_font_names() -> list[str]:
+ """List installed font names"""
+ can = canvas.Canvas(io.StringIO())
+ return can.getAvailableFonts()
+
+
def _splitPara(txt):
"split a string, returns a list of ... "
L = []
@@ -147,12 +148,26 @@ def makeParas(txt, style, suppress_empty=False):
except Exception as e:
log(traceback.format_exc())
log("Invalid pdf para format: %s" % txt)
- result = [
- Paragraph(
- SU('Erreur: format invalide'),
- style,
- )
- ]
+ try:
+ result = [
+ Paragraph(
+ SU('Erreur: format invalide'),
+ style,
+ )
+ ]
+ except ValueError as e: # probleme font ? essaye sans style
+ # recupere font en cause ?
+ m = re.match(r".*family/bold/italic for (.*)", e.args[0], re.DOTALL)
+ if m:
+ message = f"police non disponible: {m[1]}"
+ else:
+ message = "format invalide"
+ return [
+ Paragraph(
+ SU(f'Erreur: {message}'),
+ reportlab.lib.styles.ParagraphStyle({}),
+ )
+ ]
return result
@@ -166,7 +181,6 @@ def bold_paras(L, tag="b", close=None):
if hasattr(L, "keys"):
# L is a dict
for k in L:
- x = L[k]
if k[0] != "_":
L[k] = b + L[k] or "" + close
return L
@@ -256,7 +270,7 @@ class ScoDocPageTemplate(PageTemplate):
if logo is not None:
self.background_image_filename = logo.filepath
- def beforeDrawPage(self, canvas, doc):
+ def beforeDrawPage(self, canv, doc):
"""Draws (optional) background, logo and contribution message on each page.
day : Day of the month as a decimal number [01,31]
@@ -271,10 +285,10 @@ class ScoDocPageTemplate(PageTemplate):
"""
if not self.preferences:
return
- canvas.saveState()
+ canv.saveState()
# ---- Background image
if self.background_image_filename and self.with_page_background:
- canvas.drawImage(
+ canv.drawImage(
self.background_image_filename, 0, 0, doc.pagesize[0], doc.pagesize[1]
)
@@ -285,32 +299,32 @@ class ScoDocPageTemplate(PageTemplate):
(width, height),
image,
) = self.logo
- canvas.drawImage(image, inch, doc.pagesize[1] - inch, width, height)
+ canv.drawImage(image, inch, doc.pagesize[1] - inch, width, height)
# ---- Add some meta data and bookmarks
if self.pdfmeta_author:
- canvas.setAuthor(SU(self.pdfmeta_author))
+ canv.setAuthor(SU(self.pdfmeta_author))
if self.pdfmeta_title:
- canvas.setTitle(SU(self.pdfmeta_title))
+ canv.setTitle(SU(self.pdfmeta_title))
if self.pdfmeta_subject:
- canvas.setSubject(SU(self.pdfmeta_subject))
+ canv.setSubject(SU(self.pdfmeta_subject))
bookmark = self.pagesbookmarks.get(doc.page, None)
if bookmark:
- canvas.bookmarkPage(bookmark)
- canvas.addOutlineEntry(SU(bookmark), bookmark)
+ canv.bookmarkPage(bookmark)
+ canv.addOutlineEntry(SU(bookmark), bookmark)
- def draw_footer(self, canvas, content):
+ def draw_footer(self, canv, content):
"""Print the footer"""
- canvas.setFont(
+ canv.setFont(
self.preferences["SCOLAR_FONT"], self.preferences["SCOLAR_FONT_SIZE_FOOT"]
)
- canvas.drawString(
+ canv.drawString(
self.preferences["pdf_footer_x"] * mm,
self.preferences["pdf_footer_y"] * mm,
content,
)
- canvas.restoreState()
+ canv.restoreState()
def footer_string(self) -> str:
"""String contenu du pied de page"""
@@ -319,14 +333,14 @@ class ScoDocPageTemplate(PageTemplate):
d["server_url"] = self.server_name
return SU(self.footer_template % d)
- def afterDrawPage(self, canvas, doc):
+ def afterDrawPage(self, canv, doc):
if not self.preferences:
return
# ---- Footer
foot_content = None
if hasattr(doc, "current_footer"):
foot_content = doc.current_footer
- self.draw_footer(canvas, foot_content or self.footer_string())
+ self.draw_footer(canv, foot_content or self.footer_string())
# ---- Filigranne (texte en diagonal en haut a gauche de chaque page)
filigranne = None
if hasattr(doc, "filigranne"):
@@ -338,13 +352,13 @@ class ScoDocPageTemplate(PageTemplate):
else:
filigranne = self.filigranne.get(doc.page, None)
if filigranne:
- canvas.saveState()
- canvas.translate(9 * cm, 27.6 * cm)
- canvas.rotate(30)
- canvas.scale(4.5, 4.5)
- canvas.setFillColorRGB(1.0, 0.65, 0.65, alpha=0.6)
- canvas.drawRightString(0, 0, SU(filigranne))
- canvas.restoreState()
+ canv.saveState()
+ canv.translate(9 * cm, 27.6 * cm)
+ canv.rotate(30)
+ canv.scale(4.5, 4.5)
+ canv.setFillColorRGB(1.0, 0.65, 0.65, alpha=0.6)
+ canv.drawRightString(0, 0, SU(filigranne))
+ canv.restoreState()
doc.filigranne = None
def afterPage(self):
@@ -443,8 +457,8 @@ class PDFLock(object):
return # deja lock pour ce thread
try:
self.Q.put(1, True, self.timeout)
- except queue.Full:
- raise ScoGenError(msg="Traitement PDF occupé: ré-essayez")
+ except queue.Full as e:
+ raise ScoGenError(msg="Traitement PDF occupé: ré-essayez") from e
self.current_thread = threading.get_ident()
self.nref = 1
log("PDFLock: granted to %s" % self.current_thread)
@@ -471,7 +485,6 @@ class WatchLock:
def release(self):
t = threading.current_thread()
assert (self.native_id == t.native_id) and (self.ident == t.ident)
- pass
class FakeLock:
diff --git a/app/scodoc/sco_preferences.py b/app/scodoc/sco_preferences.py
index 5d019f7d2..7f1d8cc41 100644
--- a/app/scodoc/sco_preferences.py
+++ b/app/scodoc/sco_preferences.py
@@ -121,6 +121,7 @@ from app import log
from app.scodoc.sco_exceptions import ScoValueError, ScoException
from app.scodoc.TrivialFormulator import TrivialFormulator
import app.scodoc.notesdb as ndb
+from app.scodoc import sco_pdf
import app.scodoc.sco_utils as scu
@@ -194,6 +195,8 @@ def _get_pref_default_value_from_config(name, pref_spec):
return value
+_INSTALLED_FONTS = ", ".join(sco_pdf.get_available_font_names())
+
PREF_CATEGORIES = (
# sur page "Paramètres"
("general", {}),
@@ -777,7 +780,7 @@ class BasePreferences(object):
{
"initvalue": "Helvetica",
"title": "Police de caractère principale",
- "explanation": "pour les pdf (Helvetica est recommandée)",
+ "explanation": f"pour les pdf (Helvetica est recommandée, parmi {_INSTALLED_FONTS})",
"size": 25,
"category": "pdf",
},
@@ -1140,7 +1143,7 @@ class BasePreferences(object):
{
"initvalue": "Times-Roman",
"title": "Police de caractère pour les PV",
- "explanation": "pour les pdf",
+ "explanation": f"pour les pdf ({_INSTALLED_FONTS})",
"size": 25,
"category": "pvpdf",
},
@@ -1542,7 +1545,7 @@ class BasePreferences(object):
{
"initvalue": "Times-Roman",
"title": "Police titres bulletins",
- "explanation": "pour les pdf",
+ "explanation": f"pour les pdf ({_INSTALLED_FONTS})",
"size": 25,
"category": "bul",
},
diff --git a/app/scodoc/sco_pvpdf.py b/app/scodoc/sco_pvpdf.py
index 2e8cdaf66..3ac0096d6 100644
--- a/app/scodoc/sco_pvpdf.py
+++ b/app/scodoc/sco_pvpdf.py
@@ -28,15 +28,13 @@
"""Edition des PV de jury
"""
import io
-import os
import re
import reportlab
from reportlab.lib.units import cm, mm
-from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_CENTER, TA_JUSTIFY
-from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Frame, PageBreak
-from reportlab.platypus import Table, TableStyle, Image, KeepInFrame
-from reportlab.platypus.flowables import Flowable
+from reportlab.lib.enums import TA_RIGHT, TA_JUSTIFY
+from reportlab.platypus import Paragraph, Spacer, Frame, PageBreak
+from reportlab.platypus import Table, TableStyle, Image
from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate
from reportlab.lib.pagesizes import A4, landscape
from reportlab.lib import styles
@@ -53,7 +51,6 @@ from app.scodoc import sco_preferences
from app.scodoc import sco_etud
import sco_version
from app.scodoc.sco_logos import find_logo
-from app.scodoc.sco_pdf import PDFLOCK
from app.scodoc.sco_pdf import SU
LOGO_FOOTER_ASPECT = scu.CONFIG.LOGO_FOOTER_ASPECT # XXX A AUTOMATISER
@@ -317,14 +314,14 @@ class PVTemplate(CourrierIndividuelTemplate):
self.with_footer = self.preferences["PV_WITH_FOOTER"]
self.with_page_background = self.preferences["PV_WITH_BACKGROUND"]
- def afterDrawPage(self, canvas, doc):
+ def afterDrawPage(self, canv, doc):
"""Called after all flowables have been drawn on a page"""
pass
- def beforeDrawPage(self, canvas, doc):
+ def beforeDrawPage(self, canv, doc):
"""Called before any flowables are drawn on a page"""
# If the page number is even, force a page break
- CourrierIndividuelTemplate.beforeDrawPage(self, canvas, doc)
+ CourrierIndividuelTemplate.beforeDrawPage(self, canv, doc)
# Note: on cherche un moyen de generer un saut de page double
# (redémarrer sur page impaire, nouvelle feuille en recto/verso). Pas trouvé en Platypus.
#
diff --git a/app/scodoc/sco_trombino_tours.py b/app/scodoc/sco_trombino_tours.py
index 61d80de2e..56261eb9f 100644
--- a/app/scodoc/sco_trombino_tours.py
+++ b/app/scodoc/sco_trombino_tours.py
@@ -33,20 +33,23 @@
import io
from reportlab.lib import colors
-from reportlab.lib import pagesizes
+from reportlab.lib.colors import black
from reportlab.lib.pagesizes import A4, A3
+from reportlab.lib import styles
+from reportlab.lib.pagesizes import landscape
+from reportlab.lib.units import cm
+from reportlab.platypus import KeepInFrame, Paragraph, Table, TableStyle
+from reportlab.platypus.doctemplate import BaseDocTemplate
-import app.scodoc.sco_utils as scu
-from app import log
from app.scodoc import sco_abs
+from app.scodoc import sco_etud
+from app.scodoc.sco_exceptions import ScoPDFFormatError
from app.scodoc import sco_groups
from app.scodoc import sco_groups_view
from app.scodoc import sco_preferences
from app.scodoc import sco_trombino
-from app.scodoc import sco_etud
-from app.scodoc.sco_exceptions import ScoPDFFormatError
-from app.scodoc.sco_pdf import *
-
+import app.scodoc.sco_utils as scu
+from app.scodoc.sco_pdf import SU, ScoDocPageTemplate
# Paramétrage de l'aspect graphique:
PHOTOWIDTH = 2.8 * cm
@@ -55,7 +58,7 @@ N_PER_ROW = 5
def pdf_trombino_tours(
- group_ids=[], # liste des groupes à afficher
+ group_ids=(), # liste des groupes à afficher
formsemestre_id=None, # utilisé si pas de groupes selectionné
):
"""Generation du trombinoscope en fichier PDF"""
@@ -66,7 +69,6 @@ def pdf_trombino_tours(
DeptName = sco_preferences.get_preference("DeptName")
DeptFullName = sco_preferences.get_preference("DeptFullName")
- UnivName = sco_preferences.get_preference("UnivName")
InstituteName = sco_preferences.get_preference("InstituteName")
# Generate PDF page
StyleSheet = styles.getSampleStyleSheet()
@@ -143,9 +145,7 @@ def pdf_trombino_tours(
for group_id in groups_infos.group_ids:
if group_id != "None":
- members, group, group_tit, sem, nbdem = sco_groups.get_group_infos(
- group_id, "I"
- )
+ members, _, group_tit, sem, _ = sco_groups.get_group_infos(group_id, "I")
groups += " %s" % group_tit
L = []
currow = []
@@ -286,14 +286,14 @@ def pdf_trombino_tours(
def pdf_feuille_releve_absences(
- group_ids=[], # liste des groupes à afficher
+ group_ids=(), # liste des groupes à afficher
formsemestre_id=None, # utilisé si pas de groupes selectionné
):
"""Generation de la feuille d'absence en fichier PDF, avec photos"""
NB_CELL_AM = sco_preferences.get_preference("feuille_releve_abs_AM")
NB_CELL_PM = sco_preferences.get_preference("feuille_releve_abs_PM")
- COLWIDTH = 0.85 * cm
+ col_width = 0.85 * cm
if sco_preferences.get_preference("feuille_releve_abs_samedi"):
days = sco_abs.DAYNAMES[:6] # Lundi, ..., Samedi
else:
@@ -307,7 +307,6 @@ def pdf_feuille_releve_absences(
DeptName = sco_preferences.get_preference("DeptName")
DeptFullName = sco_preferences.get_preference("DeptFullName")
- UnivName = sco_preferences.get_preference("UnivName")
InstituteName = sco_preferences.get_preference("InstituteName")
# Generate PDF page
StyleSheet = styles.getSampleStyleSheet()
@@ -340,7 +339,7 @@ def pdf_feuille_releve_absences(
currow = [""] * (NB_CELL_AM + 1 + NB_CELL_PM + 1)
elem_day = Table(
[currow],
- colWidths=([COLWIDTH] * (NB_CELL_AM + 1 + NB_CELL_PM + 1)),
+ colWidths=([col_width] * (NB_CELL_AM + 1 + NB_CELL_PM + 1)),
style=TableStyle(
[
("GRID", (0, 0), (NB_CELL_AM - 1, 0), 0.25, black),
@@ -362,7 +361,7 @@ def pdf_feuille_releve_absences(
elem_week = Table(
W,
- colWidths=([COLWIDTH * (NB_CELL_AM + 1 + NB_CELL_PM + 1)] * nb_days),
+ colWidths=([col_width * (NB_CELL_AM + 1 + NB_CELL_PM + 1)] * nb_days),
style=TableStyle(
[
("LEFTPADDING", (0, 0), (-1, -1), 0),
@@ -378,7 +377,7 @@ def pdf_feuille_releve_absences(
elem_day_name = Table(
[currow],
- colWidths=([COLWIDTH * (NB_CELL_AM + 1 + NB_CELL_PM + 1)] * nb_days),
+ colWidths=([col_width * (NB_CELL_AM + 1 + NB_CELL_PM + 1)] * nb_days),
style=TableStyle(
[
("LEFTPADDING", (0, 0), (-1, -1), 0),
@@ -390,9 +389,7 @@ def pdf_feuille_releve_absences(
)
for group_id in groups_infos.group_ids:
- members, group, group_tit, sem, nbdem = sco_groups.get_group_infos(
- group_id, "I"
- )
+ members, _, group_tit, _, _ = sco_groups.get_group_infos(group_id, "I")
L = []
currow = [
@@ -429,7 +426,10 @@ def pdf_feuille_releve_absences(
T = Table(
L,
colWidths=(
- [5.0 * cm, (COLWIDTH * (NB_CELL_AM + 1 + NB_CELL_PM + 1) * nb_days)]
+ [
+ 5.0 * cm,
+ (col_width * (NB_CELL_AM + 1 + NB_CELL_PM + 1) * nb_days),
+ ]
),
style=TableStyle(
[