Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Publication catalogue sur data.gouv.fr #286

Closed
florimondmanca opened this issue Jun 14, 2022 · 20 comments
Closed

Publication catalogue sur data.gouv.fr #286

florimondmanca opened this issue Jun 14, 2022 · 20 comments
Assignees
Labels

Comments

@florimondmanca
Copy link
Collaborator

florimondmanca commented Jun 14, 2022

Issues liées

Idées pour la suite (hors périmètre de ce ticket) :

  • Après l'implémentation de Régler le niveau d'accès d'une entrée dans le catalogue #289, seules les entrées (fiches) qui ont un niveau d'accès "public" sont dans le fichier CSV public
  • Un fichier CSV qui agrége tous les catalogues
  • Une page qui donne à chaque organisation un lien copiable vers le CSV
  • Un bouton "publier sur data.gouv.fr" qui permet de créer automatiquement une fiche préremlie sur data.gouv.fr décrivant le catalogue et avec un lien vers le CSV.
  • Restreindre la publication des champs complémentaires (permettre aux responsables d'organisations de décider quels champs apparaissent dans le fichier CSV publié en open data)
@Volubyl
Copy link
Collaborator

Volubyl commented Sep 30, 2022

Proposition d'implem (en mode brouillon -- sera poursuivie/approfondie lundi)

Compréhension du besoin

Afin de pouvoir rendre public les catalogue sur data.gouv.fr il est nécessaire de rendre disponible un fichier contenant l'ensemble des jeux de données du catalogue.

Le format de fichier retenu est le CSV

Ce fichier sera disponnible sur une URL dédiée

User stories

  • ETQ responsable d'organisation, je veux publier le catalogue sur data.gouv.fr afin de le rendre accessible au grand public

  • ETQ administrateur (DINUM), je veux un fichier de tous les catalogues publics sur data.gouv.fr

Details d'implémentation

ETQ administrateur (DINUM), je veux un fichier de tous les catalogues publics sur data.gouv.fr**

Analyse de l'existant

La commande GetAllDatasets() retourne un ensemble de DatasetView

class DatasetView(BaseModel):
   id: ID
   catalog_record: CatalogRecordView
   title: str
   description: str
   service: str
   geographical_coverage: str
   formats: List[DataFormat]
   technical_source: Optional[str]
   producer_email: Optional[str]
   contact_emails: List[str]
   update_frequency: Optional[UpdateFrequency]
   last_updated_at: Optional[dt.datetime]
   url: Optional[str]
   license: Optional[str]
   tags: List[TagView]
   extra_field_values: List[ExtraFieldValueView]

   # Extras
   headlines: Optional[DatasetHeadlines] = None

Cette commande utilise la méthode getAll du SqlDatasetRepository

Implem

  1. Récupération des Datasets publics

Questions :

  1. est-ce qu'il vaut mieux modifier le query existante pour récupérer que les datasets marqués comme public ou vaut-il mieux créer une nouvelle query ?

=> a mon avis il est aussi possible d'utiliser la même query en rajoutant une spec dans la class DatasetSpec

On aurait qqch comme ceci

class DatasetSpec:
    search_term: Optional[str] = None
    organization_siret: Optional[Siret] = None
    geographical_coverage__in: Optional[Sequence[str]] = None
    service__in: Optional[Sequence[str]] = None
    format__in: Optional[Sequence[DataFormat]] = None
    technical_source__in: Optional[Sequence[str]] = None
    tag__id__in: Optional[Sequence[ID]] = None
    license: Optional[str] = None
	public_only: Optional[boolean] = false

Le truc c'est que je vois pas bien comment ça s'utiliserait.

J'imagine que ça doit être autour de cet endroit

A ce stade là, on devrait être en capacité de récupérer tous les Datasets "publics"

  1. Transformation de la List de Dataset en CSV

  2. Exposer le CSV via un endpoint de l'API

L'idée serait d'exposer ce fichier CSV via une route sur le serveur un peu à la manière d'un endpoint d'API

Idée de nom de route GET /api/data-gouv/datasets

Questions :

  1. Est-ce qu'il vaut mieux générer le CSV à la demande (à chaque appel sur le endpoint) ou déja générer à l'avance chaque CSV ?

=> si on les génère à l'avance ça implique de stocker un fichier quelque part (sur le serveur? Sur un S3 ?) A chaque création/modification de jeu de donnée il faudra penser a aussi mettre à jour/créer le fichier ...

@Florimond un avis ?

Tâches
  1. récupérer tous les jeux de données marqué comme public
    • modifier la queryhandler et le repository pour avoir un flag permettant de récupérer que les datasets "publics"
    • [] Transformer la List de Datasets en CSV via la lib csv python

ETQ administrateur (DINUM), je veux un fichier de tous les catalogues publics sur data.gouv.fr

To Do

@florimondmanca
Copy link
Collaborator Author

florimondmanca commented Sep 30, 2022

@Volubyl

Pour l'endpoint, j'aurais vu qqc comme:

  • GET /api/catalogs/:siret/export.csv
  • GET /api/catalogs/export.csv

En effet :

  • D'une part l'extension .csv est appropriée (comme on a GET /openapi/schema.json dans le cas d'un endpoint OpenAPI).
  • D'autre part on réalise véritablement un "export CSV" ('export' n'est pas un verbe mais un nom ici, ce qui reste RESTful) des jeux de données en base.
  • (Au final je ne suis pas certain de la pertinence d'ancrer le destinataire présumé de cet endpoint (datagouv) dans l'URL.)
  • Enfin, si je comprends bien on a besoin à la fois de publier un catalogue particulier (ETQ respo d'orga), et de publier le "méta-catalogue" = liste des catalogues (ETQ DINUM). Mais ce 2e point n'est pas clair.
    • cc @johanricher Quel critère d'acceptation permet de vérifier que "ETQ DINUM je veux un fichier de tous les catalogues publics" est satisfait ? Pour l'instant on n'a que "Un lien par catalogue".

est-ce qu'il vaut mieux modifier le query existante pour récupérer que les datasets marqués comme public ou vaut-il mieux créer une nouvelle query ?

De mon point de vue, puisqu'on est sur un cas d'utilisation de l'API différent, il vaut mieux créer une "chaîne" (route, query) différente. En revanche pour les repositories il faut réutiliser ce qui existe il me semble, oui, car ils sont sensés être l'interface "générique" avec le modèle de données.

En particulier, j'imagine que le résultat de la nouvelle query sera un objet particulier (par ex CatalogExport)... et qu'il contiendra les champs correctement nommés selon le catalogue de l'organisation : titre et pas title, mots_cles et pas tags, etc. (Ça peut se faire dans un 2nd temps, une fois l'export "fonctionnel". Par contre on ne stocke pas ce "nom public" (tq défini dans le schéma) dans la DB, donc soit on devra ajouter cette info (par ex en dur pour les champs communs et un champ public_name pour les champs complémentaires), soit on se réfère au JSON du catalogue stocké sur catalogage-donnees-config.)

DatasetSpec

C'est un objet qui permet de filtrer les résultats. Les query params de la recherche avancée finissent dedans. :) En l'occurrence GET /api/catalogs/:siret/export.csv ferait donc probablement une requête GetAllDatasets(spec=DatasetSpec(organization_siret=siret)). Pour GET /api/catalogs/export.csv ce serait côté CatalogRepository a priori.

Est-ce qu'il vaut mieux générer le CSV à la demande (à chaque appel sur le endpoint) ou déja générer à l'avance chaque CSV ?

Une 3e option : générer le CSV à la demande avec mise en cache (par ex 1 jour). En effet les catalogues sont vivants et le site n'est pas statique. On ne peut pas les "générer à l'avance" : il faut pouvoir récupérer une version à jour. Mais un endpoint qui ferait effectivement le calcul à chaque fois est très peu efficace. Tout dépend du rythme de mise à jour côté publication DataGouv. Donner la possibilité d'une mise à jour quotidienne semble acceptable. Concrètement le cache devrait être côté API, donc dans une première approche utiliser un stockage en mémoire sur les serveurs. Pour le calcul de l'expiration : soit 1 jour après le dernier calcul, soit chaque jour à une heure fixée (par ex 1h du matin). Dans l'idéal, pour bien comprendre ce qu'on fait, on ferait une implémentation custom avant de se demander si on pourrait s'appuyer sur une lib existante (cashews, async-cache, etc).

jeux de données marqué comme public

À ce jour on n'a pas encore de notion de restriction d'accès : #289. Donc tout jeu de donné catalogué est "public". Ça me semble une "contrainte" acceptable dans un premier temps ? cc @johanricher. De toute façon la publication sur DataGouv est à l'initiative d'un humain, l'endpoint existera mais ne branchera pas tout seul à un jeu de données dans DataGouv.

@johanricher
Copy link
Member

johanricher commented Sep 30, 2022

Oui le critère d'acceptation de ce ticket c'est "un CSV par catalogue", et qu'il soit téléchargeable sans auth.

La US ("je veux un fichier de tous les catalogues") sert juste à éclairer le besoin de façon plus globale. D'ailleurs ce besoin d'avoir cet espèce de "meta catalogue" interministériel pourrait être adressé par quelqu'un d'autre que nous en faisant une agrégation des différents catalogues CSV.

@johanricher
Copy link
Member

johanricher commented Sep 30, 2022

À ce jour on n'a pas encore de notion de restriction d'accès : #289. Donc tout jeu de donné catalogué est "public". Ça me semble une "contrainte" acceptable dans un premier temps ?

Re-oui cf. ce que j'ai mis en "critères d'acceptation" et "aller plus loin"

@johanricher
Copy link
Member

les champs correctement nommés selon le catalogue de l'organisation : titre et pas title, mots_cles et pas tags, etc. (Ça peut se faire dans un 2nd temps, une fois l'export "fonctionnel".)

Re-re-oui. Le critère d'acceptation minimal c'est un CSV qui reflète le catalogue et son schéma, tel que ça a été implémenté dans le code du logiciel et en base. Ce vers quoi il faut tendre, c'est à dire ce qui est le plus fonctionnel et utile pour l'utilisateur, c'est que le CSV soit conforme au schéma Table Schema du catalogue mais ça engendre de la complexité notamment les points que tu mentionnes, donc à faire dans un second temps (par contre svp listez ça dans un ticket, sinon dans un pad, et je ferai un ticket).

@johanricher
Copy link
Member

Concernant ce qui est acceptable comme rythme de mise à jour du fichier servi par l'API. L'idée du cache me paraît la meilleure car si je comprends bien on implémente quand même la génération à la demande et avec le cache on pourra trouver un compromis entre la "fraicheur" du fichier et la charge du calcul. Dans un premier temps une mise à jour du fichier toutes les 24h me semble acceptable. Je pense que dans un second temps il faudra descendre en dessous de l'heure comme fréquence de mise à jour mais ça pourra faire l'objet d'un ticket dédié.

@Volubyl
Copy link
Collaborator

Volubyl commented Sep 30, 2022

d'acc merci pour les retours. Je vais approfondir mon analyse lundi

@Florimond
Copy link

@florimondmanca Hors sujet, mais je vois qu'on me tag une nouvelle fois en parlant de toi. Il faut vraiment que tu changes de prénom. C'est moi le seul et l'unique! ;P

@Volubyl
Copy link
Collaborator

Volubyl commented Sep 30, 2022

@florimondmanca Hors sujet, mais je vois qu'on me tag une nouvelle fois en parlant de toi. Il faut vraiment que tu changes de prénom. C'est moi le seul et l'unique! ;P

Ce message est juste génial! La probabilité du truc!

@Volubyl
Copy link
Collaborator

Volubyl commented Oct 4, 2022

(Analyse en version quasi finale)

Compréhension du besoin

Afin de pouvoir rendre public les catalogue sur data.gouv.fr il est nécessaire de rendre disponible un fichier contenant l'ensemble des jeux de données du catalogue.

Le format de fichier retenu est le CSV

Ce fichier sera disponnible sur une URL dédiée

User stories

  • ETQ responsable d'organisation, je veux publier le catalogue sur data.gouv.fr afin de le rendre accessible au grand public

- ETQ administrateur (DINUM), je veux un fichier de tous les catalogues publics sur data.gouv.fr

Details d'implémentation

ETQ administrateur (DINUM), je veux un fichier de tous les catalogues publics sur data.gouv.fr

Analyse de l'existant

La commande GetAllDatasets() retourne un ensemble de DatasetView

class DatasetView(BaseModel):
   id: ID
   catalog_record: CatalogRecordView
   title: str
   description: str
   service: str
   geographical_coverage: str
   formats: List[DataFormat]
   technical_source: Optional[str]
   producer_email: Optional[str]
   contact_emails: List[str]
   update_frequency: Optional[UpdateFrequency]
   last_updated_at: Optional[dt.datetime]
   url: Optional[str]
   license: Optional[str]
   tags: List[TagView]
   extra_field_values: List[ExtraFieldValueView]

   # Extras
   headlines: Optional[DatasetHeadlines] = None

Cette commande utilise la méthode getAll du SqlDatasetRepository

Implem

Récupération des Datasets "publiabes"

Handler et query

Le mieux serait de créer une query (idée de nom : GetCatalogExportQuery) et d'une handler GetCatalogExportQueryHandler

Ce handler retournerait une view CatalogExport

Cette view serait construite à partir des résultats en DB mais correctement nommé selon le catalogue de l'oragnisation

Il va donc certainement falloir créer un transformer pour mapper le nom des props vers autres chose

(barrer car pas nécessaire dans un premier temps)

Le truc c'est que je vois pas bien comment ça s'utilisera

Réutiliser le repository avec le filtre "organization"

Il va être aussi nécessaire de modifier le repository

Transformation de la List de Dataset en CSV

Ajouter dans la CatalogExport une méthode "toCSV"

import csv
import io
from typing import TextIO


class CatalogExport:
    def write_csv(self, f: TextIO) -> None:
        writer = csv.DictWriter(f, fieldnames=["title", "description"], delimiter=";")
        writer.writeheader()
        writer.writerow({"title": "Bidule", "description": "Trucmuche"})


with open("monfichier.csv", mode="w") as f:
    CatalogExport().write_csv(f)

s = io.StringIO()
CatalogExport().write_csv(s)
content = s.getvalue()

print(content)

File disposition => téléchargement

Exposer le CSV via un endpoint de l'API

L'idée serait d'exposer ce fichier CSV via une route sur le serveur un peu à la manière d'un endpoint d'API

Idée de nom de route
GET /api/catalogs/:siret/export.csv

Mise en cache du CSV (en faire une US séparée)

L'idée ici est de générer le CSV à la demande avec mise en cache (par ex 1 jour). En effet les catalogues sont vivants et le site n'est pas statique. On ne peut pas les "générer à l'avance" : il faut pouvoir récupérer une version à jour. Mais un endpoint qui ferait effectivement le calcul à chaque fois est très peu efficace. Tout dépend du rythme de mise à jour côté publication DataGouv. Donner la possibilité d'une mise à jour quotidienne semble acceptable. Concrètement le cache devrait être côté API, donc dans une première approche utiliser un stockage en mémoire sur les serveurs. Pour le calcul de l'expiration : soit 1 jour après le dernier calcul, soit chaque jour à une heure fixée (par ex 1h du matin). Dans l'idéal, pour bien comprendre ce qu'on fait, on ferait une implémentation custom avant de se demander si on pourrait s'appuyer sur une lib existante (cashews, async-cache, etc).

Dans un premier temps en partirait sur un système de cache "a la mano" pour ne pas directement sortir la grosse machinerie "redis", "memcache"

https://docs.python.org/3/library/functools.html#functools.lru_cache

Tâches pour la récupération d'un jeu de donnée pour une organisation

  1. récupérer le jeu de donnée lié à un siret
    • modifier la chaine query, query handler et le repository pour avoir un flag permettant de récupérer que les datasets "publiables" + tests
    • Transformer la List de Datasets en CSV via la lib csv python
    • Mettre en cache le résultat de la requète

Rajouter un boutton sur la UI

Ici l'idée c'est de rajouter un bouton qui faerait un appel HTTP vers GET /api/catalogs/:siret/export.csv pour déclancher la génération du fichier CSV

@DaFrenchFrog on le mettrais à quel endroit ?

Tests fonctionnels
  • vérifier la présence d'un header X-Cached après le second appel
  • vérifier que le fichier csv reçu après avoir mis l'url dans le navigateur est bien formé (l'importer dans libreoffice par exemple)

@florimondmanca
Copy link
Collaborator Author

@Volubyl

Ici l'idée c'est de rajouter un bouton sur la page du jeu de donnée qui faerait un appel HTTP vers GET /api/catalogs/:siret/export.csv pour déclancher la génération du fichier CSV

Ça me semblerait curieux étant donné qu'on exporte "un catalogue" et non pas "un jeu de données".

On n'a pas à ce jour de "page de catalogue" il me semble. Aussi je ne sais pas où pourrait apparaître ce "bouton / lien export catalogue"...

@Volubyl
Copy link
Collaborator

Volubyl commented Oct 4, 2022

T'as raison @florimondmanca j'ai écrit trop vite sans faire la dinstinction catalogue/jeu de donnée

Dans la UI le seul endroit où l'on a une représentation graphique du catalogue c'est la liste qui est en home page quand on est connecté.

Est-ce que l'on rajouterais un bouton à chaque ligne ?

@johanricher
Copy link
Member

johanricher commented Oct 5, 2022

Une intervention sur le front telle que l'ajout d'un bouton n'est pas un critère d'acceptation de ce ticket (c'est à dire pas nécessaire pour répondre au besoin exprimé). C'est plutôt une "idée pour la suite" (cf. "Aller plus loin"), bien distincte de ce ticket, et qu'il faudrait le cas échéant d'abord exprimer sous forme de besoin utilisateur, puis designer et enfin prioriser dans une itération ultérieure.

@johanricher
Copy link
Member

johanricher commented Oct 5, 2022

Pour être clair sur comment ça va se passer en pratique, avec cette feature telle que spécifiée et à implémenter ici :
Quand les personnes concernées (plutôt les responsables d'organisations) voudront publier leur catalogue sur data.gouv.fr, on leur donnera le lien.

Un lien pour télécharger un catalogue sera sous la forme https://catalogue.data.gouv.fr/api/catalogs/{SIRET}/export.csv (si je dis pas de bêtise). Le fichier pourra être téléchargé sans authentification et donc publié en open data (avec une licence associée) sur data.gouv.fr.

D'autres utilisateurs plus avancés pourront découvrir (ou être orientés vers) cette feature grâce à la doc de notre API où ce endpoint sera spécifié (encore une fois je vous laisse me corriger si je dis une bêtise).

@Volubyl
Copy link
Collaborator

Volubyl commented Oct 5, 2022

j'ai tout de même une question p-e lié a un manque de compréhension

Si on part du principe qu'il suffit de mettre une URL https://catalogue.data.gouv.fr/api/catalogs/{SIRET}/export.csv dans un navigateur pour télécharger le catalogue d'une orga en CSV cela veut dire qu'il est possible de télécharger le catalogue de toutes les organisation et ce sans restriction.

C'est bien cela ?

@johanricher
Copy link
Member

A ce stade, notamment avant que #289 soit implémenté, oui c'est bien ça.

@florimondmanca
Copy link
Collaborator Author

florimondmanca commented Oct 12, 2022

@johanricher On a mergé #480, l'endpoint CSV public. Je vais déployer. Il semble que malgré les suites possibles évoquées (niveau d'accès...), on puisse fermer cette epic "contractuelle" ?

@johanricher
Copy link
Member

C'est en prod sur https://catalogue.data.gouv.fr/api ? Est-ce que ce endpoint peut être documenté ("Get catalog CSV") sur https://catalogue.data.gouv.fr/api/docs ?

@florimondmanca
Copy link
Collaborator Author

Mon message était un peu avance, je viens de déployer, tu peux réessayer d'y accéder.

https://catalogue.data.gouv.fr/api/docs#/catalogs/export_catalog_catalogs__siret__export_csv_get

@johanricher
Copy link
Member

Magnifique

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants