MTES-MCT / metadata-postgresql

Plume : gestion des métadonnées du patrimoine PostgreSQL
https://mtes-mct.github.io/metadata-postgresql/
GNU Affero General Public License v3.0
1 stars 1 forks source link

Formats et extensions dans la fonctionnalité d'export #24

Closed alhyss closed 2 years ago

alhyss commented 2 years ago

Salut @WREATCHED !

Petit point de détail, j'ai l'impression qu'il y a de petites confusions entre format et extension du fichier dans la fonctionnalité d'export.

Par exemple, quand je choisis le format pretty-xml dans le menu, la boîte de dialogue affiche : export_format_extension_actuel

Or l'extension par défaut pour le format pretty-xml est '.rdf', pas .pretty-xml qui n'est absolument pas une extension standard. Et c'est aussi un peu dommage que la liste des formats affiche l'item correspondant au format turtle et non celui de pretty-xml. L'idéal serait d'avoir quelque chose comme ça : export_format_extension_cible

Dans plume.plume_ui.Ui_Dialog_Plume.clickButtonsExportActions, si ce que tu récupères dans ta variable mItemExport est le nom de l'item du menu sur lequel l'utilisateur vient de cliquer, alors il s'agit bien du format et non l'extension du fichier. Le fait que le troisième argument de plume.bibli_plume.exportObjetMetagraph, auquel tu passes cette valeur, s'appelle extension induit peut-être un peu en erreur. Idem d'ailleurs pour mListExtensionExport, qui contient bien une liste de formats et non d'extensions.

À première vue, il me semble qu'il faudrait faire les ajustements suivants dans plume.bibli_plume.exportObjetMetagraph :

        if elem !=  modelExt[1:] :
           extStrExt += "*." + str(elem) + " "

On aura alors dans la liste turtle (*.ttl) au lieu de turtle (*.ttl *.turtle), json-ld (*.jsonld) au lieu de turtle (*.jsonld *.json-ld), etc.

ça pourrait donner :

    InitDir = os.path.join(os.path.join(os.environ['USERPROFILE']), 'Desktop')  \
        + "\\" + "metadata_" + str(schema) + "_" + str(table) + export_extension_from_format(extension)

au lieu de :

    InitDir = os.path.join(os.path.join(os.environ['USERPROFILE']), 'Desktop') + "\\" + "METADATA_" + str(schema) + "_" + str(table) + "." + extension

(pur caprice de ma part, mais est-ce que le préfixe 'METADATA_' que tu ajoutes au nom du fichier pourrait être en minuscules ? pour simplifier la vie de ceux - dont je fais partie... - qui veillent encore à ne pas avoir de majuscules dans leurs noms de fichiers)

    fileName, extension = os.path.splitext(fileName)[0], os.path.splitext(fileName)[1][1:]

Pas besoin de la remplacer par quoi que ce soit. Les variables fileName et extension que tu passeras ensuite à la méthode plume.rdf.metagraph.Metagraph.export contiennent déjà exactement ce qu'attend cette méthode, à savoir :

WREATCHED commented 2 years ago

Donc, Pas tout à fait ok sur le dernier point, mais c'est normal

mListExtensionFormat = sorted(mListExtensionFormat, key=lambda x: -1 if x==format else mListExtensionFormat.index(x))
for elem in mListExtensionFormat :
    modelExt = export_extension_from_format(elem)
    extStrExt = "*" + str(modelExt) + " "
    extStr += ";;" + str(elem) + " (" + str(extStrExt) + ")"
TypeList = extStr[2:]
table = table.replace(".","_").replace(" ","_")
InitDir = os.path.join(os.path.join(os.environ['USERPROFILE']), 'Desktop') + "\\" + "metadata_" + str(schema) + "_" + str(table) + "" +  export_extension_from_format(format)
mDialogueSave = QFileDialog

fileName = mDialogueSave.getSaveFileName(None,QtWidgets.QApplication.translate("plume_ui", "PLUME Export des fiches de métadonnées", None),InitDir,TypeList)[0]

format = export_format_from_extension(os.path.splitext(fileName)[1])

if fileName == "" : return
#**********************
# Export fiche de métadonnée
try:
   self.metagraph.export(fileName, format)
alhyss commented 2 years ago

Si je comprends bien, tu priorises l'extension saisie dans la boîte de dialogue par rapport au format choisi au départ ? C'est logique, effectivement, sans ça la liste déroulante de la boîte de dialogue ne permettrait pas de changer de format a posteriori. Mais quid du cas où l'utilisateur supprime involontairement l'extension en saisissant le nom du fichier ? Dans ce cas plume.rdf.utils.export_format_from_extension ne renvoie rien.

Dans ce cas, on pourrait garder le format initial :

format = export_format_from_extension(os.path.splitext(fileName)[1]) or format

Je suis embêtée par le cas des formats xml et pretty-xml, cependant. Les deux utilisent les mêmes extensions, donc j'ai dû faire un choix pour plume.rdf.utils.export_format_from_extension. Concrètement, la fonction renvoie toujours pretty-xml pour xml et rdf. Ça implique que, même si l'utilisateur choisit volontairement le format xml et pas pretty-xml dans le menu de Plume, il va se retrouver avec du pretty-xml au final.

Les deux donnent des choses très différentes.

Un graphe exporté avec le format xml :


<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF
   xmlns:dcat="http://www.w3.org/ns/dcat#"
   xmlns:dct="http://purl.org/dc/terms/"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
>
  <rdf:Description rdf:about="urn:uuid:479fd670-32c5-4ade-a26d-0268b0ce5046">
    <rdf:type rdf:resource="http://www.w3.org/ns/dcat#Dataset"/>
    <dct:accessRights rdf:nodeID="nbb830ca5a03e460db9ad9f364a84dcc1b1"/>
    <dct:title xml:lang="fr">ADMIN EXPRESS - Départements de métropole</dct:title>
    <dct:title xml:lang="en">ADMIN EXPRESS - Metropolitan Departments</dct:title>
    <dcat:keyword xml:lang="fr">admin express</dcat:keyword>
    <dcat:keyword xml:lang="fr">donnée externe</dcat:keyword>
    <dcat:keyword xml:lang="en">external data</dcat:keyword>
    <dcat:keyword xml:lang="fr">ign</dcat:keyword>
    <dct:temporal rdf:nodeID="nbb830ca5a03e460db9ad9f364a84dcc1b2"/>
    <dcat:theme rdf:resource="http://inspire.ec.europa.eu/theme/au"/>
    <dct:identifier>479fd670-32c5-4ade-a26d-0268b0ce5046</dct:identifier>
  </rdf:Description>
  <rdf:Description rdf:nodeID="nbb830ca5a03e460db9ad9f364a84dcc1b2">
    <rdf:type rdf:resource="http://purl.org/dc/terms/PeriodOfTime"/>
    <dcat:endDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2021-01-15</dcat:endDate>
    <dcat:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2021-01-15</dcat:startDate>
  </rdf:Description>
  <rdf:Description rdf:nodeID="nbb830ca5a03e460db9ad9f364a84dcc1b1">
    <rdf:type rdf:resource="http://purl.org/dc/terms/RightsStatement"/>
    <rdfs:label xml:lang="fr">Aucune restriction d'accès ou d'usage.</rdfs:label>
  </rdf:Description>
</rdf:RDF>

Le même graphe en pretty-xml :


<?xml version="1.0" encoding="utf-8"?>
<rdf:RDF
  xmlns:dct="http://purl.org/dc/terms/"
  xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  xmlns:dcat="http://www.w3.org/ns/dcat#"
>
  <dcat:Dataset rdf:about="urn:uuid:479fd670-32c5-4ade-a26d-0268b0ce5046">
    <dct:accessRights>
      <dct:RightsStatement rdf:nodeID="nbb830ca5a03e460db9ad9f364a84dcc1b1">
        <rdfs:label xml:lang="fr">Aucune restriction d'accès ou d'usage.</rdfs:label>
      </dct:RightsStatement>
    </dct:accessRights>
    <dct:title xml:lang="fr">ADMIN EXPRESS - Départements de métropole</dct:title>
    <dct:title xml:lang="en">ADMIN EXPRESS - Metropolitan Departments</dct:title>
    <dcat:keyword xml:lang="fr">admin express</dcat:keyword>
    <dcat:keyword xml:lang="fr">donnée externe</dcat:keyword>
    <dcat:keyword xml:lang="en">external data</dcat:keyword>
    <dcat:keyword xml:lang="fr">ign</dcat:keyword>
    <dct:temporal>
      <dct:PeriodOfTime rdf:nodeID="nbb830ca5a03e460db9ad9f364a84dcc1b2">
        <dcat:endDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2021-01-15</dcat:endDate>
        <dcat:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2021-01-15</dcat:startDate>
      </dct:PeriodOfTime>
    </dct:temporal>
    <dcat:theme rdf:resource="http://inspire.ec.europa.eu/theme/au"/>
    <dct:identifier>479fd670-32c5-4ade-a26d-0268b0ce5046</dct:identifier>
  </dcat:Dataset>
</rdf:RDF>

En gros, en pretty-xml, les noeuds anonymes sont imbriqués, en xml ils sont gérés comme des éléments à part. Il ne me paraît pas impensable qu'une application puisse être capable de gérer un format et pas l'autre, donc je trouve plutôt pertinent de proposer les deux.

Une solution possible serait que je modifie la fonction plume.rdf.utils.export_format_from_extension pour lui donner un second argument optionnel correspondant à un format par défaut qui, si présent, sera utilisé si :

Pour toi, ça voudrait dire remplacer :

format = export_format_from_extension(os.path.splitext(fileName)[1])

par :

format = export_format_from_extension(os.path.splitext(fileName)[1], format)

Est-ce qu'on part là-dessus ?

WREATCHED commented 2 years ago

Yes

alhyss commented 2 years ago

C'est bon pour la modification de plume.rdf.utils.export_format_from_extension, qui prend maintenant un second argument pour le format par défaut - default_format - avec le comportement décrit ci-avant.

WREATCHED commented 2 years ago

Tjs un pb, j'ai la même extension (rdf) pour deux types de format (Pretty-xml) et (xml)

alhyss commented 2 years ago

Effectivement, je n'avais pas vu cet aspect du problème.

Comme évoqué ensemble, l'idée sera que la sélection du format via la boîte de dialogue ne permette de choisir qu'un seul format par extension. Concrètement, si l'utilisateur avait sélectionné le format xml, alors l'extension .rdf ne lui permettra plus de choisir le format pretty-xml, il verra seulement xml (.rdf) dans sa liste. Dans tous les autres cas, il ne verra que pretty-xml (.rdf) (car pretty-xml est le format par défaut pour l'extension .rdf).

Pour que ça fonctionne, il faut que tu modifies ta méthode plume.plume_ui.Ui_Dialog_plume.clickButtonsExportActions, en remplaçant cet appel :

exportObjetMetagraph(self, self.schema, self.table, mItemExport, self.mListExtensionFormat)

par celui-là :

exportObjetMetagraph(self, self.schema, self.table, mItemExport,
    self.metagraph.available_export_formats(no_duplicate=True, format=mItemExport))

self.mListExtensionFormat contenait la liste complète des formats qui apparaît dans le menu de Plume, donc pas celle qui doit servir pour le menu déroulant de la boîte de dialogue. La liste restreinte est calculée par la méthode plume.rdf.metagraph.Metagraph.available_export_formats, qui prend en argument un paramètre booléen lui disant d'éliminer les doublons, ainsi que le fameux format pré-sélectionné (afin de le conserver dans la liste même si ce n'est pas un format par défaut).

Quitte à boucler sur les formats, plume.rdf.metagraph.Metagraph.available_export_formats renvoie une liste triée où le format pré-sélectionné est toujours la première valeur. La commande que je t'avais fait ajouter à cette fin dans plume.bibli_plume.exportObjetMetagraph devient donc inutile :

mListExtensionFormat = sorted(mListExtensionFormat, key=lambda x: -1 if x==format else mListExtensionFormat.index(x))

Tu dois pouvoir la supprimer.

WREATCHED commented 2 years ago

Ouf ouf, c'est tout bon Je pense que l'on peut clore