internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: zestedesavoir/zds-site

Issue:
La compilation LaTeX dépend de chemins hardcodés
https://github.com/zestedesavoir/zds-site/blob/751d9930c4534acfef07a81c7cc5c47e5d105fd3/zds/tutorialv2/publication_utils.py#L382-L388

Est-ce vraiment nécessaire ? À aucun moment c'est garanti que c'est installé à cet endroit. Il y a un mécanisme de recherche de paquets dans latex pour ça, symlink des fichiers comme ça à l'arrache, c'est pas très beau.

C'est bloquant pour le déploiement.

cc @artragis 


Discussion:
Dans mes tests j'ai cloné latex-template en récursif dans `TEXMFHOME/tex/generic/`, et ça marchait™.
cf le projet latex-template, je n'ai fait que porter ce qu'ils demandaient
au départ on n'en avait pas beosin mais on a eu des pbs lorsqu'on est passé à lualatex.

Comme le dis @sandhose, c'est sencé fonctionner si tu met le .cls et le .lua dans `$TEXMFMACHIN`. Il faut juste, comme tu l'a dit, faire un `texhash` après.
il me semble que @vhf avait eu des soucis, c'est même pour ça qu'il avait ajouté cette copie. A l'heure actuelle, tout fonctionne, et le script d'installation est bon.

Si vous avez une solution qui marche bien partout je veux bien faire la revue, mais ça serait cool que ça ne ralentisse pas la release, ça fait vraiment longtemps que c'est dans les tuyaux là.

Resolving patch:
diff --git a/zds/settings/abstract_base/zds.py b/zds/settings/abstract_base/zds.py
--- a/zds/settings/abstract_base/zds.py
+++ b/zds/settings/abstract_base/zds.py
@@ -186,7 +186,8 @@
             'toc': Path('toc.css'),
             'full': Path(BASE_DIR) / 'dist' / 'css' / 'zmd.css',
             'katex': Path(BASE_DIR) / 'dist' / 'css' / 'katex.min.css'
-        }
+        },
+        'latex_template_repo': 'NOT_EXISTING_DIR'
     },
     'forum': {
         'posts_per_page': 21,
diff --git a/zds/tutorialv2/publication_utils.py b/zds/tutorialv2/publication_utils.py
--- a/zds/tutorialv2/publication_utils.py
+++ b/zds/tutorialv2/publication_utils.py
@@ -379,7 +379,7 @@ def publish(self, md_file_path, base_name, **kwargs):
         )
         if content == '' and messages:
             raise FailureDuringPublication('Markdown was not parsed due to {}'.format(messages))
-        zmd_class_dir_path = Path(os.environ.get('HOME', '~')) / 'texmf' / 'tex' / 'latex'
+        zmd_class_dir_path = Path(settings.ZDS_APP['content']['latex_template_repo'])
         if zmd_class_dir_path.exists() and zmd_class_dir_path.is_dir():
             with contextlib.suppress(FileExistsError):
                 zmd_class_link = base_directory / 'zmdocument.cls'


Test patch:
Repository: zestedesavoir/zds-site

Issue:
 Insertion du smiley >_<
On obtient `&gt;_&lt;`

Solution 1 : Modifier le code ici : https://github.com/zestedesavoir/zds-site/blob/4ae0431bbf199e318dd6f2b1301ac7b6adc40198/assets/js/editor.js#L132 Vérifier qu'il n'y a pas un bug/fail avec ">" et "<".

Solution 2 : On peut ajouter l'alias `X/` pour ce smiley et remplacer le code dans l'éditeur. https://github.com/zestedesavoir/zds-site/blob/56a5b2e8b524848efa2d328c0a46365a44c1d43e/zds/utils/templatetags/smileys_def.py#L26


Discussion:
Je prends
J'utilise la solution 2 car elle me semble plus facile à implémenter de façon fiable, et que taper `X/` est plus facile que `>_<`.

Resolving patch:
diff --git a/zds/utils/templatetags/smileys_def.py b/zds/utils/templatetags/smileys_def.py
--- a/zds/utils/templatetags/smileys_def.py
+++ b/zds/utils/templatetags/smileys_def.py
@@ -23,7 +23,7 @@
     'diable.png': (':diable:', ),
     'magicien.png': (':magicien:', ),
     'ninja.gif': (':ninja:', ),
-    'pinch.png': ('>_<', ),
+    'pinch.png': ('>_<', 'X/'),
     'pirate.png': (':pirate:', ),
     'pleure.png': (":'(", ),
     'rouge.png': (':honte:', ),


Test patch:
Repository: zestedesavoir/zds-site

Issue:
Impossible de ne plus suivre un billet
Je me suis abonné au billet [Ô Belgique, ô ... ](https://zestedesavoir.com/billets/2681/o-belgique-o/) peu après sa publication. Or, il m'est désormais impossible de ne plus le suivre. De même, j'ai cliqué sur "Être notifié par courriel", et il m'est impossible de l'annuler. Quand je clique sur les boutons correspondants dans la sidebar, rien ne se passe.

La même chose se passe sur le billet [Notification des failles de sécurité et droit pénal](https://zestedesavoir.com/billets/2568/notification-des-failles-de-securite-et-droit-penal/).


Discussion:
( O Belgique O a été republié ref : https://zestedesavoir.com/forums/sujet/11038/je-ne-suis-pas-abonne-a-mon-propre-billet/ )
Ça crée un bug de faire ça ? (si oui, désolé). 

Par ailleurs, tu t'es abonné le vendredi ou le samedi?
https://sentry.sandhose.fr/zeste-de-savoir/zds-site/issues/54/

Resolving patch:
diff --git a/zds/notification/managers.py b/zds/notification/managers.py
--- a/zds/notification/managers.py
+++ b/zds/notification/managers.py
@@ -149,7 +149,8 @@ def toggle_follow(self, content_object, user=None, by_email=False):
             if by_email:
                 subscription.activate_email()
             return subscription
-        signals.content_read.send(sender=content_object.__class__, instance=content_object, user=user)
+        signals.content_read.send(sender=content_object.__class__, instance=content_object, user=user,
+                                  target=content_object.__class__)
         if by_email:
             existing.deactivate_email()
         else:


Test patch:
diff --git a/zds/notification/tests/tests_basics.py b/zds/notification/tests/tests_basics.py
--- a/zds/notification/tests/tests_basics.py
+++ b/zds/notification/tests/tests_basics.py
@@ -524,6 +524,10 @@ def test_follow_content_from_view(self):
 
         subscription = ContentReactionAnswerSubscription.objects.get_existing(user=self.user1, content_object=self.tuto)
         self.assertTrue(subscription.is_active)
+        result = self.client.post(reverse('content:follow-reactions', args=[self.tuto.pk]), {'follow': 0})
+        self.assertEqual(result.status_code, 302)
+        subscription = ContentReactionAnswerSubscription.objects.get_existing(user=self.user1, content_object=self.tuto)
+        self.assertFalse(subscription.is_active)
 
     def test_answer_subscription(self):
         """
Repository: zestedesavoir/zds-site

Issue:
« Vous êtes déjà inscrits » après s'être connecté
Bonjour,

Après m'être inscrit et activé mon compte via le lien reçu par mail, j'ai fermé l'onglet ouvert lors de l'activation, puis sur le premier onglet dans lequel j'ai effectué mon inscription, j'ai cliqué sur le bouton de connexion en haut à droite, et après m'être authentifié je tombe sur le message « Vous êtes déjà inscrits », comme on peut le constater sur la capture ci-dessous :
![ZdS](https://user-images.githubusercontent.com/9420561/35529802-720c2a9a-0532-11e8-91f1-abcbfdea9f6a.png)

La cause semble être le fait qu'en passant de la page d'inscription à celle de connexion, le paramètre `next` renvoie vers la page d'inscription (*membres/connexion/?next=/membres/inscription/*).
De manière analogue, lorsqu'on arrive en étant déconnecté directement sur la page de connexion, et que l'on clique sur le bouton *Connexion* du haut de page, puis qu'on se connecte, on a droit à un message « Vous êtes déjà connecté ».

La solution serait sans-doute d'effectuer un filtrage sur le paramètre `next` passé en GET, de sorte à ne pas le prendre en compte s'il s'agit de la page de connexion ou bien d'inscription, et ainsi renvoyer directement l'utilisateur vers la page d'accueil par exemple.


Discussion:

Resolving patch:
diff --git a/zds/member/views.py b/zds/member/views.py
--- a/zds/member/views.py
+++ b/zds/member/views.py
@@ -904,6 +904,8 @@ def remove_hat(request, user_pk, hat_pk):
 def login_view(request):
     """Logs user in."""
     next_page = request.GET.get('next', '/')
+    if next_page in [reverse('member-login'), reverse('register-member'), reverse('member-logout')]:
+        next_page = '/'
     csrf_tk = {'next_page': next_page}
     csrf_tk.update(csrf(request))
     error = False


Test patch:
Repository: zestedesavoir/zds-site

Issue:
Erreur 403 après recherche dans la bibliothèque
> Bonjour,
> 
> Je tombe sur une erreur 403 "Vous n’avez pas les droits suffisants pour accéder à cette page." après une recherche dans les cours présents dans la bibliothèque.
Voilà comment elle est apparue :
> 
> - Arrivé sur le site déconnecté
> - Je suis allé dans "Développement web" depuis le bandeau en haut du site
> - A partir de là je me suis connecté à mon compte (même onglet, bouton classique), ce qui m'a ramené sur la page
> - Puis j'ai fait une recherche "PHP" dans la barre de rechercher, ce qui m'a amené sur [ce lien](https://zestedesavoir.com/rechercher/?q=PHP&models=content&from_library=on&category=informatique&subcategory=site-web)
> 
> L'erreur 403 se produit lorsque je coche 1 à 3 cases (sous la barre de recherche), pour filtrer les résultats, et que je clique à nouveau sur le bouton "rechercher" dans la barre.
> 
> Voilà [un exemple de lien](https://zestedesavoir.com/rechercher/?q=PHP&category=informatique&subcategory=site-web&from_library=on&models=) provoquant une erreur 403 de mon côté.
> 
> Bye

Sujet : https://zestedesavoir.com/forums/sujet/11609/erreur-403-apres-recherche-dans-la-bibliotheque/
*Envoyé depuis Zeste de Savoir*


Discussion:
les cases à coché ont une value qui est vide. Il faut absolument fixer ce bug pour la v28

Resolving patch:
diff --git a/zds/searchv2/forms.py b/zds/searchv2/forms.py
--- a/zds/searchv2/forms.py
+++ b/zds/searchv2/forms.py
@@ -31,7 +31,12 @@ class SearchForm(forms.Form):
 
     models = forms.MultipleChoiceField(
         label='',
-        widget=forms.CheckboxSelectMultiple,
+        widget=forms.CheckboxSelectMultiple(
+            attrs={
+                'class': 'search-filters',
+                'form': 'search-form'
+            }
+        ),
         required=False,
         choices=choices
     )


Test patch:
Repository: zestedesavoir/zds-site

Issue:
La légende de mes images est ignorée à l'upload
Lors de l'ajout d'une image dans la galerie, la légende de l'image prend la même valeur que le titre. Par contre, lors de la mise à jour d'une image, la légende prend bien la bonne valeur.

> Salut à tous,
> 
> Je viens de voir ça en ajoutant des images à la galerie du tutoriel C++. Je précise le titre et une légende, différente du titre, puis je valide. Cependant, à l'écran d'après, je vois que la légende entrée a été écrasée par le titre.
> 
> Exemple : je tape « Accueil » pour le titre et « Accueil de mon super logiciel » pour la légende, après l'upload, je me retrouve avec Accueil comme titre **ET** légende.
> 
> Voili voilou.
> 
> *informaticienzero*

Sujet : https://zestedesavoir.com/forums/sujet/11669/la-legende-de-mes-images-est-ignoree-a-lupload/
*Envoyé depuis Zeste de Savoir*


Discussion:
Le bug est dans [le fichier `zds/gallery/views.py` à la ligne 316](https://github.com/zestedesavoir/zds-site/blob/dev/zds/gallery/views.py#L316) où il faut remplacer `form.cleaned_data.get('title')` par `form.cleaned_data.get('legend')`

Resolving patch:
diff --git a/zds/gallery/views.py b/zds/gallery/views.py
--- a/zds/gallery/views.py
+++ b/zds/gallery/views.py
@@ -313,7 +313,7 @@ def form_valid(self, form):
         self.perform_create(
             form.cleaned_data.get('title'),
             self.request.FILES.get('physical'),
-            form.cleaned_data.get('title'))
+            form.cleaned_data.get('legend'))
 
         self.success_url = reverse(
             'gallery-image-edit',


Test patch:
Repository: zestedesavoir/zds-site

Issue:
Manque des accents sur les message d'avertissement quand il n'y a pas de métrique
- sur un de vos billet qui est assez ancien (pour qu'il y ait peu de data)
- regardez les statistiques
- des messages d'avertissement apparaissent
![metrique](https://user-images.githubusercontent.com/1523653/50046847-94a82a80-00aa-11e9-9638-4db9689f4da7.PNG)

il manque l'accents sur les "é" de métrique


Discussion:

Resolving patch:
diff --git a/zds/tutorialv2/views/published.py b/zds/tutorialv2/views/published.py
--- a/zds/tutorialv2/views/published.py
+++ b/zds/tutorialv2/views/published.py
@@ -1100,7 +1100,7 @@ def config_ga_credentials(self):
             return analytics
         except (ValueError, FileNotFoundError, ServerNotFoundError) as e:
             messages.error(self.request, _("Erreur de configuration de l'API Analytics. "
-                                           "Merci de contacter l'équipe des développeurs. {}".format(str(e))))
+                                           "Merci de contacter l'équipe des développeurs. « {} »").format(str(e)))
             return None
 
     @staticmethod
@@ -1205,7 +1205,7 @@ def get_simple_stat(self, report, info):
         try:
             rows = report['data']['rows']
         except KeyError:
-            messages.error(self.request, _("Aucune donnée n'est disponible (metrique {})".format(info)))
+            messages.error(self.request, _("Aucune donnée n'est disponible (métrique « {} »)").format(info))
             return []
         api_raw = OrderedDict()
         for r in rows:
@@ -1288,7 +1288,8 @@ def get_all_stats(self, urls, start, end, display_mode):
                 body={'reportRequests': [graphs_data_report, table_data_report, referrer_report, keyword_report]}
             ).execute()
         except googleapiclient.errors.HttpError as e:
-            messages.error(self.request, _("Un problème a eu lieu lors de la requète vers l'API GA. {}".format(e)))
+            messages.error(self.request,
+                           _("Un problème a eu lieu lors de la requête vers l'API Google Analytics. « {} »").format(e))
             return ([], [], [], [])
 
         return (


Test patch:
Repository: zestedesavoir/zds-site

Issue:
La liste des filtres a changé d'ordre pour les listes de contenus
Dans la liste des contenus d'un utilisateur, l'ordre des filtres a changé : 

![Avant](https://user-images.githubusercontent.com/6664636/50146370-dc4dd280-02b3-11e9-9a09-cbdbb5030eb5.png)

![Après](https://user-images.githubusercontent.com/6664636/50146409-ee2f7580-02b3-11e9-8c88-ef170be56fe7.png)

Pages : 

- `https://beta.zestedesavoir.com/contenus/tutoriels/<pk de l'utilisateur>/`
- `https://beta.zestedesavoir.com/contenus/articles/<pk de l'utilisateur>/`

Vue en question : https://github.com/zestedesavoir/zds-site/blob/dev/zds/tutorialv2/views/contents.py#L1866

Gabarit en question : https://github.com/zestedesavoir/zds-site/blob/dev/templates/tutorialv2/index.html#L174


Discussion:
régression => bloquant car c'est un effet de bord non désiré d'un refacto.
Il faut remplacer :
```py
for filter_ in list(self.authorized_filters.keys()):
```

Par : 
```py
filterKeys = ['public', 'validation', 'beta', 'redaction']
for filter_ in filterKeys:
```

c'est bien ça ?

Resolving patch:
diff --git a/zds/tutorialv2/views/contents.py b/zds/tutorialv2/views/contents.py
--- a/zds/tutorialv2/views/contents.py
+++ b/zds/tutorialv2/views/contents.py
@@ -7,6 +7,7 @@
 import time
 import zipfile
 from datetime import datetime
+from collections import OrderedDict
 
 from PIL import Image as ImagePIL
 
@@ -1870,19 +1871,19 @@ class ContentOfAuthor(ZdSPagingListView):
     template_name = 'tutorialv2/index.html'
     model = PublishableContent
 
-    authorized_filters = {
-        'public': [lambda q: q.filter(sha_public__isnull=False), _('Publiés'), True, 'tick green'],
-        'validation': [lambda q: q.filter(sha_validation__isnull=False), _('En validation'), False, 'tick'],
-        'beta': [lambda q: q.filter(sha_beta__isnull=False), _('En bêta'), True, 'beta'],
-        'redaction': [
+    authorized_filters = OrderedDict([
+        ('public', [lambda q: q.filter(sha_public__isnull=False), _('Publiés'), True, 'tick green']),
+        ('validation', [lambda q: q.filter(sha_validation__isnull=False), _('En validation'), False, 'tick']),
+        ('beta', [lambda q: q.filter(sha_beta__isnull=False), _('En bêta'), True, 'beta']),
+        ('redaction', [
             lambda q: q.filter(sha_validation__isnull=True, sha_public__isnull=True, sha_beta__isnull=True),
-            _('Brouillons'), False, 'edit'],
-    }
-    sorts = {
-        'creation': [lambda q: q.order_by('creation_date'), _('Par date de création')],
-        'abc': [lambda q: q.order_by('title'), _('Par ordre alphabétique')],
-        'modification': [lambda q: q.order_by('-update_date'), _('Par date de dernière modification')]
-    }
+            _('Brouillons'), False, 'edit']),
+    ])
+    sorts = OrderedDict([
+        ('creation', [lambda q: q.order_by('creation_date'), _('Par date de création')]),
+        ('abc', [lambda q: q.order_by('title'), _('Par ordre alphabétique')]),
+        ('modification', [lambda q: q.order_by('-update_date'), _('Par date de dernière modification')])
+    ])
     sort = ''
     filter = ''
     user = None


Test patch:
Repository: zestedesavoir/zds-site

Issue:
Mauvais format (taille d'image) avec la TwitterCard
Le problème : 

https://twitter.com/A312_zds/status/1027577197987606528

L'image est flou car 60x60 :(


HTML :

    <meta property="twitter:image" content="http://zestedesavoir.com/media/galleries/5313/e35c638c-b58c-4ed7-851b-03f0c21cef2c.png.60x60_q95_crop.jpg">

Le format de la TwitterCard devrait être au minimum : 96x96 


Discussion:
![](https://zestedesavoir.com/media/galleries/5313/e35c638c-b58c-4ed7-851b-03f0c21cef2c.png.96x96_q95_crop.jpg)

Resolving patch:
diff --git a/zds/settings/abstract_base/zds.py b/zds/settings/abstract_base/zds.py
--- a/zds/settings/abstract_base/zds.py
+++ b/zds/settings/abstract_base/zds.py
@@ -45,6 +45,9 @@
         'featured': {'size': (228, 228), 'crop': True},
         'gallery_illu': {'size': (480, 270), 'crop': True},
         'content': {'size': (960, 960), 'crop': False},
+        'social_network': {'size': (144, 144), 'crop': True},
+        #                           ^^^  ^^^ -> minimum dimensions of 144x144
+        # https://developer.twitter.com/en/docs/tweets/optimize-with-cards/overview/summary
     },
 }
 


Test patch:
Repository: zestedesavoir/zds-site

Issue:
Impossible de cocher la case « recevoir un courriel lors de la réception d'un nouveau message privé »
Bonjour,

Suite à la réception d'un message privé j'ai remarqué que je n'avais reçu aucun email pour me le signaler.

Étonné, j'ai regardé du côté des paramètres de mon profil et remarqué que la case « recevoir un courriel lors de la réception d'un nouveau message privé » n'était plus cochée.
J'ai tenter de la recocher puis de valider le formulaire, mais sans effet, elle reste inexorablement décochée.


Discussion:
J'ai regardé vite, donc à tester plus profondément, mais j'aurais tendance à penser que c'est un problème d'affichage : la valeur `email_for_new_mp` n'est pas mise à jour dans les données initiales du formulaire ici :

https://github.com/zestedesavoir/zds-site/blob/9ee2198db14f0f6c8394dd6459122bd28a05b332/zds/member/forms.py#L260-L284

alors qu'elle est bien transmise :

https://github.com/zestedesavoir/zds-site/blob/1937b8622cc9b9333713045163c246d1f2647bd7/zds/member/views.py#L115-L130

mais elle semble bien être enregistrée dans le profil, au traitement, ici :

https://github.com/zestedesavoir/zds-site/blob/1937b8622cc9b9333713045163c246d1f2647bd7/zds/member/views.py#L155-L168
@AmauryCarrade Ça doit être ça, je ne me souviens pas d'avoir modifié de formulaire dans la PR qui a ajouté cette feature.

Je prends la résolution du bug, mais il faudrait ajouter un test front pour que ça ne se reproduise pas, non ?

Resolving patch:
diff --git a/zds/member/forms.py b/zds/member/forms.py
--- a/zds/member/forms.py
+++ b/zds/member/forms.py
@@ -279,6 +279,9 @@ def __init__(self, *args, **kwargs):
         if 'email_for_answer' in initial and initial['email_for_answer']:
             self.fields['options'].initial += 'email_for_answer'
 
+        if 'email_for_new_mp' in initial and initial['email_for_new_mp']:
+            self.fields['options'].initial += 'email_for_new_mp'
+
         layout = Layout(
             Field('biography'),
             ButtonHolder(StrictButton(_('Aperçu'), type='preview', name='preview',


Test patch:
Repository: zestedesavoir/zds-site

Issue:
Erreurs 500 pour "Ajouter en Une"
Sur certains contenus, "Ajouter en Une" renvoie une erreur 500

Sujet : https://zestedesavoir.com/forums/sujet/11676/ajouter-en-une/#p195045
*Envoyé depuis Zeste de Savoir*


Discussion:
D'après Sentry, l'erreur est `MultipleObjectsReturned: get() returned more than one PublishedContent -- it returned 2!` et elle provient de [la ligne 69 du fichier `zds/featured/views.py`](https://github.com/zestedesavoir/zds-site/blob/c017e008e3e04908d4642e954b441c2f9f1b4423/zds/featured/views.py#L69) : `content = PublishedContent.objects.get(content__pk=int(content_id))`
forcément. Il faut donc : 

- ajouter le filtre `must_redirect=False`
- utiliser la combinaison `filter().first()` plutôt que `get()`
@artragis tu peux m'expliquer pourquoi `content_pk` n'est pas unique ? :)
Tuto publié deux fois sous deux noms différents du coup on garde une trace de l'ancien objet `PublishedContent`.

Cela permet de créer la redirection quand une personne possède le vieux lien.
🎉 Je viens de reproduire l'erreur en local 🥳

Du coup, je m'en charge si ça dérange personne. Je pense pour une v29 donc j'ai le temps mais d'ici la fin du mois, j'aurais fini. Ça me permettra de mettre un petit pied dans le dev de zds (j'ai surtout fais zmarkdown pour l'instant).

À bientôt \o
impec, welcome
V28.1 si ça arrive dans moins d'un mois non ? Enfin je ne connais pas les dates de la v29 et v28.1
ya pas de date précise on est un peu comme Debian : Quand c'est prêt.

Laissons déjà le tempse à @sandhose de déployer la v28. 
Ah j'avais cru que la v28 était en ligne.

Resolving patch:
diff --git a/zds/featured/views.py b/zds/featured/views.py
--- a/zds/featured/views.py
+++ b/zds/featured/views.py
@@ -66,7 +66,7 @@ def get_initial_topic_data(self, topic_id):
 
     def get_initial_content_data(self, content_id):
         try:
-            content = PublishedContent.objects.get(content__pk=int(content_id))
+            content = PublishedContent.objects.filter(must_redirect=False, content__pk=int(content_id)).first()
         except (PublishedContent.DoesNotExist, ValueError):
             messages.error(self.request, self.initial_error_message)
             return {}
@@ -79,7 +79,7 @@ def get_initial_content_data(self, content_id):
                 'type': self.displayed_content_type[content.content_type],
                 'authors': displayed_authors,
                 'url': self.request.build_absolute_uri(content.content.get_absolute_url_online()),
-                'image_url': image_url}
+                'image_url': self.request.build_absolute_uri(image_url)}
 
     def get_initial(self):
         initial = super(FeaturedResourceCreate, self).get_initial()


Test patch: