Métadonnées calculées#
Principe • Processus de calcul • Implémentation du calcul automatique • Implémentation du calcul à déclenchement manuel
Principe#
Plume permet à l’administrateur de demander via ses modèles de formulaires à ce que certaines catégories de métadonnées puissent être mises à jour par un calcul côté serveur en plus de la saisie manuelle ordinaire. Ce calcul peut soit être exécuté automatiquement au chargement de la fiche de métadonnées (options 'auto'
, 'new'
ou 'empty'
), soit à la demande de l’utilisateur (option 'manual'
).
Les catégories pour lesquelles le calcul est proposé sont, à ce stade :
Chemin de la catégorie |
Information calculée |
Paramètres optionnels |
Dépendances |
---|---|---|---|
|
Pour les schémas de la nomenclature, thème(s) Ecosphères correspondant(s). Les thèmes Ecosphères forment une classification à deux niveaux basée sur celle de la COVADIS. |
Par défaut, les thèmes de niveau 1 (le plus général) et de niveau 2 (sous-catégorisation plus spécifique) sont récupérés. |
Aucune. |
|
Tous les référentiels de coordonnées déclarés pour les géométries de la table ou vue. |
Aucun. |
L’extension PostGIS doit être active sur la base. |
|
La date de création de la table si l’information est présente dans la table |
Aucun. |
L’extension PlumePg doit être active sur la base[1]. |
|
Importe le contenu du descriptif PostgreSQL de l’objet[2], soit dans son intégralité, soit en utilisant une expression régulière. |
|
L’extension PlumePg doit être active sur la base. |
|
La date de dernière modification de la table si l’information est présente dans la table |
Aucun. |
L’extension PlumePg doit être active sur la base[1]. |
|
Idem |
Idem. |
Idem. |
Les paramètres optionnels sont spécifiés via le champ compute_params
de z_plume.meta_categorie
et z_plume.meta_template_categories
. Il s’agit d’un champ de type jsonb
, qui attend un dictionnaire dont les clés sont les noms des paramètres et dont les valeurs sont les valeurs des paramètres.
Par exemple :
UPDATE z_plume.meta_categorie
SET compute = ARRAY['new'],
compute_params = '{"pattern": "^[\\w\\s]+"}'::jsonb
WHERE path = 'dct:title' ;
Les trois modes de calcul automatique opèrent comme suit :
Avec
'auto'
, le calcul est effectué systématiquement à l’ouverture de la fiche de métadonnées ou lorsqu’elle est re-générée par une réinitialisation, un import, une copie… Il n’est pas exécuté lorsque le formulaire est reconstruit après une sauvegarde.Avec
'empty'
, le calcul est effectué dans les mêmes conditions que pour'auto'
, avec une condition supplémentaire : le widget ou le groupe de widgets ne doit contenir aucune valeur.Avec
'new'
, le calcul n’est effectué que si la fiche de métadonnées est entièrement vide[5], soit dans le cas d’une table dont le descriptif ne contenait par encore de métadonnées, dans le cas d’une réinitialisation ou encore dans le cas de l’import d’une fiche vide.
Si plusieurs de ces modes sont spécifiés simultanément, 'auto'
prévaut sur 'empty'
, qui prévaut sur 'new'
.
Avec 'manual'
, un bouton de calcul apparaîtra à droite du champ de saisie de la métadonnées dans le formulaire. Cliquer sur ce bouton importe les informations désirées du serveur. Pour les catégories admettant plusieurs valeurs, le bouton porte sur l’ensemble du groupe.
Les boutons de calcul ne sont présents qu’en mode édition, par contre le calcul automatique opère aussi bien en mode édition qu’en mode lecture. Une catégorie sur laquelle une fonctionnalité de calcul automatique est définie apparaîtra toujours dans le formulaire, même lorsque le calcul ne renvoie aucune valeur et que le paramétrage prévoit que les catégories sans valeur ne soient pas affichées (comportement par défaut en mode lecture[6]).
Processus de calcul#
Le calcul consiste en quatre opérations successives :
vérifier que la base PostgreSQL cible dispose bien des extensions nécessaires au calcul ;
générer la requête permettant d’obtenir les informations désirées et l’envoyer au serveur PostgreSQL ;
intégrer le résultat dans le dictionnaire de widgets ;
(selon les cas) répercuter les modifications sur les widgets.
Dans la suite, on considère :
widgetsdict
le dictionnaire contenant tous les widgets et leurs informations de paramétrage (cf. Génération du dictionnaire des widgets), objet de classeplume.rdf.widgetsdict.WidgetsDict
.widgetkey
la clé de ce dictionnaire pour laquelle un calcul doit être réalisé, objet de classeplume.rdf.widgetkey.WidgetKey
.
Contrôle des extensions disponibles#
La liste des extensions PostgreSQL nécessaires à l’exécution du calcul est fournie par l’attribut dependances
de l’objet plume.pg.computer.ComputationMethod
contenu dans la clé 'compute method'
du dictionnaire interne. Il peut s’agir d’une liste vide si le calcul ne requiert aucune extension.
Pour déterminer si les extensions sont bien installées sur la base source de la table ou vue considérée, on pourra utiliser la requête renvoyée par la fonction plume.pg.queries.query_exists_extension
.
import psycopg2
from plume.pg import queries
dependances = widgetsdict[widgetkey]['compute method'].dependances
if dependances:
conn = psycopg2.connect(connection_string)
dependances_ok = True
with conn:
with conn.cursor() as cur:
for extension in dependances:
cur.execute(*queries.query_exists_extension(extension))
dependances_ok = dependances_ok and cur.fetchone()[0]
if not dependances_ok:
break
conn.close()
Si dependances_ok
vaut True
, il est possible de passer à l’étape suivante. Sinon il faudra interrompre le processus, et vraisemblablement alerter l’utilisateur qu’une au moins des extensions requises est absente.
Génération et exécution de la requête#
La requête de calcul est construite par la méthode computing_query
de la classe plume.rdf.widgetsdict.WidgetsDict
. Celle-ci renvoie un tuple contenant tous les arguments à fournir à psycopg2.cursor.execute
(contrairement à la plupart des fonctions du module plume.pg.queries
qui ne renvoient que la requête à proprement parler).
import psycopg2
conn = psycopg2.connect(connection_string)
with conn:
with conn.cursor() as cur:
query = widgetsdict.computing_query(widgetkey, schema_name, table_name)
cur.execute(*query)
result = cur.fetchall()
conn.close()
table_name
est le nom de la table ou vue à documenter. schema_name
est le nom de son schéma.
Intégration du résultat#
Le résultat de la requête, soit result
dans l’exemple de code ci-avant, peut maintenant alimenter le dictionnaire de widgets et son arbre de clés. C’est l’objet de la méthode computing_update
de la classe plume.rdf.widgetsdict.WidgetsDict
.
r = widgetsdict.computing_update(widgetkey, result)
Modification des widgets en conséquence#
Quand le calcul est réalisé alors que le formulaire est déjà intégralement constitué (cas du calcul à déclenchement manuel), les modifications effectuées par WidgetsDict.computing_update
sur le dictionnaire et son arbre de clés doivent être répercutées sur les widgets eux-mêmes.
Pour ce faire, WidgetsDict.computing_update
renvoie, comme toutes les méthodes d’interaction avec le formulaire, un dictionnaire contenant toutes les informations de matérialisation. Cf. Actions contrôlées par les widgets du formulaire pour plus de détails.
Implémentation du calcul automatique#
Le calcul automatique est la première étape de la matérialisation d’un formulaire, juste avant la génération des widgets.
Il s’agit là aussi de boucler sur les clés du dictionnaire de widgets pour exécuter les calculs, mais on utilisera pour ce faire un générateur spécifique, plume.rdf.widgetsdict.WidgetsDict.items_to_compute()
au lieu de dict.items()
. Ce générateur ne considère que les clés nécessitant un calcul (la clé 'auto compute'
de leur dictionnaire interne vaut True
) et utilise une copie du dictionnaire de widgets, afin d’autoriser l’ajout ou la suppression de clés dans le dictionnaire d’origine au cours du traitement.
for widgetkey, internaldict in widgetsdict.items_to_compute():
...
internaldict
est le dictionnaire interne de la clé widgetkey
, soit widgetsdict[widgetkey]
.
À chaque itération, on suivra toutes les étapes du processus de calcul à l’exception de la dernière. Le dictionnaire renvoyé par la méthode plume.rdf.widgetsdict.WidgetsDict.computing_update()
est inutile ici puisque le formulaire n’a pas encore été matérialisé.
Afin d’éviter que les valeurs calculées automatiquement réapparaissent dans le dictionnaire alors que l’utilisateur vient de sciemment les supprimer ou modifier, aucune clé ne sera marquée comme à calculer si le graphe de métadonnées à partir duquel a été généré le dictionnaire (le cas échéant) n’est pas considéré comme « neuf », c’est à dire si son attribut plume.rdf.metagraph.Metagraph.fresh
vaut True
. En pratique, un graphe n’est « neuf » que s’il vient d’être initialisé à partir d’un descriptif PostgreSQL ou s’il est issu d’une réinitialisation. Un graphe produit lors d’une sauvegarde ou d’un import n’est pas « neuf ».
Implémentation du calcul à déclenchement manuel#
Lorsque l’utilisateur clique sur un bouton de calcul du formulaire, toutes les étapes du processus de calcul sont à réaliser.
Cf. Création d’un nouveau widget pour les modalités de création de ces boutons.