diff --git a/ImportScolars.py b/ImportScolars.py index 8e06e93c5c..c264e9d4cf 100644 --- a/ImportScolars.py +++ b/ImportScolars.py @@ -368,16 +368,16 @@ def scolars_import_excel_file( # xxx Ad-hoc checks (should be in format description) if scu.strlower(titleslist[i]) == "sexe": try: - val = scolars.normalize_sexe(val) + val = scolars.input_civilite(val) except: raise ScoValueError( - "valeur invalide pour 'SEXE' (doit etre 'M' ou 'MME' ou 'H' ou 'F', pas '%s') ligne %d, colonne %s" + "valeur invalide pour 'SEXE' (doit etre 'M', 'F', ou 'MME', 'H', 'X' ou vide, mais pas '%s') ligne %d, colonne %s" % (val, linenum, titleslist[i]) ) # Excel date conversion: if scu.strlower(titleslist[i]) == "date_naissance": if val: - if re.match("^[0-9]*\.?[0-9]*$", str(val)): + if re.match(r"^[0-9]*\.?[0-9]*$", str(val)): val = sco_excel.xldate_as_datetime(float(val)) # INE if ( @@ -515,11 +515,11 @@ def _import_one_student( # Admissions args["etudid"] = etudid args["annee"] = annee_courante - adm_id = scolars.admission_create(cnx, args) + _ = scolars.admission_create(cnx, args) # Adresse args["typeadresse"] = "domicile" args["description"] = "(infos admission)" - adresse_id = scolars.adresse_create(cnx, args) + _ = scolars.adresse_create(cnx, args) # Inscription au semestre args["etat"] = "I" # etat insc. semestre if formsemestre_id: diff --git a/VERSION.py b/VERSION.py index 8e8a40a40d..3ff1eed40e 100644 --- a/VERSION.py +++ b/VERSION.py @@ -1,19 +1,21 @@ # -*- mode: python -*- # -*- coding: utf-8 -*- -SCOVERSION = "7.22" +SCOVERSION = "7.23" SCONAME = "ScoDoc" SCONEWS = """

Année 2021

Année 2020

") logt("Z: table_suivi_cohorte done") - return tab, "\n".join(expl), bacs, bacspecialites, annee_bacs, sexes, statuts + return ( + tab, + "\n".join(expl), + bacs, + bacspecialites, + annee_bacs, + civilites, + statuts, + ) def formsemestre_suivi_cohorte( @@ -663,27 +671,35 @@ def formsemestre_suivi_cohorte( bac="", bacspecialite="", annee_bac="", - sexe="", + civilite=None, statut="", only_primo=False, REQUEST=None, ): """Affiche suivi cohortes par numero de semestre""" percent = int(percent) - tab, expl, bacs, bacspecialites, annee_bacs, sexes, statuts = table_suivi_cohorte( + ( + tab, + expl, + bacs, + bacspecialites, + annee_bacs, + civilites, + statuts, + ) = table_suivi_cohorte( context, formsemestre_id, percent=percent, bac=bac, bacspecialite=bacspecialite, annee_bac=annee_bac, - sexe=sexe, + civilite=civilite, statut=statut, only_primo=only_primo, ) tab.base_url = ( - "%s?formsemestre_id=%s&percent=%s&bac=%s&bacspecialite=%s&sexe=%s" - % (REQUEST.URL0, formsemestre_id, percent, bac, bacspecialite, sexe) + "%s?formsemestre_id=%s&percent=%s&bac=%s&bacspecialite=%s&civilite=%s" + % (REQUEST.URL0, formsemestre_id, percent, bac, bacspecialite, civilite) ) if only_primo: tab.base_url += "&only_primo=on" @@ -693,8 +709,8 @@ def formsemestre_suivi_cohorte( base_url = REQUEST.URL0 burl = ( - "%s?formsemestre_id=%s&bac=%s&bacspecialite=%s&sexe=%s&statut=%s" - % (base_url, formsemestre_id, bac, bacspecialite, sexe, statut) + "%s?formsemestre_id=%s&bac=%s&bacspecialite=%s&civilite=%s&statut=%s" + % (base_url, formsemestre_id, bac, bacspecialite, civilite, statut) ) if percent: pplink = ( @@ -724,12 +740,12 @@ def formsemestre_suivi_cohorte( bac=bac, bacspecialite=bacspecialite, annee_bac=annee_bac, - sexe=sexe, + civilite=civilite, statut=statut, bacs=bacs, bacspecialites=bacspecialites, annee_bacs=annee_bacs, - sexes=sexes, + civilites=civilites, statuts=statuts, percent=percent, ), @@ -749,12 +765,12 @@ def _gen_form_selectetuds( bac=None, bacspecialite=None, annee_bac=None, - sexe=None, + civilite=None, statut=None, bacs=None, bacspecialites=None, annee_bacs=None, - sexes=None, + civilites=None, statuts=None, ): """HTML form pour choix criteres selection etudiants""" @@ -764,8 +780,8 @@ def _gen_form_selectetuds( bacspecialites.sort() annee_bacs = list(annee_bacs) annee_bacs.sort() - sexes = list(sexes) - sexes.sort() + civilites = list(civilites) + civilites.sort() statuts = list(statuts) statuts.sort() # @@ -824,13 +840,13 @@ def _gen_form_selectetuds( F.append("") # F.append( - """  Genre: """ % selected ) - for b in sexes: - if sexe == b: + for b in civilites: + if civilite == b: selected = 'selected="selected"' else: selected = "" @@ -984,7 +1000,7 @@ def tsp_etud_list( bac="", # selection sur type de bac bacspecialite="", annee_bac="", - sexe="", + civilite="", statut="", ): """Liste des etuds a considerer dans table suivi parcours @@ -1000,7 +1016,7 @@ def tsp_etud_list( bacs = set() bacspecialites = set() annee_bacs = set() - sexes = set() + civilites = set() statuts = set() for etudid in etudids: etud = context.getEtudInfo(etudid=etudid, filled=True)[0] @@ -1010,7 +1026,7 @@ def tsp_etud_list( (not bac or (bac == etud["bac"])) and (not bacspecialite or (bacspecialite == bacspe)) and (not annee_bac or (annee_bac == str(etud["annee_bac"]))) - and (not sexe or (sexe == etud["sexe"])) + and (not civilite or (civilite == etud["civilite"])) and (not statut or (statut == etud["statut"])) and (not only_primo or context.isPrimoEtud(etud, sem)) ): @@ -1019,11 +1035,11 @@ def tsp_etud_list( bacs.add(etud["bac"]) bacspecialites.add(bacspe) annee_bacs.add(etud["annee_bac"]) - sexes.add(etud["sexe"]) + civilites.add(etud["civilite"]) if etud["statut"]: # ne montre pas les statuts non renseignés statuts.add(etud["statut"]) # log('tsp_etud_list: %s etuds' % len(etuds)) - return etuds, bacs, bacspecialites, annee_bacs, sexes, statuts + return etuds, bacs, bacspecialites, annee_bacs, civilites, statuts def tsp_grouped_list(context, codes_etuds): @@ -1049,7 +1065,7 @@ def table_suivi_parcours( ): """Tableau recapitulant tous les parcours""" sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) - etuds, bacs, bacspecialites, annee_bacs, sexes, statuts = tsp_etud_list( + etuds, bacs, bacspecialites, annee_bacs, civilites, statuts = tsp_etud_list( context, formsemestre_id, only_primo=only_primo ) codes_etuds = scu.DictDefault(defaultvalue=[]) @@ -1065,7 +1081,7 @@ def table_suivi_parcours( titles = { "parcours": "Code parcours", "nb": "Nombre d'étudiants", - "sexe": "", + "civilite": "", "nom": "Nom", "prenom": "Prénom", "etudid": "etudid", @@ -1082,7 +1098,7 @@ def table_suivi_parcours( L = etuds columns_ids = ( "etudid", - "sexe", + "civilite", "nom", "prenom", "bac", @@ -1209,25 +1225,25 @@ def graph_parcours( bac="", # selection sur type de bac bacspecialite="", annee_bac="", - sexe="", + civilite="", statut="", ): """""" if not scu.WITH_PYDOT: raise ScoValueError("pydot module is not installed") - etuds, bacs, bacspecialites, annee_bacs, sexes, statuts = tsp_etud_list( + etuds, bacs, bacspecialites, annee_bacs, civilites, statuts = tsp_etud_list( context, formsemestre_id, only_primo=only_primo, bac=bac, bacspecialite=bacspecialite, annee_bac=annee_bac, - sexe=sexe, + civilite=civilite, statut=statut, ) # log('graph_parcours: %s etuds (only_primo=%s)' % (len(etuds), only_primo)) if not etuds: - return "", etuds, bacs, bacspecialites, annee_bacs, sexes, statuts + return "", etuds, bacs, bacspecialites, annee_bacs, civilites, statuts edges = scu.DictDefault( defaultvalue=set() ) # {(formsemestre_id_origin, formsemestre_id_dest) : etud_set} @@ -1417,7 +1433,7 @@ def graph_parcours( # cf http://groups.google.com/group/pydot/browse_thread/thread/b3704c53e331e2ec data = data.replace("font-family:Arial", "font-family:Helvetica") - return data, etuds, bacs, bacspecialites, annee_bacs, sexes, statuts + return data, etuds, bacs, bacspecialites, annee_bacs, civilites, statuts def formsemestre_graph_parcours( @@ -1428,7 +1444,7 @@ def formsemestre_graph_parcours( bac="", # selection sur type de bac bacspecialite="", annee_bac="", - sexe="", + civilite="", statut="", allkeys=False, # unused REQUEST=None, @@ -1437,7 +1453,15 @@ def formsemestre_graph_parcours( # log("formsemestre_graph_parcours") sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) if format == "pdf": - doc, etuds, bacs, bacspecialites, annee_bacs, sexes, statuts = graph_parcours( + ( + doc, + etuds, + bacs, + bacspecialites, + annee_bacs, + civilites, + statuts, + ) = graph_parcours( context, formsemestre_id, format="pdf", @@ -1445,14 +1469,22 @@ def formsemestre_graph_parcours( bac=bac, bacspecialite=bacspecialite, annee_bac=annee_bac, - sexe=sexe, + civilite=civilite, statut=statut, ) filename = scu.make_filename("flux " + sem["titreannee"]) return scu.sendPDFFile(REQUEST, doc, filename + ".pdf") elif format == "png": # - doc, etuds, bacs, bacspecialites, annee_bacs, sexes, statuts = graph_parcours( + ( + doc, + etuds, + bacs, + bacspecialites, + annee_bacs, + civilites, + statuts, + ) = graph_parcours( context, formsemestre_id, format="png", @@ -1460,7 +1492,7 @@ def formsemestre_graph_parcours( bac=bac, bacspecialite=bacspecialite, annee_bac=annee_bac, - sexe=sexe, + civilite=civilite, statut=statut, ) filename = scu.make_filename("flux " + sem["titreannee"]) @@ -1475,17 +1507,25 @@ def formsemestre_graph_parcours( else: op = "" url = urllib.quote( - "formsemestre_graph_parcours?formsemestre_id=%s&%sbac=%s&bacspecialite=%s&sexe=%s&statut=%s&format=" - % (formsemestre_id, op, bac, bacspecialite, sexe, statut) + "formsemestre_graph_parcours?formsemestre_id=%s&%sbac=%s&bacspecialite=%s&civilite=%s&statut=%s&format=" + % (formsemestre_id, op, bac, bacspecialite, civilite, statut) ) - doc, etuds, bacs, bacspecialites, annee_bacs, sexes, statuts = graph_parcours( + ( + doc, + etuds, + bacs, + bacspecialites, + annee_bacs, + civilites, + statuts, + ) = graph_parcours( context, formsemestre_id, only_primo=only_primo, bac=bac, bacspecialite=bacspecialite, annee_bac=annee_bac, - sexe=sexe, + civilite=civilite, statut=statut, ) @@ -1505,12 +1545,12 @@ def formsemestre_graph_parcours( bac=bac, bacspecialite=bacspecialite, annee_bac=annee_bac, - sexe=sexe, + civilite=civilite, statut=statut, bacs=bacs, bacspecialites=bacspecialites, annee_bacs=annee_bacs, - sexes=sexes, + civilites=civilites, statuts=statuts, percent=0, ), diff --git a/sco_saisie_notes.py b/sco_saisie_notes.py index 7decaf793e..5309ee9cd0 100644 --- a/sco_saisie_notes.py +++ b/sco_saisie_notes.py @@ -1127,7 +1127,13 @@ def _form_saisie_notes(context, E, M, group_ids, destination="", REQUEST=None): for group_info in e["groups"]: etud_classes.append(group_info["group_id"]) - label = '' % classdem + e["nomprenom"] + "" + label = ( + '' % classdem + + e["civilite_str"] + + " " + + scolars.format_nomprenom(e, reverse=True) + + "" + ) # Historique des saisies de notes: if not disabled: diff --git a/sco_synchro_etuds.py b/sco_synchro_etuds.py index 14fe953a3e..ec70f80fed 100644 --- a/sco_synchro_etuds.py +++ b/sco_synchro_etuds.py @@ -408,7 +408,7 @@ def list_synch(context, sem, anneeapogee=None): etud = etudsapo_ident[key] etud["etudid"] = "" - etud["sexe"] = etud.get( + etud["civilite"] = etud.get( "sexe", etud.get("gender", "") ) # la cle 'sexe' est prioritaire sur 'gender' etud["inscrit"] = is_inscrit # checkbox state @@ -545,16 +545,14 @@ def formsemestre_synchro_etuds_help(context, sem): ) -def gender2sex(gender): - """Le portail code en 'M', 'F', et ScoDoc en 'MR', 'MME' - Les F sont ici codées en MME - """ - if gender == "M": - return "MR" - elif gender == "F": - return "MME" - log('gender2sex: invalid value "%s", defaulting to "M"' % gender) - return "MR" +def gender2civilite(gender): + """Le portail code en 'M', 'F', et ScoDoc en 'M', 'F', 'X'""" + if gender == "M" or gender == "F" or gender == "X": + return gender + elif not gender: + return "X" + log('gender2civilite: invalid value "%s", defaulting to "X"' % gender) + return "X" # "X" en général n'est pas affiché, donc bon choix si invalide def get_opt_str(etud, k): @@ -598,7 +596,7 @@ def do_import_etuds_from_portal(context, sem, a_importer, etudsapo_ident, REQUES "prenom": etud["prenom"].strip(), # Les champs suivants sont facultatifs (pas toujours renvoyés par le portail) "code_ine": etud.get("ine", "").strip(), - "sexe": gender2sex(etud["gender"].strip()), + "civilite": gender2civilite(etud["gender"].strip()), "etape": etud.get("etape", None), "email": etud.get("mail", "").strip(), "emailperso": etud.get("mailperso", "").strip(), @@ -738,9 +736,9 @@ def do_import_etud_admission( if x: args[sco_field] = x # Champs spécifiques: - sexe = gender2sex(etud["gender"].strip()) - if sexe: - args["sexe"] = sexe + civilite = gender2civilite(etud["gender"].strip()) + if civilite: + args["civilite"] = civilite scolars.identite_edit_nocheck(cnx, args) diff --git a/sco_trombino.py b/sco_trombino.py index b529ea7735..ce3ca1b12e 100644 --- a/sco_trombino.py +++ b/sco_trombino.py @@ -337,13 +337,7 @@ def _trombino_pdf(context, groups_infos, REQUEST): [img], [ Paragraph( - SU( - scolars.format_sexe(t["sexe"]) - + " " - + scolars.format_prenom(t["prenom"]) - + " " - + scolars.format_nom(t["nom"]) - ), + SU(scolars.format_nomprenom(t)), StyleSheet["Normal"], ) ], @@ -422,13 +416,7 @@ def _listeappel_photos_pdf(context, groups_infos, REQUEST): t = groups_infos.members[i] img = _get_etud_platypus_image(context, t, image_width=PHOTOWIDTH) txt = Paragraph( - SU( - scolars.format_sexe(t["sexe"]) - + " " - + scolars.format_prenom(t["prenom"]) - + " " - + scolars.format_nom(t["nom"]) - ), + SU(scolars.format_nomprenom(t)), StyleSheet["Normal"], ) if currow: diff --git a/sco_utils.py b/sco_utils.py index 88c2a29a61..60b26cbcb8 100644 --- a/sco_utils.py +++ b/sco_utils.py @@ -704,7 +704,7 @@ if WITH_PYDOT: junk_graph = pydot.Dot("junk") junk_graph.add_node(pydot.Node("a")) n = junk_graph.get_node("a") - if type(n) == type([]): + if type(n) == type([]): # "modern" pydot def pydot_get_node(g, name): r = g.get_node(name) @@ -713,7 +713,7 @@ if WITH_PYDOT: else: return r[0] - else: + else: # very old pydot def pydot_get_node(g, name): return g.get_node(name) diff --git a/scolars.py b/scolars.py index 7a17a772e3..7b407f1b16 100644 --- a/scolars.py +++ b/scolars.py @@ -101,7 +101,7 @@ def format_etud_ident(etud): else: etud["nom_usuel"] = "" etud["prenom"] = format_prenom(etud["prenom"]) - etud["sexe"] = format_sexe(etud["sexe"]) + etud["civilite_str"] = format_civilite(etud["civilite"]) # Nom à afficher: if etud["nom_usuel"]: etud["nom_disp"] = etud["nom_usuel"] @@ -111,10 +111,12 @@ def format_etud_ident(etud): etud["nom_disp"] = etud["nom"] etud["nomprenom"] = format_nomprenom(etud) # M. Pierre DUPONT - if etud["sexe"] == "M.": + if etud["civilite"] == "M": etud["ne"] = "" - else: + elif etud["civilite"] == "F": etud["ne"] = "e" + else: # 'X' + etud["ne"] = "(e)" # Mail à utiliser pour les envois vers l'étudiant: # choix qui pourrait être controé par une preference # ici priorité au mail institutionnel: @@ -127,15 +129,22 @@ def force_uppercase(s): return s -def format_nomprenom(etud): - "formatte sexe/nom/prenom pour affichages" - return " ".join( - [format_sexe(etud["sexe"]), format_prenom(etud["prenom"]), etud["nom_disp"]] - ) +def format_nomprenom(etud, reverse=False): + """Formatte civilité/nom/prenom pour affichages: "M. Pierre Dupont" + Si reverse, "Dupont Pierre", sans civilité. + """ + nom = etud.get("nom_disp", "") or etud.get("nom_usuel", "") or etud["nom"] + prenom = format_prenom(etud["prenom"]) + civilite = format_civilite(etud["civilite"]) + if reverse: + fs = [nom, prenom] + else: + fs = [civilite, prenom, nom] + return " ".join([x for x in fs if x]) def format_prenom(s): - "formatte prenom etudiant pour affichage" + "Formatte prenom etudiant pour affichage" if not s: return "" frags = s.split() @@ -162,22 +171,33 @@ def format_nom(s, uppercase=True): return format_prenom(s) -def format_sexe(sexe): - sexe = scu.strlower(sexe) - if sexe == "mr" or sexe == "m." or sexe == "m": - return "M." - else: - return "Mme" +def input_civilite(s): + """Converts external representation of civilite to internal: + 'M', 'F', or 'X' (and nothing else). + Raises valueError if conversion fails. + """ + s = scu.strupper(s).strip() + if s in ("M", "M.", "MR", "H"): + return "M" + elif s in ("F", "MLLE", "MLLE.", "MELLE", "MME"): + return "F" + elif s == "X" or not s: + return "X" + raise ValueError("valeur invalide pour la civilité: %s" % s) -def normalize_sexe(sexe): - "returns 'MR' ou 'MME'" - sexe = scu.strupper(sexe).strip() - if sexe in ("M.", "M", "MR", "H"): - return "MR" - elif sexe in ("MLLE", "MLLE.", "MELLE", "MME", "F"): - return "MME" - raise ValueError("valeur invalide pour le sexe: %s" % sexe) +def format_civilite(civilite): + """returns 'M.' ou 'Mme' ou '' (pour le genre neutre, + personne ne souhaitant pas d'affichage) + """ + try: + return { + "M": "M.", + "F": "Mme", + "X": "", + }[civilite] + except KeyError: + raise ValueError("valeur invalide pour la civilité: %s" % civilite) def format_lycee(nomlycee): @@ -241,7 +261,7 @@ _identiteEditor = EditableTable( "nom", "nom_usuel", "prenom", - "sexe", + "civilite", # 'M", "F", or "X" "date_naissance", "lieu_naissance", "dept_naissance", @@ -257,10 +277,10 @@ _identiteEditor = EditableTable( input_formators={ "nom": force_uppercase, "prenom": force_uppercase, - "sexe": force_uppercase, + "civilite": input_civilite, "date_naissance": DateDMYtoISO, }, - output_formators={"date_naissance": DateISOtoDMY, "sexe": normalize_sexe}, + output_formators={"date_naissance": DateISOtoDMY}, convert_null_outputs_to_empty=True, allow_set_id=True, # car on specifie le code Apogee a la creation ) @@ -269,13 +289,14 @@ identite_delete = _identiteEditor.delete def identite_list(cnx, *a, **kw): - "list, add 'annee_naissance'" + """List, adding on the fly 'annee_naissance' and 'civilite_str' (M., Mme, "").""" objs = _identiteEditor.list(cnx, *a, **kw) for o in objs: if o["date_naissance"]: o["annee_naissance"] = int(o["date_naissance"].split("/")[2]) else: o["annee_naissance"] = o["date_naissance"] + o["civilite_str"] = format_civilite(o["civilite"]) return objs @@ -372,7 +393,6 @@ def identite_edit(cnx, args, context=None, REQUEST=None): if notify_to: # etat AVANT edition pour envoyer diffs before = identite_list(cnx, {"etudid": args["etudid"]})[0] - before["sexe"] = format_sexe(before["sexe"]) identite_edit_nocheck(cnx, args) @@ -380,7 +400,6 @@ def identite_edit(cnx, args, context=None, REQUEST=None): if notify_to: etud = context.getEtudInfo(etudid=args["etudid"], filled=True)[0] after = identite_list(cnx, {"etudid": args["etudid"]})[0] - after["sexe"] = format_sexe(after["sexe"]) notify_etud_change( context, notify_to, @@ -412,7 +431,7 @@ def notify_etud_change(context, email_addr, etud, before, after, subject): """ txt = [ "Code NIP:" + etud["code_nip"], - "Genre: " + etud["sexe"], + "Civilité: " + etud["civilite_str"], "Nom: " + etud["nom"], "Prénom: " + etud["prenom"], "Etudid: " + etud["etudid"], diff --git a/scotests/demo/demo_reset_noms.py b/scotests/demo/demo_reset_noms.py index 5d569362bd..d1f00cf35c 100755 --- a/scotests/demo/demo_reset_noms.py +++ b/scotests/demo/demo_reset_noms.py @@ -3,12 +3,12 @@ """Outils pour environnements de démo. -Change aléatoirement les identites (nip, sexe, nom, prenom) des étudiants d'un semestre. +Change aléatoirement les identites (nip, civilite, nom, prenom) des étudiants d'un semestre. Le NIP est choisi aléatoirement (nombre entier à 8 chiffres). Les noms et prénoms sont issus des fichiers noms.txt, prenoms-h.txt, prenoms-f.txt (ce sont simlement les plus fréquemment rencontrés en France). -Le sexe est choisi aléatoirement 50-50. +La civilité est choisie aléatoirement 50-50 Homme/Femme. """ import sys @@ -54,17 +54,17 @@ cursor.execute( wcursor = cnx.cursor() n = 0 for (etudid,) in cursor: - sexe = random.choice(("M.", "MME")) - nom, prenom = nomprenom(sexe) + civilite = random.choice(("M", "F")) # pas de neutre, on pourrait ajouter 'X' + nom, prenom = nomprenom(civilite) print(f"{etudid}: {nom}\t{prenom}") args = { "nom": nom, "prenom": prenom, - "sexe": sexe, + "civilite": civilite, "etudid": etudid, "code_nip": random.randrange(10000000, 99999999), } - req = "update identite set nom=%(nom)s, prenom=%(prenom)s, sexe=%(sexe)s where etudid=%(etudid)s" + req = "update identite set nom=%(nom)s, prenom=%(prenom)s, civilite=%(civilite)s where etudid=%(etudid)s" # print( req % args) wcursor.execute(req, args) n += 1 diff --git a/scotests/demo/gen_nomprenoms.py b/scotests/demo/gen_nomprenoms.py index ec36fd7503..6ab8518861 100644 --- a/scotests/demo/gen_nomprenoms.py +++ b/scotests/demo/gen_nomprenoms.py @@ -10,14 +10,19 @@ cur_dir = Path(os.path.abspath(__file__)).parent NOMS = [x.strip() for x in open(cur_dir / "noms.txt").readlines()] PRENOMS_H = [x.strip() for x in open(cur_dir / "prenoms-h.txt").readlines()] PRENOMS_F = [x.strip() for x in open(cur_dir / "prenoms-f.txt").readlines()] +PRENOMS_X = [x.strip() for x in open(cur_dir / "prenoms-x.txt").readlines()] -def nomprenom(sexe): - """un nom et un prenom au hasard, - toujours en majuscules. +def nomprenom(civilite): + """Un nom et un prenom au hasard, + toujours en majuscules. Pour tests et démos. """ - if "e" in sexe.lower() or "f" in sexe.lower(): + if civilite == "F": prenom = random.choice(PRENOMS_F) - else: + elif civilite == "M": prenom = random.choice(PRENOMS_H) + elif civilite == "X": + prenom = random.choice(PRENOMS_X) + else: + raise ValueError("civilite must be M, F or X") return random.choice(NOMS).upper(), prenom.upper() diff --git a/scotests/demo/prenoms-x.txt b/scotests/demo/prenoms-x.txt new file mode 100644 index 0000000000..68ce1abf65 --- /dev/null +++ b/scotests/demo/prenoms-x.txt @@ -0,0 +1,10 @@ +Camille +Sacha +Eden +Maxime +Morgan +Charlie +Alix +Claude +Ufuk +Lou diff --git a/scotests/sco_fake_gen.py b/scotests/sco_fake_gen.py index 2a066de0fe..5bf59fe5e3 100644 --- a/scotests/sco_fake_gen.py +++ b/scotests/sco_fake_gen.py @@ -38,6 +38,7 @@ DEMODIR = sco_utils.SCO_SRCDIR + "/scotests/demo/" NOMS = [x.strip() for x in open(DEMODIR + "/noms.txt").readlines()] PRENOMS_H = [x.strip() for x in open(DEMODIR + "/prenoms-h.txt").readlines()] PRENOMS_F = [x.strip() for x in open(DEMODIR + "/prenoms-f.txt").readlines()] +PRENOMS_X = [x.strip() for x in open(DEMODIR + "/prenoms-x.txt").readlines()] # nb: en python2, les chaines ci-dessus sont en utf8 @@ -66,16 +67,20 @@ class ScoFake: sys.stderr.flush() log("ScoFake: " + str(msg)) - def sexenomprenom(self): + def civilitenomprenom(self): """un nom et un prenom au hasard, toujours en majuscules. """ - sexe = random.choice(("M", "F")) - if "e" in sexe.lower() or "f" in sexe.lower(): + civilite = random.choice(("M", "M", "M", "F", "F", "F", "X")) + if civilite == "F": prenom = random.choice(PRENOMS_F) - else: + elif civilite == "M": prenom = random.choice(PRENOMS_H) - return sexe, random.choice(NOMS).upper(), prenom.upper() + elif civilite == "X": + prenom = random.choice(PRENOMS_X) + else: + raise ValueError("invalid civilite value") + return civilite, random.choice(NOMS).upper(), prenom.upper() @logging_meth def create_etud( @@ -85,7 +90,7 @@ class ScoFake: nom="", prenom="", code_ine="", - sexe="", + civilite="", etape="TST1", email="test@localhost", emailperso="perso@localhost", @@ -106,10 +111,10 @@ class ScoFake: cnx = self.context.GetDBConnexion() if code_nip == "": code_nip = str(random.randint(10000, 99999)) - if not sexe or not nom or not prenom: - r_sexe, r_nom, r_prenom = self.sexenomprenom() - if not sexe: - sexe = r_sexe + if not civilite or not nom or not prenom: + r_civilite, r_nom, r_prenom = self.civilitenomprenom() + if not civilite: + civilite = r_civilite if not nom: nom = r_nom if not prenom: diff --git a/static/css/scodoc.css b/static/css/scodoc.css index 48dd4df816..deb9cf3c75 100644 --- a/static/css/scodoc.css +++ b/static/css/scodoc.css @@ -332,8 +332,7 @@ h2.listesems { margin-bottom: 0px; } -table.semlist tr.gt_firstrow th { -} +/* table.semlist tr.gt_firstrow th {} */ table.semlist tr td { border: none; @@ -690,8 +689,7 @@ a.stdlink:hover { text-decoration: underline; } -a.link_accessible { -} +/* a.link_accessible {} */ a.link_unauthorized, a.link_unauthorized:visited { color: rgb(75,75,75); } @@ -712,8 +710,8 @@ span.spanlink:hover { margin-bottom: 3px; -ms-word-break: break-all; word-break: break-all; - // non std for webkit: - work-break: break-word; + /* non std for webkit: */ + word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; @@ -913,9 +911,10 @@ span.eval_title { font-weight: bold; font-size: 14pt; } -#saisie_notes span.eval_title { - /* border-bottom: 1px solid rgb(100,100,100); */ +/* #saisie_notes span.eval_title { + border-bottom: 1px solid rgb(100,100,100); } +*/ span.jurylink { margin-left: 1.5em; @@ -1012,9 +1011,6 @@ h2.formsemestre, .gtrcontent h2 { border-width: 0; border-collapse: collapse; } -.formsemestre_page_title table.semtitle { - /* width: 100%; */ -} .formsemestre_page_title { width: 100%; @@ -1058,6 +1054,9 @@ h2.formsemestre, .gtrcontent h2 { #formnotes .tf-ro-field.formnote_bareme { font-weight: bold; } +#formnotes td.tf-fieldlabel { + border-bottom: 1px dotted #fdcaca; +} /* .formsemestre_menubar { border-top: 3px solid #67A7E3; @@ -1105,8 +1104,6 @@ h2.formsemestre, .gtrcontent h2 { width : 200px; } -.sco_dropdown_menu { -} .sco_dropdown_menu > li { width : auto; /* 120px !important; */ font-size: 12px; @@ -1133,10 +1130,6 @@ span.inscr_addremove_menu { font-weight: bold; padding-right: 1px; } -.formsemestre_page_title span.lock { - -} - div.formsemestre_status { -moz-border-radius: 8px; -khtml-border-radius: 8px; @@ -1227,10 +1220,6 @@ ul.ue_inscr_list li.etud { border-spacing: 1px; } -#grouplists td { -} - - /* Modules */ div.moduleimpl_tableaubord { padding: 7px; @@ -1264,20 +1253,10 @@ th.moduleimpl_evaluations a:hover { text-decoration: underline; } -tr.moduleimpl_evaluation_row { -} - -td.moduleimpl_evaluation_row { -} - tr.mievr { background-color:#eeeeee; } -tr.mievr_spaced { - /* margin-top: 20px; */ -} - tr.mievr_rattr { background-color:#dddddd; } @@ -1575,8 +1554,6 @@ tr.recap_row_min, tr.recap_row_max { font-weight: normal; font-style: italic; } -tr.recap_row_coef { -} tr.recap_row_moy { font-weight: bold; } @@ -1809,9 +1786,6 @@ div.bulletin_menubar { text-decoration: underline; } -div.bull_appreciations { -} - .bull_appreciations p { margin: 0; font-style: italic; @@ -1867,9 +1841,6 @@ input.note_saved { color: green; } -input.note { -} - span.history { font-style: italic; } @@ -2016,9 +1987,6 @@ td.fvs_val_inf { color: red; } -td.fvs_chk { -} - td.fvs_tit { font-weight: bold; text-align: left; @@ -2274,8 +2242,6 @@ table.recap_hide_details tr.sem_courant td.ue_acro span, table.recap_hide_detail padding-bottom: 5px; } -td.rcp_moy { -} td.sem_ects_tit { text-align: right; } @@ -2308,9 +2274,6 @@ td.ue_cmp { color: green; } -td.ue { -} - td.ue_capitalized { text-decoration: underline; } @@ -2354,9 +2317,6 @@ div.pas_sembox { font-family: arial,verdana,sans-serif; } -div.pas_empty_sems { -} - span.sp_etape { display: inline-block; width: 4em; @@ -2365,10 +2325,6 @@ span.sp_etape { color: black; } -.inscrit { -/* font-weight: bold; */ -} - .inscrailleurs { font-weight: bold; color: red !important; @@ -2534,9 +2490,6 @@ td.calday { vertical-align: top; } -div.cal_evaluations table.monthcalendar td.calcol { -} - div.cal_evaluations table.monthcalendar td.calcell { padding-left: 0.6em; width: 6em; @@ -2585,24 +2538,24 @@ div.update_warning_sub { padding-left: 8ex; } -/* Titres des tabs: */ -.nav-tabs li a { - /* font-variant: small-caps; */ - /*font-size: 13pt;*/ -} +/* + Titres des tabs: + .nav-tabs li a { + font-variant: small-caps; + font-size: 13pt; + } -/* -#group-tabs { - clear: both; -} + #group-tabs { + clear: both; + } -#group-tabs ul { - display: inline; -} + #group-tabs ul { + display: inline; + } -#group-tabs ul li { - display: inline; -} + #group-tabs ul li { + display: inline; + } */ /* Page accueil */ @@ -2758,10 +2711,6 @@ div.apo_csv_list { div.apo_compare_csv_form_but { margin-top: 10px; margin-bottom: 10px; -} -div.apo_compare_csv_form_submit { - - } div.apo_compare_csv_form_submit input { margin-top: 2ex; @@ -2892,12 +2841,9 @@ div#formsemestre_ext_edit_ue_validations { form.tf_ext_edit_ue_validations table { border-collapse: collapse; width: 97%; - margin-left: 1em;ext + margin-left: 1em; margin-right: 1em; } -form.tf_ext_edit_ue_validations table, form.tf_ext_edit_ue_validations table th, form.tf_ext_edit_ue_validations table td { - /* border: 1px solid black; */ -} form.tf_ext_edit_ue_validations table th, form.tf_ext_edit_ue_validations table td { border-bottom: 1px solid rgb(168, 168, 168); }