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

Issue:
[beta][v20] L'api des notifications renvoie que les notifs non lues
Serveur : Beta
Version : v20/6bb2f75
Système : Mac OS X
Navigateur : 52.0.2743.116 (64-bit)

---
1. Récupérez vos notifications depuis l'API
2. Constatez que le serveur renvoie uniquement les notifs non lues.



Discussion:

Resolving patch:
diff --git a/zds/notification/api/views.py b/zds/notification/api/views.py
--- a/zds/notification/api/views.py
+++ b/zds/notification/api/views.py
@@ -79,7 +79,7 @@ def get(self, request, *args, **kwargs):
         return self.list(request, *args, **kwargs)
 
     def get_queryset(self):
-        queryset = Notification.objects.get_unread_notifications_of(self.request.user)
+        queryset = Notification.objects.get_notifications_of(self.request.user)
         subscription_type = self.request.query_params.get('subscription_type', None)
         if subscription_type:
             queryset = queryset.filter(subscription__content_type__model=subscription_type)


Test patch:
diff --git a/zds/notification/api/tests.py b/zds/notification/api/tests.py
--- a/zds/notification/api/tests.py
+++ b/zds/notification/api/tests.py
@@ -10,6 +10,7 @@
 from zds.member.api.tests import create_oauth2_client, authenticate_client
 from zds.member.factories import ProfileFactory
 from zds.mp.factories import PrivateTopicFactory
+from zds.notification.models import Notification
 from zds.utils.mps import send_message_mp
 
 
@@ -38,7 +39,6 @@ def test_list_of_notifications(self):
         """
         self.create_notification_for_pm(ProfileFactory().user, self.profile.user)
         response = self.client.get(reverse('api:notification:list'))
-        print response
         self.assertEqual(response.status_code, status.HTTP_200_OK)
         self.assertEqual(response.data.get('count'), 1)
 
@@ -60,7 +60,23 @@ def test_apply_filter_on_notifications(self):
         self.assertEqual(response.status_code, status.HTTP_200_OK)
         self.assertEqual(response.data.get('count'), 0)
 
+    def test_list_of_all_notifications(self):
+        """
+        Gets list of read and unread notifications.
+        """
+        topic1 = self.create_notification_for_pm(ProfileFactory().user, self.profile.user)
+        self.create_notification_for_pm(ProfileFactory().user, self.profile.user)
+
+        notification = Notification.objects.get(object_id=topic1.last_message.pk, is_read=False)
+        notification.is_read = True
+        notification.save()
+
+        response = self.client.get(reverse('api:notification:list'))
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertEqual(response.data.get('count'), 2)
+
     def create_notification_for_pm(self, sender, target):
         topic = PrivateTopicFactory(author=sender)
         topic.participants.add(target)
         send_message_mp(author=sender, n_topic=topic, text='Testing')
+        return topic
Repository: zestedesavoir/zds-site

Issue:
[beta][v23] Erreur 500 via opensearch
Bonjour,

**Lien incriminé** : https://beta.zestedesavoir.com/rechercher/opensearch.xml

**Problème** : j'ai une erreur 500 en allant sur cette url.


Discussion:
Bien vu :) Voir [erreur sentry associée](https://sentry.sandhose.fr/zeste-de-savoir/beta-backend/issues/899/).

En gros, j'ai fait le con et j'ai oublié de migrer la template :)

Resolving patch:
diff --git a/zds/searchv2/views.py b/zds/searchv2/views.py
--- a/zds/searchv2/views.py
+++ b/zds/searchv2/views.py
@@ -216,7 +216,7 @@ def get_context_data(self, **kwargs):
 def opensearch(request):
     """Generate OpenSearch Description file"""
 
-    return render(request, 'search/opensearch.xml', {
+    return render(request, 'searchv2/opensearch.xml', {
         'site_name': settings.ZDS_APP['site']['litteral_name'],
         'site_url': settings.ZDS_APP['site']['url'],
         'email_contact': settings.ZDS_APP['site']['email_contact'],


Test patch:
diff --git a/zds/searchv2/tests/tests_views.py b/zds/searchv2/tests/tests_views.py
--- a/zds/searchv2/tests/tests_views.py
+++ b/zds/searchv2/tests/tests_views.py
@@ -652,6 +652,18 @@ def test_change_publishedcontents_impacts_chapter(self):
         self.assertEqual(chapters[0].meta.doc_type, FakeChapter.get_es_document_type())
         self.assertEqual(chapters[0].meta.id, published.content_public_slug + '__' + chapter2.slug)  # got new chapter
 
+    def test_opensearch(self):
+
+        result = self.client.get(
+            reverse('search:opensearch'),
+            follow=False
+        )
+
+        self.assertEqual(result.status_code, 200)
+
+        self.assertContains(result, reverse('search:query'))
+        self.assertContains(result, reverse('search:opensearch'))
+
     def tearDown(self):
         if os.path.isdir(settings.ZDS_APP['content']['repo_private_path']):
             shutil.rmtree(settings.ZDS_APP['content']['repo_private_path'])
Repository: zestedesavoir/zds-site

Issue:
[v23] La promotion d'un billet en article fait perdre la source
J'ai publié un billet, il a été promu en article directement.

[Version publique du billet](https://beta.zestedesavoir.com/billets/1777/un-gros-troll-de-plus-sur-javascript/)
[Version publique de l'article](https://beta.zestedesavoir.com/articles/1799/un-gros-troll-de-plus-sur-javascript-1/)

Dans les sources html du billet on peut voir que la source a été migrée et on aperçoit `<link rel="canonical" ... >`, mais aucune de cette mention dans l'article.

Je suppose donc que la source n'a pas été migrée.


Discussion:

Resolving patch:
diff --git a/zds/tutorialv2/views/views_validations.py b/zds/tutorialv2/views/views_validations.py
--- a/zds/tutorialv2/views/views_validations.py
+++ b/zds/tutorialv2/views/views_validations.py
@@ -930,7 +930,9 @@ def form_valid(self, form):
                                      public_version=None,
                                      licence=db_object.licence,
                                      sha_validation=db_object.sha_public,
-                                     sha_draft=db_object.sha_public
+                                     sha_draft=db_object.sha_public,
+                                     image=db_object.image,
+                                     source=db_object.source
                                      )
 
         opinion_url = db_object.get_absolute_url_online()


Test patch:
Repository: zestedesavoir/zds-site

Issue:
[v25][beta] L'ordre de tri des publications a changé sur la page de profil
En comparant ma page de profil de [production](https://zestedesavoir.com/membres/voir/firm1/) et de [beta](https://beta.zestedesavoir.com/membres/voir/firm1/) je me rend compte que l'ordre d'affichage des publications à été modifié. Au lieu d'afficher d'abord les publications récentes on affiche d'abord les plus vieilles ce qui n'est pas super super niveau ergonomie.

Surtout que pour ceux qui ont beaucoup de publications comme [artragis](https://beta.zestedesavoir.com/membres/voir/artragis/) on ne voit que les plus vielles publications sur sa page de profil, ce qui donne l'impression qu'il n'a pas écrit depuis très longtemps.


Discussion:

Resolving patch:
diff --git a/zds/tutorialv2/managers.py b/zds/tutorialv2/managers.py
--- a/zds/tutorialv2/managers.py
+++ b/zds/tutorialv2/managers.py
@@ -69,9 +69,7 @@ def last_contents_of_a_member_loaded(self, author, _type=None):
         :param _type: subtype to filter request
         :rtype: django.db.models.QuerySet
         """
-        queryset = self.__get_list(content_type=[_type]) \
-            .filter(authors__in=[author])
-
+        queryset = self.last_contents(with_comments_count=True, content_type=_type).filter(authors__in=[author])
         public_contents = queryset.all()[:settings.ZDS_APP['content']['user_page_number']]
         return public_contents
 
diff --git a/zds/tutorialv2/views/views_published.py b/zds/tutorialv2/views/views_published.py
--- a/zds/tutorialv2/views/views_published.py
+++ b/zds/tutorialv2/views/views_published.py
@@ -430,7 +430,7 @@ def categories_with_contents_count(handle_types):
             .objects\
             .prefetch_related('subcategory', 'category')\
             .filter(is_main=True)\
-            .order_by('category__id')\
+            .order_by('category__id', 'subcategory__title')\
             .all()
 
         subcategories_sorted = {}
@@ -470,6 +470,7 @@ def subcategories_with_contents_count(category, handle_types):
         queryset = CategorySubCategory.objects \
             .filter(is_main=True, category=category) \
             .prefetch_related('subcategory')\
+            .order_by('subcategory__title')\
             .extra(select={'contents_count': sub_query})
 
         subcategories = []


Test patch:
Repository: zestedesavoir/zds-site

Issue:
[v25][beta] La page "tous les tags" d'une tribune montre des tags qui renvoient vers la bibliothèque
Bonjour,

Lorsque je vais sur la page de tous les tags de la tribune j'arrive sur [ce lien](https://beta.zestedesavoir.com/contenus/tags/?type=opinion) (topbar > tribune > Tous les tags).

Et là je vois ceci : 

![touttag](https://user-images.githubusercontent.com/6066015/29518504-e591aea0-8679-11e7-9b7b-0983d137fd11.PNG)

Le problème c'est que si je clique sur un tag, je suis redirigé dans les contenus de la bibliothèque au lieu des contenus de la tribune.


Discussion:

Resolving patch:
diff --git a/zds/tutorialv2/views/views_published.py b/zds/tutorialv2/views/views_published.py
--- a/zds/tutorialv2/views/views_published.py
+++ b/zds/tutorialv2/views/views_published.py
@@ -1040,3 +1040,13 @@ def get_queryset(self):
             self.displayed_types = [t]
 
         return PublishedContent.objects.get_top_tags(self.displayed_types)
+
+    def get_context_data(self, **kwargs):
+        context = super(TagsListView, self).get_context_data(**kwargs)
+
+        context['tags_to_display'] = 'publications'
+
+        if len(self.displayed_types) == 1:
+            context['tags_to_display'] = self.displayed_types[0]
+
+        return context


Test patch:
Repository: zestedesavoir/zds-site

Issue:
[v25][beta] Les boutons plus de [articles/tutoriels] ne devraient s'afficher que quand il y'en a
Dans la bibliothèque, si on affiche par exemple les publications de la catégorie "économie", on a ceci : 

![more-and-more](https://user-images.githubusercontent.com/6066015/29520902-7474bcf8-8683-11e7-8979-ecfffe50912a.PNG)


Le problème là dessus c'est que les boutons "plus d'articles" et "plus de tutoriels" sont inutiles dans ce cas (comme dans beaucoup de cas), puisqu'en cliquant dessus, on a pas plus d'articles que ce que l'on voyait avant. Ce qui peut faire perdre du temps lors de la navigation.

Il faudrait donc n'afficher ces boutons que lorsqu'il y'a d'autres contenus autres que ceux affiché.


Discussion:

Resolving patch:
diff --git a/zds/tutorialv2/views/views_published.py b/zds/tutorialv2/views/views_published.py
--- a/zds/tutorialv2/views/views_published.py
+++ b/zds/tutorialv2/views/views_published.py
@@ -569,12 +569,15 @@ def get_context_data(self, **kwargs):
                 with_previous_item=False)
 
         if self.level < 4:
-            context['last_articles'] = PublishedContent.objects.last_contents(
-                **dict(content_type='ARTICLE', **recent_kwargs)
-            )[:self.max_last_contents]
-            context['last_tutorials'] = PublishedContent.objects.last_contents(
-                **dict(content_type='TUTORIAL', **recent_kwargs)
-            )[:self.max_last_contents]
+            last_articles = PublishedContent.objects.last_contents(
+                **dict(content_type='ARTICLE', **recent_kwargs))
+            context['last_articles'] = last_articles[:self.max_last_contents]
+            context['more_articles'] = last_articles.count() > self.max_last_contents
+
+            last_tutorials = PublishedContent.objects.last_contents(
+                **dict(content_type='TUTORIAL', **recent_kwargs))
+            context['last_tutorials'] = last_tutorials[:self.max_last_contents]
+            context['more_tutorials'] = last_tutorials.count() > self.max_last_contents
 
             context['beta_forum'] = Forum.objects\
                 .prefetch_related('category')\


Test patch:
Repository: zestedesavoir/zds-site

Issue:
Logger les suppressions de galleries et de publications
Logger juste le fait que ce soit une suppression, le type d’objet concerné et le slug histoire qu’on puisse facilement remonter aux logs de nginx correspondantes avec la date et l’heures en cas de problème.


Discussion:

Resolving patch:
diff --git a/zds/tutorialv2/receivers.py b/zds/tutorialv2/receivers.py
--- a/zds/tutorialv2/receivers.py
+++ b/zds/tutorialv2/receivers.py
@@ -2,10 +2,15 @@
 
 
 import datetime
+import logging
+
 from django.dispatch.dispatcher import receiver
 from django.utils.translation import ugettext_lazy as _
+from django.db import models
+
 from zds.tutorialv2.models.models_database import PublishableContent
 from zds.tutorialv2.signals import content_unpublished
+from zds.gallery.models import Gallery
 from zds.utils import get_current_user
 from zds.utils.models import Alert
 
@@ -26,3 +31,25 @@ def cleanup_validation_alerts(sender, instance, **kwargs):
                                                                        resolve_reason=_('Le billet a été dépublié.'),
                                                                        solved_date=datetime.datetime.now(),
                                                                        solved=True)
+
+
+@receiver(models.signals.post_delete, sender=Gallery)
+@receiver(models.signals.post_delete, sender=PublishableContent)
+def log_content_deletion(sender, instance, **kwargs):
+    """
+    When a content or gallery is deleted, this action is logged.
+    """
+
+    logger = logging.getLogger(__name__)
+    current_user = get_current_user()
+
+    if current_user is None:
+        logger.info('%(instance_model)s #%(instance_pk)d (%(instance_slug)s) has been deleted. User not found.',
+                    {'instance_model': type(instance).__name__, 'instance_pk': instance.pk,
+                     'instance_slug': instance.slug})
+    else:
+        logger.info('%(instance_model)s #%(instance_pk)d (%(instance_slug)s) has been deleted '
+                    'by user #%(user_pk)d (%(username)s).', {'instance_model': type(instance).__name__,
+                                                             'instance_pk': instance.pk, 'instance_slug': instance.slug,
+                                                             'user_pk': current_user.pk,
+                                                             'username': current_user.username})


Test patch:
Repository: zestedesavoir/zds-site

Issue:
TypeError: unorderable types: method() >= int()
https://sentry.sandhose.fr/zeste-de-savoir/backend-l7/issues/1319/

```
TypeError: unorderable types: method() >= int()
(3 additional frame(s) were not displayed)
...
  File "zds/member/views.py", line 406, in post
    return self.form_valid(form)
  File "zds/member/views.py", line 418, in form_valid
    if token.count >= 1:

TypeError: unorderable types: method() >= int()
```


Discussion:
À mon avis, ce `if` ne sert à rien : 

https://github.com/zestedesavoir/zds-site/blob/a815bff56455606fb19e440c94a25cc6b1a3c756/zds/member/views.py#L415
oui c'est çàa :p 

Resolving patch:
diff --git a/zds/member/views.py b/zds/member/views.py
--- a/zds/member/views.py
+++ b/zds/member/views.py
@@ -412,7 +412,7 @@ def post(self, request, *args, **kwargs):
     def form_valid(self, form):
         # Delete old token
         token = TokenRegister.objects.filter(user=self.usr)
-        if token.count >= 1:
+        if token.count() >= 1:
             token.all().delete()
 
         # Generate new token and send email


Test patch:
Repository: zestedesavoir/zds-site

Issue:
pinger un membre qui n'existe pas fait planter le site
et génère https://sentry.sandhose.fr/zeste-de-savoir/beta-backend/issues/1516/




Discussion:

Resolving patch:
diff --git a/zds/utils/models.py b/zds/utils/models.py
--- a/zds/utils/models.py
+++ b/zds/utils/models.py
@@ -397,7 +397,10 @@ def update_content(self, text, on_error=None):
         max_ping_count = settings.ZDS_APP['comment']['max_pings']
         first_pings = all_the_pings[:max_ping_count]
         for username in first_pings:
-            signals.new_content.send(sender=self.__class__, instance=self, user=User.objects.get(username=username))
+            pinged_user = User.objects.filter(username=username).first()
+            if not pinged_user:
+                continue
+            signals.new_content.send(sender=self.__class__, instance=self, user=pinged_user)
         unpinged_usernames = set(old_metadata.get('ping', [])) - set(all_the_pings)
         unpinged_users = User.objects.filter(username__in=list(unpinged_usernames))
         for unpinged_user in unpinged_users:


Test patch:
diff --git a/zds/notification/tests/tests_tricky.py b/zds/notification/tests/tests_tricky.py
--- a/zds/notification/tests/tests_tricky.py
+++ b/zds/notification/tests/tests_tricky.py
@@ -38,6 +38,22 @@ def setUp(self):
             self.forum12.groups.add(group)
         self.forum12.save()
 
+    def test_ping_unknown(self):
+        overridden_zds_app['comment']['enable_pings'] = True
+        self.assertTrue(self.client.login(username=self.user2.username, password='hostel77'))
+        result = self.client.post(
+            reverse('topic-new') + '?forum={0}'.format(self.forum11.pk),
+            {
+                'title': 'Super sujet',
+                'subtitle': 'Pour tester les notifs',
+                'text': '@anUnExistingUser is pinged, also a special chars user @{}',
+                'tags': ''
+            },
+            follow=False)
+        self.assertEqual(result.status_code, 302, 'Request must succeed')
+        self.assertEqual(0, PingSubscription.objects.count(),
+                         'As one user is pinged, only one subscription is created.')
+
     def test_no_auto_ping(self):
         overridden_zds_app['comment']['enable_pings'] = True
         self.assertTrue(self.client.login(username=self.user2.username, password='hostel77'))
Repository: zestedesavoir/zds-site

Issue:
Mauvaise redirection lors de la connexion
https://sentry.sandhose.fr/zeste-de-savoir/beta-backend/issues/1493/

lorsqu'on se connecter avec pour "next" une page du forum, ça fait 404.


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
@@ -11,7 +11,7 @@
 from django.template.context_processors import csrf
 from django.core.exceptions import PermissionDenied
 from django.core.mail import EmailMultiAlternatives
-from django.urls import reverse, reverse_lazy, resolve, Resolver404
+from django.urls import reverse, reverse_lazy, resolve, Resolver404, NoReverseMatch
 from django.db import transaction
 from django.db.models import Q
 from django.http import Http404, HttpResponseBadRequest, StreamingHttpResponse
@@ -974,6 +974,8 @@ def login_view(request):
             # after a browser session.)
             try:
                 response = redirect(resolve(next_page).url_name)
+            except NoReverseMatch:
+                response = redirect(next_page)
             except Resolver404:
                 response = redirect(reverse('homepage'))
             set_old_smileys_cookie(response, profile)


Test patch:
Repository: zestedesavoir/zds-site

Issue:
Le ping est KO sur les réponses à un tuto/billet/article
https://sentry.sandhose.fr/zeste-de-savoir/beta-backend/issues/1523/


Discussion:

Resolving patch:
diff --git a/zds/notification/receivers.py b/zds/notification/receivers.py
--- a/zds/notification/receivers.py
+++ b/zds/notification/receivers.py
@@ -346,7 +346,7 @@ def answer_comment_event(sender, *, instance, user, **__):
 
     assert comment is not None
     assert user is not None
-    if not instance.topic.forum.can_read(user):
+    if sender == Post and not instance.topic.forum.can_read(user):
         return
     subscription = PingSubscription.objects.get_or_create_active(user, comment)
     subscription.send_notification(content=comment, sender=comment.author, send_email=False)


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
@@ -343,6 +343,19 @@ def test_move_topic_from_forum_to_another_one(self):
 
         self.assertEqual(1, len(Notification.objects.filter(object_id=topic.pk, is_read=True).all()))
 
+    def test_ping_on_tuto(self):
+        """Error from #4904"""
+        content = PublishedContentFactory(author_list=[self.user1])
+        self.assertTrue(self.client.login(username=self.user2.username, password='hostel77'))
+        result = self.client.post(
+            reverse('content:add-reaction') + '?pk={}'.format(content.pk),
+            {
+                'text': '@{}'.format(self.user1.username),
+                'last_note': 0,
+            }, follow=True)
+        self.assertEqual(200, result.status_code)
+        self.assertEqual(1, len(Notification.objects.filter(is_read=False).all()))
+
     def test_move_topic_from_forum_followed_to_forum_followed_too(self):
         NewTopicSubscription.objects.toggle_follow(self.forum11, self.user1)
         NewTopicSubscription.objects.toggle_follow(self.forum12, self.user1)
Repository: zestedesavoir/zds-site

Issue:
Faire en sorte que Travis regarde automatiquement si il ne manque pas des migrations
@gcodeur a toujours la gentillesse et la patience de vérifier ça à la main à chaque PR parce qu’il y a toujours des étourdis comme moi qui n’y pensent jamais. Soyons gentils avec @gcodeur.

Je pense qu’un simple `./manage.py makemigrations --check` suffit.


Discussion:
Il faudrait préciser comment faire pour ajouter le tag `Facile`, je l'enlève en attendant. :)
Comme ça c’est bon ? :upside_down_face: 
Oui, c'est parfait :+1: 

Resolving patch:
diff --git a/zds/utils/migrations/0020_auto_20180501_1059.py b/zds/utils/migrations/0020_auto_20180501_1059.py
new file mode 100644
--- /dev/null
+++ b/zds/utils/migrations/0020_auto_20180501_1059.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.8 on 2018-05-01 10:59
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('utils', '0019_auto_20180102_1659'),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name='subcategory',
+            options={'verbose_name': 'Sous-categorie', 'verbose_name_plural': 'Sous-categories'},
+        ),
+    ]


Test patch: