diff --git a/ietf/bin/expire-ids b/ietf/bin/expire-ids index 44f913bd1..74f432e1f 100755 --- a/ietf/bin/expire-ids +++ b/ietf/bin/expire-ids @@ -9,7 +9,7 @@ management.setup_environ(settings) syslog.openlog(os.path.basename(__file__), syslog.LOG_PID, syslog.LOG_USER) -from ietf.idrfc.expire import * +from ietf.doc.expire import * if not in_draft_expire_freeze(): for doc in get_expired_drafts(): diff --git a/ietf/bin/expire-last-calls b/ietf/bin/expire-last-calls index d50c216a1..762bae812 100755 --- a/ietf/bin/expire-last-calls +++ b/ietf/bin/expire-last-calls @@ -9,7 +9,7 @@ management.setup_environ(settings) syslog.openlog(os.path.basename(__file__), syslog.LOG_PID, syslog.LOG_USER) -from ietf.idrfc.lastcall import * +from ietf.doc.lastcall import * drafts = get_expired_last_calls() for doc in drafts: diff --git a/ietf/bin/notify-expirations b/ietf/bin/notify-expirations index 71de766f6..484adff73 100755 --- a/ietf/bin/notify-expirations +++ b/ietf/bin/notify-expirations @@ -6,7 +6,7 @@ from ietf import settings from django.core import management management.setup_environ(settings) -from ietf.idrfc.expire import get_soon_to_expire_drafts, send_expire_warning_for_draft +from ietf.doc.expire import get_soon_to_expire_drafts, send_expire_warning_for_draft # notify about documents that expire within the next 2 weeks diff --git a/ietf/idrfc/expire.py b/ietf/doc/expire.py similarity index 100% rename from ietf/idrfc/expire.py rename to ietf/doc/expire.py diff --git a/ietf/idrfc/lastcall.py b/ietf/doc/lastcall.py similarity index 98% rename from ietf/idrfc/lastcall.py rename to ietf/doc/lastcall.py index cb77b04db..a558fd1d6 100644 --- a/ietf/idrfc/lastcall.py +++ b/ietf/doc/lastcall.py @@ -7,7 +7,7 @@ from django.conf import settings from ietf.doc.models import * from ietf.person.models import Person from ietf.doc.utils import log_state_changed -from ietf.idrfc.mails import * +from ietf.doc.mails import * def request_last_call(request, doc): if not doc.latest_event(type="changed_ballot_writeup_text"): diff --git a/ietf/idrfc/mails.py b/ietf/doc/mails.py similarity index 100% rename from ietf/idrfc/mails.py rename to ietf/doc/mails.py diff --git a/ietf/doc/models.py b/ietf/doc/models.py index a9834f5e3..3f26a6f76 100644 --- a/ietf/doc/models.py +++ b/ietf/doc/models.py @@ -340,7 +340,6 @@ class Document(DocumentInfo): iesg_state = self.get_state("draft-iesg") iesg_state_summary = None if iesg_state: - # This knowledge about which tags are reportable IESG substate tags is duplicated in idrfc iesg_substate = self.tags.filter(slug__in=IESG_SUBSTATE_TAGS) # There really shouldn't be more than one tag in iesg_substate, but this will do something sort-of-sensible if there is iesg_state_summary = iesg_state.name diff --git a/ietf/idrfc/templatetags/mail_filters.py b/ietf/doc/templatetags/mail_filters.py similarity index 100% rename from ietf/idrfc/templatetags/mail_filters.py rename to ietf/doc/templatetags/mail_filters.py diff --git a/ietf/idrfc/templatetags/wg_menu.py b/ietf/doc/templatetags/wg_menu.py similarity index 100% rename from ietf/idrfc/templatetags/wg_menu.py rename to ietf/doc/templatetags/wg_menu.py diff --git a/ietf/doc/tests.py b/ietf/doc/tests.py index 43b0e9315..6959d2568 100644 --- a/ietf/doc/tests.py +++ b/ietf/doc/tests.py @@ -17,7 +17,10 @@ from ietf.meeting.models import Meeting, MeetingTypeName from ietf.iesg.models import TelechatDate # extra tests +from ietf.doc.tests_draft import * +from ietf.doc.tests_ballot import * from ietf.doc.tests_conflict_review import * +from ietf.doc.tests_status_change import * class SearchTestCase(django.test.TestCase): diff --git a/ietf/doc/tests_ballot.py b/ietf/doc/tests_ballot.py new file mode 100644 index 000000000..347647a49 --- /dev/null +++ b/ietf/doc/tests_ballot.py @@ -0,0 +1,533 @@ +import unittest +import StringIO +import os, shutil +from datetime import date, timedelta, time + +import django.test +from django.core.urlresolvers import reverse as urlreverse +from django.conf import settings + +from pyquery import PyQuery +import debug + +from ietf.doc.models import * +from ietf.name.models import * +from ietf.group.models import * +from ietf.person.models import * +from ietf.meeting.models import Meeting, MeetingTypeName +from ietf.iesg.models import TelechatDate +from ietf.utils.test_utils import login_testing_unauthorized +from ietf.utils.test_data import make_test_data +from ietf.utils.mail import outbox + +class EditPositionTestCase(django.test.TestCase): + fixtures = ['names'] + + def test_edit_position(self): + draft = make_test_data() + url = urlreverse('ietf.doc.views_ballot.edit_position', kwargs=dict(name=draft.name, + ballot_id=draft.latest_event(BallotDocEvent, type="created_ballot").pk)) + login_testing_unauthorized(self, "ad", url) + + ad = Person.objects.get(name="Aread Irector") + + # normal get + r = self.client.get(url) + self.assertEquals(r.status_code, 200) + q = PyQuery(r.content) + self.assertTrue(len(q('form input[name=position]')) > 0) + self.assertEquals(len(q('form textarea[name=comment]')), 1) + + # vote + events_before = draft.docevent_set.count() + + r = self.client.post(url, dict(position="discuss", + discuss=" This is a discussion test. \n ", + comment=" This is a test. \n ")) + self.assertEquals(r.status_code, 302) + + pos = draft.latest_event(BallotPositionDocEvent, ad=ad) + self.assertEquals(pos.pos.slug, "discuss") + self.assertTrue(" This is a discussion test." in pos.discuss) + self.assertTrue(pos.discuss_time != None) + self.assertTrue(" This is a test." in pos.comment) + self.assertTrue(pos.comment_time != None) + self.assertTrue("New position" in pos.desc) + self.assertEquals(draft.docevent_set.count(), events_before + 3) + + # recast vote + events_before = draft.docevent_set.count() + r = self.client.post(url, dict(position="noobj")) + self.assertEquals(r.status_code, 302) + + pos = draft.latest_event(BallotPositionDocEvent, ad=ad) + self.assertEquals(pos.pos.slug, "noobj") + self.assertEquals(draft.docevent_set.count(), events_before + 1) + self.assertTrue("Position for" in pos.desc) + + # clear vote + events_before = draft.docevent_set.count() + r = self.client.post(url, dict(position="norecord")) + self.assertEquals(r.status_code, 302) + + pos = draft.latest_event(BallotPositionDocEvent, ad=ad) + self.assertEquals(pos.pos.slug, "norecord") + self.assertEquals(draft.docevent_set.count(), events_before + 1) + self.assertTrue("Position for" in pos.desc) + + # change comment + events_before = draft.docevent_set.count() + r = self.client.post(url, dict(position="norecord", comment="New comment.")) + self.assertEquals(r.status_code, 302) + + pos = draft.latest_event(BallotPositionDocEvent, ad=ad) + self.assertEquals(pos.pos.slug, "norecord") + self.assertEquals(draft.docevent_set.count(), events_before + 2) + self.assertTrue("Ballot comment text updated" in pos.desc) + + def test_edit_position_as_secretary(self): + draft = make_test_data() + url = urlreverse('ietf.doc.views_ballot.edit_position', kwargs=dict(name=draft.name, + ballot_id=draft.latest_event(BallotDocEvent, type="created_ballot").pk)) + ad = Person.objects.get(name="Aread Irector") + url += "?ad=%s" % ad.pk + login_testing_unauthorized(self, "secretary", url) + + # normal get + r = self.client.get(url) + self.assertEquals(r.status_code, 200) + q = PyQuery(r.content) + self.assertTrue(len(q('form input[name=position]')) > 0) + + # vote on behalf of AD + events_before = draft.docevent_set.count() + r = self.client.post(url, dict(position="discuss", discuss="Test discuss text")) + self.assertEquals(r.status_code, 302) + + pos = draft.latest_event(BallotPositionDocEvent, ad=ad) + self.assertEquals(pos.pos.slug, "discuss") + self.assertEquals(pos.discuss, "Test discuss text") + self.assertTrue("New position" in pos.desc) + self.assertTrue("by Sec" in pos.desc) + + def test_cannot_edit_position_as_pre_ad(self): + draft = make_test_data() + url = urlreverse('ietf.doc.views_ballot.edit_position', kwargs=dict(name=draft.name, + ballot_id=draft.latest_event(BallotDocEvent, type="created_ballot").pk)) + + # transform to pre-ad + ad_role = Role.objects.filter(name="ad")[0] + ad_role.name_id = "pre-ad" + ad_role.save() + + # we can see + login_testing_unauthorized(self, ad_role.person.user.username, url) + + # but not touch + r = self.client.post(url, dict(position="discuss", discuss="Test discuss text")) + self.assertEquals(r.status_code, 403) + + def test_send_ballot_comment(self): + draft = make_test_data() + draft.notify = "somebody@example.com" + draft.save() + + ad = Person.objects.get(name="Aread Irector") + + ballot = draft.latest_event(BallotDocEvent, type="created_ballot") + + BallotPositionDocEvent.objects.create( + doc=draft, type="changed_ballot_position", + by=ad, ad=ad, ballot=ballot, pos=BallotPositionName.objects.get(slug="discuss"), + discuss="This draft seems to be lacking a clearer title?", + discuss_time=datetime.datetime.now(), + comment="Test!", + comment_time=datetime.datetime.now()) + + url = urlreverse('doc_send_ballot_comment', kwargs=dict(name=draft.name, + ballot_id=ballot.pk)) + login_testing_unauthorized(self, "ad", url) + + # normal get + r = self.client.get(url) + self.assertEquals(r.status_code, 200) + q = PyQuery(r.content) + self.assertTrue(len(q('form input[name="cc"]')) > 0) + + # send + mailbox_before = len(outbox) + + r = self.client.post(url, dict(cc="test@example.com", cc_state_change="1")) + self.assertEquals(r.status_code, 302) + + self.assertEquals(len(outbox), mailbox_before + 1) + m = outbox[-1] + self.assertTrue("COMMENT" in m['Subject']) + self.assertTrue("DISCUSS" in m['Subject']) + self.assertTrue(draft.name in m['Subject']) + self.assertTrue("clearer title" in str(m)) + self.assertTrue("Test!" in str(m)) + + +class DeferBallotTestCase(django.test.TestCase): + fixtures = ['names'] + + def test_defer_ballot(self): + draft = make_test_data() + draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="iesg-eva")) + + url = urlreverse('doc_defer_ballot', kwargs=dict(name=draft.name)) + login_testing_unauthorized(self, "ad", url) + + # normal get + r = self.client.get(url) + self.assertEquals(r.status_code, 200) + + # defer + mailbox_before = len(outbox) + + r = self.client.post(url, dict()) + self.assertEquals(r.status_code, 302) + + draft = Document.objects.get(name=draft.name) + self.assertEquals(draft.get_state_slug("draft-iesg"), "defer") + + self.assertEquals(len(outbox), mailbox_before + 2) + self.assertTrue("State Update" in outbox[-2]['Subject']) + self.assertTrue("Deferred" in outbox[-1]['Subject']) + self.assertTrue(draft.file_tag() in outbox[-1]['Subject']) + + def test_undefer_ballot(self): + draft = make_test_data() + draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="defer")) + + url = urlreverse('doc_undefer_ballot', kwargs=dict(name=draft.name)) + login_testing_unauthorized(self, "ad", url) + + # normal get + r = self.client.get(url) + self.assertEquals(r.status_code, 200) + + # undefer + r = self.client.post(url, dict()) + self.assertEquals(r.status_code, 302) + + draft = Document.objects.get(name=draft.name) + self.assertEquals(draft.get_state_slug("draft-iesg"), "iesg-eva") + +class BallotWriteupsTestCase(django.test.TestCase): + fixtures = ['names'] + + def test_edit_last_call_text(self): + draft = make_test_data() + url = urlreverse('doc_ballot_lastcall', kwargs=dict(name=draft.name)) + login_testing_unauthorized(self, "secretary", url) + + # normal get + r = self.client.get(url) + self.assertEquals(r.status_code, 200) + q = PyQuery(r.content) + self.assertEquals(len(q('textarea[name=last_call_text]')), 1) + self.assertEquals(len(q('input[type=submit][value*="Save Last Call"]')), 1) + # we're secretariat, so we got The Link + self.assertEquals(len(q('a:contains("Make Last Call")')), 1) + + # subject error + r = self.client.post(url, dict( + last_call_text="Subject: test\r\nhello\r\n\r\n", + save_last_call_text="1")) + self.assertEquals(r.status_code, 200) + q = PyQuery(r.content) + self.assertTrue(len(q('ul.errorlist')) > 0) + + # save + r = self.client.post(url, dict( + last_call_text="This is a simple test.", + save_last_call_text="1")) + self.assertEquals(r.status_code, 200) + draft = Document.objects.get(name=draft.name) + self.assertTrue("This is a simple test" in draft.latest_event(WriteupDocEvent, type="changed_last_call_text").text) + + # test regenerate + r = self.client.post(url, dict( + last_call_text="This is a simple test.", + regenerate_last_call_text="1")) + self.assertEquals(r.status_code, 200) + q = PyQuery(r.content) + draft = Document.objects.get(name=draft.name) + self.assertTrue("Subject: Last Call" in draft.latest_event(WriteupDocEvent, type="changed_last_call_text").text) + + + def test_request_last_call(self): + draft = make_test_data() + url = urlreverse('doc_ballot_lastcall', kwargs=dict(name=draft.name)) + login_testing_unauthorized(self, "secretary", url) + + # give us an announcement to send + r = self.client.post(url, dict(regenerate_last_call_text="1")) + self.assertEquals(r.status_code, 200) + + mailbox_before = len(outbox) + + # send + r = self.client.post(url, dict( + last_call_text=draft.latest_event(WriteupDocEvent, type="changed_last_call_text").text, + send_last_call_request="1")) + draft = Document.objects.get(name=draft.name) + self.assertEquals(draft.get_state_slug("draft-iesg"), "lc-req") + self.assertEquals(len(outbox), mailbox_before + 3) + self.assertTrue("Last Call" in outbox[-1]['Subject']) + self.assertTrue(draft.name in outbox[-1]['Subject']) + + def test_edit_ballot_writeup(self): + draft = make_test_data() + url = urlreverse('doc_ballot_writeupnotes', kwargs=dict(name=draft.name)) + login_testing_unauthorized(self, "secretary", url) + + # add a IANA review note + draft.set_state(State.objects.get(used=True, type="draft-iana-review", slug="not-ok")) + DocEvent.objects.create(type="iana_review", + doc=draft, + by=Person.objects.get(user__username="iana"), + desc="IANA does not approve of this document, it does not make sense.", + ) + + # normal get + r = self.client.get(url) + self.assertEquals(r.status_code, 200) + q = PyQuery(r.content) + self.assertEquals(len(q('textarea[name=ballot_writeup]')), 1) + self.assertEquals(len(q('input[type=submit][value*="Save Ballot Writeup"]')), 1) + self.assertTrue("IANA does not" in r.content) + + # save + r = self.client.post(url, dict( + ballot_writeup="This is a simple test.", + save_ballot_writeup="1")) + self.assertEquals(r.status_code, 200) + draft = Document.objects.get(name=draft.name) + self.assertTrue("This is a simple test" in draft.latest_event(WriteupDocEvent, type="changed_ballot_writeup_text").text) + + def test_issue_ballot(self): + draft = make_test_data() + url = urlreverse('doc_ballot_writeupnotes', kwargs=dict(name=draft.name)) + login_testing_unauthorized(self, "ad", url) + + ballot = draft.latest_event(BallotDocEvent, type="created_ballot") + + def create_pos(num, vote, comment="", discuss=""): + ad = Person.objects.get(name="Ad No%s" % num) + e = BallotPositionDocEvent() + e.doc = draft + e.ballot = ballot + e.by = ad + e.ad = ad + e.pos = BallotPositionName.objects.get(slug=vote) + e.type = "changed_ballot_position" + e.comment = comment + if e.comment: + e.comment_time = datetime.datetime.now() + e.discuss = discuss + if e.discuss: + e.discuss_time = datetime.datetime.now() + e.save() + + # active + create_pos(1, "yes", discuss="discuss1 " * 20) + create_pos(2, "noobj", comment="comment2 " * 20) + create_pos(3, "discuss", discuss="discuss3 " * 20, comment="comment3 " * 20) + create_pos(4, "abstain") + create_pos(5, "recuse") + + # inactive + create_pos(9, "yes") + + mailbox_before = len(outbox) + + r = self.client.post(url, dict( + ballot_writeup="This is a test.", + issue_ballot="1")) + self.assertEquals(r.status_code, 200) + draft = Document.objects.get(name=draft.name) + + self.assertTrue(draft.latest_event(type="sent_ballot_announcement")) + self.assertEquals(len(outbox), mailbox_before + 2) + issue_email = outbox[-2] + self.assertTrue("Evaluation:" in issue_email['Subject']) + self.assertTrue("comment1" not in str(issue_email)) + self.assertTrue("comment2" in str(issue_email)) + self.assertTrue("comment3" in str(issue_email)) + self.assertTrue("discuss3" in str(issue_email)) + self.assertTrue("This is a test" in str(issue_email)) + self.assertTrue("The IESG has approved" in str(issue_email)) + + def test_edit_approval_text(self): + draft = make_test_data() + url = urlreverse('doc_ballot_approvaltext', kwargs=dict(name=draft.name)) + login_testing_unauthorized(self, "secretary", url) + + # normal get + r = self.client.get(url) + self.assertEquals(r.status_code, 200) + q = PyQuery(r.content) + self.assertEquals(len(q('textarea[name=approval_text]')), 1) + self.assertEquals(len(q('input[type=submit][value*="Save Approval"]')), 1) + + # save + r = self.client.post(url, dict( + approval_text="This is a simple test.", + save_approval_text="1")) + self.assertEquals(r.status_code, 200) + draft = Document.objects.get(name=draft.name) + self.assertTrue("This is a simple test" in draft.latest_event(WriteupDocEvent, type="changed_ballot_approval_text").text) + + # test regenerate + r = self.client.post(url, dict(regenerate_approval_text="1")) + self.assertEquals(r.status_code, 200) + draft = Document.objects.get(name=draft.name) + self.assertTrue("Subject: Protocol Action" in draft.latest_event(WriteupDocEvent, type="changed_ballot_approval_text").text) + + # test regenerate when it's a disapprove + draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="nopubadw")) + + r = self.client.post(url, dict(regenerate_approval_text="1")) + self.assertEquals(r.status_code, 200) + draft = Document.objects.get(name=draft.name) + self.assertTrue("NOT be published" in draft.latest_event(WriteupDocEvent, type="changed_ballot_approval_text").text) + + # test regenerate when it's a conflict review + draft.group = Group.objects.get(type="individ") + draft.stream_id = "irtf" + draft.save() + draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="iesg-eva")) + + r = self.client.post(url, dict(regenerate_approval_text="1")) + self.assertEquals(r.status_code, 200) + draft = Document.objects.get(name=draft.name) + self.assertTrue("Subject: Results of IETF-conflict review" in draft.latest_event(WriteupDocEvent, type="changed_ballot_approval_text").text) + +class ApproveBallotTestCase(django.test.TestCase): + fixtures = ['names'] + + def test_approve_ballot(self): + draft = make_test_data() + draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="iesg-eva")) # make sure it's approvable + + url = urlreverse('doc_approve_ballot', kwargs=dict(name=draft.name)) + login_testing_unauthorized(self, "secretary", url) + + # normal get + r = self.client.get(url) + self.assertEquals(r.status_code, 200) + q = PyQuery(r.content) + self.assertTrue("send out the announcement" in q('.actions input[type=submit]')[0].get('value').lower()) + self.assertEquals(len(q('.announcement pre:contains("Subject: Protocol Action")')), 1) + + # approve + mailbox_before = len(outbox) + + r = self.client.post(url, dict(skiprfceditorpost="1")) + self.assertEquals(r.status_code, 302) + + draft = Document.objects.get(name=draft.name) + self.assertEquals(draft.get_state_slug("draft-iesg"), "ann") + self.assertEquals(len(outbox), mailbox_before + 4) + self.assertTrue("Protocol Action" in outbox[-2]['Subject']) + # the IANA copy + self.assertTrue("Protocol Action" in outbox[-1]['Subject']) + self.assertTrue(not outbox[-1]['CC']) + self.assertTrue("Protocol Action" in draft.message_set.order_by("-time")[0].subject) + + def test_disapprove_ballot(self): + draft = make_test_data() + draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="nopubadw")) + + url = urlreverse('doc_approve_ballot', kwargs=dict(name=draft.name)) + login_testing_unauthorized(self, "secretary", url) + + # disapprove (the Martians aren't going to be happy) + mailbox_before = len(outbox) + + r = self.client.post(url, dict()) + self.assertEquals(r.status_code, 302) + + draft = Document.objects.get(name=draft.name) + self.assertEquals(draft.get_state_slug("draft-iesg"), "dead") + self.assertEquals(len(outbox), mailbox_before + 3) + self.assertTrue("NOT be published" in str(outbox[-1])) + +class MakeLastCallTestCase(django.test.TestCase): + fixtures = ['names'] + + def test_make_last_call(self): + draft = make_test_data() + draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="lc-req")) + + url = urlreverse('doc_make_last_call', kwargs=dict(name=draft.name)) + login_testing_unauthorized(self, "secretary", url) + + # normal get + r = self.client.get(url) + self.assertEquals(r.status_code, 200) + q = PyQuery(r.content) + self.assertEquals(len(q('input[name=last_call_sent_date]')), 1) + + # make last call + mailbox_before = len(outbox) + + expire_date = q('input[name=last_call_expiration_date]')[0].get("value") + + r = self.client.post(url, + dict(last_call_sent_date=q('input[name=last_call_sent_date]')[0].get("value"), + last_call_expiration_date=expire_date + )) + self.assertEquals(r.status_code, 302) + + draft = Document.objects.get(name=draft.name) + self.assertEquals(draft.get_state_slug("draft-iesg"), "lc") + self.assertEquals(draft.latest_event(LastCallDocEvent, "sent_last_call").expires.strftime("%Y-%m-%d"), expire_date) + self.assertEquals(len(outbox), mailbox_before + 4) + + self.assertTrue("Last Call" in outbox[-4]['Subject']) + # the IANA copy + self.assertTrue("Last Call" in outbox[-3]['Subject']) + self.assertTrue("Last Call" in draft.message_set.order_by("-time")[0].subject) + +class RequestPublicationTestCase(django.test.TestCase): + fixtures = ['names'] + + def test_request_publication(self): + draft = make_test_data() + draft.stream = StreamName.objects.get(slug="iab") + draft.group = Group.objects.get(acronym="iab") + draft.intended_std_level = IntendedStdLevelName.objects.get(slug="inf") + draft.save() + draft.set_state(State.objects.get(used=True, type="draft-stream-iab", slug="approved")) + + url = urlreverse('doc_request_publication', kwargs=dict(name=draft.name)) + login_testing_unauthorized(self, "iabchair", url) + + # normal get + r = self.client.get(url) + self.assertEquals(r.status_code, 200) + q = PyQuery(r.content) + subject = q('input#id_subject')[0].get("value") + self.assertTrue("Document Action" in subject) + body = q('.request-publication #id_body').text() + self.assertTrue("Informational" in body) + self.assertTrue("IAB" in body) + + # approve + mailbox_before = len(outbox) + + r = self.client.post(url, dict(subject=subject, body=body, skiprfceditorpost="1")) + self.assertEquals(r.status_code, 302) + + draft = Document.objects.get(name=draft.name) + self.assertEquals(draft.get_state_slug("draft-stream-iab"), "rfc-edit") + self.assertEquals(len(outbox), mailbox_before + 2) + self.assertTrue("Document Action" in outbox[-2]['Subject']) + self.assertTrue("Document Action" in draft.message_set.order_by("-time")[0].subject) + # the IANA copy + self.assertTrue("Document Action" in outbox[-1]['Subject']) + self.assertTrue(not outbox[-1]['CC']) diff --git a/ietf/idrfc/tests.py b/ietf/doc/tests_draft.py similarity index 60% rename from ietf/idrfc/tests.py rename to ietf/doc/tests_draft.py index 6d8dff36b..37c17c319 100644 --- a/ietf/idrfc/tests.py +++ b/ietf/doc/tests_draft.py @@ -1,35 +1,3 @@ -# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -# All rights reserved. Contact: Pasi Eronen -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# -# * Neither the name of the Nokia Corporation and/or its -# subsidiary(-ies) nor the names of its contributors may be used -# to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - import unittest import StringIO import os, shutil @@ -477,517 +445,6 @@ class AddCommentTestCase(django.test.TestCase): self.assertEquals(len(q('form textarea[name=comment]')), 1) -class EditPositionTestCase(django.test.TestCase): - fixtures = ['names'] - - def test_edit_position(self): - draft = make_test_data() - url = urlreverse('ietf.idrfc.views_ballot.edit_position', kwargs=dict(name=draft.name, - ballot_id=draft.latest_event(BallotDocEvent, type="created_ballot").pk)) - login_testing_unauthorized(self, "ad", url) - - ad = Person.objects.get(name="Aread Irector") - - # normal get - r = self.client.get(url) - self.assertEquals(r.status_code, 200) - q = PyQuery(r.content) - self.assertTrue(len(q('form input[name=position]')) > 0) - self.assertEquals(len(q('form textarea[name=comment]')), 1) - - # vote - events_before = draft.docevent_set.count() - - r = self.client.post(url, dict(position="discuss", - discuss=" This is a discussion test. \n ", - comment=" This is a test. \n ")) - self.assertEquals(r.status_code, 302) - - pos = draft.latest_event(BallotPositionDocEvent, ad=ad) - self.assertEquals(pos.pos.slug, "discuss") - self.assertTrue(" This is a discussion test." in pos.discuss) - self.assertTrue(pos.discuss_time != None) - self.assertTrue(" This is a test." in pos.comment) - self.assertTrue(pos.comment_time != None) - self.assertTrue("New position" in pos.desc) - self.assertEquals(draft.docevent_set.count(), events_before + 3) - - # recast vote - events_before = draft.docevent_set.count() - r = self.client.post(url, dict(position="noobj")) - self.assertEquals(r.status_code, 302) - - pos = draft.latest_event(BallotPositionDocEvent, ad=ad) - self.assertEquals(pos.pos.slug, "noobj") - self.assertEquals(draft.docevent_set.count(), events_before + 1) - self.assertTrue("Position for" in pos.desc) - - # clear vote - events_before = draft.docevent_set.count() - r = self.client.post(url, dict(position="norecord")) - self.assertEquals(r.status_code, 302) - - pos = draft.latest_event(BallotPositionDocEvent, ad=ad) - self.assertEquals(pos.pos.slug, "norecord") - self.assertEquals(draft.docevent_set.count(), events_before + 1) - self.assertTrue("Position for" in pos.desc) - - # change comment - events_before = draft.docevent_set.count() - r = self.client.post(url, dict(position="norecord", comment="New comment.")) - self.assertEquals(r.status_code, 302) - - pos = draft.latest_event(BallotPositionDocEvent, ad=ad) - self.assertEquals(pos.pos.slug, "norecord") - self.assertEquals(draft.docevent_set.count(), events_before + 2) - self.assertTrue("Ballot comment text updated" in pos.desc) - - def test_edit_position_as_secretary(self): - draft = make_test_data() - url = urlreverse('ietf.idrfc.views_ballot.edit_position', kwargs=dict(name=draft.name, - ballot_id=draft.latest_event(BallotDocEvent, type="created_ballot").pk)) - ad = Person.objects.get(name="Aread Irector") - url += "?ad=%s" % ad.pk - login_testing_unauthorized(self, "secretary", url) - - # normal get - r = self.client.get(url) - self.assertEquals(r.status_code, 200) - q = PyQuery(r.content) - self.assertTrue(len(q('form input[name=position]')) > 0) - - # vote on behalf of AD - events_before = draft.docevent_set.count() - r = self.client.post(url, dict(position="discuss", discuss="Test discuss text")) - self.assertEquals(r.status_code, 302) - - pos = draft.latest_event(BallotPositionDocEvent, ad=ad) - self.assertEquals(pos.pos.slug, "discuss") - self.assertEquals(pos.discuss, "Test discuss text") - self.assertTrue("New position" in pos.desc) - self.assertTrue("by Sec" in pos.desc) - - def test_cannot_edit_position_as_pre_ad(self): - draft = make_test_data() - url = urlreverse('ietf.idrfc.views_ballot.edit_position', kwargs=dict(name=draft.name, - ballot_id=draft.latest_event(BallotDocEvent, type="created_ballot").pk)) - - # transform to pre-ad - ad_role = Role.objects.filter(name="ad")[0] - ad_role.name_id = "pre-ad" - ad_role.save() - - # we can see - login_testing_unauthorized(self, ad_role.person.user.username, url) - - # but not touch - r = self.client.post(url, dict(position="discuss", discuss="Test discuss text")) - self.assertEquals(r.status_code, 403) - - def test_send_ballot_comment(self): - draft = make_test_data() - draft.notify = "somebody@example.com" - draft.save() - - ad = Person.objects.get(name="Aread Irector") - - ballot = draft.latest_event(BallotDocEvent, type="created_ballot") - - BallotPositionDocEvent.objects.create( - doc=draft, type="changed_ballot_position", - by=ad, ad=ad, ballot=ballot, pos=BallotPositionName.objects.get(slug="discuss"), - discuss="This draft seems to be lacking a clearer title?", - discuss_time=datetime.datetime.now(), - comment="Test!", - comment_time=datetime.datetime.now()) - - url = urlreverse('doc_send_ballot_comment', kwargs=dict(name=draft.name, - ballot_id=ballot.pk)) - login_testing_unauthorized(self, "ad", url) - - # normal get - r = self.client.get(url) - self.assertEquals(r.status_code, 200) - q = PyQuery(r.content) - self.assertTrue(len(q('form input[name="cc"]')) > 0) - - # send - mailbox_before = len(outbox) - - r = self.client.post(url, dict(cc="test@example.com", cc_state_change="1")) - self.assertEquals(r.status_code, 302) - - self.assertEquals(len(outbox), mailbox_before + 1) - m = outbox[-1] - self.assertTrue("COMMENT" in m['Subject']) - self.assertTrue("DISCUSS" in m['Subject']) - self.assertTrue(draft.name in m['Subject']) - self.assertTrue("clearer title" in str(m)) - self.assertTrue("Test!" in str(m)) - - -class DeferBallotTestCase(django.test.TestCase): - fixtures = ['names'] - - def test_defer_ballot(self): - draft = make_test_data() - draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="iesg-eva")) - - url = urlreverse('doc_defer_ballot', kwargs=dict(name=draft.name)) - login_testing_unauthorized(self, "ad", url) - - # normal get - r = self.client.get(url) - self.assertEquals(r.status_code, 200) - - # defer - mailbox_before = len(outbox) - - r = self.client.post(url, dict()) - self.assertEquals(r.status_code, 302) - - draft = Document.objects.get(name=draft.name) - self.assertEquals(draft.get_state_slug("draft-iesg"), "defer") - - self.assertEquals(len(outbox), mailbox_before + 2) - self.assertTrue("State Update" in outbox[-2]['Subject']) - self.assertTrue("Deferred" in outbox[-1]['Subject']) - self.assertTrue(draft.file_tag() in outbox[-1]['Subject']) - - def test_undefer_ballot(self): - draft = make_test_data() - draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="defer")) - - url = urlreverse('doc_undefer_ballot', kwargs=dict(name=draft.name)) - login_testing_unauthorized(self, "ad", url) - - # normal get - r = self.client.get(url) - self.assertEquals(r.status_code, 200) - - # undefer - r = self.client.post(url, dict()) - self.assertEquals(r.status_code, 302) - - draft = Document.objects.get(name=draft.name) - self.assertEquals(draft.get_state_slug("draft-iesg"), "iesg-eva") - -class BallotWriteupsTestCase(django.test.TestCase): - fixtures = ['names'] - - def test_edit_last_call_text(self): - draft = make_test_data() - url = urlreverse('doc_ballot_lastcall', kwargs=dict(name=draft.name)) - login_testing_unauthorized(self, "secretary", url) - - # normal get - r = self.client.get(url) - self.assertEquals(r.status_code, 200) - q = PyQuery(r.content) - self.assertEquals(len(q('textarea[name=last_call_text]')), 1) - self.assertEquals(len(q('input[type=submit][value*="Save Last Call"]')), 1) - # we're secretariat, so we got The Link - self.assertEquals(len(q('a:contains("Make Last Call")')), 1) - - # subject error - r = self.client.post(url, dict( - last_call_text="Subject: test\r\nhello\r\n\r\n", - save_last_call_text="1")) - self.assertEquals(r.status_code, 200) - q = PyQuery(r.content) - self.assertTrue(len(q('ul.errorlist')) > 0) - - # save - r = self.client.post(url, dict( - last_call_text="This is a simple test.", - save_last_call_text="1")) - self.assertEquals(r.status_code, 200) - draft = Document.objects.get(name=draft.name) - self.assertTrue("This is a simple test" in draft.latest_event(WriteupDocEvent, type="changed_last_call_text").text) - - # test regenerate - r = self.client.post(url, dict( - last_call_text="This is a simple test.", - regenerate_last_call_text="1")) - self.assertEquals(r.status_code, 200) - q = PyQuery(r.content) - draft = Document.objects.get(name=draft.name) - self.assertTrue("Subject: Last Call" in draft.latest_event(WriteupDocEvent, type="changed_last_call_text").text) - - - def test_request_last_call(self): - draft = make_test_data() - url = urlreverse('doc_ballot_lastcall', kwargs=dict(name=draft.name)) - login_testing_unauthorized(self, "secretary", url) - - # give us an announcement to send - r = self.client.post(url, dict(regenerate_last_call_text="1")) - self.assertEquals(r.status_code, 200) - - mailbox_before = len(outbox) - - # send - r = self.client.post(url, dict( - last_call_text=draft.latest_event(WriteupDocEvent, type="changed_last_call_text").text, - send_last_call_request="1")) - draft = Document.objects.get(name=draft.name) - self.assertEquals(draft.get_state_slug("draft-iesg"), "lc-req") - self.assertEquals(len(outbox), mailbox_before + 3) - self.assertTrue("Last Call" in outbox[-1]['Subject']) - self.assertTrue(draft.name in outbox[-1]['Subject']) - - def test_edit_ballot_writeup(self): - draft = make_test_data() - url = urlreverse('doc_ballot_writeupnotes', kwargs=dict(name=draft.name)) - login_testing_unauthorized(self, "secretary", url) - - # add a IANA review note - draft.set_state(State.objects.get(used=True, type="draft-iana-review", slug="not-ok")) - DocEvent.objects.create(type="iana_review", - doc=draft, - by=Person.objects.get(user__username="iana"), - desc="IANA does not approve of this document, it does not make sense.", - ) - - # normal get - r = self.client.get(url) - self.assertEquals(r.status_code, 200) - q = PyQuery(r.content) - self.assertEquals(len(q('textarea[name=ballot_writeup]')), 1) - self.assertEquals(len(q('input[type=submit][value*="Save Ballot Writeup"]')), 1) - self.assertTrue("IANA does not" in r.content) - - # save - r = self.client.post(url, dict( - ballot_writeup="This is a simple test.", - save_ballot_writeup="1")) - self.assertEquals(r.status_code, 200) - draft = Document.objects.get(name=draft.name) - self.assertTrue("This is a simple test" in draft.latest_event(WriteupDocEvent, type="changed_ballot_writeup_text").text) - - def test_issue_ballot(self): - draft = make_test_data() - url = urlreverse('doc_ballot_writeupnotes', kwargs=dict(name=draft.name)) - login_testing_unauthorized(self, "ad", url) - - ballot = draft.latest_event(BallotDocEvent, type="created_ballot") - - def create_pos(num, vote, comment="", discuss=""): - ad = Person.objects.get(name="Ad No%s" % num) - e = BallotPositionDocEvent() - e.doc = draft - e.ballot = ballot - e.by = ad - e.ad = ad - e.pos = BallotPositionName.objects.get(slug=vote) - e.type = "changed_ballot_position" - e.comment = comment - if e.comment: - e.comment_time = datetime.datetime.now() - e.discuss = discuss - if e.discuss: - e.discuss_time = datetime.datetime.now() - e.save() - - # active - create_pos(1, "yes", discuss="discuss1 " * 20) - create_pos(2, "noobj", comment="comment2 " * 20) - create_pos(3, "discuss", discuss="discuss3 " * 20, comment="comment3 " * 20) - create_pos(4, "abstain") - create_pos(5, "recuse") - - # inactive - create_pos(9, "yes") - - mailbox_before = len(outbox) - - r = self.client.post(url, dict( - ballot_writeup="This is a test.", - issue_ballot="1")) - self.assertEquals(r.status_code, 200) - draft = Document.objects.get(name=draft.name) - - self.assertTrue(draft.latest_event(type="sent_ballot_announcement")) - self.assertEquals(len(outbox), mailbox_before + 2) - issue_email = outbox[-2] - self.assertTrue("Evaluation:" in issue_email['Subject']) - self.assertTrue("comment1" not in str(issue_email)) - self.assertTrue("comment2" in str(issue_email)) - self.assertTrue("comment3" in str(issue_email)) - self.assertTrue("discuss3" in str(issue_email)) - self.assertTrue("This is a test" in str(issue_email)) - self.assertTrue("The IESG has approved" in str(issue_email)) - - def test_edit_approval_text(self): - draft = make_test_data() - url = urlreverse('doc_ballot_approvaltext', kwargs=dict(name=draft.name)) - login_testing_unauthorized(self, "secretary", url) - - # normal get - r = self.client.get(url) - self.assertEquals(r.status_code, 200) - q = PyQuery(r.content) - self.assertEquals(len(q('textarea[name=approval_text]')), 1) - self.assertEquals(len(q('input[type=submit][value*="Save Approval"]')), 1) - - # save - r = self.client.post(url, dict( - approval_text="This is a simple test.", - save_approval_text="1")) - self.assertEquals(r.status_code, 200) - draft = Document.objects.get(name=draft.name) - self.assertTrue("This is a simple test" in draft.latest_event(WriteupDocEvent, type="changed_ballot_approval_text").text) - - # test regenerate - r = self.client.post(url, dict(regenerate_approval_text="1")) - self.assertEquals(r.status_code, 200) - draft = Document.objects.get(name=draft.name) - self.assertTrue("Subject: Protocol Action" in draft.latest_event(WriteupDocEvent, type="changed_ballot_approval_text").text) - - # test regenerate when it's a disapprove - draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="nopubadw")) - - r = self.client.post(url, dict(regenerate_approval_text="1")) - self.assertEquals(r.status_code, 200) - draft = Document.objects.get(name=draft.name) - self.assertTrue("NOT be published" in draft.latest_event(WriteupDocEvent, type="changed_ballot_approval_text").text) - - # test regenerate when it's a conflict review - draft.group = Group.objects.get(type="individ") - draft.stream_id = "irtf" - draft.save() - draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="iesg-eva")) - - r = self.client.post(url, dict(regenerate_approval_text="1")) - self.assertEquals(r.status_code, 200) - draft = Document.objects.get(name=draft.name) - self.assertTrue("Subject: Results of IETF-conflict review" in draft.latest_event(WriteupDocEvent, type="changed_ballot_approval_text").text) - -class ApproveBallotTestCase(django.test.TestCase): - fixtures = ['names'] - - def test_approve_ballot(self): - draft = make_test_data() - draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="iesg-eva")) # make sure it's approvable - - url = urlreverse('doc_approve_ballot', kwargs=dict(name=draft.name)) - login_testing_unauthorized(self, "secretary", url) - - # normal get - r = self.client.get(url) - self.assertEquals(r.status_code, 200) - q = PyQuery(r.content) - self.assertTrue("send out the announcement" in q('.actions input[type=submit]')[0].get('value').lower()) - self.assertEquals(len(q('.announcement pre:contains("Subject: Protocol Action")')), 1) - - # approve - mailbox_before = len(outbox) - - r = self.client.post(url, dict(skiprfceditorpost="1")) - self.assertEquals(r.status_code, 302) - - draft = Document.objects.get(name=draft.name) - self.assertEquals(draft.get_state_slug("draft-iesg"), "ann") - self.assertEquals(len(outbox), mailbox_before + 4) - self.assertTrue("Protocol Action" in outbox[-2]['Subject']) - # the IANA copy - self.assertTrue("Protocol Action" in outbox[-1]['Subject']) - self.assertTrue(not outbox[-1]['CC']) - self.assertTrue("Protocol Action" in draft.message_set.order_by("-time")[0].subject) - - def test_disapprove_ballot(self): - draft = make_test_data() - draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="nopubadw")) - - url = urlreverse('doc_approve_ballot', kwargs=dict(name=draft.name)) - login_testing_unauthorized(self, "secretary", url) - - # disapprove (the Martians aren't going to be happy) - mailbox_before = len(outbox) - - r = self.client.post(url, dict()) - self.assertEquals(r.status_code, 302) - - draft = Document.objects.get(name=draft.name) - self.assertEquals(draft.get_state_slug("draft-iesg"), "dead") - self.assertEquals(len(outbox), mailbox_before + 3) - self.assertTrue("NOT be published" in str(outbox[-1])) - -class MakeLastCallTestCase(django.test.TestCase): - fixtures = ['names'] - - def test_make_last_call(self): - draft = make_test_data() - draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="lc-req")) - - url = urlreverse('doc_make_last_call', kwargs=dict(name=draft.name)) - login_testing_unauthorized(self, "secretary", url) - - # normal get - r = self.client.get(url) - self.assertEquals(r.status_code, 200) - q = PyQuery(r.content) - self.assertEquals(len(q('input[name=last_call_sent_date]')), 1) - - # make last call - mailbox_before = len(outbox) - - expire_date = q('input[name=last_call_expiration_date]')[0].get("value") - - r = self.client.post(url, - dict(last_call_sent_date=q('input[name=last_call_sent_date]')[0].get("value"), - last_call_expiration_date=expire_date - )) - self.assertEquals(r.status_code, 302) - - draft = Document.objects.get(name=draft.name) - self.assertEquals(draft.get_state_slug("draft-iesg"), "lc") - self.assertEquals(draft.latest_event(LastCallDocEvent, "sent_last_call").expires.strftime("%Y-%m-%d"), expire_date) - self.assertEquals(len(outbox), mailbox_before + 4) - - self.assertTrue("Last Call" in outbox[-4]['Subject']) - # the IANA copy - self.assertTrue("Last Call" in outbox[-3]['Subject']) - self.assertTrue("Last Call" in draft.message_set.order_by("-time")[0].subject) - -class RequestPublicationTestCase(django.test.TestCase): - fixtures = ['names'] - - def test_request_publication(self): - draft = make_test_data() - draft.stream = StreamName.objects.get(slug="iab") - draft.group = Group.objects.get(acronym="iab") - draft.intended_std_level = IntendedStdLevelName.objects.get(slug="inf") - draft.save() - draft.set_state(State.objects.get(used=True, type="draft-stream-iab", slug="approved")) - - url = urlreverse('doc_request_publication', kwargs=dict(name=draft.name)) - login_testing_unauthorized(self, "iabchair", url) - - # normal get - r = self.client.get(url) - self.assertEquals(r.status_code, 200) - q = PyQuery(r.content) - subject = q('input#id_subject')[0].get("value") - self.assertTrue("Document Action" in subject) - body = q('.request-publication #id_body').text() - self.assertTrue("Informational" in body) - self.assertTrue("IAB" in body) - - # approve - mailbox_before = len(outbox) - - r = self.client.post(url, dict(subject=subject, body=body, skiprfceditorpost="1")) - self.assertEquals(r.status_code, 302) - - draft = Document.objects.get(name=draft.name) - self.assertEquals(draft.get_state_slug("draft-stream-iab"), "rfc-edit") - self.assertEquals(len(outbox), mailbox_before + 2) - self.assertTrue("Document Action" in outbox[-2]['Subject']) - self.assertTrue("Document Action" in draft.message_set.order_by("-time")[0].subject) - # the IANA copy - self.assertTrue("Document Action" in outbox[-1]['Subject']) - self.assertTrue(not outbox[-1]['CC']) class ExpireIDsTestCase(django.test.TestCase): fixtures = ['names'] @@ -1014,7 +471,7 @@ class ExpireIDsTestCase(django.test.TestCase): f.close() def test_in_draft_expire_freeze(self): - from ietf.idrfc.expire import in_draft_expire_freeze + from ietf.doc.expire import in_draft_expire_freeze Meeting.objects.create(number="123", type=MeetingTypeName.objects.get(slug="ietf"), @@ -1029,7 +486,7 @@ class ExpireIDsTestCase(django.test.TestCase): self.assertTrue(not in_draft_expire_freeze(datetime.datetime.combine(ietf_monday, time(0, 0, 0)))) def test_warn_expirable_drafts(self): - from ietf.idrfc.expire import get_soon_to_expire_drafts, send_expire_warning_for_draft + from ietf.doc.expire import get_soon_to_expire_drafts, send_expire_warning_for_draft draft = make_test_data() @@ -1052,7 +509,7 @@ class ExpireIDsTestCase(django.test.TestCase): self.assertTrue("wgchairman@ietf.org" in str(outbox[-1])) def test_expire_drafts(self): - from ietf.idrfc.expire import get_expired_drafts, send_expire_notice_for_draft, expire_draft + from ietf.doc.expire import get_expired_drafts, send_expire_notice_for_draft, expire_draft draft = make_test_data() @@ -1097,7 +554,7 @@ class ExpireIDsTestCase(django.test.TestCase): def test_clean_up_draft_files(self): draft = make_test_data() - from ietf.idrfc.expire import clean_up_draft_files + from ietf.doc.expire import clean_up_draft_files # put unknown file unknown = "draft-i-am-unknown-01.txt" @@ -1175,7 +632,7 @@ class ExpireLastCallTestCase(django.test.TestCase): fixtures = ['names'] def test_expire_last_call(self): - from ietf.idrfc.lastcall import get_expired_last_calls, expire_last_call + from ietf.doc.lastcall import get_expired_last_calls, expire_last_call # check that non-expirable drafts aren't expired diff --git a/ietf/idrfc/urls.py b/ietf/doc/urls.py similarity index 80% rename from ietf/idrfc/urls.py rename to ietf/doc/urls.py index 1b0e1e269..d55d7b34c 100644 --- a/ietf/idrfc/urls.py +++ b/ietf/doc/urls.py @@ -31,8 +31,8 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from django.conf.urls.defaults import patterns, url, include -from ietf.idrfc import views_search, views_edit, views_ballot, views from ietf.doc.models import State +from ietf.doc import views_search, views_draft, views_ballot from ietf.doc import views_status_change from ietf.doc import views_doc @@ -65,23 +65,23 @@ urlpatterns = patterns('', (r'^(?P[A-Za-z0-9._+-]+)/ballotpopup/(?P[0-9]+)/$', views_doc.ballot_popup), #(r'^(?P[A-Za-z0-9._+-]+)/ballot.json$', views_doc.ballot_json), # legacy view - url(r'^(?P[A-Za-z0-9._+-]+)/edit/state/$', views_edit.change_state, name='doc_change_state'), # IESG state - url(r'^(?P[A-Za-z0-9._+-]+)/edit/state/(?Piana-action|iana-review)/$', views_edit.change_iana_state, name='doc_change_iana_state'), - url(r'^(?P[A-Za-z0-9._+-]+)/edit/info/$', views_edit.edit_info, name='doc_edit_info'), - url(r'^(?P[A-Za-z0-9._+-]+)/edit/requestresurrect/$', views_edit.request_resurrect, name='doc_request_resurrect'), - url(r'^(?P[A-Za-z0-9._+-]+)/edit/resurrect/$', views_edit.resurrect, name='doc_resurrect'), - url(r'^(?P[A-Za-z0-9._+-]+)/edit/addcomment/$', views_edit.add_comment, name='doc_add_comment'), + url(r'^(?P[A-Za-z0-9._+-]+)/edit/state/$', views_draft.change_state, name='doc_change_state'), # IESG state + url(r'^(?P[A-Za-z0-9._+-]+)/edit/state/(?Piana-action|iana-review)/$', views_draft.change_iana_state, name='doc_change_iana_state'), + url(r'^(?P[A-Za-z0-9._+-]+)/edit/info/$', views_draft.edit_info, name='doc_edit_info'), + url(r'^(?P[A-Za-z0-9._+-]+)/edit/requestresurrect/$', views_draft.request_resurrect, name='doc_request_resurrect'), + url(r'^(?P[A-Za-z0-9._+-]+)/edit/resurrect/$', views_draft.resurrect, name='doc_resurrect'), + url(r'^(?P[A-Za-z0-9._+-]+)/edit/addcomment/$', views_draft.add_comment, name='doc_add_comment'), - url(r'^(?P[A-Za-z0-9._+-]+)/edit/stream/$', views_edit.change_stream, name='doc_change_stream'), - url(r'^(?P[A-Za-z0-9._+-]+)/edit/notify/$', views_edit.edit_notices, name='doc_change_notify'), - url(r'^(?P[A-Za-z0-9._+-]+)/edit/status/$', views_edit.change_intention, name='doc_change_intended_status'), - url(r'^(?P[A-Za-z0-9._+-]+)/edit/telechat/$', views_edit.telechat_date, name='doc_change_telechat_date'), - url(r'^(?P[A-Za-z0-9._+-]+)/edit/iesgnote/$', views_edit.edit_iesg_note, name='doc_change_iesg_note'), - url(r'^(?P[A-Za-z0-9._+-]+)/edit/ad/$', views_edit.edit_ad, name='doc_change_ad'), - url(r'^(?P[A-Za-z0-9._+-]+)/edit/consensus/$', views_edit.edit_consensus, name='doc_edit_consensus'), - url(r'^(?P[A-Za-z0-9._+-]+)/edit/shepherd/$', views_edit.edit_shepherd, name='doc_edit_shepherd'), - url(r'^(?P[A-Za-z0-9._+-]+)/edit/shepherdwriteup/$', views_edit.edit_shepherd_writeup, name='doc_edit_shepherd_writeup'), - url(r'^(?P[A-Za-z0-9._+-]+)/edit/requestpublication/$', views_edit.request_publication, name='doc_request_publication'), + url(r'^(?P[A-Za-z0-9._+-]+)/edit/stream/$', views_draft.change_stream, name='doc_change_stream'), + url(r'^(?P[A-Za-z0-9._+-]+)/edit/notify/$', views_draft.edit_notices, name='doc_change_notify'), + url(r'^(?P[A-Za-z0-9._+-]+)/edit/status/$', views_draft.change_intention, name='doc_change_intended_status'), + url(r'^(?P[A-Za-z0-9._+-]+)/edit/telechat/$', views_draft.telechat_date, name='doc_change_telechat_date'), + url(r'^(?P[A-Za-z0-9._+-]+)/edit/iesgnote/$', views_draft.edit_iesg_note, name='doc_change_iesg_note'), + url(r'^(?P[A-Za-z0-9._+-]+)/edit/ad/$', views_draft.edit_ad, name='doc_change_ad'), + url(r'^(?P[A-Za-z0-9._+-]+)/edit/consensus/$', views_draft.edit_consensus, name='doc_edit_consensus'), + url(r'^(?P[A-Za-z0-9._+-]+)/edit/shepherd/$', views_draft.edit_shepherd, name='doc_edit_shepherd'), + url(r'^(?P[A-Za-z0-9._+-]+)/edit/shepherdwriteup/$', views_draft.edit_shepherd_writeup, name='doc_edit_shepherd_writeup'), + url(r'^(?P[A-Za-z0-9._+-]+)/edit/requestpublication/$', views_draft.request_publication, name='doc_request_publication'), url(r'^(?P[A-Za-z0-9._+-]+)/edit/clearballot/$', views_ballot.clear_ballot, name='doc_clear_ballot'), url(r'^(?P[A-Za-z0-9._+-]+)/edit/deferballot/$', views_ballot.defer_ballot, name='doc_defer_ballot'), diff --git a/ietf/idrfc/views_ballot.py b/ietf/doc/views_ballot.py similarity index 99% rename from ietf/idrfc/views_ballot.py rename to ietf/doc/views_ballot.py index 2f01cb1f6..d10190f8a 100644 --- a/ietf/idrfc/views_ballot.py +++ b/ietf/doc/views_ballot.py @@ -20,8 +20,8 @@ from ietf.ietfauth.decorators import has_role, role_required from ietf.iesg.models import TelechatDate from ietf.ipr.models import IprDetail from ietf.ipr.search import iprs_from_docs -from ietf.idrfc.mails import * -from ietf.idrfc.lastcall import request_last_call +from ietf.doc.mails import * +from ietf.doc.lastcall import request_last_call from ietf.doc.utils import * from ietf.doc.models import * diff --git a/ietf/doc/views_conflict_review.py b/ietf/doc/views_conflict_review.py index 7b6afd9fe..98b3242ca 100644 --- a/ietf/doc/views_conflict_review.py +++ b/ietf/doc/views_conflict_review.py @@ -15,7 +15,7 @@ from ietf.doc.utils import create_ballot_if_not_open, close_open_ballots, get_do from ietf.ietfauth.decorators import has_role, role_required from ietf.utils.textupload import get_cleaned_text_file_content from ietf.utils.mail import send_mail_preformatted -from ietf.idrfc.mails import email_iana +from ietf.doc.mails import email_iana from ietf.doc.models import State, Document, DocHistory, DocAlias from ietf.doc.models import DocEvent, NewRevisionDocEvent, WriteupDocEvent, TelechatDocEvent, BallotDocEvent, BallotPositionDocEvent diff --git a/ietf/idrfc/views_edit.py b/ietf/doc/views_draft.py similarity index 99% rename from ietf/idrfc/views_edit.py rename to ietf/doc/views_draft.py index 123ba047d..85e066f4b 100644 --- a/ietf/idrfc/views_edit.py +++ b/ietf/doc/views_draft.py @@ -19,8 +19,8 @@ from ietf.utils.mail import send_mail_text, send_mail_message from ietf.ietfauth.decorators import role_required from ietf.ietfauth.utils import has_role, is_authorized_in_doc_stream, user_is_person from ietf.iesg.models import TelechatDate -from ietf.idrfc.mails import * -from ietf.idrfc.lastcall import request_last_call +from ietf.doc.mails import * +from ietf.doc.lastcall import request_last_call from ietf.utils.textupload import get_cleaned_text_file_content from ietf.person.forms import EmailsField from ietf.group.models import Group @@ -1008,7 +1008,7 @@ def request_publication(request, name): else: action = "Document Action" - from ietf.idrfc.templatetags.mail_filters import std_level_prompt + from ietf.doc.templatetags.mail_filters import std_level_prompt subject = "%s: '%s' to %s (%s-%s.txt)" % (action, doc.title, std_level_prompt(doc), doc.name, doc.rev) diff --git a/ietf/idrfc/views_search.py b/ietf/doc/views_search.py similarity index 99% rename from ietf/idrfc/views_search.py rename to ietf/doc/views_search.py index e4f2e30b4..73cc918b4 100644 --- a/ietf/idrfc/views_search.py +++ b/ietf/doc/views_search.py @@ -38,7 +38,7 @@ from django.db.models import Q from django.template import RequestContext from django.http import Http404, HttpResponse, HttpResponseBadRequest, HttpResponseRedirect -from ietf.idrfc.expire import expirable_draft +from ietf.doc.expire import expirable_draft from ietf.utils import normalize_draftname from ietf.doc.models import * from ietf.person.models import * @@ -367,6 +367,10 @@ def search(request): {'form':form, 'docs':results, 'meta':meta, 'show_add_to_list': True }, context_instance=RequestContext(request)) +def frontpage(request): + form = SearchForm() + return render_to_response('idrfc/main.html', {'form':form}, context_instance=RequestContext(request)) + def ad_dashboard_group(doc): if doc.type.slug=='draft': diff --git a/ietf/doc/views_status_change.py b/ietf/doc/views_status_change.py index dd8911a24..af8b47c31 100644 --- a/ietf/doc/views_status_change.py +++ b/ietf/doc/views_status_change.py @@ -23,9 +23,8 @@ from ietf.group.models import Group from ietf.name.models import DocRelationshipName, StdLevelName from ietf.doc.forms import TelechatForm, AdForm, NotifyForm - -from ietf.idrfc.views_ballot import LastCallTextForm -from ietf.idrfc.lastcall import request_last_call +from ietf.doc.views_ballot import LastCallTextForm +from ietf.doc.lastcall import request_last_call class ChangeStateForm(forms.Form): new_state = forms.ModelChoiceField(State.objects.filter(type="statchg", used=True), label="Status Change Evaluation State", empty_label=None, required=True) diff --git a/ietf/idrfc/templatetags/ballot_icon.py b/ietf/idrfc/templatetags/ballot_icon.py index 2afdd29bf..a43af8b0c 100644 --- a/ietf/idrfc/templatetags/ballot_icon.py +++ b/ietf/idrfc/templatetags/ballot_icon.py @@ -71,7 +71,7 @@ def render_ballot_icon(user, doc): if not ballot: return "" - edit_position_url = urlreverse('ietf.idrfc.views_ballot.edit_position', kwargs=dict(name=doc.name, ballot_id=ballot.pk)) + edit_position_url = urlreverse('ietf.doc.views_ballot.edit_position', kwargs=dict(name=doc.name, ballot_id=ballot.pk)) def sort_key(t): _, pos = t diff --git a/ietf/idrfc/templatetags/ballot_icon_redesign.py b/ietf/idrfc/templatetags/ballot_icon_redesign.py index 29f0b79e7..3604beaa8 100644 --- a/ietf/idrfc/templatetags/ballot_icon_redesign.py +++ b/ietf/idrfc/templatetags/ballot_icon_redesign.py @@ -84,7 +84,7 @@ def render_ballot_icon(user, doc): edit_position_url = "" if has_role(user, "Area Director"): - edit_position_url = urlreverse('ietf.idrfc.views_ballot.edit_position', kwargs=dict(name=doc.name, ballot_id=ballot.pk)) + edit_position_url = urlreverse('ietf.doc.views_ballot.edit_position', kwargs=dict(name=doc.name, ballot_id=ballot.pk)) title = "IESG positions (click to show more%s)" % (", right-click to edit position" if edit_position_url else "") diff --git a/ietf/idrfc/views.py b/ietf/idrfc/views.py deleted file mode 100644 index b18516b33..000000000 --- a/ietf/idrfc/views.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -# All rights reserved. Contact: Pasi Eronen -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# -# * Neither the name of the Nokia Corporation and/or its -# subsidiary(-ies) nor the names of its contributors may be used -# to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -from django.shortcuts import render_to_response -from django.template import RequestContext -from ietf.idrfc.views_search import SearchForm - -def main(request): - form = SearchForm() - return render_to_response('idrfc/main.html', {'form':form}, context_instance=RequestContext(request)) - diff --git a/ietf/secr/telechat/views.py b/ietf/secr/telechat/views.py index 195cdbe54..3f4930d94 100644 --- a/ietf/secr/telechat/views.py +++ b/ietf/secr/telechat/views.py @@ -13,8 +13,8 @@ from ietf.doc.utils import get_document_content, log_state_changed from ietf.group.models import Group from ietf.name.models import BallotPositionName from ietf.person.models import Person -from ietf.idrfc.lastcall import request_last_call -from ietf.idrfc.mails import email_ad, email_state_changed +from ietf.doc.lastcall import request_last_call +from ietf.doc.mails import email_ad, email_state_changed from ietf.iesg.models import TelechatDate, TelechatAgendaItem, WGAction from ietf.iesg.views import _agenda_data @@ -229,7 +229,7 @@ def doc_detail(request, date, name): if request.method == 'POST': button_text = request.POST.get('submit', '') - # logic from idrfc/views_ballot.py EditPositionRedesign + # logic from doc/views_ballot.py EditPositionRedesign if button_text == 'update_ballot': formset = BallotFormset(request.POST, initial=initial_ballot) state_form = ChangeStateForm(initial=initial_state) @@ -256,7 +256,7 @@ def doc_detail(request, date, name): url = reverse('telechat_doc_detail', kwargs={'date':date,'name':name}) return HttpResponseRedirect(url) - # logic from idrfc/views_edit.py change_stateREDESIGN + # logic from doc/views_draft.py change_state elif button_text == 'update_state': formset = BallotFormset(initial=initial_ballot) state_form = ChangeStateForm(request.POST, initial=initial_state) diff --git a/ietf/settings_sqlitetest.py b/ietf/settings_sqlitetest.py index 28380b3c4..80e497563 100644 --- a/ietf/settings_sqlitetest.py +++ b/ietf/settings_sqlitetest.py @@ -1,7 +1,7 @@ # Standard settings except we use SQLite, this is useful for speeding # up tests that depend on the test database, try for instance: # -# ./manage.py test --settings=settings_sqlitetest idrfc.ChangeStateTestCase +# ./manage.py test --settings=settings_sqlitetest doc.ChangeStateTestCase # from settings import * diff --git a/ietf/submit/utils.py b/ietf/submit/utils.py index 564e0fe0d..9b6f9d684 100644 --- a/ietf/submit/utils.py +++ b/ietf/submit/utils.py @@ -116,7 +116,7 @@ def perform_post(request, submission): # clean up old files if prev_rev != draft.rev: - from ietf.idrfc.expire import move_draft_files_to_archive + from ietf.doc.expire import move_draft_files_to_archive move_draft_files_to_archive(draft, prev_rev) # automatic state changes diff --git a/ietf/sync/iana.py b/ietf/sync/iana.py index c795e70a5..9e7181ec2 100644 --- a/ietf/sync/iana.py +++ b/ietf/sync/iana.py @@ -5,8 +5,8 @@ from django.conf import settings from ietf.doc.models import * from ietf.doc.utils import add_state_change_event +from ietf.doc.mails import email_ad, email_state_changed, email_authors from ietf.person.models import * -from ietf.idrfc.mails import email_ad, email_state_changed, email_authors from ietf.utils.timezone import * #PROTOCOLS_URL = "http://www.iana.org/protocols/" diff --git a/ietf/templates/doc/ballot_popup.html b/ietf/templates/doc/ballot_popup.html index 16faf4d1a..71d5f4b4a 100644 --- a/ietf/templates/doc/ballot_popup.html +++ b/ietf/templates/doc/ballot_popup.html @@ -6,7 +6,7 @@
{% if request.user|has_role:"Area Director" %} - Edit Position + Edit Position {% endif %} Close diff --git a/ietf/templates/doc/document_ballot_content.html b/ietf/templates/doc/document_ballot_content.html index da52897a0..a155ed13b 100644 --- a/ietf/templates/doc/document_ballot_content.html +++ b/ietf/templates/doc/document_ballot_content.html @@ -4,7 +4,7 @@ {% if editable and user|has_role:"Area Director,Secretariat" %}
{% if user|has_role:"Area Director" %} - + {% endif %} {% if doc.type_id == "draft" or doc.type_id == "conflrev" %} @@ -28,7 +28,7 @@
{{ n.name }}
{% for p in positions %} -
{% if p.old_ad %}[{% endif %}{{ p.ad.plain_name }}{% if p.old_ad %}]{% endif %}{% if p.comment or p.discuss %} *{% endif %}
+
{% if p.old_ad %}[{% endif %}{{ p.ad.plain_name }}{% if p.old_ad %}]{% endif %}{% if p.comment or p.discuss %} *{% endif %}
{% if p.old_positions %}
(was {{ p.old_positions|join:", " }})
{% endif %} {% empty %} none diff --git a/ietf/urls.py b/ietf/urls.py index 75a22fe7c..4ad3011b9 100644 --- a/ietf/urls.py +++ b/ietf/urls.py @@ -38,14 +38,14 @@ sitemaps = { } urlpatterns = patterns('', - (r'^$', 'ietf.idrfc.views.main'), + (r'^$', 'ietf.doc.views_search.frontpage'), (r'^accounts/', include('ietf.ietfauth.urls')), (r'^admin/', include(admin.site.urls)), (r'^admin/doc/', include('django.contrib.admindocs.urls')), (r'^ann/', include('ietf.announcements.urls')), (r'^community/', include('ietf.community.urls')), (r'^cookies/', include('ietf.cookies.urls')), - (r'^doc/', include('ietf.idrfc.urls')), + (r'^doc/', include('ietf.doc.urls')), (r'^drafts/', include('ietf.doc.redirect_drafts_urls')), (r'^feed/comments/(?P.*)/$', 'django.views.generic.simple.redirect_to', { 'url': '/feed/document-changes/%(remainder)s/'}), (r'^feed/(?P.*)/$', 'django.contrib.syndication.views.feed', { 'feed_dict': feeds}), diff --git a/ietf/wginfo/views.py b/ietf/wginfo/views.py index b81ea8731..7af56f075 100644 --- a/ietf/wginfo/views.py +++ b/ietf/wginfo/views.py @@ -38,7 +38,7 @@ from django.http import HttpResponse from django.conf import settings from django.core.urlresolvers import reverse as urlreverse from ietf.idtracker.models import Area, IETFWG -from ietf.idrfc.views_search import SearchForm, retrieve_search_results +from ietf.doc.views_search import SearchForm, retrieve_search_results from ietf.idrfc.idrfc_wrapper import IdRfcWrapper from ietf.ipr.models import IprDetail from ietf.group.models import Group