Merged additional django-port and shim-removal tweaks from olau@iola.dk: branch/iola/djangoport@7167.

- Legacy-Id: 7168
This commit is contained in:
Henrik Levkowetz 2014-01-26 16:30:52 +00:00
commit 2d420fac34
27 changed files with 824 additions and 244 deletions

View file

@ -1,7 +1,7 @@
# -*- coding: utf-8-no-bom -*-
# Copyright The IETF Trust 2007, All Rights Reserved
__version__ = "4.91-dev"
__version__ = "5.0.0-dev"
__date__ = "$Date$"

View file

@ -10,7 +10,7 @@ from ietf.utils.mail import send_mail, send_mail_subj
from ietf.doc.models import Document, DocEvent, State, save_document_in_history, IESG_SUBSTATE_TAGS
from ietf.person.models import Person, Email
from ietf.meeting.models import Meeting
from ietf.doc.utils import log_state_changed
from ietf.doc.utils import add_state_change_event
def expirable_draft(draft):
"""Return whether draft is in an expirable state or not. This is
@ -122,20 +122,18 @@ def expire_draft(doc):
# clean up files
move_draft_files_to_archive(doc, doc.rev)
# change the state
system = Person.objects.get(name="(System)")
# change the state
save_document_in_history(doc)
if doc.latest_event(type='started_iesg_process'):
dead_state = State.objects.get(used=True, type="draft-iesg", slug="dead")
prev_state = doc.friendly_state()
prev_tag = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
prev_tag = prev_tag[0] if prev_tag else None
if doc.get_state("draft-iesg") != dead_state:
doc.set_state(dead_state)
if prev_tag:
doc.tags.remove(prev_tag)
log_state_changed(None, doc, system, doc.friendly_state(), prev_state)
new_state = State.objects.get(used=True, type="draft-iesg", slug="dead")
prev_state = doc.get_state(new_state.type_id)
prev_tags = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
if new_state != prev_state:
doc.set_state(new_state)
doc.tags.remove(*prev_tags)
e = add_state_change_event(doc, system, prev_state, new_state, prev_tags=prev_tags, new_tags=[])
e = DocEvent(doc=doc, by=system)
e.type = "expired_document"

View file

@ -6,7 +6,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.doc.utils import add_state_change_event
from ietf.doc.mails import *
def request_last_call(request, doc):
@ -36,30 +36,27 @@ def get_expired_last_calls():
def expire_last_call(doc):
if doc.type_id == 'draft':
state = State.objects.get(used=True, type="draft-iesg", slug="writeupw")
new_state = State.objects.get(used=True, type="draft-iesg", slug="writeupw")
e = doc.latest_event(WriteupDocEvent, type="changed_ballot_writeup_text")
if e and "Relevant content can frequently be found in the abstract" not in e.text:
# if boiler-plate text has been removed, we assume the
# write-up has been written
state = State.objects.get(used=True, type="draft-iesg", slug="goaheadw")
prev = doc.get_state("draft-iesg")
new_state = State.objects.get(used=True, type="draft-iesg", slug="goaheadw")
elif doc.type_id == 'statchg':
state = State.objects.get(used=True, type="statchg", slug="goahead")
prev = doc.get_state("statchg")
new_state = State.objects.get(used=True, type="statchg", slug="goahead")
else:
raise ValueError("Unexpected document type to expire_last_call(): %s" % doc.type)
prev_state = doc.friendly_state()
save_document_in_history(doc)
doc.set_state(state)
prev_tag = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
prev_tag = prev_tag[0] if prev_tag else None
if prev_tag:
doc.tags.remove(prev_tag)
prev_state = doc.get_state(new_state.type_id)
doc.set_state(new_state)
e = log_state_changed(None, doc, Person.objects.get(name="(System)"), doc.friendly_state(), prev_state)
prev_tags = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
doc.tags.remove(*prev_tags)
system = Person.objects.get(name="(System)")
e = add_state_change_event(doc, system, prev_state, new_state, prev_tags=prev_tags, new_tags=[])
doc.time = e.time
doc.save()

View file

@ -0,0 +1,464 @@
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
class Migration(DataMigration):
def forwards(self, orm):
import re
events = orm.DocEvent.objects.filter(type="changed_document").filter(
models.Q(desc__istartswith="State changed to ") |
models.Q(desc__istartswith="State Changes to ") |
models.Q(desc__istartswith="Sub state has been changed to ") |
models.Q(desc__istartswith="State has been changed to ")
).select_related("doc").values("id", "desc", "doc", "doc__type")
re_state_changed = re.compile(r"(?:State (?:has been changed|changed|Changes) to <b>(?P<to>.*)</b> from (<b>|)(?P<from>.*)(</b> by|)|Sub state has been changed to (?P<tosub>.*) from (?P<fromsub>.*))")
state_map = {
"draft-iesg": {},
"charter": {},
"statchg": {},
"conflrev": {},
}
state_types = dict((t.slug, t) for t in orm.StateType.objects.all())
for t in state_map:
for s in orm.State.objects.filter(type=t).select_related("type"):
state_map[t][s.name] = s
if t == "draft-iesg":
state_map[t][str(s.order)] = s
state_map["draft-iesg"]["Last Call Issued"] = state_map["draft-iesg"]["In Last Call"]
state_map["draft-iesg"]["Wait for Last Call to End"] = state_map["draft-iesg"]["In Last Call"]
state_map["draft-iesg"]["Wait for Writeup"] = state_map["draft-iesg"]["Waiting for Writeup"]
state_map["draft-iesg"]["Ready for Telechat"] = state_map["draft-iesg"]["IESG Evaluation"]
state_map["draft-iesg"]["Defer"] = state_map["draft-iesg"]["IESG Evaluation - Defer"]
state_map["draft-iesg"]["Final AD Go-Ahead"] = state_map["draft-iesg"]["Waiting for AD Go-Ahead"]
state_map["draft-iesg"]["Do not publish - Info sent"] = state_map["draft-iesg"]["DNP-announcement to be sent"]
state_map["draft-iesg"]["AD re-review"] = state_map["draft-iesg"]["AD Evaluation"]
state_map["draft-iesg"]["Pre AD Evaluation"] = state_map["draft-iesg"]["AD Evaluation"]
state_map["draft-iesg"]["Approved - Info sent"] = state_map["draft-iesg"]["Approved-announcement sent"]
state_map["draft-iesg"]["Approved But Comments Needed"] = state_map["draft-iesg"]["Approved-announcement to be sent"]
state_map["draft-iesg"]["Approved"] = state_map["draft-iesg"]["Approved-announcement sent"]
state_map["draft-iesg"]["Requested"] = state_map["draft-iesg"]["Publication Requested"]
state_map["draft-iesg"]["Reading List"] = state_map["draft-iesg"]["AD is watching"]
state_map["draft-iesg"]["Discuss Cleared, Wait for approval"] = state_map["draft-iesg"]["IESG Evaluation"]
state_map["draft-iesg"]["Discuss Writing Received"] = state_map["draft-iesg"]["IESG Evaluation"]
state_map["draft-iesg"]["Discuss fix received"] = state_map["draft-iesg"]["IESG Evaluation"]
state_map["draft-iesg"]["Evaluation: Discuss"] = state_map["draft-iesg"]["IESG Evaluation"]
state_map["draft-iesg"]["In WG"] = state_map["draft-iesg"]["IESG Evaluation"]
state_map["draft-iesg"]["New Version Coming"] = state_map["draft-iesg"]["IESG Evaluation"]
state_map["draft-iesg"]["New Version Needed (WG/Author)"] = state_map["draft-iesg"]["IESG Evaluation"]
state_map["draft-iesg"]["Token@wg or Author"] = state_map["draft-iesg"]["IESG Evaluation"]
state_map["draft-iesg"]["WG/Author"] = state_map["draft-iesg"]["IESG Evaluation"]
state_map["draft-iesg"]["AD Followup"] = state_map["draft-iesg"]["IESG Evaluation"]
state_map["draft-iesg"]["AD to write --Don't publish"] = state_map["draft-iesg"]["DNP-waiting for AD note"]
events = list(events)
from django.db import connection
cursor = connection.cursor()
cursor.execute("start transaction")
for e in events:
desc = e["desc"]
m = re_state_changed.match(desc)
if not m:
print "FAIL", e["id"], desc
else:
to = (m.group("to") or "")
i = to.find("::")
if i != -1:
to = to[:i]
i = to.find(" --")
if i != -1:
to = to[:i]
i = to.find(" (ends ")
if i != -1:
to = to[:i]
if "IESG: Dead" in to:
to = u"Dead"
to = to.strip()
t = e["doc__type"]
if t == "draft":
t = "draft-iesg"
state = state_map[t].get(to)
state_type = state_types[t]
# insert StateDocEvent with the DocEvent as base,
# doesn't appear to be possible to do this through
# Django, so fallback to raw SQL
cursor.execute("insert into doc_statedocevent (docevent_ptr_id, state_type_id, state_id) values (%s, %s, %s)"
% (e["id"], "'" + state_type.pk + "'", state.pk if state else "NULL"))
orm.DocEvent.objects.filter(pk=e["id"]).update(type="changed_state")
#if to not in state_map[t]:
# print e["doc"], e["id"], to, desc
cursor.execute("commit")
def backwards(self, orm):
pass
models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
u'doc.ballotdocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'BallotDocEvent', '_ormbases': [u'doc.DocEvent']},
'ballot_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.BallotType']"}),
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'})
},
u'doc.ballotpositiondocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'BallotPositionDocEvent', '_ormbases': [u'doc.DocEvent']},
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']"}),
'ballot': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['doc.BallotDocEvent']", 'null': 'True'}),
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'comment_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'discuss': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'discuss_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
'pos': ('django.db.models.fields.related.ForeignKey', [], {'default': "'norecord'", 'to': u"orm['name.BallotPositionName']"})
},
u'doc.ballottype': {
'Meta': {'ordering': "['order']", 'object_name': 'BallotType'},
'doc_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'positions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['name.BallotPositionName']", 'symmetrical': 'False', 'blank': 'True'}),
'question': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
u'doc.consensusdocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'ConsensusDocEvent', '_ormbases': [u'doc.DocEvent']},
'consensus': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'})
},
u'doc.deletedevent': {
'Meta': {'object_name': 'DeletedEvent'},
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']"}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'json': ('django.db.models.fields.TextField', [], {}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})
},
u'doc.docalias': {
'Meta': {'object_name': 'DocAlias'},
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
},
u'doc.docevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'DocEvent'},
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']"}),
'desc': ('django.db.models.fields.TextField', [], {}),
'doc': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'db_index': 'True'}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'doc.dochistory': {
'Meta': {'object_name': 'DocHistory'},
'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_dochistory_set'", 'null': 'True', 'to': u"orm['person.Person']"}),
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['person.Email']", 'symmetrical': 'False', 'through': u"orm['doc.DocHistoryAuthor']", 'blank': 'True'}),
'doc': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'history_set'", 'to': u"orm['doc.Document']"}),
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']", 'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}),
'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '1', 'blank': 'True'}),
'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'related': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.DocAlias']", 'symmetrical': 'False', 'through': u"orm['doc.RelatedDocHistory']", 'blank': 'True'}),
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_dochistory_set'", 'null': 'True', 'to': u"orm['person.Person']"}),
'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StreamName']", 'null': 'True', 'blank': 'True'}),
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['name.DocTagName']", 'null': 'True', 'blank': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
},
u'doc.dochistoryauthor': {
'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocHistoryAuthor'},
'author': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Email']"}),
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.DocHistory']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {})
},
u'doc.docreminder': {
'Meta': {'object_name': 'DocReminder'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'due': ('django.db.models.fields.DateTimeField', [], {}),
'event': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.DocEvent']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocReminderTypeName']"})
},
u'doc.document': {
'Meta': {'object_name': 'Document'},
'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_document_set'", 'null': 'True', 'to': u"orm['person.Person']"}),
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['person.Email']", 'symmetrical': 'False', 'through': u"orm['doc.DocumentAuthor']", 'blank': 'True'}),
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']", 'null': 'True', 'blank': 'True'}),
'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}),
'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'primary_key': 'True'}),
'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '1', 'blank': 'True'}),
'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_document_set'", 'null': 'True', 'to': u"orm['person.Person']"}),
'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StreamName']", 'null': 'True', 'blank': 'True'}),
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['name.DocTagName']", 'null': 'True', 'blank': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
},
u'doc.documentauthor': {
'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocumentAuthor'},
'author': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Email']"}),
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '1'})
},
u'doc.initialreviewdocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'InitialReviewDocEvent', '_ormbases': [u'doc.DocEvent']},
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
},
u'doc.lastcalldocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'LastCallDocEvent', '_ormbases': [u'doc.DocEvent']},
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
},
u'doc.newrevisiondocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'NewRevisionDocEvent', '_ormbases': [u'doc.DocEvent']},
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16'})
},
u'doc.relateddochistory': {
'Meta': {'object_name': 'RelatedDocHistory'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocRelationshipName']"}),
'source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.DocHistory']"}),
'target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reversely_related_document_history_set'", 'to': u"orm['doc.DocAlias']"})
},
u'doc.relateddocument': {
'Meta': {'object_name': 'RelatedDocument'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocRelationshipName']"}),
'source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}),
'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.DocAlias']"})
},
u'doc.state': {
'Meta': {'ordering': "['type', 'order']", 'object_name': 'State'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'next_states': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'previous_states'", 'blank': 'True', 'to': u"orm['doc.State']"}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.StateType']"}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
u'doc.statedocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'StateDocEvent', '_ormbases': [u'doc.DocEvent']},
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.State']", 'null': 'True', 'blank': 'True'}),
'state_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.StateType']"})
},
u'doc.statetype': {
'Meta': {'object_name': 'StateType'},
'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '30', 'primary_key': 'True'})
},
u'doc.telechatdocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'TelechatDocEvent', '_ormbases': [u'doc.DocEvent']},
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
'returning_item': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'telechat_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'})
},
u'doc.writeupdocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'WriteupDocEvent', '_ormbases': [u'doc.DocEvent']},
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
'text': ('django.db.models.fields.TextField', [], {'blank': 'True'})
},
u'group.group': {
'Meta': {'object_name': 'Group'},
'acronym': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '40'}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']", 'null': 'True', 'blank': 'True'}),
'charter': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'chartered_group'", 'unique': 'True', 'null': 'True', 'to': u"orm['doc.Document']"}),
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']", 'null': 'True', 'blank': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.GroupStateName']", 'null': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.GroupTypeName']", 'null': 'True'}),
'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'})
},
u'name.ballotpositionname': {
'Meta': {'ordering': "['order']", 'object_name': 'BallotPositionName'},
'blocking': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
u'name.docrelationshipname': {
'Meta': {'ordering': "['order']", 'object_name': 'DocRelationshipName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'revname': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
u'name.docremindertypename': {
'Meta': {'ordering': "['order']", 'object_name': 'DocReminderTypeName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
u'name.doctagname': {
'Meta': {'ordering': "['order']", 'object_name': 'DocTagName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
u'name.doctypename': {
'Meta': {'ordering': "['order']", 'object_name': 'DocTypeName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
u'name.groupstatename': {
'Meta': {'ordering': "['order']", 'object_name': 'GroupStateName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
u'name.grouptypename': {
'Meta': {'ordering': "['order']", 'object_name': 'GroupTypeName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
u'name.intendedstdlevelname': {
'Meta': {'ordering': "['order']", 'object_name': 'IntendedStdLevelName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
u'name.stdlevelname': {
'Meta': {'ordering': "['order']", 'object_name': 'StdLevelName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
u'name.streamname': {
'Meta': {'ordering': "['order']", 'object_name': 'StreamName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
u'person.email': {
'Meta': {'object_name': 'Email'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'address': ('django.db.models.fields.CharField', [], {'max_length': '64', 'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']", 'null': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
},
u'person.person': {
'Meta': {'object_name': 'Person'},
'address': ('django.db.models.fields.TextField', [], {'max_length': '255', 'blank': 'True'}),
'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'ascii': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'ascii_short': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'})
}
}
complete_apps = ['doc']
symmetrical = True

View file

@ -426,7 +426,7 @@ class Document(DocumentInfo):
# Expired/Withdrawn by Submitter/IETF
return state.name
else:
return state.name
return state.name
def ipr(self):
"""Returns the IPR disclosures against this document (as a queryset over IprDocAlias)."""

View file

@ -143,44 +143,38 @@ def state_age_colored(doc):
if not doc.get_state_slug() in ["active", "rfc"]:
# Don't show anything for expired/withdrawn/replaced drafts
return ""
main_state = doc.get_state_slug('draft-iesg')
if not main_state:
iesg_state = doc.get_state_slug('draft-iesg')
if not iesg_state:
return ""
if main_state in ["dead", "watching", "pub"]:
if iesg_state in ["dead", "watching", "pub"]:
return ""
try:
state_date = doc.docevent_set.filter(
Q(desc__istartswith="Draft Added by ")|
Q(desc__istartswith="Draft Added in state ")|
Q(desc__istartswith="Draft added in state ")|
Q(desc__istartswith="State changed to ")|
Q(desc__istartswith="State Changes to ")|
Q(desc__istartswith="Sub state has been changed to ")|
Q(desc__istartswith="State has been changed to ")|
Q(desc__istartswith="IESG process started in state")
).order_by('-time')[0].time.date()
Q(type="started_iesg_process")|
Q(type="changed_state", statedocevent__state_type="draft-iesg")
).order_by('-time')[0].time.date()
except IndexError:
state_date = datetime.date(1990,1,1)
days = (datetime.date.today() - state_date).days
# loosely based on
# http://trac.tools.ietf.org/group/iesg/trac/wiki/PublishPath
if main_state == "lc":
if iesg_state == "lc":
goal1 = 30
goal2 = 30
elif main_state == "rfcqueue":
elif iesg_state == "rfcqueue":
goal1 = 60
goal2 = 120
elif main_state in ["lc-req", "ann"]:
elif iesg_state in ["lc-req", "ann"]:
goal1 = 4
goal2 = 7
elif 'need-rev' in [x.slug for x in doc.tags.all()]:
goal1 = 14
goal2 = 28
elif main_state == "pub-req":
elif iesg_state == "pub-req":
goal1 = 7
goal2 = 14
elif main_state == "ad-eval":
elif iesg_state == "ad-eval":
goal1 = 14
goal2 = 28
else:

View file

@ -30,6 +30,29 @@ class EditCharterTests(TestCase):
def tearDown(self):
shutil.rmtree(self.charter_dir)
def test_startstop_process(self):
make_test_data()
group = Group.objects.get(acronym="mars")
charter = group.charter
for option in ("recharter", "abandon"):
self.client.logout()
url = urlreverse('charter_startstop_process', kwargs=dict(name=charter.name, option=option))
login_testing_unauthorized(self, "secretary", url)
# normal get
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
# post
r = self.client.post(url, dict(message="test message"))
self.assertEqual(r.status_code, 302)
if option == "abandon":
self.assertTrue("abandoned" in charter.latest_event(type="changed_document").desc.lower())
else:
self.assertTrue("state changed" in charter.latest_event(type="changed_state").desc.lower())
def test_change_state(self):
make_test_data()
@ -71,7 +94,7 @@ class EditCharterTests(TestCase):
def find_event(t):
return [e for e in charter.docevent_set.all()[:events_now - events_before] if e.type == t]
self.assertTrue("state changed" in find_event("changed_document")[0].desc.lower())
self.assertTrue("state changed" in find_event("changed_state")[0].desc.lower())
if slug in ("intrev", "iesgrev"):
self.assertTrue(find_event("created_ballot"))
@ -88,6 +111,10 @@ class EditCharterTests(TestCase):
url = urlreverse('charter_telechat_date', kwargs=dict(name=charter.name))
login_testing_unauthorized(self, "secretary", url)
# get
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
# add to telechat
self.assertTrue(not charter.latest_event(TelechatDocEvent, "scheduled_for_telechat"))
telechat_date = TelechatDate.objects.active()[0].date
@ -122,6 +149,10 @@ class EditCharterTests(TestCase):
url = urlreverse('charter_edit_notify', kwargs=dict(name=charter.name))
login_testing_unauthorized(self, "secretary", url)
# get
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
# post
self.assertTrue(not charter.notify)
r = self.client.post(url, dict(notify="someone@example.com, someoneelse@example.com"))
@ -195,15 +226,82 @@ class EditCharterTests(TestCase):
self.assertEqual(f.read(),
"Windows line\nMac line\nUnix line\n" + utf_8_snippet)
class ApproveCharterTests(TestCase):
def setUp(self):
self.charter_dir = os.path.abspath("tmp-charter-dir")
os.mkdir(self.charter_dir)
settings.CHARTER_PATH = self.charter_dir
def test_edit_announcement_text(self):
draft = make_test_data()
charter = draft.group.charter
def tearDown(self):
shutil.rmtree(self.charter_dir)
for ann in ("action", "review"):
url = urlreverse('ietf.doc.views_charter.announcement_text', kwargs=dict(name=charter.name, ann=ann))
self.client.logout()
login_testing_unauthorized(self, "secretary", url)
# normal get
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
self.assertEqual(len(q('textarea[name=announcement_text]')), 1)
# as Secretariat, we can send
if ann == "review":
mailbox_before = len(outbox)
by = Person.objects.get(user__username="secretary")
r = self.client.post(url, dict(
announcement_text=default_review_text(draft.group, charter, by).text,
send_text="1"))
self.assertEqual(len(outbox), mailbox_before + 1)
# save
r = self.client.post(url, dict(
announcement_text="This is a simple test.",
save_text="1"))
self.assertEqual(r.status_code, 302)
self.assertTrue("This is a simple test" in charter.latest_event(WriteupDocEvent, type="changed_%s_announcement" % ann).text)
# test regenerate
r = self.client.post(url, dict(
announcement_text="This is a simple test.",
regenerate_text="1"))
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
self.assertTrue(draft.group.name in charter.latest_event(WriteupDocEvent, type="changed_%s_announcement" % ann).text)
def test_edit_ballot_writeupnotes(self):
draft = make_test_data()
charter = draft.group.charter
by = Person.objects.get(user__username="secretary")
BallotDocEvent.objects.create(
type="created_ballot",
ballot_type=BallotType.objects.get(doc_type="charter", slug="approve"),
by=by,
doc=charter,
desc="Created ballot",
)
url = urlreverse('ietf.doc.views_charter.ballot_writeupnotes', kwargs=dict(name=charter.name))
login_testing_unauthorized(self, "secretary", url)
default_action_text(draft.group, charter, by)
# normal get
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
self.assertEqual(len(q('textarea[name=ballot_writeup]')), 1)
# save
r = self.client.post(url, dict(
ballot_writeup="This is a simple test.",
save_ballot_writeup="1"))
self.assertEqual(r.status_code, 200)
self.assertTrue("This is a simple test" in charter.latest_event(WriteupDocEvent, type="changed_ballot_writeup_text").text)
# send
mailbox_before = len(outbox)
r = self.client.post(url, dict(
ballot_writeup="This is a simple test.",
send_ballot="1"))
self.assertEqual(len(outbox), mailbox_before + 1)
def test_approve(self):
make_test_data()
@ -278,3 +376,23 @@ class ApproveCharterTests(TestCase):
self.assertEqual(group.groupmilestone_set.filter(state="active").count(), 2)
self.assertEqual(group.groupmilestone_set.filter(state="active", desc=m1.desc).count(), 1)
self.assertEqual(group.groupmilestone_set.filter(state="active", desc=m4.desc).count(), 1)
def test_charter_with_milestones(self):
draft = make_test_data()
charter = draft.group.charter
NewRevisionDocEvent.objects.create(doc=charter,
type="new_revision",
rev=charter.rev,
by=Person.objects.get(name="(System)"))
m = GroupMilestone.objects.create(group=draft.group,
state_id="active",
desc="Test milestone",
due=datetime.date.today(),
resolved="")
url = urlreverse('charter_with_milestones_txt', kwargs=dict(name=charter.name, rev=charter.rev))
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
self.assertTrue(m.desc in r.content)

View file

@ -67,7 +67,7 @@ class ChangeStateTests(TestCase):
self.assertTrue(draft.tags.filter(slug="point"))
self.assertEqual(draft.docevent_set.count(), events_before + 2)
self.assertTrue("Test comment" in draft.docevent_set.all()[0].desc)
self.assertTrue("State changed" in draft.docevent_set.all()[1].desc)
self.assertTrue("IESG state changed" in draft.docevent_set.all()[1].desc)
self.assertEqual(len(outbox), mailbox_before + 2)
self.assertTrue("State Update Notice" in outbox[-2]['Subject'])
self.assertTrue(draft.name in outbox[-1]['Subject'])
@ -232,6 +232,10 @@ class EditInfoTests(TestCase):
note="",
)
# get
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
# add to telechat
self.assertTrue(not draft.latest_event(TelechatDocEvent, type="scheduled_for_telechat"))
data["telechat_date"] = TelechatDate.objects.active()[0].date.isoformat()
@ -347,6 +351,11 @@ class EditInfoTests(TestCase):
url = urlreverse('doc_edit_consensus', kwargs=dict(name=draft.name))
login_testing_unauthorized(self, "secretary", url)
# get
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
# post
self.assertTrue(not draft.latest_event(ConsensusDocEvent, type="changed_consensus"))
r = self.client.post(url, dict(consensus="Yes"))
self.assertEqual(r.status_code, 302)

View file

@ -11,7 +11,6 @@ urlpatterns = patterns('',
url(r'^(?P<ann>action|review)/$', "ietf.doc.views_charter.announcement_text", name="charter_edit_announcement"),
url(r'^ballotwriteupnotes/$', "ietf.doc.views_charter.ballot_writeupnotes"),
url(r'^approve/$', "ietf.doc.views_charter.approve", name='charter_approve'),
url(r'^submit/$', "ietf.doc.views_charter.submit", name='charter_submit'),
url(r'^submit/(?P<option>initcharter|recharter)/$', "ietf.doc.views_charter.submit", name='charter_submit'), # shouldn't be here
url(r'^submit/(?:(?P<option>initcharter|recharter)/)?$', "ietf.doc.views_charter.submit", name='charter_submit'),
url(r'^withmilestones-(?P<rev>[0-9-]+).txt$', "ietf.doc.views_charter.charter_with_milestones_txt", name='charter_with_milestones_txt'),
)

View file

@ -220,25 +220,24 @@ def get_document_content(key, filename, split=True, markup=True):
else:
return raw_content
def log_state_changed(request, doc, by, new_description, old_description):
e = DocEvent(doc=doc, by=by)
e.type = "changed_document"
e.desc = u"State changed to <b>%s</b> from %s" % (new_description, old_description)
e.save()
return e
def add_state_change_event(doc, by, prev_state, new_state, timestamp=None):
def add_state_change_event(doc, by, prev_state, new_state, prev_tags=[], new_tags=[], timestamp=None):
"""Add doc event to explain that state change just happened."""
if prev_state == new_state:
if prev_state and new_state:
assert prev_state.type_id == new_state.type_id
if prev_state == new_state and set(prev_tags) == set(new_tags):
return None
def tags_suffix(tags):
return (u"::" + u"::".join(t.name for t in tags)) if tags else u""
e = StateDocEvent(doc=doc, by=by)
e.type = "changed_state"
e.state_type = (prev_state or new_state).type
e.state = new_state
e.desc = "%s changed to <b>%s</b>" % (e.state_type.label, new_state.name)
e.desc = "%s changed to <b>%s</b>" % (e.state_type.label, new_state.name + tags_suffix(new_tags))
if prev_state:
e.desc += " from %s" % prev_state.name
e.desc += " from %s" % (prev_state.name + tags_suffix(prev_tags))
if timestamp:
e.time = timestamp
e.save()

View file

@ -13,15 +13,6 @@ from ietf.doc.models import DocEvent, NewRevisionDocEvent, WriteupDocEvent, Ball
from ietf.utils.history import find_history_active_at
def log_state_changed(request, doc, by, prev_state):
e = DocEvent(doc=doc, by=by)
e.type = "changed_document"
e.desc = u"State changed to <b>%s</b> from %s" % (
doc.get_state().name,
prev_state.name if prev_state else "None")
e.save()
return e
def next_revision(rev):
if rev == "":
return "00-00"
@ -140,14 +131,14 @@ def generate_ballot_writeup(request, doc):
return e
def default_action_text(group, charter, user):
def default_action_text(group, charter, by):
if next_approved_revision(group.charter.rev) == "01":
action = "Formed"
else:
action = "Rechartered"
e = WriteupDocEvent(doc=charter, by=user)
e.by = user
e = WriteupDocEvent(doc=charter, by=by)
e.by = by
e.type = "changed_action_announcement"
e.desc = "%s action text was changed" % group.type.name
e.text = render_to_string("doc/charter/action_text.txt",
@ -165,9 +156,9 @@ def default_action_text(group, charter, user):
e.save()
return e
def default_review_text(group, charter, user):
e = WriteupDocEvent(doc=charter, by=user)
e.by = user
def default_review_text(group, charter, by):
e = WriteupDocEvent(doc=charter, by=by)
e.by = by
e.type = "changed_review_announcement"
e.desc = "%s review text was changed" % group.type.name
e.text = render_to_string("doc/charter/review_text.txt",

View file

@ -49,17 +49,21 @@ def do_undefer_ballot(request, doc):
telechat_date = TelechatDate.objects.active().order_by("date")[0].date
save_document_in_history(doc)
prev_state = doc.friendly_state()
if doc.type_id == 'draft':
doc.set_state(State.objects.get(used=True, type="draft-iesg", slug='iesg-eva'))
prev_tag = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
prev_tag = prev_tag[0] if prev_tag else None
if prev_tag:
doc.tags.remove(prev_tag)
elif doc.type_id == 'conflrev':
doc.set_state(State.objects.get(used=True, type='conflrev',slug='iesgeval'))
new_state = doc.get_state()
prev_tags = new_tags = []
e = log_state_changed(request, doc, login, doc.friendly_state(), prev_state)
if doc.type_id == 'draft':
new_state = State.objects.get(used=True, type="draft-iesg", slug='iesg-eva')
prev_tags = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
elif doc.type_id == 'conflrev':
new_state = State.objects.get(used=True, type='conflrev',slug='iesgeval')
prev_state = doc.get_state(new_state.type_id if new_state else None)
doc.set_state(new_state)
doc.tags.remove(*prev_tags)
e = add_state_change_event(doc, login, prev_state, new_state, prev_tags=prev_tags, new_tags=new_tags)
doc.time = e.time
doc.save()
@ -353,17 +357,21 @@ def defer_ballot(request, name):
if request.method == 'POST':
save_document_in_history(doc)
prev_state = doc.friendly_state()
if doc.type_id == 'draft':
doc.set_state(State.objects.get(used=True, type="draft-iesg", slug='defer'))
prev_tag = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
prev_tag = prev_tag[0] if prev_tag else None
if prev_tag:
doc.tags.remove(prev_tag)
elif doc.type_id == 'conflrev':
doc.set_state(State.objects.get(used=True, type='conflrev', slug='defer'))
new_state = doc.get_state()
prev_tags = new_tags = []
e = log_state_changed(request, doc, login, doc.friendly_state(), prev_state)
if doc.type_id == 'draft':
new_state = State.objects.get(used=True, type="draft-iesg", slug='defer')
prev_tags = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
elif doc.type_id == 'conflrev':
new_state = State.objects.get(used=True, type='conflrev', slug='defer')
prev_state = doc.get_state(new_state.type_id if new_state else None)
doc.set_state(new_state)
doc.tags.remove(*prev_tags)
e = add_state_change_event(doc, login, prev_state, new_state, prev_tags=prev_tags, new_tags=new_tags)
doc.time = e.time
doc.save()
@ -445,16 +453,16 @@ def lastcalltext(request, name):
if "send_last_call_request" in request.POST:
save_document_in_history(doc)
prev_state = doc.friendly_state()
doc.set_state(State.objects.get(used=True, type="draft-iesg", slug='lc-req'))
prev_state = doc.get_state("draft-iesg")
new_state = State.objects.get(used=True, type="draft-iesg", slug='lc-req')
prev_tag = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
prev_tag = prev_tag[0] if prev_tag else None
if prev_tag:
doc.tags.remove(prev_tag)
prev_tags = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
doc.set_state(new_state)
doc.tags.remove(*prev_tags)
e = add_state_change_event(doc, login, prev_state, new_state, prev_tags=prev_tags, new_tags=[])
e = log_state_changed(request, doc, login, doc.friendly_state(), prev_state)
doc.time = e.time
doc.save()
@ -664,8 +672,9 @@ def approve_ballot(request, name):
else:
new_state = State.objects.get(used=True, type="draft-iesg", slug="ann")
prev_friendly_state = doc.friendly_state()
prev_state = doc.get_state("draft-iesg")
prev_tags = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
if new_state.slug == "ann" and new_state.slug != prev_state.slug and not request.REQUEST.get("skiprfceditorpost"):
# start by notifying the RFC Editor
import ietf.sync.rfceditor
@ -677,18 +686,14 @@ def approve_ballot(request, name):
error=error),
context_instance=RequestContext(request))
# fixup document
close_open_ballots(doc, login)
save_document_in_history(doc)
doc.set_state(new_state)
prev_tag = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
prev_tag = prev_tag[0] if prev_tag else None
if prev_tag:
doc.tags.remove(prev_tag)
doc.tags.remove(*prev_tags)
# fixup document
close_open_ballots(doc, login)
e = DocEvent(doc=doc, by=login)
if action == "do_not_publish":
e.type = "iesg_disapproved"
@ -701,8 +706,8 @@ def approve_ballot(request, name):
change_description = e.desc + " and state has been changed to %s" % doc.get_state("draft-iesg").name
e = log_state_changed(request, doc, login, doc.friendly_state(), prev_friendly_state)
e = add_state_change_event(doc, login, prev_state, new_state, prev_tags=prev_tags, new_tags=[])
doc.time = e.time
doc.save()
@ -766,26 +771,27 @@ def make_last_call(request, name):
save_document_in_history(doc)
prev_state = doc.get_state("draft-iesg")
new_state = doc.get_state()
prev_tags = new_tags = []
if doc.type.slug == 'draft':
doc.set_state(State.objects.get(used=True, type="draft-iesg", slug='lc'))
prev_tag = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
prev_tag = prev_tag[0] if prev_tag else None
if prev_tag:
doc.tags.remove(prev_tag)
e = log_state_changed(request, doc, login, doc.friendly_state(), prev_state)
change_description = "Last call has been made for %s and state has been changed to %s" % (doc.name, doc.get_state("draft-iesg").name)
new_state = State.objects.get(used=True, type="draft-iesg", slug='lc')
prev_tags = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
elif doc.type.slug == 'statchg':
doc.set_state(State.objects.get(used=True, type="statchg", slug='in-lc'))
e = log_state_changed(request, doc, login, doc.friendly_state(), prev_state)
change_description = "Last call has been made for %s and state has been changed to %s" % (doc.name, doc.friendly_state())
new_state = State.objects.get(used=True, type="statchg", slug='in-lc')
prev_state = doc.get_state(new_state.type_id)
doc.set_state(new_state)
doc.tags.remove(*prev_tags)
e = add_state_change_event(doc, login, prev_state, new_state, prev_tags=prev_tags, new_tags=new_tags)
doc.time = e.time
doc.save()
change_description = "Last call has been made for %s and state has been changed to %s" % (doc.name, new_state.name)
email_state_changed(request, doc, change_description)
email_ad(request, doc, doc.ad, login, change_description)

View file

@ -100,12 +100,13 @@ def change_state(request, name, option=None):
# Charter state changed
save_document_in_history(charter)
prev = charter.get_state()
charter.set_state(charter_state)
prev_state = charter.get_state()
new_state = charter_state
charter.set_state(new_state)
charter.rev = charter_rev
if option != "abandon":
log_state_changed(request, charter, login, prev)
add_state_change_event(charter, login, prev_state, new_state)
else:
# kill hanging ballots
close_open_ballots(charter, login)
@ -502,7 +503,7 @@ def ballot_writeupnotes(request, name):
ballot = charter.latest_event(BallotDocEvent, type="created_ballot")
if not ballot:
raise Http404()
raise Http404
login = request.user.person
@ -528,6 +529,8 @@ def ballot_writeupnotes(request, name):
e.text = t
e.save()
existing = e
if "send_ballot" in request.POST and approval:
if has_role(request.user, "Area Director") and not charter.latest_event(BallotPositionDocEvent, type="changed_ballot_position", ad=login, ballot=ballot):
# sending the ballot counts as a yes
@ -551,7 +554,6 @@ def ballot_writeupnotes(request, name):
dict(doc=charter,
),
context_instance=RequestContext(request))
return render_to_response('doc/charter/ballot_writeupnotes.html',
dict(charter=charter,
@ -611,7 +613,7 @@ def approve(request, name):
change_description += " and %s state has been changed to %s" % (group.type.name, new_state.name)
e = log_state_changed(request, charter, login, prev_charter_state)
e = add_state_change_event(charter, login, prev_charter_state, new_charter_state)
# according to spec, 00-02 becomes 01, so copy file and record new revision
try:

View file

@ -8,8 +8,7 @@ from django.template import RequestContext
from django.template.loader import render_to_string
from django.conf import settings
from ietf.doc.utils import log_state_changed, update_telechat
from ietf.doc.utils import add_state_change_event, update_telechat
from ietf.doc.models import save_document_in_history
from ietf.doc.utils import create_ballot_if_not_open, close_open_ballots, get_document_content
from ietf.ietfauth.utils import has_role, role_required
@ -41,7 +40,7 @@ def change_state(request, name, option=None):
form = ChangeStateForm(request.POST)
if form.is_valid():
clean = form.cleaned_data
review_state = clean['review_state']
new_state = clean['review_state']
comment = clean['comment'].rstrip()
if comment:
@ -49,19 +48,17 @@ def change_state(request, name, option=None):
c.desc = comment
c.save()
if review_state != review.get_state():
prev_state = review.get_state()
if new_state != prev_state:
save_document_in_history(review)
old_description = review.friendly_state()
review.set_state(review_state)
new_description = review.friendly_state()
log_state_changed(request, review, login, new_description, old_description)
review.set_state(new_state)
add_state_change_event(review, login, prev_state, new_state)
review.time = datetime.datetime.now()
review.save()
if review_state.slug == "iesgeval":
if new_state.slug == "iesgeval":
create_ballot_if_not_open(review, login, "conflrev")
ballot = review.latest_event(BallotDocEvent, type="created_ballot")
if has_role(request.user, "Area Director") and not review.latest_event(BallotPositionDocEvent, ad=login, ballot=ballot, type="changed_ballot_position"):
@ -307,15 +304,14 @@ def approve(request, name):
form = AnnouncementForm(request.POST)
if form.is_valid():
prev_state = review.get_state()
new_state_slug = 'appr-reqnopub-sent' if review.get_state('conflrev').slug=='appr-reqnopub-pend' else 'appr-noprob-sent'
new_review_state = State.objects.get(used=True, type="conflrev", slug=new_state_slug)
new_state_slug = 'appr-reqnopub-sent' if prev_state.slug == 'appr-reqnopub-pend' else 'appr-noprob-sent'
new_state = State.objects.get(used=True, type="conflrev", slug=new_state_slug)
save_document_in_history(review)
old_description = review.friendly_state()
review.set_state(new_review_state)
new_description = review.friendly_state()
log_state_changed(request, review, login, new_description, old_description)
review.set_state(new_state)
add_state_change_event(review, login, prev_state, new_state)
close_open_ballots(review, login)

View file

@ -581,7 +581,7 @@ def document_writeup(request, name):
))
if not sections:
raise Http404()
raise Http404
return render_to_response("doc/document_writeup.html",
dict(doc=doc,

View file

@ -57,7 +57,7 @@ class ChangeStateForm(forms.Form):
@role_required('Area Director','Secretariat')
def change_state(request, name):
"""Change state of Internet Draft, notifying parties as necessary
"""Change IESG state of Internet Draft, notifying parties as necessary
and logging the change as a comment."""
doc = get_object_or_404(Document, docalias__name=name)
if (not doc.latest_event(type="started_iesg_process")) or doc.get_state_slug() == "expired":
@ -69,30 +69,28 @@ def change_state(request, name):
form = ChangeStateForm(request.POST)
form.docname=name
if form.is_valid():
next_state = form.cleaned_data['state']
new_state = form.cleaned_data['state']
prev_state = doc.get_state("draft-iesg")
prev_friendly_state = doc.friendly_state()
tag = form.cleaned_data['substate']
comment = form.cleaned_data['comment'].strip()
# tag handling is a bit awkward since the UI still works
# as if IESG tags are a substate
prev_tag = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
prev_tag = prev_tag[0] if prev_tag else None
if next_state != prev_state or tag != prev_tag:
prev_tags = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
new_tags = [tag] if tag else []
if new_state != prev_state or set(new_tags) != set(prev_tags):
save_document_in_history(doc)
doc.set_state(next_state)
doc.set_state(new_state)
if prev_tag:
doc.tags.remove(prev_tag)
doc.tags.remove(*prev_tags)
doc.tags.add(*new_tags)
if tag:
doc.tags.add(tag)
e = add_state_change_event(doc, login, prev_state, new_state,
prev_tags=prev_tags, new_tags=new_tags)
e = log_state_changed(request, doc, login, doc.friendly_state(), prev_friendly_state)
msg = e.desc
if comment:
c = DocEvent(type="added_comment")
@ -101,23 +99,23 @@ def change_state(request, name):
c.desc = comment
c.save()
e.desc += "<br>" + comment
msg += "\n" + comment
doc.time = e.time
doc.save()
email_state_changed(request, doc, e.desc)
email_ad(request, doc, doc.ad, login, e.desc)
email_state_changed(request, doc, msg)
email_ad(request, doc, doc.ad, login, msg)
if prev_state and prev_state.slug in ("ann", "rfcqueue") and next_state.slug not in ("rfcqueue", "pub"):
email_pulled_from_rfc_queue(request, doc, comment, prev_state, next_state)
if prev_state and prev_state.slug in ("ann", "rfcqueue") and new_state.slug not in ("rfcqueue", "pub"):
email_pulled_from_rfc_queue(request, doc, comment, prev_state, new_state)
if next_state.slug in ("iesg-eva", "lc"):
if new_state.slug in ("iesg-eva", "lc"):
if not doc.get_state_slug("draft-iana-review"):
doc.set_state(State.objects.get(used=True, type="draft-iana-review", slug="need-rev"))
if next_state.slug == "lc-req":
if new_state.slug == "lc-req":
request_last_call(request, doc)
return render_to_response('doc/draft/last_call_requested.html',
@ -179,14 +177,14 @@ def change_iana_state(request, name, state_type):
if request.method == 'POST':
form = ChangeIanaStateForm(state_type, request.POST)
if form.is_valid():
next_state = form.cleaned_data['state']
new_state = form.cleaned_data['state']
if next_state != prev_state:
if new_state != prev_state:
save_document_in_history(doc)
doc.set_state(next_state)
doc.set_state(new_state)
e = add_state_change_event(doc, request.user.person, prev_state, next_state)
e = add_state_change_event(doc, request.user.person, prev_state, new_state)
doc.time = e.time
doc.save()
@ -1220,7 +1218,7 @@ def request_publication(request, name):
e.save()
# change state
prev_state = doc.get_state(next_state.type)
prev_state = doc.get_state(next_state.type_id)
if next_state != prev_state:
doc.set_state(next_state)
e = add_state_change_event(doc, request.user.person, prev_state, next_state)
@ -1322,7 +1320,7 @@ def adopt_draft(request, name):
new_state = State.objects.get(slug=adopt_state_slug, type="draft-stream-%s" % doc.stream_id, used=True)
if new_state != prev_state:
doc.set_state(new_state)
e = add_state_change_event(doc, by, prev_state, new_state, doc.time)
e = add_state_change_event(doc, by, prev_state, new_state, timestamp=doc.time)
due_date = None
if form.cleaned_data["weeks"] != None:
@ -1423,7 +1421,7 @@ def change_stream_state(request, name, state_type):
new_state = form.cleaned_data["new_state"]
if new_state != prev_state:
doc.set_state(new_state)
e = add_state_change_event(doc, by, prev_state, new_state, doc.time)
e = add_state_change_event(doc, by, prev_state, new_state, timestamp=doc.time)
due_date = None
if form.cleaned_data["weeks"] != None:

View file

@ -8,7 +8,7 @@ from django.template import RequestContext
from django.template.loader import render_to_string
from django.conf import settings
from ietf.doc.utils import log_state_changed, update_telechat
from ietf.doc.utils import add_state_change_event, update_telechat
from ietf.doc.models import save_document_in_history
from ietf.doc.utils import create_ballot_if_not_open, close_open_ballots, get_document_content
@ -51,14 +51,12 @@ def change_state(request, name, option=None):
c.desc = comment
c.save()
if new_state != status_change.get_state():
prev_state = status_change.get_state()
if new_state != prev_state:
save_document_in_history(status_change)
old_description = status_change.friendly_state()
status_change.set_state(new_state)
new_description = status_change.friendly_state()
log_state_changed(request, status_change, login, new_description, old_description)
add_state_change_event(status_change, login, prev_state, new_state)
status_change.time = datetime.datetime.now()
status_change.save()
@ -327,10 +325,11 @@ def approve(request, name):
save_document_in_history(status_change)
old_description = status_change.friendly_state()
status_change.set_state(State.objects.get(type='statchg', slug='appr-sent'))
new_description = status_change.friendly_state()
log_state_changed(request, status_change, login, new_description, old_description)
prev_state = status_change.get_state()
new_state = State.objects.get(type='statchg', slug='appr-sent')
status_change.set_state(new_state)
add_state_change_event(status_change, login, prev_state, new_state)
close_open_ballots(status_change, login)
@ -689,11 +688,11 @@ def last_call(request, name):
if "send_last_call_request" in request.POST:
save_document_in_history(status_change)
old_description = status_change.friendly_state()
status_change.set_state(State.objects.get(type='statchg', slug='lc-req'))
new_description = status_change.friendly_state()
prev_state = status_change.get_state()
new_state = State.objects.get(type='statchg', slug='lc-req')
e = log_state_changed(request, status_change, login, new_description, old_description)
status_change.set_state(new_state)
e = add_state_change_event(status_change, login, prev_state, new_state)
status_change.time = e.time
status_change.save()

View file

@ -56,4 +56,9 @@ class UnicodeNfkcNormalization(object):
request.META["PATH_INFO"] = unicodedata.normalize('NFKC', request.META["PATH_INFO"])
request.path_info = unicodedata.normalize('NFKC', request.path_info)
return None
class FillInRemoteUserIfLoggedInMiddleware(object):
def process_request(self, request):
if request.user.is_authenticated() and "REMOTE_USER" not in request.META:
request.META["REMOTE_USER"] = request.user.username

View file

@ -8,7 +8,7 @@ from django.shortcuts import render_to_response, get_object_or_404, redirect
from django.template import RequestContext
from ietf.doc.models import DocEvent, Document, BallotDocEvent, BallotPositionDocEvent, TelechatDocEvent, WriteupDocEvent, save_document_in_history
from ietf.doc.utils import get_document_content, log_state_changed
from ietf.doc.utils import get_document_content, add_state_change_event
from ietf.group.models import Group
from ietf.name.models import BallotPositionName
from ietf.person.models import Person
@ -237,38 +237,35 @@ def doc_detail(request, date, name):
formset = BallotFormset(initial=initial_ballot)
state_form = ChangeStateForm(request.POST, initial=initial_state)
if state_form.is_valid():
state = state_form.cleaned_data['state']
prev_state = doc.get_state(state_type)
new_state = state_form.cleaned_data['state']
tag = state_form.cleaned_data['substate']
prev = doc.get_state(state_type)
# tag handling is a bit awkward since the UI still works
# as if IESG tags are a substate
prev_tag = doc.tags.filter(slug__in=(TELECHAT_TAGS))
prev_tag = prev_tag[0] if prev_tag else None
prev_tags = doc.tags.filter(slug__in=TELECHAT_TAGS)
new_tags = [tag] if tag else []
#if state != prev or tag != prev_tag:
if state_form.changed_data:
save_document_in_history(doc)
old_description = doc.friendly_state()
if 'state' in state_form.changed_data:
doc.set_state(state)
doc.set_state(new_state)
if 'substate' in state_form.changed_data:
if prev_tag:
doc.tags.remove(prev_tag)
if tag:
doc.tags.add(tag)
doc.tags.remove(*prev_tags)
doc.tags.add(*new_tags)
new_description = doc.friendly_state()
e = log_state_changed(request, doc, login, new_description, old_description)
e = add_state_change_event(doc, login, prev_state, new_state,
prev_tags=prev_tags, new_tags=new_tags)
doc.time = e.time
doc.save()
email_state_changed(request, doc, e.desc)
email_ad(request, doc, doc.ad, login, e.desc)
if state.slug == "lc-req":
if new_state.slug == "lc-req":
request_last_call(request, doc)
messages.success(request,'Document state updated')

View file

@ -119,6 +119,7 @@ MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'ietf.middleware.FillInRemoteUserIfLoggedInMiddleware',
'django.contrib.auth.middleware.RemoteUserMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.http.ConditionalGetMiddleware',

View file

@ -187,7 +187,7 @@ def update_history_with_changes(changes, send_email=True):
# that we assume these changes are cronologically
# applied
prev_state = doc.get_state(state_type)
e = add_state_change_event(doc, system, prev_state, state, timestamp)
e = add_state_change_event(doc, system, prev_state, state, timestamp=timestamp)
if e:
# for logging purposes

View file

@ -10,6 +10,7 @@ from ietf.doc.models import *
from ietf.person.models import *
from ietf.name.models import *
from ietf.doc.utils import add_state_change_event
from ietf.doc.expire import move_draft_files_to_archive
#QUEUE_URL = "http://www.rfc-editor.org/queue2.xml"
#INDEX_URL = "http://www.rfc-editor.org/rfc/rfc-index.xml"
@ -18,10 +19,6 @@ from ietf.doc.utils import add_state_change_event
MIN_QUEUE_RESULTS = 10
MIN_INDEX_RESULTS = 5000
# Python < 2.7 doesn't have the total_seconds method on datetime.timedelta.
def total_seconds(td):
return (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6
def get_child_text(parent_node, tag_name):
for node in parent_node.childNodes:
if node.nodeType == Node.ELEMENT_NODE and node.localName == tag_name:
@ -367,6 +364,7 @@ def update_docs_from_rfc_index(data, skip_older_than_date=None):
if doc.get_state_slug() != "rfc":
changed_states.append(State.objects.get(used=True, type="draft", slug="rfc"))
move_draft_files_to_archive(doc, doc.rev)
if doc.stream != stream_mapping[stream]:
changed_attributes["stream"] = stream_mapping[stream]
@ -387,7 +385,7 @@ def update_docs_from_rfc_index(data, skip_older_than_date=None):
if abs(d - synthesized) > datetime.timedelta(days=60):
synthesized = d
else:
direction = -1 if total_seconds(d - synthesized) < 0 else +1
direction = -1 if (d - synthesized).total_seconds() < 0 else +1
while synthesized.month != d.month or synthesized.year != d.year:
synthesized += datetime.timedelta(days=direction)
e.time = synthesized

View file

@ -1,4 +1,5 @@
import unittest, re, json, datetime, StringIO
import unittest, re, json, datetime, StringIO, shutil
from django.conf import settings
from django.core.urlresolvers import reverse as urlreverse
@ -185,6 +186,24 @@ ICANN
class RFCSyncTests(TestCase):
def setUp(self):
self.id_dir = os.path.abspath("tmp-id-dir")
self.archive_dir = os.path.abspath("tmp-id-archive")
if not os.path.exists(self.id_dir):
os.mkdir(self.id_dir)
if not os.path.exists(self.archive_dir):
os.mkdir(self.archive_dir)
settings.INTERNET_DRAFT_PATH = self.id_dir
settings.INTERNET_DRAFT_ARCHIVE_DIR = self.archive_dir
def tearDown(self):
shutil.rmtree(self.id_dir)
shutil.rmtree(self.archive_dir)
def write_draft_file(self, name, size):
with open(os.path.join(self.id_dir, name), 'w') as f:
f.write("a" * size)
def test_rfc_index(self):
doc = make_test_data()
doc.set_state(State.objects.get(used=True, type="draft-iesg", slug="rfcqueue"))
@ -285,6 +304,8 @@ class RFCSyncTests(TestCase):
mailbox_before = len(outbox)
draft_filename = "%s-%s.txt" % (doc.name, doc.rev)
self.write_draft_file(draft_filename, 5000)
changed = rfceditor.update_docs_from_rfc_index(data, today - datetime.timedelta(days=30))
@ -305,6 +326,8 @@ class RFCSyncTests(TestCase):
self.assertEqual(doc.get_state_slug("draft-stream-ise"), "pub")
self.assertEqual(doc.std_level_id, "ps")
self.assertEqual(doc.pages, 42)
self.assertTrue(not os.path.exists(os.path.join(self.id_dir, draft_filename)))
self.assertTrue(os.path.exists(os.path.join(self.archive_dir, draft_filename)))
# make sure we can apply it again with no changes
changed = rfceditor.update_docs_from_rfc_index(data, today - datetime.timedelta(days=30))

View file

@ -17,9 +17,9 @@ form #id_announcement_text {
{{ announcement_text_form.announcement_text }}
<div class="actions">
<a href="{{ back_url }}">Back</a>
<input type="submit" name="regenerate_text" value="Regenerate" />
<input type="submit" name="save_text" value="Save" />
<a class="button" href="{{ back_url }}">Cancel</a>
<input class="button" type="submit" name="regenerate_text" value="Regenerate" />
<input class="button" type="submit" name="save_text" value="Save" />
</div>
{% load ietf_filters %}

View file

@ -20,9 +20,9 @@ form #id_ballot_writeup {
{{ ballot_writeup_form.ballot_writeup }}
<div class="actions">
<a href="{% url "doc_writeup" name=charter.name %}">Back</a>
<input type="submit" name="save_ballot_writeup" value="Save Ballot Writeup" />
<input style="margin-left: 8px" type="submit" name="send_ballot" value="Save and {% if reissue %}Re-{% endif %}Send Ballot to the IESG" />
<a class="button" href="{% url "doc_writeup" name=charter.name %}">Cancel</a>
<input class="button" type="submit" name="save_ballot_writeup" value="Save Ballot Writeup" />
<input class="button" style="margin-left: 8px" type="submit" name="send_ballot" value="Save and {% if reissue %}Re-{% endif %}Send Ballot to the IESG" />
</div>
</form>

View file

@ -30,8 +30,8 @@ Charter submission for {{ group.acronym }} {{ group.type.name }}
<tr>
<td></td>
<td class="actions">
<a href="{% url "doc_view" name=group.charter.name %}">Back</a>
<input type="submit" value="Submit"/>
<a class="button" href="{% url "doc_view" name=group.charter.name %}">Cancel</a>
<input class="button" type="submit" value="Submit"/>
</td>
</tr>
</table>

View file

@ -88,11 +88,6 @@ class RecordUrlsMiddleware(object):
def process_request(self, request):
visited_urls.add(request.path)
class FillInRemoteUserMiddleware(object):
def process_request(self, request):
if request.user.is_authenticated() and "REMOTE_USER" not in request.META:
request.META["REMOTE_USER"] = request.user.username
def get_url_patterns(module):
res = []
try:
@ -204,15 +199,6 @@ class IetfTestRunner(DiscoverRunner):
old_destroy = connection.creation.__class__.destroy_test_db
connection.creation.__class__.destroy_test_db = safe_destroy_0_1
classes = []
for m in settings.MIDDLEWARE_CLASSES:
if m == "django.contrib.auth.middleware.RemoteUserMiddleware":
# the tests are not passing in REMOTE_USER, so insert
# hack to do so automatically
classes.append("ietf.utils.test_runner.FillInRemoteUserMiddleware")
classes.append(m)
settings.MIDDLEWARE_CLASSES = tuple(classes)
check_coverage = not test_labels
if check_coverage: