Made several changes to correctly use the new (RFC6410) "Internet Standard" level

in email that gets sent at various stages in the handling of documents.

Fixes bug 821
 - Legacy-Id: 4288
This commit is contained in:
Robert Sparks 2012-04-17 21:00:26 +00:00
parent bf718d1b74
commit 0e2dd258c7
9 changed files with 63 additions and 228 deletions

View file

@ -1083,7 +1083,7 @@
<field type="CharField" name="intended_status">Proposed Standard</field>
</object>
<object pk="7" model="idtracker.idintendedstatus">
<field type="CharField" name="intended_status">Standard</field>
<field type="CharField" name="intended_status">Internet Standard</field>
</object>
<object pk="8" model="idtracker.idintendedstatus">
<field type="CharField" name="intended_status">None</field>
@ -1329,4 +1329,4 @@ withdrawn, etc.)</field>
<field type="CharField" name="description">Date for List of Approved V-00 Submissions from WG Chairs</field>
<field type="CharField" name="f_name">sixth</field>
</object>
</django-objects>
</django-objects>

View file

@ -72,26 +72,6 @@ if settings.USE_DB_REDESIGN_PROXY_CLASSES:
email_owner = email_adREDESIGN
def full_intended_status(intended_status):
s = str(intended_status)
# FIXME: this should perhaps be defined in the db
if "Informational" in s:
return "an Informational RFC"
elif "Experimental" in s:
return "an Experimental RFC"
elif "Proposed" in s:
return "a Proposed Standard"
elif "Draft" in s:
return "a Draft Standard"
elif "BCP" in s:
return "a BCP"
elif "Standard" in s:
return "a Full Standard"
elif "Request" in s or "None" in s:
return "*** YOU MUST SELECT AN INTENDED STATUS FOR THIS DRAFT AND REGENERATE THIS TEXT ***"
else:
return "a %s" % s
def generate_ballot_writeup(request, doc):
e = WriteupDocEvent()
e.type = "changed_ballot_writeup_text"
@ -104,48 +84,9 @@ def generate_ballot_writeup(request, doc):
return e
def generate_last_call_announcement(request, doc):
status = full_intended_status(doc.intended_status).replace("a ", "").replace("an ", "")
expiration_date = date.today() + timedelta(days=14)
cc = []
if doc.group.acronym_id == Acronym.INDIVIDUAL_SUBMITTER:
group = "an individual submitter"
expiration_date += timedelta(days=14)
else:
group = "the %s WG (%s)" % (doc.group.name, doc.group.acronym)
cc.append(doc.group.ietfwg.email_address)
urls = []
docs = [d.document() for d in doc.idinternal.ballot_set()]
for d in docs:
d.full_status = full_intended_status(d.intended_status)
d.filled_title = textwrap.fill(d.title, width=70, subsequent_indent=" " * 3)
urls.append(settings.IDTRACKER_BASE_URL + d.idinternal.get_absolute_url())
iprs, docs = iprs_from_docs(docs)
if iprs:
ipr_links = [ urlreverse("ietf.ipr.views.show", kwargs=dict(ipr_id=i.ipr_id)) for i in iprs]
ipr_links = [ settings.IDTRACKER_BASE_URL+url if not url.startswith("http") else url for url in ipr_links ]
else:
ipr_links = None
return render_to_string("idrfc/last_call_announcement.txt",
dict(doc=doc,
doc_url=settings.IDTRACKER_BASE_URL + doc.idinternal.get_absolute_url(),
expiration_date=expiration_date.strftime("%Y-%m-%d"), #.strftime("%B %-d, %Y"),
cc=", ".join("<%s>" % e for e in cc),
group=group,
docs=docs,
urls=urls,
status=status,
impl_report="Draft" in status or "Full" in status,
ipr_links=ipr_links,
)
)
pass
def generate_last_call_announcementREDESIGN(request, doc):
doc.full_status = full_intended_status(doc.intended_std_level)
status = doc.full_status.replace("a ", "").replace("an ", "")
expiration_date = date.today() + timedelta(days=14)
cc = []
@ -174,8 +115,6 @@ def generate_last_call_announcementREDESIGN(request, doc):
group=group,
docs=[ doc ],
urls=[ settings.IDTRACKER_BASE_URL + doc.get_absolute_url() ],
status=status,
impl_report="Draft" in status or "Full" in status,
ipr_links=ipr_links,
)
)
@ -195,85 +134,10 @@ if settings.USE_DB_REDESIGN_PROXY_CLASSES:
generate_last_call_announcement = generate_last_call_announcementREDESIGN
def generate_approval_mail(request, doc):
if doc.idinternal.cur_state_id in IDState.DO_NOT_PUBLISH_STATES or doc.idinternal.via_rfc_editor:
return generate_approval_mail_rfc_editor(request, doc)
status = full_intended_status(doc.intended_status).replace("a ", "").replace("an ", "")
if "an " in full_intended_status(doc.intended_status):
action_type = "Document"
else:
action_type = "Protocol"
cc = settings.DOC_APPROVAL_EMAIL_CC
if doc.group.ietfwg.group_type.type != "AG" and not doc.group.name.endswith("Working Group"):
doc.group.name_with_wg = doc.group.name + " Working Group"
cc.append("%s mailing list <%s>" % (doc.group.acronym, doc.group.ietfwg.email_address))
cc.append("%s chair <%s-chairs@tools.ietf.org>" % (doc.group.acronym, doc.group.acronym))
else:
doc.group.name_with_wg = doc.group.name
docs = [d.document() for d in doc.idinternal.ballot_set()]
for d in docs:
d.full_status = full_intended_status(d.intended_status)
d.filled_title = textwrap.fill(d.title, width=70, subsequent_indent=" " * 3)
if doc.group.acronym_id == Acronym.INDIVIDUAL_SUBMITTER:
if len(docs) > 1:
made_by = "These documents have been reviewed in the IETF but are not the products of an IETF Working Group."
else:
made_by = "This document has been reviewed in the IETF but is not the product of an IETF Working Group."
else:
if len(docs) > 1:
made_by = "These documents are products of the %s." % doc.group.name_with_wg
else:
made_by = "This document is the product of the %s." % doc.group.name_with_wg
director = doc.idinternal.job_owner
other_director = IESGLogin.objects.filter(person__in=[ad.person for ad in doc.group.ietfwg.area_directors()]).exclude(id=doc.idinternal.job_owner_id)
if doc.group.acronym_id != Acronym.INDIVIDUAL_SUBMITTER and other_director:
contacts = "The IESG contact persons are %s and %s." % (director, other_director[0])
else:
contacts = "The IESG contact person is %s." % director
doc_type = "RFC" if type(doc) == Rfc else "Internet Draft"
return render_to_string("idrfc/approval_mail.txt",
dict(doc=doc,
doc_url=settings.IDTRACKER_BASE_URL + doc.idinternal.get_absolute_url(),
cc=",\n ".join(cc),
docs=docs,
doc_type=doc_type,
made_by=made_by,
contacts=contacts,
status=status,
action_type=action_type,
)
)
pass
def generate_approval_mail_rfc_editor(request, doc):
full_status = full_intended_status(doc.intended_status)
status = full_status.replace("a ", "").replace("an ", "")
disapproved = doc.idinternal.cur_state_id in IDState.DO_NOT_PUBLISH_STATES
doc_type = "RFC" if type(doc) == Rfc else "Internet Draft"
from ietf.ietfworkflows.streams import get_stream_from_draft
stream = get_stream_from_draft(doc)
to = ", ".join([u"%s <%s>" % x.email() for x in stream.get_chairs_for_document(doc) ])
if stream.name == "IRTF":
# also send to the IRSG
to += ", Internet Research Steering Group (IRSG) <irsg@irtf.org>"
return render_to_string("idrfc/approval_mail_rfc_editor.txt",
dict(doc=doc,
doc_url=settings.IDTRACKER_BASE_URL + doc.idinternal.get_absolute_url(),
doc_type=doc_type,
status=status,
full_status=full_status,
disapproved=disapproved,
to=to,
)
)
pass
DO_NOT_PUBLISH_IESG_STATES = ("nopubadw", "nopubanw")
@ -294,8 +158,6 @@ def generate_approval_mailREDESIGN(request, doc):
return e
def generate_approval_mail_approved(request, doc):
doc.full_status = full_intended_status(doc.intended_std_level)
status = doc.full_status.replace("a ", "").replace("an ", "")
if doc.intended_std_level_id in ("std", "ds", "ps", "bcp"):
action_type = "Protocol"
@ -340,14 +202,11 @@ def generate_approval_mail_approved(request, doc):
doc_type=doc_type,
made_by=made_by,
contacts=contacts,
status=status,
action_type=action_type,
)
)
def generate_approval_mail_rfc_editorREDESIGN(request, doc):
full_status = full_intended_status(doc.intended_std_level)
status = full_status.replace("a ", "").replace("an ", "")
disapproved = doc.get_state_slug("draft-iesg") in DO_NOT_PUBLISH_IESG_STATES
doc_type = "RFC" if doc.get_state_slug() == "rfc" else "Internet Draft"
@ -370,8 +229,6 @@ def generate_approval_mail_rfc_editorREDESIGN(request, doc):
dict(doc=doc,
doc_url=settings.IDTRACKER_BASE_URL + doc.get_absolute_url(),
doc_type=doc_type,
status=status,
full_status=full_status,
disapproved=disapproved,
to=", ".join(to),
)
@ -474,66 +331,9 @@ def email_ballot_deferred(request, doc, by, telechat_date):
telechat_date=telechat_date))
def generate_issue_ballot_mail(request, doc):
full_status = full_intended_status(doc.intended_status)
status = full_status.replace("a ", "").replace("an ", "")
ads = IESGLogin.objects.filter(user_level__in=(IESGLogin.AD_LEVEL, IESGLogin.INACTIVE_AD_LEVEL)).order_by('user_level', 'last_name')
positions = dict((p.ad_id, p) for p in doc.idinternal.ballot.positions.all())
# format positions
ad_positions = []
for ad in ads:
p = positions.get(ad.id)
if not p:
continue
def formatted(val):
if val > 0:
return "[ X ]"
elif val < 0:
return "[ . ]"
else:
return "[ ]"
fmt = u"%-21s%-10s%-11s%-9s%-10s" % (
unicode(ad)[:21],
formatted(p.yes),
formatted(p.noobj),
formatted(p.discuss),
"[ R ]" if p.recuse else formatted(p.abstain),
)
ad_positions.append((ad, fmt))
active_ad_positions = filter(lambda t: t[0].user_level == IESGLogin.AD_LEVEL, ad_positions)
inactive_ad_positions = filter(lambda t: t[0].user_level == IESGLogin.INACTIVE_AD_LEVEL, ad_positions)
# arrange discusses and comments
ad_feedback = []
discusses = dict((p.ad_id, p) for p in doc.idinternal.ballot.discusses.all()
if p.ad_id in positions and positions[p.ad_id].discuss == 1)
comments = dict((p.ad_id, p) for p in doc.idinternal.ballot.comments.all())
for ad in ads:
d = discusses.get(ad.id)
c = comments.get(ad.id)
if ad.user_level != IESGLogin.AD_LEVEL or not (c or d):
continue
ad_feedback.append((ad, d, c))
return render_to_string("idrfc/issue_ballot_mail.txt",
dict(doc=doc,
doc_url=settings.IDTRACKER_BASE_URL + doc.idinternal.get_absolute_url(),
status=status,
active_ad_positions=active_ad_positions,
inactive_ad_positions=inactive_ad_positions,
ad_feedback=ad_feedback
)
)
pass
def generate_issue_ballot_mailREDESIGN(request, doc):
full_status = full_intended_status(doc.intended_std_level)
status = full_status.replace("a ", "").replace("an ", "")
active_ads = Person.objects.filter(role__name="ad", role__group__state="active").distinct()
e = doc.latest_event(type="started_iesg_process")
@ -593,7 +393,6 @@ def generate_issue_ballot_mailREDESIGN(request, doc):
return render_to_string("idrfc/issue_ballot_mailREDESIGN.txt",
dict(doc=doc,
doc_url=settings.IDTRACKER_BASE_URL + doc.get_absolute_url(),
status=status,
active_ad_positions=active_ad_positions,
inactive_ad_positions=inactive_ad_positions,
ad_feedback=ad_feedback,

View file

@ -0,0 +1,39 @@
from django import template
from django.core.cache import cache
from django.template import loader
from ietf.idtracker.models import Area
register = template.Library()
@register.filter(name='std_level_prompt')
def std_level_prompt(doc):
"""
Returns the name from the std level names table corresponding
to the object's intended_std_level (with the word RFC appended in some
cases), or a prompt requesting that the intended_std_level be set."""
prompt = "*** YOU MUST SELECT AN INTENDED STATUS FOR THIS DRAFT AND REGENERATE THIS TEXT ***"
if doc.intended_std_level:
prompt = doc.intended_std_level.name
if doc.intended_std_level_id in ('inf','exp','hist'):
prompt = prompt + " RFC"
return prompt
@register.filter(name='std_level_prompt_with_article')
def std_level_prompt_with_article(doc):
"""
Returns the standard level prompt prefixed with an appropriate article."""
# This is a very crude way to select between "a" and "an", but will
# work for the standards levels in the standards level names table
# Grammar war alert: This will generate "an historic"
article = ""
if doc.intended_std_level:
article = "a"
if doc.intended_std_level.name[0].lower() in "aehiou":
article = "an"
return article+" "+std_level_prompt(doc)

View file

@ -409,7 +409,7 @@
<field type="IntegerField" name="order">2</field>
</object>
<object pk="std" model="name.intendedstdlevelname">
<field type="CharField" name="name">Standard</field>
<field type="CharField" name="name">Internet Standard</field>
<field type="TextField" name="desc"></field>
<field type="BooleanField" name="used">True</field>
<field type="IntegerField" name="order">3</field>
@ -583,7 +583,7 @@
<field type="IntegerField" name="order">0</field>
</object>
<object pk="std" model="name.stdlevelname">
<field type="CharField" name="name">Standard</field>
<field type="CharField" name="name">Internet Standard</field>
<field type="TextField" name="desc"></field>
<field type="BooleanField" name="used">True</field>
<field type="IntegerField" name="order">0</field>
@ -1581,4 +1581,4 @@
<field type="IntegerField" name="order">2</field>
<field to="doc.state" name="next_states" rel="ManyToManyRel"></field>
</object>
</django-objects>
</django-objects>

View file

@ -34,11 +34,11 @@ class DocTagName(NameModel):
"""Waiting for Reference, IANA Coordination, Revised ID Needed,
External Party, AD Followup, Point Raised - Writeup Needed, ..."""
class StdLevelName(NameModel):
"""Proposed Standard, Draft Standard, Standard, Experimental,
"""Proposed Standard, (Draft Standard), Internet Standard, Experimental,
Informational, Best Current Practice, Historic, ..."""
class IntendedStdLevelName(NameModel):
"""Standards Track, Experimental, Informational, Best Current
Practice, Historic, ..."""
"""Proposed Standard, (Draft Standard), Internet Standard, Experimental,
Informational, Best Current Practice, Historic, ..."""
class DocReminderTypeName(NameModel):
"Stream state"
class BallotPositionName(NameModel):

View file

@ -1,11 +1,11 @@
{% load ietf_filters %}{% autoescape off %}From: The IESG <iesg-secretary@ietf.org>
{% load ietf_filters %}{%load mail_filters %}{% autoescape off %}From: The IESG <iesg-secretary@ietf.org>
To: IETF-Announce <ietf-announce@ietf.org>{% if cc %}
Cc: {{ cc }}{% endif %}
Subject: {{ action_type }} Action: '{{ doc.title|clean_whitespace }}' to {{ status }} ({{ doc.filename_with_rev }})
Subject: {{ action_type }} Action: '{{ doc.title|clean_whitespace }}' to {{ doc|std_level_prompt }} ({{ doc.filename_with_rev }})
{% filter wordwrap:73 %}The IESG has approved the following document{{ docs|pluralize }}:{% for d in docs %}
- '{{ d.filled_title }}'
({{ d.filename_with_rev }}) as {{ d.full_status }}{% endfor %}
({{ d.filename_with_rev }}) as {{ d|std_level_prompt }}{% endfor %}
{{ made_by }}

View file

@ -1,13 +1,13 @@
{% autoescape off %}From: The IESG <iesg-secretary@ietf.org>
{% load mail_filters %}{% autoescape off %}From: The IESG <iesg-secretary@ietf.org>
To: {{to}}
Cc: The IESG <iesg@ietf.org>, <iana@iana.org>, <ietf-announce@ietf.org>
Subject: Results of IETF-conflict review for {{ doc.file_tag }}
{% filter wordwrap:73 %}
The IESG has completed a review of <{{ doc.name }}> consistent with RFC5742. This review is applied to all non-IETF streams.
{% if disapproved %}
The IESG recommends that '{{ doc.title }}' {{ doc.file_tag|safe }} NOT be published as {{ full_status }}.
The IESG recommends that '{{ doc.title }}' {{ doc.file_tag|safe }} NOT be published as {{ doc|std_level_prompt_with_article }}.
{% else %}
The IESG has no problem with the publication of '{{ doc.title }}' {{ doc.file_tag|safe }} as {{ full_status }}.
The IESG has no problem with the publication of '{{ doc.title }}' {{ doc.file_tag|safe }} as {{ doc|std_level_prompt_with_article }}.
The IESG would also like the IRSG or RFC-Editor to review the comments in the datatracker ({{ doc_url }}) related to this document and determine whether or not they merit incorporation into the document. Comments may exist in both the ballot and the history log.{% endif %}

View file

@ -1,7 +1,7 @@
{% autoescape off %}To: Internet Engineering Steering Group <iesg@ietf.org>
{% load mail_filters %}{% autoescape off %}To: Internet Engineering Steering Group <iesg@ietf.org>
From: IESG Secretary <iesg-secretary@ietf.org>
Reply-To: IESG Secretary <iesg-secretary@ietf.org>
Subject: Evaluation: {{ doc.file_tag }} to {{ status }}
Subject: Evaluation: {{ doc.file_tag }} to {{ doc|std_level_prompt }}
{% filter wordwrap:73 %}Evaluation for {{ doc.file_tag }} can be found at {{ doc_url }}

View file

@ -1,13 +1,13 @@
{% load ietf_filters %}{% autoescape off %}From: The IESG <iesg-secretary@ietf.org>
{% load ietf_filters %}{% load mail_filters %}{% autoescape off %}From: The IESG <iesg-secretary@ietf.org>
To: IETF-Announce <ietf-announce@ietf.org>{% if cc %}
CC: {{ cc }}{% endif %}
Reply-To: ietf@ietf.org
Subject: Last Call: {{ doc.file_tag }} ({{ doc.title|clean_whitespace }}) to {{ status }}
Subject: Last Call: {{ doc.file_tag }} ({{ doc.title|clean_whitespace }}) to {{ doc|std_level_prompt }}
{% filter wordwrap:73 %}
The IESG has received a request from {{ group }} to consider the following document{{ docs|pluralize }}:{% for d in docs %}
- '{{ d.filled_title }}'
{{ d.file_tag }} as {{ d.full_status }}{% endfor %}
{{ d.file_tag }} as {{ d|std_level_prompt }}{% endfor %}
The IESG plans to make a decision in the next few weeks, and solicits final comments on this action. Please send substantive comments to the ietf@ietf.org mailing lists by {{ expiration_date }}. Exceptionally, comments may be sent to iesg@ietf.org instead. In either case, please retain the beginning of the Subject line to allow automated sorting.{% endfilter %}
@ -20,10 +20,7 @@ Abstract{{ docs|pluralize }}
The file{{ urls|pluralize }} can be obtained via
{% for u in urls %}{{ u }}
{% endfor %}{% if impl_report %}
Implementation Report can be accessed at
http://www.ietf.org/iesg/implementation.html
{% endif %}
{% endfor %}
IESG discussion can be tracked via
{{ doc_url }}