avant tests

This commit is contained in:
Jean-Marie Place 2021-11-06 16:04:20 +01:00
parent 0d0ba5ae60
commit 3576847fb8
7 changed files with 138 additions and 103 deletions

View File

@ -202,7 +202,7 @@ def add_pe_stuff_to_zip(zipfile, ziproot):
add_local_file_to_zip(zipfile, ziproot, pathname, "avis/" + filename)
# Logos: (add to logos/ directory in zip)
logos_names = ["logo_header.jpg", "logo_footer.jpg"]
logos_names = ["header", "footer"]
for name in logos_names:
logo = find_logo(logoname=name, dept_id=g.scodoc_dept_id)
if logo is not None:

View File

@ -142,7 +142,6 @@ def process_field(field, cdict, style, suppress_empty_pars=False, format="pdf"):
return text
# --- PDF format:
# handle logos:
breakpoint()
# la protection contre des noms malveillants est assuré par l'utilisation de secure_filename dans la classe Logo
text = re.sub(
r"<(\s*)logo(.*?)src\s*=\s*(.*?)>", r"<\1logo\2\3>", text

View File

@ -48,44 +48,27 @@ from PIL import Image as PILImage
GLOBAL = "_SERVER" # category for server level logos
def find_logo(
logoname, dept_id=None, global_if_not_found=True, prefix=scu.LOGO_FILE_PREFIX
):
def find_logo(logoname, dept_id=None, strict=False, prefix=scu.LOGO_FILE_PREFIX):
"""
"Recherche un logo 'name' existant.
Deux strategies:
si global_if_not_found:
On recherche en local au dept d'abord puis si pas trouvé recherche globale
sinon
si strict:
reherche uniquement dans le département puis si non trouvé au niveau global
sinon
On recherche en local au dept d'abord puis si pas trouvé recherche globale
quelquesoit la stratégie, retourne None si pas trouvé
:param logoname: le nom recherche
:param dept_id: l'id du département dans lequel se fait la recherche (None si global)
:param global_if_not_found: stratégie de recherche
:param strict: stratégie de recherche (strict = False => dept ou global)
:param prefix: le prefix utilisé (parmi scu.LOGO_FILE_PREFIX / scu.BACKGROUND_FILE_PREFIX)
:return: un objet Logo désignant le fichier image trouvé (ou None)
"""
try:
logo = Logo(logoname, dept_id, prefix).read()
except ScoValueError:
logo = None
if logo is None and global_if_not_found:
try:
logo = Logo(logoname=logoname, dept_id=None), prefix.read()
except ScoValueError:
logo = None
logo = Logo(logoname, dept_id, prefix).select()
if logo is None and not strict:
logo = Logo(logoname=logoname, dept_id=None, prefix=prefix).select()
return logo
def get_logo_filename(name, dept_id=None):
breakpoint()
return find_logo(name, dept_id).read().filepath
def get_logo_url(name, dept_id):
return find_logo(name, dept_id).read().get_url()
def write_logo(stream, name, dept_id=None):
Logo(logoname=name, dept_id=dept_id).create(stream)
@ -117,7 +100,7 @@ def _list_dept_logos(dept_id=None, prefix=scu.LOGO_FILE_PREFIX):
result = filename_parser.match(entry.name)
if result:
logoname = result.group(1)
logos[logoname] = Logo(logoname=logoname, dept_id=dept_id).read()
logos[logoname] = Logo(logoname=logoname, dept_id=dept_id).select()
return logos if len(logos.keys()) > 0 else None
@ -156,7 +139,7 @@ class Logo:
self.filepath = None
self.filename = None
def set_format(self, fmt):
def _set_format(self, fmt):
self.suffix = fmt
self.filepath = self.basepath + "." + fmt
self.filename = self.logoname + "." + fmt
@ -171,7 +154,7 @@ class Logo:
img_type = guess_image_type(stream)
if img_type not in scu.LOGOS_IMAGES_ALLOWED_TYPES:
abort(400, "type d'image invalide")
self.set_format(img_type)
self._set_format(img_type)
self._ensure_directory_exists()
filename = self.basepath + "." + self.suffix
with open(filename, "wb") as f:
@ -184,7 +167,7 @@ class Logo:
except IOError:
pass
def read(self):
def select(self):
"""
Récupération des données pour un logo existant (sinon -> Exception)
il doit exister un et un seul fichier image parmi les types autorisés
@ -194,19 +177,27 @@ class Logo:
for suffix in scu.LOGOS_IMAGES_ALLOWED_TYPES:
path = Path(self.basepath + "." + suffix)
if path.exists():
self.set_format(suffix)
self._set_format(suffix)
with open(self.filepath, "rb") as f:
img = PILImage.open(f)
self.dimensions = img.size
return self
# if no file found, raise exception
raise ScoValueError(
"Logo %s not found for dept %s" % (self.logoname, self.scodoc_dept_id)
)
return None
def get_url(self):
return url_for(
"scodoc.logo_custom", scodoc_dept=self.scodoc_dept_id, name=self.logoname
"scodoc.get_logo",
scodoc_dept=self.scodoc_dept_id,
name=self.logoname,
global_if_not_found=False,
)
def get_url_small(self):
return url_for(
"scodoc.get_logo_small",
scodoc_dept=self.scodoc_dept_id,
name=self.logoname,
global_if_not_found=False,
)

View File

@ -61,11 +61,7 @@ from flask import g
import app.scodoc.sco_utils as scu
from app.scodoc.sco_logos import find_logo
from app.scodoc.sco_utils import (
CONFIG,
SCODOC_LOGOS_DIR,
LOGOS_IMAGES_ALLOWED_TYPES,
)
from app.scodoc.sco_utils import CONFIG
from app import log
from app.scodoc.sco_exceptions import ScoGenError, ScoValueError
import sco_version

View File

@ -202,43 +202,36 @@ class CourrierIndividuelTemplate(PageTemplate):
self.logo_footer = None
self.logo_header = None
# Search logos in dept specific dir, then in global scu.CONFIG dir
for image_dir in (
scu.SCODOC_LOGOS_DIR + "/logos_" + g.scodoc_dept,
scu.SCODOC_LOGOS_DIR, # global logos
):
for suffix in scu.LOGOS_IMAGES_ALLOWED_TYPES:
if template_name == "PVJuryTemplate":
background = find_logo(
logoname="pvjury_background",
dept_id=g.scodoc_dept_id,
prefix="",
global_if_not_found=True,
)
else:
background = find_logo(
logoname="letter_background",
dept_id=g.scodoc_dept_id,
prefix="",
global_if_not_found=True,
)
if not self.background_image_filename and background is not None:
self.background_image_filename = background.filepath
if template_name == "PVJuryTemplate":
background = find_logo(
logoname="pvjury_background",
dept_id=g.scodoc_dept_id,
prefix="",
)
else:
background = find_logo(
logoname="letter_background",
dept_id=g.scodoc_dept_id,
prefix="",
)
if not self.background_image_filename and background is not None:
self.background_image_filename = background.filepath
footer = find_logo(logoname="footer", dept_id=g.scodoc_dept_id)
if footer is not None:
self.logo_footer = Image(
footer.filepath,
height=LOGO_FOOTER_HEIGHT,
width=LOGO_FOOTER_WIDTH,
)
footer = find_logo(logoname="footer", dept_id=g.scodoc_dept_id)
if footer is not None:
self.logo_footer = Image(
footer.filepath,
height=LOGO_FOOTER_HEIGHT,
width=LOGO_FOOTER_WIDTH,
)
header = find_logo(logoname="header", dept_id=g.scodoc_dept_id)
if header is not None:
self.logo_header = Image(
header.filepath,
height=LOGO_HEADER_HEIGHT,
width=LOGO_HEADER_WIDTH,
)
header = find_logo(logoname="header", dept_id=g.scodoc_dept_id)
if header is not None:
self.logo_header = Image(
header.filepath,
height=LOGO_HEADER_HEIGHT,
width=LOGO_HEADER_WIDTH,
)
def beforeDrawPage(self, canvas, doc):
"""Draws a logo and an contribution message on each page."""

View File

@ -36,12 +36,12 @@
<div class="configuration_logo">
<h3>Logo en-tête</h3>
<p class="help">image placée en haut de certains documents documents PDF. Image actuelle:</p>
<div class="img-container"><img src="{{ url_for('scodoc.logo_header', scodoc_dept=scodoc_dept) }}"
<div class="img-container"><img src="{{ url_for('scodoc.get_logo_global', name="header") }}"
alt="pas de logo chargé" /></div>
{{ render_field(form.logo_header) }}
<h3>Logo pied de page</h3>
<p class="help">image placée en pied de page de certains documents documents PDF. Image actuelle:</p>
<div class="img-container"><img src="{{ url_for('scodoc.logo_footer', scodoc_dept=g.scodoc_dept) }}"
<div class="img-container"><img src="{{ url_for('scodoc.get_logo_global', name="footer") }}"
alt="pas de logo chargé" /></div>
{{ render_field(form.logo_footer) }}
</div>

View File

@ -30,6 +30,8 @@ Module main: page d'accueil, avec liste des départements
Emmanuel Viennet, 2021
"""
import io
from app.auth.models import User
import os
@ -38,7 +40,7 @@ from flask import abort, flash, url_for, redirect, render_template, send_file
from flask import request
from flask.app import Flask
import flask_login
from flask_login.utils import login_required
from flask_login.utils import login_required, current_user
from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileAllowed
from werkzeug.exceptions import BadRequest, NotFound
@ -61,10 +63,14 @@ from app.decorators import (
scodoc,
permission_required_compat_scodoc7,
)
from app.scodoc.imageresize import ImageScale
from app.scodoc.sco_exceptions import AccessDenied
from app.scodoc.sco_logos import Logo
from app.scodoc.sco_permissions import Permission
from app.views import scodoc_bp as bp
from PIL import Image as PILImage
@bp.route("/")
@bp.route("/ScoDoc")
@ -240,13 +246,9 @@ def configuration():
if form.validate_on_submit():
ScoDocSiteConfig.set_bonus_sport_func(form.bonus_sport_func_name.data)
if form.logo_header.data:
sco_logos.store_image(
form.logo_header.data, os.path.join(scu.SCODOC_LOGOS_DIR, "logo_header")
)
sco_logos.write_logo(stream=form.logo_header.data, name="header")
if form.logo_footer.data:
sco_logos.store_image(
form.logo_footer.data, os.path.join(scu.SCODOC_LOGOS_DIR, "logo_footer")
)
sco_logos.write_logo(stream=form.logo_footer.data, name="footer")
app.clear_scodoc_cache()
flash(f"Configuration enregistrée")
return redirect(url_for("scodoc.index"))
@ -259,29 +261,83 @@ def configuration():
)
def _return_logo(logo_type="header", scodoc_dept=""):
SMALL_SIZE = (300, 300)
def _return_logo(
name="header", dept_id="", small=False, global_if_not_found: bool = True
):
# stockée dans /opt/scodoc-data/config/logos donc servie manuellement ici
filename = sco_logos.get_logo_filename(logo_type, scodoc_dept)
if filename:
extension = os.path.splitext(filename)[1]
return send_file(filename, mimetype=f"image/{extension}")
# génération d'une url
# url = url_for(
# "scodoc.get_logo_small",
# name=name,
# dept_id=dept_id,
# global_if_not_found=global_if_not_found,
# )
logo = sco_logos.find_logo(name, dept_id, global_if_not_found)
if logo is not None:
suffix = logo.suffix
if small:
with PILImage.open(logo.filepath) as im:
im.thumbnail(SMALL_SIZE)
stream = io.BytesIO()
# on garde le même format (on pourrait plus simplement générer systématiquement du JPEG)
fmt = { # adapt suffix to be compliant with PIL save format
"PNG": "PNG",
"JPG": "JPEG",
"JPEG": "JPEG",
}[suffix.upper()]
im.save(stream, fmt)
stream.seek(0)
return send_file(stream, mimetype=f"image/{fmt}")
else:
return send_file(logo.filepath, mimetype=f"image/{suffix}")
else:
return ""
abort(404)
@bp.route("/ScoDoc/logo_header")
@bp.route("/ScoDoc/<scodoc_dept>/logo_header")
def logo_header(scodoc_dept=""):
"Image logo header"
# "/opt/scodoc-data/config/logos/logo_header")
return _return_logo(logo_type="header", scodoc_dept=scodoc_dept)
# small version (copy/paste from get_logo
@bp.route("/ScoDoc/logos/<name>/small", defaults={"dept_id": None})
@bp.route("/ScoDoc/<int:dept_id>/logos/<name>/small")
@admin_required
def get_logo_small(name: str, dept_id: int):
global_if_not_found = request.args.get("global_if_not_found", "True")
return _return_logo(
name,
dept_id=dept_id,
small=True,
global_if_not_found=global_if_not_found.upper() not in ["0", "FALSE"],
)
@bp.route("/ScoDoc/logo_footer")
@bp.route("/ScoDoc/<scodoc_dept>/logo_footer")
def logo_footer(scodoc_dept=""):
"Image logo footer"
return _return_logo(logo_type="footer", scodoc_dept=scodoc_dept)
@bp.route(
"/ScoDoc/logos/<name>", defaults={"dept_id": None}
) # if dept not specified, take global logo
@bp.route("/ScoDoc/<int:dept_id>/logos/<name>")
@admin_required
def get_logo(name: str, dept_id: int):
global_if_not_found = request.args.get("global_if_not_found", "True")
return _return_logo(
name,
dept_id=dept_id,
small=False,
global_if_not_found=global_if_not_found.upper() not in ["0", "FALSE"],
)
# @bp.route("/ScoDoc/logo_header")
# @bp.route("/ScoDoc/<scodoc_dept>/logo_header")
# def logo_header(scodoc_dept=""):
# "Image logo header"
# return _return_logo(name="header", scodoc_dept=scodoc_dept)
# @bp.route("/ScoDoc/logo_footer")
# @bp.route("/ScoDoc/<scodoc_dept>/logo_footer")
# def logo_footer(scodoc_dept=""):
# "Image logo footer"
# return _return_logo(name="footer", scodoc_dept=scodoc_dept)
# essais