internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: ietf-tools/datatracker

Issue:
Add "totals" to "view feedback" page
### Description

It would be useful to add totals for each column in the "view feedback" page.

### Code of Conduct

- [X] I agree to follow the [IETF's Code of Conduct](https://github.com/ietf-tools/.github/blob/main/CODE_OF_CONDUCT.md)


Discussion:

Resolving patch:
diff --git a/ietf/nomcom/templatetags/nomcom_tags.py b/ietf/nomcom/templatetags/nomcom_tags.py
--- a/ietf/nomcom/templatetags/nomcom_tags.py
+++ b/ietf/nomcom/templatetags/nomcom_tags.py
@@ -1,8 +1,10 @@
-# Copyright The IETF Trust 2013-2019, All Rights Reserved
+# Copyright The IETF Trust 2013-2023, All Rights Reserved
 import os
 import tempfile
 import re
 
+from collections import defaultdict
+
 from django import template
 from django.conf import settings
 from django.template.defaultfilters import linebreaksbr, force_escape
@@ -84,3 +86,11 @@ def decrypt(string, request, year, plain=False):
     if not plain:
         return force_escape(linebreaksbr(out))
     return mark_safe(force_escape(out))
+
+@register.filter
+def feedback_totals(staterank_list):
+    totals = defaultdict(lambda: 0)
+    for fb_dict in staterank_list:
+        for fbtype_name, fbtype_count, _ in fb_dict['feedback']:
+            totals[fbtype_name] += fbtype_count
+    return totals.values()


Test patch:
diff --git a/ietf/nomcom/tests.py b/ietf/nomcom/tests.py
--- a/ietf/nomcom/tests.py
+++ b/ietf/nomcom/tests.py
@@ -1,4 +1,4 @@
-# Copyright The IETF Trust 2012-2022, All Rights Reserved
+# Copyright The IETF Trust 2012-2023, All Rights Reserved
 # -*- coding: utf-8 -*-
 
 
@@ -1423,6 +1423,35 @@ def test_can_view_but_not_edit_templates(self):
         q = PyQuery(response.content)
         self.assertFalse( q('#templateform') )
 
+class FeedbackIndexTests(TestCase):
+
+    def setUp(self):
+        super().setUp()
+        setup_test_public_keys_dir(self)
+        self.nc = NomComFactory.create(**nomcom_kwargs_for_year())
+        self.author = PersonFactory.create().email_set.first().address
+        self.member = self.nc.group.role_set.filter(name='member').first().person
+        self.nominee = self.nc.nominee_set.order_by('pk').first()
+        self.position = self.nc.position_set.first()
+        for type_id in ['comment','nomina','questio']:
+            f = FeedbackFactory.create(author=self.author,nomcom=self.nc,type_id=type_id)
+            f.positions.add(self.position)
+            f.nominees.add(self.nominee)
+
+    def tearDown(self):
+        teardown_test_public_keys_dir(self)
+        super().tearDown()
+
+    def test_feedback_index_totals(self):
+        url = reverse('ietf.nomcom.views.view_feedback',kwargs={'year':self.nc.year()})
+        login_testing_unauthorized(self, self.member.user.username, url)
+        provide_private_key_to_test_client(self)
+        response = self.client.get(url)
+        self.assertEqual(response.status_code,200)
+        q = PyQuery(response.content)
+        r = q('tfoot').eq(0).find('td').contents()
+        self.assertEqual([a.strip() for a in r], ['1', '1', '1'])
+
 class FeedbackLastSeenTests(TestCase):
 
     def setUp(self):
Repository: ietf-tools/datatracker

Issue:
Provide human-friendly status in submission status API response
### Description

The submission status API response provides minimal data, currently something like
```
{"id": "12345", "state": "aut-appr"}
```
The state field in the response is the `slug` of the `SubmissionStateName` and is not particularly human friendly. In this case, `aut-appr` means "Awaiting Approval from Previous Version Authors". 

It would be nice to include the `name` field in addition to the `slug`. 

### Code of Conduct

- [X] I agree to follow the [IETF's Code of Conduct](https://github.com/ietf-tools/.github/blob/main/CODE_OF_CONDUCT.md)


Discussion:

Resolving patch:
diff --git a/ietf/submit/views.py b/ietf/submit/views.py
--- a/ietf/submit/views.py
+++ b/ietf/submit/views.py
@@ -183,6 +183,7 @@ def api_submission_status(request, submission_id):
         {
             'id': str(submission.pk),
             'state': submission.state.slug,
+            'state_desc': submission.state.name,
         }
     )
 


Test patch:
diff --git a/ietf/submit/tests.py b/ietf/submit/tests.py
--- a/ietf/submit/tests.py
+++ b/ietf/submit/tests.py
@@ -2878,7 +2878,7 @@ def test_submission_status(self):
         self.assertEqual(r.status_code, 200)
         self.assertEqual(
             r.json(),
-            {'id': str(s.pk), 'state': 'validating'},
+            {'id': str(s.pk), 'state': 'validating', 'state_desc': s.state.name},
         )
 
         s.state_id = 'uploaded'
@@ -2887,7 +2887,7 @@ def test_submission_status(self):
         self.assertEqual(r.status_code, 200)
         self.assertEqual(
             r.json(),
-            {'id': str(s.pk), 'state': 'uploaded'},
+            {'id': str(s.pk), 'state': 'uploaded', 'state_desc': s.state.name},
         )
 
         # try an invalid one
Repository: ietf-tools/datatracker

Issue:
Server error from api_get_session_materials() when session has no agenda
### Describe the issue

The `api_get_session_materials()` method returns a url for the `Session` by calling `session.agenda().get_href()`. If the `Session` does not yet have an agenda, this causes a server error because `agenda()` returns `None`.

Need to check that the front end calling this method can deal with a null there and add a guard before calling `get_href()`.

### Code of Conduct

- [X] I agree to follow the [IETF's Code of Conduct](https://github.com/ietf-tools/.github/blob/main/CODE_OF_CONDUCT.md)


Discussion:

Resolving patch:
diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py
--- a/ietf/meeting/views.py
+++ b/ietf/meeting/views.py
@@ -1704,9 +1704,11 @@ def api_get_session_materials (request, session_id=None):
         })
     else:
         pass  # no action available if it's past cutoff
-
+    
+    agenda = session.agenda() 
+    agenda_url = agenda.get_href() if agenda is not None else None
     return JsonResponse({
-        "url": session.agenda().get_href(),
+        "url": agenda_url,
         "slides": {
             "decks": list(map(agenda_extract_slide, session.slides())),
             "actions": slides_actions,


Test patch:
diff --git a/ietf/api/tests.py b/ietf/api/tests.py
--- a/ietf/api/tests.py
+++ b/ietf/api/tests.py
@@ -725,6 +725,15 @@ def test_api_appauth(self):
         self.assertEqual(r.status_code, 200)
         jsondata = r.json()
         self.assertEqual(jsondata['success'], True)
+    
+    def test_api_get_session_matherials_no_agenda_meeting_url(self):
+        meeting = MeetingFactory(type_id='ietf')
+        session = SessionFactory(meeting=meeting)
+        url = urlreverse('ietf.meeting.views.api_get_session_materials', kwargs={'session_id': session.pk})
+        r = self.client.get(url)
+        self.assertEqual(r.status_code, 200)
+
+
 
 class DirectAuthApiTests(TestCase):
Repository: ietf-tools/datatracker

Issue:
cc slide proposer on upload email
### Description

When proposing slides for a meeting an email is sent to the chairs, responsible AD, etc.  But the proposer has only the confirmation text at the top of the resulting page to know that slides were successfully proposed.

One simple thing might be to cc the email address(es) associated with the datatracker login that proposed the slides on the email informing leadership of same.

### Code of Conduct

- [X] I agree to follow the [IETF's Code of Conduct](https://github.com/ietf-tools/.github/blob/main/CODE_OF_CONDUCT.md)


Discussion:

Resolving patch:
diff --git a/ietf/mailtrigger/migrations/0002_slidesubmitter.py b/ietf/mailtrigger/migrations/0002_slidesubmitter.py
new file mode 100644
--- /dev/null
+++ b/ietf/mailtrigger/migrations/0002_slidesubmitter.py
@@ -0,0 +1,31 @@
+# Copyright The IETF Trust 2023, All Rights Reserved
+
+from django.db import migrations
+
+def forward(apps, schema_editor):
+    MailTrigger = apps.get_model("mailtrigger", "MailTrigger")
+    Recipient = apps.get_model("mailtrigger", "Recipient")
+    r = Recipient.objects.create(
+        slug="slides_proposer",
+        desc="Person who proposed slides",
+        template="{{ proposer.email }}"
+    )
+    mt = MailTrigger.objects.get(slug="slides_proposed")
+    mt.cc.add(r)
+
+def reverse(apps, schema_editor):
+    MailTrigger = apps.get_model("mailtrigger", "MailTrigger")
+    Recipient = apps.get_model("mailtrigger", "Recipient")
+    mt = MailTrigger.objects.get(slug="slides_proposed")
+    r = Recipient.objects.get(slug="slides_proposer")
+    mt.cc.remove(r)
+    r.delete()
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ("mailtrigger", "0001_initial"),
+    ]
+
+    operations = [
+        migrations.RunPython(forward, reverse)
+    ]
diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py
--- a/ietf/meeting/views.py
+++ b/ietf/meeting/views.py
@@ -2887,7 +2887,7 @@ def propose_session_slides(request, session_id, num):
             submission.filename = filename
             submission.save()
 
-            (to, cc) = gather_address_lists('slides_proposed', group=session.group).as_strings() 
+            (to, cc) = gather_address_lists('slides_proposed', group=session.group, proposer=request.user.person).as_strings()
             msg_txt = render_to_string("meeting/slides_proposed.txt", {
                     "to": to,
                     "cc": cc,


Test patch:
Repository: ietf-tools/datatracker

Issue:
Make it possible to navigate to the IAB group itself via the menus
Right now Group->IAB lets you get to programs and administrative activities, but not the IAB itself.


Discussion:
cc: @ghwood

Resolving patch:
diff --git a/ietf/group/views.py b/ietf/group/views.py
--- a/ietf/group/views.py
+++ b/ietf/group/views.py
@@ -1338,6 +1338,16 @@ def group_menu_data(request):
 #        groups_by_parent[g.parent_id].append({ 'acronym': g.acronym, 'name': escape(g.name), 'url': url })
         groups_by_parent[g.parent_id].append({ 'acronym': g.acronym, 'name': escape(g.name), 'type': escape(g.type.verbose_name or g.type.name), 'url': url })
 
+    iab = Group.objects.get(acronym="iab")
+    groups_by_parent[iab.pk].insert(
+        0,
+        {
+            "acronym": iab.acronym,
+            "name": iab.name,
+            "type": "Top Level Group",
+            "url": urlreverse("ietf.group.views.group_home", kwargs={"acronym": iab.acronym})
+        }
+    )
     return JsonResponse(groups_by_parent)
 
 


Test patch:
Repository: ietf-tools/datatracker

Issue:
/secr/sreq doesn't allow listing rswg as a conflict
From Paul Hoffman:

> I was creating my session request, and did not see RSWG in the drop-downs for conflicts. It might not be there because the form doesn't do the Editorial stream, or it might not be there because the list has not been recently updated.


Discussion:
See also #3372

Resolving patch:
diff --git a/ietf/secr/sreq/forms.py b/ietf/secr/sreq/forms.py
--- a/ietf/secr/sreq/forms.py
+++ b/ietf/secr/sreq/forms.py
@@ -28,7 +28,7 @@
 # Helper Functions
 # -------------------------------------------------
 def allowed_conflicting_groups():
-    return Group.objects.filter(type__in=['wg', 'ag', 'rg', 'rag', 'program'], state__in=['bof', 'proposed', 'active'])
+    return Group.objects.filter(type__in=['wg', 'ag', 'rg', 'rag', 'program', 'edwg'], state__in=['bof', 'proposed', 'active'])
 
 def check_conflict(groups, source_group):
     '''


Test patch:
Repository: ietf-tools/datatracker

Issue:
Add link from IETF WG meeting session pages to WG home page
### Description

From a page such as this: https://datatracker.ietf.org/meeting/117/session/httpapi

There is no link to the WG page https://datatracker.ietf.org/wg/httpapi/about/

Currently you have to click through to the [agenda](https://datatracker.ietf.org/doc/agenda-117-httpapi/) which then has a link to the WG page.

It would be helpful to have a link directly to the WG page from the session details, for example to be able to more quickly find the link to subscribe to the group's email list.

### Code of Conduct

- [X] I agree to follow the [IETF's Code of Conduct](https://github.com/ietf-tools/.github/blob/main/CODE_OF_CONDUCT.md)


Discussion:

Resolving patch:
diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py
--- a/ietf/meeting/views.py
+++ b/ietf/meeting/views.py
@@ -2432,7 +2432,8 @@ def session_details(request, num, acronym):
 
     # we somewhat arbitrarily use the group of the last session we get from
     # get_sessions() above when checking can_manage_session_materials()
-    can_manage = can_manage_session_materials(request.user, session.group, session)
+    group = session.group
+    can_manage = can_manage_session_materials(request.user, group, session)
     can_view_request = can_view_interim_request(meeting, request.user)
 
     scheduled_sessions = [s for s in sessions if s.current_status == 'sched']
@@ -2450,7 +2451,7 @@ def session_details(request, num, acronym):
                     'unscheduled_sessions':unscheduled_sessions , 
                     'pending_suggestions' : pending_suggestions,
                     'meeting' :meeting ,
-                    'acronym' :acronym,
+                    'group': group,
                     'is_materials_manager' : session.group.has_role(request.user, session.group.features.matman_roles),
                     'can_manage_materials' : can_manage,
                     'can_view_request': can_view_request,


Test patch:
Repository: ietf-tools/datatracker

Issue:
documents that are defered should not be listed under ADs Missing ballot positions
### Describe the issue

see https://datatracker.ietf.org/doc/ad/paul.wouters

It shows draft-ietf-ntp-interleaved-modes but that document has IESG state "Defered".

### Code of Conduct

- [X] I agree to follow the [IETF's Code of Conduct](https://github.com/ietf-tools/.github/blob/main/CODE_OF_CONDUCT.md)


Discussion:

Resolving patch:
diff --git a/ietf/doc/views_search.py b/ietf/doc/views_search.py
--- a/ietf/doc/views_search.py
+++ b/ietf/doc/views_search.py
@@ -749,6 +749,7 @@ def docs_for_ad(request, name):
             if (
                 not ballot
                 or doc.get_state_slug("draft") == "repl"
+                or doc.get_state_slug("draft-iesg") == "defer"
                 or (doc.telechat_date() and doc.telechat_date() > timezone.now().date())
             ):
                 continue
@@ -801,7 +802,7 @@ def drafts_in_iesg_process(request):
 
 def recent_drafts(request, days=7):
     slowcache = caches['slowpages']
-    cache_key = f'recentdraftsview{days}' 
+    cache_key = f'recentdraftsview{days}'
     cached_val = slowcache.get(cache_key)
     if not cached_val:
         since = timezone.now()-datetime.timedelta(days=days)


Test patch:
Repository: ietf-tools/datatracker

Issue:
xml parsing heuristics crash if a reference has anchor "STD", "FYI", "RFC", or "BCP"
### Describe the issue

I'm trying to submit a draft.  On my first attempt, I realized that I tagged the wrong commit and missed some important changes from a co-author.  So when I received the email, I cancelled the submission.

I have since tried twice (with the right commit).  Both have gotten to the point where I receive an email and both have failed when I requested that the draft be published.

For my second retry attempt, the failed submission was apparently still in progress, so that failed.  I then cancelled the first retry and tried a third time.  That has also failed.  I will leave things in that state for now.

https://datatracker.ietf.org/submit/status/136389/ (original, cancelled)
https://datatracker.ietf.org/submit/status/136390/ (retry 1, failed, also cancelled)
https://datatracker.ietf.org/submit/status/136403/ (retry 3, failed)


### Code of Conduct

- [X] I agree to follow the [IETF's Code of Conduct](https://github.com/ietf-tools/.github/blob/main/CODE_OF_CONDUCT.md)


Discussion:
I think the cancellation is a red herring - the issue I see is that the draft has a reference like `<reference anchor="STD">`. The code that parses references assumes that an anchor starting with "STD..." will have a decimal number after it (like "STD123") and naively tries to convert the value to an integer. It (mis-)handles RFC, BCP, and FYI anchor prefixes in the same way.

Until we get that fixed, changing the anchor either to look like `STD123` or not to be `STD` should allow the draft to be confirmed.

Resolving patch:
diff --git a/ietf/utils/xmldraft.py b/ietf/utils/xmldraft.py
--- a/ietf/utils/xmldraft.py
+++ b/ietf/utils/xmldraft.py
@@ -88,8 +88,9 @@ def _document_name(self, ref):
         # check the anchor next
         anchor = ref.get("anchor").lower()  # always give back lowercase
         label = anchor.rstrip("0123456789")  # remove trailing digits
-        if label in series:
-            number = int(anchor[len(label) :])
+        maybe_number = anchor[len(label) :]
+        if label in series and maybe_number.isdigit():
+            number = int(maybe_number)
             return f"{label}{number}"
 
         # if we couldn't find a match so far, try the seriesInfo


Test patch:
Repository: ietf-tools/datatracker

Issue:
Migrate DocHistory objects for RFCs
### Describe the issue

`DocHistory` objects that pertain to the RFC rather than the I-D need to be migrated to hang off the new `type_id="rfc"` `Document`. The `name` and `rfc_number` fields should be updated to match.

### Code of Conduct

- [X] I agree to follow the [IETF's Code of Conduct](https://github.com/ietf-tools/.github/blob/main/CODE_OF_CONDUCT.md)


Discussion:
D'oh - the migration so far doesn't populate rfc_number.

Resolving patch:
diff --git a/ietf/doc/migrations/0017_move_dochistory.py b/ietf/doc/migrations/0017_move_dochistory.py
--- a/ietf/doc/migrations/0017_move_dochistory.py
+++ b/ietf/doc/migrations/0017_move_dochistory.py
@@ -8,6 +8,7 @@
 def forward(apps, schema_editor):
     DocHistory = apps.get_model("doc", "DocHistory")
     RelatedDocument = apps.get_model("doc", "RelatedDocument")
+    Document = apps.get_model("doc", "Document")
     DocHistory.objects.filter(type_id="draft", doc__type_id="rfc").update(type_id="rfc")
     DocHistory.objects.filter(
         type_id="draft", doc__type_id="draft", name__startswith="rfc"
@@ -20,9 +21,19 @@ def forward(apps, schema_editor):
     ).update(
         doc_id=F("rfc_id"), type_id="rfc"
     )
+    DocHistory.objects.filter(type_id="rfc").annotate(
+        rfcno=Subquery(
+            Document.objects.filter(pk=OuterRef("doc_id")).values_list(
+                "rfc_number", flat=True
+            )[:1]
+        )
+    ).update(rfc_number=F("rfcno"))
     assert not DocHistory.objects.filter(
         name__startswith="rfc", type_id="draft"
     ).exists()
+    assert not DocHistory.objects.filter(
+        type_id="rfc", rfc_number__isnull=True
+    ).exists()
 
 
 class Migration(migrations.Migration):


Test patch:
Repository: ietf-tools/datatracker

Issue:
The email sent when an IRTF charter is approved needs adjustment.
Currently the email appears to come from the IESG and does not copy irtf-announce. It does copy ietf-announce. Should it continue to do so?

cc: @csperkins, @cindymorgan


Discussion:
This should come from `irtf-chair@irtf.org` and be sent to `irtf-announce@irtf.org`, with a copy to `iab@iag.org`, `irsg@irtf.org`, the RG, and the RG Chairs.
Also, we should check the message body doesn't say "The IESG has approved…"

Resolving patch:
diff --git a/ietf/mailtrigger/migrations/0003_ballot_approved_charter.py b/ietf/mailtrigger/migrations/0003_ballot_approved_charter.py
new file mode 100644
--- /dev/null
+++ b/ietf/mailtrigger/migrations/0003_ballot_approved_charter.py
@@ -0,0 +1,26 @@
+# Copyright The IETF Trust 2023, All Rights Reserved
+
+from django.db import migrations
+
+def forward(apps, schema_editor):
+    MailTrigger = apps.get_model("mailtrigger", "MailTrigger")
+    Recipient = apps.get_model("mailtrigger", "Recipient")
+    mt = MailTrigger.objects.get(pk="ballot_approved_charter")
+    mt.to.remove(mt.to.first())
+    mt.to.add(Recipient.objects.get(slug="group_stream_announce"))
+
+def reverse(apps, schema_editor):
+    MailTrigger = apps.get_model("mailtrigger", "MailTrigger")
+    Recipient = apps.get_model("mailtrigger", "Recipient")
+    mt = MailTrigger.objects.get(pk="ballot_approved_charter")
+    mt.to.remove(mt.to.first())
+    mt.to.add(Recipient.objects.get(slug="ietf_announce"))
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ("mailtrigger", "0002_slidesubmitter"),
+    ]
+
+    operations = [
+        migrations.RunPython(forward, reverse)
+    ]


Test patch:
diff --git a/ietf/doc/tests_charter.py b/ietf/doc/tests_charter.py
--- a/ietf/doc/tests_charter.py
+++ b/ietf/doc/tests_charter.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright The IETF Trust 2011-2020, All Rights Reserved
+# Copyright The IETF Trust 2011-2023, All Rights Reserved
 
 
 import datetime
@@ -817,6 +817,19 @@ def test_approve(self):
         self.assertEqual(group.groupmilestone_set.filter(state="active", desc=m1.desc).count(), 1)
         self.assertEqual(group.groupmilestone_set.filter(state="active", desc=m4.desc).count(), 1)
 
+    def test_approve_irtf(self):
+        charter = CharterFactory(group__type_id='rg')
+        url = urlreverse('ietf.doc.views_charter.approve', kwargs=dict(name=charter.name))
+        login_testing_unauthorized(self, "secretary", url)
+        empty_outbox()
+        r = self.client.post(url, dict())
+        self.assertEqual(r.status_code, 302)
+        self.assertEqual(len(outbox), 2)
+        self.assertTrue("IRTF" in outbox[1]['From'])
+        self.assertTrue("irtf-announce" in outbox[1]['To'])
+        self.assertTrue(charter.group.acronym in outbox[1]['Cc'])
+        self.assertTrue("RG Action" in outbox[1]['Subject'])
+
     def test_charter_with_milestones(self):
         charter = CharterFactory()