internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: akvo/akvo-rsr

Issue:
UnicodeDecodeError at /rest/v1/recipient_country/
'ascii' codec can't decode byte 0xc3 in position 7: ordinal not in range(128)



Discussion:

Resolving patch:
diff --git a/akvo/rsr/models/country.py b/akvo/rsr/models/country.py
--- a/akvo/rsr/models/country.py
+++ b/akvo/rsr/models/country.py
@@ -51,7 +51,7 @@ class RecipientCountry(models.Model):
         'Project', verbose_name=_(u'project'), related_name='recipient_countries'
     )
     country = ValidXMLCharField(
-        _(u'recipient country'), blank=True, max_length=2,choices=codelist_choices(COUNTRY, show_code=False),
+        _(u'recipient country'), blank=True, max_length=2, choices=codelist_choices(COUNTRY, show_code=False),
         help_text=_(u'The country that benefits from the project.')
     )
     percentage = models.DecimalField(
@@ -85,7 +85,7 @@ def iati_country(self):
         return codelist_value(codelist_models.Country, self, 'country')
 
     def iati_country_unicode(self):
-        return str(self.iati_country())
+        return unicode(self.iati_country())
 
     class Meta:
         app_label = 'rsr'


Test patch:
diff --git a/akvo/rsr/tests/rest/test_recipient_country.py b/akvo/rsr/tests/rest/test_recipient_country.py
new file mode 100644
--- /dev/null
+++ b/akvo/rsr/tests/rest/test_recipient_country.py
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+
+"""
+Akvo RSR is covered by the GNU Affero General Public License.
+
+See more details in the license.txt file located at the root folder of the Akvo RSR module.
+For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.
+"""
+
+import json
+
+from akvo.codelists.store.codelists_v202 import COUNTRY
+from akvo.codelists.models import Country, Version
+from akvo.rsr.models import Project, RecipientCountry
+
+from django.conf import settings
+from django.test import TestCase, Client
+
+
+class RecipientCountryTestCase(TestCase):
+    """Tests the recipient country REST endpoints."""
+
+    def setUp(self):
+        self.c = Client(HTTP_HOST=settings.RSR_DOMAIN)
+        version, _ = Version.objects.get_or_create(code=settings.IATI_VERSION, url='http://iati.org')
+        for code, name in COUNTRY[1:]:
+            Country.objects.create(name=name, code=code, version=version)
+
+    def tearDown(self):
+        Project.objects.all().delete()
+        Country.objects.all().delete()
+        RecipientCountry.objects.all().delete()
+
+    def test_unicode_recipient_country_name(self):
+        """Checks that a recipient country with a unicode name can be fetched."""
+
+        # Given
+        project = Project.objects.create(title="REST test project")
+        recipient_country = RecipientCountry.objects.create(
+            project=project,
+            country="CI",
+        )
+
+        # When
+        response = self.c.get('/rest/v1/recipient_country/?format=json&project={}'.format(project.id))
+
+        # Then
+        self.assertEqual(response.status_code, 200)
+        country = json.loads(response.content)['results'][0]['country']
+        self.assertEqual(recipient_country.country, country)
Repository: akvo/akvo-rsr

Issue:
UnicodeEncodeError with ProjectCustomField
```python

  File "django/core/handlers/base.py", line 111, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "django/views/decorators/csrf.py", line 57, in wrapped_view
    return view_func(*args, **kwargs)
  File "django/views/generic/base.py", line 69, in view
    return self.dispatch(request, *args, **kwargs)
  File "rest_framework/views.py", line 466, in dispatch
    response = self.handle_exception(exc)
  File "rest_framework/views.py", line 463, in dispatch
    response = handler(request, *args, **kwargs)
  File "rest_framework/decorators.py", line 53, in handler
    return func(*args, **kwargs)
  File "akvo/rest/views/project_editor.py", line 576, in project_editor
    'changes': log_changes(changes, user, project),
  File "akvo/rest/views/project_editor.py", line 92, in log_changes
    object_repr=obj.__unicode__(),
  File "akvo/rsr/models/custom_field.py", line 77, in __unicode__
    return u'%s' % str(self.value)
```


Discussion:

Resolving patch:
diff --git a/akvo/rsr/models/custom_field.py b/akvo/rsr/models/custom_field.py
--- a/akvo/rsr/models/custom_field.py
+++ b/akvo/rsr/models/custom_field.py
@@ -74,7 +74,7 @@ class ProjectCustomField(models.Model):
     )
 
     def __unicode__(self):
-        return u'%s' % str(self.value)
+        return u'%s' % self.value
 
 
 class OrganisationCustomField(models.Model):
@@ -140,4 +140,4 @@ class OrganisationCustomField(models.Model):
         _(u'type'), max_length=20, choices=TYPES, default='text',
         help_text=_(u'Select the type of custom field. Text will show a text area in the project '
                     u'editor, and checkbox will show a checkbox.')
-    )
\ No newline at end of file
+    )


Test patch:
diff --git a/akvo/rsr/tests/models/test_custom_field.py b/akvo/rsr/tests/models/test_custom_field.py
new file mode 100644
--- /dev/null
+++ b/akvo/rsr/tests/models/test_custom_field.py
@@ -0,0 +1,31 @@
+# -*- coding: utf-8 -*-
+
+# Akvo Reporting is covered by the GNU Affero General Public License.
+# See more details in the license.txt file located at the root folder of the Akvo RSR module.
+# For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.
+
+
+from unittest import TestCase
+
+from akvo.rsr.models import Project, ProjectCustomField
+
+
+class CustomFieldTestCase(TestCase):
+    """Tests for the custom field models."""
+
+    def tearDown(self):
+        Project.objects.all().delete()
+        ProjectCustomField.objects.all().delete()
+
+    def test_unicode_value_custom_field(self):
+        """Test that unicode value custom field doesn't raise unicode errors."""
+
+        # Given
+        value = u'Côte Divoire'
+        project = Project.objects.create(title='Test project')
+        field = ProjectCustomField.objects.create(
+            project=project, section=1, value=value, order=1
+        )
+
+        # When/Then
+        self.assertEqual(value, unicode(field))
Repository: akvo/akvo-rsr

Issue:
Username validation restricts max length to 30 characters in admin interface
Even though the max length for the username field is set to 254 characters, validation seems to restrict it to 30 characters when editing from the old admin. 

![imgpsh_fullsize](https://cloud.githubusercontent.com/assets/315678/23113267/0967e0da-f75d-11e6-8ad4-6d4dd402d1a6.png)



Discussion:

Resolving patch:
diff --git a/akvo/rsr/admin.py b/akvo/rsr/admin.py
--- a/akvo/rsr/admin.py
+++ b/akvo/rsr/admin.py
@@ -13,8 +13,11 @@
 from django.contrib.admin import helpers, widgets
 from django.contrib.admin.options import IS_POPUP_VAR
 from django.contrib.admin.util import flatten_fieldsets
-from django.contrib.auth import get_permission_codename, get_user_model
+from django.contrib.auth import get_user_model
 from django.contrib.auth.admin import UserAdmin as DjangoUserAdmin
+from django.contrib.auth.forms import (
+    UserChangeForm as DjangoUserChangeForm, UserCreationForm as DjangoUserCreationForm
+)
 from django.contrib.auth.models import Group
 from django.db import models, transaction
 from django.db.models import get_model
@@ -1106,6 +1109,29 @@ def has_delete_permission(self, request, obj=None, **kwargs):
         return False
 
 
+class UserCreationForm(DjangoUserCreationForm):
+
+    username = forms.RegexField(
+        label=_("Username"), max_length=254,
+        regex=r'^[\w.@+-]+$',
+        help_text=_("Required. 254 characters or fewer. Letters, digits and "
+                    "@/./+/-/_ only."),
+        error_messages={
+            'invalid': _("This value may contain only letters, numbers and "
+                         "@/./+/-/_ characters.")})
+
+
+class UserChangeForm(DjangoUserChangeForm):
+
+    username = forms.RegexField(
+        label=_("Username"), max_length=254, regex=r"^[\w.@+-]+$",
+        help_text=_("Required. 254 characters or fewer. Letters, digits and "
+                    "@/./+/-/_ only."),
+        error_messages={
+            'invalid': _("This value may contain only letters, numbers and "
+                         "@/./+/-/_ characters.")})
+
+
 class UserAdmin(DjangoUserAdmin):
     model = get_model('rsr', 'user')
     fieldsets = (
@@ -1131,6 +1157,9 @@ class UserAdmin(DjangoUserAdmin):
     search_fields = ('username', 'email', 'first_name', 'last_name')
     ordering = ('username',)
 
+    form = UserChangeForm
+    add_form = UserCreationForm
+
     def get_readonly_fields(self, request, obj=None):
         if request.user.is_superuser:
             return ['last_login', 'date_joined']


Test patch:
Repository: akvo/akvo-rsr

Issue:
Increase the max_length of `Keyword.label`
Currently 30. EUTF needs longer keywords. 


Discussion:

Resolving patch:
diff --git a/akvo/rsr/migrations/0094_auto_20170222_1059.py b/akvo/rsr/migrations/0094_auto_20170222_1059.py
new file mode 100644
--- /dev/null
+++ b/akvo/rsr/migrations/0094_auto_20170222_1059.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+import akvo.rsr.fields
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('rsr', '0093_auto_20170216_1409'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='keyword',
+            name='label',
+            field=akvo.rsr.fields.ValidXMLCharField(help_text='Select keywords in case you are using an Akvo Page. Keywords linked to a project will determine if a project appears on the Akvo Page or not.', unique=True, max_length=100, verbose_name='label', db_index=True),
+            preserve_default=True,
+        ),
+    ]
diff --git a/akvo/rsr/models/keyword.py b/akvo/rsr/models/keyword.py
--- a/akvo/rsr/models/keyword.py
+++ b/akvo/rsr/models/keyword.py
@@ -20,7 +20,7 @@ def logo_path(instance, file_name):
 
 class Keyword(models.Model):
     label = ValidXMLCharField(
-        _(u'label'), max_length=30, unique=True, db_index=True,
+        _(u'label'), max_length=100, unique=True, db_index=True,
         help_text=_(u'Select keywords in case you are using an Akvo Page. Keywords linked to a '
                     u'project will determine if a project appears on the Akvo Page or not.')
     )


Test patch:
Repository: akvo/akvo-rsr

Issue:
non-EUTF search results appearing (estimate: 8)
Created via Reamaze:

Link: https://akvoo.reamaze.com/admin/conversations/rsr-release-3-dot-22-chisinau-is-out
Assignee: Unassigned

Message:
Hi RSR Team,

Just saw this email, nice that the new release is already out! However, I tried to use the search function, and it shows organizations that are not related to the Akvo Page, in this case the EUTF Page. Randomly searching for “Tom(bouctou)” gives the following search options. Clicking on the first organization “Catholic Diocese of Tombu", it leads you nowhere..

Please see image below.

Thanks!
Christien

Christien Bosman
Project Officer

Akvo • 's-Gravenhekje 1A • 1011 TG • Amsterdam (NL)
T +31 20 8200 175 • M +31 6 1191 5449 • S christien.bosman • I www.akvo.org &lt;http://www.akvo.org/&gt;



Discussion:

Resolving patch:
diff --git a/akvo/rest/views/typeahead.py b/akvo/rest/views/typeahead.py
--- a/akvo/rest/views/typeahead.py
+++ b/akvo/rest/views/typeahead.py
@@ -40,7 +40,8 @@ def typeahead_country(request):
 
 @api_view(['GET'])
 def typeahead_organisation(request):
-    organisations = Organisation.objects.all()
+    page = request.rsr_page
+    organisations = page.organisation.partners().distinct() if page else Organisation.objects.all()
     return Response(
         rejig(organisations, TypeaheadOrganisationSerializer(organisations,
                                                              many=True))


Test patch:
Repository: akvo/akvo-rsr

Issue:
Change landing page for 'My RSR' (estimate: 4) 
Change landing page when going to 'My RSR' from:

'My Details' 

to:

'My Projects' 


Discussion:

Resolving patch:
diff --git a/akvo/rsr/views/account.py b/akvo/rsr/views/account.py
--- a/akvo/rsr/views/account.py
+++ b/akvo/rsr/views/account.py
@@ -133,14 +133,14 @@ def approve_employment(invitee, invited, empl):
 
     def login_and_redirect(req, invited):
         """
-        Log the invited user in and redirect to the My details page in MyRSR.
+        Log the invited user in and redirect to the My projects page in MyRSR.
 
         :param req: the request
         :param invited: the invited user's instance
         """
         invited = authenticate(username=invited.username, no_password=True)
         login(request, invited)
-        return redirect('my_details')
+        return redirect('my_projects')
 
     bad_link, user, inviting_user, employment = False, None, None, None
 
@@ -198,7 +198,7 @@ def sign_in(request):
         if form.is_valid():
             login(request, form.get_user())
             next_page = request.GET.get('next')
-            return HttpResponseRedirect(next_page) if next_page else redirect('my_details')
+            return HttpResponseRedirect(next_page) if next_page else redirect('my_projects')
     # Password reset on sign in page
     elif request.method == "POST" and 'email' in request.POST:
         reset_form = PasswordResetForm(data=request.POST)
diff --git a/akvo/rsr/views/my_rsr.py b/akvo/rsr/views/my_rsr.py
--- a/akvo/rsr/views/my_rsr.py
+++ b/akvo/rsr/views/my_rsr.py
@@ -36,11 +36,11 @@
 @login_required
 def my_rsr(request):
     """
-    Redirect to the 'My Details' page in MyRSR, if the user is logged in.
+    Redirect to the 'My Projects' page in MyRSR, if the user is logged in.
 
     :param request; A Django request.
     """
-    return HttpResponseRedirect(reverse('my_details', args=[]))
+    return HttpResponseRedirect(reverse('my_projects', args=[]))
 
 
 @login_required


Test patch:
Repository: akvo/akvo-rsr

Issue:
Add honeypot hidden field to RSR Registration page (estimate: 4)
During implementation of #2340, we noticed that there are a lot of spam bots who used the RSR Register page and ended up in RSR database.

To avoid that in the future, we need to add captcha to the Register page. 


Discussion:
[This package](https://github.com/praekelt/django-recaptcha) and [blog post](http://www.yaconiello.com/blog/integrating-google-recaptcha-to-django/) can be useful when we finally get around to implementing this. 
I think we can try with just adding a hidden field to the registration form. If the field contains data we silently delete the registration. This should keep simple registration bots out and is much lighter than a full captcha.

If we implement this we can run it for a month and then evaluate if it's good enough.
What would our evaluation criteria be? Do we know the rate at which we get spam accounts created now? What would be an acceptable rate of spam? :smiley: 
Are we also going to delete the existing junk usernames, to see how effective this fix is?  Should we write a management command or a migration script for this? 

Resolving patch:
diff --git a/akvo/rsr/management/commands/delete_spam_users.py b/akvo/rsr/management/commands/delete_spam_users.py
new file mode 100644
--- /dev/null
+++ b/akvo/rsr/management/commands/delete_spam_users.py
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+
+# Akvo Reporting is covered by the GNU Affero General Public License.
+# See more details in the license.txt file located at the root folder of the Akvo RSR module.
+# For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.
+
+import datetime
+import sys
+
+from django.core.management.base import BaseCommand
+from django.contrib.auth import get_user_model
+from django.db.models import Count
+
+User = get_user_model()
+
+
+class Command(BaseCommand):
+    help = "Delete spam users from the DB"
+
+    def handle(self, *args, **options):
+        """Delete spam user accounts from the DB.
+
+        Deletes all users who joined more than a week ago, but don't have an
+        employment associated with them.
+
+        """
+
+        last_week = datetime.datetime.today() + datetime.timedelta(days=-7)
+
+        no_employment_users = User.objects.annotate(employer_count=Count('employers')).filter(
+            date_joined__lt=last_week,
+            employer_count=0
+        )
+
+        sys.stdout.write(u"Found {} spam users.".format(no_employment_users.count()))
+        sys.stdout.write(u"\nDeleting ...\n")
+        sys.stdout.flush()
+
+        no_employment_users.delete()
+
+        sys.stdout.write("\nDone!\n")


Test patch:
Repository: akvo/akvo-rsr

Issue:
Add a new project button shown even if no permissions
When a user (is an admin, but) doesn't belong to any organisation that `can_create_projects`, the `Add a new project` button shouldn't be shown. 

Currently, when that is clicked, the project editor doesn't open up and the button gets de-activated. 

But, when the projects listing page is reloaded a new empty project is shown. 

![thu sep 15 18 59 55 ist 2016](https://cloud.githubusercontent.com/assets/315678/18551619/cc113fae-7b76-11e6-8999-d46f6e7450d2.jpg)

This may not be as much of a problem on the deployed instance, but was something I found on the dev instance. 



Discussion:

Resolving patch:
diff --git a/akvo/rsr/models/user.py b/akvo/rsr/models/user.py
--- a/akvo/rsr/models/user.py
+++ b/akvo/rsr/models/user.py
@@ -376,16 +376,11 @@ def approved_employments(self):
         return self.employers.all().exclude(is_approved=False)
 
     def can_create_project(self):
-        """
-        Check to see if the user can create a project, or is a superuser.
-
-        :return: Boolean to indicate whether the user has a reportable organisation
-        """
-        if self.is_superuser or self.is_admin:
-            return True
+        """Check to see if the user can create a project."""
 
         for employment in self.approved_employments():
-            if employment.organisation.can_create_projects:
+            org = employment.organisation
+            if org.can_create_projects and self.has_perm('rsr.add_project', org):
                 return True
 
         return False


Test patch:
Repository: akvo/akvo-rsr

Issue:
UnicodeError when handling errors in project editor
http://sentry.support.akvo-ops.org/rsr/live/group/1169/

```
Stacktrace (most recent call last):

  File "django/core/handlers/base.py", line 111, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "django/views/decorators/csrf.py", line 57, in wrapped_view
    return view_func(*args, **kwargs)
  File "django/views/generic/base.py", line 69, in view
    return self.dispatch(request, *args, **kwargs)
  File "rest_framework/views.py", line 466, in dispatch
    response = self.handle_exception(exc)
  File "rest_framework/views.py", line 463, in dispatch
    response = handler(request, *args, **kwargs)
  File "rest_framework/decorators.py", line 53, in handler
    return func(*args, **kwargs)
  File "akvo/rest/views/project_editor.py", line 439, in project_editor
    obj_data, errors = pre_process_data(key, data[key], errors)
  File "akvo/rest/views/project_editor.py", line 184, in pre_process_data
    errors = add_error(errors, e, key)
  File "akvo/rest/views/project_editor.py", line 67, in add_error
    'error': str(message).capitalize()}
```



Discussion:

Resolving patch:
diff --git a/akvo/rest/views/project_editor.py b/akvo/rest/views/project_editor.py
--- a/akvo/rest/views/project_editor.py
+++ b/akvo/rest/views/project_editor.py
@@ -64,7 +64,7 @@ def add_error(errors, message, field_name):
     """Appends a new error to the errors list."""
     errors.append(
         {'name': field_name,
-         'error': str(message).capitalize()}
+         'error': message.encode('utf8').capitalize()}
     )
     return errors
 


Test patch:
diff --git a/akvo/rsr/tests/rest/test_project_editor.py b/akvo/rsr/tests/rest/test_project_editor.py
--- a/akvo/rsr/tests/rest/test_project_editor.py
+++ b/akvo/rsr/tests/rest/test_project_editor.py
@@ -14,6 +14,8 @@
 from django.contrib.auth.models import Group
 from django.test import TestCase, Client
 
+from akvo.rest.views.project_editor import add_error
+
 
 class BaseReorderTestCase(object):
 
@@ -284,3 +286,31 @@ def create_item(self, order=None):
 
     def get_items(self):
         return Indicator.objects.filter(result_id=self.result.id).order_by('id')
+
+
+class ErrorHandlerTestCase(TestCase):
+    """Tests for the error handler used by project editor."""
+
+    def test_should_handle_unicode_errors(self):
+        # Given
+        message = u"""Il n'est pas permis d'utiliser une virgule, utilisez un point pour indiquer les décimales."""
+        errors = []
+        field_name = u'rsr_budgetitem.amount.5966_new-0'
+
+        # When
+        add_error(errors, message, field_name)
+
+        # Then
+        self.assertEquals(1, len(errors))
+
+    def test_should_handle_str_errors(self):
+        # Given
+        message = "It is not allowed to use a comma, use a period to denote decimals."
+        errors = []
+        field_name = u'rsr_budgetitem.amount.5966_new-0'
+
+        # When
+        add_error(errors, message, field_name)
+
+        # Then
+        self.assertEquals(1, len(errors))
Repository: akvo/akvo-rsr

Issue:
Indicator descriptions missing in IATI file
Created via Reamaze:

Link: https://akvoo.reamaze.com/admin/conversations/urgent-indicator-descriptions-missing-in-iati-file

Indicator descriptions are not visible in RSR-generated IATI-files, even though they are an IATI field. 


Discussion:

Resolving patch:
diff --git a/akvo/iati/exports/elements/result.py b/akvo/iati/exports/elements/result.py
--- a/akvo/iati/exports/elements/result.py
+++ b/akvo/iati/exports/elements/result.py
@@ -58,7 +58,7 @@ def result(project):
                     if indicator.description:
                         description_element = etree.SubElement(indicator_element, "description")
                         narrative_element = etree.SubElement(description_element, "narrative")
-                        narrative_element.text = res.description
+                        narrative_element.text = indicator.description
 
                     for reference in indicator.references.all():
                         if reference.vocabulary or reference.reference or reference.vocabulary_uri:


Test patch:
diff --git a/akvo/rsr/tests/iati_export/test_iati_export.py b/akvo/rsr/tests/iati_export/test_iati_export.py
--- a/akvo/rsr/tests/iati_export/test_iati_export.py
+++ b/akvo/rsr/tests/iati_export/test_iati_export.py
@@ -405,7 +405,7 @@ def test_complete_project_export(self):
             measure="1",
             ascending=True,
             title="Title",
-            description="Description",
+            description="Indicator Description",
             baseline_year=2016,
             baseline_value="1",
             baseline_comment="Comment"
@@ -489,6 +489,12 @@ def test_complete_project_export(self):
         self.assertEqual(1, len(related_activities))
         self.assertEqual(attributes, related_activities[0].attrib)
 
+        # Test indicator has description
+        indicator_description_xpath = './iati-activity/result/indicator/description/narrative'
+        self.assertXpathsExist(root_test, (indicator_description_xpath,))
+        indicators = root_test.xpath(indicator_description_xpath)
+        self.assertEqual(indicators[0].text, 'Indicator Description')
+
     def test_different_complete_project_export(self):
         """
         Test the export of a fully filled project with different settings.