forked from ScoDoc/ScoDoc
Ajout image de fond sur PV jury et lettres individuelles de décision.
This commit is contained in:
parent
439571862b
commit
6160d48e9e
@ -69,7 +69,7 @@ def SU(s):
|
|||||||
# Remplace caractères composés
|
# Remplace caractères composés
|
||||||
# eg 'e\xcc\x81' COMBINING ACUTE ACCENT par '\xc3\xa9' LATIN SMALL LETTER E WITH ACUTE
|
# 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
|
# car les "combining accents" ne sont pas traités par ReportLab mais peuvent
|
||||||
# nous être envoyés par certains navigaters ou imports
|
# nous être envoyés par certains navigateurs ou imports
|
||||||
u = unicodedata.normalize("NFC", unicode(s, SCO_ENCODING, "replace"))
|
u = unicodedata.normalize("NFC", unicode(s, SCO_ENCODING, "replace"))
|
||||||
return u.encode("utf8")
|
return u.encode("utf8")
|
||||||
|
|
||||||
@ -200,9 +200,10 @@ class ScolarsPageTemplate(PageTemplate):
|
|||||||
minute: Minute as a decimal number [00,59].
|
minute: Minute as a decimal number [00,59].
|
||||||
|
|
||||||
server_url: URL du serveur ScoDoc
|
server_url: URL du serveur ScoDoc
|
||||||
|
|
||||||
"""
|
"""
|
||||||
canvas.saveState()
|
canvas.saveState()
|
||||||
|
# ---- Logo: a small image, positionned at top left of the page
|
||||||
if self.logo is not None:
|
if self.logo is not None:
|
||||||
# draws the logo if it exists
|
# draws the logo if it exists
|
||||||
((width, height), image) = self.logo
|
((width, height), image) = self.logo
|
||||||
|
@ -786,6 +786,77 @@ vu la délibération de la commission %(Type)s en date du %(Date)s présidée pa
|
|||||||
"category": "pvpdf",
|
"category": "pvpdf",
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"PV_WITH_BACKGROUND",
|
||||||
|
{
|
||||||
|
"initvalue": 0,
|
||||||
|
"title": "Mettre l'image de fond sur les PV de jury (paysage)",
|
||||||
|
"input_type": "boolcheckbox",
|
||||||
|
"labels": ["non", "oui"],
|
||||||
|
"category": "pvpdf",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"PV_WITH_HEADER",
|
||||||
|
{
|
||||||
|
"initvalue": 1, # legacy
|
||||||
|
"title": "Ajouter l'en-tête sur les PV (paysage)",
|
||||||
|
"input_type": "boolcheckbox",
|
||||||
|
"labels": ["non", "oui"],
|
||||||
|
"category": "pvpdf",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"PV_WITH_FOOTER",
|
||||||
|
{
|
||||||
|
"initvalue": 1, # legacy
|
||||||
|
"title": "Ajouter le pied de page sur les PV (paysage)",
|
||||||
|
"input_type": "boolcheckbox",
|
||||||
|
"labels": ["non", "oui"],
|
||||||
|
"category": "pvpdf",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
# marges PV paysages (en millimètres)
|
||||||
|
(
|
||||||
|
"pv_left_margin",
|
||||||
|
{
|
||||||
|
"initvalue": 0,
|
||||||
|
"size": 10,
|
||||||
|
"title": "Marge gauche PV en mm",
|
||||||
|
"type": "float",
|
||||||
|
"category": "pvpdf",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"pv_top_margin",
|
||||||
|
{
|
||||||
|
"initvalue": 23,
|
||||||
|
"size": 10,
|
||||||
|
"title": "Marge haute PV",
|
||||||
|
"type": "float",
|
||||||
|
"category": "pvpdf",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"pv_right_margin",
|
||||||
|
{
|
||||||
|
"initvalue": 0,
|
||||||
|
"size": 10,
|
||||||
|
"title": "Marge droite PV",
|
||||||
|
"type": "float",
|
||||||
|
"category": "pvpdf",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"pv_bottom_margin",
|
||||||
|
{
|
||||||
|
"initvalue": 5,
|
||||||
|
"size": 10,
|
||||||
|
"title": "Marge basse PV",
|
||||||
|
"type": "float",
|
||||||
|
"category": "pvpdf",
|
||||||
|
},
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"PV_LETTER_DIPLOMA_SIGNATURE",
|
"PV_LETTER_DIPLOMA_SIGNATURE",
|
||||||
{
|
{
|
||||||
@ -872,11 +943,21 @@ s'est réuni le %(date_jury)s.
|
|||||||
"category": "pvpdf",
|
"category": "pvpdf",
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"PV_LETTER_WITH_BACKGROUND",
|
||||||
|
{
|
||||||
|
"initvalue": 0,
|
||||||
|
"title": "Mettre l'image de fond sur les lettres individuelles de décision",
|
||||||
|
"input_type": "boolcheckbox",
|
||||||
|
"labels": ["non", "oui"],
|
||||||
|
"category": "pvpdf",
|
||||||
|
},
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"PV_LETTER_WITH_HEADER",
|
"PV_LETTER_WITH_HEADER",
|
||||||
{
|
{
|
||||||
"initvalue": 0,
|
"initvalue": 0,
|
||||||
"title": "Imprimer le logo en tête des lettres individuelles de décision",
|
"title": "Ajouter l'en-tête sur les lettres individuelles de décision",
|
||||||
"input_type": "boolcheckbox",
|
"input_type": "boolcheckbox",
|
||||||
"labels": ["non", "oui"],
|
"labels": ["non", "oui"],
|
||||||
"category": "pvpdf",
|
"category": "pvpdf",
|
||||||
@ -886,7 +967,7 @@ s'est réuni le %(date_jury)s.
|
|||||||
"PV_LETTER_WITH_FOOTER",
|
"PV_LETTER_WITH_FOOTER",
|
||||||
{
|
{
|
||||||
"initvalue": 0,
|
"initvalue": 0,
|
||||||
"title": "Imprimer le pied de page sur les lettres individuelles de décision",
|
"title": "Ajouter le pied de page sur les lettres individuelles de décision",
|
||||||
"input_type": "boolcheckbox",
|
"input_type": "boolcheckbox",
|
||||||
"labels": ["non", "oui"],
|
"labels": ["non", "oui"],
|
||||||
"category": "pvpdf",
|
"category": "pvpdf",
|
||||||
@ -1633,8 +1714,7 @@ class sco_base_preferences:
|
|||||||
self.load()
|
self.load()
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
"""Load all preferences from db
|
"""Load all preferences from db"""
|
||||||
"""
|
|
||||||
log("loading preferences")
|
log("loading preferences")
|
||||||
try:
|
try:
|
||||||
GSL.acquire()
|
GSL.acquire()
|
||||||
@ -2063,12 +2143,14 @@ def doc_preferences(context):
|
|||||||
L = []
|
L = []
|
||||||
for cat, cat_descr in PREF_CATEGORIES:
|
for cat, cat_descr in PREF_CATEGORIES:
|
||||||
L.append([""])
|
L.append([""])
|
||||||
L.append(["## " + cat_descr.get("title", "") ])
|
L.append(["## " + cat_descr.get("title", "")])
|
||||||
L.append([""])
|
L.append([""])
|
||||||
L.append( ["Nom", " ", " " ] )
|
L.append(["Nom", " ", " "])
|
||||||
L.append( ["----", "----", "----"] )
|
L.append(["----", "----", "----"])
|
||||||
for pref_name, pref in PREFS:
|
for pref_name, pref in PREFS:
|
||||||
if pref["category"] == cat:
|
if pref["category"] == cat:
|
||||||
L.append(['`'+pref_name+'`', pref["title"], pref.get("explanation", "")])
|
L.append(
|
||||||
|
["`" + pref_name + "`", pref["title"], pref.get("explanation", "")]
|
||||||
|
)
|
||||||
|
|
||||||
return "\n".join([" | ".join(x) for x in L])
|
return "\n".join([" | ".join(x) for x in L])
|
||||||
|
104
sco_pvpdf.py
104
sco_pvpdf.py
@ -94,7 +94,9 @@ def pageFooter(canvas, doc, logo, preferences, with_page_numbers=True):
|
|||||||
("RIGHTPADDING", (-1, 0), (-1, 0), 1 * cm),
|
("RIGHTPADDING", (-1, 0), (-1, 0), 1 * cm),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
elems = [p, logo]
|
elems = [p]
|
||||||
|
if logo:
|
||||||
|
elems.append(logo)
|
||||||
colWidths = [None, LOGO_FOOTER_WIDTH + 2 * mm]
|
colWidths = [None, LOGO_FOOTER_WIDTH + 2 * mm]
|
||||||
if with_page_numbers:
|
if with_page_numbers:
|
||||||
elems.append(np)
|
elems.append(np)
|
||||||
@ -124,14 +126,14 @@ def pageHeader(canvas, doc, logo, preferences, only_on_first_page=False):
|
|||||||
id="monheader",
|
id="monheader",
|
||||||
showBoundary=0,
|
showBoundary=0,
|
||||||
)
|
)
|
||||||
canvas.saveState() # is it necessary ?
|
if logo:
|
||||||
head.addFromList([logo], canvas)
|
canvas.saveState() # is it necessary ?
|
||||||
canvas.restoreState()
|
head.addFromList([logo], canvas)
|
||||||
|
canvas.restoreState()
|
||||||
|
|
||||||
|
|
||||||
class CourrierIndividuelTemplate(PageTemplate):
|
class CourrierIndividuelTemplate(PageTemplate):
|
||||||
"""Template pour courrier avisant des decisions de jury (1 page /etudiant)
|
"""Template pour courrier avisant des decisions de jury (1 page /etudiant)"""
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@ -156,6 +158,13 @@ class CourrierIndividuelTemplate(PageTemplate):
|
|||||||
self.preferences = preferences
|
self.preferences = preferences
|
||||||
self.force_header = force_header
|
self.force_header = force_header
|
||||||
self.force_footer = force_footer
|
self.force_footer = force_footer
|
||||||
|
self.with_footer = (
|
||||||
|
self.force_footer or self.preferences["PV_LETTER_WITH_HEADER"]
|
||||||
|
)
|
||||||
|
self.with_header = (
|
||||||
|
self.force_header or self.preferences["PV_LETTER_WITH_FOOTER"]
|
||||||
|
)
|
||||||
|
self.with_page_background = self.preferences["PV_LETTER_WITH_BACKGROUND"]
|
||||||
self.with_page_numbers = False
|
self.with_page_numbers = False
|
||||||
self.header_only_on_first_page = False
|
self.header_only_on_first_page = False
|
||||||
# Our doc is made of a single frame
|
# Our doc is made of a single frame
|
||||||
@ -175,16 +184,32 @@ class CourrierIndividuelTemplate(PageTemplate):
|
|||||||
|
|
||||||
PageTemplate.__init__(self, template_name, [content])
|
PageTemplate.__init__(self, template_name, [content])
|
||||||
|
|
||||||
self.logo_footer = Image(
|
self.background_image_filename = None
|
||||||
image_dir + "/logo_footer.jpg",
|
self.logo_footer = None
|
||||||
height=LOGO_FOOTER_HEIGHT,
|
self.logo_header = None
|
||||||
width=LOGO_FOOTER_WIDTH,
|
for suffix in LOGOS_IMAGES_ALLOWED_TYPES:
|
||||||
)
|
if template_name == "PVJuryTemplate":
|
||||||
self.logo_header = Image(
|
fn = image_dir + "/pvjury_background" + "." + suffix
|
||||||
image_dir + "/logo_header.jpg",
|
else:
|
||||||
height=LOGO_HEADER_HEIGHT,
|
fn = image_dir + "/letter_background" + "." + suffix
|
||||||
width=LOGO_HEADER_WIDTH,
|
if os.path.exists(fn):
|
||||||
)
|
self.background_image_filename = fn
|
||||||
|
|
||||||
|
fn = image_dir + "/logo_footer" + "." + suffix
|
||||||
|
if os.path.exists(fn):
|
||||||
|
self.logo_footer = Image(
|
||||||
|
fn,
|
||||||
|
height=LOGO_FOOTER_HEIGHT,
|
||||||
|
width=LOGO_FOOTER_WIDTH,
|
||||||
|
)
|
||||||
|
|
||||||
|
fn = image_dir + "/logo_header" + "." + suffix
|
||||||
|
if os.path.exists(fn):
|
||||||
|
self.logo_header = Image(
|
||||||
|
fn,
|
||||||
|
height=LOGO_HEADER_HEIGHT,
|
||||||
|
width=LOGO_HEADER_WIDTH,
|
||||||
|
)
|
||||||
|
|
||||||
def beforeDrawPage(self, canvas, doc):
|
def beforeDrawPage(self, canvas, doc):
|
||||||
"""Draws a logo and an contribution message on each page."""
|
"""Draws a logo and an contribution message on each page."""
|
||||||
@ -201,8 +226,15 @@ class CourrierIndividuelTemplate(PageTemplate):
|
|||||||
txt = SU(bm)
|
txt = SU(bm)
|
||||||
canvas.bookmarkPage(key)
|
canvas.bookmarkPage(key)
|
||||||
canvas.addOutlineEntry(txt, bm)
|
canvas.addOutlineEntry(txt, bm)
|
||||||
if self.force_footer or self.preferences["PV_LETTER_WITH_HEADER"]:
|
|
||||||
# --- Add header
|
# ---- Background image
|
||||||
|
if self.background_image_filename and self.with_page_background:
|
||||||
|
canvas.drawImage(
|
||||||
|
self.background_image_filename, 0, 0, doc.pagesize[0], doc.pagesize[1]
|
||||||
|
)
|
||||||
|
|
||||||
|
# ---- Header/Footer
|
||||||
|
if self.with_header:
|
||||||
pageHeader(
|
pageHeader(
|
||||||
canvas,
|
canvas,
|
||||||
doc,
|
doc,
|
||||||
@ -210,8 +242,7 @@ class CourrierIndividuelTemplate(PageTemplate):
|
|||||||
self.preferences,
|
self.preferences,
|
||||||
self.header_only_on_first_page,
|
self.header_only_on_first_page,
|
||||||
)
|
)
|
||||||
if self.force_footer or self.preferences["PV_LETTER_WITH_FOOTER"]:
|
if self.with_footer:
|
||||||
# --- Add footer
|
|
||||||
pageFooter(
|
pageFooter(
|
||||||
canvas,
|
canvas,
|
||||||
doc,
|
doc,
|
||||||
@ -222,8 +253,7 @@ class CourrierIndividuelTemplate(PageTemplate):
|
|||||||
|
|
||||||
|
|
||||||
class PVTemplate(CourrierIndividuelTemplate):
|
class PVTemplate(CourrierIndividuelTemplate):
|
||||||
"""Template pour les pages des PV de jury
|
"""Template pour les pages des PV de jury"""
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@ -231,10 +261,17 @@ class PVTemplate(CourrierIndividuelTemplate):
|
|||||||
author=None,
|
author=None,
|
||||||
title=None,
|
title=None,
|
||||||
subject=None,
|
subject=None,
|
||||||
margins=(0, 23, 0, 5), # additional margins in mm (left,top,right, bottom)
|
margins=None, # additional margins in mm (left,top,right, bottom)
|
||||||
image_dir="",
|
image_dir="",
|
||||||
preferences=None, # dictionnary with preferences, required
|
preferences=None, # dictionnary with preferences, required
|
||||||
):
|
):
|
||||||
|
if margins is None:
|
||||||
|
margins = (
|
||||||
|
preferences["pv_left_margin"],
|
||||||
|
preferences["pv_top_margin"],
|
||||||
|
preferences["pv_right_margin"],
|
||||||
|
preferences["pv_bottom_margin"],
|
||||||
|
)
|
||||||
CourrierIndividuelTemplate.__init__(
|
CourrierIndividuelTemplate.__init__(
|
||||||
self,
|
self,
|
||||||
document,
|
document,
|
||||||
@ -250,6 +287,9 @@ class PVTemplate(CourrierIndividuelTemplate):
|
|||||||
)
|
)
|
||||||
self.with_page_numbers = True
|
self.with_page_numbers = True
|
||||||
self.header_only_on_first_page = True
|
self.header_only_on_first_page = True
|
||||||
|
self.with_header = self.preferences["PV_WITH_HEADER"]
|
||||||
|
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, canvas, doc):
|
||||||
"""Called after all flowables have been drawn on a page"""
|
"""Called after all flowables have been drawn on a page"""
|
||||||
@ -331,7 +371,7 @@ def pdf_lettres_individuelles(
|
|||||||
document = BaseDocTemplate(report)
|
document = BaseDocTemplate(report)
|
||||||
image_dir = SCODOC_LOGOS_DIR + "/logos_" + context.DeptId() + "/"
|
image_dir = SCODOC_LOGOS_DIR + "/logos_" + context.DeptId() + "/"
|
||||||
if not os.path.exists(image_dir):
|
if not os.path.exists(image_dir):
|
||||||
image_dir = SCODOC_LOGOS_DIR + "/" # use global logos
|
image_dir = SCODOC_LOGOS_DIR + "/" # use global logos
|
||||||
document.addPageTemplates(
|
document.addPageTemplates(
|
||||||
CourrierIndividuelTemplate(
|
CourrierIndividuelTemplate(
|
||||||
document,
|
document,
|
||||||
@ -437,9 +477,13 @@ def pdf_lettre_individuelle(sem, decision, etud, params, signature=None, context
|
|||||||
s = "s"
|
s = "s"
|
||||||
else:
|
else:
|
||||||
s = ""
|
s = ""
|
||||||
params["autorisations_txt"] = (
|
params[
|
||||||
"""Vous êtes autorisé%s à continuer dans le%s semestre%s : <b>%s</b>"""
|
"autorisations_txt"
|
||||||
% (etud["ne"], s, s, decision["autorisations_descr"])
|
] = """Vous êtes autorisé%s à continuer dans le%s semestre%s : <b>%s</b>""" % (
|
||||||
|
etud["ne"],
|
||||||
|
s,
|
||||||
|
s,
|
||||||
|
decision["autorisations_descr"],
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
params["autorisations_txt"] = ""
|
params["autorisations_txt"] = ""
|
||||||
@ -538,9 +582,6 @@ def _make_signature_image(signature, leftindent, formsemestre_id, context=None):
|
|||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------
|
# ----------------------------------------------
|
||||||
# PV complet, tableau en format paysage
|
|
||||||
|
|
||||||
|
|
||||||
def pvjury_pdf(
|
def pvjury_pdf(
|
||||||
context,
|
context,
|
||||||
dpv,
|
dpv,
|
||||||
@ -554,6 +595,7 @@ def pvjury_pdf(
|
|||||||
anonymous=False,
|
anonymous=False,
|
||||||
):
|
):
|
||||||
"""Doc PDF récapitulant les décisions de jury
|
"""Doc PDF récapitulant les décisions de jury
|
||||||
|
(tableau en format paysage)
|
||||||
dpv: result of dict_pvjury
|
dpv: result of dict_pvjury
|
||||||
"""
|
"""
|
||||||
if not dpv:
|
if not dpv:
|
||||||
@ -602,7 +644,7 @@ def pvjury_pdf(
|
|||||||
document.pagesize = landscape(A4)
|
document.pagesize = landscape(A4)
|
||||||
image_dir = SCODOC_LOGOS_DIR + "/logos_" + context.DeptId() + "/"
|
image_dir = SCODOC_LOGOS_DIR + "/logos_" + context.DeptId() + "/"
|
||||||
if not os.path.exists(image_dir):
|
if not os.path.exists(image_dir):
|
||||||
image_dir = SCODOC_LOGOS_DIR + "/" # use global logos
|
image_dir = SCODOC_LOGOS_DIR + "/" # use global logos
|
||||||
document.addPageTemplates(
|
document.addPageTemplates(
|
||||||
PVTemplate(
|
PVTemplate(
|
||||||
document,
|
document,
|
||||||
|
40
sco_utils.py
40
sco_utils.py
@ -156,15 +156,14 @@ def fmt_note(val, note_max=None, keep_numeric=False):
|
|||||||
|
|
||||||
|
|
||||||
def fmt_coef(val):
|
def fmt_coef(val):
|
||||||
"""Conversion valeur coefficient (float) en chaine
|
"""Conversion valeur coefficient (float) en chaine"""
|
||||||
"""
|
|
||||||
if val < 0.01:
|
if val < 0.01:
|
||||||
return "%g" % val # unusually small value
|
return "%g" % val # unusually small value
|
||||||
return "%g" % round(val, 2)
|
return "%g" % round(val, 2)
|
||||||
|
|
||||||
|
|
||||||
def fmt_abs(val):
|
def fmt_abs(val):
|
||||||
""" Conversion absences en chaine. val est une list [nb_abs_total, nb_abs_justifiees
|
"""Conversion absences en chaine. val est une list [nb_abs_total, nb_abs_justifiees
|
||||||
=> NbAbs / Nb_justifiees
|
=> NbAbs / Nb_justifiees
|
||||||
"""
|
"""
|
||||||
return "%s / %s" % (val[0], val[1])
|
return "%s / %s" % (val[0], val[1])
|
||||||
@ -194,7 +193,7 @@ GSL = thread.allocate_lock() # Global ScoDoc Lock
|
|||||||
|
|
||||||
if "INSTANCE_HOME" in os.environ:
|
if "INSTANCE_HOME" in os.environ:
|
||||||
# ----- Repertoire "var" (local)
|
# ----- Repertoire "var" (local)
|
||||||
SCODOC_VAR_DIR = os.path.join( os.environ["INSTANCE_HOME"], "var", "scodoc" )
|
SCODOC_VAR_DIR = os.path.join(os.environ["INSTANCE_HOME"], "var", "scodoc")
|
||||||
# ----- Version information
|
# ----- Version information
|
||||||
SCODOC_VERSION_DIR = os.path.join(SCODOC_VAR_DIR, "config", "version")
|
SCODOC_VERSION_DIR = os.path.join(SCODOC_VAR_DIR, "config", "version")
|
||||||
# ----- Repertoire tmp
|
# ----- Repertoire tmp
|
||||||
@ -203,13 +202,12 @@ if "INSTANCE_HOME" in os.environ:
|
|||||||
os.mkdir(SCO_TMPDIR, 0o755)
|
os.mkdir(SCO_TMPDIR, 0o755)
|
||||||
# ----- Les logos: /opt/scodoc/var/scodoc/config/logos
|
# ----- Les logos: /opt/scodoc/var/scodoc/config/logos
|
||||||
SCODOC_LOGOS_DIR = os.path.join(SCODOC_VAR_DIR, "config", "logos")
|
SCODOC_LOGOS_DIR = os.path.join(SCODOC_VAR_DIR, "config", "logos")
|
||||||
|
|
||||||
# ----- Repertoire "config" (devrait s'appeler "tools"...)
|
# ----- Repertoire "config" (devrait s'appeler "tools"...)
|
||||||
SCO_CONFIG_DIR = os.path.join(
|
SCO_CONFIG_DIR = os.path.join(
|
||||||
os.environ["INSTANCE_HOME"], "Products", "ScoDoc", "config"
|
os.environ["INSTANCE_HOME"], "Products", "ScoDoc", "config"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ----- Lecture du fichier de configuration
|
# ----- Lecture du fichier de configuration
|
||||||
SCO_SRCDIR = os.path.split(VERSION.__file__)[0]
|
SCO_SRCDIR = os.path.split(VERSION.__file__)[0]
|
||||||
@ -231,7 +229,9 @@ except:
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
if hasattr(CONFIG, "CODES_EXPL"):
|
if hasattr(CONFIG, "CODES_EXPL"):
|
||||||
CODES_EXPL.update(CONFIG.CODES_EXPL) # permet de customiser les explications de codes
|
CODES_EXPL.update(
|
||||||
|
CONFIG.CODES_EXPL
|
||||||
|
) # permet de customiser les explications de codes
|
||||||
|
|
||||||
|
|
||||||
if CONFIG.CUSTOM_HTML_HEADER:
|
if CONFIG.CUSTOM_HTML_HEADER:
|
||||||
@ -270,7 +270,7 @@ SCO_DEFAULT_SQL_USERS_CNX = "dbname=SCOUSERS port=%s" % SCO_DEFAULT_SQL_PORT
|
|||||||
|
|
||||||
# Valeurs utilisées pour affichage seulement, pas de requetes ni de mails envoyés:
|
# Valeurs utilisées pour affichage seulement, pas de requetes ni de mails envoyés:
|
||||||
SCO_WEBSITE = "https://scodoc.org"
|
SCO_WEBSITE = "https://scodoc.org"
|
||||||
SCO_USER_MANUAL = "https://scodoc.org/GuideUtilisateur"
|
SCO_USER_MANUAL = "https://scodoc.org/GuideUtilisateur"
|
||||||
SCO_ANNONCES_WEBSITE = "https://listes.univ-paris13.fr/mailman/listinfo/scodoc-annonces"
|
SCO_ANNONCES_WEBSITE = "https://listes.univ-paris13.fr/mailman/listinfo/scodoc-annonces"
|
||||||
SCO_DEVEL_LIST = "scodoc-devel@listes.univ-paris13.fr"
|
SCO_DEVEL_LIST = "scodoc-devel@listes.univ-paris13.fr"
|
||||||
SCO_USERS_LIST = "notes@listes.univ-paris13.fr"
|
SCO_USERS_LIST = "notes@listes.univ-paris13.fr"
|
||||||
@ -296,6 +296,8 @@ PDF_MIMETYPE = "application/pdf"
|
|||||||
XML_MIMETYPE = "text/xml"
|
XML_MIMETYPE = "text/xml"
|
||||||
JSON_MIMETYPE = "application/json"
|
JSON_MIMETYPE = "application/json"
|
||||||
|
|
||||||
|
LOGOS_IMAGES_ALLOWED_TYPES = ("jpg", "png") # remind that PIL does not read pdf
|
||||||
|
|
||||||
|
|
||||||
class DictDefault(dict): # obsolete, use collections.defaultdict
|
class DictDefault(dict): # obsolete, use collections.defaultdict
|
||||||
"""A dictionnary with default value for all keys
|
"""A dictionnary with default value for all keys
|
||||||
@ -421,7 +423,7 @@ def simple_dictlist2xml(dictlist, doc=None, tagname=None, quote=False):
|
|||||||
<ues note="10" />
|
<ues note="10" />
|
||||||
<ues />
|
<ues />
|
||||||
</infos>
|
</infos>
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if not tagname:
|
if not tagname:
|
||||||
raise ValueError("invalid empty tagname !")
|
raise ValueError("invalid empty tagname !")
|
||||||
@ -462,8 +464,7 @@ ALPHANUM_EXP = re.compile(r"^[\w-]+$", re.UNICODE)
|
|||||||
|
|
||||||
|
|
||||||
def is_valid_code_nip(s):
|
def is_valid_code_nip(s):
|
||||||
"""True si s peut être un code NIP: au moins 6 chiffres décimaux
|
"""True si s peut être un code NIP: au moins 6 chiffres décimaux"""
|
||||||
"""
|
|
||||||
if not s:
|
if not s:
|
||||||
return False
|
return False
|
||||||
return re.match(r"^[0-9]{6,32}$", s)
|
return re.match(r"^[0-9]{6,32}$", s)
|
||||||
@ -492,7 +493,7 @@ def suppress_accents(s):
|
|||||||
|
|
||||||
def sanitize_string(s):
|
def sanitize_string(s):
|
||||||
"""s is an ordinary string, encoding given by SCO_ENCODING"
|
"""s is an ordinary string, encoding given by SCO_ENCODING"
|
||||||
suppress accents and chars interpreted in XML
|
suppress accents and chars interpreted in XML
|
||||||
Irreversible (not a quote)
|
Irreversible (not a quote)
|
||||||
|
|
||||||
For ids and some filenames
|
For ids and some filenames
|
||||||
@ -747,8 +748,7 @@ from sgmllib import SGMLParser
|
|||||||
|
|
||||||
|
|
||||||
class html2txt_parser(SGMLParser):
|
class html2txt_parser(SGMLParser):
|
||||||
"""html2txt()
|
"""html2txt()"""
|
||||||
"""
|
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
"""reset() --> initialize the parser"""
|
"""reset() --> initialize the parser"""
|
||||||
@ -757,15 +757,15 @@ class html2txt_parser(SGMLParser):
|
|||||||
|
|
||||||
def handle_data(self, text):
|
def handle_data(self, text):
|
||||||
"""handle_data(text) --> appends the pieces to self.pieces
|
"""handle_data(text) --> appends the pieces to self.pieces
|
||||||
handles all normal data not between brackets "<>"
|
handles all normal data not between brackets "<>"
|
||||||
"""
|
"""
|
||||||
self.pieces.append(text)
|
self.pieces.append(text)
|
||||||
|
|
||||||
def handle_entityref(self, ref):
|
def handle_entityref(self, ref):
|
||||||
"""called for each entity reference, e.g. for "©", ref will be
|
"""called for each entity reference, e.g. for "©", ref will be
|
||||||
"copy"
|
"copy"
|
||||||
Reconstruct the original entity reference.
|
Reconstruct the original entity reference.
|
||||||
"""
|
"""
|
||||||
if ref == "amp":
|
if ref == "amp":
|
||||||
self.pieces.append("&")
|
self.pieces.append("&")
|
||||||
|
|
||||||
@ -794,7 +794,7 @@ def icontag(name, file_format="png", **attrs):
|
|||||||
"""tag HTML pour un icone.
|
"""tag HTML pour un icone.
|
||||||
(dans les versions anterieures on utilisait Zope)
|
(dans les versions anterieures on utilisait Zope)
|
||||||
Les icones sont des fichiers PNG dans .../static/icons
|
Les icones sont des fichiers PNG dans .../static/icons
|
||||||
Si la taille (width et height) n'est pas spécifiée, lit l'image
|
Si la taille (width et height) n'est pas spécifiée, lit l'image
|
||||||
pour la mesurer (et cache le résultat).
|
pour la mesurer (et cache le résultat).
|
||||||
"""
|
"""
|
||||||
if ("width" not in attrs) or ("height" not in attrs):
|
if ("width" not in attrs) or ("height" not in attrs):
|
||||||
|
Loading…
Reference in New Issue
Block a user