Skip to content

Commit 3abaab1

Browse files
committed
Merged [7076] from rjsparks@nostrum.com:
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 - Legacy-Id: 7222 Note: SVN reference [7076] has been migrated to Git commit a3da5bb
2 parents 086c429 + a3da5bb commit 3abaab1

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
@@ -1098,3 +1098,102 @@ def test_set_state(self):
10981098
self.assertTrue("marschairman@ietf.org" in unicode(outbox[-1]))
10991099
self.assertTrue("marsdelegate@ietf.org" in unicode(outbox[-1]))
11001100

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

ietf/doc/views_draft.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -354,13 +354,14 @@ def replaces(request, name):
354354
for d in old_replaces:
355355
if d not in new_replaces:
356356
emails = collect_email_addresses(emails, d.document)
357-
RelatedDocument.objects.filter(source=doc, target=d,
358-
relationship=relationship).delete()
357+
RelatedDocument.objects.filter(source=doc, target=d, relationship=relationship).delete()
358+
if not RelatedDocument.objects.filter(target=d, relationship=relationship):
359+
d.document.set_state(State.objects.get(type='draft',slug='active' if d.document.expires>datetime.datetime.now() else 'expired'))
359360
for d in new_replaces:
360361
if d not in old_replaces:
361362
emails = collect_email_addresses(emails, d.document)
362-
RelatedDocument.objects.create(source=doc, target=d,
363-
relationship=relationship)
363+
RelatedDocument.objects.create(source=doc, target=d, relationship=relationship)
364+
d.document.set_state(State.objects.get(type='draft',slug='repl'))
364365
e = DocEvent(doc=doc,by=login,type='changed_document')
365366
new_replaces_names = ", ".join([d.name for d in new_replaces])
366367
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)