internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: ultrabug/py3status

Issue:
Undocumented requirement of dateutil
**Describe the bug**
The timewarrior module, amongst others, depend on the dateutil module, but it is not described as a requirement:
https://github.com/ultrabug/py3status/blob/786d1b2f8d9c9196664b3fe60970968af48114e3/py3status/modules/timewarrior.py#L143

https://github.com/ultrabug/py3status/blob/786d1b2f8d9c9196664b3fe60970968af48114e3/py3status/modules/timewarrior.py#L56-L57

**Your py3status version**
I found it here:
```
py3status version 3.43 (python 3.10.4) on i3
``

**To Reproduce**
Steps to reproduce the behavior along with your py3status configuration (filter out any private values):
1. Try to use py3status with timewarrior without dateutil installed. This'll happen on nixos
2. See the error when clicking the timewarrior module on your bar

**Expected behavior**
I expect dateutil to be declared as a requirement for the timewarrior module

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Additional context**
Add any other context about the problem here.



Discussion:
Hello,

Modules dependencies which are listed under the **Requires** docstring should be installed by users.
Py3status couldn't possibly start depending on every module's dependency as you can imagine.

Thanks
> Hello,
> 
> Modules dependencies which are listed under the **Requires** docstring should be installed by users. Py3status couldn't possibly start depending on every module's dependency as you can imagine.
> 
> Thanks

Thanks for clarifying, I fixed the issue to reflect that :)
Indeed @RasmusRendal ; would you like to propose a PR to add this to the module's docstring?

Resolving patch:
diff --git a/py3status/modules/timewarrior.py b/py3status/modules/timewarrior.py
--- a/py3status/modules/timewarrior.py
+++ b/py3status/modules/timewarrior.py
@@ -140,7 +140,6 @@
 
 from json import loads as json_loads
 import datetime as dt
-from dateutil.relativedelta import relativedelta
 
 STRING_NOT_INSTALLED = "not installed"
 DATETIME = "%Y%m%dT%H%M%SZ"
@@ -244,15 +243,15 @@ def _manipulate(self, data):
                 end = dt.datetime.strptime(time["end"], DATETIME)
 
             start = dt.datetime.strptime(time["start"], DATETIME)
-            duration = relativedelta(end, start)
+            duration = end - start
 
             time["format_duration"] = self.py3.safe_format(
                 self.format_duration,
                 {
                     "days": duration.days,
-                    "hours": duration.hours,
-                    "minutes": duration.minutes,
-                    "seconds": duration.seconds,
+                    "hours": duration.seconds // (60 * 60),
+                    "minutes": (duration.seconds // 60) % 60,
+                    "seconds": duration.seconds % 60,
                 },
             )
 


Test patch:
Repository: ultrabug/py3status

Issue:
volume_status module: pamixer: Use default device if none specified
Not specifying the device should use whatever pamixer thinks is the default. Using 0 might not be always the default, especially because the default (or whatever pamixer thinks is the default) can change at runtime.


Discussion:
Thanks!

Resolving patch:
diff --git a/py3status/modules/volume_status.py b/py3status/modules/volume_status.py
--- a/py3status/modules/volume_status.py
+++ b/py3status/modules/volume_status.py
@@ -172,7 +172,9 @@ def toggle_mute(self):
 class Pamixer(Audio):
     def setup(self, parent):
         is_input = "--source" if self.is_input else "--sink"
-        self.cmd = ["pamixer", "--allow-boost"] + ([is_input, self.device] if self.device else [])
+        self.cmd = ["pamixer", "--allow-boost"] + (
+            [is_input, self.device] if self.device is not None else []
+        )
 
     def get_volume(self):
         try:


Test patch:
Repository: svthalia/concrexit

Issue:
AttributeError: 'NoneType' object has no attribute 'is_authenticated'
In GitLab by _thaliatechnicie on Mar 11, 2020, 23:02

Sentry Issue: [CONCREXIT-2A](https://sentry.io/organizations/thalia/issues/1560438241/?referrer=gitlab_integration)

```
AttributeError: 'NoneType' object has no attribute 'is_authenticated'
(14 additional frame(s) were not displayed)
...
  File "rest_framework/serializers.py", line 529, in to_representation
    ret[field.field_name] = field.to_representation(attribute)
  File "rest_framework/fields.py", line 1905, in to_representation
    return method(value)
  File "events/api/serializers.py", line 86, in _class_names
    if services.is_user_registered(self.context["member"], instance):
  File "events/services.py", line 24, in is_user_registered
    if not event.registration_required or not member.is_authenticated:
  File "django/utils/functional.py", line 225, in inner
    return func(self._wrapped, *args)
```


Discussion:

Resolving patch:
diff --git a/website/events/api/serializers.py b/website/events/api/serializers.py
--- a/website/events/api/serializers.py
+++ b/website/events/api/serializers.py
@@ -83,7 +83,9 @@ def _url(self, instance):
 
     def _class_names(self, instance):
         class_names = ["regular-event"]
-        if services.is_user_registered(self.context["member"], instance):
+        if self.context["member"] and services.is_user_registered(
+            self.context["member"], instance
+        ):
             class_names.append("has-registration")
         return class_names
 


Test patch:
Repository: svthalia/concrexit

Issue:
Newsletters show unpublished events
### Describe the bug
Newsletters show unpublished events

### How to reproduce
Steps to reproduce the behaviour:
1. Check one of the newsletters of the last weeks

### Expected behaviour
Only published events should show.

### Additional context
This is probably because of the low number of events during these days.



Discussion:

Resolving patch:
diff --git a/website/newsletters/services.py b/website/newsletters/services.py
--- a/website/newsletters/services.py
+++ b/website/newsletters/services.py
@@ -55,11 +55,12 @@ def save_to_disk(newsletter, request):
 
 def get_agenda(start_date):
     end_date = start_date + timezone.timedelta(weeks=2)
-    base_events = Event.objects.filter(
-        start__gte=start_date, end__lt=end_date, published=True
+    published_events = Event.objects.filter(published=True)
+    base_events = published_events.filter(
+        start__gte=start_date, end__lt=end_date
     ).order_by("start")
     if base_events.count() < 10:
-        more_events = Event.objects.filter(end__gte=end_date).order_by("start")
+        more_events = published_events.filter(end__gte=end_date).order_by("start")
         return [*base_events, *more_events][:10]
     return base_events
 


Test patch:
Repository: svthalia/concrexit

Issue:
Manually entered usernames not lowercased in registrations
### Describe the bug
Manually entered usernames are not lowercased in registrations.

### How to reproduce
Steps to reproduce the behaviour:
1. Create a registration
2. Enter a manual username that is not completely lowercase
3. Complete the registration
4. Try to log-in with the new user
5. It is not possible

### Expected behaviour
The username should have been lowercased, since it is not possible to login with a username that has capitalisaton of any kind.


Discussion:
 The issue here is not that someone with a capiital in the username is not able to login. The problem is that this user had a non-lowercase character in the first place.

We have overridden forms to support case insensitive usernames in [user creation](https://github.com/svthalia/concrexit/blob/master/website/members/forms.py#L48), [user modification](https://github.com/svthalia/concrexit/blob/master/website/members/forms.py#L99) and [authentication](https://github.com/svthalia/concrexit/blob/master/website/thaliawebsite/forms.py#L5). We do this by always _lowercasing_ any username.

The username is automatically generated in [the registrations code](https://github.com/svthalia/concrexit/blob/master/website/registrations/services.py#L21). There it is lowercased. 

So the only option left is that the registration had a manually entered username. Which seems logical since the username is not something that could have been automatically composed.
I would say this is easy to fix, but it would require an extra test case to prevent this from happening again.

Resolving patch:
diff --git a/website/registrations/services.py b/website/registrations/services.py
--- a/website/registrations/services.py
+++ b/website/registrations/services.py
@@ -288,7 +288,7 @@ def _create_member_from_registration(registration: Registration) -> Member:
 
     # Create user
     user = get_user_model().objects.create_user(
-        username=registration.username,
+        username=registration.username.lower(),
         email=registration.email,
         password=password,
         first_name=registration.first_name,


Test patch:
diff --git a/website/registrations/tests/test_services.py b/website/registrations/tests/test_services.py
--- a/website/registrations/tests/test_services.py
+++ b/website/registrations/tests/test_services.py
@@ -338,7 +338,9 @@ def test_create_payment_for_entry(self):
 
     @mock.patch("registrations.services.check_unique_user")
     def test_create_member_from_registration(self, check_unique_user):
-        self.e1.username = "jdoe"
+        # We use capitalisation here because we want
+        # to test if the username is lowercased
+        self.e1.username = "JDoe"
         self.e1.save()
 
         check_unique_user.return_value = False
Repository: svthalia/concrexit

Issue:
Remove obsolete permissions
In GitLab by @se-bastiaan on Dec 4, 2019, 21:29

### One-sentence description

Remove obsolete permissions that are left from removed things

### Why?

They're obsolete!

### Current implementation

We have the sentry backend, access to the board wiki and soon the nextcloud admin permissions.

### Suggested implementation

Should be removed.


Discussion:

Resolving patch:
diff --git a/website/activemembers/migrations/0038_auto_20200513_2212.py b/website/activemembers/migrations/0038_auto_20200513_2212.py
new file mode 100644
--- /dev/null
+++ b/website/activemembers/migrations/0038_auto_20200513_2212.py
@@ -0,0 +1,21 @@
+# Generated by Django 3.0.2 on 2020-05-13 20:12
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('activemembers', '0037_membergroup_display_members'),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name='board',
+            options={'ordering': ['-since'], 'verbose_name': 'board', 'verbose_name_plural': 'boards'},
+        ),
+        migrations.RemoveField(
+            model_name='committee',
+            name='wiki_namespace',
+        ),
+    ]
diff --git a/website/activemembers/models.py b/website/activemembers/models.py
--- a/website/activemembers/models.py
+++ b/website/activemembers/models.py
@@ -135,10 +135,6 @@ class Committee(MemberGroup):
     objects = models.Manager()
     active_objects = ActiveMemberGroupManager()
 
-    wiki_namespace = models.CharField(
-        _("Wiki namespace"), null=True, blank=True, max_length=50
-    )
-
     def get_absolute_url(self):
         return reverse("activemembers:committee", args=[str(self.pk)])
 
@@ -170,7 +166,6 @@ class Meta:
         verbose_name = _("board")
         verbose_name_plural = _("boards")
         ordering = ["-since"]
-        permissions = (("board_wiki", _("Access the board wiki")),)
 
     def save(self, *args, **kwargs):
         self.active = True
diff --git a/website/thaliawebsite/settings/settings.py b/website/thaliawebsite/settings/settings.py
--- a/website/thaliawebsite/settings/settings.py
+++ b/website/thaliawebsite/settings/settings.py
@@ -301,9 +301,6 @@
 # Payments creditor identifier
 SEPA_CREDITOR_ID = os.environ.get("SEPA_CREDITOR_ID", "PLACEHOLDER")
 
-# Members Sentry API key
-MEMBERS_SENTRY_API_SECRET = os.environ.get("MEMBERS_SENTRY_API_SECRET", "")
-
 # Activemembers NextCloud API key
 ACTIVEMEMBERS_NEXTCLOUD_API_SECRET = os.environ.get(
     "ACTIVEMEMBERS_NEXTCLOUD_API_SECRET", ""
@@ -320,9 +317,6 @@
 # Photos settings
 PHOTO_UPLOAD_SIZE = 1920, 1080
 
-# API key for wiki
-WIKI_API_KEY = os.environ.get("WIKI_API_KEY", "debug")
-
 # TinyMCE config
 TINYMCE_JS_URL = "/static/tinymce/js/tinymce/tinymce.min.js"
 


Test patch:
Repository: svthalia/concrexit

Issue:
Fix "complex_logic" issue in website/events/services.py
Consider simplifying this complex logical expression.

https://codeclimate.com/github/svthalia/concrexit/website/events/services.py#issue_5ece61c6b391e1000100034b


Discussion:

Resolving patch:
diff --git a/website/events/services.py b/website/events/services.py
--- a/website/events/services.py
+++ b/website/events/services.py
@@ -40,33 +40,36 @@ def event_permissions(member, event, name=None):
         "cancel_registration": False,
         "update_registration": False,
     }
-    if member and member.is_authenticated or name:
-        registration = None
-        try:
-            registration = EventRegistration.objects.get(
-                event=event, member=member, name=name
-            )
-        except EventRegistration.DoesNotExist:
-            pass
+    if not member:
+        return perms
+    if not (member.is_authenticated or name):
+        return perms
 
-        perms["create_registration"] = (
-            (registration is None or registration.date_cancelled is not None)
-            and event.registration_allowed
-            and (name or member.can_attend_events)
-        )
-        perms["cancel_registration"] = (
-            registration is not None
-            and registration.date_cancelled is None
-            and (event.cancellation_allowed or name)
-        )
-        perms["update_registration"] = (
-            registration is not None
-            and registration.date_cancelled is None
-            and event.has_fields()
-            and event.registration_allowed
-            and (name or member.can_attend_events)
+    registration = None
+    try:
+        registration = EventRegistration.objects.get(
+            event=event, member=member, name=name
         )
+    except EventRegistration.DoesNotExist:
+        pass
 
+    perms["create_registration"] = (
+        (registration is None or registration.date_cancelled is not None)
+        and event.registration_allowed
+        and (name or member.can_attend_events)
+    )
+    perms["cancel_registration"] = (
+        registration is not None
+        and registration.date_cancelled is None
+        and (event.cancellation_allowed or name)
+    )
+    perms["update_registration"] = (
+        registration is not None
+        and registration.date_cancelled is None
+        and event.has_fields()
+        and event.registration_allowed
+        and (name or member.can_attend_events)
+    )
     return perms
 
 


Test patch:
Repository: svthalia/concrexit

Issue:
Fix "similar-code" issue in website/activemembers/admin.py
Similar blocks of code found in 2 locations. Consider refactoring.

https://codeclimate.com/github/svthalia/concrexit/website/activemembers/admin.py#issue_5eceacbde96d31000100042c


Discussion:

Resolving patch:
diff --git a/website/activemembers/admin.py b/website/activemembers/admin.py
--- a/website/activemembers/admin.py
+++ b/website/activemembers/admin.py
@@ -42,9 +42,8 @@ class MemberGroupMembershipInline(admin.StackedInline):
     autocomplete_fields = ("member",)
 
 
-@admin.register(models.Committee)
-class CommitteeAdmin(TranslatedModelAdmin):
-    """Manage the committees"""
+class MemberGroupAdmin(TranslatedModelAdmin):
+    """Manage the member groups"""
 
     inlines = (MemberGroupMembershipInline,)
     form = MemberGroupForm
@@ -77,39 +76,18 @@ def email(self, instance):
         return None
 
 
-@admin.register(models.Society)
-class SocietyAdmin(TranslatedModelAdmin):
-    """Manage the societies"""
+@admin.register(models.Committee)
+class CommitteeAdmin(MemberGroupAdmin):
+    """Manage the committees"""
 
-    inlines = (MemberGroupMembershipInline,)
-    form = MemberGroupForm
-    list_display = ("name", "since", "until", "active", "email")
-    list_filter = (
-        "until",
-        "active",
-    )
-    search_fields = ("name", "description")
-    filter_horizontal = ("permissions",)
+    pass
 
-    fields = (
-        "name",
-        "description",
-        "photo",
-        "permissions",
-        "since",
-        "until",
-        "contact_mailinglist",
-        "contact_email",
-        "active",
-        "display_members",
-    )
 
-    def email(self, instance):
-        if instance.contact_email:
-            return instance.contact_email
-        elif instance.contact_mailinglist:
-            return instance.contact_mailinglist.name + "@thalia.nu"
-        return None
+@admin.register(models.Society)
+class SocietyAdmin(MemberGroupAdmin):
+    """Manage the societies"""
+
+    pass
 
 
 @admin.register(models.Board)


Test patch:
Repository: svthalia/concrexit

Issue:
Deleting of EventInformationFields does not work
Steps to reproduce:

1. Create a new event with fields
2. Try to delete a field


Sentry Issue: [CONCREXIT-3K](https://sentry.io/organizations/thalia/issues/1865653504/?referrer=github_integration)

```
KeyError: 'order'
(10 additional frame(s) were not displayed)
...
  File "django/contrib/admin/options.py", line 1522, in changeform_view
    return self._changeform_view(request, object_id, form_url, extra_context)
  File "django/contrib/admin/options.py", line 1566, in _changeform_view
    self.save_related(request, form, formsets, not add)
  File "django/contrib/admin/options.py", line 1109, in save_related
    self.save_formset(request, form, formset, change=change)
  File "events/admin.py", line 221, in save_formset
    for f in sorted(
  File "events/admin.py", line 223, in <lambda>
    key=lambda x: (x.cleaned_data["order"], x.instance.pk),
```


Discussion:

Resolving patch:
diff --git a/website/events/admin.py b/website/events/admin.py
--- a/website/events/admin.py
+++ b/website/events/admin.py
@@ -214,6 +214,7 @@ def save_formset(self, request, form, formset, change):
             x
             for x in formset.forms
             if isinstance(x, forms.RegistrationInformationFieldForm)
+            and "DELETE" not in x.changed_data
         )
         form.instance.set_registrationinformationfield_order(
             [


Test patch:
Repository: svthalia/concrexit

Issue:
Events presence registration in app creates payment
### Describe the bug

Events presence registration in app creates payment

### How to reproduce
Steps to reproduce the behaviour:
1. Create an event with registrations
2. Register
3. Mark the registration as present _in the app_
You can simulate this by going to the registration using the API on `/v1/api/registrations/` and patching the body:
```
{
    "payment": "no_payment",
    "present": true
}
```
4. Note that a payment with the status 'no payment' is created for this registration

### Expected behaviour

No payment should be created




Discussion:
Looks like it is an issue [here](https://github.com/svthalia/concrexit/commit/732015365471404dbceb20d2bcf8995e55dc6016#diff-fea01ddf09080902cc7967c2de85b792R295-R299) introduced by #1173 

Can't test it since I couldn't get the app running
Mmm it is not really possible for #1173 to be the cause since it never been released on production.

Resolving patch:
diff --git a/website/events/services.py b/website/events/services.py
--- a/website/events/services.py
+++ b/website/events/services.py
@@ -293,11 +293,9 @@ def update_registration_by_organiser(registration, member, data):
         raise RegistrationError(_("You are not allowed to update this registration."))
 
     if "payment" in data:
-        if (
-            data["payment"]["type"] == PaymentTypeField.NO_PAYMENT
-            and registration.payment is not None
-        ):
-            delete_payment(registration)
+        if data["payment"]["type"] == PaymentTypeField.NO_PAYMENT:
+            if registration.payment is not None:
+                delete_payment(registration)
         else:
             registration.payment = create_payment(
                 payable=registration,


Test patch:
Repository: svthalia/concrexit

Issue:
Send email with Thalia Pay payments that will be withdrawn on batch processed
### Describe the solution you'd like
When a payment batch is processed, all users that are in that batch should receive an email notifying them that we will withdraw some amount from their bank account.

### Motivation
It is required for the SEPA direct debit mandate


Discussion:

Resolving patch:
diff --git a/website/payments/admin_views.py b/website/payments/admin_views.py
--- a/website/payments/admin_views.py
+++ b/website/payments/admin_views.py
@@ -94,6 +94,9 @@ def post(self, request, *args, **kwargs):
                 bank_account.save()
 
             batch.save()
+
+            services.send_tpay_batch_processing_emails(batch)
+
             messages.success(
                 request,
                 _("Successfully processed {}.").format(model_ngettext(batch, 1)),
diff --git a/website/payments/services.py b/website/payments/services.py
--- a/website/payments/services.py
+++ b/website/payments/services.py
@@ -3,11 +3,13 @@
 from typing import Union
 
 from django.conf import settings
-from django.db.models import QuerySet, Q
-from django.utils import timezone
+from django.db.models import QuerySet, Q, Sum
+from django.urls import reverse
+from django.utils import timezone, translation
 from django.utils.translation import gettext_lazy as _
 
 from members.models import Member
+from registrations.emails import _send_email
 from .exceptions import PaymentError
 from .models import Payment, BankAccount, Payable
 
@@ -91,3 +93,32 @@ def revoke_old_mandates() -> int:
     return BankAccount.objects.filter(
         last_used__lte=(timezone.now() - timezone.timedelta(days=36 * 30))
     ).update(valid_until=timezone.now().date())
+
+
+def send_tpay_batch_processing_emails(batch):
+    """Sends withdrawal notice emails to all members in a batch"""
+    member_payments = batch.payments_set.values("paid_by").annotate(total=Sum("amount"))
+    for member_row in member_payments:
+        member = Member.objects.get(pk=member_row["paid_by"])
+        total_amount = member_row["total"]
+
+        with translation.override(member.profile.language):
+            _send_email(
+                member.email,
+                _("Thalia Pay withdrawal notice"),
+                "payments/email/tpay_withdrawal_notice_mail.txt",
+                {
+                    "name": member.get_full_name(),
+                    "batch": batch,
+                    "bank_account": member.bank_accounts.filter(
+                        mandate_no__isnull=False
+                    ).last(),
+                    "creditor_id": settings.SEPA_CREDITOR_ID,
+                    "payments": batch.payments_set.filter(paid_by=member),
+                    "total_amount": total_amount,
+                    "payments_url": (
+                        settings.BASE_URL + reverse("payments:payment-list",)
+                    ),
+                },
+            )
+    return len(member_payments)


Test patch: