Skip to content

Commit bb7e504

Browse files
committed
12/13 merged into 6.113.1.dev0 with migration ordering failure
- Legacy-Id: 17149
1 parent cbe8da6 commit bb7e504

52 files changed

Lines changed: 15566 additions & 14356 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

ietf/doc/admin.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
StateDocEvent, ConsensusDocEvent, BallotType, BallotDocEvent, WriteupDocEvent, LastCallDocEvent,
1313
TelechatDocEvent, BallotPositionDocEvent, ReviewRequestDocEvent, InitialReviewDocEvent,
1414
AddedMessageEvent, SubmissionDocEvent, DeletedEvent, EditedAuthorsDocEvent, DocumentURL,
15-
ReviewAssignmentDocEvent, IanaExpertDocEvent )
15+
ReviewAssignmentDocEvent, IanaExpertDocEvent, IRSGBallotDocEvent )
1616

1717

1818
class StateTypeAdmin(admin.ModelAdmin):
@@ -164,8 +164,12 @@ class DeletedEventAdmin(admin.ModelAdmin):
164164
admin.site.register(DeletedEvent, DeletedEventAdmin)
165165

166166
class BallotPositionDocEventAdmin(DocEventAdmin):
167-
raw_id_fields = ["doc", "by", "ad", "ballot"]
167+
raw_id_fields = ["doc", "by", "pos_by", "ballot"]
168168
admin.site.register(BallotPositionDocEvent, BallotPositionDocEventAdmin)
169+
170+
class IRSGBallotDocEventAdmin(DocEventAdmin):
171+
raw_id_fields = ["doc", "by"]
172+
admin.site.register(IRSGBallotDocEvent, IRSGBallotDocEventAdmin)
169173

170174
class DocumentUrlAdmin(admin.ModelAdmin):
171175
list_display = ['id', 'doc', 'tag', 'url', 'desc', ]

ietf/doc/factories.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
from django.conf import settings
1616

17-
from ietf.doc.models import Document, DocEvent, NewRevisionDocEvent, DocAlias, State, DocumentAuthor, StateDocEvent, BallotPositionDocEvent, BallotDocEvent, BallotType
17+
from ietf.doc.models import Document, DocEvent, NewRevisionDocEvent, DocAlias, State, DocumentAuthor, StateDocEvent, BallotPositionDocEvent, BallotDocEvent, BallotType, IRSGBallotDocEvent
1818
from ietf.group.models import Group
1919

2020
def draft_name_generator(type_id,group,n):
@@ -192,6 +192,26 @@ def states(obj, create, extracted, **kwargs):
192192
obj.set_state(State.objects.get(type_id='draft-iesg',slug='idexists'))
193193

194194

195+
class RgRfcFactory(RgDraftFactory):
196+
197+
alias2 = factory.RelatedFactory('ietf.doc.factories.DocAliasFactory','document',name=factory.Sequence(lambda n: 'rfc%04d'%(n+1000)))
198+
199+
std_level_id = 'inf'
200+
201+
@factory.post_generation
202+
def states(obj, create, extracted, **kwargs):
203+
if not create:
204+
return
205+
if extracted:
206+
for (state_type_id,state_slug) in extracted:
207+
obj.set_state(State.objects.get(type_id=state_type_id,slug=state_slug))
208+
if not obj.get_state('draft-stream-irtf'):
209+
obj.set_state(State.objects.get(type_id='draft-stream-irtf', slug='pub'))
210+
else:
211+
obj.set_state(State.objects.get(type_id='draft',slug='rfc'))
212+
obj.set_state(State.objects.get(type_id='draft-stream-irtf', slug='pub'))
213+
214+
195215
class CharterFactory(BaseDocumentFactory):
196216

197217
type_id = 'charter'
@@ -296,9 +316,10 @@ def state(obj, create, extracted, **kwargs):
296316
class BallotTypeFactory(factory.DjangoModelFactory):
297317
class Meta:
298318
model = BallotType
319+
django_get_or_create = ('slug','doc_type_id')
299320

300-
doc_type_id = 'draft'
301321
slug = 'approve'
322+
doc_type_id = 'draft'
302323

303324

304325
class BallotDocEventFactory(DocEventFactory):
@@ -308,6 +329,13 @@ class Meta:
308329
ballot_type = factory.SubFactory(BallotTypeFactory)
309330
type = 'created_ballot'
310331

332+
class IRSGBallotDocEventFactory(BallotDocEventFactory):
333+
class Meta:
334+
model = IRSGBallotDocEvent
335+
336+
duedate = datetime.datetime.now() + datetime.timedelta(days=14)
337+
ballot_type = factory.SubFactory(BallotTypeFactory, slug='irsg-approve')
338+
311339
class BallotPositionDocEventFactory(DocEventFactory):
312340
class Meta:
313341
model = BallotPositionDocEvent
@@ -319,6 +347,6 @@ class Meta:
319347
# separately and passing the same doc into thier factories.
320348
ballot = factory.SubFactory(BallotDocEventFactory)
321349

322-
ad = factory.SubFactory('ietf.person.factories.PersonFactory')
350+
pos_by = factory.SubFactory('ietf.person.factories.PersonFactory')
323351
pos_id = 'discuss'
324352

ietf/doc/mails.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ def generate_issue_ballot_mail(request, doc, ballot):
382382
last_call_has_expired=last_call_has_expired,
383383
needed_ballot_positions=
384384
needed_ballot_positions(doc,
385-
list(doc.active_ballot().active_ad_positions().values())
385+
list(doc.active_ballot().active_balloteer_positions().values())
386386
),
387387
)
388388
)
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Copyright The IETF Trust 2019, All Rights Reserved
2+
# -*- coding: utf-8 -*-
3+
# Generated by Django 1.11.22 on 2019-08-03 10:09
4+
from __future__ import unicode_literals
5+
6+
from django.db import migrations
7+
8+
# forward, reverse initially copied from migration 0004
9+
def forward(apps, schema_editor):
10+
State = apps.get_model('doc','State')
11+
State.objects.create(type_id='draft-stream-irtf',
12+
slug='irsg_review',
13+
name='IRSG Review',
14+
desc='IRSG Review',
15+
used=True,
16+
)
17+
BallotPositionName = apps.get_model('name','BallotPositionName')
18+
# desc, used, order, and blocking all have suitable defaults
19+
BallotPositionName.objects.create(slug="moretime",
20+
name="Need More Time",
21+
)
22+
BallotPositionName.objects.create(slug="notready",
23+
name="Not Ready",
24+
)
25+
26+
# Create a new ballot type for IRSG ballot
27+
# include positions for the ballot type
28+
BallotType = apps.get_model('doc','BallotType')
29+
bt = BallotType.objects.create(doc_type_id="draft",
30+
slug="irsg-approve",
31+
name="IRSG Approve",
32+
question="Is this draft ready for publication in the IRTF stream?",
33+
)
34+
bt.positions.set(['yes','noobj','recuse','notready','moretime'])
35+
36+
def reverse(apps, schema_editor):
37+
State = apps.get_model('doc','State')
38+
State.objects.filter(type_id__in=('draft-stream-irtf',), slug='irsg_review').delete()
39+
40+
Position = apps.get_model('name','BallotPositionName')
41+
for pos in ("moretime", "notready"):
42+
Position.objects.filter(slug=pos).delete()
43+
44+
IRSGBallot = apps.get_model('doc','BallotType')
45+
IRSGBallot.objects.filter(slug="irsg-approve").delete()
46+
47+
class Migration(migrations.Migration):
48+
49+
dependencies = [
50+
('doc', '0026_add_draft_rfceditor_state'),
51+
('name', '0007_fix_m2m_slug_id_length'),
52+
]
53+
54+
operations = [
55+
migrations.RunPython(forward,reverse),
56+
migrations.RenameField(
57+
model_name='ballotpositiondocevent',
58+
old_name='ad',
59+
new_name='pos_by',
60+
),
61+
62+
]
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Copyright The IETF Trust 2019, All Rights Reserved
2+
# -*- coding: utf-8 -*-
3+
# Generated by Django 1.11.25 on 2019-10-10 10:37
4+
from __future__ import unicode_literals
5+
6+
from django.db import migrations, models
7+
import django.db.models.deletion
8+
9+
10+
class Migration(migrations.Migration):
11+
12+
dependencies = [
13+
('doc', '0027_add_irsg_doc_positions'),
14+
]
15+
16+
operations = [
17+
migrations.CreateModel(
18+
name='IRSGBallotDocEvent',
19+
fields=[
20+
('ballotdocevent_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='doc.BallotDocEvent')),
21+
('duedate', models.DateTimeField(blank=True, null=True)),
22+
],
23+
bases=('doc.ballotdocevent',),
24+
),
25+
]

ietf/doc/models.py

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
DocRelationshipName, DocReminderTypeName, BallotPositionName, ReviewRequestStateName, ReviewAssignmentStateName, FormalLanguageName,
2828
DocUrlTagName)
2929
from ietf.person.models import Email, Person
30-
from ietf.person.utils import get_active_ads
30+
from ietf.person.utils import get_active_balloteers
3131
from ietf.utils import log
3232
from ietf.utils.admin import admin_link
3333
from ietf.utils.decorators import memoize
@@ -656,7 +656,7 @@ def filename_with_rev(self):
656656

657657
def latest_event(self, *args, **filter_args):
658658
"""Get latest event of optional Python type and with filter
659-
arguments, e.g. d.latest_event(type="xyz") returns an DocEvent
659+
arguments, e.g. d.latest_event(type="xyz") returns a DocEvent
660660
while d.latest_event(WriteupDocEvent, type="xyz") returns a
661661
WriteupDocEvent event."""
662662
model = args[0] if args else DocEvent
@@ -1082,36 +1082,36 @@ class Meta:
10821082
class BallotDocEvent(DocEvent):
10831083
ballot_type = ForeignKey(BallotType)
10841084

1085-
def active_ad_positions(self):
1086-
"""Return dict mapping each active AD to a current ballot position (or None if they haven't voted)."""
1085+
def active_balloteer_positions(self):
1086+
"""Return dict mapping each active AD or IRSG member to a current ballot position (or None if they haven't voted)."""
10871087
res = {}
10881088

1089-
active_ads = get_active_ads()
1090-
positions = BallotPositionDocEvent.objects.filter(type="changed_ballot_position",ad__in=active_ads, ballot=self).select_related('ad', 'pos').order_by("-time", "-id")
1089+
active_balloteers = get_active_balloteers(self.ballot_type)
1090+
positions = BallotPositionDocEvent.objects.filter(type="changed_ballot_position",pos_by__in=active_balloteers, ballot=self).select_related('pos_by', 'pos').order_by("-time", "-id")
10911091

10921092
for pos in positions:
1093-
if pos.ad not in res:
1094-
res[pos.ad] = pos
1093+
if pos.pos_by not in res:
1094+
res[pos.pos_by] = pos
10951095

1096-
for ad in active_ads:
1097-
if ad not in res:
1098-
res[ad] = None
1096+
for balloteer in active_balloteers:
1097+
if balloteer not in res:
1098+
res[balloteer] = None
10991099
return res
11001100

11011101
def all_positions(self):
11021102
"""Return array holding the current and past positions per AD"""
11031103

11041104
positions = []
11051105
seen = {}
1106-
active_ads = get_active_ads()
1107-
for e in BallotPositionDocEvent.objects.filter(type="changed_ballot_position", ballot=self).select_related('ad', 'pos').order_by("-time", '-id'):
1108-
if e.ad not in seen:
1109-
e.old_ad = e.ad not in active_ads
1106+
active_balloteers = get_active_balloteers(self.ballot_type)
1107+
for e in BallotPositionDocEvent.objects.filter(type="changed_ballot_position", ballot=self).select_related('pos_by', 'pos').order_by("-time", '-id'):
1108+
if e.pos_by not in seen:
1109+
e.old_pos_by = e.pos_by not in active_balloteers
11101110
e.old_positions = []
11111111
positions.append(e)
1112-
seen[e.ad] = e
1112+
seen[e.pos_by] = e
11131113
else:
1114-
latest = seen[e.ad]
1114+
latest = seen[e.pos_by]
11151115
if latest.old_positions:
11161116
prev = latest.old_positions[-1]
11171117
else:
@@ -1126,25 +1126,27 @@ def all_positions(self):
11261126
while p.old_positions and p.old_positions[-1].slug == "norecord":
11271127
p.old_positions.pop()
11281128

1129-
# add any missing ADs through fake No Record events
1129+
# add any missing ADs/IRSGers through fake No Record events
11301130
if self.doc.active_ballot() == self:
11311131
norecord = BallotPositionName.objects.get(slug="norecord")
1132-
for ad in active_ads:
1133-
if ad not in seen:
1134-
e = BallotPositionDocEvent(type="changed_ballot_position", doc=self.doc, rev=self.doc.rev, ad=ad)
1135-
e.by = ad
1132+
for balloteer in active_balloteers:
1133+
if balloteer not in seen:
1134+
e = BallotPositionDocEvent(type="changed_ballot_position", doc=self.doc, rev=self.doc.rev, pos_by=balloteer)
1135+
e.by = balloteer
11361136
e.pos = norecord
1137-
e.old_ad = False
1137+
e.old_pos_by = False
11381138
e.old_positions = []
11391139
positions.append(e)
11401140

1141-
positions.sort(key=lambda p: (p.old_ad, p.ad.last_name()))
1141+
positions.sort(key=lambda p: (p.old_pos_by, p.pos_by.last_name()))
11421142
return positions
11431143

1144+
class IRSGBallotDocEvent(BallotDocEvent):
1145+
duedate = models.DateTimeField(blank=True, null=True)
11441146

11451147
class BallotPositionDocEvent(DocEvent):
11461148
ballot = ForeignKey(BallotDocEvent, null=True, default=None) # default=None is a temporary migration period fix, should be removed when charter branch is live
1147-
ad = ForeignKey(Person)
1149+
pos_by = ForeignKey(Person)
11481150
pos = ForeignKey(BallotPositionName, verbose_name="position", default="norecord")
11491151
discuss = models.TextField(help_text="Discuss text if position is discuss", blank=True)
11501152
discuss_time = models.DateTimeField(help_text="Time discuss text was written", blank=True, null=True)

ietf/doc/resources.py

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
InitialReviewDocEvent, DocHistoryAuthor, BallotDocEvent, RelatedDocument,
1818
RelatedDocHistory, BallotPositionDocEvent, AddedMessageEvent, SubmissionDocEvent,
1919
ReviewRequestDocEvent, ReviewAssignmentDocEvent, EditedAuthorsDocEvent, DocumentURL,
20-
IanaExpertDocEvent )
20+
IanaExpertDocEvent, IRSGBallotDocEvent )
2121

2222
from ietf.name.resources import BallotPositionNameResource, DocTypeNameResource
2323
class BallotTypeResource(ModelResource):
@@ -531,7 +531,7 @@ class BallotPositionDocEventResource(ModelResource):
531531
doc = ToOneField(DocumentResource, 'doc')
532532
docevent_ptr = ToOneField(DocEventResource, 'docevent_ptr')
533533
ballot = ToOneField(BallotDocEventResource, 'ballot', null=True)
534-
ad = ToOneField(PersonResource, 'ad')
534+
pos_by = ToOneField(PersonResource, 'pos_by')
535535
pos = ToOneField(BallotPositionNameResource, 'pos')
536536
class Meta:
537537
cache = SimpleCache()
@@ -553,7 +553,7 @@ class Meta:
553553
"doc": ALL_WITH_RELATIONS,
554554
"docevent_ptr": ALL_WITH_RELATIONS,
555555
"ballot": ALL_WITH_RELATIONS,
556-
"ad": ALL_WITH_RELATIONS,
556+
"pos_by": ALL_WITH_RELATIONS,
557557
"pos": ALL_WITH_RELATIONS,
558558
}
559559
api.doc.register(BallotPositionDocEventResource())
@@ -738,3 +738,32 @@ class Meta:
738738
"docevent_ptr": ALL_WITH_RELATIONS,
739739
}
740740
api.doc.register(IanaExpertDocEventResource())
741+
742+
743+
from ietf.person.resources import PersonResource
744+
class IRSGBallotDocEventResource(ModelResource):
745+
by = ToOneField(PersonResource, 'by')
746+
doc = ToOneField(DocumentResource, 'doc')
747+
docevent_ptr = ToOneField(DocEventResource, 'docevent_ptr')
748+
ballot_type = ToOneField(BallotTypeResource, 'ballot_type')
749+
ballotdocevent_ptr = ToOneField(BallotDocEventResource, 'ballotdocevent_ptr')
750+
class Meta:
751+
queryset = IRSGBallotDocEvent.objects.all()
752+
serializer = api.Serializer()
753+
cache = SimpleCache()
754+
#resource_name = 'irsgballotdocevent'
755+
ordering = ['ballotdocevent_ptr', ]
756+
filtering = {
757+
"id": ALL,
758+
"time": ALL,
759+
"type": ALL,
760+
"rev": ALL,
761+
"desc": ALL,
762+
"duedate": ALL,
763+
"by": ALL_WITH_RELATIONS,
764+
"doc": ALL_WITH_RELATIONS,
765+
"docevent_ptr": ALL_WITH_RELATIONS,
766+
"ballot_type": ALL_WITH_RELATIONS,
767+
"ballotdocevent_ptr": ALL_WITH_RELATIONS,
768+
}
769+
api.doc.register(IRSGBallotDocEventResource())

ietf/doc/templatetags/ballot_icon.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright The IETF Trust 2019, All rights reserved.
1+
# Copyright The IETF Trust 2019, All Rights Reserved
22
# Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
33
# All rights reserved. Contact: Pasi Eronen <pasi.eronen@nokia.com>
44
#
@@ -91,16 +91,16 @@ def sort_key(t):
9191
else:
9292
return (1, pos.pos.order)
9393

94-
positions = list(ballot.active_ad_positions().items())
94+
positions = list(ballot.active_balloteer_positions().items())
9595
positions.sort(key=sort_key)
9696

9797
right_click_string = ''
9898
if has_role(user, "Area Director"):
9999
right_click_string = 'oncontextmenu="window.location.href=\'%s\';return false;"' % urlreverse('ietf.doc.views_ballot.edit_position', kwargs=dict(name=doc.name, ballot_id=ballot.pk))
100100

101101
my_blocking = False
102-
for i, (ad, pos) in enumerate(positions):
103-
if user_is_person(user,ad) and pos and pos.pos.blocking:
102+
for i, (pos_by, pos) in enumerate(positions):
103+
if user_is_person(user,pos_by) and pos and pos.pos.blocking:
104104
my_blocking = True
105105
break
106106

@@ -153,7 +153,7 @@ def ballotposition(doc, user):
153153
if not ballot:
154154
return None
155155

156-
changed_pos = doc.latest_event(BallotPositionDocEvent, type="changed_ballot_position", ad__user=user, ballot=ballot)
156+
changed_pos = doc.latest_event(BallotPositionDocEvent, type="changed_ballot_position", pos_by__user=user, ballot=ballot)
157157
if changed_pos:
158158
pos = changed_pos.pos
159159
else:

0 commit comments

Comments
 (0)