Skip to content

Commit a3da5bb

Browse files
committed
Sets the State(type=draft) to Replaced when a document is replaced using views_draft.replaces.
Sets the state back to Active or Expired when a document is no longer replaced by another document. Adds tests for the above functionality. Provides a patch to repair the state of documents pointed to by RelatedDocument(relationship__slug='replaces') objects created by views_draft.replaces before this fix. Fixes bug 1234 Commit ready for merge - Legacy-Id: 7076
1 parent 77ab20d commit a3da5bb

3 files changed

Lines changed: 132 additions & 4 deletions

File tree

ietf/doc/tests_draft.py

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,3 +1089,102 @@ def test_set_state(self):
10891089
self.assertTrue("wgchairman@ietf.org" in unicode(outbox[-1]))
10901090
self.assertTrue("wgdelegate@ietf.org" in unicode(outbox[-1]))
10911091

1092+
class ChangeReplacesTests(TestCase):
1093+
def setUp(self):
1094+
1095+
make_test_data()
1096+
1097+
mars_wg = Group.objects.get(acronym='mars')
1098+
1099+
self.basea = Document.objects.create(
1100+
name="draft-test-base-a",
1101+
time=datetime.datetime.now(),
1102+
type_id="draft",
1103+
title="Base A",
1104+
stream_id="ietf",
1105+
expires=datetime.datetime.now() + datetime.timedelta(days=settings.INTERNET_DRAFT_DAYS_TO_EXPIRE),
1106+
group=mars_wg,
1107+
)
1108+
1109+
self.baseb = Document.objects.create(
1110+
name="draft-test-base-b",
1111+
time=datetime.datetime.now()-datetime.timedelta(days=365),
1112+
type_id="draft",
1113+
title="Base B",
1114+
stream_id="ietf",
1115+
expires=datetime.datetime.now() - datetime.timedelta(days = 365 - settings.INTERNET_DRAFT_DAYS_TO_EXPIRE),
1116+
group=mars_wg,
1117+
)
1118+
1119+
self.replacea = Document.objects.create(
1120+
name="draft-test-replace-a",
1121+
time=datetime.datetime.now(),
1122+
type_id="draft",
1123+
title="Replace Base A",
1124+
stream_id="ietf",
1125+
expires=datetime.datetime.now() + datetime.timedelta(days = settings.INTERNET_DRAFT_DAYS_TO_EXPIRE),
1126+
group=mars_wg,
1127+
)
1128+
1129+
self.replaceboth = Document.objects.create(
1130+
name="draft-test-replace-both",
1131+
time=datetime.datetime.now(),
1132+
type_id="draft",
1133+
title="Replace Base A and Base B",
1134+
stream_id="ietf",
1135+
expires=datetime.datetime.now() + datetime.timedelta(days = settings.INTERNET_DRAFT_DAYS_TO_EXPIRE),
1136+
group=mars_wg,
1137+
)
1138+
1139+
self.basea.set_state(State.objects.get(used=True, type="draft", slug="active"))
1140+
self.baseb.set_state(State.objects.get(used=True, type="draft", slug="expired"))
1141+
self.replacea.set_state(State.objects.get(used=True, type="draft", slug="active"))
1142+
self.replaceboth.set_state(State.objects.get(used=True, type="draft", slug="active"))
1143+
1144+
DocAlias.objects.create(document=self.basea,name=self.basea.name)
1145+
DocAlias.objects.create(document=self.baseb,name=self.baseb.name)
1146+
DocAlias.objects.create(document=self.replacea,name=self.replacea.name)
1147+
DocAlias.objects.create(document=self.replaceboth,name=self.replaceboth.name)
1148+
1149+
def test_change_replaces(self):
1150+
1151+
url = urlreverse('doc_change_replaces', kwargs=dict(name=self.replacea.name))
1152+
login_testing_unauthorized(self, "secretary", url)
1153+
1154+
# normal get
1155+
r = self.client.get(url)
1156+
self.assertEquals(r.status_code, 200)
1157+
q = PyQuery(r.content)
1158+
self.assertEquals(len(q('form[class=change-replaces]')), 1)
1159+
1160+
# Post that says replacea replaces base a
1161+
self.assertEquals(self.basea.get_state().slug,'active')
1162+
repljson='{"%d":"%s"}'%(DocAlias.objects.get(name=self.basea.name).id,self.basea.name)
1163+
r = self.client.post(url, dict(replaces=repljson))
1164+
self.assertEquals(r.status_code, 302)
1165+
self.assertEqual(RelatedDocument.objects.filter(relationship__slug='replaces',source=self.replacea).count(),1)
1166+
self.assertEquals(Document.objects.get(name='draft-test-base-a').get_state().slug,'repl')
1167+
1168+
# Post that says replaceboth replaces both base a and base b
1169+
url = urlreverse('doc_change_replaces', kwargs=dict(name=self.replaceboth.name))
1170+
self.assertEquals(self.baseb.get_state().slug,'expired')
1171+
repljson='{"%d":"%s","%d":"%s"}'%(DocAlias.objects.get(name=self.basea.name).id,self.basea.name,
1172+
DocAlias.objects.get(name=self.baseb.name).id,self.baseb.name)
1173+
r = self.client.post(url, dict(replaces=repljson))
1174+
self.assertEquals(r.status_code, 302)
1175+
self.assertEquals(Document.objects.get(name='draft-test-base-a').get_state().slug,'repl')
1176+
self.assertEquals(Document.objects.get(name='draft-test-base-b').get_state().slug,'repl')
1177+
1178+
# Post that undoes replaceboth
1179+
repljson='{}'
1180+
r = self.client.post(url, dict(replaces=repljson))
1181+
self.assertEquals(r.status_code, 302)
1182+
self.assertEquals(Document.objects.get(name='draft-test-base-a').get_state().slug,'repl') # Because A is still also replaced by replacea
1183+
self.assertEquals(Document.objects.get(name='draft-test-base-b').get_state().slug,'expired')
1184+
1185+
# Post that undoes replacea
1186+
url = urlreverse('doc_change_replaces', kwargs=dict(name=self.replacea.name))
1187+
r = self.client.post(url, dict(replaces=repljson))
1188+
self.assertEquals(r.status_code, 302)
1189+
self.assertEquals(Document.objects.get(name='draft-test-base-a').get_state().slug,'active')
1190+

ietf/doc/views_draft.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -357,13 +357,14 @@ def replaces(request, name):
357357
for d in old_replaces:
358358
if d not in new_replaces:
359359
emails = collect_email_addresses(emails, d.document)
360-
RelatedDocument.objects.filter(source=doc, target=d,
361-
relationship=relationship).delete()
360+
RelatedDocument.objects.filter(source=doc, target=d, relationship=relationship).delete()
361+
if not RelatedDocument.objects.filter(target=d, relationship=relationship):
362+
d.document.set_state(State.objects.get(type='draft',slug='active' if d.document.expires>datetime.datetime.now() else 'expired'))
362363
for d in new_replaces:
363364
if d not in old_replaces:
364365
emails = collect_email_addresses(emails, d.document)
365-
RelatedDocument.objects.create(source=doc, target=d,
366-
relationship=relationship)
366+
RelatedDocument.objects.create(source=doc, target=d, relationship=relationship)
367+
d.document.set_state(State.objects.get(type='draft',slug='repl'))
367368
e = DocEvent(doc=doc,by=login,type='changed_document')
368369
new_replaces_names = ", ".join([d.name for d in new_replaces])
369370
if not new_replaces_names:
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/usr/bin/env python
2+
from ietf import settings
3+
from django.core import management
4+
management.setup_environ(settings)
5+
6+
from ietf.doc.models import RelatedDocument,State,DocEvent
7+
from ietf.person.models import Person
8+
9+
10+
relevant_relations = RelatedDocument.objects.filter(relationship__slug='replaces',
11+
target__document__type__slug='draft',
12+
target__document__states__type='draft',
13+
target__document__states__slug__in=['active','expired'])
14+
15+
affected_docs = set([x.target.document for x in relevant_relations])
16+
17+
replaced_state = State.objects.get(type='draft',slug='repl')
18+
19+
system_user = Person.objects.get(name="(System)")
20+
21+
for d in affected_docs:
22+
d.set_state(replaced_state)
23+
DocEvent.objects.create(type="added_comment",
24+
doc=d,
25+
by=system_user,
26+
desc='Draft state administratively corrected to Replaced',
27+
)
28+

0 commit comments

Comments
 (0)