Spécification de contenu sur Zeste de Savoir, ou sa version brouillon

Brace yourself, ZEP-12 is coming

Le problème exposé dans ce sujet a été résolu.

Je dis pas le contraire. Donc tu veux virer les dits champs, en gros (ou assumer qu'en leur absence, les fichiers existent effectivement bien aux endroits qu'on attend d'eux).

Remarque : on peut étendre ça à toute spécification de chemin de fichier : si c'est pas précisé, on s'attend que le fichier se trouve à tel endroit.

+0 -0

Je note.

Le plus "dur" sera le "slug unique au sein d'un tuto". Cela impose de conserver un dictionnaire de slug (justement pour éviter de tout reparcourir à chaque fois).

Déjà implémenté (en local). C'était pas très compliqué, en fait: une pitite liste de tout les slugs stockée dans le conteneur principale, une fonction get_unique_slug() qui va vérifier si le slug existe déjà et qui lui ajoute de manière incrémentale un nombre si c'est le cas, et le tour est joué :)

(j'ai écrit ma spec' après avoir développé le code. Si je l'ai pas repoussé vers ta branche, c'est simplement parce que j'attend un peu de retour ici :) )

PS: j'en ai profité pour rajouter le truc des dicos de slugs pour pouvoir faire de la résolution d'url vite fait bien fait.

+0 -0

Déjà implémenté (en local). C'était pas très compliqué, en fait: une pitite liste de tout les slugs stockée dans le conteneur principale, une fonction get_unique_slug() qui va vérifier si le slug existe déjà et qui lui ajoute de manière incrémentale un nombre si c'est le cas, et le tour est joué :)

liste = vérification en O(n), toi qui veut optimiser, utilise des dictionnaires si tu en as la possibilité.

Quoi, comme ça ?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
def get_unique_slug(self, title):
  new_slug = slugify(title)
  try:
    dummy = self.dic_of_slug[new_slug]
  except KeyError:
    pass
  else:
    n = 0
    while True:
      n += 1
      new_slug_ = new_slug + '-' + str(n)
      try :
        dummy = self.dic_of_slug[new_slug_]
      except KeyError:
        break
    new_slug = new_slug_
  self.dic_of_slug[new_slug] = True # faut bien lui donner une valeur
  return new_slug

Ça m'as l'air juste … Moche, puis j'ai l'impression de détourner le principe des dictionnaires pour rien. Fonctionnellement parlant, dic_of_slug n'as aucun sens.

EDIT je viens de benchmarker la question, et il se trouve que tu as raison (tu me dira "je le savais" :p ). Ceci dit … Y'a pas moyen de faire ça de manière plus "jolie" ?

+0 -0

Perso, ne pas avoir de clés introduction ou conclusion serait une erreur. Vérifier si les clés existent ou pas, je pense que c'est beaucoup moins bouffeur de perf que de vérifier si un fichier existe (surtout quand le manifest est déjà chargé et donc déjà interprété…). Et surtout c'est beaucoup plus libre…

Et je comprends toujours pas en quoi le slug peut poser des problèmes, surtout si on choisi de générer en fonction du nom de la partie (qui, soyons un peu réaliste, nommerait deux contenus au même niveau et de la même manière ? Au pire (soit quoi.... 0,00001% des cas, et encore ?), ça écrase)

Et concernant le blocage de slugs introduction et conclusion, c'est, admettons le, une belle fumesterie aussi. Pourquoi devrait-on pouvoir consulter ces parties à part ? Il n'y a pas de sens a fracturer une "partie" (qui a plusieurs feuilles). Je trouve que y'a pas pire coupure de lecture que de fracturer en autant de morceau… Même OC ne le fait pas. Manquerait plus qu'a pouvoir consulter un texte paragraphe par paragraphe !

+0 -0

Vérifier si les clés existent ou pas, je pense que c'est beaucoup moins bouffeur de perf que de vérifier si un fichier existe (surtout quand le manifest est déjà chargé et donc déjà interprété…). Et surtout c'est beaucoup plus libre…

le problème c'est que la vérification ne se fait que… lorsqu'il y a importation. Sauf si bien sûr on change le comportement actuel qui crée une intro et ccl automatiquement.

Et je comprends toujours pas en quoi le slug peut poser des problèmes, surtout si on choisi de générer en fonction du nom de la partie (qui, soyons un peu réaliste, nommerait deux contenus au même niveau et de la même manière ? Au pire (soit quoi.... 0,00001% des cas, et encore ?), ça écrase)

sauf si on veut déplacer un extrait dans un autre chapitre… Mais sinon je suis 100% d'accord. Il y a aussi le fait que la rétrocompatibilité doit être assurée.

Et je comprends toujours pas en quoi le slug peut poser des problèmes, surtout si on choisi de générer en fonction du nom de la partie (qui, soyons un peu réaliste, nommerait deux contenus au même niveau et de la même manière ? Au pire (soit quoi.... 0,00001% des cas, et encore ?), ça écrase)

Au pire du pire, la condition existe et atragis m'as donné le truc pour passer relativement rapidement dessus. Si elle est jamais employée, tant mieux :)

Et concernant le blocage de slugs introduction et conclusion, c'est, admettons le, une belle fumesterie aussi. Pourquoi devrait-on pouvoir consulter ces parties à part ? Il n'y a pas de sens a fracturer une "partie" (qui a plusieurs feuilles). Je trouve que y'a pas pire coupure de lecture que de fracturer en autant de morceau… Même OC ne le fait pas. Manquerait plus qu'a pouvoir consulter un texte paragraphe par paragraphe !

Talus

J'avoue que j'ai pas bien compris ce que tu voulais dire par là ^^

le problème c'est que la vérification ne se fait que… lorsqu'il y a importation. Sauf si bien sûr on change le comportement actuel qui crée une intro et ccl automatiquement.

En quoi ça poserai problème de le changer, en fait ?

+0 -0

(Ça n'intéresse personne, mais j'ai trouvé encore plus opti pour la liste de slug:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from collections import Counter
slug_counter = Counter()
def get_unique_slug_counter(title):
  base = slugify(title)
  n = slug_counter[base]
  if n > 0:
    new_slug = base + '-' + str(n)
  else:
    new_slug = base
  slug_counter.update([base])
  return new_slug

Ça donne encore mieux que la fonction que j'ai donné plus haut, et c'est un dico derrière, donc c'est un temps d'accès en $\mathcal{O}(1)$. Voilà)

Et concernant le blocage de slugs introduction et conclusion, c'est, admettons le, une belle fumesterie aussi. Pourquoi devrait-on pouvoir consulter ces parties à part ? Il n'y a pas de sens a fracturer une "partie" (qui a plusieurs feuilles). Je trouve que y'a pas pire coupure de lecture que de fracturer en autant de morceau… Même OC ne le fait pas. Manquerait plus qu'a pouvoir consulter un texte paragraphe par paragraphe !

Talus

J'avoue que j'ai pas bien compris ce que tu voulais dire par là ^^

pierre_24

J'ai cru voir qu'il y aurait un problème avec des slugs introduction et conclusion. Comme je l'ai dit, c'est une fumisterie ; pourquoi aurait-on besoin d'accéder a l'intro ou la conclusion via un slug ? Normalement, on est censé pouvoir soit voir en entier un conteneur (enfin, la liste de ses enfants, son intro et sa conclu), soit voir un de ses enfants. Et dans ce dernier cas, pas besoin d'avoir l'intro ou la conclu séparée…

Du coup mettre un slug sur l'intro ou la conclu n'a juste sémantiquement aucun sens… Sinon autant en mettre paragraphe par paragraphe, voir même mot par mot (soyons fou) !

+1 -0

Du coup mettre un slug sur l'intro ou la conclu n'a juste sémantiquement aucun sens… Sinon autant en mettre paragraphe par paragraphe, voir même mot par mot (soyons fou) !

en fait le problème qu'il y a derrière c'est qu'on crée un fichier à partir du slug.

Or, dans ton conteneur, l'intro et la conclusion ont leur fichier introduction.md et conclusion.md. Ainsi, tout titre qui aurait pour slug "introduction" écrase la fameuse intro et créait à l'époque une erreur 500 (car l'extrait était en bdd, aujourd'hui ça ne le ferait peut être plus…).

C'est plus un problème de backend que de fonctionnalité en soit. Les mots "introduction" et "conclusion" sont des mots clefs, point.

(note: grillé par artragis)

Et concernant le blocage de slugs introduction et conclusion, c'est, admettons le, une belle fumesterie aussi. Pourquoi devrait-on pouvoir consulter ces parties à part ? Il n'y a pas de sens a fracturer une "partie" (qui a plusieurs feuilles). Je trouve que y'a pas pire coupure de lecture que de fracturer en autant de morceau… Même OC ne le fait pas. Manquerait plus qu'a pouvoir consulter un texte paragraphe par paragraphe !

Talus

J'avoue que j'ai pas bien compris ce que tu voulais dire par là ^^

pierre_24

J'ai cru voir qu'il y aurait un problème avec des slugs introduction et conclusion. Comme je l'ai dit, c'est une fumisterie ; pourquoi aurait-on besoin d'accéder a l'intro ou la conclusion via un slug ? Normalement, on est censé pouvoir soit voir en entier un conteneur (enfin, la liste de ses enfants, son intro et sa conclu), soit voir un de ses enfants. Et dans ce dernier cas, pas besoin d'avoir l'intro ou la conclu séparée…

Du coup mettre un slug sur l'intro ou la conclu n'a juste sémantiquement aucun sens… Sinon autant en mettre paragraphe par paragraphe, voir même mot par mot (soyons fou) !

Talus

Je vois d'ou vient le malaise. De mauvais souvenirs dans ton passé avec la couleur orange ?

Plus sérieusement, le but n'est pas d'accéder à l'introduction et la conclusion de manière séparée comme ce fut le cas ailleurs à un moment, ça n'aurait pas de sens comme tu dit d'autant qu'on a pas de pub a afficher. Le problème de collision se situe ici au niveau du stockage : puisque le slug est donné comme nom de dossier/fichier (ce qui simplifie énormément le stockage, crois moi), il faut qu'il n'y aie pas possibilité d'obtenir comme slug introduction, ou on va tomber sur deux fichiers introduction.md, et crac (et qui n'aurait pas envie de faire un extrait appelé "introduction" ?). Le blocage se situe simplement à ce niveau là. Bien sur, ce blocage n'as pas lieu d'être si on nomme les fichiers en question Introduction.md, puisqu'un slug peut pas contenir de majuscule, ou #introduction.md, puisque le caractère # est interdit dans un slug.

  • sha_draft fait référence au brouillon courant ou à tous ceux précédents (plus le courant) ?

Le brouillon courant. Tout ces sha font référence à UNE version bien précise.

pierre_24

Conserve-t-on également les sha des versions précédentes ou juste ceux du brouillon courant et des versions en bêta, validation et ligne ?

+0 -0

Et pourquoi pourrait-on tomber sur deux slugs introduction.md ? Voir même, pourquoi forcement utiliser un autre nom de fichier plutot que celui qui est à charger ? Si je mets une valeur dans ma propriété introduction, je m'attends a ce que le fichier md généré… ait cette valeur !

Si c'est pour passer par l'interface, alors suffit de générer un nom de fichier random lors de la création de l'intro et de s'y tenir (pareil pour la conclu)

+0 -0

bah comme on utilise git, on est capable de retrouver n'importe quel sha. Mais en bdd, on donne juste trois versions "remarquables" : la dernière version de modification en date, la dernière version mise en béta et la dernière version mise en validation. La version de "prod" a une vie à part.

Et pourquoi pourrait-on tomber sur deux slugs introduction.md

Certains vieux tuto ont une partie qui se nomme "fonctions de base" puis un extrait qui se nomme "introduction" qui est lui même situé après l'introduction. On a une exigence de rétrocompatibilité quand même.

Conserve-t-on également les sha des versions précédentes ou juste ceux du brouillon courant et des versions en bêta, validation et ligne ?

Vayel

Non, on n'en garde que un à chaque fois. Il faut savoir qu'il est possible de lire l'historique de GIT pour récupérer de toute façon tout (!) les hashs de toutes les versions précédentes, c'est par exemple ce qui est fait lorsqu'on affiche l'historique des tutoriels actuellement. Ceci dit, je vais me répéter, mais ça n'aurait aucun sens que le brouillon corresponde à plusieurs versions à la fois (ceci pourrait changer dans le futur avec l'apparition de branches multiples, mais actuelement, ça n'as aucun sens). Pour simplifier le problème, ça revient exactement au même que de dire que ça n'as aucun sens de mettre deux versions en bêta, ou deux versions en validation.

Donc sha_* = une version.

Et pourquoi pourrait-on tomber sur deux slugs introduction.md ? Voir même, pourquoi forcement utiliser un autre nom de fichier plutot que celui qui est à charger ? Si je mets une valeur dans ma propriété introduction, je m'attends a ce que le fichier md généré… ait cette valeur !

Le problème ne se pose évidement pas, puisque toi, tu sais pertinemment bien que deux fichiers ne peuvent avoir le même nom, donc en cas d'édition externe, la question ne se pose évidement pas.

Si c'est pour passer par l'interface, alors suffit de générer un nom de fichier random lors de la création de l'intro et de s'y tenir (pareil pour la conclu)

Talus

Alors pareil, ce nom en question sera un slug "interdit". En plus, j'aime pas trop l'idée d'avoir des fichiers "hi!"guf&#.md dans un dossier ne sachant pas s'ils correspondent à l'intro ou la conclusion. Le nom doit rester un minimum logique ^^

Si le manifest n'est pas en version 2 (vu que y'avait une notion de version, si j'ai pas encore perdu le truc), osef de la compatibilité. Semver, anyone ?

Talus

On ne peut pas. À moins de virer tout les historiques de tout les contenus à ce jour, on doit pouvoir s'adapter à un ancien manifest.json et le rendre du mieux qu'on peut.

Ou j'ai pas compris le doc et tu veux simplement que je mette "2.0" à la place ?

+0 -0

Et pourquoi pourrait-on tomber sur deux slugs introduction.md ? Voir même, pourquoi forcement utiliser un autre nom de fichier plutot que celui qui est à charger ? Si je mets une valeur dans ma propriété introduction, je m'attends a ce que le fichier md généré… ait cette valeur !

Le problème ne se pose évidement pas, puisque toi, tu sais pertinemment bien que deux fichiers ne peuvent avoir le même nom, donc en cas d'édition externe, la question ne se pose évidement pas.

Si c'est pour passer par l'interface, alors suffit de générer un nom de fichier random lors de la création de l'intro et de s'y tenir (pareil pour la conclu)

Talus

Alors pareil, ce nom en question sera un slug "interdit". En plus, j'aime pas trop l'idée d'avoir des fichiers "hi!"guf&#.md dans un dossier ne sachant pas s'ils correspondent à l'intro ou la conclusion. Le nom doit rester un minimum logique ^^

pierre_24

Oui, mais suffit d'employer un hash / slug / nom de fichier random. Donc plus un jfrieo-3432-fej.md par exemple (un truc valide en somme)

Si le manifest n'est pas en version 2 (vu que y'avait une notion de version, si j'ai pas encore perdu le truc), osef de la compatibilité. Semver, anyone ?

Talus

On ne peut pas. À moins de virer tout les historiques de tout les contenus à ce jour, on doit pouvoir s'adapter à un ancien manifest.json et le rendre du mieux qu'on peut.

Ou j'ai pas compris le doc et tu veux simplement que je mette "2.0" à la place ?

pierre_24

Non, ce que je veux dire par là : c'est un manifest (ou une version de celui-ci) en 2.0 ? Osef de la compat, utilisons le mécanisme de la 2.0. Sinon, utilisons le mécanisme de 1.0… C'est tout con

Surtout que les deux systèmes sont completement différents, donc cohabitables à priori plutôt que d'introduire des trucs de compat chelous qui seront par la suite chiants a maintenir

non je pense qu'il veut que ZDS + ZEP 12 = ZDS v2.0.0

artragis

Pas tout à fait ; ZEP-12 = "Nouvelle version du système de tutos" si tu préfères. Car c'est bien de ça dont on parle ; c'est quand même un gros refactoring (voir du from scratch)

+0 -0

Surtout que les deux systèmes sont completement différents, donc cohabitables à priori plutôt que d'introduire des trucs de compat chelous qui seront par la suite chiants a maintenir

très sérieusement, je pense qu'il faut plutôt faire une migration totale de la version 1 vers la version 2. Perdre toutes les améliorations, notamment de performance et de flexibilité de la v2 juste parce qu'un tuto a été commencé sur la v1, bof quoi.

C'est quoi le problème avec le fait de nommer les fichiers d'introduction et conclusion différemment (mais intelligiblement, via #introduction par exemple, comme l'a dit pierre) ? S'il n'y en a pas, j'avoue ne pas comprendre de quoi on parle. ^^'

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte