Import remaining missing attributes in InternetDraft, IDInternal and Ballot, fix bugs

- Legacy-Id: 2736
This commit is contained in:
Ole Laursen 2011-01-04 19:25:20 +00:00
parent 0ada0780fa
commit daf08da04b
6 changed files with 253 additions and 107 deletions

View file

@ -165,7 +165,8 @@ def _get_history(doc, versions):
results.append({'comment':e, 'info':info, 'date':e.time, 'is_com':True})
prev_rev = "00"
for o in reversed(results):
results.sort(key=lambda x: x['date'])
for o in results:
e = o["comment"]
if e.type == "new_revision":
e.version = e.newrevision.rev

View file

@ -164,10 +164,10 @@ EVENT_TYPES = [
("added_tombstone", "Added tombstone"),
("expired_document", "Expired document"),
("requested_resurrect", "Requested resurrect"),
("completed_resurrect", "Completed resurrect"),
# IESG events
("sent_ballot_announcement", "Sent ballot announcement"),
("deferred_ballot", "Deferred ballot"),
("changed_ballot_position", "Changed ballot position"),
("changed_ballot_approval_text", "Changed ballot approval text"),
("changed_ballot_writeup_text", "Changed ballot writeup text"),
@ -180,9 +180,8 @@ EVENT_TYPES = [
("scheduled_for_telechat", "Scheduled for telechat"),
("resolved_to_do_not_publish", "Resolved to 'do not publish'"),
("resolved_to_no_problem", "Resolved to 'no problem'"),
("iesg_approved", "IESG approved document"),
("iesg_approved", "IESG approved document (no problem)"),
("iesg_disapproved", "IESG disapproved document (do not publish)"),
("approved_in_minute", "Approved in minute"),
]
@ -221,10 +220,10 @@ class BallotPosition(Event):
comment_time = models.DateTimeField(help_text="Time optional comment was written", blank=True, null=True)
class Status(Event):
date = models.DateField()
date = models.DateField(blank=True, null=True)
class Expiration(Event):
expires = models.DateTimeField()
expires = models.DateTimeField(blank=True, null=True)
class Telechat(Event):
telechat_date = models.DateField(blank=True, null=True)

View file

@ -53,7 +53,7 @@ class InternetDraft(Document):
for t in possible_types:
if m.endswith(t):
res.add(t)
return ",".join(res)
return ",".join(res) or ".txt"
#txt_page_count = models.IntegerField()
@property
def txt_page_count(self):
@ -113,7 +113,7 @@ class InternetDraft(Document):
@property
def b_approve_date(self):
e = self.latest_event(type="iesg_approved")
return e.time if e else None
return e.time.date() if e else None
#wgreturn_date = models.DateField(null=True, blank=True) # unused
@ -148,13 +148,13 @@ class InternetDraft(Document):
#review_by_rfc_editor = models.BooleanField()
@property
def review_by_rfc_editor(self): raise NotImplemented # should use tag
def review_by_rfc_editor(self):
return bool(self.tags.filter(slug='rfc-rev'))
#expired_tombstone = models.BooleanField()
@property
def expired_tombstone(self):
# FIXME: this is probably not perfect, what happens when we delete it again
return self.latest_event(type="added_tombstone")
return bool(self.tags.filter(slug='exp-tomb'))
#idinternal = FKAsOneToOne('idinternal', reverse=True, query=models.Q(rfc_flag = 0))
@property
@ -176,7 +176,8 @@ class InternetDraft(Document):
r = max(r - 1, 0)
return "%02d" % r
def expiration(self):
return self.revision_date + datetime.timedelta(self.DAYS_TO_EXPIRE)
e = self.latest_event(type__in=("completed_resurrect", "new_revision"))
return e.time.date() + datetime.timedelta(self.DAYS_TO_EXPIRE)
def can_expire(self):
# Copying the logic from expire-ids-1 without thinking
# much about it.
@ -234,22 +235,22 @@ class InternetDraft(Document):
#primary_flag = models.IntegerField(blank=True, null=True)
@property
def primary(self):
return True # left-over from multi-ballot documents?
def primary_flag(self):
# left-over from multi-ballot documents which we don't really
# support anymore, just pretend we're always primary
return True
#group_flag = models.IntegerField(blank=True, default=0) # unused?
#group_flag = models.IntegerField(blank=True, default=0) # not used anymore, contained the group acronym_id once upon a time (so it wasn't a flag)
#token_name = models.CharField(blank=True, max_length=25)
@property
def token_name(self):
e = self.latest_event()
return e.by.person.name if e else None
return self.ad.get_name()
#token_email = models.CharField(blank=True, max_length=255)
@property
def token_email(self):
e = self.latest_event()
return e.by.address if e else None
return self.ad.address
#note = models.TextField(blank=True) # same name
@ -273,7 +274,7 @@ class InternetDraft(Document):
#prev_state = models.ForeignKey(IDState, db_column='prev_state', related_name='docs_prev')
@property
def prev_state(self):
ds = self.dochistory_set.all().order_by('-time')[:1]
ds = self.dochistory_set.exclude(iesg_state=self.iesg_state).order_by('-time')[:1]
return ds[0].iesg_state if ds else None
#assigned_to = models.CharField(blank=True, max_length=25) # unused
@ -282,7 +283,8 @@ class InternetDraft(Document):
@property
def mark_by(self):
e = self.latest_event()
return e.by if e else None
from person.proxy import IESGLogin as IESGLoginProxy
return IESGLoginProxy(e.by) if e else None
# job_owner = models.ForeignKey(IESGLogin, db_column='job_owner', related_name='documents')
@property
@ -310,10 +312,12 @@ class InternetDraft(Document):
#cur_sub_state = BrokenForeignKey(IDSubState, related_name='docs', null=True, blank=True, null_values=(0, -1))
@property
def cur_sub_state(self):
return ", ".join(self.tags.all())
s = self.tags.filter(slug__in=['extpty', 'need-rev', 'ad-f-up', 'point'])
return s[0] if s else None
@property
def cur_sub_state_id(self):
return 0
s = self.cur_sub_state
return 1 if s else 0 # need to return something numeric
#prev_sub_state = BrokenForeignKey(IDSubState, related_name='docs_prev', null=True, blank=True, null_values=(0, -1))
@property
@ -339,7 +343,7 @@ class InternetDraft(Document):
#via_rfc_editor = models.IntegerField(null=True, blank=True)
@property
def via_rfc_editor(self):
return bool(self.tags.filter(slug='viarfceditor'))
return bool(self.tags.filter(slug='via-rfc'))
#state_change_notice_to = models.CharField(blank=True, max_length=255)
@property
@ -349,23 +353,27 @@ class InternetDraft(Document):
#dnp = models.IntegerField(null=True, blank=True)
@property
def dnp(self):
return self.latest_event(type="resolved_to_do_not_publish")
e = self.latest_event(type__in=("iesg_disapproved", "iesg_approved"))
return e != None and e.type == "iesg_disapproved"
#dnp_date = models.DateField(null=True, blank=True)
@property
def dnp_date(self):
e = self.latest_event(type="resolved_to_do_not_publish")
return e.time if e else None
e = self.latest_event(type__in=("iesg_disapproved", "iesg_approved"))
return e.time.date() if e != None and e.type == "iesg_disapproved" else None
#noproblem = models.IntegerField(null=True, blank=True)
@property
def noproblem(self):
return self.latest_event(type="resolved_to_no_problem")
e = self.latest_event(type__in=("iesg_disapproved", "iesg_approved"))
return e != None and e.type == "iesg_approved"
#resurrect_requested_by = BrokenForeignKey(IESGLogin, db_column='resurrect_requested_by', related_name='docsresurrected', null=True, blank=True)
@property
def resurrect_requested_by(self):
return self.latest_event(type="requested_resurrect")
e = self.latest_event(type__in=("requested_resurrect", "completed_resurrect"))
from person.proxy import IESGLogin as IESGLoginProxy
return IESGLoginProxy(e.by) if e and e.type == "requested_resurrect" else None
#approved_in_minute = models.IntegerField(null=True, blank=True)
@property
@ -404,7 +412,8 @@ class InternetDraft(Document):
#active = models.BooleanField()
@property
def active(self):
return self.iesg_state and self.iesg_state.name in ['In Last Call', 'Waiting for Writeup', 'Waiting for AD Go-Ahead', 'IESG Evaluation', 'IESG Evaluation - Defer']
# taken from BallotWrapper
return self.latest_event(type="sent_ballot_announcement") and self.iesg_state and self.iesg_state.name in ['In Last Call', 'Waiting for Writeup', 'Waiting for AD Go-Ahead', 'IESG Evaluation', 'IESG Evaluation - Defer'] and (self.state_id == "rfc" or self.state_id == "active")
#an_sent = models.BooleanField()
@property
@ -421,42 +430,45 @@ class InternetDraft(Document):
@property
def an_sent_by(self):
e = self.latest_event(type="iesg_approved")
return e.by if e else None
from person.proxy import IESGLogin as IESGLoginProxy
return IESGLoginProxy(e.by) if e else None
#defer = models.BooleanField()
@property
def defer(self):
return bool(self.latest_event(type="deferred_ballot"))
# we're deferred if we're in the deferred state
return self.iesg_state and self.iesg_state.name == "IESG Evaluation - Defer"
#defer_by = models.ForeignKey(IESGLogin, db_column='defer_by', related_name='deferred', null=True)
@property
def defer_by(self):
e = self.latest_event(type="deferred_ballot")
return e.by if e else None
e = self.latest_event(type="changed_document", desc__startswith="State changed to <b>IESG Evaluation - Defer</b>")
from person.proxy import IESGLogin as IESGLoginProxy
return IESGLoginProxy(e.by) if e else None
#defer_date = models.DateField(null=True, blank=True)
@property
def defer_date(self):
e = self.latest_event(type="deferred_ballot")
return e.time if e else None
e = self.latest_event(type="changed_document", desc__startswith="State changed to <b>IESG Evaluation - Defer</b>")
return e.time.date() if e else None
#approval_text = models.TextField(blank=True)
@property
def approval_text(self):
e = self.latest_event(type="changed_ballot_approval_text")
return e.text.content if e else ""
e = self.latest_event(Text, type="changed_ballot_approval_text")
return e.content if e else ""
#last_call_text = models.TextField(blank=True)
@property
def last_call_text(self):
e = self.latest_event(type="changed_last_call_text")
return e.text.content if e else ""
e = self.latest_event(Text, type="changed_last_call_text")
return e.content if e else ""
#ballot_writeup = models.TextField(blank=True)
@property
def ballot_writeup(self):
e = self.latest_event(type="changed_ballot_writeup_text")
return e.text.content if e else ""
e = self.latest_event(Text, type="changed_ballot_writeup_text")
return e.content if e else ""
#ballot_issued = models.IntegerField(null=True, blank=True)
@property

View file

@ -100,6 +100,23 @@ ballot_position_mapping = {
None: name(BallotPositionName, 'norecord', 'No record'),
}
substate_mapping = {
"External Party": name(DocInfoTagName, 'extpty', "External Party", 'The document is awaiting review or input from an external party (i.e, someone other than the shepherding AD, the authors, or the WG). See the "note" field for more details on who has the action.'),
"Revised ID Needed": name(DocInfoTagName, 'need-rev', "Revised ID Needed", 'An updated ID is needed to address the issues that have been raised.'),
"AD Followup": name(DocInfoTagName, 'ad-f-up', "AD Followup", """A generic substate indicating that the shepherding AD has the action item to determine appropriate next steps. In particular, the appropriate steps (and the corresponding next state or substate) depend entirely on the nature of the issues that were raised and can only be decided with active involvement of the shepherding AD. Examples include:
- if another AD raises an issue, the shepherding AD may first iterate with the other AD to get a better understanding of the exact issue. Or, the shepherding AD may attempt to argue that the issue is not serious enough to bring to the attention of the authors/WG.
- if a documented issue is forwarded to a WG, some further iteration may be needed before it can be determined whether a new revision is needed or whether the WG response to an issue clarifies the issue sufficiently.
- when a new revision appears, the shepherding AD will first look at the changes to determine whether they believe all outstanding issues have been raised satisfactorily, prior to asking the ADs who raised the original issues to verify the changes."""),
"Point Raised - writeup needed": name(DocInfoTagName, 'point', "Point Raised - writeup needed", 'IESG discussions on the document have raised some issues that need to be brought to the attention of the authors/WG, but those issues have not been written down yet. (It is common for discussions during a telechat to result in such situations. An AD may raise a possible issue during a telechat and only decide as a result of that discussion whether the issue is worth formally writing up and bringing to the attention of the authors/WG). A document stays in the "Point Raised - Writeup Needed" state until *ALL* IESG comments that have been raised have been documented.')
}
tag_review_by_rfc_editor = name(DocInfoTagName, 'rfc-rev', "Review by RFC Editor")
tag_via_rfc_editor = name(DocInfoTagName, 'via-rfc', "Via RFC Editor")
tag_expired_tombstone = name(DocInfoTagName, 'exp-tomb', "Expired tombstone")
tag_approved_in_minute = name(DocInfoTagName, 'app-min', "Approved in minute")
# helpers for events
@ -120,6 +137,11 @@ def iesg_login_to_email(l):
if not l:
return system_email
else:
# there's a bunch of old weird comments made by "IESG
# Member", transform these into "System" instead
if l.id == 2:
return system_email
# fix logins without the right person
if not l.person:
if l.id not in buggy_iesg_logins_cache:
@ -138,8 +160,11 @@ def iesg_login_to_email(l):
try:
return Email.objects.get(address=l.person.email()[1])
except Email.DoesNotExist:
print "MISSING IESG LOGIN", l.person.email()
return None
try:
return Email.objects.get(person__name="%s %s" % (l.person.first_name, l.person.last_name))
except Email.DoesNotExist:
print "MISSING IESG LOGIN", l.person.email()
return None
# regexps for parsing document comments
@ -148,21 +173,23 @@ def date_in_match(match):
return datetime.date(int(match.group('year')), int(match.group('month')), int(match.group('day')))
re_telechat_agenda = re.compile(r"(Placed on|Removed from) agenda for telechat(| - %s) by" % date_re_str)
re_telechat_changed = re.compile(r"Telechat date (was|has been) changed to (<b>)?%s(</b>)? from" % date_re_str)
re_ballot_position = re.compile(r"\[Ballot Position Update\] (New position, (?P<position>.*), has been recorded (|for (?P<for>.*) )|Position (|for (?P<for2>.*) )has been changed to (?P<position2>.*) from .*)by (?P<by>.*)")
re_ballot_issued = re.compile(r"Ballot has been issued(| by)")
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>.*))")
re_note_changed = re.compile(r"(\[Note\]: .*'.*'|Note field has been cleared)")
re_note_changed = re.compile(r"(\[Note\]: .*'.*'|Note field has been cleared)", re.DOTALL)
re_draft_added = re.compile(r"Draft [Aa]dded (by .*)?( in state (?P<state>.*))?")
re_last_call_requested = re.compile(r"Last Call was requested")
re_document_approved = re.compile(r"IESG has approved and state has been changed to")
re_document_disapproved = re.compile(r"(Do Not Publish|DNP) note has been sent to RFC Editor and state has been changed to")
re_resurrection_requested = re.compile(r"(I-D |)Resurrection was requested by")
re_completed_resurrect = re.compile(r"(This document has been resurrected|This document has been resurrected per RFC Editor's request|Resurrection was completed)")
re_status_date_changed = re.compile(r"Status [dD]ate has been changed to (<b>)?" + date_re_str)
re_responsible_ad_changed = re.compile(r"(Responsible AD|Shepherding AD) has been changed to (<b>)?")
re_responsible_ad_changed = re.compile(r"(Responsible AD|Shepherding AD|responsible) has been changed to (<b>)?")
re_intended_status_changed = re.compile(r"Intended [sS]tatus has been changed to (<b>)?")
re_state_change_notice = re.compile(r"State Change Notice email list (have been change|has been changed) (<b>)?")
made_up_date = datetime.datetime(2030, 1, 1, 0, 0, 0)
re_area_acronym_changed = re.compile(r"Area acronymn? has been changed to \w+ from \w+(<b>)?")
all_drafts = InternetDraft.objects.all().select_related()
if draft_name_to_import:
@ -180,10 +207,10 @@ for o in all_drafts:
d.title = o.title
d.state = status_mapping[o.status.status]
d.group = Group.objects.get(acronym=o.group.acronym)
# d.tags =
d.stream = stream_ietf
d.wg_state = None
d.iesg_state = iesg_state_mapping[o.idinternal.cur_state.state if o.idinternal else None]
# we currently ignore the previous IESG state prev_state
d.iana_state = None
# d.rfc_state =
d.rev = o.revision
@ -209,12 +236,14 @@ for o in all_drafts:
d.event_set.all().delete()
if o.idinternal:
last_note_change_text = ""
# extract events
for c in o.idinternal.documentcomment_set.order_by('date', 'time', 'id'):
handled = False
# telechat agenda schedulings
match = re_telechat_agenda.search(c.comment_text)
match = re_telechat_agenda.search(c.comment_text) or re_telechat_changed.search(c.comment_text)
if match:
e = Telechat()
e.type = "scheduled_for_telechat"
@ -305,8 +334,11 @@ for o in all_drafts:
# note changed
match = re_note_changed.search(c.comment_text)
if match:
e = Event(type="changed_document")
save_event(d, e, c)
# watch out for duplicates of which the old data's got many
if c.comment_text != last_note_change_text:
last_note_change_text = c.comment_text
e = Event(type="changed_document")
save_event(d, e, c)
handled = True
# draft added
@ -322,6 +354,20 @@ for o in all_drafts:
save_event(d, e, c)
handled = True
# resurrect requested
match = re_resurrection_requested.search(c.comment_text)
if match:
e = Event(type="requested_resurrect")
save_event(d, e, c)
handled = True
# completed resurrect
match = re_completed_resurrect.search(c.comment_text)
if match:
e = Event(type="completed_resurrect")
save_event(d, e, c)
handled = True
# document expiration
if c.comment_text == "Document is expired by system":
e = Event(type="expired_document")
@ -334,6 +380,13 @@ for o in all_drafts:
e = Event(type="iesg_approved")
save_event(d, e, c)
handled = True
# disapproved document
match = re_document_disapproved.search(c.comment_text)
if match:
e = Event(type="iesg_disapproved")
save_event(d, e, c)
handled = True
# some changes can be bundled - this is not entirely
@ -353,7 +406,7 @@ for o in all_drafts:
# AD/job owner changed
match = re_responsible_ad_changed.search(line)
if match:
e = Event(type="changed_draft")
e = Event(type="changed_document")
e.desc = line
save_event(d, e, c)
handled = True
@ -361,7 +414,7 @@ for o in all_drafts:
# intended standard level changed
match = re_intended_status_changed.search(line)
if match:
e = Event(type="changed_draft")
e = Event(type="changed_document")
e.desc = line
save_event(d, e, c)
handled = True
@ -369,7 +422,15 @@ for o in all_drafts:
# state change notice
match = re_state_change_notice.search(line)
if match:
e = Event(type="changed_draft")
e = Event(type="changed_document")
e.desc = line
save_event(d, e, c)
handled = True
# area acronym
match = re_area_acronym_changed.search(line)
if match:
e = Event(type="changed_document")
e.desc = line
save_event(d, e, c)
handled = True
@ -380,7 +441,9 @@ for o in all_drafts:
if handled:
c.comment_text = "<br>".join(unhandled_lines)
if c.comment_text:
print "couldn't handle multi-line comment %s '%s'" % (c.id, c.comment_text.replace("\n", " ").replace("\r", "")[0:80])
# all others are added as comments
if not handled:
@ -392,6 +455,11 @@ for o in all_drafts:
"Document Shepherd Write-up for %s" % d.name,
"Who is the Document Shepherd for this document",
"We understand that this document doesn't require any IANA actions",
"IANA questions",
"IANA has questions",
"IANA comments",
"IANA Comments",
"IANA Evaluation Comments",
]
for t in typical_comments:
if t in c.comment_text:
@ -399,7 +467,7 @@ for o in all_drafts:
break
if not handled:
print "couldn't handle %s '%s'" % (c.id, c.comment_text.replace("\n", "").replace("\r", "")[0:80])
print "couldn't handle comment %s '%s'" % (c.id, c.comment_text.replace("\n", " ").replace("\r", "")[0:80])
# import missing revision changes from DraftVersions
@ -418,30 +486,37 @@ for o in all_drafts:
e.save()
known_revisions.add(v.revision)
# import events that might be missing, we can't be sure where
# to place them but if we don't generate them, we'll be
# missing the information completely
e = d.latest_event(Event, type="iesg_approved")
approved_date = e.time.date() if e else None
if o.b_approve_date != approved_date:
e = Event(type="iesg_approved")
e.time = o.idinternal.b_approve_date
# import events that might be missing, we can't be sure who did
# them or when but if we don't generate them, we'll be missing the
# information completely
# make sure last decision is recorded
e = d.latest_event(Event, type__in=("iesg_approved", "iesg_disapproved"))
decision_date = e.time.date() if e else None
if o.b_approve_date != decision_date:
disapproved = o.idinternal and o.idinternal.dnp
e = Event(type="iesg_disapproved" if disapproved else "iesg_approved")
e.time = o.b_approve_date
e.by = system_email
e.doc = d
e.desc = "IESG has approved"
e.desc = "Do Not Publish note has been sent to RFC Editor" if disapproved else "IESG has approved"
e.save()
if o.lc_expiration_date:
e = Expiration(type="sent_last_call", expires=o.lc_expiration_date)
e.time = o.lc_sent_date
# let's try to figure out who did it
# let's try to find the actual change
events = d.event_set.filter(type="changed_document", desc__contains=" to <b>In Last Call</b>").order_by('-time')[:1]
# event time is more accurate with actual time instead of just
# date, gives better sorting
e.time = events[0].time if events else o.lc_sent_date
e.by = events[0].by if events else system_email
e.doc = d
e.desc = "Last call sent"
e.save()
if o.idinternal:
made_up_date = d.latest_event().time + datetime.timedelta(seconds=1) # datetime.datetime(2030, 1, 1, 0, 0, 0)
e = d.latest_event(Status, type="changed_status_date")
status_date = e.date if e else None
if o.idinternal.status_date != status_date:
@ -461,17 +536,72 @@ for o in all_drafts:
e = Telechat(type="scheduled_for_telechat",
telechat_date=o.idinternal.telechat_date,
returning_item=bool(o.idinternal.returning_item))
e.time = made_up_date # FIXME: this isn't good, will override new values, estimate one instead
# a common case is that it has been removed from the
# agenda automatically by a script without a notice in the
# comments, in that case the time is simply the day after
# the telechat
e.time = telechat_date + datetime.timedelta(days=1) if telechat_date and not o.idinternal.telechat_date else made_up_date
e.by = system_email
args = ("Placed on", o.idinternal.telechat_date) if o.idinternal.telechat_date else ("Removed from", telechat_date)
e.doc = d
e.desc = "%s agenda for telechat - %s by system" % args
e.save()
if o.idinternal.ballot:
text_date = made_up_date
# if any of these events have happened, they're closer to
# the real time
e = d.event_set.filter(type__in=("requested_last_call", "sent_last_call", "sent_ballot_announcement", "iesg_approved", "iesg_disapproved")).order_by('time')[:1]
if e:
text_date = e[0].time - datetime.timedelta(seconds=1)
# FIXME: import writeups
if o.idinternal.ballot.approval_text:
e = Text(type="changed_ballot_approval_text", content=o.idinternal.ballot.approval_text)
e.time = text_date
e.by = system_email
e.doc = d
e.desc = "Ballot approval text was added"
e.save()
if o.idinternal.ballot.last_call_text:
e = Text(type="changed_last_call_text", content=o.idinternal.ballot.last_call_text)
e.time = text_date
e.by = system_email
e.doc = d
e.desc = "Last call text was added"
e.save()
if o.idinternal.ballot.ballot_writeup:
e = Text(type="changed_ballot_writeup_text", content=o.idinternal.ballot.ballot_writeup)
e.time = text_date
e.by = system_email
e.doc = d
e.desc = "Ballot writeup text was added"
e.save()
# import other attributes
# tags
tags = d.tags.all()
def sync_tag(include, tag):
if include and tag not in tags:
d.tags.add(tag)
if not include and tag in tags:
d.tags.remove(tag)
sync_tag(o.review_by_rfc_editor, tag_review_by_rfc_editor)
sync_tag(o.expired_tombstone, tag_expired_tombstone)
sync_tag(o.idinternal and o.idinternal.via_rfc_editor, tag_via_rfc_editor)
n = o.idinternal and o.idinternal.cur_sub_state and o.idinternal.cur_sub_state.sub_state
for k, v in substate_mapping.iteritems():
sync_tag(k == n, v)
# currently we ignore prev_sub_state
sync_tag(o.idinternal and o.idinternal.approved_in_minute, tag_approved_in_minute)
# RFC alias
if o.rfc_number:
rfc_name = "rfc%s" % o.rfc_number
@ -491,7 +621,7 @@ for o in all_drafts:
sys.exit(0)
class CheckListInternetDraft(models.Model):
#class CheckListInternetDraft(models.Model):
# id_document_tag = models.AutoField(primary_key=True)
# title = models.CharField(max_length=255, db_column='id_document_name')
# id_document_key = models.CharField(max_length=255, editable=False)
@ -521,51 +651,51 @@ class CheckListInternetDraft(models.Model):
# last_modified_date = models.DateField()
# replaced_by = BrokenForeignKey('self', db_column='replaced_by', blank=True, null=True, related_name='replaces_set')
# replaces = FKAsOneToOne('replaces', reverse=True)
review_by_rfc_editor = models.BooleanField()
expired_tombstone = models.BooleanField()
# review_by_rfc_editor = models.BooleanField()
# expired_tombstone = models.BooleanField()
# idinternal = FKAsOneToOne('idinternal', reverse=True, query=models.Q(rfc_flag = 0))
class CheckListIDInternal(models.Model):
#class CheckListIDInternal(models.Model):
# draft = models.ForeignKey(InternetDraft, primary_key=True, unique=True, db_column='id_document_tag')
rfc_flag = models.IntegerField(null=True)
ballot = models.ForeignKey('BallotInfo', related_name='drafts', db_column="ballot_id")
primary_flag = models.IntegerField(blank=True, null=True)
group_flag = models.IntegerField(blank=True, default=0)
token_name = models.CharField(blank=True, max_length=25)
token_email = models.CharField(blank=True, max_length=255)
# rfc_flag = models.IntegerField(null=True)
# ballot = models.ForeignKey('BallotInfo', related_name='drafts', db_column="ballot_id")
# primary_flag = models.IntegerField(blank=True, null=True)
# group_flag = models.IntegerField(blank=True, default=0)
# token_name = models.CharField(blank=True, max_length=25)
# token_email = models.CharField(blank=True, max_length=255)
# note = models.TextField(blank=True)
# status_date = models.DateField(blank=True,null=True)
email_display = models.CharField(blank=True, max_length=50)
agenda = models.IntegerField(null=True, blank=True)
# email_display = models.CharField(blank=True, max_length=50)
# agenda = models.IntegerField(null=True, blank=True)
# cur_state = models.ForeignKey(IDState, db_column='cur_state', related_name='docs')
prev_state = models.ForeignKey(IDState, db_column='prev_state', related_name='docs_prev')
assigned_to = models.CharField(blank=True, max_length=25)
mark_by = models.ForeignKey('IESGLogin', db_column='mark_by', related_name='marked')
# prev_state = models.ForeignKey(IDState, db_column='prev_state', related_name='docs_prev')
# assigned_to = models.CharField(blank=True, max_length=25)
# mark_by = models.ForeignKey('IESGLogin', db_column='mark_by', related_name='marked')
# job_owner = models.ForeignKey(IESGLogin, db_column='job_owner', related_name='documents')
event_date = models.DateField(null=True)
# event_date = models.DateField(null=True)
# area_acronym = models.ForeignKey('Area')
cur_sub_state = BrokenForeignKey('IDSubState', related_name='docs', null=True, blank=True, null_values=(0, -1))
prev_sub_state = BrokenForeignKey('IDSubState', related_name='docs_prev', null=True, blank=True, null_values=(0, -1))
# cur_sub_state = BrokenForeignKey('IDSubState', related_name='docs', null=True, blank=True, null_values=(0, -1))
# prev_sub_state = BrokenForeignKey('IDSubState', related_name='docs_prev', null=True, blank=True, null_values=(0, -1))
# returning_item = models.IntegerField(null=True, blank=True)
# telechat_date = models.DateField(null=True, blank=True)
via_rfc_editor = models.IntegerField(null=True, blank=True)
# via_rfc_editor = models.IntegerField(null=True, blank=True)
# state_change_notice_to = models.CharField(blank=True, max_length=255)
dnp = models.IntegerField(null=True, blank=True)
dnp_date = models.DateField(null=True, blank=True)
noproblem = models.IntegerField(null=True, blank=True)
resurrect_requested_by = BrokenForeignKey('IESGLogin', db_column='resurrect_requested_by', related_name='docsresurrected', null=True, blank=True)
approved_in_minute = models.IntegerField(null=True, blank=True)
# dnp = models.IntegerField(null=True, blank=True)
# dnp_date = models.DateField(null=True, blank=True)
# noproblem = models.IntegerField(null=True, blank=True)
# resurrect_requested_by = BrokenForeignKey('IESGLogin', db_column='resurrect_requested_by', related_name='docsresurrected', null=True, blank=True)
# approved_in_minute = models.IntegerField(null=True, blank=True)
class CheckListBallotInfo(models.Model):
ballot = models.AutoField(primary_key=True, db_column='ballot_id')
active = models.BooleanField()
#class CheckListBallotInfo(models.Model):
# ballot = models.AutoField(primary_key=True, db_column='ballot_id')
# active = models.BooleanField()
# an_sent = models.BooleanField()
# an_sent_date = models.DateField(null=True, blank=True)
# an_sent_by = models.ForeignKey('IESGLogin', db_column='an_sent_by', related_name='ansent', null=True)
defer = models.BooleanField(blank=True)
defer_by = models.ForeignKey('IESGLogin', db_column='defer_by', related_name='deferred', null=True)
defer_date = models.DateField(null=True, blank=True)
approval_text = models.TextField(blank=True)
last_call_text = models.TextField(blank=True)
ballot_writeup = models.TextField(blank=True)
# defer = models.BooleanField(blank=True)
# defer_by = models.ForeignKey('IESGLogin', db_column='defer_by', related_name='deferred', null=True)
# defer_date = models.DateField(null=True, blank=True)
# approval_text = models.TextField(blank=True)
# last_call_text = models.TextField(blank=True)
# ballot_writeup = models.TextField(blank=True)
# ballot_issued = models.IntegerField(null=True, blank=True)

View file

@ -40,9 +40,11 @@ area_director_role = name(RoleName, "ad", "Area Director")
# helpers for creating the objects
def get_or_create_email(o):
email = o.person.email()[1]
hardcoded_emails = { 'Dinara Suleymanova': "dinaras@ietf.org" }
email = o.person.email()[1] or hardcoded_emails.get("%s %s" % (o.person.first_name, o.person.last_name))
if not email:
print "NO EMAIL FOR %s %s" % (o.__class__, o.id)
print "NO EMAIL FOR %s %s %s %s" % (o.__class__, o.id, o.person.first_name, o.person.last_name)
return None
e, _ = Email.objects.get_or_create(address=email)

View file

@ -37,6 +37,8 @@ class IESGLogin(Email):
def __str__(self):
return self.get_name()
def __unicode__(self):
return self.get_name()
def is_current_ad(self):
return self in Email.objects.filter(role__name="ad", role__group__state="active")
@staticmethod