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: 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) 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" 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": 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: 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 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) 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 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 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):