internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: nextcloud/appstore

Issue:
Rating in app detail view
Similar to #210 both ratings (overall and recent) should be shown in a visual way (no numbers). It should be consistent with the option chosen in #210 

Below the releases there should be a non paginated list of comments (content needs to be fetched with JavaScript, if needed we will add automatic pagination later on) ordered by rated_at descending. The ratings should only be displayed if the comment is non empty and matches the current locale (see request.LANGUAGE_CODE). The comment should include both the users full name, the rated_at timestamp, the visual rating (thumbs or smilies?) and the comment rendered using markdown.



Discussion:

Resolving patch:
diff --git a/nextcloudappstore/core/templatetags/app_rating.py b/nextcloudappstore/core/templatetags/app_rating.py
new file mode 100644
--- /dev/null
+++ b/nextcloudappstore/core/templatetags/app_rating.py
@@ -0,0 +1,25 @@
+from django import template
+from django.utils.translation import ugettext_lazy as _  # type: ignore
+
+register = template.Library()
+
+
+def raise_value_error(msg):
+    raise ValueError(msg)
+
+
+to_rating = (
+    (lambda r: r <= 0.2, _('Very negative')),
+    (lambda r: r <= 0.4, _('Negative')),
+    (lambda r: r <= 0.6, _('Neutral')),
+    (lambda r: r <= 0.8, _('Positive')),
+    (lambda r: r <= 1.0, _('Very positive')),
+    (lambda r: raise_value_error('Invalid rating: ' + r), None)
+)
+
+
+@register.filter(name='app_rating')
+def app_rating(value):
+    for predicate, rating in to_rating:
+        if predicate(value):
+            return rating
diff --git a/nextcloudappstore/core/templatetags/app_rating_class.py b/nextcloudappstore/core/templatetags/app_rating_class.py
new file mode 100644
--- /dev/null
+++ b/nextcloudappstore/core/templatetags/app_rating_class.py
@@ -0,0 +1,24 @@
+from django import template
+
+register = template.Library()
+
+
+def raise_value_error(msg):
+    raise ValueError(msg)
+
+
+to_rating_class = (
+    (lambda r: r <= 0.2, 'very-negative-rating'),
+    (lambda r: r <= 0.4, 'negative-rating'),
+    (lambda r: r <= 0.6, 'neutral-rating'),
+    (lambda r: r <= 0.8, 'positive-rating'),
+    (lambda r: r <= 1.0, 'very-positive-rating'),
+    (lambda r: raise_value_error('Invalid rating: ' + r), None)
+)
+
+
+@register.filter(name='app_rating_class')
+def app_rating_class(value):
+    for predicate, clazz in to_rating_class:
+        if predicate(value):
+            return clazz
diff --git a/nextcloudappstore/settings/base.py b/nextcloudappstore/settings/base.py
--- a/nextcloudappstore/settings/base.py
+++ b/nextcloudappstore/settings/base.py
@@ -41,6 +41,7 @@
     'django.contrib.messages',
     'django.contrib.sites',
     'django.contrib.staticfiles',
+    'django.contrib.humanize'
 ]
 
 MIDDLEWARE_CLASSES = [


Test patch:
Repository: nextcloud/appstore

Issue:
Email change form
Among the account pages should be a page from which a user can change their email address. The email field on the `User` model needs to be updated and a correspondig django-allauth `EmailAddress` object should be associated with the user. django-allauth supports multiple email addresses per user, but we only want one. New email addresses should be verified with [this](http://django-allauth.readthedocs.io/en/latest/views.html#e-mail-verification). The page should be located at `/account/email/`.

@BernhardPosselt Do you agree with the above?



Discussion:

Resolving patch:
diff --git a/nextcloudappstore/core/user/views.py b/nextcloudappstore/core/user/views.py
--- a/nextcloudappstore/core/user/views.py
+++ b/nextcloudappstore/core/user/views.py
@@ -43,7 +43,7 @@ class AccountView(LoginRequiredMixin, UpdateView):
     template_name = 'user/account.html'
     template_name_suffix = ''
     model = User
-    fields = ['first_name', 'last_name']
+    fields = ['first_name', 'last_name', 'email']
     success_url = reverse_lazy('user:account')
 
     def get_context_data(self, **kwargs):
@@ -52,7 +52,7 @@ def get_context_data(self, **kwargs):
         return context
 
     def form_valid(self, form):
-        messages.success(self.request, 'Name saved.')
+        messages.success(self.request, 'Account details saved.')
         return super().form_valid(form)
 
     def get_object(self, queryset=None):


Test patch:
Repository: nextcloud/appstore

Issue:
Apps without releases should not be rendered on the app list page



Discussion:

Resolving patch:
diff --git a/nextcloudappstore/core/views.py b/nextcloudappstore/core/views.py
--- a/nextcloudappstore/core/views.py
+++ b/nextcloudappstore/core/views.py
@@ -142,7 +142,7 @@ def get_queryset(self):
         lang = get_language_info(get_language())['code']
         category_id = self.kwargs['id']
         queryset = App.objects.search(self.search_terms, lang).order_by(
-            *sort_columns)
+            *sort_columns).filter(releases__gt=0)
         if maintainer:
             try:
                 user = User.objects.get_by_natural_key(maintainer)


Test patch:
Repository: nextcloud/appstore

Issue:
API: changing the certificate for an app should delete all of its releases
Since they can not be validated anymore



Discussion:

Resolving patch:
diff --git a/nextcloudappstore/core/models.py b/nextcloudappstore/core/models.py
--- a/nextcloudappstore/core/models.py
+++ b/nextcloudappstore/core/models.py
@@ -203,6 +203,17 @@ def _latest(self, releases):
         except ValueError:
             return None
 
+    def save(self, *args, **kwargs):
+        # If the certificate has changed, delete all releases.
+        try:
+            if self.pk is not None:
+                orig = App.objects.get(pk=self.pk)
+                if self.certificate != orig.certificate:
+                    self.releases.all().delete()
+        except self.DoesNotExist:
+            pass
+        super().save(*args, **kwargs)
+
 
 class AppRating(TranslatableModel):
     app = ForeignKey('App', related_name='ratings', verbose_name=_('App'),


Test patch:
diff --git a/nextcloudappstore/core/tests/test_cert_delete_releases.py b/nextcloudappstore/core/tests/test_cert_delete_releases.py
new file mode 100644
--- /dev/null
+++ b/nextcloudappstore/core/tests/test_cert_delete_releases.py
@@ -0,0 +1,22 @@
+from django.contrib.auth.models import User
+from django.test import TestCase
+from nextcloudappstore.core.models import App, AppRelease
+
+
+class CertDeleteReleasesTest(TestCase):
+    def setUp(self):
+        self.owner = User.objects.create(username='user', password='pass')
+        self.app = App.objects.create(
+            name='App', certificate='CERT1', owner=self.owner)
+        self.rel1 = AppRelease.objects.create(version='1.0.0', app=self.app)
+        self.rel2 = AppRelease.objects.create(version='2.0.0', app=self.app)
+        self.rel3 = AppRelease.objects.create(version='3.0.0', app=self.app)
+        self.rel4 = AppRelease.objects.create(version='4.0.0', app=self.app)
+
+    def test_cert_has_changed(self):
+        self.assertEquals(self.app.releases.count(), 4)
+        AppRelease.objects.create(version='5.0.0', app=self.app)
+        self.assertEquals(self.app.releases.count(), 5)
+        self.app.certificate = 'CERT2'
+        self.app.save()
+        self.assertEquals(self.app.releases.count(), 0)
Repository: nextcloud/appstore

Issue:
Create documentation section for explaining certificates, signing and how it all works together
App devs need a very quick tutorial/walkthrough in the docs on how to generate a new certificate pair, request the public cert to be signed, registering an app id, revoking certs (like registering certs: post it on our issue tracker) and signing apps.

Also some background needs to be provided on how the whole certificate mechanism works.



Discussion:

Resolving patch:
diff --git a/nextcloudappstore/core/forms.py b/nextcloudappstore/core/forms.py
--- a/nextcloudappstore/core/forms.py
+++ b/nextcloudappstore/core/forms.py
@@ -13,15 +13,32 @@
 
 class AppReleaseUploadForm(Form):
     download = CharField(label=_('Download link (tar.gz)'), max_length=256)
-    signature = CharField(widget=Textarea, label=_('SHA512 signature'),
-                          help_text=_(
-                              'Hint: can be calculated by executing the '
-                              'following command: openssl dgst -sha512 -sign '
-                              '/path/to/private-cert.key /path/to/app.tar.gz '
-                              '| openssl base64'))
+    signature = CharField(
+        widget=Textarea,
+        label=_('SHA512 signature'),
+        help_text=_(
+            'Hint: can be calculated by executing the '
+            'following command: openssl dgst -sha512 -sign '
+            '~/.nextcloud/certificates/APP_ID.key '
+            '/path/to/app.tar.gz | openssl base64'))
     nightly = BooleanField(label=_('Nightly'))
 
 
+class AppRegisterForm(Form):
+    certificate = CharField(
+        widget=Textarea(attrs={'pattern': '-----BEGIN CERTIFICATE-----.*'}),
+        label=_('Public certificate'),
+        help_text=_(
+            'Usually stored in ~/.nextcloud/certificates/APP_ID.crt'))
+    signature = CharField(
+        widget=Textarea,
+        label=_('SHA512 signature'),
+        help_text=_(
+            'Hint: can be calculated by executing the '
+            'following command: echo -n "APP_ID" | openssl dgst -sha512 -sign '
+            '~/.nextcloud/certificates/APP_ID.key | openssl base64'))
+
+
 class AppRatingForm(Form):
     def __init__(self, *args, **kwargs):
         self._id = kwargs.pop('id', None)


Test patch:
Repository: nextcloud/appstore

Issue:
Modify own name error
There is an error when saving name on the user profile. It said the mail address is already registered instead of saving



Discussion:
Solution should be to remove the check for the same account email here https://github.com/nextcloud/appstore/blob/master/nextcloudappstore/core/user/forms.py#L53 since we only use 1 email ever


Resolving patch:
diff --git a/nextcloudappstore/core/api/v1/release/importer.py b/nextcloudappstore/core/api/v1/release/importer.py
--- a/nextcloudappstore/core/api/v1/release/importer.py
+++ b/nextcloudappstore/core/api/v1/release/importer.py
@@ -1,4 +1,6 @@
 from typing import Dict, Any, Set, Tuple  # type: ignore
+
+from django.conf import settings
 from semantic_version import Version  # type: ignore
 from django.utils import timezone
 from nextcloudappstore.core.versioning import to_spec, to_raw_spec
@@ -149,8 +151,9 @@ def map_categories(cat: Dict) -> Category:
 
 class L10NImporter(ScalarImporter):
     def import_data(self, key: str, value: Any, obj: Any) -> None:
-        for lang, translation in value.items():
-            obj.set_current_language(lang)
+        for code, _ in settings.LANGUAGES:
+            translation = value.get(code, value.get('en'))
+            obj.set_current_language(code)
             setattr(obj, key, translation)
             obj.save()
 
diff --git a/nextcloudappstore/core/user/forms.py b/nextcloudappstore/core/user/forms.py
--- a/nextcloudappstore/core/user/forms.py
+++ b/nextcloudappstore/core/user/forms.py
@@ -43,18 +43,10 @@ class Meta:
 
     def clean_email(self):
         value = self.cleaned_data["email"]
-        errors = {
-            "this_account": _("This e-mail address is already associated"
-                              " with this account."),
-            "different_account": _("This e-mail address is already associated"
-                                   " with another account."),
-        }
         users = filter_users_by_email(value)
-        on_this_account = [u for u in users if u.pk == self.instance.pk]
-        on_diff_account = [u for u in users if u.pk != self.instance.pk]
-
-        if on_this_account:
-            raise forms.ValidationError(errors["this_account"])
-        if on_diff_account:
-            raise forms.ValidationError(errors["different_account"])
+        if [u for u in users if u.pk != self.instance.pk]:
+            msg = _(
+                "This e-mail address is already associated with another "
+                "account.")
+            raise forms.ValidationError(msg)
         return value


Test patch:
Repository: nextcloud/appstore

Issue:
hide rating form for app owners
Currently app owners also see app rating forms for their own apps. While it's statistically irrelevant people seem to think that it's a way to cheat the system. We should therefore simply hide the form and button for owners.



Discussion:
Your Instagram pictures can also be liked by yourself 😛 - same for Facebook 😜 
...but yes. We should hide 😁 


Resolving patch:
diff --git a/nextcloudappstore/core/forms.py b/nextcloudappstore/core/forms.py
--- a/nextcloudappstore/core/forms.py
+++ b/nextcloudappstore/core/forms.py
@@ -61,7 +61,7 @@ def __init__(self, *args, **kwargs):
     rating = ChoiceField(initial=0.5, choices=RATING_CHOICES,
                          widget=RadioSelect)
     comment = CharField(widget=Textarea, required=False,
-                        label=_('Review'))
+                        label=_('Comment'))
 
     class Meta:
         fields = ('rating', 'comment')
diff --git a/nextcloudappstore/core/views.py b/nextcloudappstore/core/views.py
--- a/nextcloudappstore/core/views.py
+++ b/nextcloudappstore/core/views.py
@@ -80,7 +80,7 @@ def get_context_data(self, **kwargs):
                 except AppRating.DoesNotExist:
                     comment = ''
 
-                context['rating_form'] = AppRatingForm(initial={
+                context['rating_form'] = AppRatingForm({
                     'rating': app_rating.rating,
                     'comment': comment
                 })


Test patch:
Repository: nextcloud/appstore

Issue:
Loading forever
![image](https://cloud.githubusercontent.com/assets/3178412/19383883/770704fa-91fe-11e6-81f8-353c60aa6358.png)

`Error  core    Could not get application: Client error response [url] https://apps.nextcloud.com/api/v0/content/data/166055?version=9x0x53x0 [status code] 404 [reason phrase] Not Found`

This happens when navigating the categories from a NC9 snappy core NCBox instance.
They never load (obviously).

Meta: https://help.nextcloud.com/t/new-app-store-nextcloud-9-10-testers-wanted/4160



Discussion:
Yep, experienced that too but that's a bug in the server repo. As for the 404: Looks like its trying to find updates for an installed app that was not uploaded to the new store yet

For the loading spinner: change categories until it works

That is unfortunately the only relevant log entry (replicated several times for different version numbers) I didn't experience this with "stock" app store and there are no additional apps beyond Files, Activity and Gallery

@jasonbayton can you get the spinner to disappear if you click around in the category list?

Not unless I change category. Some categories load quickly, most spin forever.

Right, but you get them to show up right?

I'm not sure what you mean, so screenshots: 

![apps nextcloud](https://cloud.githubusercontent.com/assets/3178412/19386359/a34f3c96-920b-11e6-8535-da3af394fda7.png)

![apps nextcloud2](https://cloud.githubusercontent.com/assets/3178412/19386349/9093df80-920b-11e6-9e66-34e497e6f0db.png)

![apps nextcloud3](https://cloud.githubusercontent.com/assets/3178412/19386348/90930380-920b-11e6-8815-7cdf45ec5646.png)

What I mean is: 
- You click on category Office & Text
- It shows an endless spinner
- You click on category Files
- It shows an app like posted above
- You jump between the two categories until there is no Spinner for Office & Text

Ok, in which case no - no matter how much I click between categories the spinner hasn't vanished on Office. It loads forever (so far up to 20 mins)

The issue is the same for 
- authentication & authorization
- social & communication
- office & text

The reason is that no requests are made from the web interface if you click on that category. It seems that they dont use category ids but munch them in some sort of string format that can't deal with the ampersand.

Solution is probably to strip the **&** in the API and replace it with **and** since I doubt that people will put much work into fixing this :)

My next guess is that categories also fail if they contain whitespace. In that case we must strip the rest and only deliver the first word as category


Resolving patch:
diff --git a/nextcloudappstore/core/templatetags/first_word.py b/nextcloudappstore/core/templatetags/first_word.py
new file mode 100644
--- /dev/null
+++ b/nextcloudappstore/core/templatetags/first_word.py
@@ -0,0 +1,8 @@
+from django import template
+
+register = template.Library()
+
+
+@register.filter(name='first_word')
+def first_word(sentence):
+    return sentence.split()[0]


Test patch:
Repository: nextcloud/appstore

Issue:
App release changelog should be exposed on the app releases page



Discussion:

Resolving patch:
diff --git a/nextcloudappstore/core/templatetags/markdown.py b/nextcloudappstore/core/templatetags/markdown.py
new file mode 100644
--- /dev/null
+++ b/nextcloudappstore/core/templatetags/markdown.py
@@ -0,0 +1,16 @@
+from django.conf import settings
+from django.utils.safestring import mark_safe
+from django import template
+from markdown import markdown as default_markdown
+from bleach import clean
+
+register = template.Library()
+
+
+@register.filter(name='markdown')
+def markdown(sentence):
+    text = default_markdown(sentence)
+    safe_text = clean(text,
+                      attributes=settings.MARKDOWN_ALLOWED_ATTRIBUTES,
+                      tags=settings.MARKDOWN_ALLOWED_TAGS)
+    return mark_safe(safe_text)
diff --git a/nextcloudappstore/settings/base.py b/nextcloudappstore/settings/base.py
--- a/nextcloudappstore/settings/base.py
+++ b/nextcloudappstore/settings/base.py
@@ -268,10 +268,9 @@
 # whitelist for serializing markdown
 MARKDOWN_ALLOWED_TAGS = [
     'audio', 'video', 'source', 'dt', 'dd', 'dl', 'table', 'caption', 'tr',
-    'th', 'td', 'tbody', 'thead', 'h2', 'h3', 'h4', 'h5', 'h6', 'strong', 'em',
-    'code', 'pre', 'blockquote', 'p', 'ul', 'li', 'ol', 'br', 'del', 'a',
-    'img', 'figure', 'figcaption', 'cite', 'time', 'abbr', 'iframe', 'q', 'h1'
-]
+    'th', 'td', 'tbody', 'thead', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'strong',
+    'em', 'code', 'pre', 'blockquote', 'p', 'ul', 'li', 'ol', 'br', 'del', 'a',
+    'img', 'figure', 'figcaption', 'cite', 'time', 'abbr', 'iframe', 'q', ]
 MARKDOWN_ALLOWED_ATTRIBUTES = {
     'audio': ['controls', 'src'],
     'video': ['poster', 'controls', 'height', 'width', 'src'],
diff --git a/nextcloudappstore/urls.py b/nextcloudappstore/urls.py
--- a/nextcloudappstore/urls.py
+++ b/nextcloudappstore/urls.py
@@ -1,11 +1,12 @@
 from allauth.account.views import signup
 from allauth.socialaccount.views import signup as social_signup
-from csp.decorators import csp_exempt, csp_update
+from csp.decorators import csp_update
 from django.conf import settings
 from django.conf.urls import url, include
 from django.conf.urls.i18n import i18n_patterns
 from django.contrib import admin
 from django.views.decorators.http import etag
+
 from nextcloudappstore.core.caching import app_rating_etag
 from nextcloudappstore.core.feeds import AppReleaseAtomFeed, AppReleaseRssFeed
 from nextcloudappstore.core.views import CategoryAppListView, AppDetailView, \


Test patch:
Repository: nextcloud/appstore

Issue:
schema does not allow digits in app ids
Apparently app ids like ``twofactor_u2f`` are not allowed by the info.xml schema. Could we change that regex to allow digits too or are there any strong arguments against that?

ref https://github.com/nextcloud/appstore/blob/e4567ce707b332ca14eb35e322bff5ec4397191b/nextcloudappstore/core/api/v1/release/info.xsd#L245-L250


Discussion:
If it works it should not be an issue. However this would likely require you to change the regex at various other places (mainly urls) as well, for instance https://github.com/nextcloud/appstore/blob/master/nextcloudappstore/core/api/v1/urls.py#L16

I'd grep the source for **r'** and adjust the app id specific regexes if you think this should be fixed.


Resolving patch:
diff --git a/nextcloudappstore/core/api/v1/urls.py b/nextcloudappstore/core/api/v1/urls.py
--- a/nextcloudappstore/core/api/v1/urls.py
+++ b/nextcloudappstore/core/api/v1/urls.py
@@ -13,7 +13,7 @@
     url(r'^apps/releases/?$', AppReleaseView.as_view(),
         name='app-release-create'),
     url(r'^apps/?$', AppRegisterView.as_view(), name='app-register'),
-    url(r'^apps/(?P<pk>[a-z_]+)/?$', AppView.as_view(), name='app-delete'),
+    url(r'^apps/(?P<pk>[a-z0-9_]+)/?$', AppView.as_view(), name='app-delete'),
     url(r'^ratings.json$',
         etag(app_ratings_etag)(AppRatingView.as_view()),
         name='app-ratings'),


Test patch:
diff --git a/nextcloudappstore/core/api/v1/tests/data/infoxmls/digits.xml b/nextcloudappstore/core/api/v1/tests/data/infoxmls/digits.xml
new file mode 100644
--- /dev/null
+++ b/nextcloudappstore/core/api/v1/tests/data/infoxmls/digits.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<info xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../appmetadata/info.xsd">
+    <id>twofactor_u2f</id>
+    <name>News</name>
+    <description>An RSS/Atom feed reader</description>
+    <version>8.8.2</version>
+    <licence>agpl</licence>
+    <author>Bernhard Posselt</author>
+    <category>multimedia</category>
+    <dependencies>
+        <owncloud min-version="9.0"/>
+    </dependencies>
+</info>
diff --git a/nextcloudappstore/core/api/v1/tests/test_parser.py b/nextcloudappstore/core/api/v1/tests/test_parser.py
--- a/nextcloudappstore/core/api/v1/tests/test_parser.py
+++ b/nextcloudappstore/core/api/v1/tests/test_parser.py
@@ -74,6 +74,13 @@ def test_parse_pre_release(self):
         version = result['app']['release']['version']
         self.assertEqual('1.0.0-alpha.1', version)
 
+    def test_parse_digit_id(self):
+        xml = self._get_contents('data/infoxmls/digits.xml')
+        result = parse_app_metadata(xml, self.config.info_schema,
+                                    self.config.pre_info_xslt,
+                                    self.config.info_xslt)
+        self.assertEqual('twofactor_u2f', result['app']['id'])
+
     def test_parse_invalid_elements(self):
         xml = self._get_contents('data/infoxmls/invalid-elements.xml')
         with (self.assertRaises(InvalidAppMetadataXmlException)):
Repository: nextcloud/appstore

Issue:
RSS/Atom Feed: Don't show Changes headline if Changelog is empty
Needs a check if item.changelog is empty https://github.com/nextcloud/appstore/blob/master/nextcloudappstore/core/feeds.py#L36


Discussion:

Resolving patch:
diff --git a/nextcloudappstore/core/feeds.py b/nextcloudappstore/core/feeds.py
--- a/nextcloudappstore/core/feeds.py
+++ b/nextcloudappstore/core/feeds.py
@@ -33,8 +33,11 @@ def item_title(self, item):
 
     def item_description(self, item):
         try:
-            content = ('%s\n\n# %s\n\n%s' % (
-                item.app.description, _('Changes'), item.changelog))
+            if item.changelog:
+                changelog = '\n\n# %s\n\n%s' % (_('Changes'), item.changelog)
+            else:
+                changelog = ''
+            content = '%s%s' % (item.app.description, changelog)
         except TranslationDoesNotExist:
             content = item.app.description
         content += '\n\n [%s](%s)' % (_('Download'), item.download)


Test patch: