Merged in branch/iola/shimfree@6856. This pretty much completes the shim removal. Next step is upgrading Django to 1.6, and then doing some final polishing.

- Legacy-Id: 6966
This commit is contained in:
Henrik Levkowetz 2013-12-17 21:29:05 +00:00
commit ecb5cd6526
509 changed files with 15650 additions and 33801 deletions

View file

@ -9,7 +9,7 @@ trap 'echo "$program($LINENO): Command failed with error code $? ($0 $*)"; exit
if [ "$*" ]; then apps="$@"; graph="${1%.*}"; else apps=$(ls */models.py | sed 's!/models.py!!'); graph="models"; fi
newapps="doc group meeting message person name"
legacyapps="announcements idindex idrfc idtracker iesg ietfauth ietfworkflows ipr liaisons mailinglists proceedings redirects submit wgchairs wgcharter wginfo"
legacyapps="announcements idindex idrfc idtracker iesg ietfauth ipr liaisons mailinglists proceedings redirects submit wgcharter wginfo"
proxy="$(grep ^class */proxy.py | tr '()' ' ' | awk '{printf $2 ","}')"
names="$(grep ^class name/models.py | tr '()' ' ' | awk '{printf $2 ","}')"

View file

@ -24,8 +24,6 @@ try:
except ImportError:
debug = True
from decorator import decorator
# A debug decorator, written by Paul Butler, taken from
# http://paulbutler.org/archives/python-debugging-with-decorators/
# Additional functions and decorator functionality added by
@ -78,6 +76,7 @@ def trace(fn): # renamed from 'report' by henrik 16 Jun 2011
return ret
wrap.callcount = 0
if debug:
from decorator import decorator
return decorator(wrap, fn)
else:
return fn
@ -109,6 +108,7 @@ def time(fn):
return ret
wrap.callcount = 0
if debug:
from decorator import decorator
return decorator(wrap, fn)
else:
return fn
@ -169,6 +169,7 @@ def profile(fn):
prof.dump_stats(datafn)
return retval
if debug:
from decorator import decorator
return decorator(wrapper, fn)
else:
return fn

View file

@ -1,2 +0,0 @@
/*.pyc
/settings_local.py

View file

@ -1,2 +0,0 @@
# Copyright The IETF Trust 2007, All Rights Reserved

View file

@ -1,88 +0,0 @@
# Copyright The IETF Trust 2007, All Rights Reserved
from django.db import models
from django.conf import settings
from ietf.idtracker.models import PersonOrOrgInfo, ChairsHistory
#from django.contrib.auth.models import Permission
# I don't know why the IETF database mostly stores times
# as char(N) instead of TIME. Until it's important, let's
# keep them as char here too.
# email is not used; the announced_from text is Foo Bar <foo@bar.com>
class AnnouncedFrom(models.Model):
announced_from_id = models.AutoField(primary_key=True)
announced_from = models.CharField(blank=True, max_length=255, db_column='announced_from_value')
email = models.CharField(blank=True, max_length=255, db_column='announced_from_email', editable=False)
#permission = models.ManyToManyField(Permission, limit_choices_to={'codename__endswith':'announcedfromperm'}, verbose_name='Permission Required', blank=True)
def __str__(self):
return self.announced_from
class Meta:
db_table = 'announced_from'
#permissions = (
# ("ietf_chair_announcedfromperm", "Can send messages from IETF Chair"),
# ("iab_chair_announcedfromperm", "Can send messages from IAB Chair"),
# ("iad_announcedfromperm", "Can send messages from IAD"),
# ("ietf_execdir_announcedfromperm", "Can send messages from IETF Executive Director"),
# ("other_announcedfromperm", "Can send announcements from others"),
#)
class AnnouncedTo(models.Model):
announced_to_id = models.AutoField(primary_key=True)
announced_to = models.CharField(blank=True, max_length=255, db_column='announced_to_value')
email = models.CharField(blank=True, max_length=255, db_column='announced_to_email')
def __str__(self):
return self.announced_to
class Meta:
db_table = 'announced_to'
class Announcement(models.Model):
announcement_id = models.AutoField(primary_key=True)
announced_by = models.ForeignKey(PersonOrOrgInfo, db_column='announced_by')
announced_date = models.DateField(null=True, blank=True)
announced_time = models.CharField(blank=True, max_length=20)
text = models.TextField(blank=True, db_column='announcement_text')
announced_from = models.ForeignKey(AnnouncedFrom)
cc = models.CharField(blank=True, null=True, max_length=255)
subject = models.CharField(blank=True, max_length=255)
extra = models.TextField(blank=True,null=True)
announced_to = models.ForeignKey(AnnouncedTo)
nomcom = models.NullBooleanField()
nomcom_chair = models.ForeignKey(ChairsHistory, null=True, blank=True)
manually_added = models.BooleanField(db_column='manualy_added')
other_val = models.CharField(blank=True, null=True, max_length=255)
def __str__(self):
return "Announcement from %s to %s on %s %s" % (self.announced_from, self.announced_to, self.announced_date, self.announced_time)
def from_name(self):
if self.announced_from_id == 99:
return self.other_val
if self.announced_from_id == 18: # sigh hardcoding
return self.nomcom_chair.person
return self.announced_from
class Meta:
db_table = 'announcements'
class ScheduledAnnouncement(models.Model):
mail_sent = models.BooleanField()
to_be_sent_date = models.DateField(null=True, blank=True)
to_be_sent_time = models.CharField(blank=True, null=True, max_length=50)
scheduled_by = models.CharField(blank=True, max_length=100)
scheduled_date = models.DateField(null=True, blank=True)
scheduled_time = models.CharField(blank=True, max_length=50)
subject = models.CharField(blank=True, max_length=255)
to_val = models.CharField(blank=True, max_length=255)
from_val = models.CharField(blank=True, max_length=255)
cc_val = models.TextField(blank=True,null=True)
body = models.TextField(blank=True)
actual_sent_date = models.DateField(null=True, blank=True)
actual_sent_time = models.CharField(blank=True, max_length=50) # should be time, but database contains oddities
first_q = models.IntegerField(null=True, blank=True)
second_q = models.IntegerField(null=True, blank=True)
note = models.TextField(blank=True,null=True)
content_type = models.CharField(blank=True, max_length=255)
replyto = models.CharField(blank=True, null=True, max_length=255)
bcc_val = models.CharField(blank=True, null=True, max_length=255)
def __str__(self):
return "Scheduled Announcement from %s to %s on %s %s" % (self.from_val, self.to_val, self.to_be_sent_date, self.to_be_sent_time)
class Meta:
db_table = 'scheduled_announcements'

View file

@ -1,68 +0,0 @@
import re, datetime, email
from django.conf import settings
from ietf.utils.mail import send_mail_text, send_mail_mime
first_dot_on_line_re = re.compile(r'^\.', re.MULTILINE)
def send_scheduled_announcement(announcement):
# for some reason, the old Perl code base substituted away . on line starts
body = first_dot_on_line_re.sub("", announcement.body)
extra = {}
if announcement.replyto:
extra['Reply-To'] = announcement.replyto
# announcement.content_type can contain a case-sensitive parts separator,
# so we need to keep it as is, not lowercased, but we want a lowercased
# version for the coming comparisons.
content_type_lowercase = announcement.content_type.lower()
if not content_type_lowercase or 'text/plain' in content_type_lowercase:
send_mail_text(None, announcement.to_val, announcement.from_val, announcement.subject,
body, cc=announcement.cc_val, bcc=announcement.bcc_val)
elif 'multipart/' in content_type_lowercase:
# make body a real message so we can parse it.
body = ("MIME-Version: 1.0\r\nContent-Type: %s\r\n" % announcement.content_type) + body
msg = email.message_from_string(body.encode("utf-8"))
send_mail_mime(None, announcement.to_val, announcement.from_val, announcement.subject,
msg, cc=announcement.cc_val, bcc=announcement.bcc_val)
now = datetime.datetime.now()
announcement.actual_sent_date = now.date()
announcement.actual_sent_time = str(now.time())
announcement.mail_sent = True
announcement.save()
def send_scheduled_announcementREDESIGN(send_queue):
message = send_queue.message
# for some reason, the old Perl code base substituted away . on line starts
body = first_dot_on_line_re.sub("", message.body)
extra = {}
if message.reply_to:
extra['Reply-To'] = message.reply_to
# announcement.content_type can contain a case-sensitive parts separator,
# so we need to keep it as is, not lowercased, but we want a lowercased
# version for the coming comparisons.
content_type_lowercase = message.content_type.lower()
if not content_type_lowercase or 'text/plain' in content_type_lowercase:
send_mail_text(None, message.to, message.frm, message.subject,
body, cc=message.cc, bcc=message.bcc)
elif 'multipart' in content_type_lowercase:
# make body a real message so we can parse it
body = ("MIME-Version: 1.0\r\nContent-Type: %s\r\n" % message.content_type) + body
msg = email.message_from_string(body.encode("utf-8"))
send_mail_mime(None, message.to, message.frm, message.subject,
msg, cc=message.cc, bcc=message.bcc)
send_queue.sent_at = datetime.datetime.now()
send_queue.save()
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
send_scheduled_announcement = send_scheduled_announcementREDESIGN

View file

@ -1,18 +0,0 @@
# Copyright The IETF Trust 2007, All Rights Reserved
from django.conf import settings
from django.contrib.sitemaps import Sitemap
from ietf.announcements.models import Announcement
from ietf.message.models import Message
class NOMCOMAnnouncementsMap(Sitemap):
changefreq = "never"
def items(self):
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
return Message.objects.filter(related_groups__acronym__startswith="nomcom").exclude(related_groups__acronym="nomcom").order_by('-time')
return Announcement.objects.all().filter(nomcom=True)
def location(self, obj):
return "/ann/nomcom/%d/" % obj.id
def lastmod(self, obj):
# could re-parse the time into a datetime object
return obj.time

View file

@ -1,133 +0,0 @@
import datetime
from django.conf import settings
from ietf.utils.test_utils import SimpleUrlTestCase, canonicalize_sitemap
from ietf.utils.test_data import make_test_data
from ietf.utils.mail import outbox
from ietf.utils import TestCase
from ietf.announcements.models import ScheduledAnnouncement
from ietf.message.models import Message, SendQueue
from ietf.person.models import Person
class AnnouncementsUrlTestCase(SimpleUrlTestCase):
def testUrls(self):
self.doTestUrls(__file__)
def doCanonicalize(self, url, content):
if url.startswith("/sitemap"):
return canonicalize_sitemap(content)
else:
return content
class SendScheduledAnnouncementsTestCase(TestCase):
def test_send_plain_announcement(self):
a = ScheduledAnnouncement.objects.create(
mail_sent=False,
subject="This is a test",
to_val="test@example.com",
from_val="testmonkey@example.com",
cc_val="cc.a@example.com, cc.b@example.com",
bcc_val="bcc@example.com",
body="Hello World!",
content_type="",
)
mailbox_before = len(outbox)
from ietf.announcements.send_scheduled import send_scheduled_announcement
send_scheduled_announcement(a)
self.assertEquals(len(outbox), mailbox_before + 1)
self.assertTrue("This is a test" in outbox[-1]["Subject"])
self.assertTrue(ScheduledAnnouncement.objects.get(id=a.id).mail_sent)
def test_send_mime_announcement(self):
a = ScheduledAnnouncement.objects.create(
mail_sent=False,
subject="This is a test",
to_val="test@example.com",
from_val="testmonkey@example.com",
cc_val="cc.a@example.com, cc.b@example.com",
bcc_val="bcc@example.com",
body='--NextPart\r\n\r\nA New Internet-Draft is available from the on-line Internet-Drafts directories.\r\n--NextPart\r\nContent-Type: Message/External-body;\r\n\tname="draft-huang-behave-bih-01.txt";\r\n\tsite="ftp.ietf.org";\r\n\taccess-type="anon-ftp";\r\n\tdirectory="internet-drafts"\r\n\r\nContent-Type: text/plain\r\nContent-ID: <2010-07-30001541.I-D@ietf.org>\r\n\r\n--NextPart--',
content_type='Multipart/Mixed; Boundary="NextPart"',
)
mailbox_before = len(outbox)
from ietf.announcements.send_scheduled import send_scheduled_announcement
send_scheduled_announcement(a)
self.assertEquals(len(outbox), mailbox_before + 1)
self.assertTrue("This is a test" in outbox[-1]["Subject"])
self.assertTrue("--NextPart" in outbox[-1].as_string())
self.assertTrue(ScheduledAnnouncement.objects.get(id=a.id).mail_sent)
class SendScheduledAnnouncementsTestCaseREDESIGN(TestCase):
# See ietf.utils.test_utils.TestCase for the use of perma_fixtures vs. fixtures
perma_fixtures = ["names"]
def test_send_plain_announcement(self):
make_test_data()
msg = Message.objects.create(
by=Person.objects.get(name="(System)"),
subject="This is a test",
to="test@example.com",
frm="testmonkey@example.com",
cc="cc.a@example.com, cc.b@example.com",
bcc="bcc@example.com",
body="Hello World!",
content_type="",
)
q = SendQueue.objects.create(
by=Person.objects.get(name="(System)"),
message=msg,
send_at=datetime.datetime.now() + datetime.timedelta(hours=12)
)
mailbox_before = len(outbox)
from ietf.announcements.send_scheduled import send_scheduled_announcement
send_scheduled_announcement(q)
self.assertEquals(len(outbox), mailbox_before + 1)
self.assertTrue("This is a test" in outbox[-1]["Subject"])
self.assertTrue(SendQueue.objects.get(id=q.id).sent_at)
def test_send_mime_announcement(self):
make_test_data()
msg = Message.objects.create(
by=Person.objects.get(name="(System)"),
subject="This is a test",
to="test@example.com",
frm="testmonkey@example.com",
cc="cc.a@example.com, cc.b@example.com",
bcc="bcc@example.com",
body='--NextPart\r\n\r\nA New Internet-Draft is available from the on-line Internet-Drafts directories.\r\n--NextPart\r\nContent-Type: Message/External-body;\r\n\tname="draft-huang-behave-bih-01.txt";\r\n\tsite="ftp.ietf.org";\r\n\taccess-type="anon-ftp";\r\n\tdirectory="internet-drafts"\r\n\r\nContent-Type: text/plain\r\nContent-ID: <2010-07-30001541.I-D@ietf.org>\r\n\r\n--NextPart--',
content_type='Multipart/Mixed; Boundary="NextPart"',
)
q = SendQueue.objects.create(
by=Person.objects.get(name="(System)"),
message=msg,
send_at=datetime.datetime.now() + datetime.timedelta(hours=12)
)
mailbox_before = len(outbox)
from ietf.announcements.send_scheduled import send_scheduled_announcement
send_scheduled_announcement(q)
self.assertEquals(len(outbox), mailbox_before + 1)
self.assertTrue("This is a test" in outbox[-1]["Subject"])
self.assertTrue("--NextPart" in outbox[-1].as_string())
self.assertTrue(SendQueue.objects.get(id=q.id).sent_at)
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
SendScheduledAnnouncementsTestCase = SendScheduledAnnouncementsTestCaseREDESIGN

View file

@ -1,5 +0,0 @@
200 /ann/nomcom/
200 /ann/nomcom/1230/
200 /ann/nomcom/1607/ # non-ASCII content
200 /ann/nomcom/2001/ # non-ASCII content
200 /sitemap-nomcom-announcements.xml

View file

@ -1,16 +0,0 @@
# Copyright The IETF Trust 2007, All Rights Reserved
from django.conf.urls.defaults import patterns
from ietf.announcements.models import Announcement
from django.conf import settings
nomcom_dict = {
'queryset': Announcement.objects.all().filter(nomcom=True)
}
urlpatterns = patterns('',
# (r'^nomcom/$', 'django.views.generic.simple.redirect_to', {'url': 'http://www.ietf.org/nomcom/index.html'} ),
(r'^nomcom/$', 'ietf.announcements.views.nomcom'),
(r'^nomcom/(?P<object_id>\d+)/$', 'ietf.announcements.views.message_detail') if settings.USE_DB_REDESIGN_PROXY_CLASSES else (r'^nomcom/(?P<object_id>\d+)/$', 'django.views.generic.list_detail.object_detail', nomcom_dict)
)

View file

@ -1,88 +0,0 @@
# Copyright The IETF Trust 2007, All Rights Reserved
from django.views.generic.simple import direct_to_template
from django.shortcuts import get_object_or_404
from django.conf import settings
from django.db.models import Q
import re
from ietf.idtracker.models import ChairsHistory
from ietf.idtracker.models import Role
from ietf.announcements.models import Announcement
from ietf.group.models import Group, GroupEvent
from ietf.message.models import Message
def nomcom(request):
curr_chair = (ChairsHistory.objects.
get(chair_type=Role.NOMCOM_CHAIR, present_chair='1'))
all_chairs = (ChairsHistory.objects.all().
filter(chair_type='3',start_year__gt = 2003).
order_by('-start_year'))
nomcom_announcements = Announcement.objects.all().filter(nomcom=1)
regimes = []
for chair in all_chairs:
chair_announcements = (nomcom_announcements.filter(nomcom_chair=chair).
order_by('-announced_date','-announced_time'))
regimes = regimes + [{'chair': chair,
'announcements' : chair_announcements }]
return direct_to_template(request,
"announcements/nomcom.html",
{ 'curr_chair' : curr_chair,
'regimes' : regimes })
def nomcomREDESIGN(request):
address_re = re.compile("<.*>")
nomcoms = list(Group.objects.filter(acronym__startswith="nomcom").exclude(name="nomcom"))
regimes = []
for n in nomcoms:
e = GroupEvent.objects.filter(group=n, type="changed_state", changestategroupevent__state="active").order_by('time')[:1]
n.start_year = e[0].time.year if e else 0
if n.start_year <= 2003:
continue
e = GroupEvent.objects.filter(group=n, type="changed_state", changestategroupevent__state="conclude").order_by('time')[:1]
n.end_year = e[0].time.year if e else ""
r = n.role_set.select_related().filter(name="chair")
chair = None
if r:
chair = r[0]
announcements = Message.objects.filter(related_groups=n).order_by('-time')
for a in announcements:
a.to_name = address_re.sub("", a.to)
regimes.append(dict(chair=chair,
announcements=announcements,
group=n))
regimes.sort(key=lambda x: x["group"].start_year, reverse=True)
return direct_to_template(request,
"announcements/nomcomREDESIGN.html",
{ 'curr_chair' : regimes[0]["chair"],
'regimes' : regimes })
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
nomcom = nomcomREDESIGN
def message_detail(request, object_id):
# restrict to nomcom announcements for the time being
nomcoms = Group.objects.filter(acronym__startswith="nomcom").exclude(acronym="nomcom")
m = get_object_or_404(Message, id=object_id,
related_groups__in=nomcoms)
return direct_to_template(request,
"announcements/message_detail.html",
dict(message=m))

View file

@ -12,15 +12,21 @@ os.environ["DJANGO_SETTINGS_MODULE"] = "ietf.settings"
from django.template import Template, Context
from ietf.idtracker.models import IDInternal
#from ietf.idtracker.models import InternetDraft
#from ietf.idtracker.models import IDStatus
from ietf.doc.models import Document
from ietf.person.models import Person
drafts = IDInternal.objects.all()
drafts = Document.objects.filter(type="draft")
templ_text = """{% for draft in drafts %}{% if draft.state_change_notice_to or draft.job_owner %}{% if draft.draft.filename %}{{ draft.draft.filename }}{% if draft.state_change_notice_to %} docnotify='{{ draft.state_change_notice_to|cut:"<"|cut:">" }}'{% endif %}{% if draft.job_owner %} docsponsor='{{ draft.job_owner.person.email.1 }}'{% endif %}
{% endif %}{% endif %}{% endfor %}"""
ads = {}
for p in Person.objects.filter(ad_document_set__type="draft").distinct():
ads[p.id] = p.role_email("ad")
for d in drafts:
d.ad_email = ads.get(d.ad_id)
templ_text = """{% for draft in drafts %}{% if draft.notify or draft.ad_email %}{{ draft.name }}{% if draft.notify %} docnotify='{{ draft.notify|cut:"<"|cut:">" }}'{% endif %}{% if draft.ad_email %} docsponsor='{{ draft.ad_email }}'{% endif %}
{% endif %}{% endfor %}"""
template = Template(templ_text)
context = Context({ 'drafts':drafts })
context = Context({ 'drafts':drafts })
print template.render(context)
print template.render(context).encode('utf-8')

View file

@ -0,0 +1,20 @@
#!/usr/bin/env python
import datetime, os
import syslog
from ietf import settings
from django.core import management
management.setup_environ(settings)
syslog.openlog(os.path.basename(__file__), syslog.LOG_PID, syslog.LOG_USER)
from ietf.person.models import Person
from ietf.submit.utils import expirable_submissions, expire_submission
system = Person.objects.get(name="(System)")
for sub in expirable_submissions(older_than_days=30):
expire_submission(sub, system)
syslog.syslog("Expired submission %s of %s-%s" % (sub.pk, sub.name, sub.rev))

View file

@ -31,7 +31,7 @@ from django.conf import settings
from ietf.utils.path import path as Path
from ietf.submit.models import IdSubmissionDetail
from ietf.submit.models import Submission
from ietf.doc.models import Document
@ -56,13 +56,13 @@ from_email = settings.IDSUBMIT_FROM_EMAIL
if "<" in from_email:
from_email = from_email.split("<")[1].split(">")[0]
submission = IdSubmissionDetail.objects.filter(filename=draft).latest('submission_date')
submission = Submission.objects.filter(name=draft).latest('submission_date')
document = Document.objects.get(name=draft)
emails = [ author.address for author in document.authors.all() ]
timestrings = []
for file in [ Path(settings.INTERNET_DRAFT_PATH) / ("%s-%s.txt"%(draft, submission.revision)),
Path(settings.IDSUBMIT_STAGING_PATH) / ("%s-%s.txt"%(draft, submission.revision)) ]:
for file in [ Path(settings.INTERNET_DRAFT_PATH) / ("%s-%s.txt"%(draft, submission.rev)),
Path(settings.IDSUBMIT_STAGING_PATH) / ("%s-%s.txt"%(draft, submission.rev)) ]:
if os.path.exists(file):
upload_time = time.localtime(file.mtime)
ts = time.strftime("%b %d %H:%M", upload_time)
@ -95,4 +95,3 @@ for log in logfiles:
for qi in queue_ids:
if qi in line:
sys.stdout.write(line)

View file

@ -10,42 +10,24 @@ management.setup_environ(settings)
syslog.openlog(os.path.basename(__file__), syslog.LOG_PID, syslog.LOG_USER)
from ietf.announcements.models import ScheduledAnnouncement
from ietf.announcements.send_scheduled import *
from django.db.models import Q
if len(sys.argv) != 2 or sys.argv[1] not in ('all', 'rsync', 'specific'):
print "USAGE: %s <all | rsync | specific>" % os.path.basename(__file__)
print "USAGE: %s <all | specific>" % os.path.basename(__file__)
print "'all' means all not sent"
print "'rsync' means all not sent where to-be-sent-date is null"
print "'specific' means all not sent that are due to be sent"
sys.exit(1)
from ietf.message.utils import send_scheduled_message_from_send_queue
from ietf.message.models import SendQueue
mode = sys.argv[1]
now = datetime.datetime.now()
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
from ietf.message.models import SendQueue
announcements = SendQueue.objects.filter(sent_at=None)
if mode == "rsync":
announcements = announcements.filter(send_at=None)
elif mode == "specific":
announcements = announcements.exclude(send_at=None).filter(send_at__lte=now)
else:
announcements = ScheduledAnnouncement.objects.filter(mail_sent=False)
if mode == "rsync":
# include bogus 0000-00-00 entries
announcements = announcements.filter(Q(to_be_sent_date=None) | Q(to_be_sent_date__lte=datetime.date.min))
elif mode == "specific":
# exclude null/bogus entries
announcements = announcements.exclude(Q(to_be_sent_date=None) | Q(to_be_sent_date__lte=datetime.date.min))
needs_sending = SendQueue.objects.filter(sent_at=None).select_related("message")
if mode == "specific":
needs_sending = needs_sending.exclude(send_at=None).filter(send_at__lte=now)
announcements = announcements.filter(to_be_sent_date__lte=now.date(),
to_be_sent_time__lte=now.time())
for announcement in announcements:
send_scheduled_announcement(announcement)
for s in needs_sending:
send_scheduled_message_from_send_queue(s)
subject = announcement.message.subject if settings.USE_DB_REDESIGN_PROXY_CLASSES else announcement.subject
syslog.syslog(u'Sent scheduled announcement %s "%s"' % (announcement.id, subject))
syslog.syslog(u'Sent scheduled message %s "%s"' % (s.id, s.message.subject))

View file

@ -24,7 +24,7 @@ connection.queries = DontSaveQueries()
MAX_URL_LENGTH = 500
SLOW_THRESHOLD = 1.0
initial = ["/doc/all/", "/doc/in-last-call/"]
initial = ["/doc/all/", "/doc/in-last-call/", "/iesg/decisions/"]
visited = set()
urls = {} # url -> referrer

View file

@ -3,7 +3,6 @@ import datetime
from django.db.models import Q
from django.core.urlresolvers import reverse as urlreverse
from ietf.ietfworkflows.utils import get_state_for_draft
from ietf.doc.models import DocAlias, DocEvent

View file

@ -5,18 +5,18 @@ from django.db.models import Q
from ietf.community.constants import SIGNIFICANT_STATES
from ietf.community.models import DocumentChangeDates
from redesign.doc.models import Document
from ietf.doc.models import Document
class Command(BaseCommand):
help = (u"Update drafts in community lists by reviewing their rules")
def handle(self, *args, **options):
documents = Document.objects.filter(Q(type__name='Draft') | Q(states__name='rfc')).distinct()
documents = Document.objects.filter(type='draft')
index = 1
total = documents.count()
for doc in documents:
for doc in documents.iterator():
(changes, created) = DocumentChangeDates.objects.get_or_create(document=doc)
new_version = doc.latest_event(type='new_revision')
normal_change = doc.latest_event()

View file

@ -51,7 +51,7 @@ def expires_soon(request, days="14"):
def full_draft(request, enabled="off"):
if enabled != "on" and enabled != "off":
enabled = "off"
enabled = "off"
response = settings(request, -1, -1, enabled)
response.set_cookie("full_draft", enabled, 315360000)
return response

View file

@ -5,7 +5,7 @@ from django.template import RequestContext
from ietf.dbtemplate.models import DBTemplate
from ietf.dbtemplate.forms import DBTemplateForm
from ietf.group.models import Group
from ietf.ietfauth.decorators import has_role
from ietf.ietfauth.utils import has_role
def template_list(request, acronym):

View file

@ -9,7 +9,7 @@ from django.core.urlresolvers import reverse as urlreverse
from ietf.utils.mail import send_mail, send_mail_text
from ietf.ipr.search import iprs_from_docs, related_docs
from ietf.doc.models import WriteupDocEvent, BallotPositionDocEvent, LastCallDocEvent, DocAlias, ConsensusDocEvent
from ietf.doc.models import WriteupDocEvent, BallotPositionDocEvent, LastCallDocEvent, DocAlias, ConsensusDocEvent, DocTagName
from ietf.person.models import Person
from ietf.group.models import Group, Role
@ -413,3 +413,66 @@ def email_last_call_expired(doc):
doc=doc,
url=settings.IDTRACKER_BASE_URL + doc.get_absolute_url()),
cc="iesg-secretary@ietf.org")
def stream_state_email_recipients(doc, extra_recipients=[]):
persons = set()
res = []
for r in Role.objects.filter(group=doc.group, name__in=("chair", "delegate")).select_related("person", "email"):
res.append(r.formatted_email())
persons.add(r.person)
for email in doc.authors.all():
if email.person not in persons:
res.append(email.formatted_email())
persons.add(email.person)
for p in extra_recipients:
if not p in persons:
res.append(p.formatted_email())
persons.add(p)
return res
def email_draft_adopted(request, doc, by, comment):
recipients = stream_state_email_recipients(doc)
send_mail(request, recipients, settings.DEFAULT_FROM_EMAIL,
u"%s adopted in %s %s" % (doc.name, doc.group.acronym, doc.group.type.name),
'doc/mail/draft_adopted_email.txt',
dict(doc=doc,
url=settings.IDTRACKER_BASE_URL + doc.get_absolute_url(),
by=by,
comment=comment))
def email_stream_state_changed(request, doc, prev_state, new_state, by, comment=""):
recipients = stream_state_email_recipients(doc)
state_type = (prev_state or new_state).type
send_mail(request, recipients, settings.DEFAULT_FROM_EMAIL,
u"%s changed for %s" % (state_type.label, doc.name),
'doc/mail/stream_state_changed_email.txt',
dict(doc=doc,
url=settings.IDTRACKER_BASE_URL + doc.get_absolute_url(),
state_type=state_type,
prev_state=prev_state,
new_state=new_state,
by=by,
comment=comment))
def email_stream_tags_changed(request, doc, added_tags, removed_tags, by, comment=""):
extra_recipients = []
if DocTagName.objects.get(slug="sheph-u") in added_tags and doc.shepherd:
extra_recipients.append(doc.shepherd)
recipients = stream_state_email_recipients(doc, extra_recipients)
send_mail(request, recipients, settings.DEFAULT_FROM_EMAIL,
u"Tags changed for %s" % doc.name,
'doc/mail/stream_tags_changed_email.txt',
dict(doc=doc,
url=settings.IDTRACKER_BASE_URL + doc.get_absolute_url(),
added=added_tags,
removed=removed_tags,
by=by,
comment=comment))

View file

@ -0,0 +1,435 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
class Migration(DataMigration):
def forwards(self, orm):
state_mapping = dict((s.name.lower(), s) for s in orm.State.objects.filter(type="draft-iesg"))
doc_type_mapping = {
'draft': " the document",
'conflrev': " the conflict review response",
'statchg': " the status change",
'charter': " the charter",
}
import re
approve_re = re.compile(r"IESG has approved( the charter| the document| the conflict review response| the status change)?( and state has been changed to '?(.*?)'?( by .*)?\.?)?$")
disapprove_re = re.compile("(DNP|Do Not Publish) note has been sent to( the)? RFC Editor( and state has been changed to '?(.*?)'?( by .*)?\.?)?$")
for e in orm.DocEvent.objects.filter(type__in=("iesg_disapproved", "iesg_approved")).order_by("id").select_related("doc").iterator():
if e.type == "iesg_approved":
m = approve_re.match(e.desc)
if not m:
print "FAIL", e.desc
else:
doc_type, state_set, state_name, by = m.groups()
if state_set:
state = state_mapping[state_name.lower()]
s = orm.StateDocEvent()
s.doc_id = e.doc_id
s.by_id = e.by_id
s.type = "changed_state"
s.state_type_id = state.type_id
s.state = state
s.desc = "%s changed to <b>%s</b>" % (state.type.label, state.name)
s.time = e.time
s.save()
#print e.doc_id, s.desc
if not doc_type:
doc_type = doc_type_mapping[e.doc.type_id]
new_desc = "IESG has approved%s" % doc_type
if new_desc != e.desc:
#print e.doc_id, e.desc, "->", new_desc
orm.DocEvent.objects.filter(id=e.id).update(desc=new_desc)
elif e.type == "iesg_disapproved":
m = disapprove_re.match(e.desc)
if not m:
print "FAIL", e.desc
else:
dnp, the, state_set, state_name, by = m.groups()
if state_set:
state = state_mapping[state_name.lower()]
s = orm.StateDocEvent()
s.doc_id = e.doc_id
s.by_id = e.by_id
s.type = "changed_state"
s.state_type_id = state.type_id
s.state = state
s.desc = "%s changed to <b>%s</b>" % (state.type.label, state.name)
s.time = e.time
s.save()
#print e.doc_id, s.desc
new_desc = "Do Not Publish note has been sent to the RFC Editor"
if new_desc != e.desc:
#print e.doc_id, e.desc, "->", new_desc
orm.DocEvent.objects.filter(id=e.id).update(desc=new_desc)
def backwards(self, orm):
"Write your backwards methods here."
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'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': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'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', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'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', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'})
},
'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'}),
'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'})
},
'doc.ballotdocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'BallotDocEvent', '_ormbases': ['doc.DocEvent']},
'ballot_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.BallotType']"}),
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'})
},
'doc.ballotpositiondocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'BallotPositionDocEvent', '_ormbases': ['doc.DocEvent']},
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
'ballot': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "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'}),
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
'pos': ('django.db.models.fields.related.ForeignKey', [], {'default': "'norecord'", 'to': "orm['name.BallotPositionName']"})
},
'doc.ballottype': {
'Meta': {'ordering': "['order']", 'object_name': 'BallotType'},
'doc_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'}),
'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': "orm['name.BallotPositionName']", 'symmetrical': 'False', 'blank': 'True'}),
'question': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'doc.consensusdocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'ConsensusDocEvent', '_ormbases': ['doc.DocEvent']},
'consensus': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'})
},
'doc.deletedevent': {
'Meta': {'object_name': 'DeletedEvent'},
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'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'})
},
'doc.docalias': {
'Meta': {'object_name': 'DocAlias'},
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
},
'doc.docevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'DocEvent'},
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
'desc': ('django.db.models.fields.TextField', [], {}),
'doc': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
'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'})
},
'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': "orm['person.Person']"}),
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['person.Email']", 'symmetrical': 'False', 'through': "orm['doc.DocHistoryAuthor']", 'blank': 'True'}),
'doc': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'history_set'", 'to': "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': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "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': "orm['doc.DocAlias']", 'symmetrical': 'False', 'through': "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': "orm['person.Person']"}),
'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StreamName']", 'null': 'True', 'blank': 'True'}),
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "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': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
},
'doc.dochistoryauthor': {
'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocHistoryAuthor'},
'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocHistory']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {})
},
'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': "orm['doc.DocEvent']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocReminderTypeName']"})
},
'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': "orm['person.Person']"}),
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['person.Email']", 'symmetrical': 'False', 'through': "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': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "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': "orm['person.Person']"}),
'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StreamName']", 'null': 'True', 'blank': 'True'}),
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "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': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
},
'doc.documentauthor': {
'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocumentAuthor'},
'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '1'})
},
'doc.initialreviewdocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'InitialReviewDocEvent', '_ormbases': ['doc.DocEvent']},
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
},
'doc.lastcalldocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'LastCallDocEvent', '_ormbases': ['doc.DocEvent']},
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
},
'doc.newrevisiondocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'NewRevisionDocEvent', '_ormbases': ['doc.DocEvent']},
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16'})
},
'doc.relateddochistory': {
'Meta': {'object_name': 'RelatedDocHistory'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocRelationshipName']"}),
'source': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocHistory']"}),
'target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reversely_related_document_history_set'", 'to': "orm['doc.DocAlias']"})
},
'doc.relateddocument': {
'Meta': {'object_name': 'RelatedDocument'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocRelationshipName']"}),
'source': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
'target': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocAlias']"})
},
'doc.state': {
'Meta': {'ordering': "['type', 'order']", 'object_name': 'State'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'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': "orm['doc.State']"}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.StateType']"}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'doc.statedocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'StateDocEvent', '_ormbases': ['doc.DocEvent']},
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.State']", 'null': 'True', 'blank': 'True'}),
'state_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.StateType']"})
},
'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'})
},
'doc.telechatdocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'TelechatDocEvent', '_ormbases': ['doc.DocEvent']},
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "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'})
},
'doc.writeupdocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'WriteupDocEvent', '_ormbases': ['doc.DocEvent']},
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
'text': ('django.db.models.fields.TextField', [], {'blank': 'True'})
},
'group.group': {
'Meta': {'object_name': 'Group'},
'acronym': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '40', 'db_index': 'True'}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "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': "orm['doc.Document']"}),
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'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': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']", 'null': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupTypeName']", 'null': 'True'}),
'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'})
},
'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'})
},
'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'})
},
'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'})
},
'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'})
},
'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'})
},
'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'})
},
'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'})
},
'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'})
},
'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'})
},
'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'})
},
'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': "orm['person.Person']", 'null': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
},
'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'}),
'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': "orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'})
}
}
complete_apps = ['doc']

View file

@ -0,0 +1,370 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding index on 'DocEvent', fields ['time']
db.create_index('doc_docevent', ['time'])
def backwards(self, orm):
# Removing index on 'DocEvent', fields ['time']
db.delete_index('doc_docevent', ['time'])
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'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': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'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', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'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', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'})
},
'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'}),
'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'})
},
'doc.ballotdocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'BallotDocEvent', '_ormbases': ['doc.DocEvent']},
'ballot_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.BallotType']"}),
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'})
},
'doc.ballotpositiondocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'BallotPositionDocEvent', '_ormbases': ['doc.DocEvent']},
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
'ballot': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "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'}),
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
'pos': ('django.db.models.fields.related.ForeignKey', [], {'default': "'norecord'", 'to': "orm['name.BallotPositionName']"})
},
'doc.ballottype': {
'Meta': {'ordering': "['order']", 'object_name': 'BallotType'},
'doc_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'}),
'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': "orm['name.BallotPositionName']", 'symmetrical': 'False', 'blank': 'True'}),
'question': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'doc.consensusdocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'ConsensusDocEvent', '_ormbases': ['doc.DocEvent']},
'consensus': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'})
},
'doc.deletedevent': {
'Meta': {'object_name': 'DeletedEvent'},
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'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'})
},
'doc.docalias': {
'Meta': {'object_name': 'DocAlias'},
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
},
'doc.docevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'DocEvent'},
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
'desc': ('django.db.models.fields.TextField', [], {}),
'doc': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
'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'})
},
'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': "orm['person.Person']"}),
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['person.Email']", 'symmetrical': 'False', 'through': "orm['doc.DocHistoryAuthor']", 'blank': 'True'}),
'doc': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'history_set'", 'to': "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': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "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': "orm['doc.DocAlias']", 'symmetrical': 'False', 'through': "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': "orm['person.Person']"}),
'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StreamName']", 'null': 'True', 'blank': 'True'}),
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "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': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
},
'doc.dochistoryauthor': {
'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocHistoryAuthor'},
'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocHistory']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {})
},
'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': "orm['doc.DocEvent']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocReminderTypeName']"})
},
'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': "orm['person.Person']"}),
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['person.Email']", 'symmetrical': 'False', 'through': "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': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "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': "orm['person.Person']"}),
'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StreamName']", 'null': 'True', 'blank': 'True'}),
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "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': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
},
'doc.documentauthor': {
'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocumentAuthor'},
'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '1'})
},
'doc.initialreviewdocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'InitialReviewDocEvent', '_ormbases': ['doc.DocEvent']},
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
},
'doc.lastcalldocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'LastCallDocEvent', '_ormbases': ['doc.DocEvent']},
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
},
'doc.newrevisiondocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'NewRevisionDocEvent', '_ormbases': ['doc.DocEvent']},
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16'})
},
'doc.relateddochistory': {
'Meta': {'object_name': 'RelatedDocHistory'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocRelationshipName']"}),
'source': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocHistory']"}),
'target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reversely_related_document_history_set'", 'to': "orm['doc.DocAlias']"})
},
'doc.relateddocument': {
'Meta': {'object_name': 'RelatedDocument'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocRelationshipName']"}),
'source': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
'target': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocAlias']"})
},
'doc.state': {
'Meta': {'ordering': "['type', 'order']", 'object_name': 'State'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'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': "orm['doc.State']"}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.StateType']"}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'doc.statedocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'StateDocEvent', '_ormbases': ['doc.DocEvent']},
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.State']", 'null': 'True', 'blank': 'True'}),
'state_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.StateType']"})
},
'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'})
},
'doc.telechatdocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'TelechatDocEvent', '_ormbases': ['doc.DocEvent']},
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "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'})
},
'doc.writeupdocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'WriteupDocEvent', '_ormbases': ['doc.DocEvent']},
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
'text': ('django.db.models.fields.TextField', [], {'blank': 'True'})
},
'group.group': {
'Meta': {'object_name': 'Group'},
'acronym': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '40', 'db_index': 'True'}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "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': "orm['doc.Document']"}),
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'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': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']", 'null': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupTypeName']", 'null': 'True'}),
'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'})
},
'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'})
},
'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'})
},
'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'})
},
'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'})
},
'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'})
},
'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'})
},
'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'})
},
'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'})
},
'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'})
},
'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'})
},
'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': "orm['person.Person']", 'null': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
},
'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'}),
'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': "orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'})
}
}
complete_apps = ['doc']

View file

@ -80,6 +80,8 @@ class DocumentInfo(models.Model):
return settings.CHARTER_PATH
elif self.type_id == "conflrev":
return settings.CONFLICT_REVIEW_PATH
elif self.type_id == "statchg":
return settings.STATUS_CHANGE_PATH
else:
raise NotImplemented
@ -120,7 +122,7 @@ class DocumentInfo(models.Model):
if not hasattr(self, "state_cache") or self.state_cache == None:
self.state_cache = {}
for s in self.states.all().select_related():
for s in self.states.all().select_related("type"):
self.state_cache[s.type_id] = s
return self.state_cache.get(state_type, None)
@ -147,8 +149,8 @@ class DocumentInfo(models.Model):
def active_ballot(self):
"""Returns the most recently created ballot if it isn't closed."""
ballot = self.latest_event(BallotDocEvent, type="created_ballot")
if ballot and self.ballot_open(ballot.ballot_type.slug):
ballot = self.latest_event(BallotDocEvent, type__in=("created_ballot", "closed_ballot"))
if ballot and ballot.type == "created_ballot":
return ballot
else:
return None
@ -334,7 +336,7 @@ class Document(DocumentInfo):
if g:
if g.type_id == "area":
return g.acronym
elif g.type_id != "individ":
elif g.type_id != "individ" and g.parent:
return g.parent.acronym
else:
return None
@ -367,7 +369,7 @@ class Document(DocumentInfo):
return self.latest_event(LastCallDocEvent,type="sent_last_call")
def displayname_with_link(self):
return '<a href="%s">%s-%s</a>' % (self.get_absolute_url(), self.name , self.rev)
return mark_safe('<a href="%s">%s-%s</a>' % (self.get_absolute_url(), self.name , self.rev))
def rfc_number(self):
n = self.canonical_name()
@ -596,7 +598,7 @@ EVENT_TYPES = [
class DocEvent(models.Model):
"""An occurrence for a document, used for tracking who, when and what."""
time = models.DateTimeField(default=datetime.datetime.now, help_text="When the event happened")
time = models.DateTimeField(default=datetime.datetime.now, help_text="When the event happened", db_index=True)
type = models.CharField(max_length=50, choices=EVENT_TYPES)
by = models.ForeignKey(Person)
doc = models.ForeignKey('doc.Document')
@ -642,17 +644,15 @@ class BallotDocEvent(DocEvent):
active_ads = list(Person.objects.filter(role__name="ad", role__group__state="active"))
res = {}
if self.doc.latest_event(BallotDocEvent, type="created_ballot") == self:
positions = BallotPositionDocEvent.objects.filter(type="changed_ballot_position",ad__in=active_ads, ballot=self).select_related('ad', 'pos').order_by("-time", "-id")
for pos in positions:
if pos.ad not in res:
res[pos.ad] = pos
for ad in active_ads:
if ad not in res:
res[ad] = None
positions = BallotPositionDocEvent.objects.filter(type="changed_ballot_position",ad__in=active_ads, ballot=self).select_related('ad', 'pos').order_by("-time", "-id")
for pos in positions:
if pos.ad not in res:
res[pos.ad] = pos
for ad in active_ads:
if ad not in res:
res[ad] = None
return res
def all_positions(self):

File diff suppressed because it is too large Load diff

View file

@ -40,31 +40,35 @@ from django.utils.safestring import mark_safe
from ietf.ietfauth.utils import user_is_person, has_role
from ietf.doc.models import BallotDocEvent, BallotPositionDocEvent, IESG_BALLOT_ACTIVE_STATES, IESG_SUBSTATE_TAGS
from ietf.name.models import BallotPositionName
register = template.Library()
def render_ballot_icon(user, doc):
@register.filter
def showballoticon(doc):
if doc.type_id == "draft":
if doc.get_state_slug("draft-iesg") not in IESG_BALLOT_ACTIVE_STATES:
return False
elif doc.type_id == "charter":
if doc.get_state_slug() not in ("intrev", "iesgrev"):
return False
elif doc.type_id == "conflrev":
if doc.get_state_slug() not in ("iesgeval","defer"):
return False
elif doc.type_id == "statchg":
if doc.get_state_slug() not in ("iesgeval","defer"):
return False
return True
def render_ballot_icon(doc, user):
if not doc:
return ""
# FIXME: temporary backwards-compatibility hack
from ietf.doc.models import Document
if not isinstance(doc, Document):
doc = doc._draft
if doc.type_id == "draft":
if doc.get_state_slug("draft-iesg") not in IESG_BALLOT_ACTIVE_STATES:
return ""
elif doc.type_id == "charter":
if doc.get_state_slug() not in ("intrev", "iesgrev"):
return ""
elif doc.type_id == "conflrev":
if doc.get_state_slug() not in ("iesgeval","defer"):
return ""
elif doc.type_id == "statchg":
if doc.get_state_slug() not in ("iesgeval","defer"):
return ""
if not showballoticon(doc):
return ""
ballot = doc.active_ballot()
if not ballot:
@ -119,7 +123,7 @@ class BallotIconNode(template.Node):
self.doc_var = doc_var
def render(self, context):
doc = template.resolve_variable(self.doc_var, context)
return render_ballot_icon(context.get("user"), doc)
return render_ballot_icon(doc, context.get("user"))
def do_ballot_icon(parser, token):
try:
@ -132,29 +136,24 @@ register.tag('ballot_icon', do_ballot_icon)
@register.filter
def my_position(doc, user):
if not has_role(user, "Area Director"):
def ballotposition(doc, user):
if not showballoticon(doc) or not has_role(user, "Area Director"):
return None
# FIXME: temporary backwards-compatibility hack
from ietf.doc.models import Document
if not isinstance(doc, Document):
doc = doc._draft
ballot = doc.active_ballot()
pos = "No Record"
if ballot:
changed_pos = doc.latest_event(BallotPositionDocEvent, type="changed_ballot_position", ad__user=user, ballot=ballot)
if changed_pos:
pos = changed_pos.pos.name;
if not ballot:
return None
changed_pos = doc.latest_event(BallotPositionDocEvent, type="changed_ballot_position", ad__user=user, ballot=ballot)
if changed_pos:
pos = changed_pos.pos
else:
pos = BallotPositionName.objects.get(slug="norecord")
return pos
@register.filter()
def state_age_colored(doc):
# FIXME: temporary backwards-compatibility hack
from ietf.doc.models import Document
if not isinstance(doc, Document):
doc = doc._draft
@register.filter
def state_age_colored(doc):
if doc.type_id == 'draft':
if not doc.get_state_slug() in ["active", "rfc"]:
# Don't show anything for expired/withdrawn/replaced drafts
@ -174,7 +173,6 @@ def state_age_colored(doc):
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 has approved and state has been changed to")|
Q(desc__istartswith="IESG process started in state")
).order_by('-time')[0].time.date()
except IndexError:

View file

@ -9,14 +9,13 @@ from django.template.defaultfilters import linebreaksbr, wordwrap, stringfilter,
from django.template import resolve_variable
from django.utils.safestring import mark_safe, SafeData
from django.utils import simplejson
try:
from email import utils as emailutils
except ImportError:
from email import Utils as emailutils
from django.utils.html import strip_tags
from django.template import RequestContext
from email.utils import parseaddr
import re
import datetime
import types
from django.template import RequestContext
register = template.Library()
@ -73,14 +72,23 @@ def parse_email_list(value):
addrs = re.split(", ?", value)
ret = []
for addr in addrs:
(name, email) = emailutils.parseaddr(addr)
(name, email) = parseaddr(addr)
if not(name):
name = email
ret.append('<a href="mailto:%s">%s</a>' % ( fix_ampersands(email), escape(name) ))
return ", ".join(ret)
return mark_safe(", ".join(ret))
else:
return value
@register.filter
def strip_email(value):
"""Get rid of email part of name/email string like 'Some Name <email@example.com>'."""
if not value:
return ""
if "@" not in value:
return value
return parseaddr(value)[0]
@register.filter(name='fix_angle_quotes')
def fix_angle_quotes(value):
if "<" in value:
@ -92,7 +100,7 @@ def fix_angle_quotes(value):
@register.filter(name='make_one_per_line')
def make_one_per_line(value):
"""
Turn a comma-separated list into a carraige-return-seperated list.
Turn a comma-separated list into a carriage-return-seperated list.
>>> make_one_per_line("a, b, c")
'a\\nb\\nc'
@ -276,6 +284,10 @@ def truncate_ellipsis(text, arg):
else:
return escape(text)
@register.filter
def split(text, splitter=None):
return text.split(splitter)
@register.filter(name="wrap_long_lines")
def wrap_long_lines(text):
"""Wraps long lines without loosing the formatting and indentation
@ -405,25 +417,13 @@ def expires_soon(x,request):
days = 14
return x > -days
@register.filter(name='equal')
def equal(x, y):
return str(x)==str(y)
@register.filter(name='startswith')
def startswith(x, y):
return unicode(x).startswith(y)
# based on http://www.djangosnippets.org/snippets/847/ by 'whiteinge'
@register.filter
def in_group(user, groups):
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
return has_role(user, groups.replace("Area_Director", "Area Director"))
return user and user.is_authenticated() and bool(user.groups.filter(name__in=groups.split(',')).values('name'))
@register.filter
def has_role(user, role_names):
from ietf.ietfauth.decorators import has_role
from ietf.ietfauth.utils import has_role
if not user:
return False
return has_role(user, role_names.split(','))
@ -475,6 +475,18 @@ def state(doc, slug):
slug = "%s-stream-%s" % (doc.type_id, doc.stream_id)
return doc.get_state(slug)
@register.filter
def statehelp(state):
"Output help icon with tooltip for state."
from django.core.urlresolvers import reverse as urlreverse
tooltip = escape(strip_tags(state.desc))
url = urlreverse("state_help", kwargs=dict(type=state.type_id)) + "#" + state.slug
return mark_safe('<a class="state-help-icon" href="%s" title="%s">?</a>' % (url, tooltip))
@register.filter
def sectionlevel(section_number):
return section_number.count(".") + 1
def _test():
import doctest
doctest.testmod()
@ -483,13 +495,13 @@ if __name__ == "__main__":
_test()
@register.filter
def plural(text, list, arg=u's'):
def plural(text, seq, arg=u's'):
"Similar to pluralize, but looks at the text, too"
from django.template.defaultfilters import pluralize
if text.endswith('s'):
return text
else:
return text + pluralize(len(list), arg)
return text + pluralize(len(seq), arg)
@register.filter
def ics_esc(text):

View file

@ -0,0 +1,32 @@
from django import template
from django.conf import settings
from django.core.urlresolvers import reverse as urlreverse
from django.contrib.auth.models import AnonymousUser
from ietf.ietfauth.utils import has_role
from ietf.group.models import Group
from ietf.name.models import StreamName
register = template.Library()
@register.inclusion_tag('base/streams_menu.html', takes_context=True)
def streams_menu(context):
editable_streams = []
user = context["request"].user if "request" in context else AnonymousUser()
if user.is_authenticated():
streams = StreamName.objects.exclude(slug="legacy")
if has_role(user, "Secretariat"):
editable_streams.extend(streams)
else:
acronyms = Group.objects.filter(acronym__in=(s.slug for s in streams),
role__name="chair",
role__person__user=user).distinct().values_list("acronym", flat=True)
for s in streams:
if s.slug in acronyms:
editable_streams.append(s)
return { 'editable_streams': editable_streams }

View file

@ -61,7 +61,7 @@ class WgMenuNode(template.Node):
areas = [a for a in areas if a.active_groups]
res = loader.render_to_string('base_wgmenu.html', {'areas':areas})
res = loader.render_to_string('base/wg_menu.html', {'areas':areas})
cache.set('base_left_wgmenu', x, 30*60)
return res

View file

@ -24,9 +24,6 @@ from ietf.doc.tests_status_change import *
class SearchTestCase(TestCase):
# See ietf.utils.test_utils.TestCase for the use of perma_fixtures vs. fixtures
perma_fixtures = ['names']
def test_search(self):
draft = make_test_data()
@ -127,9 +124,6 @@ class SearchTestCase(TestCase):
class DocTestCase(TestCase):
# See ietf.utils.test_utils.TestCase for the use of perma_fixtures vs. fixtures
perma_fixtures = ['names']
def test_document_draft(self):
draft = make_test_data()
@ -251,9 +245,6 @@ class DocTestCase(TestCase):
class AddCommentTestCase(TestCase):
# See ietf.utils.test_utils.TestCase for the use of perma_fixtures vs. fixtures
perma_fixtures = ['names']
def test_add_comment(self):
draft = make_test_data()
url = urlreverse('doc_add_comment', kwargs=dict(name=draft.name))

View file

@ -20,10 +20,7 @@ from ietf.utils.test_data import make_test_data
from ietf.utils.mail import outbox
from ietf.utils import TestCase
class EditPositionTestCase(TestCase):
# See ietf.utils.test_utils.TestCase for the use of perma_fixtures vs. fixtures
perma_fixtures = ['names']
class EditPositionTests(TestCase):
def test_edit_position(self):
draft = make_test_data()
url = urlreverse('ietf.doc.views_ballot.edit_position', kwargs=dict(name=draft.name,
@ -170,10 +167,7 @@ class EditPositionTestCase(TestCase):
self.assertTrue("Test!" in str(m))
class DeferBallotTestCase(TestCase):
# See ietf.utils.test_utils.TestCase for the use of perma_fixtures vs. fixtures
perma_fixtures = ['names']
class DeferBallotTests(TestCase):
def test_defer_ballot(self):
draft = make_test_data()
draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="iesg-eva"))
@ -217,10 +211,8 @@ class DeferBallotTestCase(TestCase):
draft = Document.objects.get(name=draft.name)
self.assertEquals(draft.get_state_slug("draft-iesg"), "iesg-eva")
class BallotWriteupsTestCase(TestCase):
# See ietf.utils.test_utils.TestCase for the use of perma_fixtures vs. fixtures
perma_fixtures = ['names']
class BallotWriteupsTests(TestCase):
def test_edit_last_call_text(self):
draft = make_test_data()
url = urlreverse('doc_ballot_lastcall', kwargs=dict(name=draft.name))
@ -409,10 +401,8 @@ class BallotWriteupsTestCase(TestCase):
draft = Document.objects.get(name=draft.name)
self.assertTrue("Subject: Results of IETF-conflict review" in draft.latest_event(WriteupDocEvent, type="changed_ballot_approval_text").text)
class ApproveBallotTestCase(TestCase):
# See ietf.utils.test_utils.TestCase for the use of perma_fixtures vs. fixtures
perma_fixtures = ['names']
class ApproveBallotTests(TestCase):
def test_approve_ballot(self):
draft = make_test_data()
draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="iesg-eva")) # make sure it's approvable
@ -460,10 +450,8 @@ class ApproveBallotTestCase(TestCase):
self.assertEquals(len(outbox), mailbox_before + 3)
self.assertTrue("NOT be published" in str(outbox[-1]))
class MakeLastCallTestCase(TestCase):
# See ietf.utils.test_utils.TestCase for the use of perma_fixtures vs. fixtures
perma_fixtures = ['names']
class MakeLastCallTests(TestCase):
def test_make_last_call(self):
draft = make_test_data()
draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="lc-req"))

View file

@ -22,10 +22,7 @@ from ietf.group.models import Person
from ietf.iesg.models import TelechatDate
class ConflictReviewTestCase(TestCase):
# See ietf.utils.test_utils.TestCase for the use of perma_fixtures vs. fixtures
perma_fixtures = ['names']
class ConflictReviewTests(TestCase):
def test_start_review(self):
doc = Document.objects.get(name='draft-imaginary-independent-submission')
@ -254,10 +251,7 @@ class ConflictReviewTestCase(TestCase):
make_test_data()
class ConflictReviewSubmitTestCase(TestCase):
# See ietf.utils.test_utils.TestCase for the use of perma_fixtures vs. fixtures
perma_fixtures = ['names',]
class ConflictReviewSubmitTests(TestCase):
def test_initial_submission(self):
doc = Document.objects.get(name='conflict-review-imaginary-irtf-submission')
url = urlreverse('conflict_review_submit',kwargs=dict(name=doc.name))

View file

@ -1,7 +1,5 @@
import unittest
import StringIO
import os, shutil
from datetime import date, timedelta, time
import os, shutil, datetime
from django.core.urlresolvers import reverse as urlreverse
from django.conf import settings
@ -10,6 +8,7 @@ from pyquery import PyQuery
import debug
from ietf.doc.models import *
from ietf.doc.utils import *
from ietf.name.models import *
from ietf.group.models import *
from ietf.person.models import *
@ -21,10 +20,7 @@ from ietf.utils.mail import outbox
from ietf.utils import TestCase
class ChangeStateTestCase(TestCase):
# See ietf.utils.test_utils.TestCase for the use of perma_fixtures vs. fixtures
perma_fixtures = ['names']
class ChangeStateTests(TestCase):
def test_change_state(self):
draft = make_test_data()
draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="ad-eval"))
@ -178,10 +174,7 @@ class ChangeStateTestCase(TestCase):
self.assertTrue("Last call was requested" in draft.latest_event().desc)
class EditInfoTestCase(TestCase):
# See ietf.utils.test_utils.TestCase for the use of perma_fixtures vs. fixtures
perma_fixtures = ['names']
class EditInfoTests(TestCase):
def test_edit_info(self):
draft = make_test_data()
url = urlreverse('doc_edit_info', kwargs=dict(name=draft.name))
@ -361,10 +354,7 @@ class EditInfoTestCase(TestCase):
self.assertEqual(draft.latest_event(ConsensusDocEvent, type="changed_consensus").consensus, True)
class ResurrectTestCase(TestCase):
# See ietf.utils.test_utils.TestCase for the use of perma_fixtures vs. fixtures
perma_fixtures = ['names']
class ResurrectTests(TestCase):
def test_request_resurrect(self):
draft = make_test_data()
draft.set_state(State.objects.get(used=True, type="draft", slug="expired"))
@ -429,10 +419,7 @@ class ResurrectTestCase(TestCase):
self.assertEquals(len(outbox), mailbox_before + 1)
class ExpireIDsTestCase(TestCase):
# See ietf.utils.test_utils.TestCase for the use of perma_fixtures vs. fixtures
perma_fixtures = ['names']
class ExpireIDsTests(TestCase):
def setUp(self):
self.id_dir = os.path.abspath("tmp-id-dir")
self.archive_dir = os.path.abspath("tmp-id-archive")
@ -459,15 +446,15 @@ class ExpireIDsTestCase(TestCase):
Meeting.objects.create(number="123",
type=MeetingTypeName.objects.get(slug="ietf"),
date=date.today())
date=datetime.date.today())
second_cut_off = Meeting.get_second_cut_off()
ietf_monday = Meeting.get_ietf_monday()
self.assertTrue(not in_draft_expire_freeze(datetime.datetime.combine(second_cut_off - datetime.timedelta(days=7), time(0, 0, 0))))
self.assertTrue(not in_draft_expire_freeze(datetime.datetime.combine(second_cut_off, time(0, 0, 0))))
self.assertTrue(in_draft_expire_freeze(datetime.datetime.combine(second_cut_off + datetime.timedelta(days=7), time(0, 0, 0))))
self.assertTrue(in_draft_expire_freeze(datetime.datetime.combine(ietf_monday - datetime.timedelta(days=1), time(0, 0, 0))))
self.assertTrue(not in_draft_expire_freeze(datetime.datetime.combine(ietf_monday, time(0, 0, 0))))
self.assertTrue(not in_draft_expire_freeze(datetime.datetime.combine(second_cut_off - datetime.timedelta(days=7), datetime.time(0, 0, 0))))
self.assertTrue(not in_draft_expire_freeze(datetime.datetime.combine(second_cut_off, datetime.time(0, 0, 0))))
self.assertTrue(in_draft_expire_freeze(datetime.datetime.combine(second_cut_off + datetime.timedelta(days=7), datetime.time(0, 0, 0))))
self.assertTrue(in_draft_expire_freeze(datetime.datetime.combine(ietf_monday - datetime.timedelta(days=1), datetime.time(0, 0, 0))))
self.assertTrue(not in_draft_expire_freeze(datetime.datetime.combine(ietf_monday, datetime.time(0, 0, 0))))
def test_warn_expirable_drafts(self):
from ietf.doc.expire import get_soon_to_expire_drafts, send_expire_warning_for_draft
@ -612,10 +599,8 @@ class ExpireIDsTestCase(TestCase):
self.assertTrue(not os.path.exists(os.path.join(self.id_dir, txt)))
self.assertTrue(os.path.exists(os.path.join(self.archive_dir, "deleted_tombstones", txt)))
class ExpireLastCallTestCase(TestCase):
# See ietf.utils.test_utils.TestCase for the use of perma_fixtures vs. fixtures
perma_fixtures = ['names']
class ExpireLastCallTests(TestCase):
def test_expire_last_call(self):
from ietf.doc.lastcall import get_expired_last_calls, expire_last_call
@ -662,10 +647,8 @@ class ExpireLastCallTestCase(TestCase):
self.assertEquals(len(outbox), mailbox_before + 1)
self.assertTrue("Last Call Expired" in outbox[-1]["Subject"])
class IndividualInfoFormsTestCase(TestCase):
# See ietf.utils.test_utils.TestCase for the use of perma_fixtures vs. fixtures
perma_fixtures = ['names']
class IndividualInfoFormsTests(TestCase):
def test_doc_change_stream(self):
url = urlreverse('doc_change_stream', kwargs=dict(name=self.docname))
login_testing_unauthorized(self, "secretary", url)
@ -890,10 +873,8 @@ class IndividualInfoFormsTestCase(TestCase):
self.docname='draft-ietf-mars-test'
self.doc = Document.objects.get(name=self.docname)
class SubmitToIesgTestCase(TestCase):
# See ietf.utils.test_utils.TestCase for the use of perma_fixtures vs. fixtures
perma_fixtures = ['names']
class SubmitToIesgTests(TestCase):
def verify_permissions(self):
def verify_fail(remote_user):
@ -951,10 +932,8 @@ class SubmitToIesgTestCase(TestCase):
self.doc = Document.objects.get(name=self.docname)
self.doc.unset_state('draft-iesg')
class RequestPublicationTestCase(TestCase):
# See ietf.utils.test_utils.TestCase for the use of perma_fixtures vs. fixtures
perma_fixtures = ['names']
class RequestPublicationTests(TestCase):
def test_request_publication(self):
draft = make_test_data()
draft.stream = StreamName.objects.get(slug="iab")
@ -990,3 +969,123 @@ class RequestPublicationTestCase(TestCase):
# the IANA copy
self.assertTrue("Document Action" in outbox[-1]['Subject'])
self.assertTrue(not outbox[-1]['CC'])
class AdoptDraftTests(TestCase):
def test_adopt_document(self):
draft = make_test_data()
draft.stream = None
draft.group = Group.objects.get(type="individ")
draft.save()
draft.unset_state("draft-stream-ietf")
url = urlreverse('doc_adopt_draft', kwargs=dict(name=draft.name))
login_testing_unauthorized(self, "marschairman", url)
# get
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
self.assertEqual(len(q('form select[name="group"] option')), 1) # we can only select "mars"
# adopt in mars WG
mailbox_before = len(outbox)
events_before = draft.docevent_set.count()
r = self.client.post(url,
dict(comment="some comment",
group=Group.objects.get(acronym="mars").pk,
weeks="10"))
self.assertEqual(r.status_code, 302)
draft = Document.objects.get(pk=draft.pk)
self.assertEqual(draft.group.acronym, "mars")
self.assertEqual(draft.stream_id, "ietf")
self.assertEqual(draft.docevent_set.count() - events_before, 4)
self.assertEqual(len(outbox), mailbox_before + 1)
self.assertTrue("adopted" in outbox[-1]["Subject"].lower())
self.assertTrue("wgchairman@ietf.org" in unicode(outbox[-1]))
self.assertTrue("wgdelegate@ietf.org" in unicode(outbox[-1]))
class ChangeStreamStateTests(TestCase):
def test_set_tags(self):
draft = make_test_data()
draft.tags = DocTagName.objects.filter(slug="w-expert")
draft.group.unused_tags.add("w-refdoc")
url = urlreverse('doc_change_stream_state', kwargs=dict(name=draft.name, state_type="draft-stream-ietf"))
login_testing_unauthorized(self, "marschairman", url)
# get
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
# make sure the unused tags are hidden
unused = draft.group.unused_tags.values_list("slug", flat=True)
for t in q("input[name=tags]"):
self.assertTrue(t.attrib["value"] not in unused)
# set tags
mailbox_before = len(outbox)
events_before = draft.docevent_set.count()
r = self.client.post(url,
dict(new_state=draft.get_state("draft-stream-%s" % draft.stream_id).pk,
comment="some comment",
weeks="10",
tags=["need-aut", "sheph-u"],
))
self.assertEqual(r.status_code, 302)
draft = Document.objects.get(pk=draft.pk)
self.assertEqual(draft.tags.count(), 2)
self.assertEqual(draft.tags.filter(slug="w-expert").count(), 0)
self.assertEqual(draft.tags.filter(slug="need-aut").count(), 1)
self.assertEqual(draft.tags.filter(slug="sheph-u").count(), 1)
self.assertEqual(draft.docevent_set.count() - events_before, 2)
self.assertEqual(len(outbox), mailbox_before + 1)
self.assertTrue("tags changed" in outbox[-1]["Subject"].lower())
self.assertTrue("wgchairman@ietf.org" in unicode(outbox[-1]))
self.assertTrue("wgdelegate@ietf.org" in unicode(outbox[-1]))
self.assertTrue("plain@example.com" in unicode(outbox[-1]))
def test_set_state(self):
draft = make_test_data()
url = urlreverse('doc_change_stream_state', kwargs=dict(name=draft.name, state_type="draft-stream-ietf"))
login_testing_unauthorized(self, "marschairman", url)
# get
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
# make sure the unused states are hidden
unused = draft.group.unused_states.values_list("pk", flat=True)
for t in q("select[name=new_state]").find("option[name=tags]"):
self.assertTrue(t.attrib["value"] not in unused)
self.assertEqual(len(q('select[name=new_state]')), 1)
# set new state
old_state = draft.get_state("draft-stream-%s" % draft.stream_id )
new_state = State.objects.get(used=True, type="draft-stream-%s" % draft.stream_id, slug="parked")
self.assertNotEqual(old_state, new_state)
mailbox_before = len(outbox)
events_before = draft.docevent_set.count()
r = self.client.post(url,
dict(new_state=new_state.pk,
comment="some comment",
weeks="10",
tags=[t.pk for t in draft.tags.filter(slug__in=get_tags_for_stream_id(draft.stream_id))],
))
self.assertEqual(r.status_code, 302)
draft = Document.objects.get(pk=draft.pk)
self.assertEqual(draft.get_state("draft-stream-%s" % draft.stream_id), new_state)
self.assertEqual(draft.docevent_set.count() - events_before, 2)
reminder = DocReminder.objects.filter(event__doc=draft, type="stream-s")
self.assertEqual(len(reminder), 1)
due = datetime.datetime.now() + datetime.timedelta(weeks=10)
self.assertTrue(due - datetime.timedelta(days=1) <= reminder[0].due <= due + datetime.timedelta(days=1))
self.assertEqual(len(outbox), mailbox_before + 1)
self.assertTrue("state changed" in outbox[-1]["Subject"].lower())
self.assertTrue("wgchairman@ietf.org" in unicode(outbox[-1]))
self.assertTrue("wgdelegate@ietf.org" in unicode(outbox[-1]))

View file

@ -22,10 +22,7 @@ from ietf.group.models import Person
from ietf.iesg.models import TelechatDate
class StatusChangeTestCase(TestCase):
# See ietf.utils.test_utils.TestCase for the use of perma_fixtures vs. fixtures
perma_fixtures = ['names']
class StatusChangeTests(TestCase):
def test_start_review(self):
url = urlreverse('start_rfc_status_change',kwargs=dict(name=""))
@ -353,10 +350,7 @@ class StatusChangeTestCase(TestCase):
make_test_data()
class StatusChangeSubmitTestCase(TestCase):
# See ietf.utils.test_utils.TestCase for the use of perma_fixtures vs. fixtures
perma_fixtures = ['names']
class StatusChangeSubmitTests(TestCase):
def test_initial_submission(self):
doc = Document.objects.get(name='status-change-imaginary-mid-review')
url = urlreverse('status_change_submit',kwargs=dict(name=doc.name))

View file

@ -68,7 +68,6 @@ urlpatterns += patterns('',
url(r'^(?P<name>[A-Za-z0-9._+-]+)/ballot/$', views_doc.document_ballot, name="doc_ballot"),
(r'^(?P<name>[A-Za-z0-9._+-]+)/doc.json$', views_doc.document_json),
(r'^(?P<name>[A-Za-z0-9._+-]+)/ballotpopup/(?P<ballot_id>[0-9]+)/$', views_doc.ballot_popup),
#(r'^(?P<name>[A-Za-z0-9._+-]+)/ballot.json$', views_doc.ballot_json), # legacy view
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/state/$', views_draft.change_state, name='doc_change_state'), # IESG state
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/state/(?P<state_type>iana-action|iana-review)/$', views_draft.change_iana_state, name='doc_change_iana_state'),
@ -90,6 +89,8 @@ urlpatterns += patterns('',
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/shepherd/$', views_draft.edit_shepherd, name='doc_edit_shepherd'),
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/shepherdwriteup/$', views_draft.edit_shepherd_writeup, name='doc_edit_shepherd_writeup'),
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/requestpublication/$', views_draft.request_publication, name='doc_request_publication'),
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/adopt/$', views_draft.adopt_draft, name='doc_adopt_draft'),
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/state/(?P<state_type>draft-stream-[a-z]+)/$', views_draft.change_stream_state, name='doc_change_stream_state'),
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/clearballot/$', views_ballot.clear_ballot, name='doc_clear_ballot'),
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/deferballot/$', views_ballot.defer_ballot, name='doc_defer_ballot'),

View file

@ -5,6 +5,8 @@ from django.conf import settings
from ietf.utils import markup_txt
from ietf.doc.models import *
from ietf.group.models import Role
from ietf.ietfauth.utils import has_role
from ietf.utils import draft
@ -39,6 +41,20 @@ def get_tags_for_stream_id(stream_id):
else:
return []
def can_adopt_draft(user, doc):
if not user.is_authenticated():
return False
if has_role(user, "Secretariat"):
return True
return (doc.stream_id in (None, "ietf", "irtf")
and doc.group.type_id == "individ"
and Role.objects.filter(name__in=("chair", "delegate", "secr"),
group__type__in=("wg", "rg"),
group__state="active",
person__user=user).exists())
def needed_ballot_positions(doc, active_positions):
'''Returns text answering the question "what does this document
need to pass?". The return value is only useful if the document
@ -227,7 +243,30 @@ def add_state_change_event(doc, by, prev_state, new_state, timestamp=None):
e.time = timestamp
e.save()
return e
def update_reminder(doc, reminder_type_slug, event, due_date):
reminder_type = DocReminderTypeName.objects.get(slug=reminder_type_slug)
try:
reminder = DocReminder.objects.get(event__doc=doc, type=reminder_type, active=True)
except DocReminder.DoesNotExist:
reminder = None
if due_date:
# activate/update reminder
if not reminder:
reminder = DocReminder(type=reminder_type)
reminder.event = event
reminder.due = due_date
reminder.active = True
reminder.save()
else:
# deactivate reminder
if reminder:
reminder.active = False
reminder.save()
def prettify_std_name(n):
if re.match(r"(rfc|bcp|fyi|std)[0-9]+", n):
return n[:3].upper() + " " + n[3:]

View file

@ -16,7 +16,7 @@ from django.conf import settings
import debug
from ietf.utils.mail import send_mail_text, send_mail_preformatted
from ietf.ietfauth.decorators import has_role, role_required
from ietf.ietfauth.utils import has_role, role_required
from ietf.iesg.models import TelechatDate
from ietf.ipr.models import IprDetail
from ietf.ipr.search import iprs_from_docs
@ -693,7 +693,7 @@ def approve_ballot(request, name):
e = DocEvent(doc=doc, by=login)
if action == "do_not_publish":
e.type = "iesg_disapproved"
e.desc = "Do Not Publish note has been sent to RFC Editor"
e.desc = "Do Not Publish note has been sent to the RFC Editor"
else:
e.type = "iesg_approved"
e.desc = "IESG has approved the document"

View file

@ -12,7 +12,7 @@ from ietf.doc.utils import log_state_changed, 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.decorators import has_role, role_required
from ietf.ietfauth.utils import has_role, role_required
from ietf.utils.textupload import get_cleaned_text_file_content
from ietf.utils.mail import send_mail_preformatted
from ietf.doc.mails import email_iana

View file

@ -61,12 +61,10 @@ def render_document_top(request, doc, tab, name):
ballot = doc.latest_event(BallotDocEvent, type="created_ballot")
if doc.type_id in ("draft","conflrev", "statchg"):
# if doc.in_ietf_process and doc.ietf_process.has_iesg_ballot:
tabs.append(("IESG Evaluation Record", "ballot", urlreverse("doc_ballot", kwargs=dict(name=name)), ballot, None if ballot else "IESG Evaluation Ballot has not been created yet"))
elif doc.type_id == "charter":
tabs.append(("IESG Review", "ballot", urlreverse("doc_ballot", kwargs=dict(name=name)), ballot, None if ballot else "IEST Review Ballot has not been created yet"))
# FIXME: if doc.in_ietf_process and doc.ietf_process.has_iesg_ballot:
if doc.type_id not in ["conflrev", "statchg"]:
tabs.append(("IESG Writeups", "writeup", urlreverse("doc_writeup", kwargs=dict(name=name)), True))
@ -254,9 +252,11 @@ def document_main(request, name, rev=None):
resurrected_by = e.by
# stream info
stream_state_type_slug = None
stream_state = None
if doc.stream:
stream_state = doc.get_state("draft-stream-%s" % doc.stream_id)
stream_state_type_slug = "draft-stream-%s" % doc.stream_id
stream_state = doc.get_state(stream_state_type_slug)
stream_tags = doc.tags.filter(slug__in=get_tags_for_stream_id(doc.stream_id))
shepherd_writeup = doc.latest_event(WriteupDocEvent, type="changed_protocol_writeup")
@ -286,13 +286,8 @@ def document_main(request, name, rev=None):
# remaining actions
actions = []
if ((not doc.stream_id or doc.stream_id in ("ietf", "irtf")) and group.type_id == "individ" and
(request.user.is_authenticated() and
Role.objects.filter(person__user=request.user, name__in=("chair", "secr", "delegate"),
group__type__in=("wg","rg"),
group__state="active")
or has_role(request.user, "Secretariat"))):
actions.append(("Adopt in Group", urlreverse('edit_adopt', kwargs=dict(name=doc.name))))
if can_adopt_draft(request.user, doc):
actions.append(("Adopt in Group", urlreverse('doc_adopt_draft', kwargs=dict(name=doc.name))))
if doc.get_state_slug() == "expired" and not resurrected_by and can_edit:
actions.append(("Request Resurrect", urlreverse('doc_request_resurrect', kwargs=dict(name=doc.name))))
@ -366,6 +361,7 @@ def document_main(request, name, rev=None):
has_errata=doc.tags.filter(slug="errata"),
published=doc.latest_event(type="published_rfc"),
file_urls=file_urls,
stream_state_type_slug=stream_state_type_slug,
stream_state=stream_state,
stream_tags=stream_tags,
milestones=doc.groupmilestone_set.filter(state="active"),
@ -765,48 +761,6 @@ def document_json(request, name):
return HttpResponse(json.dumps(data, indent=2), mimetype='text/plain')
def ballot_json(request, name):
# REDESIGN: this view needs to be deleted or updated
def get_ballot(name):
from ietf.doc.models import DocAlias
alias = get_object_or_404(DocAlias, name=name)
d = alias.document
from ietf.idtracker.models import InternetDraft, BallotInfo
from ietf.idrfc.idrfc_wrapper import BallotWrapper, IdWrapper, RfcWrapper
id = None
bw = None
dw = None
if (d.type_id=='draft'):
id = get_object_or_404(InternetDraft, name=d.name)
try:
if not id.ballot.ballot_issued:
raise Http404
except BallotInfo.DoesNotExist:
raise Http404
bw = BallotWrapper(id) # XXX Fixme: Eliminate this as we go forward
# Python caches ~100 regex'es -- explicitly compiling it inside a method
# (where you then throw away the compiled version!) doesn't make sense at
# all.
if re.search("^rfc([1-9][0-9]*)$", name):
id.viewing_as_rfc = True
dw = RfcWrapper(id)
else:
dw = IdWrapper(id)
# XXX Fixme: Eliminate 'dw' as we go forward
try:
b = d.latest_event(BallotDocEvent, type="created_ballot")
except BallotDocEvent.DoesNotExist:
raise Http404
return (bw, dw, b, d)
ballot, doc, b, d = get_ballot(name)
response = HttpResponse(mimetype='text/plain')
response.write(json.dumps(ballot.dict(), indent=2))
return response
class AddCommentForm(forms.Form):
comment = forms.CharField(required=True, widget=forms.Textarea)

View file

@ -15,9 +15,10 @@ from django.db.models import Max
from django.conf import settings
from django.forms.util import ErrorList
from django.contrib.auth.decorators import login_required
from django.template.defaultfilters import pluralize
from ietf.utils.mail import send_mail_text, send_mail_message
from ietf.ietfauth.decorators import role_required
from ietf.ietfauth.utils import role_required
from ietf.ietfauth.utils import has_role, is_authorized_in_doc_stream, user_is_person
from ietf.iesg.models import TelechatDate
from ietf.doc.mails import *
@ -27,11 +28,6 @@ from ietf.person.forms import EmailsField
from ietf.group.models import Group
from ietf.secr.lib import jsonapi
from ietf.ietfworkflows.models import Stream
from ietf.ietfworkflows.utils import update_stream
from ietf.ietfworkflows.streams import get_stream_from_draft
from ietf.ietfworkflows.accounts import can_edit_state
from ietf.doc.models import *
from ietf.doc.utils import *
from ietf.name.models import IntendedStdLevelName, DocTagName, StreamName
@ -402,7 +398,7 @@ def replaces(request, name):
return HttpResponseRedirect(doc.get_absolute_url())
else:
form = ReplacesForm(doc=doc)
return render_to_response('idrfc/change_replaces.html',
return render_to_response('doc/draft/change_replaces.html',
dict(form=form,
doc=doc,
),
@ -1180,7 +1176,7 @@ def request_publication(request, name):
doc = get_object_or_404(Document, type="draft", name=name, stream__in=("iab", "ise", "irtf"))
if not can_edit_state(request.user, doc):
if not is_authorized_in_doc_stream(request.user, doc):
return HttpResponseForbidden("You do not have the necessary permissions to view this page")
m = Message()
@ -1255,3 +1251,225 @@ def request_publication(request, name):
),
context_instance = RequestContext(request))
class AdoptDraftForm(forms.Form):
group = forms.ModelChoiceField(queryset=Group.objects.filter(type__in=["wg", "rg"], state="active").order_by("-type", "acronym"), required=True, empty_label=None)
comment = forms.CharField(widget=forms.Textarea, required=False, label="Comment", help_text="Optional comment explaining the reasons for the adoption")
weeks = forms.IntegerField(required=False, label="Expected weeks in adoption state")
def __init__(self, *args, **kwargs):
user = kwargs.pop("user")
super(AdoptDraftForm, self).__init__(*args, **kwargs)
if has_role(user, "Secretariat"):
pass # all groups
else:
self.fields["group"].queryset = self.fields["group"].queryset.filter(role__person__user=user, role__name__in=("chair", "delegate", "secr")).distinct()
self.fields['group'].choices = [(g.pk, '%s - %s' % (g.acronym, g.name)) for g in self.fields["group"].queryset]
@login_required
def adopt_draft(request, name):
doc = get_object_or_404(Document, type="draft", name=name)
if not can_adopt_draft(request.user, doc):
return HttpResponseForbidden("You don't have permission to access this page")
if request.method == 'POST':
form = AdoptDraftForm(request.POST, user=request.user)
if form.is_valid():
# adopt
by = request.user.get_profile()
save_document_in_history(doc)
doc.time = datetime.datetime.now()
group = form.cleaned_data["group"]
if group.type.slug == "rg":
new_stream = StreamName.objects.get(slug="irtf")
adopt_state_slug = "active"
else:
new_stream = StreamName.objects.get(slug="ietf")
adopt_state_slug = "c-adopt"
# stream
if doc.stream != new_stream:
e = DocEvent(type="changed_stream", time=doc.time, by=by, doc=doc)
e.desc = u"Changed stream to <b>%s</b>" % new_stream.name
if doc.stream:
e.desc += u" from %s" % doc.stream.name
e.save()
doc.stream = new_stream
# group
if group != doc.group:
e = DocEvent(type="changed_group", time=doc.time, by=by, doc=doc)
e.desc = u"Changed group to <b>%s (%s)</b>" % (group.name, group.acronym.upper())
if doc.group.type_id != "individ":
e.desc += " from %s (%s)" % (doc.group.name, doc.group.acronym.upper())
e.save()
doc.group = group
doc.save()
# state
prev_state = doc.get_state("draft-stream-%s" % doc.stream_id)
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)
due_date = None
if form.cleaned_data["weeks"] != None:
due_date = datetime.date.today() + datetime.timedelta(weeks=form.cleaned_data["weeks"])
update_reminder(doc, "stream-s", e, due_date)
# comment
comment = form.cleaned_data["comment"].strip()
if comment:
e = DocEvent(type="added_comment", time=doc.time, by=by, doc=doc)
e.desc = comment
e.save()
email_draft_adopted(request, doc, by, comment)
return HttpResponseRedirect(doc.get_absolute_url())
else:
form = AdoptDraftForm(user=request.user)
return render_to_response('doc/draft/adopt_draft.html',
{'doc': doc,
'form': form,
},
context_instance=RequestContext(request))
class ChangeStreamStateForm(forms.Form):
new_state = forms.ModelChoiceField(queryset=State.objects.filter(used=True), label='State', help_text=u"Only select 'Submitted to IESG for Publication' to correct errors. Use the document's main page to request publication.")
weeks = forms.IntegerField(label='Expected weeks in state',required=False)
comment = forms.CharField(widget=forms.Textarea, required=False, help_text="Optional comment for the document history")
tags = forms.ModelMultipleChoiceField(queryset=DocTagName.objects.filter(used=True), widget=forms.CheckboxSelectMultiple, required=False)
def __init__(self, *args, **kwargs):
doc = kwargs.pop("doc")
state_type = kwargs.pop("state_type")
super(ChangeStreamStateForm, self).__init__(*args, **kwargs)
f = self.fields["new_state"]
f.queryset = f.queryset.filter(type=state_type)
if doc.group:
unused_states = doc.group.unused_states.values_list("pk", flat=True)
f.queryset = f.queryset.exclude(pk__in=unused_states)
f.label = state_type.label
f = self.fields['tags']
f.queryset = f.queryset.filter(slug__in=get_tags_for_stream_id(doc.stream_id))
if doc.group:
unused_tags = doc.group.unused_tags.values_list("pk", flat=True)
f.queryset = f.queryset.exclude(pk__in=unused_tags)
def next_states_for_stream_state(doc, state_type, current_state):
# find next states
next_states = []
if current_state:
next_states = current_state.next_states.all()
if doc.stream_id == "ietf" and doc.group:
transitions = doc.group.groupstatetransitions_set.filter(state=current_state)
if transitions:
next_states = transitions[0].next_states.all()
else:
# return the initial state
states = State.objects.filter(used=True, type=state_type).order_by('order')
if states:
next_states = states[:1]
if doc.group:
unused_states = doc.group.unused_states.values_list("pk", flat=True)
next_states = [n for n in next_states if n.pk not in unused_states]
return next_states
@login_required
def change_stream_state(request, name, state_type):
doc = get_object_or_404(Document, type="draft", name=name)
if not doc.stream:
raise Http404
state_type = get_object_or_404(StateType, slug=state_type)
if not is_authorized_in_doc_stream(request.user, doc):
return HttpResponseForbidden("You don't have permission to access this page")
prev_state = doc.get_state(state_type.slug)
next_states = next_states_for_stream_state(doc, state_type, prev_state)
if request.method == 'POST':
form = ChangeStreamStateForm(request.POST, doc=doc, state_type=state_type)
if form.is_valid():
by = request.user.get_profile()
save_document_in_history(doc)
doc.time = datetime.datetime.now()
comment = form.cleaned_data["comment"].strip()
# state
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)
due_date = None
if form.cleaned_data["weeks"] != None:
due_date = datetime.date.today() + datetime.timedelta(weeks=form.cleaned_data["weeks"])
update_reminder(doc, "stream-s", e, due_date)
email_stream_state_changed(request, doc, prev_state, new_state, by, comment)
# tags
existing_tags = set(doc.tags.all())
new_tags = set(form.cleaned_data["tags"])
if existing_tags != new_tags:
doc.tags = new_tags
e = DocEvent(type="changed_document", time=doc.time, by=by, doc=doc)
added_tags = new_tags - existing_tags
removed_tags = existing_tags - new_tags
l = []
if added_tags:
l.append(u"Tag%s %s set." % (pluralize(added_tags), ", ".join(t.name for t in added_tags)))
if removed_tags:
l.append(u"Tag%s %s cleared." % (pluralize(removed_tags), ", ".join(t.name for t in removed_tags)))
e.desc = " ".join(l)
e.save()
email_stream_tags_changed(request, doc, added_tags, removed_tags, by, comment)
# comment
if comment:
e = DocEvent(type="added_comment", time=doc.time, by=by, doc=doc)
e.desc = comment
e.save()
return HttpResponseRedirect(doc.get_absolute_url())
else:
form = ChangeStreamStateForm(initial=dict(new_state=prev_state.pk if prev_state else None),
doc=doc, state_type=state_type)
milestones = doc.groupmilestone_set.all()
return render_to_response("doc/draft/change_stream_state.html",
{"doc": doc,
"form": form,
"milestones": milestones,
"state_type": state_type,
"next_states": next_states,
},
context_instance=RequestContext(request))

View file

@ -4,12 +4,14 @@ from django.template import RequestContext
from django.http import Http404
from ietf.doc.models import *
from ietf.doc.utils import get_tags_for_stream_id
def state_help(request, type):
slug, title = {
"draft-iesg": ("draft-iesg", "IESG States For Internet-Drafts"),
"draft-rfceditor": ("draft-rfceditor", "RFC Editor States For Internet-Drafts"),
"draft-iana-action": ("draft-iana-action", "IANA Action States For Internet-Drafts"),
"draft-stream-ietf": ("draft-stream-ietf", "IETF Stream States For Internet-Drafts"),
"charter": ("charter", "Charter States"),
"conflict-review": ("conflrev", "Conflict Review States"),
"status-change": ("statchg", "RFC Status Change States"),
@ -36,6 +38,9 @@ def state_help(request, type):
states.insert(0, fake_state)
tags = DocTagName.objects.filter(slug__in=IESG_SUBSTATE_TAGS)
elif state_type.slug.startswith("draft-stream-"):
possible = get_tags_for_stream_id(state_type.slug.replace("draft-stream-", ""))
tags = DocTagName.objects.filter(slug__in=possible)
return render_to_response("doc/state_help.html", {
"title": title,

View file

@ -12,7 +12,7 @@ from ietf.doc.utils import log_state_changed, 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.decorators import has_role, role_required
from ietf.ietfauth.utils import has_role, role_required
from ietf.utils.textupload import get_cleaned_text_file_content
from ietf.utils.mail import send_mail_preformatted
from ietf.doc.models import State, Document, DocHistory, DocAlias

View file

@ -1,17 +1,15 @@
from django.utils import simplejson as json
from dajaxice.core import dajaxice_functions
from dajaxice.decorators import dajaxice_register
from ietf.ietfauth.decorators import group_required
from django.shortcuts import get_object_or_404
from django.http import HttpResponseRedirect, HttpResponse, Http404
from ietf.group.models import Group
import datetime
import logging
import sys
from ietf.settings import LOG_DIR
log = logging.getLogger(__name__)
from django.utils import simplejson as json
from django.shortcuts import get_object_or_404
from django.http import HttpResponseRedirect, HttpResponse, Http404
from dajaxice.core import dajaxice_functions
from dajaxice.decorators import dajaxice_register
from ietf.group.models import Group
def group_json(request, groupname):
group = get_object_or_404(Group, acronym=groupname)

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -58,26 +58,15 @@ class Group(GroupInfo):
e = model.objects.filter(group=self).filter(**filter_args).order_by('-time', '-id')[:1]
return e[0] if e else None
def is_chair(self, user):
chair = self.get_chair()
if chair:
return self.get_chair().person.user == user
else:
return False
def is_member(self, user):
members = self.get_members()
users = [member.person.user for member in members]
return user in users
def has_role(self, user, role_names):
if isinstance(role_names, str) or isinstance(role_names, unicode):
role_names = [role_names]
return user.is_authenticated() and self.role_set.filter(name__in=role_names, person__user=user).exists()
def get_chair(self):
chair = self.role_set.filter(name__slug='chair')[:1]
return chair and chair[0] or None
def get_members(self):
members = self.role_set.filter(name__slug__in=["chair", "member", "advisor", "liaison"])
return members
# these are copied to Group because it is still proxied.
@property
def upcase_acronym(self):

View file

@ -1,259 +0,0 @@
from ietf.utils.proxy import TranslatingManager, proxy_role_email
from models import *
class Acronym(Group):
class LazyIndividualSubmitter(object):
def __get__(self, obj, type=None):
return Group.objects.get(acronym="none").id
INDIVIDUAL_SUBMITTER = LazyIndividualSubmitter()
def from_object(self, base):
for f in base._meta.fields:
setattr(self, f.name, getattr(base, f.name))
return self
#acronym_id = models.AutoField(primary_key=True)
@property
def acronym_id(self):
return self.id
#acronym = models.CharField(max_length=12) # same name
#name = models.CharField(max_length=100) # same name
#name_key = models.CharField(max_length=50, editable=False)
@property
def name_key(self):
return self.name.upper()
@property
def ietfwg(self):
return IETFWG().from_object(self)
def __str__(self):
return self.acronym
def __unicode__(self):
return self.acronym
class Meta:
proxy = True
class Area(Group):
objects = TranslatingManager(dict(area_acronym__acronym="acronym",
area_acronym__name="name",
status=lambda v: ("state", {1: "active", 2: "dormant", 3: "conclude"}[v] )),
always_filter=dict(type="area"))
def from_object(self, base):
for f in base._meta.fields:
setattr(self, f.name, getattr(base, f.name))
return self
ACTIVE=1
#area_acronym = models.OneToOneField(Acronym, primary_key=True)
@property
def area_acronym(self):
return Acronym().from_object(self)
#start_date = models.DateField(auto_now_add=True)
#concluded_date = models.DateField(null=True, blank=True)
#status = models.ForeignKey(AreaStatus)
@property
def status_id(self):
return { "active": 1, "dormant": 2, "conclude": 3, "proposed": 4 }[self.state_id]
#comments = models.TextField(blank=True)
#last_modified_date = models.DateField(auto_now=True)
@property
def last_modified_date(self):
return self.time.date()
#extra_email_addresses = models.TextField(blank=True,null=True)
#def additional_urls(self):
# return AreaWGURL.objects.filter(name=self.area_acronym.name)
def active_wgs(self):
return IETFWG.objects.filter(type="wg", state="active", parent=self).select_related('type', 'state', 'parent').order_by("acronym")
@property
def areadirector_set(self):
return proxied_role_emails(Email.objects.filter(role__group=self, role__name="ad"))
@staticmethod
def active_areas():
return Area.objects.filter(type="area", state="active").select_related('type', 'state', 'parent').order_by('acronym')
def __str__(self):
return self.acronym
def __unicode__(self):
return self.acronym
class Meta:
proxy = True
def proxied_role_emails(emails):
for e in emails:
proxy_role_email(e)
return emails
class IETFWG(Group):
objects = TranslatingManager(dict(group_acronym="id",
group_acronym__acronym="acronym",
group_acronym__acronym__in="acronym__in",
group_acronym__acronym__contains="acronym__contains",
email_archive__startswith="list_archive__startswith",
group_type=lambda v: ("type__in", { 1: ("wg",), 2: ("wg", "rg") }[int(v)]),
status=lambda v: ("state__in", { 1: ("active", "bof") }[int(v)]),
areagroup__area__status=lambda v: ("parent__state", { 1: "active" }[v]),
start_date__isnull=lambda v: None if v else ("groupevent__changestategroupevent__state__slug", "active"),
),
always_filter=dict(type__in=("wg", "rg", "individ", "area")))
def from_object(self, base):
for f in base._meta.fields:
setattr(self, f.name, getattr(base, f.name))
return self
ACTIVE=1
#group_acronym = models.OneToOneField(Acronym, primary_key=True, editable=False)
@property
def group_acronym(self):
return Acronym().from_object(self)
#group_type = models.ForeignKey(WGType)
#proposed_date = models.DateField(null=True, blank=True)
#start_date = models.DateField(null=True, blank=True)
@property
def start_date(self):
e = GroupEvent.objects.filter(group=self, type="changed_state", changestategroupevent__state="active").order_by('time')[:1]
return e[0].time.date() if e else None
#dormant_date = models.DateField(null=True, blank=True)
#concluded_date = models.DateField(null=True, blank=True)
#status = models.ForeignKey(WGStatus)
@property
def status_id(self):
return { "active": 1, "dormant": 2, "conclude": 3, "bof-conc": 3, "proposed": 4, "bof": 4, "abandon": 4, "replaced": 4}[self.state_id]
#area_director = models.ForeignKey(AreaDirector, null=True)
#meeting_scheduled = models.CharField(blank=True, max_length=3)
@property
def meeting_scheduled(self):
from ietf.meeting.models import Meeting
latest_meeting = Meeting.objects.order_by('-date')[0]
return "YES" if self.session_set.filter(meeting=latest_meeting) else "NO"
#email_address = models.CharField(blank=True, max_length=60)
@property
def email_address(self):
return self.list_email
#email_subscribe = models.CharField(blank=True, max_length=120)
@property
def email_subscribe(self):
return self.list_subscribe
#email_keyword = models.CharField(blank=True, max_length=50)
#email_archive = models.CharField(blank=True, max_length=95)
@property
def email_archive(self):
return self.list_archive
#comments = models.TextField(blank=True)
#last_modified_date = models.DateField()
@property
def last_modified_date(self):
return self.time.date()
#meeting_scheduled_old = models.CharField(blank=True, max_length=3)
#area = FKAsOneToOne('areagroup', reverse=True)
@property
def area(self):
if self.parent:
areagroup = AreaGroup().from_object(self)
return areagroup
else:
return None
def __str__(self):
return self.group_acronym.acronym
def __unicode__(self):
return self.group_acronym.acronym
def active_drafts(self):
from ietf.doc.proxy import InternetDraft
return InternetDraft.objects.filter(group=self, states__type="draft", states__slug="active")
# def choices():
# return [(wg.group_acronym_id, wg.group_acronym.acronym) for wg in IETFWG.objects.all().filter(group_type__type='WG').select_related().order_by('acronym.acronym')]
# choices = staticmethod(choices)
def area_acronym(self):
return Area().from_object(self.parent) if self.parent else None
def area_directors(self):
if not self.parent:
return None
return proxied_role_emails(sorted(Email.objects.filter(role__group=self.parent, role__name="ad"), key=lambda e: e.person.name_parts()[3]))
def chairs(self): # return a set of WGChair objects for this work group
return proxied_role_emails(sorted(Email.objects.filter(role__group=self, role__name="chair"), key=lambda e: e.person.name_parts()[3]))
# def secretaries(self): # return a set of WGSecretary objects for this group
# return WGSecretary.objects.filter(group_acronym__exact=self.group_acronym)
# def milestones(self): # return a set of GoalMilestone objects for this group
# return GoalMilestone.objects.filter(group_acronym__exact=self.group_acronym)
# def rfcs(self): # return a set of Rfc objects for this group
# return Rfc.objects.filter(group_acronym__exact=self.group_acronym)
# def drafts(self): # return a set of Rfc objects for this group
# return InternetDraft.objects.filter(group__exact=self.group_acronym)
def charter_text(self): # return string containing WG description read from file
from ietf.group.utils import get_charter_text
return get_charter_text(self)
def additional_urls(self):
return self.groupurl_set.all().order_by("name")
def clean_email_archive(self):
return self.list_archive
@property
def wgchair_set(self):
# gross hack ...
class Dummy: pass
d = Dummy()
d.all = self.chairs
return d
@property
def wgdelegate_set(self):
from ietf.wgchairs.models import WGDelegate
return WGDelegate.objects.filter(group=self, name="delegate")
class Meta:
proxy = True
class IRTF(Group):
objects = TranslatingManager(dict(),
always_filter=dict(type="rg"))
#irtf_id = models.AutoField(primary_key=True)
@property
def irtf_id(self):
return self.pk
#acronym = models.CharField(blank=True, max_length=25, db_column='irtf_acronym') # same name
#name = models.CharField(blank=True, max_length=255, db_column='irtf_name') # same name
#charter_text = models.TextField(blank=True,null=True)
#meeting_scheduled = models.BooleanField(blank=True)
def __str__(self):
return self.acronym
def __unicode__(self):
return self.acronym
#def chairs(self): # return a set of IRTFChair objects for this work group
# return IRTFChair.objects.filter(irtf=self)
class Meta:
proxy = True
class AreaGroup(Group):
objects = TranslatingManager(dict(group=lambda v: ("pk", v.pk)),
always_filter=dict(type="wg"))
def from_object(self, base):
for f in base._meta.fields:
setattr(self, f.name, getattr(base, f.name))
return self
@property
def area(self):
return Area().from_object(self.parent)
@property
def group(self):
return self
class Meta:
proxy = True

View file

@ -2,13 +2,10 @@
from django.conf.urls.defaults import patterns, include
import views
import views_stream
urlpatterns = patterns('',
(r'^$', views.streams),
(r'^(?P<acronym>[a-zA-Z0-9-]+)/$', views.stream_documents, None),
# (r'^(?P<acronym>[a-zA-Z0-9-]+)/history/$', views.stream_history),
# (r'^(?P<acronym>[a-zA-Z0-9-]+)/edit/$', views.stream_edit)
(r'^management/', include('ietf.ietfworkflows.urls')),
(r'^$', views_stream.streams),
(r'^(?P<acronym>[a-zA-Z0-9-]+)/$', views_stream.stream_documents, None),
(r'^(?P<acronym>[a-zA-Z0-9-]+)/edit/$', views_stream.stream_edit),
)

31
ietf/group/tests.py Normal file
View file

@ -0,0 +1,31 @@
import os, shutil, datetime
import django.test
from django.core.urlresolvers import reverse as urlreverse
from pyquery import PyQuery
from ietf.utils.mail import outbox
from ietf.utils.test_utils import login_testing_unauthorized
from ietf.utils.test_data import make_test_data
from ietf.name.models import *
from ietf.group.models import *
from ietf.person.models import *
class StreamTests(TestCase):
def test_stream_edit(self):
make_test_data()
stream_acronym = "ietf"
url = urlreverse("ietf.group.views_stream.stream_edit", kwargs=dict(acronym=stream_acronym))
login_testing_unauthorized(self, "secretary", url)
# get
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
r = self.client.post(url, dict(delegates="ad2@ietf.org"))
self.assertEqual(r.status_code, 302)
self.assertTrue(Role.objects.filter(name="delegate", group__acronym=stream_acronym, email__address="ad2@ietf.org"))

View file

@ -1,29 +0,0 @@
# Copyright The IETF Trust 2008, All Rights Reserved
from django.shortcuts import render_to_response
from django.template import RequestContext, loader
from django.http import Http404, HttpResponse
from ietf.group.models import Group
from ietf.doc.models import Document
from ietf.doc.views_search import SearchForm, retrieve_search_results
from ietf.name.models import StreamName
import debug
def streams(request):
streams = [ s.slug for s in StreamName.objects.all().exclude(slug__in=['ietf', 'legacy']) ]
streams = Group.objects.filter(acronym__in=streams)
return render_to_response('group/index.html', {'streams':streams}, context_instance=RequestContext(request))
def stream_documents(request, acronym):
streams = [ s.slug for s in StreamName.objects.all().exclude(slug__in=['ietf', 'legacy']) ]
if not acronym in streams:
raise Http404("No such stream: %s" % acronym)
stream = StreamName.objects.get(slug=acronym)
form = SearchForm({'by':'stream', 'stream':acronym,
'rfcs':'on', 'activedrafts':'on'})
docs, meta = retrieve_search_results(form)
return render_to_response('group/stream_documents.html', {'stream':stream, 'docs':docs, 'meta':meta }, context_instance=RequestContext(request))

View file

@ -0,0 +1,75 @@
# Copyright The IETF Trust 2008, All Rights Reserved
from django.shortcuts import render_to_response, get_object_or_404, redirect
from django.template import RequestContext, loader
from django.http import Http404, HttpResponse, HttpResponseForbidden
from django import forms
from ietf.group.models import *
from ietf.group.utils import *
from ietf.doc.models import Document
from ietf.doc.views_search import SearchForm, retrieve_search_results
from ietf.name.models import StreamName
from ietf.ietfauth.utils import has_role
from ietf.person.forms import EmailsField
import debug
def streams(request):
streams = [ s.slug for s in StreamName.objects.all().exclude(slug__in=['ietf', 'legacy']) ]
streams = Group.objects.filter(acronym__in=streams)
return render_to_response('group/index.html', {'streams':streams}, context_instance=RequestContext(request))
def stream_documents(request, acronym):
streams = [ s.slug for s in StreamName.objects.all().exclude(slug__in=['ietf', 'legacy']) ]
if not acronym in streams:
raise Http404("No such stream: %s" % acronym)
stream = StreamName.objects.get(slug=acronym)
form = SearchForm({'by':'stream', 'stream':acronym,
'rfcs':'on', 'activedrafts':'on'})
docs, meta = retrieve_search_results(form)
return render_to_response('group/stream_documents.html', {'stream':stream, 'docs':docs, 'meta':meta }, context_instance=RequestContext(request))
class StreamEditForm(forms.Form):
delegates = EmailsField(label="Delegates", required=False, help_text=u"Type in name to search for person")
def stream_edit(request, acronym):
group = get_object_or_404(Group, acronym=acronym)
if not (has_role(request.user, "Secretariat") or group.has_role(request.user, "chair")):
return HttpResponseForbidden("You don't have permission to access this page.")
chairs = Email.objects.filter(role__group=group, role__name="chair").select_related("person")
if request.method == 'POST':
form = StreamEditForm(request.POST)
if form.is_valid():
save_group_in_history(group)
# update roles
attr, slug, title = ('delegates', 'delegate', "Delegates")
new = form.cleaned_data[attr]
old = Email.objects.filter(role__group=group, role__name=slug).select_related("person")
if set(new) != set(old):
desc = "%s changed to <b>%s</b> from %s" % (
title, ", ".join(x.get_name() for x in new), ", ".join(x.get_name() for x in old))
GroupEvent.objects.create(group=group, by=request.user.get_profile(), type="info_changed", desc=desc)
group.role_set.filter(name=slug).delete()
for e in new:
Role.objects.get_or_create(name_id=slug, email=e, group=group, person=e.person)
return redirect("ietf.group.views.streams")
else:
form = StreamEditForm(initial=dict(delegates=Email.objects.filter(role__group=group, role__name="delegate")))
return render_to_response('group/stream_edit.html',
{'group': group,
'chairs': chairs,
'form': form,
},
context_instance=RequestContext(request))

View file

@ -9,10 +9,7 @@ from ietf.doc.models import *
from ietf.idindex.index import *
class IndexTestCase(TestCase):
# See ietf.utils.test_utils.TestCase for the use of perma_fixtures vs. fixtures
perma_fixtures = ['names']
class IndexTests(TestCase):
def setUp(self):
self.id_dir = os.path.abspath("tmp-id-dir")
os.mkdir(self.id_dir)

View file

@ -1 +0,0 @@
/*.pyc

View file

@ -1 +0,0 @@
#

View file

@ -1,967 +0,0 @@
# Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
# All rights reserved. Contact: Pasi Eronen <pasi.eronen@nokia.com>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# * Neither the name of the Nokia Corporation and/or its
# subsidiary(-ies) nor the names of its contributors may be used
# to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from ietf.idtracker.models import InternetDraft, IDInternal, BallotInfo, IESGDiscuss, IESGLogin, DocumentComment, Acronym, IDState
from ietf.idrfc.models import RfcEditorQueue
from ietf.ipr.models import IprRfc, IprDraft, IprDetail
from ietf.doc.models import BallotDocEvent
import re
from datetime import date
from django.utils import simplejson as json
from django.db.models import Q
from django.db import models
from django.core.urlresolvers import reverse
from django.conf import settings
import types
import debug
BALLOT_ACTIVE_STATES = ['In Last Call',
'Waiting for Writeup',
'Waiting for AD Go-Ahead',
'IESG Evaluation',
'IESG Evaluation - Defer']
def jsonify_helper(obj, keys):
result = {}
for k in keys:
if hasattr(obj, k):
v = getattr(obj, k)
if callable(v):
v = v()
if v == None:
pass
elif isinstance(v, (types.StringType, types.IntType, types.BooleanType, types.LongType, types.ListType, types.UnicodeType)):
result[k] = v
elif isinstance(v, date):
result[k] = str(v)
else:
result[k] = 'Unknown type '+str(type(v))
return result
# Wrappers to make writing templates less painful
# ---------------------------------------------------------------------------
class IdWrapper:
_draft = None
_idinternal = None
is_id_wrapper = True
is_rfc_wrapper = False
draft_name = None
# Active/Expired/RFC/Withdrawn by Submitter/Replaced/Withdrawn by IETF
draft_status = None
# Revision is sometimes incorrect (+1 too large) if status != Active
latest_revision = None
# Set if and only if draft_status is "RFC"
rfc_number = None
title = None
tracker_id = None
publication_date = None
ietf_process = None
def __init__(self, draft):
self.id = self
if isinstance(draft, IDInternal) and not settings.USE_DB_REDESIGN_PROXY_CLASSES:
self._idinternal = draft
self._draft = self._idinternal.draft
else:
self._draft = draft
if draft.idinternal:
self._idinternal = draft.idinternal
if self._idinternal:
self.ietf_process = IetfProcessData(self._idinternal)
self.draft_name = self._draft.filename
self.draft_status = str(self._draft.status)
if self.draft_status == "RFC":
if self._draft.rfc_number:
self.rfc_number = self._draft.rfc_number
else:
# Handle incorrect database entries
self.draft_status = "Expired"
self.latest_revision = self._draft.revision_display()
self.title = self._draft.title
self.tracker_id = self._draft.id_document_tag
self.resurrect_requested_by = self._idinternal.resurrect_requested_by if self._idinternal else None
self.publication_date = self._draft.revision_date
if not self.publication_date:
# should never happen -- but unfortunately it does. Return an
# obviously bogus date
self.publication_date = date(1990,1,1)
def rfc_editor_state(self):
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
s = self._draft.get_state("draft-rfceditor")
if s:
# extract possible extra annotations
tags = self._draft.tags.filter(slug__in=("iana", "ref"))
return "*".join([s.name] + [t.slug.upper() for t in tags])
else:
return None
try:
qs = self._draft.rfc_editor_queue_state
return qs.state
except RfcEditorQueue.DoesNotExist:
pass
return None
def replaced_by(self):
try:
if self._draft.replaced_by:
return [self._draft.replaced_by.filename]
except InternetDraft.DoesNotExist:
pass
return None
def replaces(self):
r = [str(r.filename) for r in self._draft.replaces_set.all()]
if len(r) > 0:
return r
else:
return None
def in_ietf_process(self):
return self.ietf_process != None
def submission(self):
if self._draft.stream_id != u'ietf':
return self._draft.stream
if self._draft.group_id == Acronym.INDIVIDUAL_SUBMITTER:
return "Individual"
if self._draft.group and self._draft.group.type_id == "area":
return u"Individual in %s area" % self._draft.group.acronym
a = self.group_acronym()
if a:
if self._draft.stream_id == "ietf" and self._draft.get_state_slug("draft-stream-ietf") == "c-adopt":
return "candidate for <a href='/wg/%s/'>%s WG</a>" % (a, a)
return "<a href='/wg/%s/'>%s WG</a>" % (a, a)
return ""
submission.allow_tags = True
def search_archive(self):
if self._idinternal and self._idinternal.stream in ("IRTF","ISE"):
return "www.ietf.org/mail-archive/web/"
if self._draft.group_id == Acronym.INDIVIDUAL_SUBMITTER or (settings.USE_DB_REDESIGN_PROXY_CLASSES and self._draft.group.type_id == "area"):
return "www.ietf.org/mail-archive/web/"
a = self._draft.group_ml_archive()
if a:
return a
return ""
def file_types(self):
return self._draft.file_type.split(",")
def group_acronym(self):
if self._draft.group_id != 0 and self._draft.group != None and str(self._draft.group) != "none":
if settings.USE_DB_REDESIGN_PROXY_CLASSES and self._draft.group.type_id == "area":
return None
return str(self._draft.group)
else:
return None
# TODO: Returning integers here isn't nice
# 0=Unknown, 1=IETF, 2=IAB, 3=IRTF, 4=Independent
def stream_id(self):
if self.draft_name.startswith("draft-iab-"):
return 2
elif self.draft_name.startswith("draft-irtf-"):
return 3
elif self._idinternal:
if self._idinternal.stream == "ISE":
return 4
else:
return 1
elif self.group_acronym():
return 1
else:
return 0
def draft_name_and_revision(self):
return self.draft_name+"-"+self.latest_revision
def friendly_state(self):
if self.draft_status == "RFC":
return "<a href=\"%s\">RFC %d</a>" % (reverse('doc_view', args=['rfc%d' % self.rfc_number]), self.rfc_number)
elif self.draft_status == "Active":
if self.in_ietf_process():
if self.ietf_process.main_state == "Dead":
# Many drafts in "Dead" state are not dead; they're
# just not currently under IESG processing. Show
# them as "I-D Exists (IESG: Dead)" instead...
return "I-D Exists (IESG: "+self.ietf_process.state+")"
elif self.ietf_process.main_state == "In Last Call":
return self.ietf_process.state + " (ends "+str(self._idinternal.document().lc_expiration_date)+")"
else:
return self.ietf_process.state
else:
return "I-D Exists"
else:
if self.in_ietf_process() and self.ietf_process.main_state == "Dead":
return self.draft_status+" (IESG: "+self.ietf_process.state+")"
# Expired/Withdrawn by Submitter/IETF
return self.draft_status
def abstract(self):
return self._draft.clean_abstract()
# TODO: ugly hack
def authors(self):
return self._draft.authors
def expected_expiration_date(self):
if self.draft_status == "Active" and self._draft.can_expire():
return self._draft.expiration()
else:
return None
def ad_name(self):
if self.in_ietf_process():
return self.ietf_process.ad_name()
else:
return None
def get_absolute_url(self):
return "/doc/"+self.draft_name+"/"
def displayname_with_link(self):
return '<a href="%s">%s</a>' % (self.get_absolute_url(), self.draft_name_and_revision())
def underlying_document(self):
""" Expose the Document object underneath the proxy """
from ietf.doc.models import Document
return Document.objects.get(docalias__name=self.draft_name)
def to_json(self):
result = jsonify_helper(self, ['draft_name', 'draft_status', 'latest_revision', 'rfc_number', 'title', 'tracker_id', 'publication_date','rfc_editor_state', 'replaced_by', 'replaces', 'in_ietf_process', 'file_types', 'group_acronym', 'stream_id','friendly_state', 'abstract', 'ad_name'])
if self.in_ietf_process():
result['ietf_process'] = self.ietf_process.dict()
return json.dumps(result, indent=2)
# ---------------------------------------------------------------------------
class RfcWrapper:
_rfc = None
_rfcindex = None
_idinternal = None
is_id_wrapper = False
is_rfc_wrapper = True
rfc_number = None
title = None
publication_date = None
maturity_level = None
ietf_process = None
draft_name = None
def __init__(self, rfcindex, rfc=None, idinternal=None):
self._rfcindex = rfcindex
self._rfc = rfc
self._idinternal = idinternal
self.rfc = self
if not self._idinternal:
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
pub = rfcindex.rfc_published_date
started = rfcindex.started_iesg_process if hasattr(rfcindex, 'started_iesg_process') else rfcindex.latest_event(type="started_iesg_process")
if pub and started and pub < started.time.date():
self._idinternal = rfcindex
else:
try:
self._idinternal = IDInternal.objects.get(rfc_flag=1, draft=self._rfcindex.rfc_number)
except IDInternal.DoesNotExist:
pass
if self._idinternal:
self.ietf_process = IetfProcessData(self._idinternal)
self.rfc_number = self._rfcindex.rfc_number
self.title = self._rfcindex.title
self.publication_date = self._rfcindex.rfc_published_date
self.maturity_level = self._rfcindex.current_status
if not self.maturity_level:
self.maturity_level = "Unknown"
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
if not rfcindex.name.startswith('rfc'):
self.draft_name = rfcindex.name
return # we've already done the lookup while importing so skip the rest
ids = InternetDraft.objects.filter(rfc_number=self.rfc_number)
if len(ids) >= 1:
self.draft_name = ids[0].filename
elif self._rfcindex and self._rfcindex.draft:
# rfcindex occasionally includes drafts that were not
# really submitted to IETF (e.g. April 1st)
ids = InternetDraft.objects.filter(filename=self._rfcindex.draft)
if len(ids) > 0:
self.draft_name = self._rfcindex.draft
def _rfc_doc_list(self, name):
if (not self._rfcindex) or (not getattr(self._rfcindex, name)):
return None
else:
s = getattr(self._rfcindex, name)
s = s.replace(",", ", ")
s = re.sub("([A-Z])([0-9])", "\\1 \\2", s)
return s
def obsoleted_by(self):
return self._rfc_doc_list("obsoleted_by")
def obsoletes(self):
return self._rfc_doc_list("obsoletes")
def updated_by(self):
return self._rfc_doc_list("updated_by")
def updates(self):
return self._rfc_doc_list("updates")
def also(self):
return self._rfc_doc_list("also")
def has_errata(self):
return self._rfcindex and (self._rfcindex.has_errata > 0)
def stream_name(self):
if not self._rfcindex:
return None
else:
x = self._rfcindex.stream
if x == "INDEPENDENT":
return "Independent Submission Stream"
elif x == "LEGACY":
return "Legacy Stream"
else:
return x+" Stream"
def in_ietf_process(self):
return self.ietf_process != None
def file_types(self):
types = self._rfcindex.file_formats
types = types.replace("ascii","txt")
return ["."+x for x in types.split(",")]
def friendly_state(self):
if self.in_ietf_process():
s = self.ietf_process.main_state
if not s in ["RFC Published", "AD is watching", "Dead"]:
return "RFC %d (%s)<br/>%s (to %s)" % (self.rfc_number, self.maturity_level, self.ietf_process.state, self.ietf_process.intended_maturity_level())
return "RFC %d (%s)" % (self.rfc_number, self.maturity_level)
def ad_name(self):
if self.in_ietf_process():
return self.ietf_process.ad_name()
else:
# TODO: get AD name of the draft
return None
def filename(self):
return self._rfcindex.filename
@models.permalink
def get_absolute_url(self):
return ('ietf.doc.views_doc.document_main', ['rfc%s' % (str(self.rfc_number))])
def displayname_with_link(self):
return '<a href="%s">RFC %d</a>' % (self.get_absolute_url(), self.rfc_number)
def to_json(self):
result = jsonify_helper(self, ['rfc_number', 'title', 'publication_date', 'maturity_level', 'obsoleted_by','obsoletes','updated_by','updates','also','has_errata','stream_name','file_types','in_ietf_process', 'friendly_state'])
if self.in_ietf_process():
result['ietf_process'] = self.ietf_process.dict()
return json.dumps(result, indent=2)
def underlying_document(self):
""" Expose the Document object underneath the proxy """
# Things like RFC500 are special - there may not _be_ a docalias for them
from ietf.doc.models import Document
q = Document.objects.filter(docalias__name='rfc%04d'%self.rfc_number)
if q:
return q[0]
else:
return None
# ---------------------------------------------------------------------------
class IetfProcessData:
_idinternal = None
main_state = None
sub_state = None
state = None
_ballot = None
def __init__(self, idinternal):
self._idinternal = idinternal
i = self._idinternal
self.main_state = str(i.cur_state)
if i.cur_sub_state_id > 0:
self.sub_state = str(i.cur_sub_state)
self.state = self.main_state + "::" + self.sub_state
else:
self.sub_state = None
self.state = self.main_state
def has_iesg_ballot(self):
try:
if self._idinternal.ballot.ballot_issued:
return True
except BallotInfo.DoesNotExist:
pass
return False
def has_active_iesg_ballot(self):
if not self.has_iesg_ballot():
return False
if not self.main_state in BALLOT_ACTIVE_STATES:
return False
if (not self._idinternal.rfc_flag) and self._idinternal.draft.status_id != 1:
# Active
return False
return True
# don't call this unless has_[active_]iesg_ballot returns True
def iesg_ballot(self):
if not self._ballot:
self._ballot = BallotWrapper(self._idinternal)
return self._ballot
# don't call this unless has_[active_]iesg_ballot returns True
def iesg_ballot_needed( self ):
standardsTrack = 'Standard' in self.intended_maturity_level() or \
self.intended_maturity_level() in ("BCP", "Best Current Practice")
return self.iesg_ballot().ballot.needed( standardsTrack )
def ad_name(self):
return str(self._idinternal.job_owner)
def iesg_note(self):
if self._idinternal.note:
n = self._idinternal.note
# Hide unnecessary note of form "RFC 1234"
if re.match("^RFC\s*\d+$", n):
return None
return n
else:
return None
def state_date(self):
try:
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
return self._idinternal.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 has approved and state has been changed to")|
Q(desc__istartswith="IESG process started in state")).order_by('-time')[0].time.date()
return self._idinternal.comments().filter(
Q(comment_text__istartswith="Draft Added by ")|
Q(comment_text__istartswith="Draft Added in state ")|
Q(comment_text__istartswith="Draft added in state ")|
Q(comment_text__istartswith="State changed to ")|
Q(comment_text__istartswith="State Changes to ")|
Q(comment_text__istartswith="Sub state has been changed to ")|
Q(comment_text__istartswith="State has been changed to ")|
Q(comment_text__istartswith="IESG has approved and state has been changed to")).order_by('-id')[0].date
except IndexError:
# should never happen -- return an obviously bogus date
return date(1990,1,1)
def dict(self):
result = {'main_state':self.main_state,
'sub_state':self.sub_state,
'state':self.state,
'state_date':str(self.state_date()),
'has_iesg_ballot':self.has_iesg_ballot(),
'has_active_iesg_ballot':self.has_active_iesg_ballot(),
'ad_name':self.ad_name(),
'intended_maturity_level':self.intended_maturity_level(),
'telechat_date':self.telechat_date()}
if result['telechat_date']:
result['telechat_date'] = str(result['telechat_date'])
result['telechat_returning_item'] = self.telechat_returning_item()
if self.iesg_note():
result['iesg_note'] = self.iesg_note()
if self.has_iesg_ballot():
result['iesg_ballot'] = self.iesg_ballot().dict()
return result
def intended_maturity_level(self):
if self._idinternal.rfc_flag:
s = str(self._idinternal.document().intended_status)
# rfc_intend_status table uses different names, argh!
if s == "Proposed":
s = "Proposed Standard"
elif s == "Draft":
s = "Draft Standard"
elif s == "None":
s = None
else:
s = str(self._idinternal.draft.intended_status)
if s == "None":
s = None
elif s == "Request":
s = None
return s
def telechat_date(self):
# return date only if it's on upcoming agenda
if self._idinternal.agenda:
return self._idinternal.telechat_date
else:
return None
def telechat_returning_item(self):
# should be called only if telechat_date() returns non-None
return bool(self._idinternal.returning_item)
def state_change_notice_to(self):
return self._idinternal.state_change_notice_to
# comment_log?
# ---------------------------------------------------------------------------
class IdRfcWrapper:
rfc = None
id = None
iprCount = None
iprUrl = None
def __init__(self, id, rfc):
self.id = id
self.rfc = rfc
if id:
iprs = IprDraft.objects.filter(document=self.id.tracker_id, ipr__status__in=[1,3])
self.iprUrl = "/ipr/search?option=document_search&id_document_tag=" + str(self.id.tracker_id)
elif rfc:
iprs = IprRfc.objects.filter(document=self.rfc.rfc_number, ipr__status__in=[1,3])
self.iprUrl = "/ipr/search?option=rfc_search&rfc_search=" + str(self.rfc.rfc_number)
else:
raise ValueError("Construction with null id and rfc")
# iprs is a list of docs which contain IPR
self.iprCount = len(iprs)
def title(self):
if self.rfc:
return self.rfc.title
else:
return self.id.title
def friendly_state(self):
if self.rfc:
return self.rfc.friendly_state()
else:
return self.id.friendly_state()
def get_absolute_url(self):
if self.rfc:
return self.rfc.get_absolute_url()
else:
return self.id.get_absolute_url()
def comment_count(self):
if self.rfc:
return DocumentComment.objects.filter(document=self.rfc.rfc_number,rfc_flag=1).count()
else:
return DocumentComment.objects.filter(document=self.id.tracker_id).exclude(rfc_flag=1).count()
def ad_name(self):
if self.rfc:
s = self.rfc.ad_name()
if s:
return s
if self.id:
return self.id.ad_name()
return None
def publication_date(self):
if self.rfc:
return self.rfc.publication_date
else:
return self.id.publication_date
def telechat_date(self):
if self.rfc and self.rfc.in_ietf_process():
return self.rfc.ietf_process.telechat_date()
elif self.id and self.id.in_ietf_process():
return self.id.ietf_process.telechat_date()
else:
return None
def view_sort_group(self):
if self.rfc:
return 'RFC'
elif self.id.draft_status == "Active":
return 'Active Internet-Draft'
else:
return 'Old Internet-Draft'
def view_sort_group_byad(self):
if self.rfc:
return 'RFC'
elif self.id.draft_status == "Active":
if self.id.in_ietf_process():
if self.id.ietf_process._idinternal.cur_state_id == IDState.DEAD:
return 'IESG Dead Internet-Draft'
else:
return "%s Internet-Draft" % self.id.ietf_process._idinternal.cur_state
else:
return 'Active Internet-Draft'
else:
return 'Old Internet-Draft'
def view_sort_key(self, sort_by=None):
if sort_by is None:
if self.rfc:
return "2%04d" % self.rfc.rfc_number
elif self.id.draft_status == "Active":
return "1"+self.id.draft_name
else:
return "3"+self.id.draft_name
else:
if self.rfc:
sort_key = "2"
elif self.id.draft_status == "Active":
sort_key = "1"
else:
sort_key = "3"
# Depending on what we're sorting on, we may
# need to do some conversion.
if sort_by == "title":
sort_key += self.title()
elif sort_by == "date":
sort_key = sort_key + str(self.publication_date())
elif sort_by == "status":
if self.rfc:
sort_key += "%04d" % self.rfc.rfc_number
else:
sort_key += self.id.draft_status
elif sort_by == "ipr":
sort_key += self.iprUrl
elif sort_by == "ad":
return self.view_sort_key_byad()
else:
# sort default or unknown sort value, revert to default
if self.rfc:
sort_key += "%04d" % self.rfc.rfc_number
else:
sort_key += self.id.draft_name
return sort_key
def view_sort_key_byad(self):
if self.rfc:
return "2%04d" % self.rfc.rfc_number
elif self.id.draft_status == "Active":
if self.id.in_ietf_process():
return "11%02d" % (self.id.ietf_process._idinternal.cur_state_id)
else:
return "10"
else:
return "3"
# ---------------------------------------------------------------------------
class BallotWrapper:
_idinternal = None
ballot = None
ballot_active = False
_positions = None
position_values = ["Discuss", "Yes", "No Objection", "Abstain", "Recuse", "No Record"]
def __init__(self, idinternal):
self._idinternal = idinternal
self.ballot = idinternal.ballot
if not idinternal.rfc_flag:
self.ballot_active = self.ballot.ballot_issued and (str(idinternal.cur_state) in BALLOT_ACTIVE_STATES) and str(idinternal.draft.status)=="Active";
else:
self.ballot_active = self.ballot.ballot_issued and (str(idinternal.cur_state) in BALLOT_ACTIVE_STATES)
self._ballot_set = None
def approval_text(self):
return self.ballot.approval_text
def ballot_writeup(self):
return self.ballot.ballot_writeup
def is_active(self):
return self.ballot_active
def ballot_id(self):
return self._idinternal.ballot_id
def was_deferred(self):
return self.ballot.defer
def deferred_by(self):
return self.ballot.defer_by
def deferred_date(self):
return self.ballot.defer_date
def is_ballot_set(self):
if not self._ballot_set:
self._ballot_set = self._idinternal.ballot_set()
return len(list(self._ballot_set)) > 1
def ballot_set_other(self):
if not self.is_ballot_set():
return []
else:
return self._ballot_set.exclude(draft=self._idinternal)
def _init(self):
if not settings.USE_DB_REDESIGN_PROXY_CLASSES:
self.old_init()
return
from ietf.person.models import Person
from ietf.doc.models import BallotPositionDocEvent, NewRevisionDocEvent, BallotDocEvent
active_ads = Person.objects.filter(role__name="ad", role__group__state="active").distinct()
positions = []
seen = {}
new_revisions = list(NewRevisionDocEvent.objects.filter(doc=self.ballot, type="new_revision").order_by('-time', '-id'))
ballot = self.ballot.latest_event(BallotDocEvent, type="created_ballot")
for pos in BallotPositionDocEvent.objects.filter(doc=self.ballot, type="changed_ballot_position", ballot=ballot).select_related('ad').order_by("-time", '-id'):
if pos.ad not in seen:
p = dict(ad_name=pos.ad.plain_name(),
ad_username=pos.ad.pk, # ought to rename this in doc_ballot_list
position=pos.pos.name,
is_old_ad=pos.ad not in active_ads,
old_positions=[])
rev = pos.doc.rev
for n in new_revisions:
if n.time <= pos.time:
rev = n.rev
break
if pos.pos.slug == "discuss":
p["has_text"] = True
p["discuss_text"] = pos.discuss
p["discuss_date"] = pos.discuss_time.date()
p["discuss_revision"] = rev
if pos.comment:
p["has_text"] = True
p["comment_text"] = pos.comment
p["comment_date"] = pos.comment_time.date()
p["comment_revision"] = rev
positions.append(p)
seen[pos.ad] = p
else:
latest = seen[pos.ad]
if latest["old_positions"]:
prev = latest["old_positions"][-1]
else:
prev = latest["position"]
if prev != pos.pos.name:
seen[pos.ad]["old_positions"].append(pos.pos.name)
# add any missing ADs as No Record
if self.ballot_active:
for ad in active_ads:
if ad not in seen:
d = dict(ad_name=ad.plain_name(),
ad_username=ad.pk,
position="No Record",
)
positions.append(d)
self._positions = positions
def old_init(self):
try:
ads = set()
except NameError:
# for Python 2.3
from sets import Set as set
ads = set()
positions = []
all_comments = self.ballot.comments.all().select_related('ad')
for p in self.ballot.positions.all().select_related('ad'):
po = create_position_object(self.ballot, p, all_comments)
#if not self.ballot_active:
# if 'is_old_ad' in po:
# del po['is_old_ad']
ads.add(str(p.ad))
positions.append(po)
for c in all_comments:
if (str(c.ad) not in ads) and c.ad.is_current_ad():
positions.append({'has_text':True,
'comment_text':c.text,
'comment_date':c.date,
'comment_revision':str(c.revision),
'ad_name':str(c.ad),
'ad_username': c.ad.login_name,
'position':'No Record',
'is_old_ad':False})
ads.add(str(c.ad))
if self.ballot_active:
for ad in IESGLogin.active_iesg():
if str(ad) not in ads:
positions.append(dict(ad_name=str(ad),
ad_username=ad.login_name,
position="No Record"))
self._positions = positions
def position_for_ad(self, ad_name):
pl = self.position_list()
for p in pl:
if p["ad_name"] == ad_name:
return p["position"]
return None
def position_list(self):
if not self._positions:
self._init()
return self._positions
def get(self, v):
return [p for p in self.position_list() if p['position']==v]
def get_discuss(self):
return self.get("Discuss")
def get_yes(self):
return self.get("Yes")
def get_no_objection(self):
return self.get("No Objection")
def get_abstain(self):
return self.get("Abstain")
def get_recuse(self):
return self.get("Recuse")
def get_no_record(self):
return self.get("No Record")
def get_texts(self):
return [p for p in self.position_list() if ('has_text' in p) and p['has_text']]
def dict(self):
summary = {}
for key in self.position_values:
tag = key.lower().replace(" ", "_")
summary[tag] = [ pos["ad_name"] for pos in self.get(key) ]
positions = self.position_list()
for i in range(len(positions)):
for key in ["comment_date", "discuss_date", ]:
if key in positions[i]:
positions[i][key] = positions[i][key].strftime("%Y-%m-%d")
return {
"active": self.is_active(),
"approval_text": self.approval_text(),
"ballot_writeup": self.ballot_writeup(),
"ballot_id": self.ballot_id(),
"deferred_by": unicode(self.deferred_by()),
"deferred_date": self.deferred_date() and self.deferred_date().strftime("%Y-%m-%d") ,
"positions": positions,
"summary": summary,
"was_deferred": self.was_deferred(),
}
def position_to_string(position):
positions = {"yes":"Yes",
"noobj":"No Objection",
"discuss":"Discuss",
"abstain":"Abstain",
"recuse":"Recuse"}
if not position:
return "No Record"
p = None
for k,v in positions.iteritems():
if getattr(position, k) > 0:
p = v
if not p:
p = "No Record"
return p
def create_position_object(ballot, position, all_comments):
positions = {"yes":"Yes",
"noobj":"No Objection",
"discuss":"Discuss",
"abstain":"Abstain",
"recuse":"Recuse"}
p = None
for k,v in positions.iteritems():
if position.__dict__[k] > 0:
p = v
if not p:
p = "No Record"
r = dict(ad_name=str(position.ad),
ad_username=position.ad.login_name,
position=p)
if not position.ad.is_current_ad():
r['is_old_ad'] = True
else:
r['is_old_ad'] = False
was = [v for k,v in positions.iteritems() if position.__dict__[k] < 0]
if len(was) > 0:
r['old_positions'] = was
comment = None
for c in all_comments:
if c.ad == position.ad:
comment = c
break
if comment and comment.text:
r['has_text'] = True
r['comment_text'] = comment.text
r['comment_date'] = comment.date
r['comment_revision'] = str(comment.revision)
if p == "Discuss":
try:
discuss = ballot.discusses.get(ad=position.ad)
if discuss.text:
r['discuss_text'] = discuss.text
else:
r['discuss_text'] = '(empty)'
r['discuss_revision'] = str(discuss.revision)
r['discuss_date'] = discuss.date
except IESGDiscuss.DoesNotExist:
# this should never happen, but unfortunately it does
# fill in something to keep other parts of the code happy
r['discuss_text'] = "(error: discuss text not found)"
r['discuss_revision'] = "00"
r['discuss_date'] = date(2000, 1,1)
r['has_text'] = True
return r

View file

@ -1,88 +0,0 @@
# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
# All rights reserved. Contact: Pasi Eronen <pasi.eronen@nokia.com>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# * Neither the name of the Nokia Corporation and/or its
# subsidiary(-ies) nor the names of its contributors may be used
# to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from ietf import settings
from django.core import management
management.setup_environ(settings)
from django import db
import urllib2
from datetime import datetime
import socket
import sys
URL = "http://merlot.tools.ietf.org/~pasi/draft_versions.txt"
TABLE = "draft_versions_mirror"
log_data = ""
def log(line):
global log_data
if len(sys.argv) > 1:
print line
else:
log_data += line + "\n"
try:
log("output from mirror_draft_versions.py:\n")
log("time: "+str(datetime.now()))
log("host: "+socket.gethostname())
log("url: "+URL)
log("downloading...")
socket.setdefaulttimeout(30)
response = urllib2.urlopen(URL)
#log("got \n"+str(response.info()))
log("parsing...")
data = []
for line in response.readlines():
rec = line[:-1].split("\t")
data.append(rec)
log("got " + str(len(data)) + " entries")
if len(data) < 10000:
raise Exception('not enough data')
log("connecting to database...")
cursor = db.connection.cursor()
log("removing old data...")
cursor.execute("DELETE FROM "+TABLE)
log("inserting new data...")
cursor.executemany("INSERT INTO "+TABLE+" (filename, revision, revision_date) VALUES (%s, %s, %s)", data)
cursor.close()
db.connection._commit()
db.connection.close()
log("all done!")
log_data = ""
finally:
if len(log_data) > 0:
print log_data

View file

@ -1,104 +0,0 @@
# Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
# All rights reserved. Contact: Pasi Eronen <pasi.eronen@nokia.com>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# * Neither the name of the Nokia Corporation and/or its
# subsidiary(-ies) nor the names of its contributors may be used
# to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from django.db import models
from ietf.idtracker.models import InternetDraft
class RfcEditorQueue(models.Model):
STREAM_CHOICES = (
(0, 'Unknown'),
(1, 'IETF'),
(2, 'IAB'),
(3, 'IRTF'),
(4, 'Independent')
)
draft = models.OneToOneField(InternetDraft, db_column="id_document_tag", related_name="rfc_editor_queue_state",primary_key=True)
date_received = models.DateField()
state = models.CharField(max_length=200, blank=True, null=True)
# currently, queue2.xml does not have this information, so
# this field will be NULL (but we could get it from other sources)
state_date = models.DateField(blank=True,null=True)
stream = models.IntegerField(choices=STREAM_CHOICES)
auth48_url = models.CharField(max_length=200, blank=True, null=True)
rfc_number = models.IntegerField(null=True)
def __str__(self):
return "RfcEditorQueue"+str([self.draft, self.date_received, self.state, self.state_date, self.stream])
class Meta:
db_table = "rfc_editor_queue_mirror"
class RfcEditorQueueRef(models.Model):
source = models.ForeignKey(InternetDraft, db_column="source", related_name="rfc_editor_queue_refs")
destination = models.CharField(max_length=200)
in_queue = models.BooleanField()
direct = models.BooleanField() # Is this a direct (or indirect) depencency?
class Meta:
db_table = "rfc_editor_queue_mirror_refs"
class RfcIndex(models.Model):
rfc_number = models.IntegerField(primary_key=True)
title = models.CharField(max_length=250)
authors = models.CharField(max_length=250)
rfc_published_date = models.DateField()
current_status = models.CharField(max_length=50,null=True)
updates = models.CharField(max_length=200,blank=True,null=True)
updated_by = models.CharField(max_length=200,blank=True,null=True)
obsoletes = models.CharField(max_length=200,blank=True,null=True)
obsoleted_by = models.CharField(max_length=200,blank=True,null=True)
also = models.CharField(max_length=50,blank=True,null=True)
draft = models.CharField(max_length=200,null=True)
has_errata = models.BooleanField()
stream = models.CharField(max_length=15,blank=True,null=True)
wg = models.CharField(max_length=15,blank=True,null=True)
file_formats = models.CharField(max_length=20,blank=True,null=True)
def __str__(self):
return "RfcIndex"+str(self.rfc_number)
class Meta:
db_table = "rfc_index_mirror"
class DraftVersions(models.Model):
# Django does not support multi-column primary keys, so
# we can't use filename+revision. But the key for this table
# does not really matter, so we'll have an 'id' field
id = models.AutoField(primary_key=True)
filename = models.CharField(max_length=200, db_index=True)
revision = models.CharField(max_length=2)
revision_date = models.DateField()
def __str__(self):
return "DraftVersions"+self.filename+self.revision+str(self.revision_date)
class Meta:
db_table = "draft_versions_mirror"
from django.conf import settings
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
RfcIndexOld = RfcIndex
from ietf.doc.proxy import RfcIndex

View file

@ -1 +0,0 @@
/*.pyc

View file

@ -1,2 +0,0 @@
# Copyright The IETF Trust 2007, All Rights Reserved

View file

@ -1 +0,0 @@
/*.pyc

View file

@ -1,437 +0,0 @@
from south.db import db
from django.db import models
from ietf.idtracker.models import *
class Migration:
def forwards(self, orm):
# Adding field 'InternetDraft.shepherd'
db.add_column('internet_drafts', 'shepherd', orm['idtracker.internetdraft:shepherd'])
def backwards(self, orm):
# Deleting field 'InternetDraft.shepherd'
db.delete_column('internet_drafts', 'shepherd_id')
models = {
'idtracker.acronym': {
'Meta': {'db_table': "'acronym'"},
'acronym': ('django.db.models.fields.CharField', [], {'max_length': '12'}),
'acronym_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name_key': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'idtracker.area': {
'Meta': {'db_table': "'areas'"},
'area_acronym': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['idtracker.Acronym']", 'unique': 'True', 'primary_key': 'True'}),
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'concluded_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'extra_email_addresses': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'last_modified_date': ('django.db.models.fields.DateField', [], {'auto_now': 'True', 'blank': 'True'}),
'start_date': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.AreaStatus']"})
},
'idtracker.areadirector': {
'Meta': {'db_table': "'area_directors'"},
'area': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.Area']", 'null': 'True', 'db_column': "'area_acronym_id'"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"})
},
'idtracker.areagroup': {
'Meta': {'db_table': "'area_group'"},
'area': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'areagroup'", 'db_column': "'area_acronym_id'", 'to': "orm['idtracker.Area']"}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IETFWG']", 'unique': 'True', 'db_column': "'group_acronym_id'"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'idtracker.areastatus': {
'Meta': {'db_table': "'area_status'"},
'status': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'status_value'"}),
'status_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'idtracker.areawgurl': {
'Meta': {'db_table': "'wg_www_pages'"},
'description': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True', 'db_column': "'area_ID'"}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_column': "'area_Name'"}),
'url': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'idtracker.ballotinfo': {
'Meta': {'db_table': "'ballot_info'"},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'an_sent': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'an_sent_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ansent'", 'null': 'True', 'db_column': "'an_sent_by'", 'to': "orm['idtracker.IESGLogin']"}),
'an_sent_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'approval_text': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'ballot': ('django.db.models.fields.AutoField', [], {'primary_key': 'True', 'db_column': "'ballot_id'"}),
'ballot_issued': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'ballot_writeup': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'defer': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'defer_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'deferred'", 'null': 'True', 'db_column': "'defer_by'", 'to': "orm['idtracker.IESGLogin']"}),
'defer_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'last_call_text': ('django.db.models.fields.TextField', [], {'blank': 'True'})
},
'idtracker.chairshistory': {
'Meta': {'db_table': "'chairs_history'"},
'chair_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.Role']"}),
'end_year': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"}),
'present_chair': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'start_year': ('django.db.models.fields.IntegerField', [], {})
},
'idtracker.documentcomment': {
'Meta': {'db_table': "'document_comments'"},
'ballot': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'comment_text': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'created_by': ('BrokenForeignKey', ["orm['idtracker.IESGLogin']"], {'null': 'True', 'db_column': "'created_by'", 'null_values': '(0,999)'}),
'date': ('django.db.models.fields.DateField', [], {'default': 'datetime.date.today', 'db_column': "'comment_date'"}),
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IDInternal']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'origin_state': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments_coming_from_state'", 'null': 'True', 'db_column': "'origin_state'", 'to': "orm['idtracker.IDState']"}),
'public_flag': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'result_state': ('BrokenForeignKey', ["orm['idtracker.IDState']"], {'related_name': '"comments_leading_to_state"', 'null': 'True', 'db_column': "'result_state'", 'null_values': '(0,99)'}),
'rfc_flag': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'time': ('django.db.models.fields.CharField', [], {'default': "'05:10:39'", 'max_length': '20', 'db_column': "'comment_time'"}),
'version': ('django.db.models.fields.CharField', [], {'max_length': '3', 'blank': 'True'})
},
'idtracker.emailaddress': {
'Meta': {'db_table': "'email_addresses'"},
'address': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_column': "'email_address'"}),
'comment': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'db_column': "'email_comment'", 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person_or_org': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"}),
'priority': ('django.db.models.fields.IntegerField', [], {'db_column': "'email_priority'"}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '4', 'db_column': "'email_type'"})
},
'idtracker.goalmilestone': {
'Meta': {'db_table': "'goals_milestones'"},
'description': ('django.db.models.fields.TextField', [], {}),
'done': ('django.db.models.fields.CharField', [], {'max_length': '4', 'blank': 'True'}),
'done_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'expected_due_date': ('django.db.models.fields.DateField', [], {}),
'gm_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'group_acronym': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IETFWG']"}),
'last_modified_date': ('django.db.models.fields.DateField', [], {})
},
'idtracker.idauthor': {
'Meta': {'db_table': "'id_authors'"},
'author_order': ('django.db.models.fields.IntegerField', [], {}),
'document': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'authors'", 'db_column': "'id_document_tag'", 'to': "orm['idtracker.InternetDraft']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"})
},
'idtracker.idintendedstatus': {
'Meta': {'db_table': "'id_intended_status'"},
'intended_status': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'status_value'"}),
'intended_status_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'idtracker.idinternal': {
'Meta': {'db_table': "'id_internal'"},
'agenda': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'approved_in_minute': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'area_acronym': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.Area']"}),
'assigned_to': ('django.db.models.fields.CharField', [], {'max_length': '25', 'blank': 'True'}),
'ballot': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'drafts'", 'db_column': "'ballot_id'", 'to': "orm['idtracker.BallotInfo']"}),
'cur_state': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'docs'", 'db_column': "'cur_state'", 'to': "orm['idtracker.IDState']"}),
'cur_sub_state': ('BrokenForeignKey', ["orm['idtracker.IDSubState']"], {'related_name': "'docs'", 'null': 'True', 'null_values': '(0,-1)', 'blank': 'True'}),
'dnp': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'dnp_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'draft': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.InternetDraft']", 'unique': 'True', 'primary_key': 'True', 'db_column': "'id_document_tag'"}),
'email_display': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'event_date': ('django.db.models.fields.DateField', [], {'null': 'True'}),
'group_flag': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'}),
'job_owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'documents'", 'db_column': "'job_owner'", 'to': "orm['idtracker.IESGLogin']"}),
'mark_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'marked'", 'db_column': "'mark_by'", 'to': "orm['idtracker.IESGLogin']"}),
'noproblem': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'prev_state': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'docs_prev'", 'db_column': "'prev_state'", 'to': "orm['idtracker.IDState']"}),
'prev_sub_state': ('BrokenForeignKey', ["orm['idtracker.IDSubState']"], {'related_name': "'docs_prev'", 'null': 'True', 'null_values': '(0,-1)', 'blank': 'True'}),
'primary_flag': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'resurrect_requested_by': ('BrokenForeignKey', ["orm['idtracker.IESGLogin']"], {'related_name': "'docsresurrected'", 'null': 'True', 'db_column': "'resurrect_requested_by'", 'blank': 'True'}),
'returning_item': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'rfc_flag': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'state_change_notice_to': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'status_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'telechat_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'token_email': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'token_name': ('django.db.models.fields.CharField', [], {'max_length': '25', 'blank': 'True'}),
'via_rfc_editor': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
},
'idtracker.idnextstate': {
'Meta': {'db_table': "'ref_next_states_new'"},
'condition': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'cur_state': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nextstate'", 'to': "orm['idtracker.IDState']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'next_state': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'prevstate'", 'to': "orm['idtracker.IDState']"})
},
'idtracker.idstate': {
'Meta': {'db_table': "'ref_doc_states_new'"},
'description': ('django.db.models.fields.TextField', [], {'db_column': "'document_desc'", 'blank': 'True'}),
'document_state_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'equiv_group_flag': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'state': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_column': "'document_state_val'"})
},
'idtracker.idstatus': {
'Meta': {'db_table': "'id_status'"},
'status': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'status_value'"}),
'status_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'idtracker.idsubstate': {
'Meta': {'db_table': "'sub_state'"},
'description': ('django.db.models.fields.TextField', [], {'db_column': "'sub_state_desc'", 'blank': 'True'}),
'sub_state': ('django.db.models.fields.CharField', [], {'max_length': '55', 'db_column': "'sub_state_val'"}),
'sub_state_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'idtracker.iesgcomment': {
'Meta': {'unique_together': "(('ballot', 'ad'),)", 'db_table': "'ballots_comment'"},
'active': ('django.db.models.fields.IntegerField', [], {}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IESGLogin']"}),
'ballot': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['idtracker.BallotInfo']"}),
'date': ('django.db.models.fields.DateField', [], {'db_column': "'comment_date'"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'revision': ('django.db.models.fields.CharField', [], {'max_length': '2'}),
'text': ('django.db.models.fields.TextField', [], {'db_column': "'comment_text'", 'blank': 'True'})
},
'idtracker.iesgdiscuss': {
'Meta': {'unique_together': "(('ballot', 'ad'),)", 'db_table': "'ballots_discuss'"},
'active': ('django.db.models.fields.IntegerField', [], {}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IESGLogin']"}),
'ballot': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'discusses'", 'to': "orm['idtracker.BallotInfo']"}),
'date': ('django.db.models.fields.DateField', [], {'db_column': "'discuss_date'"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'revision': ('django.db.models.fields.CharField', [], {'max_length': '2'}),
'text': ('django.db.models.fields.TextField', [], {'db_column': "'discuss_text'", 'blank': 'True'})
},
'idtracker.iesglogin': {
'Meta': {'db_table': "'iesg_login'"},
'default_search': ('django.db.models.fields.NullBooleanField', [], {'null': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '25', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '25', 'blank': 'True'}),
'login_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '25'}),
'person': ('BrokenForeignKey', ["orm['idtracker.PersonOrOrgInfo']"], {'unique': 'True', 'null': 'True', 'db_column': "'person_or_org_tag'", 'null_values': '(0,888888)'}),
'pgp_id': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}),
'user_level': ('django.db.models.fields.IntegerField', [], {})
},
'idtracker.ietfwg': {
'Meta': {'db_table': "'groups_ietf'"},
'area_director': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.AreaDirector']", 'null': 'True'}),
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'concluded_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'dormant_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'email_address': ('django.db.models.fields.CharField', [], {'max_length': '60', 'blank': 'True'}),
'email_archive': ('django.db.models.fields.CharField', [], {'max_length': '95', 'blank': 'True'}),
'email_keyword': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'email_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '120', 'blank': 'True'}),
'group_acronym': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['idtracker.Acronym']", 'unique': 'True', 'primary_key': 'True'}),
'group_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.WGType']"}),
'last_modified_date': ('django.db.models.fields.DateField', [], {}),
'meeting_scheduled': ('django.db.models.fields.CharField', [], {'max_length': '3', 'blank': 'True'}),
'meeting_scheduled_old': ('django.db.models.fields.CharField', [], {'max_length': '3', 'blank': 'True'}),
'proposed_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'start_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.WGStatus']"})
},
'idtracker.internetdraft': {
'Meta': {'db_table': "'internet_drafts'"},
'abstract': ('django.db.models.fields.TextField', [], {}),
'b_approve_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'b_discussion_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'b_sent_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'comments': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'dunn_sent_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'expiration_date': ('django.db.models.fields.DateField', [], {'null': 'True'}),
'expired_tombstone': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'extension_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'file_type': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'filename': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.Acronym']", 'db_column': "'group_acronym_id'"}),
'id_document_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'id_document_tag': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'intended_status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IDIntendedStatus']"}),
'last_modified_date': ('django.db.models.fields.DateField', [], {}),
'lc_changes': ('django.db.models.fields.CharField', [], {'max_length': '3', 'null': 'True'}),
'lc_expiration_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'lc_sent_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'local_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'replaced_by': ('BrokenForeignKey', ["orm['idtracker.InternetDraft']"], {'related_name': "'replaces_set'", 'null': 'True', 'db_column': "'replaced_by'", 'blank': 'True'}),
'review_by_rfc_editor': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'revision': ('django.db.models.fields.CharField', [], {'max_length': '2'}),
'revision_date': ('django.db.models.fields.DateField', [], {}),
'rfc_number': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']"}),
'start_date': ('django.db.models.fields.DateField', [], {}),
'status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IDStatus']"}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_column': "'id_document_name'"}),
'txt_page_count': ('django.db.models.fields.IntegerField', [], {}),
'wgreturn_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'})
},
'idtracker.irtf': {
'Meta': {'db_table': "'irtf'"},
'acronym': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'irtf_acronym'", 'blank': 'True'}),
'charter_text': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'irtf_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'meeting_scheduled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_column': "'irtf_name'", 'blank': 'True'})
},
'idtracker.irtfchair': {
'Meta': {'db_table': "'irtf_chairs'"},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'irtf': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IRTF']"}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"})
},
'idtracker.personororginfo': {
'Meta': {'db_table': "'person_or_org_info'"},
'address_type': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
'created_by': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}),
'date_created': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
'date_modified': ('django.db.models.fields.DateField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'first_name_key': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'last_name_key': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'middle_initial': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
'middle_initial_key': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
'modified_by': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}),
'name_prefix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
'name_suffix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
'person_or_org_tag': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'record_type': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'})
},
'idtracker.phonenumber': {
'Meta': {'db_table': "'phone_numbers'"},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person_or_org': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"}),
'phone_comment': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'phone_number': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'phone_priority': ('django.db.models.fields.IntegerField', [], {}),
'phone_type': ('django.db.models.fields.CharField', [], {'max_length': '3'})
},
'idtracker.position': {
'Meta': {'unique_together': "(('ballot', 'ad'),)", 'db_table': "'ballots'"},
'abstain': ('django.db.models.fields.IntegerField', [], {}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IESGLogin']"}),
'approve': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'ballot': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'positions'", 'to': "orm['idtracker.BallotInfo']"}),
'discuss': ('django.db.models.fields.IntegerField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'noobj': ('django.db.models.fields.IntegerField', [], {'db_column': "'no_col'"}),
'recuse': ('django.db.models.fields.IntegerField', [], {}),
'yes': ('django.db.models.fields.IntegerField', [], {'db_column': "'yes_col'"})
},
'idtracker.postaladdress': {
'Meta': {'db_table': "'postal_addresses'"},
'address_priority': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'address_type': ('django.db.models.fields.CharField', [], {'max_length': '4'}),
'aff_company_key': ('django.db.models.fields.CharField', [], {'max_length': '70', 'blank': 'True'}),
'affiliated_company': ('django.db.models.fields.CharField', [], {'max_length': '70', 'blank': 'True'}),
'city': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'country': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'department': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'mail_stop': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'person_or_org': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"}),
'person_title': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'postal_code': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'staddr1': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
'staddr2': ('django.db.models.fields.CharField', [], {'max_length': '40', 'blank': 'True'}),
'state_or_prov': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'})
},
'idtracker.rfc': {
'Meta': {'db_table': "'rfcs'"},
'area_acronym': ('django.db.models.fields.CharField', [], {'max_length': '8', 'blank': 'True'}),
'b_approve_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'b_sent_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'draft_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'fyi_number': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'group_acronym': ('django.db.models.fields.CharField', [], {'max_length': '8', 'blank': 'True'}),
'historic_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'intended_status': ('django.db.models.fields.related.ForeignKey', [], {'default': '5', 'to': "orm['idtracker.RfcIntendedStatus']", 'db_column': "'intended_status_id'"}),
'last_modified_date': ('django.db.models.fields.DateField', [], {}),
'lc_expiration_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'lc_sent_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'online_version': ('django.db.models.fields.CharField', [], {'default': "'YES'", 'max_length': '3'}),
'proposed_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'rfc_name_key': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
'rfc_number': ('django.db.models.fields.IntegerField', [], {'primary_key': 'True'}),
'rfc_published_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'standard_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.RfcStatus']", 'db_column': "'status_id'"}),
'std_number': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '200', 'db_column': "'rfc_name'"}),
'txt_page_count': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
},
'idtracker.rfcauthor': {
'Meta': {'db_table': "'rfc_authors'"},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"}),
'rfc': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'authors'", 'db_column': "'rfc_number'", 'to': "orm['idtracker.Rfc']"})
},
'idtracker.rfcintendedstatus': {
'Meta': {'db_table': "'rfc_intend_status'"},
'intended_status_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'status': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'status_value'"})
},
'idtracker.rfcobsolete': {
'Meta': {'db_table': "'rfcs_obsolete'"},
'action': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'rfc': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'updates_or_obsoletes'", 'db_column': "'rfc_number'", 'to': "orm['idtracker.Rfc']"}),
'rfc_acted_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'updated_or_obsoleted_by'", 'db_column': "'rfc_acted_on'", 'to': "orm['idtracker.Rfc']"})
},
'idtracker.rfcstatus': {
'Meta': {'db_table': "'rfc_status'"},
'status': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'status_value'"}),
'status_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'idtracker.role': {
'Meta': {'db_table': "'chairs'"},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"}),
'role_name': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'chair_name'"})
},
'idtracker.wgchair': {
'Meta': {'db_table': "'g_chairs'"},
'group_acronym': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IETFWG']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"})
},
'idtracker.wgeditor': {
'Meta': {'db_table': "'g_editors'"},
'group_acronym': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IETFWG']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'unique': 'True', 'db_column': "'person_or_org_tag'"})
},
'idtracker.wgsecretary': {
'Meta': {'db_table': "'g_secretaries'"},
'group_acronym': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IETFWG']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"})
},
'idtracker.wgstatus': {
'Meta': {'db_table': "'g_status'"},
'status': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'status_value'"}),
'status_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'idtracker.wgtechadvisor': {
'Meta': {'db_table': "'g_tech_advisors'"},
'group_acronym': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IETFWG']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"})
},
'idtracker.wgtype': {
'Meta': {'db_table': "'g_type'"},
'group_type_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'group_type'"})
}
}
complete_apps = ['idtracker']

View file

@ -1,439 +0,0 @@
from south.db import db
from django.db import models
from ietf.idtracker.models import *
class Migration:
def forwards(self, orm):
# Changing field 'InternetDraft.shepherd'
# (to signature: django.db.models.fields.related.ForeignKey(to=orm['idtracker.PersonOrOrgInfo'], null=True, blank=True))
db.alter_column('internet_drafts', 'shepherd_id', orm['idtracker.internetdraft:shepherd'])
def backwards(self, orm):
# Changing field 'InternetDraft.shepherd'
# (to signature: django.db.models.fields.related.ForeignKey(to=orm['idtracker.PersonOrOrgInfo']))
db.alter_column('internet_drafts', 'shepherd_id', orm['idtracker.internetdraft:shepherd'])
models = {
'idtracker.acronym': {
'Meta': {'db_table': "'acronym'"},
'acronym': ('django.db.models.fields.CharField', [], {'max_length': '12'}),
'acronym_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name_key': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'idtracker.area': {
'Meta': {'db_table': "'areas'"},
'area_acronym': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['idtracker.Acronym']", 'unique': 'True', 'primary_key': 'True'}),
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'concluded_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'extra_email_addresses': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'last_modified_date': ('django.db.models.fields.DateField', [], {'auto_now': 'True', 'blank': 'True'}),
'start_date': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.AreaStatus']"})
},
'idtracker.areadirector': {
'Meta': {'db_table': "'area_directors'"},
'area': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.Area']", 'null': 'True', 'db_column': "'area_acronym_id'"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"})
},
'idtracker.areagroup': {
'Meta': {'db_table': "'area_group'"},
'area': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'areagroup'", 'db_column': "'area_acronym_id'", 'to': "orm['idtracker.Area']"}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IETFWG']", 'unique': 'True', 'db_column': "'group_acronym_id'"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'idtracker.areastatus': {
'Meta': {'db_table': "'area_status'"},
'status': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'status_value'"}),
'status_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'idtracker.areawgurl': {
'Meta': {'db_table': "'wg_www_pages'"},
'description': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True', 'db_column': "'area_ID'"}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_column': "'area_Name'"}),
'url': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'idtracker.ballotinfo': {
'Meta': {'db_table': "'ballot_info'"},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'an_sent': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'an_sent_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ansent'", 'null': 'True', 'db_column': "'an_sent_by'", 'to': "orm['idtracker.IESGLogin']"}),
'an_sent_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'approval_text': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'ballot': ('django.db.models.fields.AutoField', [], {'primary_key': 'True', 'db_column': "'ballot_id'"}),
'ballot_issued': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'ballot_writeup': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'defer': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'defer_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'deferred'", 'null': 'True', 'db_column': "'defer_by'", 'to': "orm['idtracker.IESGLogin']"}),
'defer_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'last_call_text': ('django.db.models.fields.TextField', [], {'blank': 'True'})
},
'idtracker.chairshistory': {
'Meta': {'db_table': "'chairs_history'"},
'chair_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.Role']"}),
'end_year': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"}),
'present_chair': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'start_year': ('django.db.models.fields.IntegerField', [], {})
},
'idtracker.documentcomment': {
'Meta': {'db_table': "'document_comments'"},
'ballot': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'comment_text': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'created_by': ('BrokenForeignKey', ["orm['idtracker.IESGLogin']"], {'null': 'True', 'db_column': "'created_by'", 'null_values': '(0,999)'}),
'date': ('django.db.models.fields.DateField', [], {'default': 'datetime.date.today', 'db_column': "'comment_date'"}),
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IDInternal']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'origin_state': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments_coming_from_state'", 'null': 'True', 'db_column': "'origin_state'", 'to': "orm['idtracker.IDState']"}),
'public_flag': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'result_state': ('BrokenForeignKey', ["orm['idtracker.IDState']"], {'related_name': '"comments_leading_to_state"', 'null': 'True', 'db_column': "'result_state'", 'null_values': '(0,99)'}),
'rfc_flag': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'time': ('django.db.models.fields.CharField', [], {'default': "'08:36:20'", 'max_length': '20', 'db_column': "'comment_time'"}),
'version': ('django.db.models.fields.CharField', [], {'max_length': '3', 'blank': 'True'})
},
'idtracker.emailaddress': {
'Meta': {'db_table': "'email_addresses'"},
'address': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_column': "'email_address'"}),
'comment': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'db_column': "'email_comment'", 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person_or_org': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"}),
'priority': ('django.db.models.fields.IntegerField', [], {'db_column': "'email_priority'"}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '4', 'db_column': "'email_type'"})
},
'idtracker.goalmilestone': {
'Meta': {'db_table': "'goals_milestones'"},
'description': ('django.db.models.fields.TextField', [], {}),
'done': ('django.db.models.fields.CharField', [], {'max_length': '4', 'blank': 'True'}),
'done_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'expected_due_date': ('django.db.models.fields.DateField', [], {}),
'gm_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'group_acronym': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IETFWG']"}),
'last_modified_date': ('django.db.models.fields.DateField', [], {})
},
'idtracker.idauthor': {
'Meta': {'db_table': "'id_authors'"},
'author_order': ('django.db.models.fields.IntegerField', [], {}),
'document': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'authors'", 'db_column': "'id_document_tag'", 'to': "orm['idtracker.InternetDraft']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"})
},
'idtracker.idintendedstatus': {
'Meta': {'db_table': "'id_intended_status'"},
'intended_status': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'status_value'"}),
'intended_status_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'idtracker.idinternal': {
'Meta': {'db_table': "'id_internal'"},
'agenda': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'approved_in_minute': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'area_acronym': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.Area']"}),
'assigned_to': ('django.db.models.fields.CharField', [], {'max_length': '25', 'blank': 'True'}),
'ballot': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'drafts'", 'db_column': "'ballot_id'", 'to': "orm['idtracker.BallotInfo']"}),
'cur_state': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'docs'", 'db_column': "'cur_state'", 'to': "orm['idtracker.IDState']"}),
'cur_sub_state': ('BrokenForeignKey', ["orm['idtracker.IDSubState']"], {'related_name': "'docs'", 'null': 'True', 'null_values': '(0,-1)', 'blank': 'True'}),
'dnp': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'dnp_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'draft': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.InternetDraft']", 'unique': 'True', 'primary_key': 'True', 'db_column': "'id_document_tag'"}),
'email_display': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'event_date': ('django.db.models.fields.DateField', [], {'null': 'True'}),
'group_flag': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'}),
'job_owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'documents'", 'db_column': "'job_owner'", 'to': "orm['idtracker.IESGLogin']"}),
'mark_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'marked'", 'db_column': "'mark_by'", 'to': "orm['idtracker.IESGLogin']"}),
'noproblem': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'prev_state': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'docs_prev'", 'db_column': "'prev_state'", 'to': "orm['idtracker.IDState']"}),
'prev_sub_state': ('BrokenForeignKey', ["orm['idtracker.IDSubState']"], {'related_name': "'docs_prev'", 'null': 'True', 'null_values': '(0,-1)', 'blank': 'True'}),
'primary_flag': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'resurrect_requested_by': ('BrokenForeignKey', ["orm['idtracker.IESGLogin']"], {'related_name': "'docsresurrected'", 'null': 'True', 'db_column': "'resurrect_requested_by'", 'blank': 'True'}),
'returning_item': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'rfc_flag': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'state_change_notice_to': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'status_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'telechat_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'token_email': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'token_name': ('django.db.models.fields.CharField', [], {'max_length': '25', 'blank': 'True'}),
'via_rfc_editor': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
},
'idtracker.idnextstate': {
'Meta': {'db_table': "'ref_next_states_new'"},
'condition': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'cur_state': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nextstate'", 'to': "orm['idtracker.IDState']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'next_state': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'prevstate'", 'to': "orm['idtracker.IDState']"})
},
'idtracker.idstate': {
'Meta': {'db_table': "'ref_doc_states_new'"},
'description': ('django.db.models.fields.TextField', [], {'db_column': "'document_desc'", 'blank': 'True'}),
'document_state_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'equiv_group_flag': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'state': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_column': "'document_state_val'"})
},
'idtracker.idstatus': {
'Meta': {'db_table': "'id_status'"},
'status': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'status_value'"}),
'status_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'idtracker.idsubstate': {
'Meta': {'db_table': "'sub_state'"},
'description': ('django.db.models.fields.TextField', [], {'db_column': "'sub_state_desc'", 'blank': 'True'}),
'sub_state': ('django.db.models.fields.CharField', [], {'max_length': '55', 'db_column': "'sub_state_val'"}),
'sub_state_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'idtracker.iesgcomment': {
'Meta': {'unique_together': "(('ballot', 'ad'),)", 'db_table': "'ballots_comment'"},
'active': ('django.db.models.fields.IntegerField', [], {}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IESGLogin']"}),
'ballot': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['idtracker.BallotInfo']"}),
'date': ('django.db.models.fields.DateField', [], {'db_column': "'comment_date'"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'revision': ('django.db.models.fields.CharField', [], {'max_length': '2'}),
'text': ('django.db.models.fields.TextField', [], {'db_column': "'comment_text'", 'blank': 'True'})
},
'idtracker.iesgdiscuss': {
'Meta': {'unique_together': "(('ballot', 'ad'),)", 'db_table': "'ballots_discuss'"},
'active': ('django.db.models.fields.IntegerField', [], {}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IESGLogin']"}),
'ballot': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'discusses'", 'to': "orm['idtracker.BallotInfo']"}),
'date': ('django.db.models.fields.DateField', [], {'db_column': "'discuss_date'"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'revision': ('django.db.models.fields.CharField', [], {'max_length': '2'}),
'text': ('django.db.models.fields.TextField', [], {'db_column': "'discuss_text'", 'blank': 'True'})
},
'idtracker.iesglogin': {
'Meta': {'db_table': "'iesg_login'"},
'default_search': ('django.db.models.fields.NullBooleanField', [], {'null': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '25', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '25', 'blank': 'True'}),
'login_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '25'}),
'person': ('BrokenForeignKey', ["orm['idtracker.PersonOrOrgInfo']"], {'unique': 'True', 'null': 'True', 'db_column': "'person_or_org_tag'", 'null_values': '(0,888888)'}),
'pgp_id': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}),
'user_level': ('django.db.models.fields.IntegerField', [], {})
},
'idtracker.ietfwg': {
'Meta': {'db_table': "'groups_ietf'"},
'area_director': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.AreaDirector']", 'null': 'True'}),
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'concluded_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'dormant_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'email_address': ('django.db.models.fields.CharField', [], {'max_length': '60', 'blank': 'True'}),
'email_archive': ('django.db.models.fields.CharField', [], {'max_length': '95', 'blank': 'True'}),
'email_keyword': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'email_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '120', 'blank': 'True'}),
'group_acronym': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['idtracker.Acronym']", 'unique': 'True', 'primary_key': 'True'}),
'group_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.WGType']"}),
'last_modified_date': ('django.db.models.fields.DateField', [], {}),
'meeting_scheduled': ('django.db.models.fields.CharField', [], {'max_length': '3', 'blank': 'True'}),
'meeting_scheduled_old': ('django.db.models.fields.CharField', [], {'max_length': '3', 'blank': 'True'}),
'proposed_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'start_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.WGStatus']"})
},
'idtracker.internetdraft': {
'Meta': {'db_table': "'internet_drafts'"},
'abstract': ('django.db.models.fields.TextField', [], {}),
'b_approve_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'b_discussion_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'b_sent_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'comments': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'dunn_sent_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'expiration_date': ('django.db.models.fields.DateField', [], {'null': 'True'}),
'expired_tombstone': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'extension_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'file_type': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'filename': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.Acronym']", 'db_column': "'group_acronym_id'"}),
'id_document_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'id_document_tag': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'intended_status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IDIntendedStatus']"}),
'last_modified_date': ('django.db.models.fields.DateField', [], {}),
'lc_changes': ('django.db.models.fields.CharField', [], {'max_length': '3', 'null': 'True'}),
'lc_expiration_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'lc_sent_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'local_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'replaced_by': ('BrokenForeignKey', ["orm['idtracker.InternetDraft']"], {'related_name': "'replaces_set'", 'null': 'True', 'db_column': "'replaced_by'", 'blank': 'True'}),
'review_by_rfc_editor': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'revision': ('django.db.models.fields.CharField', [], {'max_length': '2'}),
'revision_date': ('django.db.models.fields.DateField', [], {}),
'rfc_number': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'null': 'True', 'blank': 'True'}),
'start_date': ('django.db.models.fields.DateField', [], {}),
'status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IDStatus']"}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_column': "'id_document_name'"}),
'txt_page_count': ('django.db.models.fields.IntegerField', [], {}),
'wgreturn_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'})
},
'idtracker.irtf': {
'Meta': {'db_table': "'irtf'"},
'acronym': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'irtf_acronym'", 'blank': 'True'}),
'charter_text': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'irtf_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'meeting_scheduled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_column': "'irtf_name'", 'blank': 'True'})
},
'idtracker.irtfchair': {
'Meta': {'db_table': "'irtf_chairs'"},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'irtf': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IRTF']"}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"})
},
'idtracker.personororginfo': {
'Meta': {'db_table': "'person_or_org_info'"},
'address_type': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
'created_by': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}),
'date_created': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
'date_modified': ('django.db.models.fields.DateField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'first_name_key': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'last_name_key': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'middle_initial': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
'middle_initial_key': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
'modified_by': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}),
'name_prefix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
'name_suffix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
'person_or_org_tag': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'record_type': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'})
},
'idtracker.phonenumber': {
'Meta': {'db_table': "'phone_numbers'"},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person_or_org': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"}),
'phone_comment': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'phone_number': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'phone_priority': ('django.db.models.fields.IntegerField', [], {}),
'phone_type': ('django.db.models.fields.CharField', [], {'max_length': '3'})
},
'idtracker.position': {
'Meta': {'unique_together': "(('ballot', 'ad'),)", 'db_table': "'ballots'"},
'abstain': ('django.db.models.fields.IntegerField', [], {}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IESGLogin']"}),
'approve': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'ballot': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'positions'", 'to': "orm['idtracker.BallotInfo']"}),
'discuss': ('django.db.models.fields.IntegerField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'noobj': ('django.db.models.fields.IntegerField', [], {'db_column': "'no_col'"}),
'recuse': ('django.db.models.fields.IntegerField', [], {}),
'yes': ('django.db.models.fields.IntegerField', [], {'db_column': "'yes_col'"})
},
'idtracker.postaladdress': {
'Meta': {'db_table': "'postal_addresses'"},
'address_priority': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'address_type': ('django.db.models.fields.CharField', [], {'max_length': '4'}),
'aff_company_key': ('django.db.models.fields.CharField', [], {'max_length': '70', 'blank': 'True'}),
'affiliated_company': ('django.db.models.fields.CharField', [], {'max_length': '70', 'blank': 'True'}),
'city': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'country': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'department': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'mail_stop': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'person_or_org': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"}),
'person_title': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'postal_code': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'staddr1': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
'staddr2': ('django.db.models.fields.CharField', [], {'max_length': '40', 'blank': 'True'}),
'state_or_prov': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'})
},
'idtracker.rfc': {
'Meta': {'db_table': "'rfcs'"},
'area_acronym': ('django.db.models.fields.CharField', [], {'max_length': '8', 'blank': 'True'}),
'b_approve_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'b_sent_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'draft_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'fyi_number': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'group_acronym': ('django.db.models.fields.CharField', [], {'max_length': '8', 'blank': 'True'}),
'historic_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'intended_status': ('django.db.models.fields.related.ForeignKey', [], {'default': '5', 'to': "orm['idtracker.RfcIntendedStatus']", 'db_column': "'intended_status_id'"}),
'last_modified_date': ('django.db.models.fields.DateField', [], {}),
'lc_expiration_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'lc_sent_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'online_version': ('django.db.models.fields.CharField', [], {'default': "'YES'", 'max_length': '3'}),
'proposed_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'rfc_name_key': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
'rfc_number': ('django.db.models.fields.IntegerField', [], {'primary_key': 'True'}),
'rfc_published_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'standard_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.RfcStatus']", 'db_column': "'status_id'"}),
'std_number': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '200', 'db_column': "'rfc_name'"}),
'txt_page_count': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
},
'idtracker.rfcauthor': {
'Meta': {'db_table': "'rfc_authors'"},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"}),
'rfc': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'authors'", 'db_column': "'rfc_number'", 'to': "orm['idtracker.Rfc']"})
},
'idtracker.rfcintendedstatus': {
'Meta': {'db_table': "'rfc_intend_status'"},
'intended_status_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'status': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'status_value'"})
},
'idtracker.rfcobsolete': {
'Meta': {'db_table': "'rfcs_obsolete'"},
'action': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'rfc': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'updates_or_obsoletes'", 'db_column': "'rfc_number'", 'to': "orm['idtracker.Rfc']"}),
'rfc_acted_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'updated_or_obsoleted_by'", 'db_column': "'rfc_acted_on'", 'to': "orm['idtracker.Rfc']"})
},
'idtracker.rfcstatus': {
'Meta': {'db_table': "'rfc_status'"},
'status': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'status_value'"}),
'status_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'idtracker.role': {
'Meta': {'db_table': "'chairs'"},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"}),
'role_name': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'chair_name'"})
},
'idtracker.wgchair': {
'Meta': {'db_table': "'g_chairs'"},
'group_acronym': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IETFWG']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"})
},
'idtracker.wgeditor': {
'Meta': {'db_table': "'g_editors'"},
'group_acronym': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IETFWG']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'unique': 'True', 'db_column': "'person_or_org_tag'"})
},
'idtracker.wgsecretary': {
'Meta': {'db_table': "'g_secretaries'"},
'group_acronym': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IETFWG']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"})
},
'idtracker.wgstatus': {
'Meta': {'db_table': "'g_status'"},
'status': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'status_value'"}),
'status_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'idtracker.wgtechadvisor': {
'Meta': {'db_table': "'g_tech_advisors'"},
'group_acronym': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IETFWG']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"})
},
'idtracker.wgtype': {
'Meta': {'db_table': "'g_type'"},
'group_type_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'group_type'"})
}
}
complete_apps = ['idtracker']

File diff suppressed because it is too large Load diff

View file

@ -1 +0,0 @@
/*.pyc

View file

@ -1,2 +0,0 @@
# Copyright The IETF Trust 2007, All Rights Reserved

View file

@ -5,9 +5,5 @@ class TelechatAgendaItemAdmin(admin.ModelAdmin):
pass
admin.site.register(TelechatAgendaItem, TelechatAgendaItemAdmin)
class WGActionAdmin(admin.ModelAdmin):
pass
admin.site.register(WGAction, WGActionAdmin)
admin.site.register(TelechatDate)

217
ietf/iesg/agenda.py Normal file
View file

@ -0,0 +1,217 @@
# utilities for constructing agendas for IESG telechats
import codecs, re, os, datetime
# FIXME: once we're on Python 2.7, replace with: from collections import OrderedDict
from django.utils.datastructures import SortedDict as OrderedDict
from django.http import Http404
from django.conf import settings
from ietf.iesg.models import TelechatDate, TelechatAgendaItem
from ietf.doc.models import Document, TelechatDocEvent, LastCallDocEvent, ConsensusDocEvent, DocEvent
from ietf.group.models import Group, GroupMilestone
def get_agenda_date(date=None):
if not date:
try:
return TelechatDate.objects.active().order_by('date')[0].date
except IndexError:
return datetime.date.today()
else:
try:
# FIXME: .active()
return TelechatDate.objects.all().get(date=datetime.datetime.strptime(date, "%Y-%m-%d").date()).date
except (ValueError, TelechatDate.DoesNotExist):
raise Http404
def get_doc_section(doc):
if doc.type_id == 'draft':
if doc.intended_std_level_id in ["bcp", "ds", "ps", "std"]:
s = "2"
else:
s = "3"
g = doc.group_acronym()
if g and str(g) != 'none':
s += ".1"
elif s == "3" and doc.stream_id in ("ise","irtf"):
s += ".3"
else:
s += ".2"
if doc.get_state_slug() != "rfc" and doc.get_state_slug('draft-iesg') not in ("lc", "writeupw", "goaheadw", "iesg-eva", "defer"):
s += ".3"
elif doc.returning_item():
s += ".2"
else:
s += ".1"
elif doc.type_id == 'charter':
s = "4"
if doc.group.state_id in ('active', 'dormant'):
s += ".2"
else:
s += ".1"
if doc.get_state_slug() in ('extrev', 'iesgrev'):
s += '.2'
else:
s += '.1'
elif doc.type_id == 'statchg':
protocol_action = False
for relation in doc.relateddocument_set.filter(relationship__slug__in=('tops','tois','tohist','toinf','tobcp','toexp')):
if relation.relationship.slug in ('tops','tois') or relation.target.document.std_level.slug in ('std','ds','ps'):
protocol_action = True
if protocol_action:
s = "2.3"
else:
s = "3.3"
if doc.get_state_slug() not in ("iesgeval", "defer", "appr-pr", "appr-pend", "appr-sent"):
s += ".3"
elif doc.returning_item():
s += ".2"
else:
s += ".1"
elif doc.type_id == 'conflrev':
if doc.get_state('conflrev').slug not in ('adrev','iesgeval','appr-reqnopub-pend','appr-reqnopub-sent','appr-noprob-pend','appr-noprob-sent','defer'):
s = "3.4.3"
elif doc.returning_item():
s = "3.4.2"
else:
s = "3.4.1"
return s
def agenda_sections():
return OrderedDict([
('1', {'title':"Administrivia"}),
('1.1', {'title':"Roll Call"}),
('1.2', {'title':"Bash the Agenda"}),
('1.3', {'title':"Approval of the Minutes of Past Telechats"}),
('1.4', {'title':"List of Remaining Action Items from Last Telechat"}),
('2', {'title':"Protocol Actions"}),
('2.1', {'title':"WG Submissions"}),
('2.1.1', {'title':"New Items", 'docs': []}),
('2.1.2', {'title':"Returning Items", 'docs':[]}),
('2.1.3', {'title':"For Action", 'docs':[]}),
('2.2', {'title':"Individual Submissions"}),
('2.2.1', {'title':"New Items", 'docs':[]}),
('2.2.2', {'title':"Returning Items", 'docs':[]}),
('2.2.3', {'title':"For Action", 'docs':[]}),
('2.3', {'title':"Status Changes"}),
('2.3.1', {'title':"New Items", 'docs':[]}),
('2.3.2', {'title':"Returning Items", 'docs':[]}),
('2.3.3', {'title':"For Action", 'docs':[]}),
('3', {'title':"Document Actions"}),
('3.1', {'title':"WG Submissions"}),
('3.1.1', {'title':"New Items", 'docs':[]}),
('3.1.2', {'title':"Returning Items", 'docs':[]}),
('3.1.3', {'title':"For Action", 'docs':[]}),
('3.2', {'title':"Individual Submissions Via AD"}),
('3.2.1', {'title':"New Items", 'docs':[]}),
('3.2.2', {'title':"Returning Items", 'docs':[]}),
('3.2.3', {'title':"For Action", 'docs':[]}),
('3.3', {'title':"Status Changes"}),
('3.3.1', {'title':"New Items", 'docs':[]}),
('3.3.2', {'title':"Returning Items", 'docs':[]}),
('3.3.3', {'title':"For Action", 'docs':[]}),
('3.4', {'title':"IRTF and Independent Submission Stream Documents"}),
('3.4.1', {'title':"New Items", 'docs':[]}),
('3.4.2', {'title':"Returning Items", 'docs':[]}),
('3.4.3', {'title':"For Action", 'docs':[]}),
('4', {'title':"Working Group Actions"}),
('4.1', {'title':"WG Creation"}),
('4.1.1', {'title':"Proposed for IETF Review", 'docs':[]}),
('4.1.2', {'title':"Proposed for Approval", 'docs':[]}),
('4.2', {'title':"WG Rechartering"}),
('4.2.1', {'title':"Under Evaluation for IETF Review", 'docs':[]}),
('4.2.2', {'title':"Proposed for Approval", 'docs':[]}),
('5', {'title':"IAB News We Can Use"}),
('6', {'title':"Management Issues"}),
('7', {'title':"Working Group News"}),
])
def fill_in_agenda_administrivia(date, sections):
extra_info_files = (
("1.1", "roll_call", settings.IESG_ROLL_CALL_FILE),
("1.3", "minutes", settings.IESG_MINUTES_FILE),
("1.4", "action_items", settings.IESG_TASK_FILE),
)
for s, key, filename in extra_info_files:
try:
with codecs.open(filename, 'r', 'utf-8', 'replace') as f:
t = f.read().strip()
except IOError:
t = u"(Error reading %s)" % filename
sections[s]["text"] = t
def fill_in_agenda_docs(date, sections, matches=None):
if not matches:
matches = Document.objects.filter(docevent__telechatdocevent__telechat_date=date)
matches = matches.select_related("stream", "group").distinct()
docs = []
for doc in matches:
if doc.latest_event(TelechatDocEvent, type="scheduled_for_telechat").telechat_date != date:
continue
e = doc.latest_event(type="started_iesg_process")
doc.balloting_started = e.time if e else datetime.datetime.min
if doc.type_id == "draft":
s = doc.get_state("draft-iana-review")
if s: # and s.slug in ("not-ok", "changed", "need-rev"):
doc.iana_review_state = str(s)
if doc.get_state_slug("draft-iesg") == "lc":
e = doc.latest_event(LastCallDocEvent, type="sent_last_call")
if e:
doc.lastcall_expires = e.expires
if doc.stream_id in ("ietf", "irtf", "iab"):
doc.consensus = "Unknown"
e = doc.latest_event(ConsensusDocEvent, type="changed_consensus")
if e:
doc.consensus = "Yes" if e.consensus else "No"
elif doc.type_id == "conflrev":
doc.conflictdoc = doc.relateddocument_set.get(relationship__slug='conflrev').target.document
elif doc.type_id == "charter":
#if doc.group.state_id not in ("proposed", "active"):
# continue
doc.group.txt_link = settings.CHARTER_TXT_URL + "%s-%s.txt" % (doc.canonical_name(), doc.rev)
num = get_doc_section(doc)
if num: # and num in sections
sections[num]["docs"].append(doc)
# prune empty "For action" sections
empty_for_action = [num for num, section in sections.iteritems()
if section["title"] == "For Action" and not section["docs"]]
for num in empty_for_action:
del sections[num]
# Be careful to keep this the same as what's used in agenda_documents
for s in sections.itervalues():
if "docs" in s:
s["docs"].sort(key=lambda d: d.balloting_started)
def fill_in_agenda_management_issues(date, sections):
s = "6.%s"
for i, item in enumerate(TelechatAgendaItem.objects.filter(type=3).order_by('id'), start=1):
sections[s % i] = { "title": item.title, "text": item.text }
def agenda_data(date=None):
"""Return a dict with the different IESG telechat agenda components."""
date = get_agenda_date(date)
sections = agenda_sections()
fill_in_agenda_administrivia(date, sections)
fill_in_agenda_docs(date, sections)
fill_in_agenda_management_issues(date, sections)
return { 'date': date.isoformat(), 'sections': sections }

View file

@ -8,27 +8,31 @@ import datetime
class IESGAgenda(Feed):
title = "Documents on Future IESG Telechat Agendas"
link = "http://datatracker.ietf.org/iesg/agenda/"
link = settings.IDTRACKER_BASE_URL + "/iesg/agenda/"
feed_type = Atom1Feed
def items(self):
from ietf.doc.models import TelechatDocEvent
drafts = Document.objects.filter(docevent__telechatdocevent__telechat_date__gte=datetime.date.min).distinct()
for d in drafts:
docs = Document.objects.filter(docevent__telechatdocevent__telechat_date__gte=datetime.date.today()).distinct()
for d in docs:
d.latest_telechat_event = d.latest_event(TelechatDocEvent, type="scheduled_for_telechat")
drafts = [d for d in drafts if d.latest_telechat_event.telechat_date]
drafts.sort(key=lambda d: d.latest_telechat_event.telechat_date)
return drafts
docs = [d for d in docs if d.latest_telechat_event.telechat_date]
docs.sort(key=lambda d: d.latest_telechat_event.telechat_date, reverse=True)
return docs
def item_categories(self, doc):
return [ str(doc.telechat_date) ]
def item_categories(self, item):
return [ str(item.telechat_date) ]
def item_pubdate(self, item):
return item.latest_telechat_event.time
def item_pubdate(self, doc):
return doc.latest_telechat_event.time
def item_author_name(self, item):
return str( item.ad ) if item.ad else "None"
def item_author_name(self, doc):
return doc.ad.plain_name() if doc.ad else "None"
def item_author_email(self, item):
return str( item.ad.role_email("ad") ) if item.ad else ""
def item_author_email(self, doc):
if not doc.ad:
return ""
e = doc.ad.role_email("ad")
if not e:
return ""
return e.address

View file

@ -1,143 +0,0 @@
Sieve Mail Filtering Language (sieve)
-------------------------------------
Current Status: Active
Last updated: 2010-05-07
Chairs:
Cyrus Daboo <cyrus@daboo.name>
Aaron Stone <aaron@serendipity.cx>
Applications Area Directors:
Alexey Melnikov <alexey.melnikov@isode.com>
Peter Saint-Andre <stpeter@stpeter.im>
Applications Area Advisor:
Alexey Melnikov <alexey.melnikov@isode.com>
Mailing Lists:
General Discussion: sieve@ietf.org
To Subscribe: sieve-request@ietf.org
Archive:
http://www.ietf.org/mail-archive/web/sieve/current/maillist.html
Description of Working Group:
The SIEVE email filtering language is specified in RFC 5228, together
with a number of extensions.
The SIEVE working group is being re-chartered to:
(1) Finish work on existing in-progress Working Group documents:
(a) External lists (draft-ietf-sieve-external-lists)
(b) Notify SIP (draft-ietf-sieve-notify-sip-message)
(c) RegEx (draft-ietf-sieve-regex)
(d) Include/multi-script (draft-ietf-sieve-include)
(e) Sieve in IMAP (draft-ietf-sieve-imap-sieve)
(2) Finalize and publish the following SIEVE extensions as proposed
standards:
(a) General Auto-reply (draft-george-sieve-autoreply)
(b) Notify presence (draft-george-sieve-notify-presence)
(c) Vacation time (draft-george-sieve-vacation-time)
(d) Convert messages (draft-melnikov-sieve-convert)
Additional drafts may be added to this list, but only via a charter
revision. There must also be demonstrable willingness in the SIEVE
development community to actually implement a given extension before it
can be added to this charter.
(3) Work on a specification for iCalendar and vCard extraction, and
cooperate with the VCARDDAV WG for address book tests in Sieve.
(4) Work on a specification to describe how EAI/IDN issues should be
handled in SIEVE.
(5) Work on a "Benefits of SIEVE" guide for client and server vendors
that:
(a) Describes the SIEVE protocol and its suite of extensions.
(b) Explains the benefits of server-side filtering in practical terms.
(c) Shows how client-side filtering can be migrated to SIEVE.
(6) Produce one or more informational RFCs containing a set of test
scripts and test email messages that are to be filtered by the scripts,
and the expected results of that filtering. This will serve as the basis
of a interoperability test suite to help determine the suitability of
moving the base specification and selected extensions to Draft status.
Goals and Milestones:
Done - Submit revised variables draft.
Done - Submit revised vacation draft.
Done - WG last call for variables draft.
Done - Initial submission of RFC 3028bis.
Done - WG last call for RFC 3028bis.
Done - Initial submission of revised relational draft.
Done - Initial submission of revised subaddress draft.
Done - Initial submission of revised spamtest/virustest draft.
Done - Submit revised editheader draft.
Done - Submit revised imapflags draft.
Done - WG last call of revised subaddress draft.
Done - Submit revised body test draft.
Done - Submit revised reject before delivery draft.
Done - WG last call for editheader draft.
Done - WG last call for body test draft.
Done - WG last call for refuse draft
Done - WG last call of revised spamtest draft
Done - Submit variables draft to IESG
Done - Submit revised loop draft
Done - Submit revised notification action draft
Done - WG last call of revised relational draft
Done - WG last call for imap-flags draft
Done - WG last call for vacation draft
Done - WG last call of revised subaddress draft
Done - Submit revised relational draft to IESG
Done - Submit vacation draft to IESG
Done - Submit revised subaddress draft to IESG
Done - Submit imapflags draft to IESG
Done - Submit revised spamtest draft to IESG
Done - Submit 3028bis to IESG
Done - Submit editheader draft to IESG
Done - Submit body test draft to IESG
Done - WG last call for notification action draft
Done - Submit notification action draft to IESG
Done - Submit refuse-reject to IESG
Done - Submit notify-mailto to IESG
Done - Submit mime-loops to IESG
Done - WGLC iHave
Done - WGLC Notary
Done - Submit iHave to IESG
Done - Submit Notary to IESG
Done - WGLC sieve-in-xml
Done - Submit sieve-in-xml to IESG
Done - WGLC ManageSIEVE
Done - Submit ManageSIEVE to IESG
Done - WGLC Notify-sip
Done - WGLC Metadata
Done - Submit Metadata to IESG
Done - Publish refuse/reject - RFC 5429
Done - Publish notify base spec - RFC 5435
Done - Publish notify mailto extension - RFC 5436
Done - Publish notify xmpp extension - RFC 5437
Done - Publish ihave - RFC 5463
Done - Publish meta-data - RFC 5490
Done - Publish mime loops - RFC 5703
Done - Publish Sieve in XML - RFC 5784
Done - Revised RegEx draft
Apr 2010 - Revised Include/multi-script draft
Apr 2010 - WGLC external-lists
May 2010 - WGLC Include/multi-script
May 2010 - Submit external-lists to IESG
Jun 2010 - Submit Include/multi-script to IESG
Jun 2010 - WGLC Notify-SIP
Jul 2010 - Initial eai-issues draft
Jul 2010 - Submit Notify-SIP to IESG
Aug 2010 - WGLC RegEx
Aug 2010 - Initial test-scripts draft
Aug 2010 - Initial benefits draft
Sep 2010 - Submit RegEx to IESG
Oct 2010 - WGLC eai-issues
Nov 2010 - Submit eai-issues to IESG
Nov 2010 - WGLC benefits
Jan 2011 - Submit benefits to IESG
Mar 2011 - WGLC test-scripts
Apr 2011 - Submit test-scripts to IESG

View file

@ -32,53 +32,10 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from django.db import models
from django.conf import settings
from ietf.idtracker.models import Acronym
import datetime
# This table is not used by any code right now, and according to Glen,
# probably not currently (Aug 2009) maintained by the secretariat.
#class TelechatMinutes(models.Model):
# telechat_date = models.DateField(null=True, blank=True)
# telechat_minute = models.TextField(blank=True)
# exported = models.IntegerField(null=True, blank=True)
# def get_absolute_url(self):
# return "/iesg/telechat/%d/" % self.id
# def __str__(self):
# return "IESG Telechat Minutes for %s" % self.telechat_date
# class Meta:
# db_table = 'telechat_minutes'
# verbose_name = "Telechat Minute Text"
# verbose_name_plural = "Telechat Minutes"
# this model is deprecated
class TelechatDates(models.Model):
date1 = models.DateField(primary_key=True, null=True, blank=True)
date2 = models.DateField(null=True, blank=True)
date3 = models.DateField(null=True, blank=True)
date4 = models.DateField(null=True, blank=True)
def dates(self):
l = []
if self.date1:
l.append(self.date1)
if self.date2:
l.append(self.date2)
if self.date3:
l.append(self.date3)
if self.date4:
l.append(self.date4)
return l
def save(self):
# date1 isn't really a primary id, so save() doesn't work
raise NotImplemented
def __str__(self):
return " / ".join([str(d) for d in [self.date1,self.date2,self.date3,self.date4]])
class Meta:
db_table = "telechat_dates"
verbose_name = "Next Telechat Date"
from django.db import models
from django.conf import settings
class TelechatAgendaItem(models.Model):
TYPE_CHOICES = (
@ -91,41 +48,10 @@ class TelechatAgendaItem(models.Model):
text = models.TextField(blank=True, db_column='template_text')
type = models.IntegerField(db_column='template_type', choices=TYPE_CHOICES, default=3)
title = models.CharField(max_length=255, db_column='template_title')
#The following fields are apparently not used
#note = models.TextField(null=True,blank=True)
#discussed_status_id = models.IntegerField(null=True, blank=True)
#decision = models.TextField(null=True,blank=True)
def __unicode__(self):
type_name = self.TYPE_CHOICES_DICT.get(self.type, str(self.type))
return u'%s: %s' % (type_name, self.title or "")
class Meta:
if not settings.USE_DB_REDESIGN_PROXY_CLASSES:
db_table = 'templates'
class WGAction(models.Model):
CATEGORY_CHOICES = (
(11, "WG Creation::In Internal Review"),
(12, "WG Creation::Proposed for IETF Review"),
(13, "WG Creation::Proposed for Approval"),
(21, "WG Rechartering::In Internal Review"),
(22, "WG Rechartering::Under evaluation for IETF Review"),
(23, "WG Rechartering::Proposed for Approval")
)
# note that with the new schema, Acronym is monkey-patched and is really Group
group_acronym = models.ForeignKey(Acronym, db_column='group_acronym_id', primary_key=True, unique=True)
note = models.TextField(blank=True,null=True)
status_date = models.DateField()
agenda = models.BooleanField("On Agenda")
token_name = models.CharField(max_length=25)
category = models.IntegerField(db_column='pwg_cat_id', choices=CATEGORY_CHOICES, default=11)
telechat_date = models.DateField() #choices = [(x.telechat_date,x.telechat_date) for x in Telechat.objects.all().order_by('-telechat_date')])
def __str__(self):
return str(self.telechat_date)+": "+str(self.group_acronym)
class Meta:
if not settings.USE_DB_REDESIGN_PROXY_CLASSES:
db_table = 'group_internal'
ordering = ['-telechat_date']
verbose_name = "WG Action"
class Telechat(models.Model):
telechat_id = models.IntegerField(primary_key=True)
@ -136,6 +62,7 @@ class Telechat(models.Model):
management_issue = models.TextField(blank=True)
frozen = models.IntegerField(null=True, blank=True)
mi_frozen = models.IntegerField(null=True, blank=True)
class Meta:
db_table = u'telechat'
@ -160,55 +87,3 @@ class TelechatDate(models.Model):
class Meta:
ordering = ['-date']
class TelechatDatesProxyDummy(object):
def all(self):
class Dummy(object):
def __getitem__(self, i):
return self
def get_date(self, index):
if not hasattr(self, "date_cache"):
self.date_cache = TelechatDate.objects.active().order_by("date")
if index < len(self.date_cache):
return self.date_cache[index].date
return None
#date1 = models.DateField(primary_key=True, null=True, blank= True)
@property
def date1(self):
return self.get_date(0)
#date2 = models.DateField(null=True, blank=True)
@property
def date2(self):
return self.get_date(1)
#date3 = models.DateField(null=True, blank=True)
@property
def date3(self):
return self.get_date(2)
#date4 = models.DateField(null=True, blank=True)
@property
def date4(self):
return self.get_date(3)
def dates(self):
l = []
if self.date1:
l.append(self.date1)
if self.date2:
l.append(self.date2)
if self.date3:
l.append(self.date3)
if self.date4:
l.append(self.date4)
return l
return Dummy()
class TelechatDatesProxy(object):
objects = TelechatDatesProxyDummy()
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
TelechatDatesOld = TelechatDates
TelechatDates = TelechatDatesProxy

View file

@ -1,67 +1,367 @@
from datetime import timedelta
import os, shutil
import os, shutil, json
from django.core.urlresolvers import reverse as urlreverse
from django.conf import settings
from pyquery import PyQuery
from ietf.idtracker.models import *
from ietf.utils.test_data import make_test_data
from ietf.doc.models import *
from ietf.person.models import Person
from ietf.group.models import Group
from ietf.name.models import StreamName
from ietf.iesg.models import *
from ietf.utils.test_utils import TestCase, SimpleUrlTestCase, RealDatabaseTest, canonicalize_feed, login_testing_unauthorized
from ietf.ietfworkflows.models import Stream
from ietf.utils.test_utils import TestCase, login_testing_unauthorized
from ietf.iesg.agenda import get_agenda_date, agenda_data
class RescheduleOnAgendaTestCase(TestCase):
# See ietf.utils.test_utils.TestCase for the use of perma_fixtures vs. fixtures
perma_fixtures = ['base', 'draft']
class ReviewDecisionsTests(TestCase):
def test_review_decisions(self):
draft = make_test_data()
def test_reschedule(self):
draft = InternetDraft.objects.get(filename="draft-ietf-mipshop-pfmipv6")
draft.idinternal.telechat_date = TelechatDates.objects.all()[0].dates()[0]
draft.idinternal.agenda = True
draft.idinternal.returning_item = True
draft.idinternal.save()
e = DocEvent(type="iesg_approved")
e.doc = draft
e.by = Person.objects.get(name="Aread Irector")
e.save()
form_id = draft.idinternal.draft_id
telechat_date_before = draft.idinternal.telechat_date
url = urlreverse('ietf.iesg.views.agenda_documents')
self.client.login(remote_user="klm")
url = urlreverse('ietf.iesg.views.review_decisions')
# normal get
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertEquals(len(q('form select[name=%s-telechat_date]' % form_id)), 1)
self.assertEquals(len(q('form input[name=%s-clear_returning_item]' % form_id)), 1)
self.assertTrue(draft.name in r.content)
# reschedule
comments_before = draft.idinternal.comments().count()
d = TelechatDates.objects.all()[0].dates()[2]
class IESGAgendaTests(TestCase):
def setUp(self):
make_test_data()
r = self.client.post(url, { '%s-telechat_date' % form_id: d.strftime("%Y-%m-%d"),
'%s-clear_returning_item' % form_id: "1" })
ise_draft = Document.objects.get(name="draft-imaginary-independent-submission")
ise_draft.stream = StreamName.objects.get(slug="ise")
ise_draft.save()
self.telechat_docs = {
"ietf_draft": Document.objects.get(name="draft-ietf-mars-test"),
"ise_draft": ise_draft,
"conflrev": Document.objects.get(name="conflict-review-imaginary-irtf-submission"),
"statchg": Document.objects.get(name="status-change-imaginary-mid-review"),
"charter": Document.objects.filter(type="charter")[0],
}
by = Person.objects.get(name="Aread Irector")
date = get_agenda_date()
self.draft_dir = os.path.abspath("tmp-agenda-draft-dir")
os.mkdir(self.draft_dir)
settings.INTERNET_DRAFT_PATH = self.draft_dir
for d in self.telechat_docs.values():
TelechatDocEvent.objects.create(type="scheduled_for_telechat",
doc=d,
by=by,
telechat_date=date,
returning_item=True)
def tearDown(self):
shutil.rmtree(self.draft_dir)
def test_fill_in_agenda_docs(self):
draft = self.telechat_docs["ietf_draft"]
statchg = self.telechat_docs["statchg"]
conflrev = self.telechat_docs["conflrev"]
charter = self.telechat_docs["charter"]
# put on agenda
date = datetime.date.today() + datetime.timedelta(days=50)
TelechatDate.objects.create(date=date)
telechat_event = TelechatDocEvent.objects.create(
type="scheduled_for_telechat",
doc=draft,
by=Person.objects.get(name="Aread Irector"),
telechat_date=date,
returning_item=False)
date_str = date.isoformat()
# 2.1 protocol WG submissions
draft.intended_std_level_id = "ps"
draft.group = Group.objects.get(acronym="mars")
draft.save()
draft.set_state(State.objects.get(type="draft-iesg", slug="iesg-eva"))
self.assertTrue(draft in agenda_data(date_str)["sections"]["2.1.1"]["docs"])
telechat_event.returning_item = True
telechat_event.save()
self.assertTrue(draft in agenda_data(date_str)["sections"]["2.1.2"]["docs"])
telechat_event.returning_item = False
telechat_event.save()
draft.set_state(State.objects.get(type="draft-iesg", slug="pub-req"))
self.assertTrue(draft in agenda_data(date_str)["sections"]["2.1.3"]["docs"])
# 2.2 protocol individual submissions
draft.group = Group.objects.get(type="individ")
draft.save()
draft.set_state(State.objects.get(type="draft-iesg", slug="iesg-eva"))
self.assertTrue(draft in agenda_data(date_str)["sections"]["2.2.1"]["docs"])
telechat_event.returning_item = True
telechat_event.save()
self.assertTrue(draft in agenda_data(date_str)["sections"]["2.2.2"]["docs"])
telechat_event.returning_item = False
telechat_event.save()
draft.set_state(State.objects.get(type="draft-iesg", slug="pub-req"))
self.assertTrue(draft in agenda_data(date_str)["sections"]["2.2.3"]["docs"])
# 3.1 document WG submissions
draft.intended_std_level_id = "inf"
draft.group = Group.objects.get(acronym="mars")
draft.save()
draft.set_state(State.objects.get(type="draft-iesg", slug="iesg-eva"))
self.assertTrue(draft in agenda_data(date_str)["sections"]["3.1.1"]["docs"])
telechat_event.returning_item = True
telechat_event.save()
self.assertTrue(draft in agenda_data(date_str)["sections"]["3.1.2"]["docs"])
telechat_event.returning_item = False
telechat_event.save()
draft.set_state(State.objects.get(type="draft-iesg", slug="pub-req"))
self.assertTrue(draft in agenda_data(date_str)["sections"]["3.1.3"]["docs"])
# 3.2 document individual submissions
draft.group = Group.objects.get(type="individ")
draft.save()
draft.set_state(State.objects.get(type="draft-iesg", slug="iesg-eva"))
self.assertTrue(draft in agenda_data(date_str)["sections"]["3.2.1"]["docs"])
telechat_event.returning_item = True
telechat_event.save()
self.assertTrue(draft in agenda_data(date_str)["sections"]["3.2.2"]["docs"])
telechat_event.returning_item = False
telechat_event.save()
draft.set_state(State.objects.get(type="draft-iesg", slug="pub-req"))
self.assertTrue(draft in agenda_data(date_str)["sections"]["3.2.3"]["docs"])
# 2.3 protocol status changes
telechat_event.doc = statchg
telechat_event.save()
relation = RelatedDocument.objects.create(
source=statchg,
target=DocAlias.objects.filter(name__startswith='rfc', document__std_level="ps")[0],
relationship_id="tohist")
statchg.group = Group.objects.get(acronym="mars")
statchg.save()
statchg.set_state(State.objects.get(type="statchg", slug="iesgeval"))
self.assertTrue(statchg in agenda_data(date_str)["sections"]["2.3.1"]["docs"])
telechat_event.returning_item = True
telechat_event.save()
self.assertTrue(statchg in agenda_data(date_str)["sections"]["2.3.2"]["docs"])
telechat_event.returning_item = False
telechat_event.save()
statchg.set_state(State.objects.get(type="statchg", slug="adrev"))
self.assertTrue(statchg in agenda_data(date_str)["sections"]["2.3.3"]["docs"])
# 3.3 document status changes
relation.target = DocAlias.objects.filter(name__startswith='rfc', document__std_level="inf")[0]
relation.save()
statchg.group = Group.objects.get(acronym="mars")
statchg.save()
statchg.set_state(State.objects.get(type="statchg", slug="iesgeval"))
self.assertTrue(statchg in agenda_data(date_str)["sections"]["3.3.1"]["docs"])
telechat_event.returning_item = True
telechat_event.save()
self.assertTrue(statchg in agenda_data(date_str)["sections"]["3.3.2"]["docs"])
telechat_event.returning_item = False
telechat_event.save()
statchg.set_state(State.objects.get(type="statchg", slug="adrev"))
self.assertTrue(statchg in agenda_data(date_str)["sections"]["3.3.3"]["docs"])
# 3.4 IRTF/ISE conflict reviews
telechat_event.doc = conflrev
telechat_event.save()
conflrev.group = Group.objects.get(acronym="mars")
conflrev.save()
conflrev.set_state(State.objects.get(type="conflrev", slug="iesgeval"))
self.assertTrue(conflrev in agenda_data(date_str)["sections"]["3.4.1"]["docs"])
telechat_event.returning_item = True
telechat_event.save()
self.assertTrue(conflrev in agenda_data(date_str)["sections"]["3.4.2"]["docs"])
telechat_event.returning_item = False
telechat_event.save()
conflrev.set_state(State.objects.get(type="conflrev", slug="needshep"))
self.assertTrue(conflrev in agenda_data(date_str)["sections"]["3.4.3"]["docs"])
# 4 WGs
telechat_event.doc = charter
telechat_event.save()
charter.group = Group.objects.get(acronym="mars")
charter.save()
charter.group.state_id = "bof"
charter.group.save()
charter.set_state(State.objects.get(type="charter", slug="infrev"))
self.assertTrue(charter in agenda_data(date_str)["sections"]["4.1.1"]["docs"])
charter.set_state(State.objects.get(type="charter", slug="iesgrev"))
self.assertTrue(charter in agenda_data(date_str)["sections"]["4.1.2"]["docs"])
charter.group.state_id = "active"
charter.group.save()
charter.set_state(State.objects.get(type="charter", slug="infrev"))
self.assertTrue(charter in agenda_data(date_str)["sections"]["4.2.1"]["docs"])
charter.set_state(State.objects.get(type="charter", slug="iesgrev"))
self.assertTrue(charter in agenda_data(date_str)["sections"]["4.2.2"]["docs"])
#for n, s in agenda_data(date_str)["sections"].iteritems():
# print n, s.get("docs") if "docs" in s else s["title"]
def test_feed(self):
url = "/feed/iesg-agenda/"
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
# check that it moved below the right header in the DOM
d_header_pos = r.content.find("IESG telechat %s" % d.strftime("%Y-%m-%d"))
draft_pos = r.content.find(draft.filename)
self.assertTrue(d_header_pos < draft_pos)
for d in self.telechat_docs.values():
self.assertTrue(d.name in r.content)
self.assertTrue(d.title in r.content)
draft = InternetDraft.objects.get(filename="draft-ietf-mipshop-pfmipv6")
self.assertEquals(draft.idinternal.telechat_date, d)
self.assertTrue(not draft.idinternal.returning_item)
self.assertEquals(draft.idinternal.comments().count(), comments_before + 1)
self.assertTrue("Telechat" in draft.idinternal.comments()[0].comment_text)
def test_agenda_json(self):
r = self.client.get(urlreverse("ietf.iesg.views.agenda_json"))
self.assertEquals(r.status_code, 200)
class RescheduleOnAgendaTestCaseREDESIGN(TestCase):
perma_fixtures = ['names']
for k, d in self.telechat_docs.iteritems():
if d.type_id == "charter":
self.assertTrue(d.group.name in r.content, "%s not in response" % k)
self.assertTrue(d.group.acronym in r.content, "%s acronym not in response" % k)
else:
self.assertTrue(d.name in r.content, "%s not in response" % k)
self.assertTrue(d.title in r.content, "%s title not in response" % k)
self.assertTrue(json.loads(r.content))
def test_agenda(self):
r = self.client.get(urlreverse("ietf.iesg.views.agenda"))
self.assertEquals(r.status_code, 200)
for k, d in self.telechat_docs.iteritems():
self.assertTrue(d.name in r.content, "%s not in response" % k)
self.assertTrue(d.title in r.content, "%s title not in response" % k)
def test_agenda_txt(self):
r = self.client.get(urlreverse("ietf.iesg.views.agenda_txt"))
self.assertEquals(r.status_code, 200)
for k, d in self.telechat_docs.iteritems():
if d.type_id == "charter":
self.assertTrue(d.group.name in r.content, "%s not in response" % k)
self.assertTrue(d.group.acronym in r.content, "%s acronym not in response" % k)
else:
self.assertTrue(d.name in r.content, "%s not in response" % k)
self.assertTrue(d.title in r.content, "%s title not in response" % k)
def test_agenda_scribe_template(self):
r = self.client.get(urlreverse("ietf.iesg.views.agenda_scribe_template"))
self.assertEquals(r.status_code, 200)
for k, d in self.telechat_docs.iteritems():
if d.type_id == "charter":
continue # scribe template doesn't contain chartering info
self.assertTrue(d.name in r.content, "%s not in response" % k)
self.assertTrue(d.title in r.content, "%s title not in response" % k)
def test_agenda_moderator_package(self):
url = urlreverse("ietf.iesg.views.agenda_moderator_package")
login_testing_unauthorized(self, "secretary", url)
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
for k, d in self.telechat_docs.iteritems():
if d.type_id == "charter":
self.assertTrue(d.group.name in r.content, "%s not in response" % k)
self.assertTrue(d.group.acronym in r.content, "%s acronym not in response" % k)
else:
self.assertTrue(d.name in r.content, "%s not in response" % k)
self.assertTrue(d.title in r.content, "%s title not in response" % k)
def test_agenda_package(self):
url = urlreverse("ietf.iesg.views.agenda_package")
login_testing_unauthorized(self, "secretary", url)
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
for k, d in self.telechat_docs.iteritems():
if d.type_id == "charter":
self.assertTrue(d.group.name in r.content, "%s not in response" % k)
self.assertTrue(d.group.acronym in r.content, "%s acronym not in response" % k)
else:
self.assertTrue(d.name in r.content, "%s not in response" % k)
self.assertTrue(d.title in r.content, "%s title not in response" % k)
def test_agenda_documents_txt(self):
url = urlreverse("ietf.iesg.views.agenda_documents_txt")
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
for k, d in self.telechat_docs.iteritems():
self.assertTrue(d.name in r.content, "%s not in response" % k)
def test_agenda_documents(self):
url = urlreverse("ietf.iesg.views.agenda_documents")
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
for k, d in self.telechat_docs.iteritems():
self.assertTrue(d.name in r.content, "%s not in response" % k)
self.assertTrue(d.title in r.content, "%s title not in response" % k)
def test_agenda_telechat_docs(self):
d1 = self.telechat_docs["ietf_draft"]
d2 = self.telechat_docs["ise_draft"]
d1_filename = "%s-%s.txt" % (d1.name, d1.rev)
d2_filename = "%s-%s.txt" % (d2.name, d2.rev)
with open(os.path.join(self.draft_dir, d1_filename), "w") as f:
f.write("test content")
url = urlreverse("ietf.iesg.views.telechat_docs_tarfile", kwargs=dict(date=get_agenda_date().isoformat()))
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
import tarfile, StringIO
tar = tarfile.open(None, fileobj=StringIO.StringIO(r.content))
names = tar.getnames()
self.assertTrue(d1_filename in names)
self.assertTrue(d2_filename not in names)
self.assertTrue("manifest.txt" in names)
f = tar.extractfile(d1_filename)
self.assertEqual(f.read(), "test content")
f = tar.extractfile("manifest.txt")
lines = list(f.readlines())
self.assertTrue("Included" in [l for l in lines if d1_filename in l][0])
self.assertTrue("Not found" in [l for l in lines if d2_filename in l][0])
class RescheduleOnAgendaTests(TestCase):
def test_reschedule(self):
from ietf.utils.test_data import make_test_data
from ietf.person.models import Person
from ietf.doc.models import TelechatDocEvent
draft = make_test_data()
# add to schedule
@ -94,10 +394,12 @@ class RescheduleOnAgendaTestCaseREDESIGN(TestCase):
r = self.client.post(url, { '%s-telechat_date' % form_id: d.isoformat(),
'%s-clear_returning_item' % form_id: "1" })
self.assertEquals(r.status_code, 200)
self.assertEquals(r.status_code, 302)
# check that it moved below the right header in the DOM on the
# agenda docs page
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
d_header_pos = r.content.find("IESG telechat %s" % d.isoformat())
draft_pos = r.content.find(draft.name)
self.assertTrue(d_header_pos < draft_pos)
@ -107,376 +409,7 @@ class RescheduleOnAgendaTestCaseREDESIGN(TestCase):
self.assertTrue(not draft.latest_event(TelechatDocEvent, "scheduled_for_telechat").returning_item)
self.assertEquals(draft.docevent_set.count(), events_before + 1)
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
RescheduleOnAgendaTestCase = RescheduleOnAgendaTestCaseREDESIGN
class ManageTelechatDatesTestCase(TestCase):
perma_fixtures = ['base', 'draft']
def test_set_dates(self):
dates = TelechatDates.objects.all()[0]
url = urlreverse('ietf.iesg.views.telechat_dates')
login_testing_unauthorized(self, "klm", url)
# normal get
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertEquals(len(q('form input[name=date1]')), 1)
# post
new_date = dates.date1 + timedelta(days=7)
r = self.client.post(url, dict(date1=new_date.isoformat(),
date2=new_date.isoformat(),
date3=new_date.isoformat(),
date4=new_date.isoformat(),
))
self.assertEquals(r.status_code, 200)
dates = TelechatDates.objects.all()[0]
self.assertTrue(dates.date1 == new_date)
def test_rollup_dates(self):
dates = TelechatDates.objects.all()[0]
url = urlreverse('ietf.iesg.views.telechat_dates')
login_testing_unauthorized(self, "klm", url)
old_date2 = dates.date2
new_date = dates.date4 + timedelta(days=14)
r = self.client.post(url, dict(rollup_dates="1"))
self.assertEquals(r.status_code, 200)
dates = TelechatDates.objects.all()[0]
self.assertTrue(dates.date4 == new_date)
self.assertTrue(dates.date1 == old_date2)
# class ManageTelechatDatesTestCaseREDESIGN(TestCase):
# perma_fixtures = ['names']
# def test_set_dates(self):
# from ietf.utils.test_data import make_test_data
# make_test_data()
# dates = TelechatDates.objects.all()[0]
# url = urlreverse('ietf.iesg.views.telechat_dates')
# login_testing_unauthorized(self, "secretary", url)
# # normal get
# r = self.client.get(url)
# self.assertEquals(r.status_code, 200)
# q = PyQuery(r.content)
# self.assertEquals(len(q('form input[name=date1]')), 1)
# # post
# new_date = dates.date1 + timedelta(days=7)
# r = self.client.post(url, dict(date1=new_date.isoformat(),
# date2=new_date.isoformat(),
# date3=new_date.isoformat(),
# date4=new_date.isoformat(),
# ))
# self.assertEquals(r.status_code, 200)
# dates = TelechatDates.objects.all()[0]
# self.assertTrue(dates.date1 == new_date)
# def test_rollup_dates(self):
# from ietf.utils.test_data import make_test_data
# make_test_data()
# dates = TelechatDates.objects.all()[0]
# url = urlreverse('ietf.iesg.views.telechat_dates')
# login_testing_unauthorized(self, "secretary", url)
# old_date2 = dates.date2
# new_date = dates.date4 + timedelta(days=14)
# r = self.client.post(url, dict(rollup_dates="1"))
# self.assertEquals(r.status_code, 200)
# dates = TelechatDates.objects.all()[0]
# self.assertTrue(dates.date4 == new_date)
# self.assertTrue(dates.date1 == old_date2)
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
#ManageTelechatDatesTestCase = ManageTelechatDatesTestCaseREDESIGN
del ManageTelechatDatesTestCase
class WorkingGroupActionsTestCase(TestCase):
perma_fixtures = ['base', 'wgactions']
def setUp(self):
super(self.__class__, self).setUp()
curdir = os.path.dirname(os.path.abspath(__file__))
self.evaldir = os.path.join(curdir, "testdir")
os.mkdir(self.evaldir)
src = os.path.join(curdir, "fixtures", "sieve-charter.txt")
shutil.copy(src, self.evaldir)
settings.IESG_WG_EVALUATION_DIR = self.evaldir
def tearDown(self):
super(self.__class__, self).tearDown()
shutil.rmtree(self.evaldir)
def test_working_group_actions(self):
url = urlreverse('iesg_working_group_actions')
login_testing_unauthorized(self, "klm", url)
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
for wga in WGAction.objects.all():
self.assertTrue(wga.group_acronym.name in r.content)
self.assertTrue('(sieve)' in r.content)
def test_delete_wgaction(self):
wga = WGAction.objects.all()[0]
url = urlreverse('iesg_edit_working_group_action', kwargs=dict(wga_id=wga.pk))
login_testing_unauthorized(self, "klm", url)
r = self.client.post(url, dict(delete="1"))
self.assertEquals(r.status_code, 302)
self.assertTrue(not WGAction.objects.filter(pk=wga.pk))
def test_edit_wgaction(self):
wga = WGAction.objects.all()[0]
url = urlreverse('iesg_edit_working_group_action', kwargs=dict(wga_id=wga.pk))
login_testing_unauthorized(self, "klm", url)
# normal get
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertEquals(len(q('form select[name=token_name]')), 1)
self.assertEquals(len(q('form select[name=telechat_date]')), 1)
# change
dates = TelechatDates.objects.all()[0]
token_name = IESGLogin.active_iesg().exclude(first_name=wga.token_name)[0].first_name
old = wga.pk
r = self.client.post(url, dict(status_date=dates.date1.isoformat(),
token_name=token_name,
category="23",
note="Testing.",
telechat_date=dates.date4.isoformat()))
self.assertEquals(r.status_code, 302)
wga = WGAction.objects.get(pk=old)
self.assertEquals(wga.status_date, dates.date1)
self.assertEquals(wga.token_name, token_name)
self.assertEquals(wga.category, 23)
self.assertEquals(wga.note, "Testing.")
self.assertEquals(wga.telechat_date, dates.date4)
def test_add_possible_wg(self):
url = urlreverse('iesg_working_group_actions')
login_testing_unauthorized(self, "klm", url)
r = self.client.post(url, dict(add="1",
filename='sieve-charter.txt'))
self.assertEquals(r.status_code, 302)
add_url = r['Location']
r = self.client.get(add_url)
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertTrue('(sieve)' in r.content)
self.assertEquals(len(q('form select[name=token_name]')), 1)
self.assertEquals(q('form input[name=status_date]')[0].get("value"), "2010-05-07")
self.assertEquals(len(q('form select[name=telechat_date]')), 1)
wgas_before = WGAction.objects.all().count()
dates = TelechatDates.objects.all()[0]
token_name = IESGLogin.active_iesg()[0].first_name
r = self.client.post(add_url,
dict(status_date=dates.date1.isoformat(),
token_name=token_name,
category="23",
note="Testing.",
telechat_date=dates.date4.isoformat()))
self.assertEquals(r.status_code, 302)
self.assertEquals(wgas_before + 1, WGAction.objects.all().count())
def test_delete_possible_wg(self):
url = urlreverse('iesg_working_group_actions')
login_testing_unauthorized(self, "klm", url)
r = self.client.post(url, dict(delete="1",
filename='sieve-charter.txt'))
self.assertEquals(r.status_code, 200)
self.assertTrue('(sieve)' not in r.content)
class WorkingGroupActionsTestCaseREDESIGN(TestCase):
perma_fixtures = ['names']
def setUp(self):
super(self.__class__, self).setUp()
curdir = os.path.dirname(os.path.abspath(__file__))
self.evaldir = os.path.join(curdir, "tmp-testdir")
os.mkdir(self.evaldir)
src = os.path.join(curdir, "fixtures", "sieve-charter.txt")
shutil.copy(src, self.evaldir)
settings.IESG_WG_EVALUATION_DIR = self.evaldir
def tearDown(self):
super(self.__class__, self).tearDown()
shutil.rmtree(self.evaldir)
def test_working_group_actions(self):
from ietf.utils.test_data import make_test_data
make_test_data()
url = urlreverse('iesg_working_group_actions')
login_testing_unauthorized(self, "secretary", url)
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
for wga in WGAction.objects.all():
self.assertTrue(wga.group_acronym.name in r.content)
self.assertTrue('(sieve)' in r.content)
def test_delete_wgaction(self):
from ietf.utils.test_data import make_test_data
make_test_data()
wga = WGAction.objects.all()[0]
url = urlreverse('iesg_edit_working_group_action', kwargs=dict(wga_id=wga.pk))
login_testing_unauthorized(self, "secretary", url)
r = self.client.post(url, dict(delete="1"))
self.assertEquals(r.status_code, 302)
self.assertTrue(not WGAction.objects.filter(pk=wga.pk))
def test_edit_wgaction(self):
from ietf.utils.test_data import make_test_data
from ietf.person.models import Person
make_test_data()
wga = WGAction.objects.all()[0]
url = urlreverse('iesg_edit_working_group_action', kwargs=dict(wga_id=wga.pk))
login_testing_unauthorized(self, "secretary", url)
# normal get
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertEquals(len(q('form select[name=token_name]')), 1)
self.assertEquals(len(q('form select[name=telechat_date]')), 1)
# change
dates = TelechatDate.objects.active()
token_name = Person.objects.get(name="Ad No1").plain_name()
old = wga.pk
r = self.client.post(url, dict(status_date=dates[0].date.isoformat(),
token_name=token_name,
category="23",
note="Testing.",
telechat_date=dates[3].date.isoformat()))
self.assertEquals(r.status_code, 302)
wga = WGAction.objects.get(pk=old)
self.assertEquals(wga.status_date, dates[0].date)
self.assertEquals(wga.token_name, token_name)
self.assertEquals(wga.category, 23)
self.assertEquals(wga.note, "Testing.")
self.assertEquals(wga.telechat_date, dates[3].date)
def test_add_possible_wg(self):
from ietf.utils.test_data import make_test_data
from ietf.person.models import Person
from ietf.group.models import Group
make_test_data()
url = urlreverse('iesg_working_group_actions')
login_testing_unauthorized(self, "secretary", url)
r = self.client.post(url, dict(add="1",
filename='sieve-charter.txt'))
self.assertEquals(r.status_code, 302)
# now we got back a URL we can use for adding, but first make
# sure we got a proposed group with the acronym
group = Group.objects.create(
name="Sieve test test",
acronym="sieve",
state_id="proposed",
type_id="wg",
parent=None
)
add_url = r['Location']
r = self.client.get(add_url)
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertTrue('(sieve)' in r.content)
self.assertEquals(len(q('form select[name=token_name]')), 1)
self.assertEquals(q('form input[name=status_date]')[0].get("value"), "2010-05-07")
self.assertEquals(len(q('form select[name=telechat_date]')), 1)
wgas_before = WGAction.objects.all().count()
dates = TelechatDate.objects.active()
token_name = Person.objects.get(name="Ad No1").plain_name()
r = self.client.post(add_url,
dict(status_date=dates[0].date.isoformat(),
token_name=token_name,
category="23",
note="Testing.",
telechat_date=dates[3].date.isoformat()))
self.assertEquals(r.status_code, 302)
self.assertEquals(wgas_before + 1, WGAction.objects.all().count())
def test_delete_possible_wg(self):
from ietf.utils.test_data import make_test_data
make_test_data()
url = urlreverse('iesg_working_group_actions')
login_testing_unauthorized(self, "secretary", url)
r = self.client.post(url, dict(delete="1",
filename='sieve-charter.txt'))
self.assertEquals(r.status_code, 200)
self.assertTrue('(sieve)' not in r.content)
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
WorkingGroupActionsTestCase = WorkingGroupActionsTestCaseREDESIGN
class IesgUrlTestCase(SimpleUrlTestCase):
def testUrls(self):
self.doTestUrls(__file__)
def doCanonicalize(self, url, content):
if url.startswith("/feed/"):
return canonicalize_feed(content)
else:
return content
#Tests added since database redesign that speak the new clases
from ietf.doc.models import Document,TelechatDocEvent,State
from ietf.group.models import Person
class DeferUndeferTestCase(TestCase):
perma_fixtures = ['names']
def helper_test_defer(self,name):
doc = Document.objects.get(name=name)
@ -571,5 +504,24 @@ class DeferUndeferTestCase(TestCase):
# when charters support being deferred, be sure to test them here
def setUp(self):
from ietf.utils.test_data import make_test_data
make_test_data()
class IESGDiscussesTests(TestCase):
def test_feed(self):
draft = make_test_data()
draft.set_state(State.objects.get(type="draft-iesg", slug="iesg-eva"))
pos = BallotPositionDocEvent()
pos.ballot = draft.latest_event(BallotDocEvent, type="created_ballot")
pos.pos_id = "discuss"
pos.type = "changed_ballot_position"
pos.doc = draft
pos.ad = pos.by = Person.objects.get(user__username="ad")
pos.save()
r = self.client.get(urlreverse("ietf.iesg.views.discusses"))
self.assertEquals(r.status_code, 200)
self.assertTrue(draft.name in r.content)
self.assertTrue(pos.ad.plain_name() in r.content)

View file

@ -1,24 +0,0 @@
301 /iesg/telechat/
301 /iesg/telechat/y/2007/
301 /iesg/telechat/y/2007/apr/
301 /iesg/telechat/354/
200 /iesg/agenda/
200 /iesg/agenda/agenda.txt
200 /iesg/agenda/scribe_template.html
200 /iesg/agenda/documents.txt
200 /iesg/agenda/documents/
200 /iesg/discusses/
302 /iesg/agenda/moderator_package.html
302 /iesg/agenda/agenda_package.txt
200 /iesg/_test/moderator_package.html
200 /iesg/_test/agenda_package.txt
200 /iesg/ann/ind/
200 /iesg/ann/new/
# This takes ~ 300s:
#200 /iesg/ann/prev/
200 /feed/iesg-agenda/

View file

@ -35,41 +35,23 @@
from django.conf.urls.defaults import patterns, url
from django.conf import settings
from ietf.iesg import views
from ietf.idtracker.models import BallotInfo
queryset_ann = BallotInfo.objects.all()
urlpatterns = patterns('',
(r'^telechat/.*$', 'django.views.generic.simple.redirect_to', { 'url': 'http://www.ietf.org/iesg/minutes.html' })
)
(r'^telechat/.*$', 'django.views.generic.simple.redirect_to', { 'url': 'http://www.ietf.org/iesg/minutes.html' }),
(r'^ann/(?:ind|new|prev)/$', 'django.views.generic.simple.redirect_to', { 'url': "/iesg/decisions/", 'permanent': True }),
(r'^telechatdates/$', 'django.views.generic.simple.redirect_to', { 'url': '/admin/iesg/telechatdate/' }),
urlpatterns += patterns('django.views.generic.list_detail',
(r'^ann/(?P<object_id>\d+)/$', 'object_detail', { 'queryset': queryset_ann, 'template_name':"iesg/ballotinfo_detail.html" }),
(r'^decisions/(?:(?P<year>[0-9]{4})/)?$', views.review_decisions),
(r'^agenda/(?:(?P<date>\d{4}-\d{2}-\d{2})/)?$', views.agenda),
(r'^agenda/(?:(?P<date>\d{4}-\d{2}-\d{2})/)?agenda.txt$', views.agenda_txt),
(r'^agenda/(?:(?P<date>\d{4}-\d{2}-\d{2})/)?agenda.json$', views.agenda_json),
(r'^agenda/(?:(?P<date>\d{4}-\d{2}-\d{2})/)?scribe_template.html$', views.agenda_scribe_template),
(r'^agenda/(?:(?P<date>\d{4}-\d{2}-\d{2})/)?moderator_package.html$', views.agenda_moderator_package),
(r'^agenda/(?:(?P<date>\d{4}-\d{2}-\d{2})/)?agenda_package.txt$', views.agenda_package),
(r'^agenda/documents.txt$', views.agenda_documents_txt),
(r'^agenda/documents/$', views.agenda_documents),
(r'^agenda/telechat-(?:(?P<date>\d{4}-\d{2}-\d{2})-)?docs.tgz', views.telechat_docs_tarfile),
(r'^discusses/$', views.discusses),
(r'^milestones/$', views.milestones_needing_review),
)
urlpatterns += patterns('',
(r'^ann/ind/$',views.inddocs),
(r'^ann/(?P<cat>[^/]+)/$',views.wgdocs),
(r'^agenda/$', views.agenda),
(r'^agenda/agenda.txt$', views.agenda_txt),
(r'^agenda/agenda.json$', views.agenda_json),
(r'^agenda/scribe_template.html$', views.agenda_scribe_template),
(r'^agenda/moderator_package.html$', views.agenda_moderator_package),
(r'^agenda/agenda_package.txt$', views.agenda_package),
(r'^agenda/documents.txt$', views.agenda_documents_txt),
(r'^agenda/documents/$', views.agenda_documents),
(r'^agenda/telechat-(?P<year>\d+)-(?P<month>\d+)-(?P<day>\d+)-docs.tgz', views.telechat_docs_tarfile),
(r'^discusses/$', views.discusses),
(r'^milestones', views.milestones_needing_review),
(r'^telechatdates/$', 'django.views.generic.simple.redirect_to', { 'url': '/admin/iesg/telechatdate/' }),
url(r'^wgactions/$', views.working_group_actions, name="iesg_working_group_actions"),
url(r'^wgactions/add/$', views.edit_working_group_action, { 'wga_id': None }, name="iesg_add_working_group_action"),
url(r'^wgactions/(?P<wga_id>\d+)/$', views.edit_working_group_action, name="iesg_edit_working_group_action"),
)
if settings.SERVER_MODE != 'production':
urlpatterns += patterns('',
(r'^agenda/(?P<date>\d{4}-\d\d-\d\d)/$', views.agenda),
(r'^_test/moderator_package.html$', views.agenda_moderator_package_test),
(r'^_test/agenda_package.txt', views.agenda_package_test),
)

File diff suppressed because it is too large Load diff

View file

@ -1,2 +0,0 @@
# Copyright The IETF Trust 2007, All Rights Reserved

View file

@ -1,115 +0,0 @@
# Portions Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
# All rights reserved. Contact: Pasi Eronen <pasi.eronen@nokia.com>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# * Neither the name of the Nokia Corporation and/or its
# subsidiary(-ies) nor the names of its contributors may be used
# to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Copyright The IETF Trust 2007, All Rights Reserved
from django.contrib.auth.backends import RemoteUserBackend
from django.contrib.auth.models import Group
from ietf.idtracker.models import IESGLogin, Role
from ietf.ietfauth.models import IetfUserProfile
from ietf.utils import log
AUTOMATIC_GROUPS = ["Area_Director", "Secretariat", "IETF_Chair",
"IAB_Chair", "IRTF_Chair", ]
class IetfUserBackend(RemoteUserBackend):
def find_groups(username):
"""
Role/Group:
Area_Director currently sitting AD
IETF_Chair currently sitting IETF Chair
IAB_Chair currently sitting IAB Chair
IRTF_Chair currently sitting IRTF Chair
Secretariat secretariat staff
Roles/Groups NOT YET IMPLEMENTED
WG_Chair currently sitting chair of some WG
IESG_Liaison non-ADs on iesg@ietf.org and telechats
Session_Chair chairing a non-WG session in IETF meeting
Ex_Area_Director past AD
"""
# Any group name added by this method should be added to the
# AUTOMATIC_GROUPS list
groups = []
try:
login = IESGLogin.objects.get(login_name=username)
if login.user_level == 1:
groups.append("Area_Director")
elif login.user_level == 0:
groups.append("Secretariat")
if login.person:
for role in login.person.role_set.all():
if role.id == Role.IETF_CHAIR:
groups.append("IETF_Chair")
elif role.id == Role.IAB_CHAIR:
groups.append("IAB_Chair")
elif role.id == Role.IRTF_CHAIR:
groups.append("IRTF_Chair")
except IESGLogin.DoesNotExist:
pass
#
# Additional sources of group memberships:
# - wg_password table
# - other Roles
# - the /etc/.../*.perms files
return groups
find_groups = staticmethod(find_groups)
def authenticate(self, remote_user):
user = RemoteUserBackend.authenticate(self, remote_user)
if not user:
return user
# Create profile if it doesn't exist
try:
profile = user.get_profile()
except IetfUserProfile.DoesNotExist:
profile = IetfUserProfile(user=user)
profile.save()
# Remove any automatic groups, the proper ones will be retrieved by
# find_groups
groups = [group for group in user.groups.exclude(name__in=AUTOMATIC_GROUPS)]
# Update group memberships
group_names = IetfUserBackend.find_groups(user.username)
for group_name in group_names:
# Create groups as needed
group,created = Group.objects.get_or_create(name=group_name)
if created:
log("IetfUserBackend created Group '%s'" % (group_name,))
groups.append(group)
user.groups = groups
return user

View file

@ -1,35 +0,0 @@
# Portion Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
# All rights reserved. Contact: Pasi Eronen <pasi.eronen@nokia.com>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# * Neither the name of the Nokia Corporation and/or its
# subsidiary(-ies) nor the names of its contributors may be used
# to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# REDESIGN: backwards compatibility, to be deleted
from ietf.ietfauth.utils import role_required, has_role, passes_test_decorator
group_required = lambda *group_names: role_required(*[n.replace("Area_Director", "Area Director") for n in group_names])

View file

@ -10,7 +10,8 @@ from django.contrib.sites.models import Site
from django.utils.translation import ugettext_lazy as _
from ietf.utils.mail import send_mail
from ietf.person.models import Person, Email
from ietf.person.models import Person, Email, Alias
from ietf.group.models import Role
class RegistrationForm(forms.Form):
@ -167,7 +168,6 @@ class PersonForm(ModelForm):
request = None
new_emails = []
class Meta:
from ietf.person.models import Person
model = Person
exclude = ('time','user')
@ -193,8 +193,6 @@ class PersonForm(ModelForm):
send_mail(self.request, to_email, from_email, subject, 'registration/add_email_email.txt', context)
def save(self, force_insert=False, force_update=False, commit=True):
from ietf.group.models import Role
from ietf.person.models import Alias
m = super(PersonForm, self).save(commit=False)
self.new_emails = [v for k,v in self.data.items() if k[:10] == u'new_email_' and u'@' in v]

View file

@ -1,136 +1 @@
# Portions Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
# All rights reserved. Contact: Pasi Eronen <pasi.eronen@nokia.com>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# * Neither the name of the Nokia Corporation and/or its
# subsidiary(-ies) nor the names of its contributors may be used
# to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Copyright The IETF Trust 2007, All Rights Reserved
from django.db import models
from django.contrib.auth.models import User
from ietf.idtracker.models import PersonOrOrgInfo, IESGLogin
from ietf.utils.admin import admin_link
def find_person(username):
try:
person = IESGLogin.objects.get(login_name=username).person
return person
except IESGLogin.DoesNotExist, PersonOrOrgInfo.DoesNotExist:
pass
# try LegacyWgPassword next
try:
return LegacyWgPassword.objects.get(login_name=username).person
except LegacyWgPassword.DoesNotExist, PersonOrOrgInfo.DoesNotExist:
pass
# try LegacyLiaisonUser next
try:
return LegacyLiaisonUser.objects.get(login_name=username).person
except LegacyLiaisonUser.DoesNotExist, PersonOrOrgInfo.DoesNotExist:
pass
return None
class IetfUserProfile(models.Model):
user = models.ForeignKey(User,unique=True)
def person(self):
return find_person(self.user.username)
def iesg_login_id(self):
person = self.person()
if not person:
return None
try:
return person.iesglogin_set.all()[0].id
except:
return None
def email(self):
# quick hack to bind new and old schema together for the time being
try:
l = IESGLogin.objects.get(login_name=self.user.username)
if l.person:
person = l.person
else:
person = PersonOrOrgInfo.objects.get(first_name=l.first_name,
last_name=l.last_name)
except IESGLogin.DoesNotExist, PersonOrOrgInfo.DoesNotExist:
person = None
from ietf.person.models import Email
return Email.objects.get(address=person.email()[1])
def __str__(self):
return "IetfUserProfile(%s)" % (self.user,)
######################################################
# legacy per-tool access tables.
# ietf.idtracker.models.IESGLogin is in the same vein.
class LegacyLiaisonUser(models.Model):
USER_LEVEL_CHOICES = (
(0, 'Secretariat'),
(1, 'IESG'),
(2, 'ex-IESG'),
(3, 'Level 3'),
(4, 'Comment Only(?)'),
)
person = models.ForeignKey(PersonOrOrgInfo, db_column='person_or_org_tag', primary_key=True)
login_name = models.CharField(max_length=255)
password = models.CharField(max_length=25, blank=True, editable=False)
user_level = models.IntegerField(null=True, blank=True, choices=USER_LEVEL_CHOICES)
comment = models.TextField(blank=True,null=True)
def __str__(self):
return self.login_name
class Meta:
db_table = 'users'
ordering = ['login_name']
person_link = admin_link('person')
class LegacyWgPassword(models.Model):
person = models.ForeignKey(PersonOrOrgInfo, db_column='person_or_org_tag', primary_key=True)
password = models.CharField(blank=True, null=True,max_length=255)
secrete_question_id = models.IntegerField(null=True, blank=True)
secrete_answer = models.CharField(blank=True, null=True, max_length=255)
is_tut_resp = models.IntegerField(null=True, blank=True)
irtf_id = models.IntegerField(null=True, blank=True)
comment = models.TextField(blank=True,null=True)
login_name = models.CharField(blank=True, max_length=100)
def __str__(self):
return self.login_name
class Meta:
db_table = 'wg_password'
ordering = ['login_name']
person_link = admin_link('person')
# changes done by convert-096.py:changed maxlength to max_length
# removed core
# removed edit_inline
# removed max_num_in_admin
# removed num_in_admin
# removed raw_id_admin

View file

@ -30,76 +30,46 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import unittest
from django.conf import settings
from django.contrib.auth.models import User
from django.test.client import Client
from ietf.utils.test_utils import SimpleUrlTestCase, RealDatabaseTest
from ietf.idtracker.models import Role
from urlparse import urlsplit
class IetfAuthUrlTestCase(SimpleUrlTestCase):
def testUrls(self):
self.doTestUrls(__file__)
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse as urlreverse
# this test case should really work on a test database instead of the
# real one
class IetfAuthTestCase(unittest.TestCase,RealDatabaseTest):
def setUp(self):
self.setUpRealDatabase()
def tearDown(self):
self.tearDownRealDatabase()
from ietf.utils.test_utils import TestCase, login_testing_unauthorized
from ietf.utils.test_data import make_test_data
def _doLogin(self, username):
c = Client()
response = c.get('/accounts/login/', {}, False, REMOTE_USER=username)
self.assertEquals(response.status_code, 302)
nexturl = urlsplit(response['Location'])
self.assertEquals(nexturl[2], "/accounts/loggedin/")
class IetfAuthTests(TestCase):
def test_index(self):
self.assertEqual(self.client.get(urlreverse("ietf.ietfauth.views.index")).status_code, 200)
response = c.get(nexturl[2], {}, False, REMOTE_USER=username)
self.assertEquals(response.status_code, 302)
nexturl = urlsplit(response['Location'])
self.assertEquals(nexturl[2], "/accounts/profile/")
def test_login(self):
make_test_data()
response = c.get(nexturl[2], {}, False, REMOTE_USER=username)
self.assertEquals(response.status_code, 200)
self.assert_("User name" in response.content)
return response
# try logging in with a next
r = self.client.get('/accounts/login/?next=/foobar', REMOTE_USER="plain")
self.assertEqual(r.status_code, 302)
self.assertEqual(urlsplit(r["Location"])[2], "/accounts/loggedin/")
def testLogin(self):
TEST_USERNAME = '__testuser'
print " Testing login with "+TEST_USERNAME
r = self.client.get('/accounts/loggedin/?next=/foobar', REMOTE_USER="plain")
self.assertEqual(r.status_code, 302)
self.assertEqual(urlsplit(r["Location"])[2], "/foobar")
# Delete test user (if it exists)
try:
testuser = User.objects.get(username=TEST_USERNAME)
testuser.delete()
except User.DoesNotExist:
pass
# try again without a next
r = self.client.get('/accounts/login/', REMOTE_USER="plain")
r = self.client.get('/accounts/loggedin/', REMOTE_USER="plain")
self.assertEqual(r.status_code, 302)
self.assertEqual(urlsplit(r["Location"])[2], "/accounts/profile/")
self._doLogin(TEST_USERNAME)
# Delete test user after test
testuser = User.objects.get(username=TEST_USERNAME)
testuser.delete()
print "OK"
def test_profile(self):
url = urlreverse('ietf.ietfauth.views.profile')
login_testing_unauthorized(self, "plain", url)
def testGroups(self):
print " Testing group assignment"
username = Role.objects.get(id=Role.IETF_CHAIR).person.iesglogin_set.all()[0].login_name
print " (with username "+str(username)+")"
self._doLogin(username)
user = User.objects.get(username=username)
groups = [x.name for x in user.groups.all()]
self.assert_("Area_Director" in groups)
self.assert_("IETF_Chair" in groups)
# get
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
self.assertTrue("plain" in r.content)
print "OK"
# post
# ... fill in
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
del IetfAuthTestCase.testLogin
# this test doesn't make any sense anymore
del IetfAuthTestCase.testGroups
# we're missing tests of the other views

View file

@ -1 +0,0 @@
302 /accounts/profile/

View file

@ -1,18 +1,14 @@
# Copyright The IETF Trust 2007, 2009, All Rights Reserved
from django.conf.urls.defaults import patterns, url
from ietf.ietfauth import views
urlpatterns = patterns('',
(r'^$', views.index, None, 'account_index'),
(r'^login/$', views.ietf_login),
(r'^loggedin/$', views.ietf_loggedin),
(r'^profile/$', views.profile),
# (r'^login/(?P<user>[a-z0-9.@]+)/(?P<passwd>.+)$', views.url_login),
(r'^testemail/$', views.test_email),
)
urlpatterns += patterns('ietf.ietfauth.views',
urlpatterns = patterns('ietf.ietfauth.views',
url(r'^$', 'index', name='account_index'),
url(r'^login/$', 'ietf_login'),
url(r'^loggedin/$', 'ietf_loggedin'),
url(r'^profile/$', 'profile'),
# (r'^login/(?P<user>[a-z0-9.@]+)/(?P<passwd>.+)$', 'url_login'),
url(r'^testemail/$', 'test_email'),
url(r'^create/$', 'create_account', name='create_account'),
url(r'^confirm/(?P<username>[\w.@+-]+)/(?P<date>[\d]+)/(?P<realm>[\w]+)/(?P<hash>[a-f0-9]+)/$', 'confirm_account', name='confirm_account'),
url(r'^reset/$', 'password_reset_view', name='password_reset'),

View file

@ -34,6 +34,7 @@
import datetime
import hashlib
import json
from django.conf import settings
from django.template import RequestContext
@ -43,10 +44,12 @@ from django.contrib.auth import REDIRECT_FIELD_NAME, authenticate, login
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.utils.http import urlquote
from django.utils import simplejson as json
from django.utils.translation import ugettext as _
from django.core.exceptions import ValidationError, NON_FIELD_ERRORS
from ietf.ietfauth.forms import RegistrationForm, PasswordForm, RecoverPasswordForm, TestEmailForm
from ietf.person.models import Person, Email, Alias
from ietf.group.models import Role
from ietf.ietfauth.forms import RegistrationForm, PasswordForm, RecoverPasswordForm, TestEmailForm, PersonForm
def index(request):
return render_to_response('registration/index.html', context_instance=RequestContext(request))
@ -62,8 +65,8 @@ def url_login(request, user, passwd):
def ietf_login(request):
if not request.user.is_authenticated():
# This probably means an exception occured inside IetfUserBackend
return HttpResponse("Not authenticated?", status=500)
redirect_to = request.REQUEST.get(REDIRECT_FIELD_NAME, '')
request.session.set_test_cookie()
return HttpResponseRedirect('/accounts/loggedin/?%s=%s' % (REDIRECT_FIELD_NAME, urlquote(redirect_to)))
@ -79,10 +82,6 @@ def ietf_loggedin(request):
@login_required
def profile(request):
from ietf.person.models import Person, Email, Alias
from ietf.group.models import Role
from ietf.ietfauth.forms import PersonForm
roles = []
person = None
try:
@ -119,8 +118,6 @@ def profile(request):
context_instance=RequestContext(request))
def confirm_new_email(request, username, date, email, hash):
from ietf.person.models import Person, Email, Alias
from django.core.exceptions import ValidationError, NON_FIELD_ERRORS
valid = hashlib.md5('%s%s%s%s' % (settings.SECRET_KEY, date, email, username)).hexdigest() == hash
if not valid:
raise Http404
@ -233,24 +230,15 @@ def ajax_check_username(request):
return HttpResponse(json.dumps({'error': error}), mimetype='text/plain')
def test_email(request):
"""Set email address to which email generated in the system will be sent."""
if settings.SERVER_MODE == "production":
raise Http404()
raise Http404
# note that the cookie set here is only used when running in
# Note that the cookie set here is only used when running in
# "test" mode, normally you run the server in "development" mode,
# in which case email is sent out as usual; for development, put
# this
#
# EMAIL_HOST = 'localhost'
# EMAIL_PORT = 1025
# EMAIL_HOST_USER = None
# EMAIL_HOST_PASSWORD = None
# EMAIL_COPY_TO = ""
#
# in your settings.py and start a little debug email server in a
# console with the following (it receives and prints messages)
#
# python -m smtpd -n -c DebuggingServer localhost:1025
# in which case email is sent out as usual; for development, you
# can easily start a little email debug server with Python, see
# the instructions in utils/mail.py.
cookie = None

View file

@ -1 +0,0 @@
/*.pyc

View file

@ -1,18 +0,0 @@
# coding: latin-1
from types import ModuleType
import urls, models, views, forms, accounts
# These people will be sent a stack trace if there's an uncaught exception in
# code any of the modules imported above:
DEBUG_EMAILS = [
('Emilio A. Sánchez', 'esanchez@yaco.es'),
]
for k in locals().keys():
m = locals()[k]
if isinstance(m, ModuleType):
if hasattr(m, "DEBUG_EMAILS"):
DEBUG_EMAILS += list(getattr(m, "DEBUG_EMAILS"))
setattr(m, "DEBUG_EMAILS", DEBUG_EMAILS)

View file

@ -1,132 +0,0 @@
from django.conf import settings
from django.db.models import Q
from ietf.ietfworkflows.streams import get_streamed_draft
from ietf.group.models import Role
def get_person_for_user(user):
try:
return user.get_profile().person()
except:
return None
def is_secretariat(user):
if not user or not user.is_authenticated():
return False
return bool(user.groups.filter(name='Secretariat'))
def is_wgchair(person):
return bool(person.wgchair_set.all())
def is_wgchairREDESIGN(person):
return bool(Role.objects.filter(name="chair", group__type="wg", group__state="active", person=person))
def is_rgchairREDESIGN(person):
return bool(Role.objects.filter(name="chair", group__type="rg", group__state="active", person=person))
def is_wgdelegate(person):
return bool(person.wgdelegate_set.all())
def is_wgdelegateREDESIGN(person):
return bool(Role.objects.filter(name="delegate", group__type="wg", group__state="active", person=person))
def is_rgdelegateREDESIGN(person):
return bool(Role.objects.filter(name="delegate", group__type="rg", group__state="active", person=person))
def is_delegate_of_stream(user, stream):
if is_secretariat(user):
return True
person = get_person_for_user(user)
return stream.check_delegate(person)
def is_delegate_of_streamREDESIGN(user, stream):
if is_secretariat(user):
return True
return user.is_authenticated() and bool(Role.objects.filter(group__acronym=stream.slug, name="delegate", person__user=user))
def is_chair_of_stream(user, stream):
if is_secretariat(user):
return True
person = get_person_for_user(user)
return stream.check_chair(person)
def is_chair_of_streamREDESIGN(user, stream):
if is_secretariat(user):
return True
if isinstance(user, basestring):
return False
return user.is_authenticated() and bool(Role.objects.filter(group__acronym=stream.slug, name="chair", person__user=user))
def is_authorized_in_draft_stream(user, draft):
if is_secretariat(user):
return True
person = get_person_for_user(user)
if not person:
return False
streamed = get_streamed_draft(draft)
if not streamed or not streamed.stream:
return False
# Check if the person is chair of the stream
if is_chair_of_stream(user, streamed.stream):
return True
# Check if the person is delegate of the stream
if is_delegate_of_stream(user, streamed.stream):
return True
# Check if the person is chair of the related group
chairs = streamed.stream.get_chairs_for_document(draft)
if chairs and person in [i.person for i in chairs]:
return True
# Check if the person is authorized by a delegate system
delegates = streamed.stream.get_delegates_for_document(draft)
return bool(person in delegates)
def is_authorized_in_draft_streamREDESIGN(user, draft):
if is_secretariat(user):
return True
from ietf.doc.models import Document
if not super(Document, draft).stream:
return False
# must be a chair or delegate of the stream group (or draft group)
group_req = Q(group__acronym=super(Document, draft).stream.slug)
if draft.group and super(Document, draft).stream.slug in ["ietf", "irtf"]:
group_req |= Q(group=draft.group)
return user.is_authenticated() and bool(Role.objects.filter(name__in=("chair", "secr", "delegate"), person__user=user).filter(group_req))
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
from ietf.liaisons.accounts import is_secretariat, get_person_for_user
is_wgdelegate = is_wgdelegateREDESIGN
is_wgchair = is_wgchairREDESIGN
is_rgdelegate = is_rgdelegateREDESIGN
is_rgchair = is_rgchairREDESIGN
is_chair_of_stream = is_chair_of_streamREDESIGN
is_delegate_of_stream = is_delegate_of_streamREDESIGN
is_authorized_in_draft_stream = is_authorized_in_draft_streamREDESIGN
def can_edit_state(user, draft):
return (is_secretariat(user) or
is_authorized_in_draft_stream(user, draft))
def can_edit_stream(user, draft):
return is_secretariat(user)
def can_adopt(user, draft):
if settings.USE_DB_REDESIGN_PROXY_CLASSES and (not draft.stream_id or draft.stream_id in ["ietf", "irtf"]) and draft.group.type_id == "individ":
person = get_person_for_user(user)
if not person:
return False
return is_wgchair(person) or is_rgchair(person) or is_wgdelegate(person) or is_rgdelegate() or is_secretariat(user)
else:
return is_secretariat(user)

View file

@ -1,13 +0,0 @@
# Required states
CALL_FOR_ADOPTION = 'Call For Adoption By WG Issued'
WG_DOCUMENT = 'WG Document'
SUBMITTED_TO_IESG = 'Submitted to IESG for Publication'
REQUIRED_STATES = (
CALL_FOR_ADOPTION,
WG_DOCUMENT,
SUBMITTED_TO_IESG,
)
# IETF Stream
IETF_STREAM = 'IETF'

View file

@ -1 +0,0 @@
/*.pyc

View file

@ -1,686 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<django-objects version="1.0">
<object pk="1" model="workflows.workflow">
<field type="CharField" name="name">Default WG Workflow</field>
<field to="workflows.state" name="initial_state" rel="ManyToOneRel">11</field>
</object>
<object pk="2" model="workflows.workflow">
<field type="CharField" name="name">IAB Workflow</field>
<field to="workflows.state" name="initial_state" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="3" model="workflows.workflow">
<field type="CharField" name="name">IRTF Workflow</field>
<field to="workflows.state" name="initial_state" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="4" model="workflows.workflow">
<field type="CharField" name="name">ISE Workflow</field>
<field to="workflows.state" name="initial_state" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="32" model="workflows.state">
<field type="CharField" name="name">Active IAB Document</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">2</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="42" model="workflows.state">
<field type="CharField" name="name">Active RG Document</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">3</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="12" model="workflows.state">
<field type="CharField" name="name">Adopted by a WG</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"><object pk="12"></object></field>
</object>
<object pk="13" model="workflows.state">
<field type="CharField" name="name">Adopted for WG Info Only</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="36" model="workflows.state">
<field type="CharField" name="name">Approved by IAB, To Be Sent to RFC Editor</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">2</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="47" model="workflows.state">
<field type="CharField" name="name">Awaiting IRSG Reviews</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">3</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="11" model="workflows.state">
<field type="CharField" name="name">Call For Adoption By WG Issued</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"><object pk="10"></object><object pk="11"></object></field>
</object>
<object pk="31" model="workflows.state">
<field type="CharField" name="name">Candidate IAB Document</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">2</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="41" model="workflows.state">
<field type="CharField" name="name">Candidate RG Document</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">3</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="35" model="workflows.state">
<field type="CharField" name="name">Community Review</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">2</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="40" model="workflows.state">
<field type="CharField" name="name">Dead IAB Document</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">2</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="53" model="workflows.state">
<field type="CharField" name="name">Dead IRTF Document</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">3</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="16" model="workflows.state">
<field type="CharField" name="name">Dead WG Document</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"><object pk="12"></object></field>
</object>
<object pk="51" model="workflows.state">
<field type="CharField" name="name">Document on Hold Based On IESG Request</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">3</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="62" model="workflows.state">
<field type="CharField" name="name">Document on Hold Based On IESG Request</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">4</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="55" model="workflows.state">
<field type="CharField" name="name">Finding Reviewers</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">4</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="34" model="workflows.state">
<field type="CharField" name="name">IAB Review</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">2</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="49" model="workflows.state">
<field type="CharField" name="name">In IESG Review</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">3</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="58" model="workflows.state">
<field type="CharField" name="name">In IESG Review</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">4</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="48" model="workflows.state">
<field type="CharField" name="name">In IRSG Poll</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">3</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="56" model="workflows.state">
<field type="CharField" name="name">In ISE Review</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">4</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="44" model="workflows.state">
<field type="CharField" name="name">In RG Last Call</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">3</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="17" model="workflows.state">
<field type="CharField" name="name">In WG Last Call</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"><object pk="12"></object><object pk="17"></object><object pk="18"></object></field>
</object>
<object pk="61" model="workflows.state">
<field type="CharField" name="name">No Longer In Independent Submission Stream</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">4</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="33" model="workflows.state">
<field type="CharField" name="name">Parked IAB Document</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">2</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="43" model="workflows.state">
<field type="CharField" name="name">Parked RG Document</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">3</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="15" model="workflows.state">
<field type="CharField" name="name">Parked WG Document</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"><object pk="12"></object></field>
</object>
<object pk="57" model="workflows.state">
<field type="CharField" name="name">Response to Review Needed</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">4</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="37" model="workflows.state">
<field type="CharField" name="name">Sent to a Different Organization for Publication</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">2</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="38" model="workflows.state">
<field type="CharField" name="name">Sent to the RFC Editor</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">2</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="59" model="workflows.state">
<field type="CharField" name="name">Sent to the RFC Editor</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">4</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="50" model="workflows.state">
<field type="CharField" name="name">Sent to the RFC Editor</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">3</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="54" model="workflows.state">
<field type="CharField" name="name">Submission Received</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">4</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="20" model="workflows.state">
<field type="CharField" name="name">Submitted to IESG for Publication</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"><object pk="12"></object></field>
</object>
<object pk="45" model="workflows.state">
<field type="CharField" name="name">Waiting for Document Shepherd</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">3</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="46" model="workflows.state">
<field type="CharField" name="name">Waiting for IRTF Chair</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">3</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"></field>
</object>
<object pk="18" model="workflows.state">
<field type="CharField" name="name">Waiting for WG Chair Go-Ahead</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"><object pk="16"></object><object pk="17"></object></field>
</object>
<object pk="19" model="workflows.state">
<field type="CharField" name="name">WG Consensus: Waiting for Write-Up</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"><object pk="15"></object></field>
</object>
<object pk="14" model="workflows.state">
<field type="CharField" name="name">WG Document</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="workflows.transition" name="transitions" rel="ManyToManyRel"><object pk="13"></object><object pk="14"></object><object pk="16"></object><object pk="17"></object></field>
</object>
<object pk="18" model="workflows.transition">
<field type="CharField" name="name">Wait for go-ahead</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="workflows.state" name="destination" rel="ManyToOneRel">18</field>
<field type="CharField" name="condition"></field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="17" model="workflows.transition">
<field type="CharField" name="name">Reach consensus</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="workflows.state" name="destination" rel="ManyToOneRel">19</field>
<field type="CharField" name="condition"></field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="10" model="workflows.transition">
<field type="CharField" name="name">Adopt</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="workflows.state" name="destination" rel="ManyToOneRel">12</field>
<field type="CharField" name="condition"></field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="11" model="workflows.transition">
<field type="CharField" name="name">Adopt for WG info only</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="workflows.state" name="destination" rel="ManyToOneRel">13</field>
<field type="CharField" name="condition"></field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="12" model="workflows.transition">
<field type="CharField" name="name">Develop</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="workflows.state" name="destination" rel="ManyToOneRel">14</field>
<field type="CharField" name="condition"></field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="13" model="workflows.transition">
<field type="CharField" name="name">Park</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="workflows.state" name="destination" rel="ManyToOneRel">15</field>
<field type="CharField" name="condition"></field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="14" model="workflows.transition">
<field type="CharField" name="name">Die</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="workflows.state" name="destination" rel="ManyToOneRel">16</field>
<field type="CharField" name="condition"></field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="15" model="workflows.transition">
<field type="CharField" name="name">Submit to IESG</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="workflows.state" name="destination" rel="ManyToOneRel">20</field>
<field type="CharField" name="condition"></field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="16" model="workflows.transition">
<field type="CharField" name="name">Raise last call</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="workflows.state" name="destination" rel="ManyToOneRel">17</field>
<field type="CharField" name="condition"></field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="31" model="ietfworkflows.annotationtag">
<field type="CharField" name="name">Revised I-D Needed</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">3</field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="29" model="ietfworkflows.annotationtag">
<field type="CharField" name="name">Shepherd Needed</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">3</field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="30" model="ietfworkflows.annotationtag">
<field type="CharField" name="name">Waiting for Dependency on Other Document</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">3</field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="26" model="ietfworkflows.annotationtag">
<field type="CharField" name="name">Revised I-D Needed</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">2</field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="27" model="ietfworkflows.annotationtag">
<field type="CharField" name="name">Document Shepherd Followup</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">2</field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="28" model="ietfworkflows.annotationtag">
<field type="CharField" name="name">Editor Needed</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">3</field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="25" model="ietfworkflows.annotationtag">
<field type="CharField" name="name">Awaiting Reviews</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">2</field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="24" model="ietfworkflows.annotationtag">
<field type="CharField" name="name">Waiting for Partner Feedback</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">2</field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="11" model="ietfworkflows.annotationtag">
<field type="CharField" name="name">Other - see Comment Log</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="23" model="ietfworkflows.annotationtag">
<field type="CharField" name="name">Editor Needed</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">2</field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="10" model="ietfworkflows.annotationtag">
<field type="CharField" name="name">Doc Shepherd Follow-Up Underway</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="9" model="ietfworkflows.annotationtag">
<field type="CharField" name="name">Revised I-D Needed - Issue raised by IESG</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="1" model="ietfworkflows.annotationtag">
<field type="CharField" name="name">Awaiting Expert Review/Resolution of Issues Raised</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="2" model="ietfworkflows.annotationtag">
<field type="CharField" name="name">Awaiting External Review/Resolution of Issues Raised</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="3" model="ietfworkflows.annotationtag">
<field type="CharField" name="name">Awaiting Merge with Other Document</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="4" model="ietfworkflows.annotationtag">
<field type="CharField" name="name">Author or Editor Needed</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="5" model="ietfworkflows.annotationtag">
<field type="CharField" name="name">Waiting for Referenced Document</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="8" model="ietfworkflows.annotationtag">
<field type="CharField" name="name">Revised I-D Needed - Issue raised by AD</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="7" model="ietfworkflows.annotationtag">
<field type="CharField" name="name">Revised I-D Needed - Issue raised by WGLC</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="6" model="ietfworkflows.annotationtag">
<field type="CharField" name="name">Waiting for Referencing Document</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">1</field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="32" model="ietfworkflows.annotationtag">
<field type="CharField" name="name">IESG Review Completed</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">3</field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="33" model="ietfworkflows.annotationtag">
<field type="CharField" name="name">Waiting for Dependency on Other Document</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">4</field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="34" model="ietfworkflows.annotationtag">
<field type="CharField" name="name">Awaiting Reviews</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">4</field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="35" model="ietfworkflows.annotationtag">
<field type="CharField" name="name">Revised I-D Needed</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">4</field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="36" model="ietfworkflows.annotationtag">
<field type="CharField" name="name">IESG Review Completed</field>
<field to="workflows.workflow" name="workflow" rel="ManyToOneRel">4</field>
<field to="permissions.permission" name="permission" rel="ManyToOneRel"><None></None></field>
</object>
<object pk="1" model="ietfworkflows.wgworkflow">
<field to="workflows.state" name="selected_states" rel="ManyToManyRel"></field>
<field to="ietfworkflows.annotationtag" name="selected_tags" rel="ManyToManyRel"></field>
</object>
<object pk="2" model="ietfworkflows.wgworkflow">
<field to="workflows.state" name="selected_states" rel="ManyToManyRel"></field>
<field to="ietfworkflows.annotationtag" name="selected_tags" rel="ManyToManyRel"></field>
</object>
<object pk="3" model="ietfworkflows.wgworkflow">
<field to="workflows.state" name="selected_states" rel="ManyToManyRel"></field>
<field to="ietfworkflows.annotationtag" name="selected_tags" rel="ManyToManyRel"></field>
</object>
<object pk="4" model="ietfworkflows.wgworkflow">
<field to="workflows.state" name="selected_states" rel="ManyToManyRel"></field>
<field to="ietfworkflows.annotationtag" name="selected_tags" rel="ManyToManyRel"></field>
</object>
<object pk="1" model="ietfworkflows.stream">
<field type="CharField" name="name">IETF</field>
<field type="CharField" name="document_group_attribute">group.ietfwg</field>
<field type="CharField" name="group_chair_attribute">chairs</field>
<field to="ietfworkflows.wgworkflow" name="workflow" rel="ManyToOneRel">1</field>
</object>
<object pk="2" model="ietfworkflows.stream">
<field type="CharField" name="name">IAB</field>
<field type="CharField" name="document_group_attribute"></field>
<field type="CharField" name="group_chair_attribute"></field>
<field to="ietfworkflows.wgworkflow" name="workflow" rel="ManyToOneRel">2</field>
</object>
<object pk="3" model="ietfworkflows.stream">
<field type="CharField" name="name">IRTF</field>
<field type="CharField" name="document_group_attribute"></field>
<field type="CharField" name="group_chair_attribute"></field>
<field to="ietfworkflows.wgworkflow" name="workflow" rel="ManyToOneRel">3</field>
</object>
<object pk="4" model="ietfworkflows.stream">
<field type="CharField" name="name">ISE</field>
<field type="CharField" name="document_group_attribute"></field>
<field type="CharField" name="group_chair_attribute"></field>
<field to="ietfworkflows.wgworkflow" name="workflow" rel="ManyToOneRel">4</field>
</object>
<object pk="1" model="ietfworkflows.statedescription">
<field to="workflows.state" name="state" rel="ManyToOneRel">11</field>
<field type="TextField" name="definition">&lt;a href="http://tools.ietf.org/html/rfc6174#section-4.2.1" target="_blank"&gt;4.2.1. Call for Adoption by WG Issued&lt;/a&gt;
The "Call for Adoption by WG Issued" state should be used to indicate
when an I-D is being considered for adoption by an IETF WG. An I-D
that is in this state is actively being considered for adoption and
has not yet achieved consensus, preference, or selection in the WG.
This state may be used to describe an I-D that someone has asked a WG
to consider for adoption, if the WG Chair has agreed with the
request. This state may also be used to identify an I-D that a WG
Chair asked an author to write specifically for consideration as a
candidate WG item [WGDTSPEC], and/or an I-D that is listed as a
'candidate draft' in the WG's charter.
Under normal conditions, it should not be possible for an I-D to be
in the "Call for Adoption by WG Issued" state in more than one
working group at the same time. This said, it is not uncommon for
authors to "shop" their I-Ds to more than one WG at a time, with the
hope of getting their documents adopted somewhere.
After this state is implemented in the Datatracker, an I-D that is in
the "Call for Adoption by WG Issued" state will not be able to be
"shopped" to any other WG without the consent of the WG Chairs and
the responsible ADs impacted by the shopping.
Note that Figure 1 includes an arc leading from this state to outside
of the WG state machine. This illustrates that some I-Ds that are
considered do not get adopted as WG drafts. An I-D that is not
adopted as a WG draft will transition out of the WG state machine and
revert back to having no stream-specific state; however, the status
change history log of the I-D will record that the I-D was previously
in the "Call for Adoption by WG Issued" state.
</field>
<field type="PositiveIntegerField" name="order">1</field>
</object>
<object pk="2" model="ietfworkflows.statedescription">
<field to="workflows.state" name="state" rel="ManyToOneRel">12</field>
<field type="TextField" name="definition">&lt;a href="http://tools.ietf.org/html/rfc6174#section-4.2.2" target="_blank"&gt;4.2.2. Adopted by a WG&lt;/a&gt;
The "Adopted by a WG" state describes an individual submission I-D
that an IETF WG has agreed to adopt as one of its WG drafts.
WG Chairs who use this state will be able to clearly indicate when
their WGs adopt individual submission I-Ds. This will facilitate the
Datatracker's ability to correctly capture "Replaces" information for
WG drafts and correct "Replaced by" information for individual
submission I-Ds that have been replaced by WG drafts.
This state is needed because the Datatracker uses the filename of an
I-D as a key to search its database for status information about the
I-D, and because the filename of a WG I-D is supposed to be different
from the filename of an individual submission I-D.
The filename of an individual submission I-D will typically be
formatted as 'draft-author-wgname-topic-nn'.
The filename of a WG document is supposed to be formatted as 'draft-
ietf-wgname-topic-nn'.
An individual I-D that is adopted by a WG may take weeks or months to
be resubmitted by the author as a new (version-00) WG draft. If the
"Adopted by a WG" state is not used, the Datatracker has no way to
determine that an I-D has been adopted until a new version of the I-D
is submitted to the WG by the author and until the I-D is approved
for posting by a WG Chair.
</field>
<field type="PositiveIntegerField" name="order">2</field>
</object>
<object pk="3" model="ietfworkflows.statedescription">
<field to="workflows.state" name="state" rel="ManyToOneRel">13</field>
<field type="TextField" name="definition">&lt;a href="http://tools.ietf.org/html/rfc6174#section-4.2.3" target="_blank"&gt;4.2.3. Adopted for WG Info Only&lt;/a&gt;
The "Adopted for WG Info Only" state describes a document that
contains useful information for the WG that adopted it, but the
document is not intended to be published as an RFC. The WG will not
actively develop the contents of the I-D or progress it for
publication as an RFC. The only purpose of the I-D is to provide
information for internal use by the WG.
</field>
<field type="PositiveIntegerField" name="order">3</field>
</object>
<object pk="4" model="ietfworkflows.statedescription">
<field to="workflows.state" name="state" rel="ManyToOneRel">14</field>
<field type="TextField" name="definition">&lt;a href="http://tools.ietf.org/html/rfc6174#section-4.2.4" target="_blank"&gt;4.2.4. WG Document&lt;/a&gt;
The "WG Document" state describes an I-D that has been adopted by an
IETF WG and is being actively developed.
A WG Chair may transition an I-D into the "WG Document" state at any
time as long as the I-D is not being considered or developed in any
other WG.
Alternatively, WG Chairs may rely upon new functionality to be added
to the Datatracker to automatically move version-00 drafts into the
"WG Document" state as described in Section 4.1.
Under normal conditions, it should not be possible for an I-D to be
in the "WG Document" state in more than one WG at a time. This said,
I-Ds may be transferred from one WG to another with the consent of
the WG Chairs and the responsible ADs.
</field>
<field type="PositiveIntegerField" name="order">4</field>
</object>
<object pk="5" model="ietfworkflows.statedescription">
<field to="workflows.state" name="state" rel="ManyToOneRel">15</field>
<field type="TextField" name="definition">&lt;a href="http://tools.ietf.org/html/rfc6174#section-4.2.5" target="_blank"&gt;4.2.5. Parked WG Document&lt;/a&gt;
A "Parked WG Document" is an I-D that has lost its author or editor,
is waiting for another document to be written or for a review to be
completed, or cannot be progressed by the working group for some
other reason.
Some of the annotation tags described in Section 4.3 may be used in
conjunction with this state to indicate why an I-D has been parked,
and/or what may need to happen for the I-D to be un-parked.
Parking a WG draft will not prevent it from expiring; however, this
state can be used to indicate why the I-D has stopped progressing in
the WG.
A "Parked WG Document" that is not expired may be transferred from
one WG to another with the consent of the WG Chairs and the
responsible ADs.
</field>
<field type="PositiveIntegerField" name="order">5</field>
</object>
<object pk="6" model="ietfworkflows.statedescription">
<field to="workflows.state" name="state" rel="ManyToOneRel">16</field>
<field type="TextField" name="definition">&lt;a href="http://tools.ietf.org/html/rfc6174#section-4.2.6" target="_blank"&gt;4.2.6. Dead WG Document&lt;/a&gt;
A "Dead WG Document" is an I-D that has been abandoned. Note that
'Dead' is not always a final state for a WG I-D. If consensus is
subsequently achieved, a "Dead WG Document" may be resurrected. A
"Dead WG Document" that is not resurrected will eventually expire.
Note that an I-D that is declared to be "Dead" in one WG and that is
not expired may be transferred to a non-dead state in another WG with
the consent of the WG Chairs and the responsible ADs.
</field>
<field type="PositiveIntegerField" name="order">6</field>
</object>
<object pk="7" model="ietfworkflows.statedescription">
<field to="workflows.state" name="state" rel="ManyToOneRel">17</field>
<field type="TextField" name="definition">&lt;a href="http://tools.ietf.org/html/rfc6174#section-4.2.7" target="_blank"&gt;4.2.7. In WG Last Call&lt;/a&gt;
A document "In WG Last Call" is an I-D for which a WG Last Call
(WGLC) has been issued and is in progress.
Note that conducting a WGLC is an optional part of the IETF WG
process, per Section 7.4 of RFC 2418 [RFC2418].
If a WG Chair decides to conduct a WGLC on an I-D, the "In WG Last
Call" state can be used to track the progress of the WGLC. The Chair
may configure the Datatracker to send a WGLC message to one or more
mailing lists when the Chair moves the I-D into this state. The WG
Chair may also be able to select a different set of mailing lists for
a different document undergoing a WGLC; some documents may deserve
coordination with other WGs.
A WG I-D in this state should remain "In WG Last Call" until the WG
Chair moves it to another state. The WG Chair may configure the
Datatracker to send an e-mail after a specified period of time to
remind or 'nudge' the Chair to conclude the WGLC and to determine the
next state for the document.
It is possible for one WGLC to lead into another WGLC for the same
document. For example, an I-D that completed a WGLC as an
"Informational" document may need another WGLC if a decision is taken
to convert the I-D into a Standards Track document.
</field>
<field type="PositiveIntegerField" name="order">7</field>
</object>
<object pk="8" model="ietfworkflows.statedescription">
<field to="workflows.state" name="state" rel="ManyToOneRel">18</field>
<field type="TextField" name="definition">&lt;a href="http://tools.ietf.org/html/rfc6174#section-4.2.8" target="_blank"&gt;4.2.8. Waiting for WG Chair Go-Ahead&lt;/a&gt;
A WG Chair may wish to place an I-D that receives a lot of comments
during a WGLC into the "Waiting for WG Chair Go-Ahead" state. This
state describes an I-D that has undergone a WGLC; however, the Chair
is not yet ready to call consensus on the document.
If comments from the WGLC need to be responded to, or a revision to
the I-D is needed, the Chair may place an I-D into this state until
all of the WGLC comments are adequately addressed and the (possibly
revised) document is in the I-D repository.
</field>
<field type="PositiveIntegerField" name="order">8</field>
</object>
<object pk="9" model="ietfworkflows.statedescription">
<field to="workflows.state" name="state" rel="ManyToOneRel">19</field>
<field type="TextField" name="definition">&lt;a href="http://tools.ietf.org/html/rfc6174#section-4.2.9" target="_blank"&gt;4.2.9. WG Consensus: Waiting for Writeup&lt;/a&gt;
A document in the "WG Consensus: Waiting for Writeup" state has
essentially completed its development within the working group, and
is nearly ready to be sent to the IESG for publication. The last
thing to be done is the preparation of a protocol writeup by a
Document Shepherd. The IESG requires that a document shepherd
writeup be completed before publication of the I-D is requested. The
IETF document shepherding process and the role of a WG Document
Shepherd is described in RFC 4858 [RFC4858]
A WG Chair may call consensus on an I-D without a formal WGLC and
transition an I-D that was in the "WG Document" state directly into
this state.
The name of this state includes the words "Waiting for Writeup"
because a good document shepherd writeup takes time to prepare.
</field>
<field type="PositiveIntegerField" name="order">9</field>
</object>
<object pk="10" model="ietfworkflows.statedescription">
<field to="workflows.state" name="state" rel="ManyToOneRel">20</field>
<field type="TextField" name="definition">&lt;a href="http://tools.ietf.org/html/rfc6174#section-4.2.10" target="_blank"&gt;4.2.10. Submitted to IESG for Publication&lt;/a&gt;
This state describes a WG document that has been submitted to the
IESG for publication and that has not been sent back to the working
group for revision.
An I-D in this state may be under review by the IESG, it may have
been approved and be in the RFC Editor's queue, or it may have been
published as an RFC. Other possibilities exist too. The document
may be "Dead" (in the IESG state machine) or in a "Do Not Publish"
state.
</field>
<field type="PositiveIntegerField" name="order">10</field>
</object>
</django-objects>

View file

@ -1,363 +0,0 @@
import datetime
from django.conf import settings
from django import forms
from django.template.loader import render_to_string
from workflows.models import State
from workflows.utils import set_workflow_for_object
from ietf.idtracker.models import PersonOrOrgInfo, IETFWG, InternetDraft
from ietf.wgchairs.accounts import get_person_for_user
from ietf.ietfworkflows.models import Stream, StreamDelegate
from ietf.ietfworkflows.utils import (get_workflow_for_draft, get_workflow_for_wg,
get_state_for_draft, get_state_by_name,
update_state, FOLLOWUP_TAG,
get_annotation_tags_for_draft,
update_tags, update_stream)
from ietf.ietfworkflows.accounts import is_secretariat
from ietf.ietfworkflows.streams import (get_stream_from_draft, get_streamed_draft,
get_stream_by_name, set_stream_for_draft)
from ietf.ietfworkflows.constants import CALL_FOR_ADOPTION, IETF_STREAM
from ietf.doc.utils import get_tags_for_stream_id
from ietf.doc.models import save_document_in_history, DocEvent, Document
from ietf.name.models import DocTagName, StreamName, RoleName
from ietf.group.models import Group, GroupStateTransitions, Role
from ietf.group.utils import save_group_in_history
from ietf.person.models import Person, Email
class StreamDraftForm(forms.Form):
can_cancel = False
template = None
def __init__(self, *args, **kwargs):
self.draft = kwargs.pop('draft', None)
self.user = kwargs.pop('user', None)
self.person = get_person_for_user(self.user)
self.workflow = get_workflow_for_draft(self.draft)
self.message = {}
super(StreamDraftForm, self).__init__(*args, **kwargs)
def get_message(self):
return self.message
def set_message(self, msg_type, msg_value):
self.message = {'type': msg_type,
'value': msg_value,
}
def __unicode__(self):
return render_to_string(self.template, {'form': self})
class NoWorkflowStateForm(StreamDraftForm):
comment = forms.CharField(widget=forms.Textarea, required=False)
weeks = forms.IntegerField(required=False)
group = forms.ChoiceField(required=False)
template = 'ietfworkflows/noworkflow_state_form.html'
def __init__(self, *args, **kwargs):
super(NoWorkflowStateForm, self).__init__(*args, **kwargs)
self.groups = None
if is_secretariat(self.user):
groups = IETFWG.objects.all().order_by('group_acronym__acronym')
else:
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
groups = IETFWG.objects.filter(type__in=["wg", "rg"], state="active", role__name__in=("chair", "secr", "delegate"), role__person__user=self.user).order_by('acronym').distinct()
else:
groups = set([i.group_acronym for i in self.person.wgchair_set.all()]).union(set([i.wg for i in self.person.wgdelegate_set.all()]))
groups = list(groups)
groups.sort(lambda x, y: cmp(x.group_acronym.acronym, y.group_acronym.acronym))
self.groups = groups
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
self.fields['group'].choices = [(i.pk, '%s - %s' % (i.acronym, i.name)) for i in self.groups]
else:
self.fields['group'].choices = [(i.pk, '%s - %s' % (i.group_acronym.acronym, i.group_acronym.name)) for i in self.groups]
def save(self):
comment = self.cleaned_data.get('comment').strip()
weeks = self.cleaned_data.get('weeks')
group = IETFWG.objects.get(pk=self.cleaned_data.get('group'))
estimated_date = None
if weeks:
now = datetime.date.today()
estimated_date = now + datetime.timedelta(weeks=weeks)
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
# do changes on real Document object instead of proxy to avoid trouble
doc = Document.objects.get(pk=self.draft.pk)
save_document_in_history(doc)
doc.time = datetime.datetime.now()
if group.type.slug == "rg":
new_stream = StreamName.objects.get(slug="irtf")
else:
new_stream = StreamName.objects.get(slug="ietf")
if doc.stream != new_stream:
e = DocEvent(type="changed_stream")
e.time = doc.time
e.by = self.user.get_profile()
e.doc = doc
e.desc = u"Changed to <b>%s</b>" % new_stream.name
if doc.stream:
e.desc += u" from %s" % doc.stream.name
e.save()
doc.stream = new_stream
if doc.group.pk != group.pk:
e = DocEvent(type="changed_group")
e.time = doc.time
e.by = self.user.get_profile()
e.doc = doc
e.desc = u"Changed group to <b>%s (%s)</b>" % (group.name, group.acronym.upper())
if doc.group.type_id != "individ":
e.desc += " from %s (%s)" % (doc.group.name, doc.group.acronym)
e.save()
doc.group_id = group.pk
doc.save()
self.draft = InternetDraft.objects.get(pk=doc.pk) # make sure proxy object is updated
else:
workflow = get_workflow_for_wg(wg)
set_workflow_for_object(self.draft, workflow)
stream = get_stream_by_name(IETF_STREAM)
streamed = get_streamed_draft(self.draft)
if not streamed:
set_stream_for_draft(self.draft, stream)
streamed = get_streamed_draft(self.draft)
streamed.stream = stream
streamed.group = wg
streamed.save()
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
from ietf.doc.models import State
if self.draft.stream_id == "irtf":
to_state = State.objects.get(used=True, slug="active", type="draft-stream-irtf")
else:
to_state = State.objects.get(used=True, slug="c-adopt", type="draft-stream-%s" % self.draft.stream_id)
else:
to_state = get_state_by_name(CALL_FOR_ADOPTION)
update_state(self.request, self.draft,
comment=comment,
person=self.person,
to_state=to_state,
added_tags=[],
removed_tags=[],
estimated_date=estimated_date)
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
if comment:
e = DocEvent(type="added_comment")
e.time = self.draft.time
e.by = self.person
e.doc_id = self.draft.pk
e.desc = comment
e.save()
class DraftTagsStateForm(StreamDraftForm):
new_state = forms.ChoiceField(label='State')
weeks = forms.IntegerField(label='Expected weeks in state',required=False)
comment = forms.CharField(widget=forms.Textarea, required=False)
tags = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple, required=False)
template = 'ietfworkflows/state_form.html'
def __init__(self, *args, **kwargs):
super(DraftTagsStateForm, self).__init__(*args, **kwargs)
self.state = get_state_for_draft(self.draft)
self.fields['new_state'].choices = self.get_states()
self.fields['new_state'].initial = self.state.pk if self.state else None
if self.draft.stream_id == 'ietf':
self.fields['new_state'].help_text = "Only select 'Submitted to IESG for Publication' to correct errors. Use the document's main page to request publication."
if self.is_bound:
for key, value in self.data.items():
if key.startswith('transition_'):
new_state = self.get_new_state(key)
if new_state:
self.data = self.data.copy()
self.data.update({'new_state': new_state.id})
if key.startswith('new_state_'): # hack to get value from submit buttons
self.data = self.data.copy()
self.data['new_state'] = key.replace('new_state_', '')
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
possible_tags = get_tags_for_stream_id(self.draft.stream_id)
if self.draft.stream_id == "ietf" and self.draft.group:
unused_tags = self.draft.group.unused_tags.values_list("slug", flat=True)
possible_tags = [t for t in possible_tags if t not in unused_tags]
self.available_tags = DocTagName.objects.filter(slug__in=possible_tags)
self.tags = self.draft.tags.filter(slug__in=possible_tags)
else:
self.available_tags = self.workflow.get_tags()
self.tags = [i.annotation_tag for i in get_annotation_tags_for_draft(self.draft)]
self.fields['tags'].choices = [(i.pk, i.name) for i in self.available_tags]
self.fields['tags'].initial = [i.pk for i in self.tags]
def get_new_state(self, key):
transition_id = key.replace('transition_', '')
transition = self.get_transitions().filter(id=transition_id)
if transition:
return transition[0].destination
return None
def get_transitions(self):
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
return []
return self.state.transitions.filter(workflow=self.workflow)
def get_next_states(self):
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
if not self.draft.stream_id:
return []
from ietf.doc.models import State
state_type = "draft-stream-%s" % self.draft.stream_id
s = self.draft.get_state(state_type)
next_states = []
if s:
next_states = s.next_states.all()
if self.draft.stream_id == "ietf" and self.draft.group:
transitions = self.draft.group.groupstatetransitions_set.filter(state=s)
if transitions:
next_states = transitions[0].next_states.all()
else:
# return the initial state
states = State.objects.filter(used=True, type=state_type).order_by('order')
if states:
next_states = states[:1]
unused = []
if self.draft.group:
unused = self.draft.group.unused_states.values_list("pk", flat=True)
return [n for n in next_states if n.pk not in unused]
return []
def get_states(self):
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
if not self.draft.stream_id:
return []
from ietf.doc.models import State
states = State.objects.filter(used=True, type="draft-stream-%s" % self.draft.stream_id)
if self.draft.stream_id == "ietf" and self.draft.group:
unused_states = self.draft.group.unused_states.values_list("pk", flat=True)
states = [s for s in states if s.pk not in unused_states]
return [(i.pk, i.name) for i in states]
return [(i.pk, i.name) for i in self.workflow.get_states()]
def save_tags(self,send_email=True):
comment = self.cleaned_data.get('comment')
new_tags = self.cleaned_data.get('tags')
set_tags = [tag for tag in self.available_tags if str(tag.pk) in new_tags and tag not in self.tags]
reset_tags = [tag for tag in self.available_tags if str(tag.pk) not in new_tags and tag in self.tags]
followup = bool([tag for tag in set_tags if tag.name == FOLLOWUP_TAG])
extra_notify = []
if followup:
try:
shepherd = self.draft.shepherd
if shepherd:
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
extra_notify = [shepherd.formatted_email()]
else:
extra_notify = ['%s <%s>' % shepherd.email()]
except PersonOrOrgInfo.DoesNotExist:
pass
if not set_tags and not reset_tags:
return
update_tags(self.request, self.draft,
comment=comment,
person=self.person,
set_tags=set_tags,
reset_tags=reset_tags,
extra_notify=extra_notify,
send_email=send_email)
def save_state(self):
comment = self.cleaned_data.get('comment')
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
from ietf.doc.models import State
state = State.objects.get(pk=self.cleaned_data.get('new_state'))
old_state = self.draft.get_state("draft-stream-%s" % self.draft.stream_id)
if state==old_state:
self.save_tags()
return
self.save_tags(False)
new_tags = self.cleaned_data.get('tags')
set_tags = [tag for tag in self.available_tags if str(tag.pk) in new_tags and tag not in self.tags]
reset_tags = [tag for tag in self.available_tags if str(tag.pk) not in new_tags and tag in self.tags]
weeks = self.cleaned_data.get('weeks')
estimated_date = None
if weeks:
now = datetime.date.today()
estimated_date = now + datetime.timedelta(weeks=weeks)
update_state(self.request, self.draft,
comment=comment,
person=self.person,
to_state=state,
estimated_date=estimated_date,
added_tags=set_tags,
removed_tags=reset_tags)
def save(self):
self.save_state()
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
comment = self.cleaned_data.get('comment').strip()
if comment:
e = DocEvent(type="added_comment")
e.time = datetime.datetime.now()
e.by = self.person
e.doc_id = self.draft.pk
e.desc = comment
e.save()
class StreamDelegatesForm(forms.Form):
email = forms.EmailField()
def __init__(self, *args, **kwargs):
self.stream = kwargs.pop('stream')
super(StreamDelegatesForm, self).__init__(*args, **kwargs)
def get_person(self, email):
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
persons = Person.objects.filter(email__address=email).distinct()
else:
persons = PersonOrOrgInfo.objects.filter(emailaddress__address=email).distinct()
if not persons:
return None
return persons[0]
def clean_email(self):
email = self.cleaned_data.get('email')
self.person = self.get_person(email)
if not self.person:
raise forms.ValidationError('There is no user with this email in the system')
return email
def save(self):
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
stream_group = Group.objects.get(acronym=self.stream.slug)
save_group_in_history(stream_group)
Role.objects.get_or_create(person=self.person,
group=stream_group,
name=RoleName.objects.get(slug="delegate"),
email=Email.objects.get(address=self.cleaned_data.get('email')))
return
StreamDelegate.objects.get_or_create(
person=self.person,
stream=self.stream)

View file

@ -1 +0,0 @@
/*.pyc

View file

@ -1,148 +0,0 @@
from south.db import db
from django.db import models
from ietf.ietfworkflows.models import *
class Migration:
def forwards(self, orm):
# Adding model 'WGWorkflow'
db.create_table('ietfworkflows_wgworkflow', (
('workflow_ptr', orm['ietfworkflows.WGWorkflow:workflow_ptr']),
))
db.send_create_signal('ietfworkflows', ['WGWorkflow'])
# Adding model 'ObjectWorkflowHistoryEntry'
db.create_table('ietfworkflows_objectworkflowhistoryentry', (
('id', orm['ietfworkflows.ObjectWorkflowHistoryEntry:id']),
('content_type', orm['ietfworkflows.ObjectWorkflowHistoryEntry:content_type']),
('content_id', orm['ietfworkflows.ObjectWorkflowHistoryEntry:content_id']),
('from_state', orm['ietfworkflows.ObjectWorkflowHistoryEntry:from_state']),
('to_state', orm['ietfworkflows.ObjectWorkflowHistoryEntry:to_state']),
('transition_date', orm['ietfworkflows.ObjectWorkflowHistoryEntry:transition_date']),
('comment', orm['ietfworkflows.ObjectWorkflowHistoryEntry:comment']),
))
db.send_create_signal('ietfworkflows', ['ObjectWorkflowHistoryEntry'])
# Adding model 'ObjectAnnotationTagHistoryEntry'
db.create_table('ietfworkflows_objectannotationtaghistoryentry', (
('id', orm['ietfworkflows.ObjectAnnotationTagHistoryEntry:id']),
('content_type', orm['ietfworkflows.ObjectAnnotationTagHistoryEntry:content_type']),
('content_id', orm['ietfworkflows.ObjectAnnotationTagHistoryEntry:content_id']),
('setted', orm['ietfworkflows.ObjectAnnotationTagHistoryEntry:setted']),
('unsetted', orm['ietfworkflows.ObjectAnnotationTagHistoryEntry:unsetted']),
('change_date', orm['ietfworkflows.ObjectAnnotationTagHistoryEntry:change_date']),
('comment', orm['ietfworkflows.ObjectAnnotationTagHistoryEntry:comment']),
))
db.send_create_signal('ietfworkflows', ['ObjectAnnotationTagHistoryEntry'])
# Adding model 'AnnotationTag'
db.create_table('ietfworkflows_annotationtag', (
('id', orm['ietfworkflows.AnnotationTag:id']),
('name', orm['ietfworkflows.AnnotationTag:name']),
('workflow', orm['ietfworkflows.AnnotationTag:workflow']),
('permission', orm['ietfworkflows.AnnotationTag:permission']),
))
db.send_create_signal('ietfworkflows', ['AnnotationTag'])
# Adding model 'AnnotationTagObjectRelation'
db.create_table('ietfworkflows_annotationtagobjectrelation', (
('id', orm['ietfworkflows.AnnotationTagObjectRelation:id']),
('content_type', orm['ietfworkflows.AnnotationTagObjectRelation:content_type']),
('content_id', orm['ietfworkflows.AnnotationTagObjectRelation:content_id']),
('annotation_tag', orm['ietfworkflows.AnnotationTagObjectRelation:annotation_tag']),
))
db.send_create_signal('ietfworkflows', ['AnnotationTagObjectRelation'])
def backwards(self, orm):
# Deleting model 'WGWorkflow'
db.delete_table('ietfworkflows_wgworkflow')
# Deleting model 'ObjectWorkflowHistoryEntry'
db.delete_table('ietfworkflows_objectworkflowhistoryentry')
# Deleting model 'ObjectAnnotationTagHistoryEntry'
db.delete_table('ietfworkflows_objectannotationtaghistoryentry')
# Deleting model 'AnnotationTag'
db.delete_table('ietfworkflows_annotationtag')
# Deleting model 'AnnotationTagObjectRelation'
db.delete_table('ietfworkflows_annotationtagobjectrelation')
models = {
'contenttypes.contenttype': {
'Meta': {'unique_together': "(('app_label', 'model'),)", 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'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'})
},
'ietfworkflows.annotationtag': {
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'permission': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['permissions.Permission']", 'null': 'True', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'annotation_tags'", 'to': "orm['workflows.Workflow']"})
},
'ietfworkflows.annotationtagobjectrelation': {
'annotation_tag': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ietfworkflows.AnnotationTag']"}),
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'annotation_tags'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'ietfworkflows.objectannotationtaghistoryentry': {
'change_date': ('django.db.models.fields.DateTimeField', [], {}),
'comment': ('django.db.models.fields.TextField', [], {}),
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'annotation_tags_history'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'setted': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'unsetted': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'})
},
'ietfworkflows.objectworkflowhistoryentry': {
'comment': ('django.db.models.fields.TextField', [], {}),
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'workflow_history'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'from_state': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'to_state': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'transition_date': ('django.db.models.fields.DateTimeField', [], {})
},
'ietfworkflows.wgworkflow': {
'workflow_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['workflows.Workflow']", 'unique': 'True', 'primary_key': 'True'})
},
'permissions.permission': {
'codename': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'content_types': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['contenttypes.ContentType']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'})
},
'workflows.state': {
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'transitions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['workflows.Transition']", 'null': 'True', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'states'", 'to': "orm['workflows.Workflow']"})
},
'workflows.transition': {
'condition': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'destination': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'destination_state'", 'null': 'True', 'to': "orm['workflows.State']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'permission': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['permissions.Permission']", 'null': 'True', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'transitions'", 'to': "orm['workflows.Workflow']"})
},
'workflows.workflow': {
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'initial_state': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'workflow_state'", 'null': 'True', 'to': "orm['workflows.State']"}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['permissions.Permission']", 'symmetrical': 'False'})
}
}
complete_apps = ['ietfworkflows']

View file

@ -1,107 +0,0 @@
from south.db import db
from django.db import models
from ietf.ietfworkflows.models import *
class Migration:
def forwards(self, orm):
# Adding ManyToManyField 'WGWorkflow.selected_tags'
db.create_table('ietfworkflows_wgworkflow_selected_tags', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('wgworkflow', models.ForeignKey(orm.WGWorkflow, null=False)),
('annotationtag', models.ForeignKey(orm.AnnotationTag, null=False))
))
# Adding ManyToManyField 'WGWorkflow.selected_states'
db.create_table('ietfworkflows_wgworkflow_selected_states', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('wgworkflow', models.ForeignKey(orm.WGWorkflow, null=False)),
('state', models.ForeignKey(orm['workflows.State'], null=False))
))
def backwards(self, orm):
# Dropping ManyToManyField 'WGWorkflow.selected_tags'
db.delete_table('ietfworkflows_wgworkflow_selected_tags')
# Dropping ManyToManyField 'WGWorkflow.selected_states'
db.delete_table('ietfworkflows_wgworkflow_selected_states')
models = {
'contenttypes.contenttype': {
'Meta': {'unique_together': "(('app_label', 'model'),)", 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'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'})
},
'ietfworkflows.annotationtag': {
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'permission': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['permissions.Permission']", 'null': 'True', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'annotation_tags'", 'to': "orm['workflows.Workflow']"})
},
'ietfworkflows.annotationtagobjectrelation': {
'annotation_tag': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ietfworkflows.AnnotationTag']"}),
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'annotation_tags'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'ietfworkflows.objectannotationtaghistoryentry': {
'change_date': ('django.db.models.fields.DateTimeField', [], {}),
'comment': ('django.db.models.fields.TextField', [], {}),
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'annotation_tags_history'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'setted': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'unsetted': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'})
},
'ietfworkflows.objectworkflowhistoryentry': {
'comment': ('django.db.models.fields.TextField', [], {}),
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'workflow_history'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'from_state': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'to_state': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'transition_date': ('django.db.models.fields.DateTimeField', [], {})
},
'ietfworkflows.wgworkflow': {
'selected_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['workflows.State']"}),
'selected_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['ietfworkflows.AnnotationTag']"}),
'workflow_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['workflows.Workflow']", 'unique': 'True', 'primary_key': 'True'})
},
'permissions.permission': {
'codename': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'content_types': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['contenttypes.ContentType']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'})
},
'workflows.state': {
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'transitions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['workflows.Transition']", 'null': 'True', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'states'", 'to': "orm['workflows.Workflow']"})
},
'workflows.transition': {
'condition': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'destination': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'destination_state'", 'null': 'True', 'to': "orm['workflows.State']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'permission': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['permissions.Permission']", 'null': 'True', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'transitions'", 'to': "orm['workflows.Workflow']"})
},
'workflows.workflow': {
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'initial_state': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'workflow_state'", 'null': 'True', 'to': "orm['workflows.State']"}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['permissions.Permission']", 'symmetrical': 'False'})
}
}
complete_apps = ['ietfworkflows']

View file

@ -1,119 +0,0 @@
from south.db import db
from django.db import models
from ietf.ietfworkflows.models import *
class Migration:
def forwards(self, orm):
# Adding field 'ObjectWorkflowHistoryEntry.person'
db.add_column('ietfworkflows_objectworkflowhistoryentry', 'person', orm['ietfworkflows.objectworkflowhistoryentry:person'])
# Adding field 'ObjectAnnotationTagHistoryEntry.person'
db.add_column('ietfworkflows_objectannotationtaghistoryentry', 'person', orm['ietfworkflows.objectannotationtaghistoryentry:person'])
def backwards(self, orm):
# Deleting field 'ObjectWorkflowHistoryEntry.person'
db.delete_column('ietfworkflows_objectworkflowhistoryentry', 'person_id')
# Deleting field 'ObjectAnnotationTagHistoryEntry.person'
db.delete_column('ietfworkflows_objectannotationtaghistoryentry', 'person_id')
models = {
'contenttypes.contenttype': {
'Meta': {'unique_together': "(('app_label', 'model'),)", 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'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'})
},
'idtracker.personororginfo': {
'Meta': {'db_table': "'person_or_org_info'"},
'address_type': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
'created_by': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}),
'date_created': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
'date_modified': ('django.db.models.fields.DateField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'first_name_key': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'last_name_key': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'middle_initial': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
'middle_initial_key': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
'modified_by': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}),
'name_prefix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
'name_suffix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
'person_or_org_tag': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'record_type': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'})
},
'ietfworkflows.annotationtag': {
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'permission': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['permissions.Permission']", 'null': 'True', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'annotation_tags'", 'to': "orm['workflows.Workflow']"})
},
'ietfworkflows.annotationtagobjectrelation': {
'annotation_tag': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ietfworkflows.AnnotationTag']"}),
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'annotation_tags'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'ietfworkflows.objectannotationtaghistoryentry': {
'change_date': ('django.db.models.fields.DateTimeField', [], {}),
'comment': ('django.db.models.fields.TextField', [], {}),
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'annotation_tags_history'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']"}),
'setted': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'unsetted': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'})
},
'ietfworkflows.objectworkflowhistoryentry': {
'comment': ('django.db.models.fields.TextField', [], {}),
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'workflow_history'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'from_state': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']"}),
'to_state': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'transition_date': ('django.db.models.fields.DateTimeField', [], {})
},
'ietfworkflows.wgworkflow': {
'selected_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['workflows.State']", 'symmetrical': 'False'}),
'selected_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['ietfworkflows.AnnotationTag']", 'symmetrical': 'False'}),
'workflow_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['workflows.Workflow']", 'unique': 'True', 'primary_key': 'True'})
},
'permissions.permission': {
'codename': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'content_types': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['contenttypes.ContentType']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'})
},
'workflows.state': {
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'transitions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['workflows.Transition']", 'null': 'True', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'states'", 'to': "orm['workflows.Workflow']"})
},
'workflows.transition': {
'condition': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'destination': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'destination_state'", 'null': 'True', 'to': "orm['workflows.State']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'permission': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['permissions.Permission']", 'null': 'True', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'transitions'", 'to': "orm['workflows.Workflow']"})
},
'workflows.workflow': {
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'initial_state': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'workflow_state'", 'null': 'True', 'to': "orm['workflows.State']"}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['permissions.Permission']", 'symmetrical': 'False'})
}
}
complete_apps = ['ietfworkflows']

View file

@ -1,132 +0,0 @@
from south.db import db
from django.db import models
from ietf.ietfworkflows.models import *
class Migration:
def forwards(self, orm):
# Adding model 'StateObjectRelationMetadata'
db.create_table('ietfworkflows_stateobjectrelationmetadata', (
('id', orm['ietfworkflows.stateobjectrelationmetadata:id']),
('relation', orm['ietfworkflows.stateobjectrelationmetadata:relation']),
('from_date', orm['ietfworkflows.stateobjectrelationmetadata:from_date']),
('estimated_date', orm['ietfworkflows.stateobjectrelationmetadata:estimated_date']),
))
db.send_create_signal('ietfworkflows', ['StateObjectRelationMetadata'])
def backwards(self, orm):
# Deleting model 'StateObjectRelationMetadata'
db.delete_table('ietfworkflows_stateobjectrelationmetadata')
models = {
'contenttypes.contenttype': {
'Meta': {'unique_together': "(('app_label', 'model'),)", 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'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'})
},
'idtracker.personororginfo': {
'Meta': {'db_table': "'person_or_org_info'"},
'address_type': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
'created_by': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}),
'date_created': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
'date_modified': ('django.db.models.fields.DateField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'first_name_key': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'last_name_key': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'middle_initial': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
'middle_initial_key': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
'modified_by': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}),
'name_prefix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
'name_suffix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
'person_or_org_tag': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'record_type': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'})
},
'ietfworkflows.annotationtag': {
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'permission': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['permissions.Permission']", 'null': 'True', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'annotation_tags'", 'to': "orm['workflows.Workflow']"})
},
'ietfworkflows.annotationtagobjectrelation': {
'annotation_tag': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ietfworkflows.AnnotationTag']"}),
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'annotation_tags'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'ietfworkflows.objectannotationtaghistoryentry': {
'change_date': ('django.db.models.fields.DateTimeField', [], {}),
'comment': ('django.db.models.fields.TextField', [], {}),
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'annotation_tags_history'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']"}),
'setted': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'unsetted': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'})
},
'ietfworkflows.objectworkflowhistoryentry': {
'comment': ('django.db.models.fields.TextField', [], {}),
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'workflow_history'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'from_state': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']"}),
'to_state': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'transition_date': ('django.db.models.fields.DateTimeField', [], {})
},
'ietfworkflows.stateobjectrelationmetadata': {
'estimated_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'from_date': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'relation': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['workflows.StateObjectRelation']"})
},
'ietfworkflows.wgworkflow': {
'selected_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['workflows.State']", 'symmetrical': 'False'}),
'selected_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['ietfworkflows.AnnotationTag']", 'symmetrical': 'False'}),
'workflow_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['workflows.Workflow']", 'unique': 'True', 'primary_key': 'True'})
},
'permissions.permission': {
'codename': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'content_types': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['contenttypes.ContentType']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'})
},
'workflows.state': {
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'transitions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['workflows.Transition']", 'null': 'True', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'states'", 'to': "orm['workflows.Workflow']"})
},
'workflows.stateobjectrelation': {
'Meta': {'unique_together': "(('content_type', 'content_id', 'state'),)"},
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'state_object'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['workflows.State']"})
},
'workflows.transition': {
'condition': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'destination': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'destination_state'", 'null': 'True', 'to': "orm['workflows.State']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'permission': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['permissions.Permission']", 'null': 'True', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'transitions'", 'to': "orm['workflows.Workflow']"})
},
'workflows.workflow': {
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'initial_state': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'workflow_state'", 'null': 'True', 'to': "orm['workflows.State']"}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['permissions.Permission']", 'symmetrical': 'False'})
}
}
complete_apps = ['ietfworkflows']

View file

@ -1,209 +0,0 @@
from south.db import db
from django.db import models
from ietf.ietfworkflows.models import *
class Migration:
def forwards(self, orm):
# Adding model 'StreamedID'
db.create_table('ietfworkflows_streamedid', (
('id', orm['ietfworkflows.streamedid:id']),
('draft', orm['ietfworkflows.streamedid:draft']),
('stream', orm['ietfworkflows.streamedid:stream']),
))
db.send_create_signal('ietfworkflows', ['StreamedID'])
# Adding model 'Stream'
db.create_table('ietfworkflows_stream', (
('id', orm['ietfworkflows.stream:id']),
('name', orm['ietfworkflows.stream:name']),
('with_groups', orm['ietfworkflows.stream:with_groups']),
('group_model', orm['ietfworkflows.stream:group_model']),
('group_chair_model', orm['ietfworkflows.stream:group_chair_model']),
('workflow', orm['ietfworkflows.stream:workflow']),
))
db.send_create_signal('ietfworkflows', ['Stream'])
def backwards(self, orm):
# Deleting model 'StreamedID'
db.delete_table('ietfworkflows_streamedid')
# Deleting model 'Stream'
db.delete_table('ietfworkflows_stream')
models = {
'contenttypes.contenttype': {
'Meta': {'unique_together': "(('app_label', 'model'),)", 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'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'})
},
'idtracker.acronym': {
'Meta': {'db_table': "'acronym'"},
'acronym': ('django.db.models.fields.CharField', [], {'max_length': '12'}),
'acronym_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name_key': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'idtracker.idintendedstatus': {
'Meta': {'db_table': "'id_intended_status'"},
'intended_status': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'status_value'"}),
'intended_status_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'idtracker.idstatus': {
'Meta': {'db_table': "'id_status'"},
'status': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'status_value'"}),
'status_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'idtracker.internetdraft': {
'Meta': {'db_table': "'internet_drafts'"},
'abstract': ('django.db.models.fields.TextField', [], {}),
'b_approve_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'b_discussion_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'b_sent_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'comments': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'dunn_sent_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'expiration_date': ('django.db.models.fields.DateField', [], {'null': 'True'}),
'expired_tombstone': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'extension_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'file_type': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'filename': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.Acronym']", 'db_column': "'group_acronym_id'"}),
'id_document_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'id_document_tag': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'intended_status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IDIntendedStatus']"}),
'last_modified_date': ('django.db.models.fields.DateField', [], {}),
'lc_changes': ('django.db.models.fields.CharField', [], {'max_length': '3', 'null': 'True'}),
'lc_expiration_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'lc_sent_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'local_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'replaced_by': ('django.db.models.fields.related.ForeignKey', ["orm['idtracker.InternetDraft']"], {'related_name': "'replaces_set'", 'null': 'True', 'db_column': "'replaced_by'", 'blank': 'True'}),
'review_by_rfc_editor': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'revision': ('django.db.models.fields.CharField', [], {'max_length': '2'}),
'revision_date': ('django.db.models.fields.DateField', [], {}),
'rfc_number': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'null': 'True', 'blank': 'True'}),
'start_date': ('django.db.models.fields.DateField', [], {}),
'status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IDStatus']"}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_column': "'id_document_name'"}),
'txt_page_count': ('django.db.models.fields.IntegerField', [], {}),
'wgreturn_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'})
},
'idtracker.personororginfo': {
'Meta': {'db_table': "'person_or_org_info'"},
'address_type': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
'created_by': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}),
'date_created': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
'date_modified': ('django.db.models.fields.DateField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'first_name_key': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'last_name_key': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'middle_initial': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
'middle_initial_key': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
'modified_by': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}),
'name_prefix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
'name_suffix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
'person_or_org_tag': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'record_type': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'})
},
'ietfworkflows.annotationtag': {
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'permission': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['permissions.Permission']", 'null': 'True', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'annotation_tags'", 'to': "orm['workflows.Workflow']"})
},
'ietfworkflows.annotationtagobjectrelation': {
'annotation_tag': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ietfworkflows.AnnotationTag']"}),
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'annotation_tags'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'ietfworkflows.objectannotationtaghistoryentry': {
'change_date': ('django.db.models.fields.DateTimeField', [], {}),
'comment': ('django.db.models.fields.TextField', [], {}),
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'annotation_tags_history'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']"}),
'setted': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'unsetted': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'})
},
'ietfworkflows.objectworkflowhistoryentry': {
'comment': ('django.db.models.fields.TextField', [], {}),
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'workflow_history'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'from_state': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']"}),
'to_state': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'transition_date': ('django.db.models.fields.DateTimeField', [], {})
},
'ietfworkflows.stateobjectrelationmetadata': {
'estimated_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'from_date': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'relation': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['workflows.StateObjectRelation']"})
},
'ietfworkflows.stream': {
'group_chair_model': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'group_model': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'with_groups': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ietfworkflows.WGWorkflow']"})
},
'ietfworkflows.streamedid': {
'draft': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['idtracker.InternetDraft']", 'unique': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ietfworkflows.Stream']"})
},
'ietfworkflows.wgworkflow': {
'selected_states': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['workflows.State']", 'null': 'True', 'blank': 'True'}),
'selected_tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['ietfworkflows.AnnotationTag']", 'null': 'True', 'blank': 'True'}),
'workflow_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['workflows.Workflow']", 'unique': 'True', 'primary_key': 'True'})
},
'permissions.permission': {
'codename': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'content_types': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['contenttypes.ContentType']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'})
},
'workflows.state': {
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'transitions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['workflows.Transition']", 'null': 'True', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'states'", 'to': "orm['workflows.Workflow']"})
},
'workflows.stateobjectrelation': {
'Meta': {'unique_together': "(('content_type', 'content_id', 'state'),)"},
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'state_object'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['workflows.State']"})
},
'workflows.transition': {
'condition': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'destination': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'destination_state'", 'null': 'True', 'to': "orm['workflows.State']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'permission': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['permissions.Permission']", 'null': 'True', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'transitions'", 'to': "orm['workflows.Workflow']"})
},
'workflows.workflow': {
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'initial_state': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'workflow_state'", 'null': 'True', 'to': "orm['workflows.State']"}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['permissions.Permission']", 'symmetrical': 'False'})
}
}
complete_apps = ['ietfworkflows']

View file

@ -1,198 +0,0 @@
from south.db import db
from django.db import models
from ietf.ietfworkflows.models import *
class Migration:
def forwards(self, orm):
# Adding field 'StreamedID.content_type'
db.add_column('ietfworkflows_streamedid', 'content_type', orm['ietfworkflows.streamedid:content_type'])
# Adding field 'StreamedID.content_id'
db.add_column('ietfworkflows_streamedid', 'content_id', orm['ietfworkflows.streamedid:content_id'])
def backwards(self, orm):
# Deleting field 'StreamedID.content_type'
db.delete_column('ietfworkflows_streamedid', 'content_type_id')
# Deleting field 'StreamedID.content_id'
db.delete_column('ietfworkflows_streamedid', 'content_id')
models = {
'contenttypes.contenttype': {
'Meta': {'unique_together': "(('app_label', 'model'),)", 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'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'})
},
'idtracker.acronym': {
'Meta': {'db_table': "'acronym'"},
'acronym': ('django.db.models.fields.CharField', [], {'max_length': '12'}),
'acronym_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name_key': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'idtracker.idintendedstatus': {
'Meta': {'db_table': "'id_intended_status'"},
'intended_status': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'status_value'"}),
'intended_status_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'idtracker.idstatus': {
'Meta': {'db_table': "'id_status'"},
'status': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'status_value'"}),
'status_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'idtracker.internetdraft': {
'Meta': {'db_table': "'internet_drafts'"},
'abstract': ('django.db.models.fields.TextField', [], {}),
'b_approve_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'b_discussion_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'b_sent_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'comments': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'dunn_sent_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'expiration_date': ('django.db.models.fields.DateField', [], {'null': 'True'}),
'expired_tombstone': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'extension_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'file_type': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'filename': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.Acronym']", 'db_column': "'group_acronym_id'"}),
'id_document_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'id_document_tag': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'intended_status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IDIntendedStatus']"}),
'last_modified_date': ('django.db.models.fields.DateField', [], {}),
'lc_changes': ('django.db.models.fields.CharField', [], {'max_length': '3', 'null': 'True'}),
'lc_expiration_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'lc_sent_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'local_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'replaced_by': ('django.db.models.fields.related.ForeignKey', ["orm['idtracker.InternetDraft']"], {'related_name': "'replaces_set'", 'null': 'True', 'db_column': "'replaced_by'", 'blank': 'True'}),
'review_by_rfc_editor': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'revision': ('django.db.models.fields.CharField', [], {'max_length': '2'}),
'revision_date': ('django.db.models.fields.DateField', [], {}),
'rfc_number': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'null': 'True', 'blank': 'True'}),
'start_date': ('django.db.models.fields.DateField', [], {}),
'status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IDStatus']"}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_column': "'id_document_name'"}),
'txt_page_count': ('django.db.models.fields.IntegerField', [], {}),
'wgreturn_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'})
},
'idtracker.personororginfo': {
'Meta': {'db_table': "'person_or_org_info'"},
'address_type': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
'created_by': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}),
'date_created': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
'date_modified': ('django.db.models.fields.DateField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'first_name_key': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'last_name_key': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'middle_initial': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
'middle_initial_key': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
'modified_by': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}),
'name_prefix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
'name_suffix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
'person_or_org_tag': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'record_type': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'})
},
'ietfworkflows.annotationtag': {
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'permission': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['permissions.Permission']", 'null': 'True', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'annotation_tags'", 'to': "orm['workflows.Workflow']"})
},
'ietfworkflows.annotationtagobjectrelation': {
'annotation_tag': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ietfworkflows.AnnotationTag']"}),
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'annotation_tags'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'ietfworkflows.objectannotationtaghistoryentry': {
'change_date': ('django.db.models.fields.DateTimeField', [], {}),
'comment': ('django.db.models.fields.TextField', [], {}),
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'annotation_tags_history'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']"}),
'setted': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'unsetted': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'})
},
'ietfworkflows.objectworkflowhistoryentry': {
'comment': ('django.db.models.fields.TextField', [], {}),
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'workflow_history'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'from_state': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']"}),
'to_state': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'transition_date': ('django.db.models.fields.DateTimeField', [], {})
},
'ietfworkflows.stateobjectrelationmetadata': {
'estimated_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'from_date': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'relation': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['workflows.StateObjectRelation']"})
},
'ietfworkflows.stream': {
'group_chair_model': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'group_model': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'with_groups': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ietfworkflows.WGWorkflow']"})
},
'ietfworkflows.streamedid': {
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'streamed_id'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'draft': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['idtracker.InternetDraft']", 'unique': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ietfworkflows.Stream']"})
},
'ietfworkflows.wgworkflow': {
'selected_states': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['workflows.State']", 'null': 'True', 'blank': 'True'}),
'selected_tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['ietfworkflows.AnnotationTag']", 'null': 'True', 'blank': 'True'}),
'workflow_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['workflows.Workflow']", 'unique': 'True', 'primary_key': 'True'})
},
'permissions.permission': {
'codename': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'content_types': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['contenttypes.ContentType']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'})
},
'workflows.state': {
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'transitions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['workflows.Transition']", 'null': 'True', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'states'", 'to': "orm['workflows.Workflow']"})
},
'workflows.stateobjectrelation': {
'Meta': {'unique_together': "(('content_type', 'content_id', 'state'),)"},
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'state_object'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['workflows.State']"})
},
'workflows.transition': {
'condition': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'destination': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'destination_state'", 'null': 'True', 'to': "orm['workflows.State']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'permission': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['permissions.Permission']", 'null': 'True', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'transitions'", 'to': "orm['workflows.Workflow']"})
},
'workflows.workflow': {
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'initial_state': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'workflow_state'", 'null': 'True', 'to': "orm['workflows.State']"}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['permissions.Permission']", 'symmetrical': 'False'})
}
}
complete_apps = ['ietfworkflows']

View file

@ -1,194 +0,0 @@
from south.db import db
from django.db import models
from ietf.ietfworkflows.models import *
class Migration:
def forwards(self, orm):
# Changing field 'StreamedID.stream'
# (to signature: django.db.models.fields.related.ForeignKey(to=orm['ietfworkflows.Stream'], null=True, blank=True))
db.alter_column('ietfworkflows_streamedid', 'stream_id', orm['ietfworkflows.streamedid:stream'])
def backwards(self, orm):
# Changing field 'StreamedID.stream'
# (to signature: django.db.models.fields.related.ForeignKey(to=orm['ietfworkflows.Stream']))
db.alter_column('ietfworkflows_streamedid', 'stream_id', orm['ietfworkflows.streamedid:stream'])
models = {
'contenttypes.contenttype': {
'Meta': {'unique_together': "(('app_label', 'model'),)", 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'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'})
},
'idtracker.acronym': {
'Meta': {'db_table': "'acronym'"},
'acronym': ('django.db.models.fields.CharField', [], {'max_length': '12'}),
'acronym_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name_key': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'idtracker.idintendedstatus': {
'Meta': {'db_table': "'id_intended_status'"},
'intended_status': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'status_value'"}),
'intended_status_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'idtracker.idstatus': {
'Meta': {'db_table': "'id_status'"},
'status': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'status_value'"}),
'status_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'idtracker.internetdraft': {
'Meta': {'db_table': "'internet_drafts'"},
'abstract': ('django.db.models.fields.TextField', [], {}),
'b_approve_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'b_discussion_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'b_sent_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'comments': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'dunn_sent_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'expiration_date': ('django.db.models.fields.DateField', [], {'null': 'True'}),
'expired_tombstone': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'extension_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'file_type': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'filename': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.Acronym']", 'db_column': "'group_acronym_id'"}),
'id_document_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'id_document_tag': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'intended_status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IDIntendedStatus']"}),
'last_modified_date': ('django.db.models.fields.DateField', [], {}),
'lc_changes': ('django.db.models.fields.CharField', [], {'max_length': '3', 'null': 'True'}),
'lc_expiration_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'lc_sent_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'local_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'replaced_by': ('django.db.models.fields.related.ForeignKey', ["orm['idtracker.InternetDraft']"], {'related_name': "'replaces_set'", 'null': 'True', 'db_column': "'replaced_by'", 'blank': 'True'}),
'review_by_rfc_editor': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'revision': ('django.db.models.fields.CharField', [], {'max_length': '2'}),
'revision_date': ('django.db.models.fields.DateField', [], {}),
'rfc_number': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'null': 'True', 'blank': 'True'}),
'start_date': ('django.db.models.fields.DateField', [], {}),
'status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IDStatus']"}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_column': "'id_document_name'"}),
'txt_page_count': ('django.db.models.fields.IntegerField', [], {}),
'wgreturn_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'})
},
'idtracker.personororginfo': {
'Meta': {'db_table': "'person_or_org_info'"},
'address_type': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
'created_by': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}),
'date_created': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
'date_modified': ('django.db.models.fields.DateField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'first_name_key': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'last_name_key': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'middle_initial': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
'middle_initial_key': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
'modified_by': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}),
'name_prefix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
'name_suffix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
'person_or_org_tag': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'record_type': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'})
},
'ietfworkflows.annotationtag': {
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'permission': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['permissions.Permission']", 'null': 'True', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'annotation_tags'", 'to': "orm['workflows.Workflow']"})
},
'ietfworkflows.annotationtagobjectrelation': {
'annotation_tag': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ietfworkflows.AnnotationTag']"}),
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'annotation_tags'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'ietfworkflows.objectannotationtaghistoryentry': {
'change_date': ('django.db.models.fields.DateTimeField', [], {}),
'comment': ('django.db.models.fields.TextField', [], {}),
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'annotation_tags_history'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']"}),
'setted': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'unsetted': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'})
},
'ietfworkflows.objectworkflowhistoryentry': {
'comment': ('django.db.models.fields.TextField', [], {}),
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'workflow_history'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'from_state': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']"}),
'to_state': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'transition_date': ('django.db.models.fields.DateTimeField', [], {})
},
'ietfworkflows.stateobjectrelationmetadata': {
'estimated_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'from_date': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'relation': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['workflows.StateObjectRelation']"})
},
'ietfworkflows.stream': {
'group_chair_model': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'group_model': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'with_groups': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ietfworkflows.WGWorkflow']"})
},
'ietfworkflows.streamedid': {
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'streamed_id'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'draft': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['idtracker.InternetDraft']", 'unique': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ietfworkflows.Stream']", 'null': 'True', 'blank': 'True'})
},
'ietfworkflows.wgworkflow': {
'selected_states': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['workflows.State']", 'null': 'True', 'blank': 'True'}),
'selected_tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['ietfworkflows.AnnotationTag']", 'null': 'True', 'blank': 'True'}),
'workflow_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['workflows.Workflow']", 'unique': 'True', 'primary_key': 'True'})
},
'permissions.permission': {
'codename': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'content_types': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['contenttypes.ContentType']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'})
},
'workflows.state': {
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'transitions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['workflows.Transition']", 'null': 'True', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'states'", 'to': "orm['workflows.Workflow']"})
},
'workflows.stateobjectrelation': {
'Meta': {'unique_together': "(('content_type', 'content_id', 'state'),)"},
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'state_object'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['workflows.State']"})
},
'workflows.transition': {
'condition': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'destination': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'destination_state'", 'null': 'True', 'to': "orm['workflows.State']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'permission': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['permissions.Permission']", 'null': 'True', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'transitions'", 'to': "orm['workflows.Workflow']"})
},
'workflows.workflow': {
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'initial_state': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'workflow_state'", 'null': 'True', 'to': "orm['workflows.State']"}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['permissions.Permission']", 'symmetrical': 'False'})
}
}
complete_apps = ['ietfworkflows']

View file

@ -1,267 +0,0 @@
from south.db import db
from django.db import models
from ietf.ietfworkflows.models import *
class Migration:
def forwards(self, orm):
# Deleting model 'objectworkflowhistoryentry'
db.delete_table('ietfworkflows_objectworkflowhistoryentry')
# Deleting model 'objectannotationtaghistoryentry'
db.delete_table('ietfworkflows_objectannotationtaghistoryentry')
# Adding model 'ObjectAnnotationTagHistoryEntry'
db.create_table('ietfworkflows_objectannotationtaghistoryentry', (
('objecthistoryentry_ptr', orm['ietfworkflows.objectannotationtaghistoryentry:objecthistoryentry_ptr']),
('setted', orm['ietfworkflows.objectannotationtaghistoryentry:setted']),
('unsetted', orm['ietfworkflows.objectannotationtaghistoryentry:unsetted']),
))
db.send_create_signal('ietfworkflows', ['ObjectAnnotationTagHistoryEntry'])
# Adding model 'ObjectHistoryEntry'
db.create_table('ietfworkflows_objecthistoryentry', (
('id', orm['ietfworkflows.objecthistoryentry:id']),
('content_type', orm['ietfworkflows.objecthistoryentry:content_type']),
('content_id', orm['ietfworkflows.objecthistoryentry:content_id']),
('date', orm['ietfworkflows.objecthistoryentry:date']),
('comment', orm['ietfworkflows.objecthistoryentry:comment']),
('person', orm['ietfworkflows.objecthistoryentry:person']),
))
db.send_create_signal('ietfworkflows', ['ObjectHistoryEntry'])
# Adding model 'ObjectStreamHistoryEntry'
db.create_table('ietfworkflows_objectstreamhistoryentry', (
('objecthistoryentry_ptr', orm['ietfworkflows.objectstreamhistoryentry:objecthistoryentry_ptr']),
('from_stream', orm['ietfworkflows.objectstreamhistoryentry:from_stream']),
('to_stream', orm['ietfworkflows.objectstreamhistoryentry:to_stream']),
))
db.send_create_signal('ietfworkflows', ['ObjectStreamHistoryEntry'])
# Adding model 'ObjectWorkflowHistoryEntry'
db.create_table('ietfworkflows_objectworkflowhistoryentry', (
('objecthistoryentry_ptr', orm['ietfworkflows.objectworkflowhistoryentry:objecthistoryentry_ptr']),
('from_state', orm['ietfworkflows.objectworkflowhistoryentry:from_state']),
('to_state', orm['ietfworkflows.objectworkflowhistoryentry:to_state']),
))
db.send_create_signal('ietfworkflows', ['ObjectWorkflowHistoryEntry'])
def backwards(self, orm):
# Deleting model 'ObjectAnnotationTagHistoryEntry'
db.delete_table('ietfworkflows_objectannotationtaghistoryentry')
# Deleting model 'ObjectHistoryEntry'
db.delete_table('ietfworkflows_objecthistoryentry')
# Deleting model 'ObjectStreamHistoryEntry'
db.delete_table('ietfworkflows_objectstreamhistoryentry')
# Deleting model 'ObjectWorkflowHistoryEntry'
db.delete_table('ietfworkflows_objectworkflowhistoryentry')
# Adding model 'objectworkflowhistoryentry'
db.create_table('ietfworkflows_objectworkflowhistoryentry', (
('comment', orm['ietfworkflows.objectworkflowhistoryentry:comment']),
('from_state', orm['ietfworkflows.objectworkflowhistoryentry:from_state']),
('to_state', orm['ietfworkflows.objectworkflowhistoryentry:to_state']),
('content_type', orm['ietfworkflows.objectworkflowhistoryentry:content_type']),
('person', orm['ietfworkflows.objectworkflowhistoryentry:person']),
('content_id', orm['ietfworkflows.objectworkflowhistoryentry:content_id']),
('id', orm['ietfworkflows.objectworkflowhistoryentry:id']),
('transition_date', orm['ietfworkflows.objectworkflowhistoryentry:transition_date']),
))
db.send_create_signal('ietfworkflows', ['objectworkflowhistoryentry'])
# Adding model 'objectannotationtaghistoryentry'
db.create_table('ietfworkflows_objectannotationtaghistoryentry', (
('comment', orm['ietfworkflows.objectannotationtaghistoryentry:comment']),
('person', orm['ietfworkflows.objectannotationtaghistoryentry:person']),
('unsetted', orm['ietfworkflows.objectannotationtaghistoryentry:unsetted']),
('content_type', orm['ietfworkflows.objectannotationtaghistoryentry:content_type']),
('change_date', orm['ietfworkflows.objectannotationtaghistoryentry:change_date']),
('setted', orm['ietfworkflows.objectannotationtaghistoryentry:setted']),
('content_id', orm['ietfworkflows.objectannotationtaghistoryentry:content_id']),
('id', orm['ietfworkflows.objectannotationtaghistoryentry:id']),
))
db.send_create_signal('ietfworkflows', ['objectannotationtaghistoryentry'])
models = {
'contenttypes.contenttype': {
'Meta': {'unique_together': "(('app_label', 'model'),)", 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'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'})
},
'idtracker.acronym': {
'Meta': {'db_table': "'acronym'"},
'acronym': ('django.db.models.fields.CharField', [], {'max_length': '12'}),
'acronym_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name_key': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'idtracker.idintendedstatus': {
'Meta': {'db_table': "'id_intended_status'"},
'intended_status': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'status_value'"}),
'intended_status_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'idtracker.idstatus': {
'Meta': {'db_table': "'id_status'"},
'status': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_column': "'status_value'"}),
'status_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'idtracker.internetdraft': {
'Meta': {'db_table': "'internet_drafts'"},
'abstract': ('django.db.models.fields.TextField', [], {}),
'b_approve_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'b_discussion_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'b_sent_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'comments': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'dunn_sent_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'expiration_date': ('django.db.models.fields.DateField', [], {'null': 'True'}),
'expired_tombstone': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'extension_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'file_type': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'filename': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.Acronym']", 'db_column': "'group_acronym_id'"}),
'id_document_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'id_document_tag': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'intended_status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IDIntendedStatus']"}),
'last_modified_date': ('django.db.models.fields.DateField', [], {}),
'lc_changes': ('django.db.models.fields.CharField', [], {'max_length': '3', 'null': 'True'}),
'lc_expiration_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'lc_sent_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'local_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'replaced_by': ('django.db.models.fields.related.ForeignKey', ["orm['idtracker.InternetDraft']"], {'related_name': "'replaces_set'", 'null': 'True', 'db_column': "'replaced_by'", 'blank': 'True'}),
'review_by_rfc_editor': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'revision': ('django.db.models.fields.CharField', [], {'max_length': '2'}),
'revision_date': ('django.db.models.fields.DateField', [], {}),
'rfc_number': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'null': 'True', 'blank': 'True'}),
'start_date': ('django.db.models.fields.DateField', [], {}),
'status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.IDStatus']"}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_column': "'id_document_name'"}),
'txt_page_count': ('django.db.models.fields.IntegerField', [], {}),
'wgreturn_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'})
},
'idtracker.personororginfo': {
'Meta': {'db_table': "'person_or_org_info'"},
'address_type': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
'created_by': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}),
'date_created': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
'date_modified': ('django.db.models.fields.DateField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'first_name_key': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'last_name_key': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'middle_initial': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
'middle_initial_key': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
'modified_by': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}),
'name_prefix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
'name_suffix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
'person_or_org_tag': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'record_type': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'})
},
'ietfworkflows.annotationtag': {
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'permission': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['permissions.Permission']", 'null': 'True', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'annotation_tags'", 'to': "orm['workflows.Workflow']"})
},
'ietfworkflows.annotationtagobjectrelation': {
'annotation_tag': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ietfworkflows.AnnotationTag']"}),
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'annotation_tags'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'ietfworkflows.objectannotationtaghistoryentry': {
'objecthistoryentry_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['ietfworkflows.ObjectHistoryEntry']", 'unique': 'True', 'primary_key': 'True'}),
'setted': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'unsetted': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'})
},
'ietfworkflows.objecthistoryentry': {
'comment': ('django.db.models.fields.TextField', [], {}),
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'workflow_history'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']"})
},
'ietfworkflows.objectstreamhistoryentry': {
'from_stream': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'objecthistoryentry_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['ietfworkflows.ObjectHistoryEntry']", 'unique': 'True', 'primary_key': 'True'}),
'to_stream': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'})
},
'ietfworkflows.objectworkflowhistoryentry': {
'from_state': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'objecthistoryentry_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['ietfworkflows.ObjectHistoryEntry']", 'unique': 'True', 'primary_key': 'True'}),
'to_state': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'ietfworkflows.stateobjectrelationmetadata': {
'estimated_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'from_date': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'relation': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['workflows.StateObjectRelation']"})
},
'ietfworkflows.stream': {
'group_chair_model': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'group_model': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'with_groups': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ietfworkflows.WGWorkflow']"})
},
'ietfworkflows.streamedid': {
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'streamed_id'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'draft': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['idtracker.InternetDraft']", 'unique': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ietfworkflows.Stream']", 'null': 'True', 'blank': 'True'})
},
'ietfworkflows.wgworkflow': {
'selected_states': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['workflows.State']", 'null': 'True', 'blank': 'True'}),
'selected_tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['ietfworkflows.AnnotationTag']", 'null': 'True', 'blank': 'True'}),
'workflow_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['workflows.Workflow']", 'unique': 'True', 'primary_key': 'True'})
},
'permissions.permission': {
'codename': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'content_types': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['contenttypes.ContentType']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'})
},
'workflows.state': {
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'transitions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['workflows.Transition']", 'null': 'True', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'states'", 'to': "orm['workflows.Workflow']"})
},
'workflows.stateobjectrelation': {
'Meta': {'unique_together': "(('content_type', 'content_id', 'state'),)"},
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'state_object'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['workflows.State']"})
},
'workflows.transition': {
'condition': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'destination': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'destination_state'", 'null': 'True', 'to': "orm['workflows.State']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'permission': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['permissions.Permission']", 'null': 'True', 'blank': 'True'}),
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'transitions'", 'to': "orm['workflows.Workflow']"})
},
'workflows.workflow': {
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'initial_state': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'workflow_state'", 'null': 'True', 'to': "orm['workflows.State']"}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['permissions.Permission']", 'symmetrical': 'False'})
}
}
complete_apps = ['ietfworkflows']

Some files were not shown because too many files have changed in this diff Show more