From 2ab52d956780bdf8326d76e5f63ae1a2d817c7a9 Mon Sep 17 00:00:00 2001 From: Ole Laursen Date: Tue, 20 Mar 2012 12:05:41 +0000 Subject: [PATCH 01/10] Defer import of get_stream_from_draft to kill import loop that prevents bin/expire-ids from running. - Legacy-Id: 4142 --- ietf/idrfc/mails.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ietf/idrfc/mails.py b/ietf/idrfc/mails.py index 19592b138..4b7bcb78f 100644 --- a/ietf/idrfc/mails.py +++ b/ietf/idrfc/mails.py @@ -11,8 +11,6 @@ from django.core.urlresolvers import reverse as urlreverse from ietf.utils.mail import send_mail, send_mail_text from ietf.idtracker.models import * from ietf.ipr.search import iprs_from_docs -from ietf.ietfworkflows.streams import (get_stream_from_draft) -from ietf.ietfworkflows.models import (Stream) from ietf.doc.models import WriteupDocEvent, BallotPositionDocEvent, LastCallDocEvent, DocAlias from ietf.person.models import Person from ietf.group.models import Group @@ -258,7 +256,8 @@ def generate_approval_mail_rfc_editor(request, doc): status = full_status.replace("a ", "").replace("an ", "") disapproved = doc.idinternal.cur_state_id in IDState.DO_NOT_PUBLISH_STATES doc_type = "RFC" if type(doc) == Rfc else "Internet Draft" - + + from ietf.ietfworkflows.streams import get_stream_from_draft stream = get_stream_from_draft(doc) to = ", ".join([u"%s <%s>" % x.email() for x in stream.get_chairs_for_document(doc) ]) if stream.name == "IRTF": From fb71294b99dec60a8a6fb6b4897c8cedf669cad6 Mon Sep 17 00:00:00 2001 From: Ole Laursen Date: Wed, 21 Mar 2012 11:08:16 +0000 Subject: [PATCH 02/10] Only show RFC documents that are in state RFC, this prevents documents with an RFC DocAlias but not the right state from being displayed as RFCs (as in issue #815). Displaying them as RFCs doesn't work properly as most of the wrapper currently assumes the RFC state. - Legacy-Id: 4151 --- ietf/idrfc/views_doc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ietf/idrfc/views_doc.py b/ietf/idrfc/views_doc.py index b6cf8df58..e6c4aab47 100644 --- a/ietf/idrfc/views_doc.py +++ b/ietf/idrfc/views_doc.py @@ -84,7 +84,7 @@ def include_text(request): return include_text def document_main_rfc(request, rfc_number, tab): - rfci = get_object_or_404(RfcIndex, rfc_number=rfc_number) + rfci = get_object_or_404(RfcIndex, rfc_number=rfc_number, states__type="draft", states__slug="rfc") rfci.viewing_as_rfc = True doc = RfcWrapper(rfci) From 59aedbe937172382aefb3c59748604fc2a875c4a Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Wed, 21 Mar 2012 13:12:38 +0000 Subject: [PATCH 03/10] The RFC Queue import has been broken by the introduction of '*R' suffices on some states. Ignore those for now; find out the semantics of this from the RFC editor and fix accordingly. - Legacy-Id: 4152 --- ietf/idrfc/mirror_rfc_editor_queue.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/ietf/idrfc/mirror_rfc_editor_queue.py b/ietf/idrfc/mirror_rfc_editor_queue.py index af030f54d..a3912e58f 100644 --- a/ietf/idrfc/mirror_rfc_editor_queue.py +++ b/ietf/idrfc/mirror_rfc_editor_queue.py @@ -231,7 +231,7 @@ def insert_into_databaseREDESIGN(drafts, refs): from ietf.name.models import DocTagName tags = get_rfc_tag_mapping() - states = get_rfc_state_mapping() + state_map = get_rfc_state_mapping() rfc_editor_tags = tags.values() @@ -242,20 +242,25 @@ def insert_into_databaseREDESIGN(drafts, refs): log("inserting new data...") - for name, date_received, state, stream_id in drafts: + for name, date_received, state_info, stream_id in drafts: try: d = Document.objects.get(name=name) except Document.DoesNotExist: log("unknown document %s" % name) continue - s = state.split(" ") - if s: + state_list = state_info.split(" ") + if state_list: + state = state_list[0] + # For now, ignore the '*R...' that's appeared for some states. + # FIXME : see if we need to add some refinement for this. + if '*' in state: + state = state.split("*")[0] # first is state - d.set_state(states[s[0]]) + d.set_state(state_map[state]) # remainding are tags - for x in s[1:]: + for x in state_list[1:]: d.tags.add(tags[x]) if settings.USE_DB_REDESIGN_PROXY_CLASSES: From 0dd2563b222666616a0587c805c60db403f10714 Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Wed, 21 Mar 2012 14:20:29 +0000 Subject: [PATCH 04/10] Tweak the admin interface for Documents a bit. - Legacy-Id: 4153 --- ietf/doc/admin.py | 5 +++-- ietf/doc/models.py | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ietf/doc/admin.py b/ietf/doc/admin.py index ddc721e11..88c341a0e 100644 --- a/ietf/doc/admin.py +++ b/ietf/doc/admin.py @@ -111,14 +111,15 @@ class DocAliasAdmin(admin.ModelAdmin): list_display = [ 'name', 'document_link', ] search_fields = [ 'name', 'document__name', ] raw_id_fields = ['document'] - document_link = admin_link("document") admin.site.register(DocAlias, DocAliasAdmin) # events class DocEventAdmin(admin.ModelAdmin): - list_display = ["doc", "type", "by", "time"] + def rev(obj): + return obj.doc.rev + list_display = ["doc", "type", "rev", "by", "time"] search_fields = ["doc__name", "by__name"] raw_id_fields = ["doc", "by"] diff --git a/ietf/doc/models.py b/ietf/doc/models.py index 7693a4671..52afb5dba 100644 --- a/ietf/doc/models.py +++ b/ietf/doc/models.py @@ -7,6 +7,7 @@ from django.conf import settings from ietf.group.models import * from ietf.name.models import * from ietf.person.models import Email, Person +from ietf.utils.admin import admin_link import datetime, os @@ -266,6 +267,7 @@ class DocAlias(models.Model): name = models.CharField(max_length=255, db_index=True) def __unicode__(self): return "%s-->%s" % (self.name, self.document.name) + document_link = admin_link("document") class Meta: verbose_name = "document alias" verbose_name_plural = "document aliases" From 8e82213b57bc28e3f3e9cf30b167e64d2aeda972 Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Wed, 21 Mar 2012 14:23:09 +0000 Subject: [PATCH 05/10] Correct the cutoff hour to 00 to get the correct reopening time -- was 24 hours too late with the '24' value. FIXME: Refactory the cutoff calculations and display, puttting display text in the template, and using datetime objects consistently for calculations and to pass to template. - Legacy-Id: 4154 --- ietf/settings.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ietf/settings.py b/ietf/settings.py index 94e82b569..2c69d5281 100644 --- a/ietf/settings.py +++ b/ietf/settings.py @@ -233,9 +233,9 @@ IDSUBMIT_ANNOUNCE_FROM_EMAIL = 'internet-drafts@ietf.org' IDSUBMIT_ANNOUNCE_LIST_EMAIL = 'i-d-announce@ietf.org' # Days from meeting to cut off dates on submit -FIRST_CUTOFF_DAYS = 20 -SECOND_CUTOFF_DAYS = 13 -CUTOFF_HOUR = 24 # midnight UTC +FIRST_CUTOFF_DAYS = 19 +SECOND_CUTOFF_DAYS = 12 +CUTOFF_HOUR = 00 # midnight UTC SUBMISSION_START_DAYS = -90 SUBMISSION_CUTOFF_DAYS = 33 SUBMISSION_CORRECTION_DAYS = 52 From 896c1272c8d3f626fcd9abd38740c5254632cd21 Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Wed, 21 Mar 2012 14:24:37 +0000 Subject: [PATCH 06/10] Indicate UTC on passed cut-off time and reopening time. - Legacy-Id: 4155 --- ietf/submit/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ietf/submit/forms.py b/ietf/submit/forms.py index 3f8efc91b..e2878f19b 100644 --- a/ietf/submit/forms.py +++ b/ietf/submit/forms.py @@ -66,7 +66,7 @@ class UploadForm(forms.Form): self.cutoff_warning = 'The pre-meeting cutoff date for new documents (i.e., version -00 Internet-Drafts) was %s at %02sh UTC. You will not be able to submit a new document until %s, at %02sh UTC.
The I-D submission tool will be shut down at %02sh UTC today, and reopened at %02sh UTC on %s' % (first_cut_off, settings.CUTOFF_HOUR, ietf_monday, settings.CUTOFF_HOUR, settings.CUTOFF_HOUR, settings.CUTOFF_HOUR, ietf_monday) self.in_first_cut_off = True else: # Completely shut down of the tool - self.cutoff_warning = 'The cut off time for the I-D submission was %02sh, %s.
The I-D submission tool will be reopened at %02sh, %s' % (settings.CUTOFF_HOUR, second_cut_off, settings.CUTOFF_HOUR, ietf_monday) + self.cutoff_warning = 'The cut off time for the I-D submission was %02dh UTC, %s.
The I-D submission tool will be reopened at %02dh UTC, %s.' % (settings.CUTOFF_HOUR, second_cut_off, settings.CUTOFF_HOUR, ietf_monday) self.shutdown = True def __unicode__(self): From 56b8f3e738baefd1cc72223e22546fe20d66360e Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Wed, 21 Mar 2012 14:26:06 +0000 Subject: [PATCH 07/10] Update forms and helptexts associated with user.username admin to consistently show our tweaked length of 64 characters. - Legacy-Id: 4156 --- django/contrib/auth/forms.py | 10 +++++----- django/contrib/auth/models.py | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/django/contrib/auth/forms.py b/django/contrib/auth/forms.py index ee09a626a..711dba529 100644 --- a/django/contrib/auth/forms.py +++ b/django/contrib/auth/forms.py @@ -11,8 +11,8 @@ class UserCreationForm(forms.ModelForm): """ A form that creates a user, with no privileges, from the given username and password. """ - username = forms.RegexField(label=_("Username"), max_length=30, regex=r'^[\w.@+-]+$', - help_text = _("Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only."), + username = forms.RegexField(label=_("Username"), max_length=64, regex=r'^[\w.@+-]+$', + help_text = _("Required. 64 characters or fewer. Letters, digits and @/./+/-/_ only."), error_messages = {'invalid': _("This value may contain only letters, numbers and @/./+/-/_ characters.")}) password1 = forms.CharField(label=_("Password"), widget=forms.PasswordInput) password2 = forms.CharField(label=_("Password confirmation"), widget=forms.PasswordInput, @@ -45,8 +45,8 @@ class UserCreationForm(forms.ModelForm): return user class UserChangeForm(forms.ModelForm): - username = forms.RegexField(label=_("Username"), max_length=30, regex=r'^[\w.@+-]+$', - help_text = _("Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only."), + username = forms.RegexField(label=_("Username"), max_length=64, regex=r'^[\w.@+-]+$', + help_text = _("Required. 64 characters or fewer. Letters, digits and @/./+/-/_ only."), error_messages = {'invalid': _("This value may contain only letters, numbers and @/./+/-/_ characters.")}) class Meta: @@ -63,7 +63,7 @@ class AuthenticationForm(forms.Form): Base class for authenticating users. Extend this to get a form that accepts username/password logins. """ - username = forms.CharField(label=_("Username"), max_length=30) + username = forms.CharField(label=_("Username"), max_length=64) password = forms.CharField(label=_("Password"), widget=forms.PasswordInput) def __init__(self, request=None, *args, **kwargs): diff --git a/django/contrib/auth/models.py b/django/contrib/auth/models.py index ed5349453..e3e947700 100644 --- a/django/contrib/auth/models.py +++ b/django/contrib/auth/models.py @@ -189,7 +189,7 @@ class User(models.Model): Username and password are required. Other fields are optional. """ - username = models.CharField(_('username'), max_length=64, unique=True, help_text=_("Required. 30 characters or fewer. Letters, numbers and @/./+/-/_ characters")) + username = models.CharField(_('username'), max_length=64, unique=True, help_text=_("Required. 64 characters or fewer. Letters, numbers and @/./+/-/_ characters")) first_name = models.CharField(_('first name'), max_length=30, blank=True) last_name = models.CharField(_('last name'), max_length=30, blank=True) email = models.EmailField(_('e-mail address'), blank=True) From ca1148ab67152de8c39fb8288bad3cc1a0daef5e Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Wed, 21 Mar 2012 14:27:32 +0000 Subject: [PATCH 08/10] Python 2.6 (used in production) doesn't have the total_seconds() method on datetime.timedelta -- use a module function instead. - Legacy-Id: 4157 --- ietf/idrfc/mirror_rfc_index.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ietf/idrfc/mirror_rfc_index.py b/ietf/idrfc/mirror_rfc_index.py index cca52f658..afb81cec0 100644 --- a/ietf/idrfc/mirror_rfc_index.py +++ b/ietf/idrfc/mirror_rfc_index.py @@ -53,6 +53,10 @@ def log(line): else: log_data += line + "\n" +# python before 2.7 doesn't have the total_seconds method on datetime.timedelta. +def total_seconds(td): + return (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6 + def parse(response): def getChildText(parentNode, tagName): for node in parentNode.childNodes: @@ -262,7 +266,7 @@ def insert_to_databaseREDESIGN(data): if abs(pubdate - synthesized) > timedelta(days=60): synthesized = pubdate else: - direction = -1 if (pubdate - synthesized).total_seconds() < 0 else +1 + direction = -1 if total_seconds(pubdate - synthesized) < 0 else +1 while synthesized.month != pubdate.month or synthesized.year != pubdate.year: synthesized += timedelta(days=direction) e.time = synthesized From 6eb2e7c78f561d960c40516c32616ec55441689d Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Thu, 22 Mar 2012 13:40:38 +0000 Subject: [PATCH 09/10] Avoid complications from trying to save user login time when running with readonly access to the database. - Legacy-Id: 4160 --- django/contrib/auth/__init__.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/django/contrib/auth/__init__.py b/django/contrib/auth/__init__.py index 9d24cc4f9..5244f5619 100644 --- a/django/contrib/auth/__init__.py +++ b/django/contrib/auth/__init__.py @@ -64,11 +64,15 @@ def login(request, user): Persist a user id and a backend in the request. This way a user doesn't have to reauthenticate on every request. """ + from MySQLdb import OperationalError if user is None: user = request.user # TODO: It would be nice to support different login methods, like signed cookies. user.last_login = datetime.datetime.now() - user.save() + try: + user.save() + except OperationalError: + pass if SESSION_KEY in request.session: if request.session[SESSION_KEY] != user.id: From 58f50b7ef2d038312d3896a2221f2714449cb17c Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Thu, 22 Mar 2012 13:44:54 +0000 Subject: [PATCH 10/10] Don't overwrite possible manual changes to existing name table entries when using name() to create/fetch name entries. - Legacy-Id: 4161 --- ietf/name/utils.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/ietf/name/utils.py b/ietf/name/utils.py index 6480c8773..25b85ba4f 100644 --- a/ietf/name/utils.py +++ b/ietf/name/utils.py @@ -1,10 +1,11 @@ def name(name_class, slug, name, desc="", order=0, **kwargs): # create if it doesn't exist, set name and desc - obj, _ = name_class.objects.get_or_create(slug=slug) - obj.name = name - obj.desc = desc - obj.order = order - for k, v in kwargs.iteritems(): - setattr(obj, k, v) - obj.save() + obj, created = name_class.objects.get_or_create(slug=slug) + if created: + obj.name = name + obj.desc = desc + obj.order = order + for k, v in kwargs.iteritems(): + setattr(obj, k, v) + obj.save() return obj