aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas "Cakeisalie5" Touhey <thomas@touhey.fr>2018-10-04 13:59:03 +0200
committerThomas "Cakeisalie5" Touhey <thomas@touhey.fr>2018-10-04 13:59:03 +0200
commitea182c4cba8b3b0127abdc4937be889bf7b121db (patch)
tree66988aa2fa11075e151ceedb02636e84f713aab1
parent0c722731c2f36352ec35a09588de9e8e4cec298d (diff)
Can automatically load functions from the intranet now.
-rwxr-xr-xsgdfi/__main__.py28
-rwxr-xr-xsgdfi/_db.py61
-rwxr-xr-xsgdfi/_dbs/__init__.py9
-rw-r--r--sgdfi/_dbs/_funcdata.py356
-rwxr-xr-xsgdfi/_dbs/_funcs.py464
-rw-r--r--sgdfi/_dbs/_regime.py26
-rwxr-xr-xsgdfi/_dbs/_st.py4
-rwxr-xr-xsgdfi/_dbs/_ststatus.py91
-rwxr-xr-xsgdfi/_manager.py406
-rwxr-xr-xsgdfi/_repr.py64
-rwxr-xr-xsgdfi/_session.py21
11 files changed, 1083 insertions, 447 deletions
diff --git a/sgdfi/__main__.py b/sgdfi/__main__.py
index 22916a2..f5ccfde 100755
--- a/sgdfi/__main__.py
+++ b/sgdfi/__main__.py
@@ -7,15 +7,20 @@
import os.path as _path
-def test_session():
- """ Test the session. """
+def get_session():
+ """ Get a logged in session. """
from . import Session as _Session
path = _path.join(_path.dirname(__file__), '..', '..', 'logins.txt')
user, pw = (x.splitlines()[0] for x in open(path).readlines())
- s = _Session(user = user, pw = pw, save = True)
+ return _Session(user = user, pw = pw, save = True)
+
+def test_session():
+ """ Test the session. """
+
+ s = get_session()
#ret = s.get_ops('4', "yCbyTmNDHpp8CotDhWoEkQ==")
#ret = s.get_place('ONCt5ZDoIUZIXlYv9QyGuw==')
@@ -32,7 +37,8 @@ def test_repr():
""" Test the representations. """
from datetime import datetime as _datetime
- from ._repr import Operation as _Operation, Adherent as _Adherent
+ from ._repr import Operation as _Operation, Adherent as _Adherent, \
+ Function as _Function
op = _Operation()
op.time = _datetime(2018, 10, 1, 0, 17, 38)
@@ -43,7 +49,7 @@ def test_repr():
ad = _Adherent()
ad.iid = "yCbyTmNDHpp8CotDhWoEkQ=="
- ad.name = "TOUHEY Thomas"
+ ad.function = _Function.CHEF_PIONNIER_CARAVELLE
op.related.add(ad)
@@ -70,11 +76,19 @@ def test_load():
else:
print(ret)
+def test_funcs():
+ """ Test getting the functions. """
+
+ s = get_session()
+
+ f = s.get_functions()
+ s.export_functions(f)
+
if __name__ == '__main__':
#test_repr()
- #test_repr2()
#test_session()
#test_save()
- test_load()
+ #test_load()
+ test_funcs()
# End of file.
diff --git a/sgdfi/_db.py b/sgdfi/_db.py
new file mode 100755
index 0000000..03359a5
--- /dev/null
+++ b/sgdfi/_db.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python3
+#******************************************************************************
+# Copyright (C) 2018 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
+# This file is part of the sgdfi project, which is MIT-licensed.
+#******************************************************************************
+""" This submodule defines the local database (or data manager) for managing
+ our knowledge of the intranet. """
+
+__all__ = ["Database"]
+
+class Database:
+ """ The internal class to manage all data. """
+
+ def __init__(self, cache_dir):
+ self.__cache_dir = cache_dir
+
+ # ---
+ # Save and load the database.
+ # ---
+
+ def save(self):
+ """ Save the database. """
+
+ # TODO
+ pass
+
+ def load(self):
+ """ Load the saved database. """
+
+ # TODO
+ pass
+
+ # ---
+ # Feed the database with fetched (and possibly incomplete) data.
+ # ---
+
+ def add_op(self, op):
+ """ Add an operation. """
+
+ # TODO
+ pass
+
+ def add_place(self, pl):
+ """ Add a place. """
+
+ # TODO
+ pass
+
+ def add_structure(self, st):
+ """ Add a structure. """
+
+ # TODO
+ pass
+
+ def add_adherent(self, ad):
+ """ Add an adherent. """
+
+ # TODO
+ pass
+
+# End of file.
diff --git a/sgdfi/_dbs/__init__.py b/sgdfi/_dbs/__init__.py
index d6f79a9..10f4180 100755
--- a/sgdfi/_dbs/__init__.py
+++ b/sgdfi/_dbs/__init__.py
@@ -5,8 +5,11 @@
#******************************************************************************
""" Databases for SGDFi. """
-from ._ops import OperationType, OperationTypeData
-from ._st import StructureType, StructureTypeData
-from ._funcs import Function, FunctionData
+from ._ops import OperationType, OperationTypeData
+from ._st import StructureType, StructureTypeData
+from ._ststatus import StructureStatus, StructureStatusData
+from ._funcs import Function, FunctionData, FunctionRawData
+
+from ._regime import AllocationsRegime
# End of file.
diff --git a/sgdfi/_dbs/_funcdata.py b/sgdfi/_dbs/_funcdata.py
new file mode 100644
index 0000000..b3e9fcc
--- /dev/null
+++ b/sgdfi/_dbs/_funcdata.py
@@ -0,0 +1,356 @@
+#!/usr/bin/env python3
+#******************************************************************************
+# Copyright (C) 2018 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
+# This file is part of the sgdfi project, which is MIT-licensed.
+#******************************************************************************
+""" Functions generated data for SGDFi. """
+
+from enum import Enum as _Enum
+
+class Function(_Enum):
+ """ Unknown function. """
+ UNKNOWN = 0
+
+ LOUVETEAU = 1
+ MOUSSAILLON = 2
+ SCOUT = 3
+ MOUSSE = 4
+ PIONNIER = 5
+ MARIN = 6
+ COMPAGNON = 7
+ COMPAGNON_MARIN = 8
+ COMPAGNON_3EME_TEMPS = 9
+ ECLAIREUR = 10
+ FARFADET = 11
+ MEMBRE_ASSOCIE_L = 12
+ MEMBRE_ASSOCIE_N = 13
+ MEMBRE_ASSOCIE_T = 14
+ VENT_DU_LARGE = 15
+ RESPONSABLE_D_UNITE_LOUVETEAU_JEANNETTE = 16
+ RESPONSABLE_D_UNITE_MOUSSAILLON = 17
+ CHEF_LOUVETEAU_JEANNETTE = 18
+ CHEF_MOUSSAILLON = 19
+ RESPONSABLE_D_UNITE_SCOUT_GUIDE = 20
+ RESPONSABLE_D_UNITE_MOUSSE = 21
+ CHEF_SCOUT_GUIDE = 22
+ CHEF_MOUSSE = 23
+ RESPONSABLE_D_UNITE_PIONNIER_CARAVELLE = 24
+ RESPONSABLE_D_UNITE_FLOTILLE_CARAVELLE_MARINE = 25
+ CHEF_PIONNIER_CARAVELLE = 26
+ CHEF_FLOTILLE_CARAVELLE_MARINE = 27
+ ACCOMPAGNATEUR_COMPAGNON = 28
+ RESPONSABLE_FARFADET = 29
+ PARENT_ANIMATEUR_FARFADET = 30
+ RESPONSABLE_VENT_DU_LARGE = 31
+ RESPONSABLE_DE_GROUPE = 32
+ RESPONSABLE_DE_GROUPE_ADJOINT = 33
+ AUMONIER_DE_GROUPE = 34
+ SECRETAIRE_DE_GROUPE = 35
+ TRESORIER_DE_GROUPE = 36
+ ANIMATEUR_CLEOPHAS_L = 37
+ CHARGE_DE_MISSION__DU_GROUPE = 38
+ REFERENT_TECHNIQUE_MARIN = 39
+ REPRESENTANT_ASSOCIATIF = 40
+ OUVREUR_DE_GROUPE_L = 41
+ DIRECTEUR_DE_CAMP = 42
+ RESPONSABLE_LOCAL_DEVELOPPEMENT_ET_RESEAUX = 43
+ FF_TRESORIER_DE_GROUPE = 44
+ NOMINATION_DES_CHEFS_ET_EQUIPIERS_DE_GROUPE = 45
+ FF_RESPONSABLE_DE_GROUPE = 46
+ DELEGUE_TERRITORIAL = 47
+ DELEGUE_TERRITORIAL_ADJOINT = 48
+ AUMONIER_TERRITORIAL = 49
+ RESPONSABLE_POLE_PEDAGOGIQUE = 50
+ RESPONSABLE_POLE_DEVELOPPEMENT = 51
+ RESPONSABLE_POLE_ADMINISTRATIF_ET_FINANCIER = 52
+ FF_RESPONSABLE_POLE_ADMINISTRATIF_ET_FINANCIER = 53
+ NOMINATION_DES_EQUIPIERS_TERRITORIAUX = 54
+ FF_DELEGUE_TERRITORIAL = 55
+ ACCOMPAGNATEUR_PEDAGOGIQUE = 56
+ AUMONIER_DIOCESAIN = 57
+ ACCOMPAGNATEUR_DES_RESPONSABLES_DE_GROUPE = 58
+ ANIMATEUR_CLEOPHAS_T = 59
+ CHARGE_MISSION_DEVELOPPEMENT = 60
+ COORDINATEUR_DEVELOPPEMENT_ET_RESEAUX = 61
+ OUVREUR_DE_GROUPE_T = 62
+ RESPONSABLE_RECRUTEMENT = 63
+ RESPONSABLE_PARTENARIATS_FINANCIERS = 64
+ RESPONSABLE_COMMUNICATION = 65
+ CORRESPONDANT_HANDICAP = 66
+ RESPONSABLE_SCOUTISME_EN_QUARTIER = 67
+ CHARGE_MISSION_TERRITORIAL = 68
+ MEDIATEUR_T = 69
+ REPRESENTANT_ASSOCIATIF_L = 70
+ RESPONSABLE_BOUTIQUE_SGDF = 71
+ DIRECTEUR_DE_CAMP_TERRITORIAL = 72
+ TRESORIER_DE_BOUTIQUE = 73
+ CHARGE_DE_MISSION_RASSEMBLEMENT = 74
+ CHARGE_MISSION_ADMINISTRATIF = 75
+ GESTIONNAIRE_MATERIEL_ET_LOGISTIQUE = 76
+ TRESORIER_DE_BASE = 77
+ EQUIPIER_DE_BASE = 78
+ RESPONSABLE_DE_BASE = 79
+ SECRETAIRE_TERRITORIAL = 80
+ CHARGE_DE_MISSION_RW2016_T = 81
+ TRESORIER_TERRITORIAL = 82
+ FF_TRESORIER_TERRITORIAL = 83
+ DIRECTEUR_DE_STAGE = 84
+ DIRECTEUR_DE_CAMP_GROUPE = 85
+ VOLONTAIRE_SERVICE_CIVIQUE = 86
+ VOLONTAIRE_SERVICE_INTERNATIONAL = 87
+ DELEGUE_GENERAL = 88
+ DELEGUE_GENERAL_ADJOINT = 89
+ AUMONIER_GENERAL = 90
+ DELEGUE_NATIONAL = 91
+ RESPONSABLE_NATIONAL = 92
+ AUMONIER_NATIONAL = 93
+ EQUIPIER_NATIONAL = 94
+ RESPONSABLE_DE_LA_FORMATION_CR = 95
+ CHARGE_MISSION = 96
+ CHARGE_MISSION_PAYS = 97
+ ADMINISTRATEUR = 98
+ MEMBRE_D_HONNEUR = 99
+ MEDIATEUR_N = 100
+ REPRESENTANT_ASSOCIATIF_T = 101
+ SALARIE = 102
+ SALARIE_FORMATION = 103
+ SALARIE_SERVICE_INTERNATIONAL = 104
+ CONSULTANT_BATEAU = 105
+ ASSISTANT_DE_SAISIE = 106
+ CHARGE_DE_MISSION_RW2016_N = 107
+ CHARGE_DE_MISSION_RASSEMBLEMENT_EN = 108
+ ADMINISTRATEUR_MODULE_FORMATION = 109
+ CONSULTANT_INTEGRATION = 110
+ SALARIE_COMPTABILITE = 111
+ SALARIE_ASSURANCE = 112
+ ADMINISTRATEUR_ASSURANCE = 113
+ SALARIE_CENTRE_DE_RESSOURCES = 114
+ ADMINISTRATEUR_COMPTABILITE = 115
+ DIRECTEUR_DE_CENTRE_DE_RESSOURCES = 116
+ RESPONSABLE_ADMINISTRATIF_CR = 117
+ ANIMATION_TERRITORIALE_ET_DEVELOPPEMENT = 118
+ ADMINISTRATEUR_INTRANET = 119
+ MONITORING_APPLICATIF = 120
+
+FunctionData = {
+ Function.LOUVETEAU: ("110", 8434, 'LOUVETEAU', 'JEANNETTE'),
+ Function.MOUSSAILLON: ("110M", 8435, 'MOUSSAILLON'),
+ Function.SCOUT: ("120", 8440, 'SCOUT', 'GUIDE'),
+ Function.MOUSSE: ("120M", 8441, 'MOUSSE'),
+ Function.PIONNIER: ("130", 8487, 'PIONNIER', 'CARAVELLE'),
+ Function.MARIN: ("130M", 8488, 'MARIN', 'CARAVELLE MARINE'),
+ Function.COMPAGNON: ("140", 8493, 'COMPAGNON'),
+ Function.COMPAGNON_MARIN: ("140M", 8494, 'COMPAGNON MARIN'),
+ Function.COMPAGNON_3EME_TEMPS: ("141", 8495, 'COMPAGNON 3EME TEMPS'),
+ Function.ECLAIREUR: ("150", 8501, 'ECLAIREUR', 'ECLAIREUSE'),
+ Function.FARFADET: ("170", 8497, 'FARFADET'),
+ Function.MEMBRE_ASSOCIE_L: ("180L", 8439, 'MEMBRE ASSOCIE',
+ 'MEMBRE ASSOCIEE'),
+ Function.MEMBRE_ASSOCIE_N: ("180N", 8445, 'MEMBRE ASSOCIE',
+ 'MEMBRE ASSOCIEE'),
+ Function.MEMBRE_ASSOCIE_T: ("180T", 8438, 'MEMBRE ASSOCIE',
+ 'MEMBRE ASSOCIEE'),
+ Function.VENT_DU_LARGE: ("193", 8499, 'VENT DU LARGE'),
+ Function.RESPONSABLE_D_UNITE_LOUVETEAU_JEANNETTE: ("210", 8436,
+ "RESPONSABLE D'UNITE LOUVETEAU JEANNETTE"),
+ Function.RESPONSABLE_D_UNITE_MOUSSAILLON: ("210M", 8550,
+ "RESPONSABLE D'UNITE MOUSSAILLON"),
+ Function.CHEF_LOUVETEAU_JEANNETTE: ("213", 8551,
+ 'CHEF LOUVETEAU JEANNETTE', 'CHEFTAINE LOUVETEAU JEANNETTE'),
+ Function.CHEF_MOUSSAILLON: ("213M", 8552, 'CHEF MOUSSAILLON',
+ 'CHEFTAINE MOUSSAILLON'),
+ Function.RESPONSABLE_D_UNITE_SCOUT_GUIDE: ("220", 8442,
+ "RESPONSABLE D'UNITE SCOUT GUIDE"),
+ Function.RESPONSABLE_D_UNITE_MOUSSE: ("220M", 8484,
+ "RESPONSABLE D'UNITE MOUSSE"),
+ Function.CHEF_SCOUT_GUIDE: ("223", 8485, 'CHEF SCOUT GUIDE',
+ 'CHEFTAINE SCOUT GUIDE'),
+ Function.CHEF_MOUSSE: ("223M", 8486, 'CHEF MOUSSE',
+ 'CHEFTAINE MOUSSE'),
+ Function.RESPONSABLE_D_UNITE_PIONNIER_CARAVELLE: ("230", 8489,
+ "RESPONSABLE D'UNITE PIONNIER CARAVELLE"),
+ Function.RESPONSABLE_D_UNITE_FLOTILLE_CARAVELLE_MARINE: ("230M", 8490,
+ "RESPONSABLE D'UNITE FLOTILLE - CARAVELLE MARINE"),
+ Function.CHEF_PIONNIER_CARAVELLE: ("233", 8491,
+ 'CHEF PIONNIER CARAVELLE', 'CHEFTAINE PIONNIER CARAVELLE'),
+ Function.CHEF_FLOTILLE_CARAVELLE_MARINE: ("233M", 8492,
+ 'CHEF FLOTILLE - CARAVELLE MARINE',
+ 'CHEFTAINE FLOTILLE - CARAVELLE MARINE'),
+ Function.ACCOMPAGNATEUR_COMPAGNON: ("240", 8496,
+ 'ACCOMPAGNATEUR COMPAGNON', 'ACCOMPAGNATRICE COMPAGNON'),
+ Function.RESPONSABLE_FARFADET: ("270", 8498, 'RESPONSABLE FARFADET'),
+ Function.PARENT_ANIMATEUR_FARFADET: ("271", 8554,
+ 'PARENT ANIMATEUR FARFADET'),
+ Function.RESPONSABLE_VENT_DU_LARGE: ("293", 8500,
+ 'RESPONSABLE VENT DU LARGE'),
+ Function.RESPONSABLE_DE_GROUPE: ("300", 8502,
+ 'RESPONSABLE DE GROUPE'),
+ Function.RESPONSABLE_DE_GROUPE_ADJOINT: ("301", 8503,
+ 'RESPONSABLE DE GROUPE ADJOINT', 'RESPONSABLE DE GROUPE ADJOINTE'),
+ Function.AUMONIER_DE_GROUPE: ("302", 8504, 'AUMONIER DE GROUPE'),
+ Function.SECRETAIRE_DE_GROUPE: ("307", 8506, 'SECRETAIRE DE GROUPE'),
+ Function.TRESORIER_DE_GROUPE: ("309", 8508, 'TRESORIER DE GROUPE',
+ 'TRESORIERE DE GROUPE'),
+ Function.ANIMATEUR_CLEOPHAS_L: ("316", 8509, 'ANIMATEUR CLEOPHAS',
+ 'ANIMATRICE CLEOPHAS'),
+ Function.CHARGE_DE_MISSION__DU_GROUPE: ("330", 8511,
+ 'CHARGE DE MISSION DU GROUPE', 'CHARGEE DE MISSION DU GROUPE'),
+ Function.REFERENT_TECHNIQUE_MARIN: ("330M", 8512,
+ 'REFERENT TECHNIQUE MARIN', 'REFERENTE TECHNIQUE MARIN'),
+ Function.REPRESENTANT_ASSOCIATIF_L: ("332", 8513,
+ 'REPRESENTANT ASSOCIATIF'),
+ Function.OUVREUR_DE_GROUPE_L: ("333", 8516, 'OUVREUR DE GROUPE'),
+ Function.DIRECTEUR_DE_CAMP: ("351", 8517, 'DIRECTEUR DE CAMP',
+ 'DIRECTRICE DE CAMP'),
+ Function.RESPONSABLE_LOCAL_DEVELOPPEMENT_ET_RESEAUX: ("380", 8518,
+ 'RESPONSABLE LOCAL DEVELOPPEMENT ET RESEAUX'),
+ Function.FF_TRESORIER_DE_GROUPE: ("391", 8519,
+ 'FF TRESORIER DE GROUPE', 'FF TRESORIERE DE GROUPE'),
+ Function.NOMINATION_DES_CHEFS_ET_EQUIPIERS_DE_GROUPE: ("397", 8480,
+ 'NOMINATION DES CHEFS ET EQUIPIERS DE GROUPE'),
+ Function.FF_RESPONSABLE_DE_GROUPE: ("399", 8520,
+ 'FF RESPONSABLE DE GROUPE'),
+ Function.DELEGUE_TERRITORIAL: ("500", 8482, 'DELEGUE TERRITORIAL',
+ 'DELEGUEE TERRITORIALE'),
+ Function.DELEGUE_TERRITORIAL_ADJOINT: ("501", 8481,
+ 'DELEGUE TERRITORIAL ADJOINT', 'DELEGUEE TERRITORIALE ADJOINTE'),
+ Function.AUMONIER_TERRITORIAL: ("502", 8505, 'AUMONIER TERRITORIAL'),
+ Function.RESPONSABLE_POLE_PEDAGOGIQUE: ("503", 8521,
+ 'RESPONSABLE POLE PEDAGOGIQUE'),
+ Function.RESPONSABLE_POLE_DEVELOPPEMENT: ("504", 8522,
+ 'RESPONSABLE POLE DEVELOPPEMENT'),
+ Function.RESPONSABLE_POLE_ADMINISTRATIF_ET_FINANCIER: ("505", 8515,
+ 'RESPONSABLE POLE ADMINISTRATIF ET FINANCIER'),
+ Function.FF_RESPONSABLE_POLE_ADMINISTRATIF_ET_FINANCIER: ("591", 8514,
+ 'FF RESPONSABLE POLE ADMINISTRATIF ET FINANCIER'),
+ Function.NOMINATION_DES_EQUIPIERS_TERRITORIAUX: ("597", 8507,
+ 'NOMINATION DES EQUIPIERS TERRITORIAUX'),
+ Function.FF_DELEGUE_TERRITORIAL: ("598", 8483,
+ 'FF DELEGUE TERRITORIAL', 'FF DELEGUEE TERRITORIALE'),
+ Function.ACCOMPAGNATEUR_PEDAGOGIQUE: ("600", 8523,
+ 'ACCOMPAGNATEUR PEDAGOGIQUE', 'ACCOMPAGNATRICE PEDAGOGIQUE'),
+ Function.AUMONIER_DIOCESAIN: ("602", 8510, 'AUMONIER DIOCESAIN'),
+ Function.ACCOMPAGNATEUR_DES_RESPONSABLES_DE_GROUPE: ("609", 8524,
+ 'ACCOMPAGNATEUR DES RESPONSABLES DE GROUPE'),
+ Function.ANIMATEUR_CLEOPHAS_T: ("616", 8525, 'ANIMATEUR CLEOPHAS',
+ 'ANIMATRICE CLEOPHAS'),
+ Function.CHARGE_MISSION_DEVELOPPEMENT: ("620", 8526,
+ 'CHARGE MISSION DEVELOPPEMENT', 'CHARGEE MISSION DEVELOPPEMENT'),
+ Function.COORDINATEUR_DEVELOPPEMENT_ET_RESEAUX: ("621", 8527,
+ 'COORDINATEUR DEVELOPPEMENT ET RESEAUX',
+ 'COORDINATRICE DEVELOPPEMENT ET RESEAUX'),
+ Function.OUVREUR_DE_GROUPE_T: ("622", 8528, 'OUVREUR DE GROUPE'),
+ Function.RESPONSABLE_RECRUTEMENT: ("623", 8529,
+ 'RESPONSABLE RECRUTEMENT'),
+ Function.RESPONSABLE_PARTENARIATS_FINANCIERS: ("624", 8530,
+ 'RESPONSABLE PARTENARIATS FINANCIERS'),
+ Function.RESPONSABLE_COMMUNICATION: ("625", 8531,
+ 'RESPONSABLE COMMUNICATION'),
+ Function.CORRESPONDANT_HANDICAP: ("626", 8532,
+ 'CORRESPONDANT HANDICAP'),
+ Function.RESPONSABLE_SCOUTISME_EN_QUARTIER: ("627", 8533,
+ 'RESPONSABLE SCOUTISME EN QUARTIER'),
+ Function.CHARGE_MISSION_TERRITORIAL: ("630", 8534,
+ 'CHARGE MISSION TERRITORIAL', 'CHARGEE MISSION TERRITORIALE'),
+ Function.MEDIATEUR_T: ("631", 8535, 'MEDIATEUR', 'MEDIATRICE'),
+ Function.REPRESENTANT_ASSOCIATIF_T: ("632", 8536,
+ 'REPRESENTANT ASSOCIATIF', 'REPRESENTANTE ASSOCIATIF'),
+ Function.RESPONSABLE_BOUTIQUE_SGDF: ("650", 8537,
+ 'RESPONSABLE BOUTIQUE SGDF'),
+ Function.DIRECTEUR_DE_CAMP_TERRITORIAL: ("651", 8538,
+ 'DIRECTEUR DE CAMP TERRITORIAL', 'DIRECTRICE DE CAMP TERRITORIAL'),
+ Function.TRESORIER_DE_BOUTIQUE: ("652", 8539, 'TRESORIER DE BOUTIQUE',
+ 'TRESORIERE DE BOUTIQUE'),
+ Function.CHARGE_DE_MISSION_RASSEMBLEMENT: ("659", 8540,
+ 'CHARGE DE MISSION RASSEMBLEMENT'),
+ Function.CHARGE_MISSION_ADMINISTRATIF: ("660", 8541,
+ 'CHARGE MISSION ADMINISTRATIF', 'CHARGEE MISSION ADMINISTRATIF'),
+ Function.GESTIONNAIRE_MATERIEL_ET_LOGISTIQUE: ("661", 8542,
+ 'GESTIONNAIRE MATERIEL ET LOGISTIQUE'),
+ Function.TRESORIER_DE_BASE: ("663", 8543, 'TRESORIER DE BASE',
+ 'TRESORIERE DE BASE'),
+ Function.EQUIPIER_DE_BASE: ("664", 8544, 'EQUIPIER DE BASE',
+ 'EQUIPIERE DE BASE'),
+ Function.RESPONSABLE_DE_BASE: ("665", 8545, 'RESPONSABLE DE BASE'),
+ Function.SECRETAIRE_TERRITORIAL: ("670", 8546,
+ 'SECRETAIRE TERRITORIAL', 'SECRETAIRE TERRITORIALE'),
+ Function.CHARGE_DE_MISSION_RW2016_T: ("685", 8547,
+ 'CHARGE DE MISSION RW2016 T', 'CHARGEE DE MISSION RW2016 T'),
+ Function.TRESORIER_TERRITORIAL: ("690", 8548, 'TRESORIER TERRITORIAL',
+ 'TRESORIERE TERRITORIALE'),
+ Function.FF_TRESORIER_TERRITORIAL: ("691", 8549,
+ 'FF TRESORIER TERRITORIAL', 'FF TRESORIERE TERRITORIAL'),
+ Function.DIRECTEUR_DE_STAGE: ("850", 8446, 'DIRECTEUR DE STAGE',
+ 'DIRECTRICE DE STAGE'),
+ Function.DIRECTEUR_DE_CAMP_GROUPE: ("851", 8447,
+ 'DIRECTEUR DE CAMP GROUPE', 'DIRECTRICE DE CAMP GROUPE'),
+ Function.VOLONTAIRE_SERVICE_CIVIQUE: ("860", 8451,
+ 'VOLONTAIRE SERVICE CIVIQUE'),
+ Function.VOLONTAIRE_SERVICE_INTERNATIONAL: ("861", 8452,
+ 'VOLONTAIRE SERVICE INTERNATIONAL'),
+ Function.DELEGUE_GENERAL: ("900", 8449, 'DELEGUE GENERAL',
+ 'DELEGUEE GENERALE'),
+ Function.DELEGUE_GENERAL_ADJOINT: ("901", 8450,
+ 'DELEGUE GENERAL ADJOINT', 'DELEGUEE GENERALE ADJOINTE'),
+ Function.AUMONIER_GENERAL: ("902", 8453, 'AUMONIER GENERAL'),
+ Function.DELEGUE_NATIONAL: ("903", 8454, 'DELEGUE NATIONAL',
+ 'DELEGUEE NATIONALE'),
+ Function.RESPONSABLE_NATIONAL: ("910", 8448, 'RESPONSABLE NATIONAL',
+ 'RESPONSABLE NATIONALE'),
+ Function.AUMONIER_NATIONAL: ("911", 8455, 'AUMONIER NATIONAL'),
+ Function.EQUIPIER_NATIONAL: ("912", 8456, 'EQUIPIER NATIONAL',
+ 'EQUIPIERE NATIONALE'),
+ Function.RESPONSABLE_DE_LA_FORMATION_CR: ("913", 8457,
+ 'RESPONSABLE DE LA FORMATION CR'),
+ Function.CHARGE_MISSION: ("914", 8458, 'CHARGE MISSION',
+ 'CHARGEE MISSION'),
+ Function.CHARGE_MISSION_PAYS: ("915", 8459, 'CHARGE MISSION PAYS',
+ 'CHARGEE MISSION PAYS'),
+ Function.ADMINISTRATEUR: ("920", 8460, 'ADMINISTRATEUR',
+ 'ADMINISTRATRICE'),
+ Function.MEMBRE_D_HONNEUR: ("921", 8461, 'MEMBRE D HONNEUR'),
+ Function.MEDIATEUR_N: ("931", 8462, 'MEDIATEUR', 'MEDIATRICE'),
+ Function.REPRESENTANT_ASSOCIATIF: ("932", 8463,
+ 'REPRESENTANT ASSOCIATIF', 'REPRESENTANTE ASSOCIATIF'),
+ Function.SALARIE: ("980", 8464, 'SALARIE', 'SALARIEE'),
+ Function.SALARIE_FORMATION: ("981", 8465, 'SALARIE FORMATION',
+ 'SALARIEE FORMATION'),
+ Function.SALARIE_SERVICE_INTERNATIONAL: ("982", 8466,
+ 'SALARIE SERVICE INTERNATIONAL', 'SALARIEE SERVICE INTERNATIONAL'),
+ Function.CONSULTANT_BATEAU: ("983", 8467, 'CONSULTANT BATEAU',
+ 'CONSULTANTE BATEAU'),
+ Function.ASSISTANT_DE_SAISIE: ("984", 8468, 'ASSISTANT DE SAISIE',
+ 'ASSISTANTE DE SAISIE'),
+ Function.CHARGE_DE_MISSION_RW2016_N: ("985", 8469,
+ 'CHARGE DE MISSION RW2016 N', 'CHARGEE DE MISSION RW2016 N'),
+ Function.CHARGE_DE_MISSION_RASSEMBLEMENT_EN: ("987", 8470,
+ 'CHARGE DE MISSION RASSEMBLEMENT EN',
+ 'CHARGEE DE MISSION RASSEMBLEMENT EN'),
+ Function.ADMINISTRATEUR_MODULE_FORMATION: ("989", 8471,
+ 'ADMINISTRATEUR MODULE FORMATION', 'ADMINISTRATRICE MODULE FORMATION'),
+ Function.CONSULTANT_INTEGRATION: ("990", 8472,
+ 'Consultant Intégration', 'Consultante Intégration'),
+ Function.SALARIE_COMPTABILITE: ("991", 8473, 'SALARIE COMPTABILITE',
+ 'SALARIEE COMPTABILITE'),
+ Function.SALARIE_ASSURANCE: ("992", 8474, 'SALARIE ASSURANCE',
+ 'SALARIEE ASSURANCE'),
+ Function.ADMINISTRATEUR_ASSURANCE: ("993", 8475,
+ 'ADMINISTRATEUR ASSURANCE', 'ADMINISTRATRICE ASSURANCE'),
+ Function.SALARIE_CENTRE_DE_RESSOURCES: ("994", 8476,
+ 'SALARIE CENTRE DE RESSOURCES', 'SALARIEE CENTRE DE RESSOURCES'),
+ Function.ADMINISTRATEUR_COMPTABILITE: ("995", 8477,
+ 'ADMINISTRATEUR COMPTABILITE', 'ADMINISTRATRICE COMPTABILITE'),
+ Function.DIRECTEUR_DE_CENTRE_DE_RESSOURCES: ("996", 8478,
+ 'DIRECTEUR DE CENTRE DE RESSOURCES',
+ 'DIRECTRICE DE CENTRE DE RESSOURCES'),
+ Function.RESPONSABLE_ADMINISTRATIF_CR: ("997", 8444,
+ 'RESPONSABLE ADMINISTRATIF CR', 'RESPONSABLE ADMINISTRATIVE CR'),
+ Function.ANIMATION_TERRITORIALE_ET_DEVELOPPEMENT: ("998", 8443,
+ 'ANIMATION TERRITORIALE ET DEVELOPPEMENT'),
+ Function.ADMINISTRATEUR_INTRANET: ("999", 8437,
+ 'ADMINISTRATEUR INTRANET', 'ADMINISTRATRICE INTRANET'),
+ Function.MONITORING_APPLICATIF: ("9XX", 8479,
+ 'Monitoring applicatif'),
+}
+
+# End of file.
diff --git a/sgdfi/_dbs/_funcs.py b/sgdfi/_dbs/_funcs.py
index 5162175..9440c38 100755
--- a/sgdfi/_dbs/_funcs.py
+++ b/sgdfi/_dbs/_funcs.py
@@ -5,363 +5,16 @@
#******************************************************************************
""" Functions reference for SGDFi. """
-from enum import Enum as _Enum, unique as _unique
-
-__all__ = ["Function", "FunctionData"]
-
-@_unique
-class Function(_Enum):
- """ Unknown function. """
- UNKNOWN = 0
-
- LOUVETEAU = 1
- MOUSSAILLON = 2
- SCOUT = 3
- MOUSSE = 4
- PIONNIER = 5
- MARIN = 6
- COMPAGNON = 7
- COMPAGNON_MARIN = 8
- COMPAGNON_3EME_TEMPS = 9
- ECLAIREUR = 10
- FARFADET = 11
- MEMBRE_ASSOCIE_L = 12
- MEMBRE_ASSOCIE_N = 13
- MEMBRE_ASSOCIE_T = 14
- VENT_DU_LARGE = 15
- RESPONSABLE_D_UNITE_LOUVETEAU_JEANNETTE = 16
- RESPONSABLE_D_UNITE_MOUSSAILLON = 17
- CHEF_LOUVETEAU_JEANNETTE = 18
- CHEF_MOUSSAILLON = 19
- RESPONSABLE_D_UNITE_SCOUT_GUIDE = 20
- RESPONSABLE_D_UNITE_MOUSSE = 21
- CHEF_SCOUT_GUIDE = 22
- CHEF_MOUSSE = 23
- RESPONSABLE_D_UNITE_PIONNIER_CARAVELLE = 24
- RESPONSABLE_D_UNITE_FLOTILLE_CARAVELLE_MARINE = 25
- CHEF_PIONNIER_CARAVELLE = 26
- CHEF_FLOTILLE_CARAVELLE_MARINE = 27
- ACCOMPAGNATEUR_COMPAGNON = 28
- RESPONSABLE_FARFADET = 29
- PARENT_ANIMATEUR_FARFADET = 30
- RESPONSABLE_VENT_DU_LARGE = 31
- RESPONSABLE_DE_GROUPE = 32
- RESPONSABLE_DE_GROUPE_ADJOINT = 33
- AUMONIER_DE_GROUPE = 34
- SECRETAIRE_DE_GROUPE = 35
- TRESORIER_DE_GROUPE = 36
- ANIMATEUR_CLEOPHAS_L = 37
- CHARGE_DE_MISSION__DU_GROUPE = 38
- REFERENT_TECHNIQUE_MARIN = 39
- REPRESENTANT_ASSOCIATIF = 40
- OUVREUR_DE_GROUPE_L = 41
- DIRECTEUR_DE_CAMP = 42
- RESPONSABLE_LOCAL_DEVELOPPEMENT_ET_RESEAUX = 43
- FF_TRESORIER_DE_GROUPE = 44
- NOMINATION_DES_CHEFS_ET_EQUIPIERS_DE_GROUPE = 45
- FF_RESPONSABLE_DE_GROUPE = 46
- DELEGUE_TERRITORIAL = 47
- DELEGUE_TERRITORIAL_ADJOINT = 48
- AUMONIER_TERRITORIAL = 49
- RESPONSABLE_POLE_PEDAGOGIQUE = 50
- RESPONSABLE_POLE_DEVELOPPEMENT = 51
- RESPONSABLE_POLE_ADMINISTRATIF_ET_FINANCIER = 52
- FF_RESPONSABLE_POLE_ADMINISTRATIF_ET_FINANCIER = 53
- NOMINATION_DES_EQUIPIERS_TERRITORIAUX = 54
- FF_DELEGUE_TERRITORIAL = 55
- ACCOMPAGNATEUR_PEDAGOGIQUE = 56
- AUMONIER_DIOCESAIN = 57
- ACCOMPAGNATEUR_DES_RESPONSABLES_DE_GROUPE = 58
- ANIMATEUR_CLEOPHAS_T = 59
- CHARGE_MISSION_DEVELOPPEMENT = 60
- COORDINATEUR_DEVELOPPEMENT_ET_RESEAUX = 61
- OUVREUR_DE_GROUPE_T = 62
- RESPONSABLE_RECRUTEMENT = 63
- RESPONSABLE_PARTENARIATS_FINANCIERS = 64
- RESPONSABLE_COMMUNICATION = 65
- CORRESPONDANT_HANDICAP = 66
- RESPONSABLE_SCOUTISME_EN_QUARTIER = 67
- CHARGE_MISSION_TERRITORIAL = 68
- MEDIATEUR_T = 69
- REPRESENTANT_ASSOCIATIF_L = 70
- RESPONSABLE_BOUTIQUE_SGDF = 71
- DIRECTEUR_DE_CAMP_TERRITORIAL = 72
- TRESORIER_DE_BOUTIQUE = 73
- CHARGE_DE_MISSION_RASSEMBLEMENT = 74
- CHARGE_MISSION_ADMINISTRATIF = 75
- GESTIONNAIRE_MATERIEL_ET_LOGISTIQUE = 76
- TRESORIER_DE_BASE = 77
- EQUIPIER_DE_BASE = 78
- RESPONSABLE_DE_BASE = 79
- SECRETAIRE_TERRITORIAL = 80
- CHARGE_DE_MISSION_RW2016_T = 81
- TRESORIER_TERRITORIAL = 82
- FF_TRESORIER_TERRITORIAL = 83
- DIRECTEUR_DE_STAGE = 84
- DIRECTEUR_DE_CAMP_GROUPE = 85
- VOLONTAIRE_SERVICE_CIVIQUE = 86
- VOLONTAIRE_SERVICE_INTERNATIONAL = 87
- DELEGUE_GENERAL = 88
- DELEGUE_GENERAL_ADJOINT = 89
- AUMONIER_GENERAL = 90
- DELEGUE_NATIONAL = 91
- RESPONSABLE_NATIONAL = 92
- AUMONIER_NATIONAL = 93
- EQUIPIER_NATIONAL = 94
- RESPONSABLE_DE_LA_FORMATION_CR = 95
- CHARGE_MISSION = 96
- CHARGE_MISSION_PAYS = 97
- ADMINISTRATEUR = 98
- MEMBRE_D_HONNEUR = 99
- MEDIATEUR_N = 100
- REPRESENTANT_ASSOCIATIF_T = 101
- SALARIE = 102
- SALARIE_FORMATION = 103
- SALARIE_SERVICE_INTERNATIONAL = 104
- CONSULTANT_BATEAU = 105
- ASSISTANT_DE_SAISIE = 106
- CHARGE_DE_MISSION_RW2016_N = 107
- CHARGE_DE_MISSION_RASSEMBLEMENT_EN = 108
- ADMINISTRATEUR_MODULE_FORMATION = 109
- CONSULTANT_INTEGRATION = 110
- SALARIE_COMPTABILITE = 111
- SALARIE_ASSURANCE = 112
- ADMINISTRATEUR_ASSURANCE = 113
- SALARIE_CENTRE_DE_RESSOURCES = 114
- ADMINISTRATEUR_COMPTABILITE = 115
- DIRECTEUR_DE_CENTRE_DE_RESSOURCES = 116
- RESPONSABLE_ADMINISTRATIF_CR = 117
- ANIMATION_TERRITORIALE_ET_DEVELOPPEMENT = 118
- ADMINISTRATEUR_INTRANET = 119
- MONITORING_APPLICATIF = 120
-
-# Each entry in `FunctionData` has the function identifier as the key, and
-# a data composed of the following components:
-# - `c`: the intranet code (e.g. "120", "110M", "9XX", …).
-# - `ii`: the intranet internal identifier (e.g. "8434", "8437", …).
-# - `nm`: the masculin name for the function.
-# - `nf` (opt.): the feminine name for the function.
+from ._funcdata import Function, FunctionData as _FunctionData
-_FunctionData = {
- Function.LOUVETEAU: ("110", 8434, 'LOUVETEAU', 'JEANNETTE'),
- Function.MOUSSAILLON: ("110M", 8435, 'MOUSSAILLON'),
- Function.SCOUT: ("120", 8440, 'SCOUT', 'GUIDE'),
- Function.MOUSSE: ("120M", 8441, 'MOUSSE'),
- Function.PIONNIER: ("130", 8487, 'PIONNIER', 'CARAVELLE'),
- Function.MARIN: ("130M", 8488, 'MARIN', 'CARAVELLE MARINE'),
- Function.COMPAGNON: ("140", 8493, 'COMPAGNON'),
- Function.COMPAGNON_MARIN: ("140M", 8494, 'COMPAGNON MARIN'),
- Function.COMPAGNON_3EME_TEMPS: ("141", 8495, 'COMPAGNON 3EME TEMPS'),
- Function.ECLAIREUR: ("150", 8501, 'ECLAIREUR', 'ECLAIREUSE'),
- Function.FARFADET: ("170", 8497, 'FARFADET'),
- Function.MEMBRE_ASSOCIE_L: ("180L", 8439, 'MEMBRE ASSOCIE',
- 'MEMBRE ASSOCIEE'),
- Function.MEMBRE_ASSOCIE_N: ("180N", 8445, 'MEMBRE ASSOCIE',
- 'MEMBRE ASSOCIEE'),
- Function.MEMBRE_ASSOCIE_T: ("180T", 8438, 'MEMBRE ASSOCIE',
- 'MEMBRE ASSOCIEE'),
- Function.VENT_DU_LARGE: ("193", 8499, 'VENT DU LARGE'),
- Function.RESPONSABLE_D_UNITE_LOUVETEAU_JEANNETTE: ("210", 8436,
- "RESPONSABLE D'UNITE LOUVETEAU JEANNETTE"),
- Function.RESPONSABLE_D_UNITE_MOUSSAILLON: ("210M", 8550,
- "RESPONSABLE D'UNITE MOUSSAILLON"),
- Function.CHEF_LOUVETEAU_JEANNETTE: ("213", 8551,
- 'CHEF LOUVETEAU JEANNETTE', 'CHEFTAINE LOUVETEAU JEANNETTE'),
- Function.CHEF_MOUSSAILLON: ("213M", 8552, 'CHEF MOUSSAILLON',
- 'CHEFTAINE MOUSSAILLON'),
- Function.RESPONSABLE_D_UNITE_SCOUT_GUIDE: ("220", 8442,
- "RESPONSABLE D'UNITE SCOUT GUIDE"),
- Function.RESPONSABLE_D_UNITE_MOUSSE: ("220M", 8484,
- "RESPONSABLE D'UNITE MOUSSE"),
- Function.CHEF_SCOUT_GUIDE: ("223", 8485, 'CHEF SCOUT GUIDE',
- 'CHEFTAINE SCOUT GUIDE'),
- Function.CHEF_MOUSSE: ("223M", 8486, 'CHEF MOUSSE',
- 'CHEFTAINE MOUSSE'),
- Function.RESPONSABLE_D_UNITE_PIONNIER_CARAVELLE: ("230", 8489,
- "RESPONSABLE D'UNITE PIONNIER CARAVELLE"),
- Function.RESPONSABLE_D_UNITE_FLOTILLE_CARAVELLE_MARINE: ("230M", 8490,
- "RESPONSABLE D'UNITE FLOTILLE - CARAVELLE MARINE"),
- Function.CHEF_PIONNIER_CARAVELLE: ("233", 8491,
- 'CHEF PIONNIER CARAVELLE', 'CHEFTAINE PIONNIER CARAVELLE'),
- Function.CHEF_FLOTILLE_CARAVELLE_MARINE: ("233M", 8492,
- 'CHEF FLOTILLE - CARAVELLE MARINE',
- 'CHEFTAINE FLOTILLE - CARAVELLE MARINE'),
- Function.ACCOMPAGNATEUR_COMPAGNON: ("240", 8496,
- 'ACCOMPAGNATEUR COMPAGNON', 'ACCOMPAGNATRICE COMPAGNON'),
- Function.RESPONSABLE_FARFADET: ("270", 8498, 'RESPONSABLE FARFADET'),
- Function.PARENT_ANIMATEUR_FARFADET: ("271", 8554,
- 'PARENT ANIMATEUR FARFADET'),
- Function.RESPONSABLE_VENT_DU_LARGE: ("293", 8500,
- 'RESPONSABLE VENT DU LARGE'),
- Function.RESPONSABLE_DE_GROUPE: ("300", 8502,
- 'RESPONSABLE DE GROUPE'),
- Function.RESPONSABLE_DE_GROUPE_ADJOINT: ("301", 8503,
- 'RESPONSABLE DE GROUPE ADJOINT', 'RESPONSABLE DE GROUPE ADJOINTE'),
- Function.AUMONIER_DE_GROUPE: ("302", 8504, 'AUMONIER DE GROUPE'),
- Function.SECRETAIRE_DE_GROUPE: ("307", 8506, 'SECRETAIRE DE GROUPE'),
- Function.TRESORIER_DE_GROUPE: ("309", 8508, 'TRESORIER DE GROUPE',
- 'TRESORIERE DE GROUPE'),
- Function.ANIMATEUR_CLEOPHAS_L: ("316", 8509, 'ANIMATEUR CLEOPHAS',
- 'ANIMATRICE CLEOPHAS'),
- Function.CHARGE_DE_MISSION__DU_GROUPE: ("330", 8511,
- 'CHARGE DE MISSION DU GROUPE', 'CHARGEE DE MISSION DU GROUPE'),
- Function.REFERENT_TECHNIQUE_MARIN: ("330M", 8512,
- 'REFERENT TECHNIQUE MARIN', 'REFERENTE TECHNIQUE MARIN'),
- Function.REPRESENTANT_ASSOCIATIF_L: ("332", 8513,
- 'REPRESENTANT ASSOCIATIF'),
- Function.OUVREUR_DE_GROUPE_L: ("333", 8516, 'OUVREUR DE GROUPE'),
- Function.DIRECTEUR_DE_CAMP: ("351", 8517, 'DIRECTEUR DE CAMP',
- 'DIRECTRICE DE CAMP'),
- Function.RESPONSABLE_LOCAL_DEVELOPPEMENT_ET_RESEAUX: ("380", 8518,
- 'RESPONSABLE LOCAL DEVELOPPEMENT ET RESEAUX'),
- Function.FF_TRESORIER_DE_GROUPE: ("391", 8519,
- 'FF TRESORIER DE GROUPE', 'FF TRESORIERE DE GROUPE'),
- Function.NOMINATION_DES_CHEFS_ET_EQUIPIERS_DE_GROUPE: ("397", 8480,
- 'NOMINATION DES CHEFS ET EQUIPIERS DE GROUPE'),
- Function.FF_RESPONSABLE_DE_GROUPE: ("399", 8520,
- 'FF RESPONSABLE DE GROUPE'),
- Function.DELEGUE_TERRITORIAL: ("500", 8482, 'DELEGUE TERRITORIAL',
- 'DELEGUEE TERRITORIALE'),
- Function.DELEGUE_TERRITORIAL_ADJOINT: ("501", 8481,
- 'DELEGUE TERRITORIAL ADJOINT', 'DELEGUEE TERRITORIALE ADJOINTE'),
- Function.AUMONIER_TERRITORIAL: ("502", 8505, 'AUMONIER TERRITORIAL'),
- Function.RESPONSABLE_POLE_PEDAGOGIQUE: ("503", 8521,
- 'RESPONSABLE POLE PEDAGOGIQUE'),
- Function.RESPONSABLE_POLE_DEVELOPPEMENT: ("504", 8522,
- 'RESPONSABLE POLE DEVELOPPEMENT'),
- Function.RESPONSABLE_POLE_ADMINISTRATIF_ET_FINANCIER: ("505", 8515,
- 'RESPONSABLE POLE ADMINISTRATIF ET FINANCIER'),
- Function.FF_RESPONSABLE_POLE_ADMINISTRATIF_ET_FINANCIER: ("591", 8514,
- 'FF RESPONSABLE POLE ADMINISTRATIF ET FINANCIER'),
- Function.NOMINATION_DES_EQUIPIERS_TERRITORIAUX: ("597", 8507,
- 'NOMINATION DES EQUIPIERS TERRITORIAUX'),
- Function.FF_DELEGUE_TERRITORIAL: ("598", 8483,
- 'FF DELEGUE TERRITORIAL', 'FF DELEGUEE TERRITORIALE'),
- Function.ACCOMPAGNATEUR_PEDAGOGIQUE: ("600", 8523,
- 'ACCOMPAGNATEUR PEDAGOGIQUE', 'ACCOMPAGNATRICE PEDAGOGIQUE'),
- Function.AUMONIER_DIOCESAIN: ("602", 8510, 'AUMONIER DIOCESAIN'),
- Function.ACCOMPAGNATEUR_DES_RESPONSABLES_DE_GROUPE: ("609", 8524,
- 'ACCOMPAGNATEUR DES RESPONSABLES DE GROUPE'),
- Function.ANIMATEUR_CLEOPHAS_T: ("616", 8525, 'ANIMATEUR CLEOPHAS',
- 'ANIMATRICE CLEOPHAS'),
- Function.CHARGE_MISSION_DEVELOPPEMENT: ("620", 8526,
- 'CHARGE MISSION DEVELOPPEMENT', 'CHARGEE MISSION DEVELOPPEMENT'),
- Function.COORDINATEUR_DEVELOPPEMENT_ET_RESEAUX: ("621", 8527,
- 'COORDINATEUR DEVELOPPEMENT ET RESEAUX',
- 'COORDINATRICE DEVELOPPEMENT ET RESEAUX'),
- Function.OUVREUR_DE_GROUPE_T: ("622", 8528, 'OUVREUR DE GROUPE'),
- Function.RESPONSABLE_RECRUTEMENT: ("623", 8529,
- 'RESPONSABLE RECRUTEMENT'),
- Function.RESPONSABLE_PARTENARIATS_FINANCIERS: ("624", 8530,
- 'RESPONSABLE PARTENARIATS FINANCIERS'),
- Function.RESPONSABLE_COMMUNICATION: ("625", 8531,
- 'RESPONSABLE COMMUNICATION'),
- Function.CORRESPONDANT_HANDICAP: ("626", 8532,
- 'CORRESPONDANT HANDICAP'),
- Function.RESPONSABLE_SCOUTISME_EN_QUARTIER: ("627", 8533,
- 'RESPONSABLE SCOUTISME EN QUARTIER'),
- Function.CHARGE_MISSION_TERRITORIAL: ("630", 8534,
- 'CHARGE MISSION TERRITORIAL', 'CHARGEE MISSION TERRITORIALE'),
- Function.MEDIATEUR_T: ("631", 8535, 'MEDIATEUR', 'MEDIATRICE'),
- Function.REPRESENTANT_ASSOCIATIF_T: ("632", 8536,
- 'REPRESENTANT ASSOCIATIF', 'REPRESENTANTE ASSOCIATIF'),
- Function.RESPONSABLE_BOUTIQUE_SGDF: ("650", 8537,
- 'RESPONSABLE BOUTIQUE SGDF'),
- Function.DIRECTEUR_DE_CAMP_TERRITORIAL: ("651", 8538,
- 'DIRECTEUR DE CAMP TERRITORIAL', 'DIRECTRICE DE CAMP TERRITORIAL'),
- Function.TRESORIER_DE_BOUTIQUE: ("652", 8539, 'TRESORIER DE BOUTIQUE',
- 'TRESORIERE DE BOUTIQUE'),
- Function.CHARGE_DE_MISSION_RASSEMBLEMENT: ("659", 8540,
- 'CHARGE DE MISSION RASSEMBLEMENT'),
- Function.CHARGE_MISSION_ADMINISTRATIF: ("660", 8541,
- 'CHARGE MISSION ADMINISTRATIF', 'CHARGEE MISSION ADMINISTRATIF'),
- Function.GESTIONNAIRE_MATERIEL_ET_LOGISTIQUE: ("661", 8542,
- 'GESTIONNAIRE MATERIEL ET LOGISTIQUE'),
- Function.TRESORIER_DE_BASE: ("663", 8543, 'TRESORIER DE BASE',
- 'TRESORIERE DE BASE'),
- Function.EQUIPIER_DE_BASE: ("664", 8544, 'EQUIPIER DE BASE',
- 'EQUIPIERE DE BASE'),
- Function.RESPONSABLE_DE_BASE: ("665", 8545, 'RESPONSABLE DE BASE'),
- Function.SECRETAIRE_TERRITORIAL: ("670", 8546,
- 'SECRETAIRE TERRITORIAL', 'SECRETAIRE TERRITORIALE'),
- Function.CHARGE_DE_MISSION_RW2016_T: ("685", 8547,
- 'CHARGE DE MISSION RW2016 T', 'CHARGEE DE MISSION RW2016 T'),
- Function.TRESORIER_TERRITORIAL: ("690", 8548, 'TRESORIER TERRITORIAL',
- 'TRESORIERE TERRITORIALE'),
- Function.FF_TRESORIER_TERRITORIAL: ("691", 8549,
- 'FF TRESORIER TERRITORIAL', 'FF TRESORIERE TERRITORIAL'),
- Function.DIRECTEUR_DE_STAGE: ("850", 8446, 'DIRECTEUR DE STAGE',
- 'DIRECTRICE DE STAGE'),
- Function.DIRECTEUR_DE_CAMP_GROUPE: ("851", 8447,
- 'DIRECTEUR DE CAMP GROUPE', 'DIRECTRICE DE CAMP GROUPE'),
- Function.VOLONTAIRE_SERVICE_CIVIQUE: ("860", 8451,
- 'VOLONTAIRE SERVICE CIVIQUE'),
- Function.VOLONTAIRE_SERVICE_INTERNATIONAL: ("861", 8452,
- 'VOLONTAIRE SERVICE INTERNATIONAL'),
- Function.DELEGUE_GENERAL: ("900", 8449, 'DELEGUE GENERAL',
- 'DELEGUEE GENERALE'),
- Function.DELEGUE_GENERAL_ADJOINT: ("901", 8450,
- 'DELEGUE GENERAL ADJOINT', 'DELEGUEE GENERALE ADJOINTE'),
- Function.AUMONIER_GENERAL: ("902", 8453, 'AUMONIER GENERAL'),
- Function.DELEGUE_NATIONAL: ("903", 8454, 'DELEGUE NATIONAL',
- 'DELEGUEE NATIONALE'),
- Function.RESPONSABLE_NATIONAL: ("910", 8448, 'RESPONSABLE NATIONAL',
- 'RESPONSABLE NATIONALE'),
- Function.AUMONIER_NATIONAL: ("911", 8455, 'AUMONIER NATIONAL'),
- Function.EQUIPIER_NATIONAL: ("912", 8456, 'EQUIPIER NATIONAL',
- 'EQUIPIERE NATIONALE'),
- Function.RESPONSABLE_DE_LA_FORMATION_CR: ("913", 8457,
- 'RESPONSABLE DE LA FORMATION CR'),
- Function.CHARGE_MISSION: ("914", 8458, 'CHARGE MISSION',
- 'CHARGEE MISSION'),
- Function.CHARGE_MISSION_PAYS: ("915", 8459, 'CHARGE MISSION PAYS',
- 'CHARGEE MISSION PAYS'),
- Function.ADMINISTRATEUR: ("920", 8460, 'ADMINISTRATEUR',
- 'ADMINISTRATRICE'),
- Function.MEMBRE_D_HONNEUR: ("921", 8461, 'MEMBRE D HONNEUR'),
- Function.MEDIATEUR_N: ("931", 8462, 'MEDIATEUR', 'MEDIATRICE'),
- Function.REPRESENTANT_ASSOCIATIF: ("932", 8463,
- 'REPRESENTANT ASSOCIATIF', 'REPRESENTANTE ASSOCIATIF'),
- Function.SALARIE: ("980", 8464, 'SALARIE', 'SALARIEE'),
- Function.SALARIE_FORMATION: ("981", 8465, 'SALARIE FORMATION',
- 'SALARIEE FORMATION'),
- Function.SALARIE_SERVICE_INTERNATIONAL: ("982", 8466,
- 'SALARIE SERVICE INTERNATIONAL', 'SALARIEE SERVICE INTERNATIONAL'),
- Function.CONSULTANT_BATEAU: ("983", 8467, 'CONSULTANT BATEAU',
- 'CONSULTANTE BATEAU'),
- Function.ASSISTANT_DE_SAISIE: ("984", 8468, 'ASSISTANT DE SAISIE',
- 'ASSISTANTE DE SAISIE'),
- Function.CHARGE_DE_MISSION_RW2016_N: ("985", 8469,
- 'CHARGE DE MISSION RW2016 N', 'CHARGEE DE MISSION RW2016 N'),
- Function.CHARGE_DE_MISSION_RASSEMBLEMENT_EN: ("987", 8470,
- 'CHARGE DE MISSION RASSEMBLEMENT EN',
- 'CHARGEE DE MISSION RASSEMBLEMENT EN'),
- Function.ADMINISTRATEUR_MODULE_FORMATION: ("989", 8471,
- 'ADMINISTRATEUR MODULE FORMATION', 'ADMINISTRATRICE MODULE FORMATION'),
- Function.CONSULTANT_INTEGRATION: ("990", 8472,
- 'Consultant Intégration', 'Consultante Intégration'),
- Function.SALARIE_COMPTABILITE: ("991", 8473, 'SALARIE COMPTABILITE',
- 'SALARIEE COMPTABILITE'),
- Function.SALARIE_ASSURANCE: ("992", 8474, 'SALARIE ASSURANCE',
- 'SALARIEE ASSURANCE'),
- Function.ADMINISTRATEUR_ASSURANCE: ("993", 8475,
- 'ADMINISTRATEUR ASSURANCE', 'ADMINISTRATRICE ASSURANCE'),
- Function.SALARIE_CENTRE_DE_RESSOURCES: ("994", 8476,
- 'SALARIE CENTRE DE RESSOURCES', 'SALARIEE CENTRE DE RESSOURCES'),
- Function.ADMINISTRATEUR_COMPTABILITE: ("995", 8477,
- 'ADMINISTRATEUR COMPTABILITE', 'ADMINISTRATRICE COMPTABILITE'),
- Function.DIRECTEUR_DE_CENTRE_DE_RESSOURCES: ("996", 8478,
- 'DIRECTEUR DE CENTRE DE RESSOURCES',
- 'DIRECTRICE DE CENTRE DE RESSOURCES'),
- Function.RESPONSABLE_ADMINISTRATIF_CR: ("997", 8444,
- 'RESPONSABLE ADMINISTRATIF CR', 'RESPONSABLE ADMINISTRATIVE CR'),
- Function.ANIMATION_TERRITORIALE_ET_DEVELOPPEMENT: ("998", 8443,
- 'ANIMATION TERRITORIALE ET DEVELOPPEMENT'),
- Function.ADMINISTRATEUR_INTRANET: ("999", 8437,
- 'ADMINISTRATEUR INTRANET', 'ADMINISTRATRICE INTRANET'),
- Function.MONITORING_APPLICATIF: ("9XX", 8479,
- 'Monitoring applicatif'),
-}
+__all__ = ["Function", "FunctionData", "FunctionRawData"]
+
+def _isid(value):
+ try:
+ Function(value)
+ except:
+ return False
+ return True
def _isint(value):
try:
@@ -370,7 +23,94 @@ def _isint(value):
return False
return True
-# Leads are:
+class FunctionRawData:
+ """ Raw data from a function for importation of the autocomplete file
+ from the intranet. """
+
+ def __init__(self, iid, code, nm, nf, cname, srcorder):
+ self.__iid = iid
+ self.__code = code
+ self.__nm = nm
+ self.__nf = nf
+ self.__cname = cname
+ self.__srcorder = srcorder
+
+ def __repr__(self):
+ p = []
+ p.append(f"cname = {repr(self.__cname)}")
+ p.append(f"iid = {repr(self.__iid)}")
+ p.append(f"code = {repr(self.__code)}")
+ p.append(f"nm = {repr(self.__nm)}")
+ if self.__nf is not None:
+ p.append(f"nf = {repr(self.__nf)}")
+
+ return f"{self.__class__.__name__}({', '.join(p)})"
+
+ @property
+ def cname(self):
+ """ The canonical/constant name for the function. """
+
+ return self.__cname
+
+ @property
+ def iid(self):
+ """ The internal identifier (e.g. 8434). """
+
+ return self.__iid
+
+ @property
+ def code(self):
+ """ The code (e.g. "110", "110M" or "9XX"). """
+
+ return self.__code
+
+ @property
+ def name(self):
+ """ The full name. """
+
+ p = [self.__nm]
+ if self.__nf is not None:
+ p.append(self.__nf)
+ return " / ".join(p)
+
+ @property
+ def nm(self):
+ """ The masculine name. """
+
+ return self.__nm
+
+ @property
+ def nf(self):
+ """ The feminine name. """
+
+ return self.__nf
+
+ def replace(self, **kwargs):
+ cname = self.__cname
+
+ if 'cname' in kwargs:
+ cname = kwargs['cname']
+ del kwargs['cname']
+ if kwargs:
+ raise ValueError(f"Invalid keyword {repr(kwargs.keys()[0])}")
+
+ return FunctionRawData(self.__iid, self.__code, self.__nm, self.__nf,
+ cname, self.__srcorder)
+
+ @property
+ def srcorder(self):
+ """ Order in the original JSON. """
+
+ return self.__srcorder
+
+# Each entry in `_FunctionData` has the function identifier as the key, and
+# a data composed of the following components:
+# - `c`: the intranet code (e.g. "120", "110M", "9XX", …).
+# - `ii`: the intranet internal identifier (e.g. "8434", "8437", …).
+# - `nm`: the masculin name for the function.
+# - `nf` (opt.): the feminine name for the function.
+#
+# Leads defined in `_FunctionLeads` are:
# - the masculine noun (e.g. "LOUVETEAU").
# - the feminine noun (e.g. "JEANETTE").
# - the integer internal identifier (e.g. 8434).
@@ -400,13 +140,6 @@ _FunctionLeads.update({f"{c} ({nouns[1]})".strip().casefold(): i \
_FunctionLeads.update({f"{c} ({nouns[0]} / {nouns[1]})".strip().casefold(): i \
for i, (c, ii, *nouns) in _FunctionData.items() if len(nouns) > 1})
-def _isid(value):
- try:
- Function(value)
- except:
- return False
- return True
-
class FunctionData:
""" Function data (code, id, name, other). """
@@ -429,8 +162,7 @@ class FunctionData:
self.__nf = None
elif _isid(value):
value = Function(value)
- self.__id = _FunctionCodes.get(value, UNKNOWN)
- self.__code = value
+ self.__id = value
data = _FunctionData.get(self.__id, None)
else:
diff --git a/sgdfi/_dbs/_regime.py b/sgdfi/_dbs/_regime.py
new file mode 100644
index 0000000..3bcff3c
--- /dev/null
+++ b/sgdfi/_dbs/_regime.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python3
+#******************************************************************************
+# Copyright (C) 2018 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
+# This file is part of the sgdfi project, which is MIT-licensed.
+#******************************************************************************
+""" Allocations regime reference for SGDFi. """
+
+from enum import Enum as _Enum, unique as _unique
+
+__all__ = ["AllocationsRegime"]
+
+@_unique
+class AllocationsRegime(_Enum):
+ """ The default type (unknown). """
+ UNKNOWN = 0
+
+ """ Régime général (CAF, Maritime, SNCF, …). """
+ GENERAL = 1
+
+ """ MSA. """
+ MSA = 2
+
+ """ Étranger, conseil de l'Europe. """
+ EUROPE = 3
+
+# End of file.
diff --git a/sgdfi/_dbs/_st.py b/sgdfi/_dbs/_st.py
index ef7ac1d..e9c47a9 100755
--- a/sgdfi/_dbs/_st.py
+++ b/sgdfi/_dbs/_st.py
@@ -40,7 +40,7 @@ class StructureTypeData:
return False
return True
- self.__id = None
+ self.__id = StructureType.UNKNOWN
self.__name = None
data = None
@@ -49,7 +49,7 @@ class StructureTypeData:
self.__name = value.name
elif isid(value):
value = StructureType(value)
- self.__id = value.id
+ self.__id = value
data = _StructureTypeData.get(value, None)
else:
diff --git a/sgdfi/_dbs/_ststatus.py b/sgdfi/_dbs/_ststatus.py
new file mode 100755
index 0000000..ee7b0ed
--- /dev/null
+++ b/sgdfi/_dbs/_ststatus.py
@@ -0,0 +1,91 @@
+#!/usr/bin/env python3
+#******************************************************************************
+# Copyright (C) 2018 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
+# This file is part of the sgdfi project, which is MIT-licensed.
+#******************************************************************************
+""" Structure status reference for SGDFi. """
+
+from enum import Enum as _Enum, unique as _unique
+
+__all__ = ["StructureStatus", "StructureStatusData"]
+
+@_unique
+class StructureStatus(_Enum):
+ """ The default status (unknown). """
+ UNKNOWN = 0
+
+ """ Ouverte. """
+ OPEN = 1
+
+_StructureStatusData = {
+ StructureStatus.OPEN: "Ouverte"
+}
+
+_StructureStatusLeads = {}
+_StructureStatusLeads.update({name.strip().casefold(): i for i, name \
+ in _StructureStatusData.items()})
+
+class StructureStatusData:
+ """ The structure status data. """
+
+ def __init__(self, value):
+ def isid(id):
+ try:
+ StructureStatus(value)
+ except ValueError:
+ return False
+ return True
+
+ self.__id = StructureStatus.UNKNOWN
+ self.__name = None
+ data = None
+
+ if isinstance(value, StructureStatusData):
+ self.__id = value.id
+ self.__name = value.name
+ elif isid(value):
+ value = StructureStatus(value)
+ self.__id = value
+
+ data = _StructureStatusData.get(value, None)
+ else:
+ lead = value
+ if type(lead) == str:
+ lead = lead.strip().casefold()
+
+ try:
+ self.__id = _StructureStatusLeads[lead]
+ data = _StructureStatusData.get(self.__id, None)
+ except KeyError:
+ if type(value) == str:
+ self.__name = value
+ else:
+ msg = "Could not determine a structure status."
+ raise ValueError(msg) from None
+
+ if data is not None:
+ self.__name = data
+
+ def __repr__(self):
+ p = []
+ if self.__id is not None:
+ p.append(f"id = {repr(self.__id)}")
+ if self.__name is not None:
+ p.append(f"name = {repr(self.__name)}")
+
+ return f"{self.__class__.__name__}({', '.join(p)})"
+
+ @property
+ def id(self):
+ """ The status identifier, as one of the identifiers defined in
+ the StructureStatus enumeration. """
+
+ return self.__id
+
+ @property
+ def name(self):
+ """ The status name as defined in the structure summary page. """
+
+ return self.__name
+
+# End of file.
diff --git a/sgdfi/_manager.py b/sgdfi/_manager.py
index eebb7b0..16ba771 100755
--- a/sgdfi/_manager.py
+++ b/sgdfi/_manager.py
@@ -12,6 +12,7 @@ import os.path as _path
from os import makedirs as _makedirs, open as _open, fdopen as _fdopen, \
O_WRONLY as _O_WRONLY, O_CREAT as _O_CREAT, O_EXCL as _O_EXCL
+from sys import stdout as _stdout
from itertools import count as _count
from datetime import datetime as _datetime
from re import finditer as _rfindter, sub as _rreplace, split as _rsplit
@@ -20,6 +21,9 @@ from base64 import b64decode as _b64decode
from urllib.parse import urlparse as _urlparse, parse_qs as _parse_qs, \
unquote as _unquote
from html import unescape as _htmlunescape
+from xml.etree.ElementTree import ElementTree as _XMLTree, \
+ fromstring as _XMLFromString
+from json import loads as _jsonloads
from csv import reader as _csvreader
from bs4 import BeautifulSoup as _BeautifulSoup
@@ -28,43 +32,55 @@ from appdirs import user_cache_dir as _user_cache_dir
from ._repr import Structure as _Structure, Adherent as _Adherent, \
Place as _Place, RallyRegistration as _RallyRegistration, Camp as _Camp, \
- Operation as _Operation
+ Operation as _Operation, FunctionRawData as _FunctionRawData
+from ._db import Database as _Database
__all__ = ["Manager"]
-# Data manager.
-
-class _DataManager:
- """ The internal class to manage all data. """
+# Internal classes for the `_Manager` class.
+class _Pagination:
def __init__(self):
- self.__ops = {}
+ self.current = 0
+ self.number = 0
+ self.more = False
- def add_op(self, op):
- """ Add an operation. """
+class _AjaxField:
+ """ Microsoft Ajax response part. """
- # TODO
- pass
+ def __init__(self, code, name, value, text):
+ self.__code = str(code)
+ self.__name = str(name)
+ self.__value = str(value)
+ self.__text = str(text)
- def add_place(self, pl):
- """ Add a place. """
+ def __repr__(self):
+ return f'Field(id = {repr(self.code)}, name = {repr(self.name)}, ' \
+ f'attrib = {repr(self.value)})'
- # TODO
- pass
+ @property
+ def code(self):
+ """ The code (first field). """
- def add_structure(self, st):
- """ Add a structure. """
+ return self.__code
- # TODO
- pass
+ @property
+ def name(self):
+ """ The name (second field). """
-# Internal classes for the `_Manager` class.
+ return self.__name
-class _Pagination:
- def __init__(self):
- self.current = 0
- self.number = 0
- self.more = False
+ @property
+ def value(self):
+ """ The value (third field). """
+
+ return self.__value
+
+ @property
+ def text(self):
+ """ The text (fourth field). """
+
+ return self.__text
class _OperationManager:
""" The operations manager. """
@@ -102,8 +118,22 @@ class _StructureManager:
self.__main.add_structure(st)
+class _AdherentManager:
+ """ The adherent manager. """
+
+ def __init__(self, main):
+ self.__main = main
+
+ def add(self, ad):
+ if not isinstance(ad, _Adherent):
+ raise ValueError("Expected an 'Adherent'.")
+
+ self.__main.add_adherent(ad)
+
# The main class.
+_type = type
+
class Manager:
""" Manage objects from SGDF's intranet. """
@@ -114,8 +144,9 @@ class Manager:
# Work out the folder, and make sure it exists.
+ cache_dir = _user_cache_dir(appname = "sgdfi")
if folder is None:
- self.__folder = _user_cache_dir(appname = "sgdfi")
+ self.__folder = cache_dir
try:
_makedirs(self.__folder)
except FileExistsError:
@@ -123,10 +154,11 @@ class Manager:
# Make the data manager.
- data = _DataManager()
+ data = _Database(cache_dir = cache_dir)
self.__ops = _OperationManager(data)
self.__pls = _PlaceManager(data)
self.__sts = _StructureManager(data)
+ self.__ads = _AdherentManager(data)
@property
def operations(self):
@@ -146,6 +178,12 @@ class Manager:
return self.__sts
+ @property
+ def adherents(self):
+ """ The adherents manager. """
+
+ return self.__ads
+
# ---
# Save file management.
# ---
@@ -175,14 +213,15 @@ class Manager:
return self.read(path, type, hint)
- def save(self, content, hint = None, ext = 'txt'):
+ def save(self, content, hint = None, type = 'html'):
""" Save a file. """
- if not self.__save:
- return
+ exts = {'html': 'html', 'csv': 'csv', 'xls': 'xls', 'xml': 'xml',
+ 'json': 'json'}
+ ext = exts.get(type, 'txt')
fdmode = 'w'
- if type(hint) == str:
+ if _type(hint) == str:
hint = f"-{hint}"
else:
hint = ""
@@ -213,6 +252,15 @@ class Manager:
return self.feed(open(path).read(), type, hint)
+ _AjaxFieldHintCodes = {
+ 'personlist': (9192, 9431, 9449, 15819, 17464, 17721, 20723,
+ 22607, 22864),
+ 'person_summary': (21686,),
+ 'person_family': (7190,)
+ }
+ _AjaxFieldCodeHints = {code: hint \
+ for hint, codes in _AjaxFieldHintCodes.items() for code in codes}
+
def feed(self, content, type, hint = None):
""" Feed the manager with a document.
@@ -223,9 +271,14 @@ class Manager:
if hint == 'ignore':
return None
- if type == 'html':
- self.save(content, hint, 'html')
+ if self.__save:
+ self.save(content, hint, type)
+ if hint == 'raw':
+ return content
+ # FIXME: vérifier s'il y a eu une erreur.
+
+ if type == 'html':
if hint == 'operations':
func = self.__feed_html_operations
elif hint == 'place':
@@ -248,21 +301,6 @@ class Manager:
content = _BeautifulSoup(content, 'lxml')
return func(content)
elif type == 'ajax':
- self.save(content, hint, 'txt')
-
- if hint == 'personlist':
- func = self.__feed_html_personlist_fragment
- elif hint == 'person_summary':
- func = self.__feed_html_person_summary_fragment
- elif hint == 'person_family':
- func = self.__feed_html_person_family_fragment
- elif hint == 'calendar_month':
- func = self.__feed_html_calendar_month_fragment
- elif hint is None:
- func = None
- else:
- raise ValueError(f"unknown ajax hint: {repr(hint)}")
-
# Les réponses aux appels AJAX sont un ensemble d'éléments séparés
# par des pipes ('|'), à prendre par groupe de quatre tels que
# décrits par le document `intranet.rst`.
@@ -275,27 +313,38 @@ class Manager:
attrib = next(raw)
text = next(raw)
- resp.append(_Field(code, name, attrib, text))
-
- # FIXME: vérifier s'il y a eu une erreur.
+ resp.append(_AjaxField(code, name, attrib, text))
# La charge utile de la réponse est dans la seconde entrée
# généralement. Le code permet de déterminer de quoi il en
# retourne, mais beaucoup de codes peuvent être émis selon les
- # actions précédentes, donc on fait confiance au contexte.
-
- # TODO: si `hint` est égal à None ici, par rapport aux codes
- # connus, on peut tenter d'identifier les fragments ?
- # e.g. `if field.code in (25XXX, 25XXX, …): func = …`.
+ # actions précédentes et le contexte (e.g. état du formulaire
+ # de recherche), donc on fait confiance au contexte tout en
+ # proposant un contexte par défaut selon le code.
field = resp[1]
+
+ # On vérifie l'indice donné par l'utilisateur, s'il y en a un.
+
if hint is None:
- raise ValueError("required ajax hint")
+ try:
+ hint = _AjaxFieldCodeHints[field.code]
+ except KeyError:
+ raise ValueError("ajax hint could not be determined")
+
+ if hint == 'personlist':
+ func = self.__feed_html_personlist_fragment
+ elif hint == 'person_summary':
+ func = self.__feed_html_person_summary_fragment
+ elif hint == 'person_family':
+ func = self.__feed_html_person_family_fragment
+ elif hint == 'calendar_month':
+ func = self.__feed_html_calendar_month_fragment
+ else:
+ raise ValueError(f"unknown ajax hint: {repr(hint)}")
return func(field.text)
elif type == 'csv':
- self.save(content, hint, 'csv')
-
if hint == 'attend':
func = self.__feed_csv_attend
else:
@@ -308,8 +357,6 @@ class Manager:
return func(resp)
elif type == 'xls':
- self.save(content, hint, 'xls')
-
if hint == 'people':
func = self.__feed_xls_people
else:
@@ -330,15 +377,112 @@ class Manager:
resp = [e for e in entries(content)]
return func(resp)
- else:
- self.save(content, hint, 'bin')
+ elif type == 'xml':
+ tree = _XMLTree(_XMLFromString(content))
+
+ if hint == 'functions':
+ data = _jsonloads(tree.getroot().text)
+ return self.__feed_json_functions(data)
+ else:
+ raise ValueError("unknown xml hint: {repr(hint)}")
+ elif type == 'json':
+ data = _jsonloads(content)
+ if hint == 'functions':
+ return self.__feed_json_functions(data)
+ else:
+ raise ValueError("unknown json hint: {repr(hint)}")
+ else:
raise ValueError(f"unknown type: {repr(type)}")
# ---
# HTML pages and fragments decoding.
# ---
+ def __feed_json_functions(self, content):
+ """ Decode the JSON functions autocompletion data and return
+ them without feeding the database. """
+
+ def _sfix(code):
+ if code[-1:] == "L" or code[:1] == "3":
+ return "_L"
+ if code[-1:] == "N" or code[:1] == "6":
+ return "_N"
+ if code[-1:] == "T" or code[:1] == "9":
+ return "_T"
+ return ""
+
+ # First phase: load from the JSON and store as an array under the
+ # constant name.
+
+ funcs = {}
+
+ for idx, value in enumerate(content):
+ iid = int(value['id'])
+ name = value['name']
+
+ code, rest = name.split('(')
+ code = code.strip()
+ rest = rest.split(')')[0]
+
+ rest = rest.split('/')
+ nm = rest[0].strip()
+ if len(rest) == 1:
+ nf = None
+ else:
+ nf = '/'.join(rest[1:])
+ nf = nf.strip()
+
+ cfilt = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_'
+
+ cname = nm.casefold().upper()
+ cname = cname.replace(' - ', ' ')
+ cname = cname.replace(' ', ' ')
+ cname = cname.replace("D'", '')
+ cname = cname.replace(' ', '_')
+ cname = cname.replace('É', 'E')
+ cname = cname.replace('À', 'A')
+ cname = ''.join(filter(lambda c: c in cfilt, cname))
+
+ func = _FunctionRawData(iid, code, nm, nf, cname, idx + 1)
+
+ if not cname in funcs:
+ funcs[cname] = []
+ funcs[cname].append(func)
+
+ # Second phase: disambiguation.
+
+ while True:
+ try:
+ cname = next(cn for cn in funcs.keys() if len(funcs[cn]) > 1)
+ except StopIteration:
+ break
+
+ disf = funcs[cname]
+ del funcs[cname]
+
+ # We ought to find a solution to make other canonical names.
+
+ codes = [func.code for func in disf]
+ sfix = [_sfix(code) for code in codes]
+ if len(sfix) > len(set(sfix)):
+ raise ValueError(f"Could not deduplicate using scale: {codes}")
+
+ for func in disf:
+ cname = func.cname + sfix.pop(0)
+ func = func.replace(cname = cname)
+
+ if not cname in funcs:
+ funcs[cname] = []
+ funcs[cname].append(func)
+
+ # Third phase: flatten the functions and we're done!
+
+ funcs = [func[0] for func in funcs.values()]
+ funcs.sort(key = lambda x: x.srcorder)
+
+ return funcs
+
def __feed_html_operations(self, content):
""" Decode the HTML operations from a BeautifulSoup decoded
content and feed it into the manager's operations. """
@@ -634,8 +778,8 @@ class Manager:
parent = content.find(id = 'ctl00_ctl00_MainContent_TabsContent_' \
'TabContainerResumeStructure__tabResume')
- rp = 'ctl00_ctl00_MainContent_TabsContent_TabContainerResumeStructure_' \
- '_tabResume__resume__'
+ rp = 'ctl00_ctl00_MainContent_TabsContent_' \
+ 'TabContainerResumeStructure__tabResume__resume__'
st = _Structure()
@@ -775,4 +919,138 @@ class Manager:
#self.structures.add(st)
return None
+ def __feed_html_personlist_fragment(self, content):
+ """ Decode the HTML operations from a BeautifulSoup decoded
+ content and feed it into the manager's operations. """
+
+ people = []
+
+ parent = content.find(id = 'ctl00_MainContent__recherche__gvResultats')
+ for line in parent.children:
+ try:
+ _, name, adh, fct, st, finfct, cp, vil, \
+ finadh, *_ = line.children
+ except:
+ continue
+
+ p = Person()
+
+ # Nom et ID interne.
+
+ try:
+ url = next(name.children)['href']
+ q = _parse_qs(_urlparse(url).query)
+ iid = q['id'][0]
+ except:
+ continue
+
+ nom = next(name.children).text
+ props = nom.split()
+
+ p.iid = iid
+ p.common_name = props[0]
+ p.first_name = props[-1]
+
+ # Code d'adhérent, fonction, structure associée,
+ # période d'adhésion. TODO
+ #
+ # La date de fin de fonction est au format JJ/MM/AAAA.
+ # La date de fin d'adhésion est au format JJ/MM/AAAA.
+ # Le code adhérent est un nombre uniquement, e.g. « 110 ».
+ #
+ # Si la personne est une invitée, les champs de fin d'adhésion
+ # ainsi que le code adhérent sont vides (mais pas le champ de
+ # fin de fonction, qui fait référence à la date de fin du
+ # statut d'invité).
+ #
+ # Il peut y avoir un code adhérent mais pas de date de fin
+ # d'adhésion + fonction, ou simplement pas de date de fin de
+ # fonction.
+
+ try:
+ code = next(adh.children).text
+ fin_adhesion = next(finadh.children).text
+ except:
+ code = None
+
+ fonction = fct.text
+ try:
+ finfonction = next(finfct.children).text
+ except:
+ finfonction = None
+ structure = next(st.children).text
+
+ # Commune de résidence.
+
+ code_postal = next(cp.children).text
+ ville = next(vil.children).text
+
+ p.address.municipality.name = ville
+ p.address.municipality.postal_code = code_postal
+
+ # Ajout au tableau.
+
+ people.append(p)
+
+ # TODO: feed.
+ return people
+
+ # ---
+ # Export functions as a Python file to replace the one
+ # in `_dbs/_funcdata.py`.
+ # ---
+
+ def export_functions(self, functions, to = _stdout):
+ """ Export a functions array as a `_dbs/_funcdata.py` file. """
+
+ docstring = "Generated functions reference for `_funcs.py`."
+
+ # Initial header.
+
+ print("#!/usr/bin/env python3", file = to)
+ print("#" + "*" * 78, file = to)
+ print("# Copyright (C) 2018 Thomas Touhey <thomas@touhey.fr>",
+ file = to)
+ print("# This file is part of the sgdfi project, which " \
+ "is MIT-licensed.", file = to)
+ print("#" + "*" * 78, file = to)
+ print(f"{repr(docstring)}", file = to)
+ print("", file = to)
+ print("from enum import Enum as _Enum", file = to)
+ print("", file = to)
+ print("__all__ = [\"Function\", \"FunctionData\"]", file = to)
+ print("", file = to)
+ print("# This file was generated, do not edit it manually!", file = to)
+ print("", file = to)
+
+ # Enumeration definition.
+
+ print("class Function(_Enum):", file = to)
+ print("\t\"Unknown function.\"", file = to)
+ print("\tUNKNOWN = 0", file = to)
+ print("", file = to)
+
+ for i, func in enumerate(functions, start = 1):
+ print(f"\t{repr(func.name)}", file = to)
+ print(f"\t{func.cname} = {i}")
+ print("", file = to)
+
+ # Function data definition.
+
+ print("FunctionData = {", file = to)
+
+ for func in functions:
+ lnk = "," if func.nf is not None else "),"
+
+ print(f"\tFunction.{func.cname}: " \
+ f"({repr(func.code)}, {repr(func.iid)},", file = to)
+ print(f"\t\t{repr(func.nm)}{lnk}", file = to)
+
+ if func.nf is not None:
+ print(f"\t\t{repr(func.nf)}),", file = to)
+
+ print("}", file = to)
+ print("", file = to)
+ print("# End of file.", file = to)
+
# End of file.
diff --git a/sgdfi/_repr.py b/sgdfi/_repr.py
index b941422..aa9d97f 100755
--- a/sgdfi/_repr.py
+++ b/sgdfi/_repr.py
@@ -13,11 +13,14 @@ from ._util import IID, Enum as _Enum, \
BoolProperty as _BoolProperty, EnumProperty as _EnumProperty, \
ArrayProperty as _ArrayProperty, TextProperty as _TextProperty
from ._dbs import OperationType, OperationTypeData as _OperationTypeData, \
- Function, FunctionData as _FunctionData, StructureType, \
- StructureTypeData as _StructureTypeData
+ Function, FunctionRawData, FunctionData as _FunctionData, StructureType, \
+ StructureTypeData as _StructureTypeData, StructureStatus, \
+ StructureStatusData as _StructureStatusData, \
+ AllocationsRegime
__all__ = ["IID", "Structure", "Adherent", "RallyRegistration", "Camp",
- "Place", "Operation", "OperationType", "Function"]
+ "Place", "Operation", "OperationType", "Function", "StructureType",
+ "StructureStatus", "AllocationsRegime"]
# ---
# Specific properties.
@@ -80,6 +83,25 @@ class _StructureTypeProperty(_Property):
def delete(self):
self.__data = None
+class _StructureStatusProperty(_Property):
+ """ Structure type. """
+
+ def init(self):
+ self.__data = None
+
+ def get(self):
+ return self.__data
+
+ def set(self, value):
+ if value is None:
+ self.__data = None
+ return
+
+ self.__data = _StructureStatusData(value)
+
+ def delete(self):
+ self.__data = None
+
class _OperationFieldsProperty(_Property):
""" Operation fields. """
@@ -147,7 +169,7 @@ class Structure(_Base):
code = _TextProperty() # TODO: public code thingy?
# TODO: private code thingy?
description = _TextProperty(not_empty = True)
- status = _TextProperty() # TODO: enum?
+ status = _StructureStatusProperty()
hemisphere = _TextProperty()
address = _TextProperty(not_empty = True)
postal_code = _TextProperty()
@@ -167,7 +189,39 @@ class Adherent(_Base):
""" A person who is part of the organization. """
iid = _IIDProperty()
- name = _TextProperty()
+ common_name = _TextProperty()
+ last_name = _TextProperty()
+ first_name = _TextProperty()
+
+ # TODO: inscription (code adhérent, structure, fonction, fct 2ndaires,
+ # statut, début de mandat, fin de mandat).
+
+ function = _FunctionProperty()
+
+ address = _TextProperty()
+ postal_code = _TextProperty()
+ town = _TextProperty()
+ country = _TextProperty()
+ npai = _BoolProperty()
+ home_phone = _TextProperty()
+ work_phone = _TextProperty()
+ portable_phone1 = _TextProperty()
+ portable_phone2 = _TextProperty()
+ home_email = _TextProperty()
+ work_email = _TextProperty()
+ birth_date = _DateProperty()
+ birth_postal_code = _TextProperty()
+ birth_insee_code = _TextProperty()
+ birth_town = _TextProperty()
+ profession = _TextProperty()
+ allocations_beneficiary_number = _TextProperty()
+ allocations_beneficiary_regime = _EnumProperty(enum = AllocationsRegime)
+ image_rights = _BoolProperty()
+ medical_surgical_measures = _BoolProperty()
+ civil_liability_insurance = _BoolProperty()
+ ice_last_name = _TextProperty()
+ ice_first_name = _TextProperty()
+ ice_phone = _TextProperty()
class RallyRegistration(_Base):
""" A registration to an event common to several structures. """
diff --git a/sgdfi/_session.py b/sgdfi/_session.py
index 3396c8f..3d83b38 100755
--- a/sgdfi/_session.py
+++ b/sgdfi/_session.py
@@ -143,6 +143,14 @@ class Session(_Manager):
self.__log(f"Decoding HTML content{htext}.")
return self.feed(r.text, 'html', hint)
+ elif ct == 'text/xml':
+ self.__log(f"Decoding XML content{htext}.")
+
+ return self.feed(r.text, 'xml', hint)
+ elif ct == 'application/json':
+ self.__log(f"Decoding JSON content{htext}.")
+
+ return self.feed(r.text, 'json', hint)
self.__log(f"Unmanaged Content-Type {repr(ct)}")
self.__log(f"Falling back on HTML decoding.")
@@ -239,6 +247,19 @@ class Session(_Manager):
return ret(r)
# ---
+ # Data generation.
+ # ---
+
+ def get_functions(self):
+ """ Get the functions. """
+
+ path = '/Specialisation/Sgdf' \
+ '/WebServices/AutoComplete.asmx/GetFonctions?q='
+
+ return self.get_page(path, method = self.METHOD_BASIC,
+ hint = 'functions')
+
+ # ---
# Usage.
# ---