diff --git a/.gitignore b/.gitignore index fc1b23833..77d367a65 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ /.settings /.tmp /.factoryboy_random_state +/attic /bin /etc /ghostdriver.log diff --git a/bin/add-old-drafts-from-archive.py b/bin/add-old-drafts-from-archive.py index 195501a26..d53ab32a7 100755 --- a/bin/add-old-drafts-from-archive.py +++ b/bin/add-old-drafts-from-archive.py @@ -1,4 +1,5 @@ #!/usr/bin/env python +# Copyright The IETF Trust 2017-2019, All Rights Reserved import datetime import os @@ -79,7 +80,7 @@ for name in sorted(names): words=draft.get_wordcount(), expires=time+datetime.timedelta(settings.INTERNET_DRAFT_DAYS_TO_EXPIRE), ) - doc.docalias_set.create(name=doc.name) + DocAlias.objects.create(name=doc.name).docs.add(doc) doc.states.add(expired) # update authors authors = [] diff --git a/ietf/community/migrations/0003_add_communitylist_docs2_m2m.py b/ietf/community/migrations/0003_add_communitylist_docs2_m2m.py new file mode 100644 index 000000000..6ab7a26c7 --- /dev/null +++ b/ietf/community/migrations/0003_add_communitylist_docs2_m2m.py @@ -0,0 +1,44 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-21 14:23 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('community', '0002_auto_20180220_1052'), + ] + + operations = [ + migrations.CreateModel( + name='CommunityListDocs', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('communitylist', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='community.CommunityList')), + ('document', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field=b'id')), + ], + ), + migrations.AddField( + model_name='communitylist', + name='added_docs2', + field=models.ManyToManyField(related_name='communitylists', through='community.CommunityListDocs', to='doc.Document'), + ), + migrations.CreateModel( + name='SearchRuleDocs', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('document', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field=b'id')), + ('searchrule', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='community.SearchRule')), + ], + ), + migrations.AddField( + model_name='searchrule', + name='name_contains_index2', + field=models.ManyToManyField(related_name='searchrules', through='community.SearchRuleDocs', to='doc.Document'), + ), + ] diff --git a/ietf/community/migrations/0004_set_document_m2m_keys.py b/ietf/community/migrations/0004_set_document_m2m_keys.py new file mode 100644 index 000000000..2c2db4d13 --- /dev/null +++ b/ietf/community/migrations/0004_set_document_m2m_keys.py @@ -0,0 +1,56 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-21 14:27 +from __future__ import unicode_literals + +import sys + +from tqdm import tqdm + +from django.db import migrations + + +def forward(apps, schema_editor): + + Document = apps.get_model('doc','Document') + CommunityList = apps.get_model('community', 'CommunityList') + CommunityListDocs = apps.get_model('community', 'CommunityListDocs') + SearchRule = apps.get_model('community', 'SearchRule') + SearchRuleDocs = apps.get_model('community', 'SearchRuleDocs') + + # Document id fixup ------------------------------------------------------------ + + objs = Document.objects.in_bulk() + nameid = { o.name: o.id for id, o in objs.iteritems() } + + sys.stderr.write('\n') + + sys.stderr.write(' %s.%s:\n' % (CommunityList.__name__, 'added_docs')) + count = 0 + for l in tqdm(CommunityList.objects.all()): + for d in l.added_docs.all(): + count += 1 + CommunityListDocs.objects.get_or_create(communitylist=l, document_id=nameid[d.name]) + sys.stderr.write(' %s CommunityListDocs objects created\n' % (count, )) + + sys.stderr.write(' %s.%s:\n' % (SearchRule.__name__, 'name_contains_index')) + count = 0 + for r in tqdm(SearchRule.objects.all()): + for d in r.name_contains_index.all(): + count += 1 + SearchRuleDocs.objects.get_or_create(searchrule=r, document_id=nameid[d.name]) + sys.stderr.write(' %s SearchRuleDocs objects created\n' % (count, )) + +def reverse(apps, schema_editor): + pass + +class Migration(migrations.Migration): + + dependencies = [ + ('community', '0003_add_communitylist_docs2_m2m'), + ('doc', '0014_set_document_docalias_id'), + ] + + operations = [ + migrations.RunPython(forward, reverse), + ] diff --git a/ietf/community/migrations/0005_1_del_docs_m2m_table.py b/ietf/community/migrations/0005_1_del_docs_m2m_table.py new file mode 100644 index 000000000..68afc2e9f --- /dev/null +++ b/ietf/community/migrations/0005_1_del_docs_m2m_table.py @@ -0,0 +1,32 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-22 08:15 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('community', '0004_set_document_m2m_keys'), + ] + + # The implementation of AlterField in Django 1.11 applies + # 'ALTER TABLE MODIFY ...;' in order to fix foregn keys + # to the altered field, but as it seems does _not_ fix up m2m + # intermediary tables in an equivalent manner, so here we remove and + # then recreate the m2m tables so they will have the appropriate field + # types. + + operations = [ + # Remove fields + migrations.RemoveField( + model_name='communitylist', + name='added_docs', + ), + migrations.RemoveField( + model_name='searchrule', + name='name_contains_index', + ), + ] diff --git a/ietf/community/migrations/0005_2_add_docs_m2m_table.py b/ietf/community/migrations/0005_2_add_docs_m2m_table.py new file mode 100644 index 000000000..9e0438702 --- /dev/null +++ b/ietf/community/migrations/0005_2_add_docs_m2m_table.py @@ -0,0 +1,34 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-22 08:15 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('community', '0005_1_del_docs_m2m_table'), + ] + + # The implementation of AlterField in Django 1.11 applies + # 'ALTER TABLE
MODIFY ...;' in order to fix foregn keys + # to the altered field, but as it seems does _not_ fix up m2m + # intermediary tables in an equivalent manner, so here we remove and + # then recreate the m2m tables so they will have the appropriate field + # types. + + operations = [ + # Add fields back (will create the m2m tables with the right field types) + migrations.AddField( + model_name='communitylist', + name='added_docs', + field=models.ManyToManyField(to='doc.Document'), + ), + migrations.AddField( + model_name='searchrule', + name='name_contains_index', + field=models.ManyToManyField(to='doc.Document'), + ), + ] diff --git a/ietf/community/migrations/0006_copy_docs_m2m_table.py b/ietf/community/migrations/0006_copy_docs_m2m_table.py new file mode 100644 index 000000000..7d0f76803 --- /dev/null +++ b/ietf/community/migrations/0006_copy_docs_m2m_table.py @@ -0,0 +1,57 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-27 05:56 +from __future__ import unicode_literals + +from django.db import migrations + +import sys, time + +from tqdm import tqdm + + +def forward(apps, schema_editor): + + CommunityList = apps.get_model('community', 'CommunityList') + CommunityListDocs = apps.get_model('community', 'CommunityListDocs') + SearchRule = apps.get_model('community', 'SearchRule') + SearchRuleDocs = apps.get_model('community', 'SearchRuleDocs') + + # Document id fixup ------------------------------------------------------------ + + + sys.stderr.write('\n') + + sys.stderr.write(' %s.%s:\n' % (CommunityList.__name__, 'added_docs')) + for l in tqdm(CommunityList.objects.all()): + l.added_docs.set([ d.document for d in CommunityListDocs.objects.filter(communitylist=l) ]) + + sys.stderr.write(' %s.%s:\n' % (SearchRule.__name__, 'name_contains_index')) + for r in tqdm(SearchRule.objects.all()): + r.name_contains_index.set([ d.document for d in SearchRuleDocs.objects.filter(searchrule=r) ]) + +def reverse(apps, schema_editor): + pass + +def timestamp(apps, schema_editor): + sys.stderr.write('\n %s' % time.strftime('%Y-%m-%d %H:%M:%S')) + +class Migration(migrations.Migration): + + dependencies = [ + ('community', '0005_2_add_docs_m2m_table'), + ] + + operations = [ + #migrations.RunPython(forward, reverse), + # Alternative: + migrations.RunPython(timestamp, timestamp), + migrations.RunSQL( + "INSERT INTO community_communitylist_added_docs SELECT * FROM community_communitylistdocs;", + ""), + migrations.RunPython(timestamp, timestamp), + migrations.RunSQL( + "INSERT INTO community_searchrule_name_contains_index SELECT * FROM community_searchruledocs;", + ""), + migrations.RunPython(timestamp, timestamp), + ] diff --git a/ietf/community/migrations/0007_remove_docs2_m2m.py b/ietf/community/migrations/0007_remove_docs2_m2m.py new file mode 100644 index 000000000..9687aa3ad --- /dev/null +++ b/ietf/community/migrations/0007_remove_docs2_m2m.py @@ -0,0 +1,46 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-30 03:06 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('community', '0006_copy_docs_m2m_table'), + ] + + operations = [ + migrations.RemoveField( + model_name='communitylistdocs', + name='communitylist', + ), + migrations.RemoveField( + model_name='communitylistdocs', + name='document', + ), + migrations.RemoveField( + model_name='searchruledocs', + name='document', + ), + migrations.RemoveField( + model_name='searchruledocs', + name='searchrule', + ), + migrations.RemoveField( + model_name='communitylist', + name='added_docs2', + ), + migrations.RemoveField( + model_name='searchrule', + name='name_contains_index2', + ), + migrations.DeleteModel( + name='CommunityListDocs', + ), + migrations.DeleteModel( + name='SearchRuleDocs', + ), + ] diff --git a/ietf/community/tests.py b/ietf/community/tests.py index 759cce65b..afc9e5122 100644 --- a/ietf/community/tests.py +++ b/ietf/community/tests.py @@ -1,3 +1,6 @@ +# Copyright The IETF Trust 2016-2019, All Rights Reserved +# -*- coding: utf-8 -*- + import json from pyquery import PyQuery @@ -107,7 +110,7 @@ class CommunityListTests(TestCase): self.assertEqual(r.status_code, 200) # add document - r = self.client.post(url, { "action": "add_documents", "documents": draft.pk }) + r = self.client.post(url, { "action": "add_documents", "documents": draft.name }) self.assertEqual(r.status_code, 302) clist = CommunityList.objects.get(user__username="plain") self.assertTrue(clist.added_docs.filter(pk=draft.pk)) @@ -118,7 +121,7 @@ class CommunityListTests(TestCase): self.assertTrue(draft.name in unicontent(r)) # remove document - r = self.client.post(url, { "action": "remove_document", "document": draft.pk }) + r = self.client.post(url, { "action": "remove_document", "document": draft.name }) self.assertEqual(r.status_code, 302) clist = CommunityList.objects.get(user__username="plain") self.assertTrue(not clist.added_docs.filter(pk=draft.pk)) diff --git a/ietf/community/utils.py b/ietf/community/utils.py index de1064645..7e5b7b558 100644 --- a/ietf/community/utils.py +++ b/ietf/community/utils.py @@ -1,3 +1,6 @@ +# Copyright The IETF Trust 2016-2019, All Rights Reserved +# -*- coding: utf-8 -*- + import re from django.db.models import Q @@ -61,7 +64,7 @@ def augment_docs_with_tracking_info(docs, user): if user and user.is_authenticated: clist = CommunityList.objects.filter(user=user).first() if clist: - tracked.update(docs_tracked_by_community_list(clist).filter(pk__in=docs).values_list("pk", flat=True)) + tracked.update(docs_tracked_by_community_list(clist).filter(pk__in=[ d.pk for d in docs ]).values_list("pk", flat=True)) for d in docs: d.tracked_in_personal_community_list = d.pk in tracked diff --git a/ietf/community/views.py b/ietf/community/views.py index 472665e4e..1ee16bd8e 100644 --- a/ietf/community/views.py +++ b/ietf/community/views.py @@ -1,3 +1,6 @@ +# Copyright The IETF Trust 2012-2019, All Rights Reserved +# -*- coding: utf-8 -*- + import csv import uuid import datetime @@ -57,9 +60,9 @@ def manage_list(request, username=None, acronym=None, group_type=None): add_doc_form = AddDocumentsForm() if request.method == 'POST' and action == 'remove_document': - document_pk = request.POST.get('document') - if clist.pk is not None and document_pk: - document = get_object_or_404(clist.added_docs, pk=document_pk) + document_name = request.POST.get('document') + if clist.pk is not None and document_name: + document = get_object_or_404(clist.added_docs, name=document_name) clist.added_docs.remove(document) return HttpResponseRedirect("") @@ -209,7 +212,7 @@ def feed(request, username=None, acronym=None, group_type=None): since = datetime.datetime.now() - datetime.timedelta(days=14) events = DocEvent.objects.filter( - doc__in=documents, + doc__id__in=documents, time__gte=since, ).distinct().order_by('-time', '-id').select_related("doc") diff --git a/ietf/doc/admin.py b/ietf/doc/admin.py index d61ccb191..44b0a8224 100644 --- a/ietf/doc/admin.py +++ b/ietf/doc/admin.py @@ -1,3 +1,6 @@ +# Copyright The IETF Trust 2010-2019, All Rights Reserved +# -*- coding: utf-8 -*- + from django.contrib import admin from django import forms @@ -19,9 +22,9 @@ class StateAdmin(admin.ModelAdmin): filter_horizontal = ["next_states"] admin.site.register(State, StateAdmin) -class DocAliasInline(admin.TabularInline): - model = DocAlias - extra = 1 +# class DocAliasInline(admin.TabularInline): +# model = DocAlias +# extra = 1 class DocAuthorInline(admin.TabularInline): model = DocumentAuthor @@ -58,7 +61,7 @@ class DocumentAdmin(admin.ModelAdmin): search_fields = ['name'] list_filter = ['type'] raw_id_fields = ['group', 'shepherd', 'ad'] - inlines = [DocAliasInline, DocAuthorInline, RelatedDocumentInline, ] + inlines = [DocAuthorInline, RelatedDocumentInline, ] form = DocumentForm def save_model(self, request, obj, form, change): @@ -88,9 +91,9 @@ class DocHistoryAdmin(admin.ModelAdmin): admin.site.register(DocHistory, DocHistoryAdmin) class DocAliasAdmin(admin.ModelAdmin): - list_display = ['name', 'document_link'] - search_fields = ['name', 'document__name'] - raw_id_fields = ['document'] +# list_display = ['name', 'document_link'] +# search_fields = ['name', 'document__name'] + raw_id_fields = ['docs'] admin.site.register(DocAlias, DocAliasAdmin) class DocReminderAdmin(admin.ModelAdmin): @@ -102,7 +105,7 @@ admin.site.register(DocReminder, DocReminderAdmin) class RelatedDocumentAdmin(admin.ModelAdmin): list_display = ['source', 'target', 'relationship', ] list_filter = ['relationship', ] - search_fields = ['source__name', 'target__name', 'target__document__name', ] + search_fields = ['source__name', 'target__name', 'target__docs__name', ] raw_id_fields = ['source', 'target', ] admin.site.register(RelatedDocument, RelatedDocumentAdmin) diff --git a/ietf/doc/factories.py b/ietf/doc/factories.py index f5f669181..ad46c66f2 100644 --- a/ietf/doc/factories.py +++ b/ietf/doc/factories.py @@ -1,3 +1,6 @@ +# Copyright The IETF Trust 2016-2019, All Rights Reserved +# -*- coding: utf-8 -*- + import debug # pyflakes:ignore import factory import datetime @@ -33,13 +36,14 @@ class BaseDocumentFactory(factory.DjangoModelFactory): newrevisiondocevent = factory.RelatedFactory('ietf.doc.factories.NewRevisionDocEventFactory','doc') - alias = factory.RelatedFactory('ietf.doc.factories.DocAliasFactory','document') - @factory.post_generation def other_aliases(obj, create, extracted, **kwargs): # pylint: disable=no-self-argument + alias = DocAliasFactory(name=obj.name) + alias.docs.add(obj) if create and extracted: - for alias in extracted: - obj.docalias_set.create(name=alias) + for name in extracted: + alias = DocAliasFactory(name=name) + alias.docs.add(obj) @factory.post_generation def states(obj, create, extracted, **kwargs): # pylint: disable=no-self-argument @@ -61,10 +65,14 @@ class BaseDocumentFactory(factory.DjangoModelFactory): @factory.post_generation def relations(obj, create, extracted, **kwargs): # pylint: disable=no-self-argument if create and extracted: - for (rel_id,docalias) in extracted: - if isinstance(docalias,Document): - docalias = docalias.docalias_set.first() - obj.relateddocument_set.create(relationship_id=rel_id,target=docalias) + for (rel_id, doc) in extracted: + if isinstance(doc, Document): + docalias = doc.docalias.first() + elif isinstance(doc, DocAlias): + docalias = doc + else: + continue + obj.relateddocument_set.create(relationship_id=rel_id, target=docalias) @classmethod def _after_postgeneration(cls, obj, create, results=None): @@ -195,9 +203,9 @@ class ConflictReviewFactory(BaseDocumentFactory): if not create: return if extracted: - obj.relateddocument_set.create(relationship_id='conflrev',target=extracted.docalias_set.first()) + obj.relateddocument_set.create(relationship_id='conflrev',target=extracted.docalias.first()) else: - obj.relateddocument_set.create(relationship_id='conflrev',target=DocumentFactory(type_id='draft',group=Group.objects.get(type_id='individ')).docalias_set.first()) + obj.relateddocument_set.create(relationship_id='conflrev',target=DocumentFactory(type_id='draft',group=Group.objects.get(type_id='individ')).docalias.first()) @factory.post_generation def states(obj, create, extracted, **kwargs): @@ -219,12 +227,18 @@ class DocAliasFactory(factory.DjangoModelFactory): class Meta: model = DocAlias - document = factory.SubFactory('ietf.doc.factories.DocumentFactory') + @factory.post_generation + def document(self, create, extracted, **kwargs): + if create and extracted: + self.docs.add(extracted) + + @factory.post_generation + def docs(self, create, extracted, **kwargs): + if create and extracted: + for doc in extracted: + if not doc in self.docs.all(): + self.docs.add(doc) - @factory.lazy_attribute - def name(self): - return self.document.name - class DocEventFactory(factory.DjangoModelFactory): class Meta: diff --git a/ietf/doc/fields.py b/ietf/doc/fields.py index 1d19a128e..57d4af654 100644 --- a/ietf/doc/fields.py +++ b/ietf/doc/fields.py @@ -1,7 +1,11 @@ +# Copyright The IETF Trust 2014-2019, All Rights Reserved +# -*- coding: utf-8 -*- + import json from django.utils.html import escape from django import forms +from django.db.models import Q from django.urls import reverse as urlreverse import debug # pyflakes:ignore @@ -52,11 +56,13 @@ class SearchableDocumentsField(forms.CharField): if isinstance(value, (int, long)): value = str(value) if isinstance(value, basestring): - pks = self.parse_select2_value(value) - value = self.model.objects.filter(pk__in=pks) + items = self.parse_select2_value(value) + names = [ i for i in items if not i.isdigit() ] + ids = [ i for i in items if i.isdigit() ] + value = self.model.objects.filter(Q(name__in=names)|Q(id__in=ids)) filter_args = {} if self.model == DocAlias: - filter_args["document__type"] = self.doc_type + filter_args["docs__type"] = self.doc_type else: filter_args["type"] = self.doc_type value = value.filter(**filter_args) @@ -76,17 +82,17 @@ class SearchableDocumentsField(forms.CharField): def clean(self, value): value = super(SearchableDocumentsField, self).clean(value) - pks = self.parse_select2_value(value) + names = self.parse_select2_value(value) - objs = self.model.objects.filter(pk__in=pks) + objs = self.model.objects.filter(name__in=names) - found_pks = [str(o.pk) for o in objs] - failed_pks = [x for x in pks if x not in found_pks] - if failed_pks: - raise forms.ValidationError(u"Could not recognize the following documents: {pks}. You can only input documents already registered in the Datatracker.".format(pks=", ".join(failed_pks))) + found_names = [str(o.name) for o in objs] + failed_names = [x for x in names if x not in found_names] + if failed_names: + raise forms.ValidationError(u"Could not recognize the following documents: {names}. You can only input documents already registered in the Datatracker.".format(names=", ".join(failed_names))) if self.max_entries != None and len(objs) > self.max_entries: - raise forms.ValidationError(u"You can select at most %s entries only." % self.max_entries) + raise forms.ValidationError(u"You can select at most %s entries." % self.max_entries) return objs diff --git a/ietf/doc/migrations/0013_add_document_docalias_id.py b/ietf/doc/migrations/0013_add_document_docalias_id.py new file mode 100644 index 000000000..e86c4270b --- /dev/null +++ b/ietf/doc/migrations/0013_add_document_docalias_id.py @@ -0,0 +1,26 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-08 08:41 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0012_add_event_type_closed_review_assignment'), + ] + + operations = [ + migrations.AddField( + model_name='docalias', + name='id', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='document', + name='id', + field=models.IntegerField(default=0), + ), + ] diff --git a/ietf/doc/migrations/0014_set_document_docalias_id.py b/ietf/doc/migrations/0014_set_document_docalias_id.py new file mode 100644 index 000000000..06ff9b89e --- /dev/null +++ b/ietf/doc/migrations/0014_set_document_docalias_id.py @@ -0,0 +1,36 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-08 08:42 +from __future__ import unicode_literals + +import sys + +from tqdm import tqdm + +from django.db import migrations + + +def forward(apps, schema_editor): + Document = apps.get_model('doc','Document') + sys.stderr.write('\n') + for i, d in enumerate(tqdm(Document.objects.all()), start=1): + d.id = i + d.save() + + DocAlias = apps.get_model('doc','DocAlias') + for i, d in enumerate(tqdm(DocAlias.objects.all()), start=1): + d.id = i + d.save() + +def reverse(apps, schema_editor): + pass + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0013_add_document_docalias_id'), + ] + + operations = [ + migrations.RunPython(forward, reverse), + ] diff --git a/ietf/doc/migrations/0015_1_add_fk_to_document_id.py b/ietf/doc/migrations/0015_1_add_fk_to_document_id.py new file mode 100644 index 000000000..a60d9864f --- /dev/null +++ b/ietf/doc/migrations/0015_1_add_fk_to_document_id.py @@ -0,0 +1,122 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-08 10:29 +from __future__ import unicode_literals + +import django.core.validators +from django.db import migrations, models +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0014_set_document_docalias_id'), + ] + + operations = [ + # Fix name and id fields first + migrations.AlterField( + model_name='docalias', + name='name', + field=models.CharField(max_length=255, unique=True), + ), + migrations.AlterField( + model_name='docalias', + name='id', + field=models.IntegerField(primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='document', + name='name', + field=models.CharField(max_length=255, unique=True, validators=[django.core.validators.RegexValidator(b'^[-a-z0-9]+$', b'Provide a valid document name consisting of lowercase letters, numbers and hyphens.', b'invalid')]), + ), + migrations.AlterField( + model_name='document', + name='id', + field=models.IntegerField(primary_key=True, serialize=False), + ), + + # Then remaining fields + migrations.AddField( + model_name='docalias', + name='document2', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field=b'id'), + ), + migrations.AddField( + model_name='dochistory', + name='doc2', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='history_set', to='doc.Document', to_field=b'id'), + ), + migrations.AddField( + model_name='documentauthor', + name='document2', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field=b'id'), + ), + migrations.AddField( + model_name='documenturl', + name='doc2', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field=b'id'), + ), + migrations.AddField( + model_name='relateddochistory', + name='target2', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='reversely_related_document_history_set', to='doc.DocAlias', to_field=b'id'), + ), + migrations.AddField( + model_name='relateddocument', + name='source2', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field=b'id'), + ), + migrations.AddField( + model_name='relateddocument', + name='target2', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.DocAlias', to_field=b'id'), + ), + migrations.AddField( + model_name='docevent', + name='doc2', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field='id'), + ), + migrations.AlterField( + model_name='docalias', + name='document', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='old_docalias', to='doc.Document', to_field=b'name'), + ), + migrations.AlterField( + model_name='dochistory', + name='doc', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='old_hist', to='doc.Document', to_field=b'name'), + ), + migrations.AlterField( + model_name='documentauthor', + name='document', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='old_doc_auth', to='doc.Document', to_field=b'name'), + ), + migrations.AlterField( + model_name='documenturl', + name='doc', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='old_doc_url', to='doc.Document', to_field=b'name'), + ), + migrations.AlterField( + model_name='relateddochistory', + name='target', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='old_hist_target', to='doc.DocAlias', to_field=b'name'), + ), + migrations.AlterField( + model_name='relateddocument', + name='source', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='old_rel_source', to='doc.Document', to_field=b'name'), + ), + migrations.AlterField( + model_name='relateddocument', + name='target', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='old_rel_target', to='doc.DocAlias', to_field=b'name'), + ), + migrations.AlterField( + model_name='docevent', + name='doc', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='old_docevent', to='doc.Document', to_field=b'name'), + ), + ] diff --git a/ietf/doc/migrations/0015_2_add_doc_document_m2m_fields.py b/ietf/doc/migrations/0015_2_add_doc_document_m2m_fields.py new file mode 100644 index 000000000..5e62dbf26 --- /dev/null +++ b/ietf/doc/migrations/0015_2_add_doc_document_m2m_fields.py @@ -0,0 +1,94 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-28 12:42 +from __future__ import unicode_literals + +import sys, time + +from django.db import migrations, models +import django.db.models.deletion +import ietf.utils.models + + +def timestamp(apps, schema_editor): + sys.stderr.write('\n %s' % time.strftime('%Y-%m-%d %H:%M:%S')) + +class Migration(migrations.Migration): + + dependencies = [ + ('name', '0006_adjust_statenames'), + ('doc', '0015_1_add_fk_to_document_id'), + ] + + operations = [ + migrations.CreateModel( + name='DocumentLanguages', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('document', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field='name', related_name='doclanguages')), + ('formallanguagename', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='name.FormalLanguageName')), + ], + ), + migrations.CreateModel( + name='DocumentStates', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('document', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field='name', related_name='docstates')), + ('state', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.State')), + ], + ), + migrations.CreateModel( + name='DocumentTags', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('document', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field='name', related_name='doctags')), + ('doctagname', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='name.DocTagName')), + ], + ), + migrations.AddField( + model_name='document', + name='formal_languages2', + field=models.ManyToManyField(blank=True, related_name='languagedocs', through='doc.DocumentLanguages', to='name.FormalLanguageName'), + ), + migrations.AddField( + model_name='document', + name='states2', + field=models.ManyToManyField(blank=True, related_name='statedocs', through='doc.DocumentStates', to='doc.State'), + ), + migrations.AddField( + model_name='document', + name='tags2', + field=models.ManyToManyField(blank=True, related_name='tagdocs', through='doc.DocumentTags', to='name.DocTagName'), + ), + # Here we copy the content of the existing implicit m2m tables for + # the Document m2m fields into the explicit through tabeles, in order + # to be able to later set the correct id from name + migrations.RunPython(timestamp, timestamp), + migrations.RunSQL( + "INSERT INTO doc_documentlanguages SELECT * FROM doc_document_formal_languages;", + ""), + migrations.RunPython(timestamp, timestamp), + migrations.RunSQL( + "INSERT INTO doc_documentstates SELECT * FROM doc_document_states;", + ""), + migrations.RunPython(timestamp, timestamp), + migrations.RunSQL( + "INSERT INTO doc_documenttags SELECT * FROM doc_document_tags;", + ""), + migrations.RunPython(timestamp, timestamp), + migrations.AddField( + model_name='documentlanguages', + name='document2', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field='id', null=True, default=None), + ), + migrations.AddField( + model_name='documentstates', + name='document2', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field='id', null=True, default=None), ), + migrations.AddField( + model_name='documenttags', + name='document2', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field='id', null=True, default=None), + + ), + ] diff --git a/ietf/doc/migrations/0016_set_document_docalias_fk.py b/ietf/doc/migrations/0016_set_document_docalias_fk.py new file mode 100644 index 000000000..ac1376b76 --- /dev/null +++ b/ietf/doc/migrations/0016_set_document_docalias_fk.py @@ -0,0 +1,113 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-08 14:04 +from __future__ import unicode_literals + +import sys + +from tqdm import tqdm + +from django.db import migrations + +def forward(apps, schema_editor): + + def add_id_fk(o, a, nameid): + n = getattr(o, a+'_id') + if n: + i = nameid[n] + if not isinstance(i, (int, long)): + raise ValueError("Inappropriate value: %s: nameid[%s]: %s" % (o.__class__.__name__, n, i)) + if getattr(o, a+'2_id') != i: + setattr(o, a+'2_id', i) + o.save() + + DocAlias = apps.get_model('doc','DocAlias') + DocEvent = apps.get_model('doc', 'DocEvent') + DocHistory = apps.get_model('doc', 'DocHistory') + Document = apps.get_model('doc', 'Document') + DocumentAuthor = apps.get_model('doc', 'DocumentAuthor') + DocumentLanguages = apps.get_model('doc', 'DocumentLanguages') + DocumentStates = apps.get_model('doc', 'DocumentStates') + DocumentTags = apps.get_model('doc', 'DocumentTags') + DocumentURL = apps.get_model('doc', 'DocumentURL') + Group = apps.get_model('group', 'Group') + IprDocRel = apps.get_model('ipr', 'IprDocRel') + LiaisonStatementAttachment = apps.get_model('liaisons', 'LiaisonStatementAttachment') + RelatedDocHistory = apps.get_model('doc', 'RelatedDocHistory') + RelatedDocument = apps.get_model('doc', 'RelatedDocument') + ReviewAssignment = apps.get_model('review', 'ReviewAssignment') + ReviewRequest = apps.get_model('review', 'ReviewRequest') + ReviewWish = apps.get_model('review', 'ReviewWish') + SessionPresentation = apps.get_model('meeting', 'SessionPresentation') + Submission = apps.get_model('submit', 'Submission') + + # Document id fixup ------------------------------------------------------------ + + objs = Document.objects.in_bulk() + nameid = { o.name: o.id for id, o in objs.iteritems() } + + sys.stderr.write('\n') + + sys.stderr.write('Setting Document FKs:\n') + + for C, a in [ + ( DocAlias , 'document'), + ( DocEvent , 'doc'), + ( DocHistory , 'doc'), + ( DocumentAuthor , 'document'), + ( DocumentLanguages , 'document'), + ( DocumentStates , 'document'), + ( DocumentTags , 'document'), + ( DocumentURL , 'doc'), + ( Group , 'charter'), + ( LiaisonStatementAttachment , 'document'), + ( RelatedDocument , 'source'), + ( ReviewAssignment , 'review'), + ( ReviewRequest , 'doc'), + ( ReviewRequest , 'unused_review'), + ( ReviewWish , 'doc'), + ( SessionPresentation , 'document'), + ( Submission , 'draft'), + ]: + sys.stderr.write(' %s.%s:\n' % (C.__name__, a)) + for o in tqdm(C.objects.all()): + add_id_fk(o, a, nameid) + + # DocAlias id fixup ------------------------------------------------------------ + + sys.stderr.write('\n') + + objs = DocAlias.objects.in_bulk() + nameid = { o.name: o.id for id, o in objs.iteritems() } + + sys.stderr.write('Setting DocAlias FKs:\n') + + for C, a in [ + ( IprDocRel , 'document'), + ( RelatedDocument , 'target'), + ( RelatedDocHistory , 'target'), + ]: + sys.stderr.write(' %s.%s:\n' % (C.__name__, a)) + for o in tqdm(C.objects.all()): + add_id_fk(o, a, nameid) + +def reverse(apps, schema_editor): + pass + +class Migration(migrations.Migration): + + dependencies = [ + ('community', '0004_set_document_m2m_keys'), + ('doc', '0015_2_add_doc_document_m2m_fields'), + ('group', '0014_set_document_m2m_keys'), + ('ipr', '0003_add_ipdocrel_document2_fk'), + ('liaisons', '0003_liaison_document2_fk'), + ('meeting', '0015_sessionpresentation_document2_fk'), + ('message', '0003_set_document_m2m_keys'), + ('review', '0011_review_document2_fk'), + ('submit', '0002_submission_document2_fk'), + ] + + operations = [ + migrations.RunPython(forward, reverse), + ] diff --git a/ietf/doc/migrations/0017_make_document_id_primary_key.py b/ietf/doc/migrations/0017_make_document_id_primary_key.py new file mode 100644 index 000000000..851b2dbeb --- /dev/null +++ b/ietf/doc/migrations/0017_make_document_id_primary_key.py @@ -0,0 +1,26 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-09 05:46 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0016_set_document_docalias_fk'), + ] + + operations = [ + migrations.AlterField( + model_name='docalias', + name='id', + field=models.AutoField(primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='document', + name='id', + field=models.AutoField(primary_key=True, serialize=False), + ), + ] diff --git a/ietf/doc/migrations/0018_remove_old_document_field.py b/ietf/doc/migrations/0018_remove_old_document_field.py new file mode 100644 index 000000000..146317da2 --- /dev/null +++ b/ietf/doc/migrations/0018_remove_old_document_field.py @@ -0,0 +1,125 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-20 09:53 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0017_make_document_id_primary_key'), + ] + + operations = [ + migrations.AlterModelOptions( + name='documentauthor', + options={'ordering': ['document2', 'order']}, + ), + migrations.RemoveIndex( + model_name='docevent', + name='doc_doceven_type_43e53e_idx', + ), + migrations.RemoveField( + model_name='docalias', + name='document', + ), + migrations.RemoveField( + model_name='docevent', + name='doc', + ), + migrations.RemoveField( + model_name='dochistory', + name='doc', + ), + migrations.RemoveField( + model_name='documentauthor', + name='document', + ), + migrations.RemoveField( + model_name='documenturl', + name='doc', + ), + migrations.RemoveField( + model_name='relateddochistory', + name='target', + ), + migrations.RemoveField( + model_name='relateddocument', + name='source', + ), + migrations.RemoveField( + model_name='relateddocument', + name='target', + ), + migrations.AddIndex( + model_name='docevent', + index=models.Index(fields=[b'type', b'doc2'], name='doc_doceven_type_ac7748_idx'), + ), + # The following 9 migrations are related to the m2m fields on Document + # Remove the intermediary model field pointing to Document.name + migrations.RemoveField( + model_name='documentlanguages', + name='document', + ), + migrations.RemoveField( + model_name='documentstates', + name='document', + ), + migrations.RemoveField( + model_name='documenttags', + name='document', + ), + # Rename the intermediary model field pointing to Document.id, to + # match the implicit m2m table + migrations.RenameField( + model_name='documentlanguages', + old_name='document2', + new_name='document', + ), + migrations.RenameField( + model_name='documentstates', + old_name='document2', + new_name='document', + ), + migrations.RenameField( + model_name='documenttags', + old_name='document2', + new_name='document', + ), + # Alter the fields to point to Document.pk instead of Document.name + migrations.AlterField( + model_name='documentlanguages', + name='document', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document'), + ), + migrations.AlterField( + model_name='documentstates', + name='document', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document'), + ), + migrations.AlterField( + model_name='documenttags', + name='document', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document'), + ), + # Remove the implicit m2m tables which point to Document.name + migrations.RemoveField( + model_name='document', + name='formal_languages', + ), + migrations.RemoveField( + model_name='document', + name='states', + ), + migrations.RemoveField( + model_name='document', + name='tags', + ), + # Next (in a separate migration, in order to commit the above before + # we proceed) we'll create the implicit m2m tables again, this time + # pointing to Document.id since that's now the primary key. + ] diff --git a/ietf/doc/migrations/0019_rename_field_document2.py b/ietf/doc/migrations/0019_rename_field_document2.py new file mode 100644 index 000000000..5b4504d01 --- /dev/null +++ b/ietf/doc/migrations/0019_rename_field_document2.py @@ -0,0 +1,84 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-21 05:31 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0018_remove_old_document_field'), + ] + + operations = [ + migrations.AlterModelOptions( + name='documentauthor', + options={'ordering': ['document', 'order']}, + ), + migrations.RemoveIndex( + model_name='docevent', + name='doc_doceven_type_ac7748_idx', + ), + migrations.RenameField( + model_name='docalias', + old_name='document2', + new_name='document', + ), + migrations.RenameField( + model_name='docevent', + old_name='doc2', + new_name='doc', + ), + migrations.RenameField( + model_name='dochistory', + old_name='doc2', + new_name='doc', + ), + migrations.RenameField( + model_name='documentauthor', + old_name='document2', + new_name='document', + ), + migrations.RenameField( + model_name='documenturl', + old_name='doc2', + new_name='doc', + ), + migrations.RenameField( + model_name='relateddochistory', + old_name='target2', + new_name='target', + ), + migrations.RenameField( + model_name='relateddocument', + old_name='source2', + new_name='source', + ), + migrations.RenameField( + model_name='relateddocument', + old_name='target2', + new_name='target', + ), + migrations.AddIndex( + model_name='docevent', + index=models.Index(fields=[b'type', b'doc'], name='doc_doceven_type_43e53e_idx'), + ), + # Add back the m2m field we removed in 0018_... + migrations.AddField( + model_name='document', + name='formal_languages', + field=models.ManyToManyField(blank=True, help_text=b'Formal languages used in document', to='name.FormalLanguageName'), + ), + migrations.AddField( + model_name='document', + name='states', + field=models.ManyToManyField(blank=True, to='doc.State'), + ), + migrations.AddField( + model_name='document', + name='tags', + field=models.ManyToManyField(blank=True, to='name.DocTagName'), + ), + ] diff --git a/ietf/doc/migrations/0020_copy_docs_m2m_table.py b/ietf/doc/migrations/0020_copy_docs_m2m_table.py new file mode 100644 index 000000000..4a6555c71 --- /dev/null +++ b/ietf/doc/migrations/0020_copy_docs_m2m_table.py @@ -0,0 +1,34 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-21 05:31 +from __future__ import unicode_literals + +import sys, time + +from django.db import migrations + +def timestamp(apps, schema_editor): + sys.stderr.write('\n %s' % time.strftime('%Y-%m-%d %H:%M:%S')) + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0019_rename_field_document2'), + ] + + operations = [ + # Copy the doc IDs from the explicit m2m table to the implicit table + migrations.RunPython(timestamp, timestamp), + migrations.RunSQL( + "INSERT INTO doc_document_formal_languages SELECT id,document_id,formallanguagename_id FROM doc_documentlanguages;", + ""), + migrations.RunPython(timestamp, timestamp), + migrations.RunSQL( + "INSERT INTO doc_document_states SELECT id,document_id,state_id FROM doc_documentstates;", + ""), + migrations.RunPython(timestamp, timestamp), + migrations.RunSQL( + "INSERT INTO doc_document_tags SELECT id,document_id,doctagname_id FROM doc_documenttags;", + ""), + migrations.RunPython(timestamp, timestamp), + ] diff --git a/ietf/doc/migrations/0021_remove_docs2_m2m.py b/ietf/doc/migrations/0021_remove_docs2_m2m.py new file mode 100644 index 000000000..c11464cdc --- /dev/null +++ b/ietf/doc/migrations/0021_remove_docs2_m2m.py @@ -0,0 +1,63 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-30 03:36 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0020_copy_docs_m2m_table'), + ] + + operations = [ + # Get rid of the explicit m2m tables which we needed only to be + # able to convert from Document.name to Document.id + migrations.RemoveField( + model_name='documentlanguages', + name='document', + ), + migrations.RemoveField( + model_name='documentlanguages', + name='formallanguagename', + ), + migrations.RemoveField( + model_name='documentstates', + name='document', + ), + migrations.RemoveField( + model_name='documentstates', + name='state', + ), + migrations.RemoveField( + model_name='documenttags', + name='doctagname', + ), + migrations.RemoveField( + model_name='documenttags', + name='document', + ), + migrations.RemoveField( + model_name='document', + name='formal_languages2', + ), + migrations.RemoveField( + model_name='document', + name='states2', + ), + migrations.RemoveField( + model_name='document', + name='tags2', + ), + migrations.DeleteModel( + name='DocumentLanguages', + ), + migrations.DeleteModel( + name='DocumentStates', + ), + migrations.DeleteModel( + name='DocumentTags', + ), + ] diff --git a/ietf/doc/migrations/0022_document_primary_key_cleanup.py b/ietf/doc/migrations/0022_document_primary_key_cleanup.py new file mode 100644 index 000000000..23d74f13a --- /dev/null +++ b/ietf/doc/migrations/0022_document_primary_key_cleanup.py @@ -0,0 +1,68 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-06-10 03:47 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0021_remove_docs2_m2m'), + ] + + operations = [ + migrations.AlterField( + model_name='docalias', + name='document', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document'), + ), + migrations.AlterField( + model_name='docalias', + name='id', + field=models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='docevent', + name='doc', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document'), + ), + migrations.AlterField( + model_name='dochistory', + name='doc', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='history_set', to='doc.Document'), + ), + migrations.AlterField( + model_name='document', + name='id', + field=models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='documentauthor', + name='document', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document'), + ), + migrations.AlterField( + model_name='documenturl', + name='doc', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document'), + ), + migrations.AlterField( + model_name='relateddochistory', + name='target', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='reversely_related_document_history_set', to='doc.DocAlias'), + ), + migrations.AlterField( + model_name='relateddocument', + name='source', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document'), + ), + migrations.AlterField( + model_name='relateddocument', + name='target', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.DocAlias'), + ), + ] diff --git a/ietf/doc/models.py b/ietf/doc/models.py index 0c8509837..25b34885e 100644 --- a/ietf/doc/models.py +++ b/ietf/doc/models.py @@ -1,4 +1,5 @@ -# Copyright The IETF Trust 2007, All Rights Reserved +# Copyright The IETF Trust 2007-2019, All Rights Reserved +# -*- coding: utf-8 -*- import datetime import logging @@ -323,7 +324,7 @@ class DocumentInfo(models.Model): elif state.slug == "repl": rs = self.related_that("replaces") if rs: - return mark_safe("Replaced by " + ", ".join("%s" % (urlreverse('ietf.doc.views_doc.document_main', kwargs=dict(name=alias.document)), alias.document) for alias in rs)) + return mark_safe("Replaced by " + ", ".join("%s" % (urlreverse('ietf.doc.views_doc.document_main', kwargs=dict(name=alias.document.name)), alias.document) for alias in rs)) else: return "Replaced" elif state.slug == "active": @@ -411,9 +412,9 @@ class DocumentInfo(models.Model): if not isinstance(relationship, tuple): raise TypeError("Expected a string or tuple, received %s" % type(relationship)) if isinstance(self, Document): - return RelatedDocument.objects.filter(target__document=self, relationship__in=relationship).select_related('source') + return RelatedDocument.objects.filter(target__docs=self, relationship__in=relationship).select_related('source') elif isinstance(self, DocHistory): - return RelatedDocHistory.objects.filter(target__document=self.doc, relationship__in=relationship).select_related('source') + return RelatedDocHistory.objects.filter(target__docs=self.doc, relationship__in=relationship).select_related('source') else: raise TypeError("Expected method called on Document or DocHistory") @@ -434,9 +435,9 @@ class DocumentInfo(models.Model): if not isinstance(relationship, tuple): raise TypeError("Expected a string or tuple, received %s" % type(relationship)) if isinstance(self, Document): - return RelatedDocument.objects.filter(source=self, relationship__in=relationship).select_related('target__document') + return RelatedDocument.objects.filter(source=self, relationship__in=relationship).select_related('target') elif isinstance(self, DocHistory): - return RelatedDocHistory.objects.filter(source=self, relationship__in=relationship).select_related('target__document') + return RelatedDocHistory.objects.filter(source=self, relationship__in=relationship).select_related('target') else: raise TypeError("Expected method called on Document or DocHistory") @@ -447,14 +448,15 @@ class DocumentInfo(models.Model): for r in rels: if not r in related: related += ( r, ) - related = r.target.document.all_relations_that_doc(relationship, related) + for doc in r.target.docs.all(): + related = doc.all_relations_that_doc(relationship, related) return related def related_that(self, relationship): - return list(set([x.source.docalias_set.get(name=x.source.name) for x in self.relations_that(relationship)])) + return list(set([x.source.docalias.get(name=x.source.name) for x in self.relations_that(relationship)])) def all_related_that(self, relationship, related=None): - return list(set([x.source.docalias_set.get(name=x.source.name) for x in self.all_relations_that(relationship)])) + return list(set([x.source.docalias.get(name=x.source.name) for x in self.all_relations_that(relationship)])) def related_that_doc(self, relationship): return list(set([x.target for x in self.relations_that_doc(relationship)])) @@ -463,7 +465,7 @@ class DocumentInfo(models.Model): return list(set([x.target for x in self.all_relations_that_doc(relationship)])) def replaces(self): - return set([ r.document for r in self.related_that_doc("replaces")]) + return set([ d for r in self.related_that_doc("replaces") for d in r.docs.all() ]) def replaces_canonical_name(self): s = set([ r.document for r in self.related_that_doc("replaces")]) @@ -609,7 +611,7 @@ validate_docname = RegexValidator( ) class Document(DocumentInfo): - name = models.CharField(max_length=255, primary_key=True, validators=[validate_docname,]) # immutable + name = models.CharField(max_length=255, validators=[validate_docname,], unique=True) # immutable def __unicode__(self): return self.name @@ -657,7 +659,7 @@ class Document(DocumentInfo): if not hasattr(self, '_canonical_name'): name = self.name if self.type_id == "draft" and self.get_state_slug() == "rfc": - a = self.docalias_set.filter(name__startswith="rfc").order_by('-name').first() + a = self.docalias.filter(name__startswith="rfc").order_by('-name').first() if a: name = a.name elif self.type_id == "charter": @@ -671,7 +673,7 @@ class Document(DocumentInfo): def canonical_docalias(self): - return self.docalias_set.get(name=self.name) + return self.docalias.get(name=self.name) def display_name(self): name = self.canonical_name() @@ -766,14 +768,14 @@ class Document(DocumentInfo): def ipr(self,states=('posted','removed')): """Returns the IPR disclosures against this document (as a queryset over IprDocRel).""" from ietf.ipr.models import IprDocRel - return IprDocRel.objects.filter(document__document=self,disclosure__state__in=states) + return IprDocRel.objects.filter(document__docs=self, disclosure__state__in=states) def related_ipr(self): """Returns the IPR disclosures against this document and those documents this document directly or indirectly obsoletes or replaces """ from ietf.ipr.models import IprDocRel - iprs = IprDocRel.objects.filter(document__in=list(self.docalias_set.all())+self.all_related_that_doc(('obs','replaces'))).filter(disclosure__state__in=('posted','removed')).values_list('disclosure', flat=True).distinct() + iprs = IprDocRel.objects.filter(document__in=list(self.docalias.all())+self.all_related_that_doc(('obs','replaces'))).filter(disclosure__state__in=('posted','removed')).values_list('disclosure', flat=True).distinct() return iprs def future_presentations(self): @@ -889,8 +891,9 @@ class DocHistory(DocumentInfo): return self.doc.groupmilestone_set @property - def docalias_set(self): - return self.doc.docalias_set + def docalias(self): + log.unreachable('2019-06-11') + return self.doc.docalias def is_dochistory(self): return True @@ -908,10 +911,15 @@ class DocAlias(models.Model): same immutable Document.name, in the tables, but will be referred to by RFC number, primarily, after achieving RFC status. """ - name = models.CharField(max_length=255, primary_key=True) - document = ForeignKey(Document) + name = models.CharField(max_length=255, unique=True) + docs = models.ManyToManyField(Document, related_name='docalias') + + @property + def document(self): + return self.docs.first() + def __unicode__(self): - return "%s-->%s" % (self.name, self.document.name) + return "%s-->%s" % (self.name, ','.join([unicode(d.name) for d in self.docs.all() if isinstance(d, Document) ])) document_link = admin_link("document") class Meta: verbose_name = "document alias" @@ -1005,7 +1013,7 @@ class DocEvent(models.Model): 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 = ForeignKey(Person) - doc = ForeignKey('doc.Document') + doc = ForeignKey(Document) rev = models.CharField(verbose_name="revision", max_length=16, null=True, blank=True) desc = models.TextField() diff --git a/ietf/doc/tests.py b/ietf/doc/tests.py index 7fac55de8..dfe565cc6 100644 --- a/ietf/doc/tests.py +++ b/ietf/doc/tests.py @@ -1,3 +1,6 @@ +# Copyright The IETF Trust 2012-2019, All Rights Reserved +# -*- coding: utf-8 -*- + import os import shutil import datetime @@ -216,7 +219,7 @@ class SearchTests(TestCase): draft.set_state(State.objects.get(type='draft-iesg', slug='lc')) rfc = IndividualDraftFactory(ad=ad) rfc.set_state(State.objects.get(type='draft', slug='rfc')) - rfc.docalias_set.create(name='rfc6666') + DocAlias.objects.create(name='rfc6666').docs.add(rfc) conflrev = DocumentFactory(type_id='conflrev',ad=ad) conflrev.set_state(State.objects.get(type='conflrev', slug='iesgeval')) statchg = DocumentFactory(type_id='statchg',ad=ad) @@ -278,7 +281,7 @@ class SearchTests(TestCase): self.assertEqual(data[0]["id"], draft.pk) # DocAlias - doc_alias = draft.docalias_set.get() + doc_alias = draft.docalias.first() url = urlreverse('ietf.doc.views_search.ajax_select2_search_docs', kwargs={ "model_name": "docalias", @@ -499,7 +502,7 @@ Man Expires September 22, 2015 [Page 3] draft = WgDraftFactory(name='draft-ietf-mars-test',rev='01') HolderIprDisclosureFactory(docs=[draft]) replaced = IndividualDraftFactory() - draft.relateddocument_set.create(relationship_id='replaces',source=draft,target=replaced.docalias_set.first()) + draft.relateddocument_set.create(relationship_id='replaces',source=draft,target=replaced.docalias.first()) # these tests aren't testing all attributes yet, feel free to # expand them @@ -580,7 +583,7 @@ Man Expires September 22, 2015 [Page 3] shepherd_id=draft.shepherd_id, ad_id=draft.ad_id, expires=draft.expires, notify=draft.notify, note=draft.note) rel = RelatedDocument.objects.create(source=replacement, - target=draft.docalias_set.get(name__startswith="draft"), + target=draft.docalias.get(name__startswith="draft"), relationship_id="replaces") r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name))) @@ -595,8 +598,10 @@ Man Expires September 22, 2015 [Page 3] draft.save_with_history([DocEvent.objects.create(doc=draft, rev=draft.rev, type="published_rfc", by=Person.objects.get(name="(System)"))]) - rfc_alias = DocAlias.objects.create(name="rfc123456", document=draft) - bcp_alias = DocAlias.objects.create(name="bcp123456", document=draft) + rfc_alias = DocAlias.objects.create(name="rfc123456") + rfc_alias.docs.add(draft) + bcp_alias = DocAlias.objects.create(name="bcp123456") + bcp_alias.docs.add(draft) r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name))) self.assertEqual(r.status_code, 302) @@ -759,8 +764,8 @@ class DocTestCase(TestCase): self.assertFalse('more YES or NO' in unicontent(r)) # status change - IndividualDraftFactory().docalias_set.create(name='rfc9998') - IndividualDraftFactory().docalias_set.create(name='rfc9999') + DocAlias.objects.create(name='rfc9998').docs.add(IndividualDraftFactory()) + DocAlias.objects.create(name='rfc9999').docs.add(IndividualDraftFactory()) doc = DocumentFactory(type_id='statchg',name='status-change-imaginary-mid-review') iesgeval_pk = str(State.objects.get(slug='iesgeval',type__slug='statchg').pk) self.client.login(username='ad', password='ad+password') @@ -1003,7 +1008,7 @@ class ReferencesTest(TestCase): def test_references(self): doc1 = WgDraftFactory(name='draft-ietf-mars-test') - doc2 = IndividualDraftFactory(name='draft-imaginary-independent-submission').docalias_set.first() + doc2 = IndividualDraftFactory(name='draft-imaginary-independent-submission').docalias.first() RelatedDocument.objects.get_or_create(source=doc1,target=doc2,relationship=DocRelationshipName.objects.get(slug='refnorm')) url = urlreverse('ietf.doc.views_doc.document_references', kwargs=dict(name=doc1.name)) r = self.client.get(url) diff --git a/ietf/doc/tests_ballot.py b/ietf/doc/tests_ballot.py index 46340abf8..de43c58d1 100644 --- a/ietf/doc/tests_ballot.py +++ b/ietf/doc/tests_ballot.py @@ -1,4 +1,6 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved # -*- coding: utf-8 -*- + import datetime from pyquery import PyQuery @@ -741,7 +743,7 @@ class ApproveBallotTests(TestCase): self.assertTrue("No downward references for" in r.content) # Add a downref, the page should ask if it should be added to the registry - rel = draft.relateddocument_set.create(target=rfc.docalias_set.get(name='rfc6666'),relationship_id='refnorm') + rel = draft.relateddocument_set.create(target=rfc.docalias.get(name='rfc6666'),relationship_id='refnorm') d = [rdoc for rdoc in draft.relateddocument_set.all() if rel.is_approved_downref()] original_len = len(d) r = self.client.get(url) @@ -970,7 +972,7 @@ class RegenerateLastCallTestCase(TestCase): std_level_id='inf', ) - draft.relateddocument_set.create(target=rfc.docalias_set.get(name='rfc6666'),relationship_id='refnorm') + draft.relateddocument_set.create(target=rfc.docalias.get(name='rfc6666'),relationship_id='refnorm') r = self.client.post(url, dict(regenerate_last_call_text="1")) self.assertEqual(r.status_code, 200) @@ -980,7 +982,7 @@ class RegenerateLastCallTestCase(TestCase): self.assertTrue("rfc6666" in lc_text) self.assertTrue("Independent Submission Editor stream" in lc_text) - draft.relateddocument_set.create(target=rfc.docalias_set.get(name='rfc6666'),relationship_id='downref-approval') + draft.relateddocument_set.create(target=rfc.docalias.get(name='rfc6666'),relationship_id='downref-approval') r = self.client.post(url, dict(regenerate_last_call_text="1")) self.assertEqual(r.status_code, 200) diff --git a/ietf/doc/tests_downref.py b/ietf/doc/tests_downref.py index ad35e89c1..a567f90e5 100644 --- a/ietf/doc/tests_downref.py +++ b/ietf/doc/tests_downref.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2017, All Rights Reserved +# Copyright The IETF Trust 2017-2019, All Rights Reserved # -*- coding: utf-8 -*- from __future__ import unicode_literals @@ -21,7 +21,7 @@ class Downref(TestCase): WgDraftFactory(name='draft-ietf-mars-test') doc = WgDraftFactory(name='draft-ietf-mars-approved-document',states=[('draft-iesg','rfcqueue')]) rfc = WgRfcFactory(alias2__name='rfc9998') - RelatedDocument.objects.create(source=doc, target=rfc.docalias_set.get(name='rfc9998'),relationship_id='downref-approval') + RelatedDocument.objects.create(source=doc, target=rfc.docalias.get(name='rfc9998'),relationship_id='downref-approval') def test_downref_registry(self): url = urlreverse('ietf.doc.views_downref.downref_registry') @@ -118,7 +118,7 @@ class Downref(TestCase): draft = WgDraftFactory(name='draft-ietf-mars-ready-for-lc-document',intended_std_level_id='ps',states=[('draft-iesg','iesg-eva')]) WgDraftFactory(name='draft-ietf-mars-another-approved-document',states=[('draft-iesg','rfcqueue')]) rfc9999 = WgRfcFactory(alias2__name='rfc9999', std_level_id=None) - RelatedDocument.objects.create(source=draft, target=rfc9999.docalias_set.get(name='rfc9999'), relationship_id='refnorm') + RelatedDocument.objects.create(source=draft, target=rfc9999.docalias.get(name='rfc9999'), relationship_id='refnorm') url = urlreverse('ietf.doc.views_ballot.lastcalltext', kwargs=dict(name=draft.name)) login_testing_unauthorized(self, "secretary", url) @@ -130,7 +130,7 @@ class Downref(TestCase): self.assertIn('The document contains these normative downward references', text) # now, the announcement text about the downref to RFC 9999 should be gone - RelatedDocument.objects.create(source=draft, target=rfc9999.docalias_set.get(name='rfc9999'),relationship_id='downref-approval') + RelatedDocument.objects.create(source=draft, target=rfc9999.docalias.get(name='rfc9999'),relationship_id='downref-approval') r = self.client.post(url, dict(regenerate_last_call_text="1")) self.assertEqual(r.status_code, 200) q = PyQuery(r.content) diff --git a/ietf/doc/tests_draft.py b/ietf/doc/tests_draft.py index 13c551d1c..1aadc79c5 100644 --- a/ietf/doc/tests_draft.py +++ b/ietf/doc/tests_draft.py @@ -1,4 +1,6 @@ +# Copyright The IETF Trust 2011-2019, All Rights Reserved # -*- coding: utf-8 -*- + import os import shutil import datetime @@ -1569,7 +1571,7 @@ class ChangeReplacesTests(TestCase): # Post that says replacea replaces base a empty_outbox() - RelatedDocument.objects.create(source=self.replacea, target=self.basea.docalias_set.first(), + RelatedDocument.objects.create(source=self.replacea, target=self.basea.docalias.first(), relationship=DocRelationshipName.objects.get(slug="possibly-replaces")) self.assertEqual(self.basea.get_state().slug,'active') r = self.client.post(url, dict(replaces=self.basea.name)) @@ -1617,7 +1619,7 @@ class ChangeReplacesTests(TestCase): def test_review_possibly_replaces(self): - replaced = self.basea.docalias_set.first() + replaced = self.basea.docalias.first() RelatedDocument.objects.create(source=self.replacea, target=replaced, relationship=DocRelationshipName.objects.get(slug="possibly-replaces")) diff --git a/ietf/doc/tests_material.py b/ietf/doc/tests_material.py index 687719a5c..c2d857d70 100644 --- a/ietf/doc/tests_material.py +++ b/ietf/doc/tests_material.py @@ -1,4 +1,5 @@ -# Copyright The IETF Trust 2011, All Rights Reserved +# Copyright The IETF Trust 2011-2019, All Rights Reserved +# -*- coding: utf-8 -*- import os import shutil @@ -52,7 +53,7 @@ class GroupMaterialTests(TestCase): doc = Document.objects.create(name="slides-testteam-test-file", rev="01", type_id="slides", group=group) doc.set_state(State.objects.get(type="slides", slug="active")) doc.set_state(State.objects.get(type="reuse_policy", slug="multiple")) - DocAlias.objects.create(name=doc.name, document=doc) + DocAlias.objects.create(name=doc.name).docs.add(doc) NewRevisionDocEvent.objects.create(doc=doc,by=Person.objects.get(name="(System)"),rev='00',type='new_revision',desc='New revision available') NewRevisionDocEvent.objects.create(doc=doc,by=Person.objects.get(name="(System)"),rev='01',type='new_revision',desc='New revision available') diff --git a/ietf/doc/tests_review.py b/ietf/doc/tests_review.py index d78c31437..40fe8da5f 100644 --- a/ietf/doc/tests_review.py +++ b/ietf/doc/tests_review.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2016-2019, All Rights Reserved # -*- coding: utf-8 -*- import datetime, os, shutil, json @@ -144,8 +145,8 @@ class ReviewTests(TestCase): # check we can fish it out old_doc = WgDraftFactory(name="draft-foo-mars-test") older_doc = WgDraftFactory(name="draft-older") - RelatedDocument.objects.create(source=old_doc, target=older_doc.docalias_set.first(), relationship_id='replaces') - RelatedDocument.objects.create(source=doc, target=old_doc.docalias_set.first(), relationship_id='replaces') + RelatedDocument.objects.create(source=old_doc, target=older_doc.docalias.first(), relationship_id='replaces') + RelatedDocument.objects.create(source=doc, target=old_doc.docalias.first(), relationship_id='replaces') review_req.doc = older_doc review_req.save() diff --git a/ietf/doc/tests_status_change.py b/ietf/doc/tests_status_change.py index 937191d6c..36d3415bb 100644 --- a/ietf/doc/tests_status_change.py +++ b/ietf/doc/tests_status_change.py @@ -1,4 +1,6 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved # -*- coding: utf-8 -*- + import os import shutil @@ -74,7 +76,7 @@ class StatusChangeTests(TestCase): self.assertEqual(status_change.rev,u'00') self.assertEqual(status_change.ad.name,u'Areað Irector') self.assertEqual(status_change.notify,u'ipu@ietf.org') - self.assertTrue(status_change.relateddocument_set.filter(relationship__slug='tois',target__document__name='draft-ietf-random-thing')) + self.assertTrue(status_change.relateddocument_set.filter(relationship__slug='tois',target__docs__name='draft-ietf-random-thing')) def test_change_state(self): diff --git a/ietf/doc/utils.py b/ietf/doc/utils.py index 69fee36f9..d38d00e43 100644 --- a/ietf/doc/utils.py +++ b/ietf/doc/utils.py @@ -1,3 +1,6 @@ +# Copyright The IETF Trust 2011-2019, All Rights Reserved +# -*- coding: utf-8 -*- + import os import re import urllib @@ -684,10 +687,8 @@ def extract_complete_replaces_ancestor_mapping_for_docs(names): if not front: break - relations = RelatedDocument.objects.filter( - source__in=front, relationship="replaces" - ).select_related("target").values_list("source", "target__document") - + relations = ( RelatedDocument.objects.filter(source__name__in=front, relationship="replaces") + .select_related("target").values_list("source__name", "target__docs__name") ) if not relations: break diff --git a/ietf/doc/utils_search.py b/ietf/doc/utils_search.py index 31b365e27..ae25bef31 100644 --- a/ietf/doc/utils_search.py +++ b/ietf/doc/utils_search.py @@ -1,4 +1,5 @@ -# Copyright The IETF Trust 2016, All Rights Reserved +# Copyright The IETF Trust 2016-2019, All Rights Reserved +# -*- coding: utf-8 -*- import datetime import debug # pyflakes:ignore @@ -20,7 +21,7 @@ def fill_in_telechat_date(docs, doc_dict=None, doc_ids=None): doc_ids = doc_dict.keys() seen = set() - for e in TelechatDocEvent.objects.filter(doc__in=doc_ids, type="scheduled_for_telechat").order_by('-time'): + for e in TelechatDocEvent.objects.filter(doc__id__in=doc_ids, type="scheduled_for_telechat").order_by('-time'): if e.doc_id not in seen: d = doc_dict[e.doc_id] d.telechat_date = wrap_value(d.telechat_date(e)) @@ -49,7 +50,7 @@ def fill_in_document_table_attributes(docs, have_telechat_date=False): doc_dict = dict((d.pk, d) for d in docs) doc_ids = doc_dict.keys() - rfc_aliases = dict(DocAlias.objects.filter(name__startswith="rfc", document__in=doc_ids).values_list("document", "name")) + rfc_aliases = dict([ (a.document.id, a.name) for a in DocAlias.objects.filter(name__startswith="rfc", docs__id__in=doc_ids) ]) # latest event cache event_types = ("published_rfc", @@ -61,11 +62,11 @@ def fill_in_document_table_attributes(docs, have_telechat_date=False): for e in event_types: d.latest_event_cache[e] = None - for e in DocEvent.objects.filter(doc__in=doc_ids, type__in=event_types).order_by('time'): + for e in DocEvent.objects.filter(doc__id__in=doc_ids, type__in=event_types).order_by('time'): doc_dict[e.doc_id].latest_event_cache[e.type] = e seen = set() - for e in BallotDocEvent.objects.filter(doc__in=doc_ids, type__in=('created_ballot', 'closed_ballot')).order_by('-time','-id'): + for e in BallotDocEvent.objects.filter(doc__id__in=doc_ids, type__in=('created_ballot', 'closed_ballot')).order_by('-time','-id'): if not e.doc_id in seen: doc_dict[e.doc_id].ballot = e if e.type == 'created_ballot' else None seen.add(e.doc_id) @@ -122,11 +123,10 @@ def fill_in_document_table_attributes(docs, have_telechat_date=False): d.updated_by_list = [] xed_by = RelatedDocument.objects.filter(target__name__in=rfc_aliases.values(), - relationship__in=("obs", "updates")).select_related('target__document') - rel_rfc_aliases = dict(DocAlias.objects.filter(name__startswith="rfc", - document__in=[rel.source_id for rel in xed_by]).values_list('document', 'name')) + relationship__in=("obs", "updates")).select_related('target') + rel_rfc_aliases = dict([ (a.document.id, a.name) for a in DocAlias.objects.filter(name__startswith="rfc", docs__id__in=[rel.source_id for rel in xed_by]) ]) for rel in xed_by: - d = doc_dict[rel.target.document_id] + d = doc_dict[rel.target.document.id] if rel.relationship_id == "obs": l = d.obsoleted_by_list elif rel.relationship_id == "updates": @@ -146,7 +146,7 @@ def prepare_document_table(request, docs, query=None, max_results=200): # the number of queries docs = docs.select_related("ad", "std_level", "intended_std_level", "group", "stream", "shepherd", ) docs = docs.prefetch_related("states__type", "tags", "groupmilestone_set__group", "reviewrequest_set__team", - "submission_set__checks", "ad__email_set", "docalias_set__iprdocrel_set") + "submission_set__checks", "ad__email_set", "docalias__iprdocrel_set") if docs.count() > max_results: docs = docs[:max_results] diff --git a/ietf/doc/views_charter.py b/ietf/doc/views_charter.py index 39e8eac99..2f6f36e19 100644 --- a/ietf/doc/views_charter.py +++ b/ietf/doc/views_charter.py @@ -1,3 +1,6 @@ +# Copyright The IETF Trust 2011-2019, All Rights Reserved +# -*- coding: utf-8 -*- + import os, datetime, textwrap, json from django.http import HttpResponseRedirect, HttpResponseNotFound, HttpResponseForbidden, Http404 @@ -392,7 +395,7 @@ def submit(request, name, option=None): abstract=group.name, rev=next_rev, ) - DocAlias.objects.create(name=charter.name, document=charter) + DocAlias.objects.create(name=charter.name).docs.add(charter) charter.set_state(State.objects.get(used=True, type="charter", slug="notrev")) diff --git a/ietf/doc/views_conflict_review.py b/ietf/doc/views_conflict_review.py index 350d5a4c4..03d06235b 100644 --- a/ietf/doc/views_conflict_review.py +++ b/ietf/doc/views_conflict_review.py @@ -1,3 +1,6 @@ +# Copyright The IETF Trust 2012-2019, All Rights Reserved +# -*- coding: utf-8 -*- + import datetime, os from django import forms @@ -388,7 +391,7 @@ def start_review_sanity_check(request, name): raise Http404 # sanity check that there's not already a conflict review document for this document - if [ rel.source for alias in doc_to_review.docalias_set.all() for rel in alias.relateddocument_set.filter(relationship='conflrev') ]: + if [ rel.source for alias in doc_to_review.docalias.all() for rel in alias.relateddocument_set.filter(relationship='conflrev') ]: raise Http404 return doc_to_review @@ -421,7 +424,8 @@ def build_conflict_review_document(login, doc_to_review, ad, notify, create_in_s ) conflict_review.set_state(create_in_state) - DocAlias.objects.create( name=review_name , document=conflict_review ) + DocAlias.objects.create( name=review_name).docs.add( conflict_review ) + conflict_review.relateddocument_set.create(target=DocAlias.objects.get(name=doc_to_review.name),relationship_id='conflrev') diff --git a/ietf/doc/views_doc.py b/ietf/doc/views_doc.py index eacba0cc4..343d6e1f4 100644 --- a/ietf/doc/views_doc.py +++ b/ietf/doc/views_doc.py @@ -103,7 +103,7 @@ def document_main(request, name, rev=None): doc = get_object_or_404(Document.objects.select_related(), docalias__name=name) # take care of possible redirections - aliases = DocAlias.objects.filter(document=doc).values_list("name", flat=True) + aliases = DocAlias.objects.filter(docs=doc).values_list("name", flat=True) if rev==None and doc.type_id == "draft" and not name.startswith("rfc"): for a in aliases: if a.startswith("rfc"): @@ -382,7 +382,7 @@ def document_main(request, name, rev=None): published = doc.latest_event(type="published_rfc") started_iesg_process = doc.latest_event(type="started_iesg_process") - review_assignments = review_assignments_to_list_for_docs([doc]).get(doc.pk, []) + review_assignments = review_assignments_to_list_for_docs([doc]).get(doc.name, []) no_review_from_teams = no_review_from_teams_on_doc(doc, rev or doc.rev) return render(request, "doc/document_draft.html", @@ -598,12 +598,12 @@ def document_main(request, name, rev=None): # If we want to go back to using markup_txt.markup_unicode, call it explicitly here like this: # content = markup_txt.markup_unicode(content, split=False, width=80) - assignments = ReviewAssignment.objects.filter(review=doc.name) + assignments = ReviewAssignment.objects.filter(review__name=doc.name) review_assignment = assignments.first() other_reviews = [] if review_assignment: - other_reviews = [r for r in review_assignments_to_list_for_docs([review_assignment.review_request.doc]).get(doc.pk, []) if r != review_assignment] + other_reviews = [r for r in review_assignments_to_list_for_docs([review_assignment.review_request.doc]).get(doc.name, []) if r != review_assignment] return render(request, "doc/document_review.html", dict(doc=doc, @@ -716,7 +716,7 @@ def document_history(request, name): if doc.get_state_slug() == "rfc": e = doc.latest_event(type="published_rfc") - aliases = doc.docalias_set.filter(name__startswith="rfc") + aliases = doc.docalias.filter(name__startswith="rfc") if aliases: name = aliases[0].name diff_revisions.append((name, "", e.time if e else doc.time, name)) @@ -1011,7 +1011,7 @@ def document_json(request, name, rev=None): data["expires"] = doc.expires.strftime("%Y-%m-%d %H:%M:%S") if doc.expires else None data["title"] = doc.title data["abstract"] = doc.abstract - data["aliases"] = list(doc.docalias_set.values_list("name", flat=True)) + data["aliases"] = list(doc.docalias.values_list("name", flat=True)) data["state"] = extract_name(doc.get_state()) data["intended_std_level"] = extract_name(doc.intended_std_level) data["std_level"] = extract_name(doc.std_level) diff --git a/ietf/doc/views_material.py b/ietf/doc/views_material.py index dbbc98369..5cc5609cb 100644 --- a/ietf/doc/views_material.py +++ b/ietf/doc/views_material.py @@ -1,3 +1,6 @@ +# Copyright The IETF Trust 2014-2019, All Rights Reserved +# -*- coding: utf-8 -*- + # views for managing group materials (slides, ...) import os import re @@ -142,7 +145,8 @@ def edit_material(request, name=None, acronym=None, action=None, doc_type=None): dest.write(chunk) if action == "new": - DocAlias.objects.get_or_create(name=doc.name, document=doc) + alias, __ = DocAlias.objects.get_or_create(name=doc.name) + alias.docs.add(doc) if prev_rev != doc.rev: e = NewRevisionDocEvent(type="new_revision", doc=doc, rev=doc.rev) diff --git a/ietf/doc/views_review.py b/ietf/doc/views_review.py index 8101226b7..cec4fbfbc 100644 --- a/ietf/doc/views_review.py +++ b/ietf/doc/views_review.py @@ -1,5 +1,5 @@ +# Copyright The IETF Trust 2016-2019, All Rights Reserved # -*- coding: utf-8 -*- -# Copyright The IETF Trust 2011, All Rights Reserved from __future__ import unicode_literals, print_function import os @@ -593,7 +593,7 @@ def complete_review(request, name, assignment_id): name = "-".join(c for c in name_components if c).lower() if not Document.objects.filter(name=name).exists(): review = Document.objects.create(name=name) - DocAlias.objects.create(document=review, name=review.name) + DocAlias.objects.create(name=review.name).docs.add(review) break review.type = DocTypeName.objects.get(slug="review") diff --git a/ietf/doc/views_search.py b/ietf/doc/views_search.py index 8bd40ed4f..24ec9f51e 100644 --- a/ietf/doc/views_search.py +++ b/ietf/doc/views_search.py @@ -1,4 +1,7 @@ -# Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). +# Copyright The IETF Trust 2009-2019, All Rights Reserved +# -*- coding: utf-8 -*- + +# Some parts Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). # All rights reserved. Contact: Pasi Eronen # # Redistribution and use in source and binary forms, with or without @@ -478,7 +481,7 @@ def index_all_drafts(request): else: heading = "%s Internet-Drafts" % state.name - draft_names = DocAlias.objects.filter(document__states=state).values_list("name", "document") + draft_names = DocAlias.objects.filter(docs__states=state).values_list("name", "docs__name") names = [] names_to_skip = set() @@ -528,7 +531,7 @@ def ajax_select2_search_docs(request, model_name, doc_type): if model == Document: qs = qs.filter(type=doc_type) elif model == DocAlias: - qs = qs.filter(document__type=doc_type) + qs = qs.filter(docs__type=doc_type) for t in q: qs = qs.filter(name__icontains=t) diff --git a/ietf/doc/views_status_change.py b/ietf/doc/views_status_change.py index 5be43e3c7..d62319fad 100644 --- a/ietf/doc/views_status_change.py +++ b/ietf/doc/views_status_change.py @@ -1,3 +1,6 @@ +# Copyright The IETF Trust 2012-2019, All Rights Reserved +# -*- coding: utf-8 -*- + import datetime, os, re from django import forms @@ -527,7 +530,7 @@ def start_rfc_status_change(request,name): ) status_change.set_state(form.cleaned_data['create_in_state']) - DocAlias.objects.create( name= 'status-change-'+form.cleaned_data['document_name'], document=status_change ) + DocAlias.objects.create( name= 'status-change-'+form.cleaned_data['document_name']).docs.add(status_change) for key in form.cleaned_data['relations']: status_change.relateddocument_set.create(target=DocAlias.objects.get(name=key), diff --git a/ietf/group/dot.py b/ietf/group/dot.py index 00a65f733..abb5c4efe 100644 --- a/ietf/group/dot.py +++ b/ietf/group/dot.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2007, All Rights Reserved +# Copyright The IETF Trust 2007-2019, All Rights Reserved # -*- check-flake8 -*- from __future__ import unicode_literals, print_function @@ -100,7 +100,7 @@ def get_node_styles(node, group): def make_dot(group): references = Q(source__group=group, source__type='draft', relationship__slug__startswith='ref') - both_rfcs = Q(source__states__slug='rfc', target__document__states__slug='rfc') + both_rfcs = Q(source__states__slug='rfc', target__docs__states__slug='rfc') inactive = Q(source__states__slug__in=['expired', 'repl']) attractor = Q(target__name__in=['rfc5000', 'rfc5741']) removed = Q(source__states__slug__in=['auth-rm', 'ietf-rm']) @@ -114,7 +114,7 @@ def make_dot(group): edges.add(Edge(x)) replacements = RelatedDocument.objects.filter(relationship__slug='replaces', - target__document__in=[x.relateddocument.target.document for x in edges]) + target__docs__in=[x.relateddocument.target.document for x in edges]) for x in replacements: edges.add(Edge(x)) diff --git a/ietf/group/feeds.py b/ietf/group/feeds.py index 3b36b0608..c41b2ada2 100644 --- a/ietf/group/feeds.py +++ b/ietf/group/feeds.py @@ -1,4 +1,5 @@ -# Copyright The IETF Trust 2011, All Rights Reserved +# Copyright The IETF Trust 2011-2019, All Rights Reserved +# -*- coding: utf-8 -*- from django.contrib.syndication.views import Feed, FeedDoesNotExist from django.utils.feedgenerator import Atom1Feed @@ -38,7 +39,7 @@ class GroupChangesFeed(Feed): def item_link(self, obj): if isinstance(obj, DocEvent): - return urlreverse("ietf.doc.views_doc.document_main", kwargs={'name': obj.doc_id }) + return urlreverse("ietf.doc.views_doc.document_main", kwargs={'name': obj.doc.name }) elif isinstance(obj, GroupEvent): return obj.group.about_url() diff --git a/ietf/group/forms.py b/ietf/group/forms.py index 635312263..81dab5aea 100644 --- a/ietf/group/forms.py +++ b/ietf/group/forms.py @@ -1,4 +1,5 @@ -# Copyright The IETF Trust 2007, All Rights Reserved +# Copyright The IETF Trust 2007-2019, All Rights Reserved +# -*- coding: utf-8 -*- from __future__ import unicode_literals, print_function # Stdlib imports @@ -227,7 +228,7 @@ class ManageReviewRequestForm(forms.Form): def __init__(self, review_req, *args, **kwargs): if not "prefix" in kwargs: if review_req.pk is None: - kwargs["prefix"] = "r{}-{}".format(review_req.type_id, review_req.doc_id) + kwargs["prefix"] = "r{}-{}".format(review_req.type_id, review_req.doc.name) else: kwargs["prefix"] = "r{}".format(review_req.pk) diff --git a/ietf/group/migrations/0013_add_groupmilestone_docs2_m2m.py b/ietf/group/migrations/0013_add_groupmilestone_docs2_m2m.py new file mode 100644 index 000000000..1ccca9b13 --- /dev/null +++ b/ietf/group/migrations/0013_add_groupmilestone_docs2_m2m.py @@ -0,0 +1,53 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-02-25 13:02 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import ietf.utils.models + +class Migration(migrations.Migration): + + dependencies = [ + ('group', '0012_add_old_nomcom_announcements'), + ] + + operations = [ + migrations.CreateModel( + name='GroupMilestoneDocs', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('document', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field=b'id')), + ('groupmilestone', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='group.GroupMilestone')), + ], + ), + migrations.CreateModel( + name='GroupMilestoneHistoryDocs', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('document', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field=b'id')), + ('groupmilestonehistory', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='group.GroupMilestoneHistory')), + ], + ), + migrations.AddField( + model_name='group', + name='charter2', + field=ietf.utils.models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='chartered_group', to='doc.Document', to_field=b'id'), + ), + migrations.AlterField( + model_name='group', + name='charter', + field=ietf.utils.models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='old_group', to='doc.Document', to_field=b'name'), + ), + migrations.AddField( + model_name='groupmilestone', + name='docs2', + field=models.ManyToManyField(blank=True, related_name='groupmilestones', through='group.GroupMilestoneDocs', to='doc.Document'), + ), + migrations.AddField( + model_name='groupmilestonehistory', + name='docs2', + field=models.ManyToManyField(blank=True, related_name='groupmilestoneshistory', through='group.GroupMilestoneHistoryDocs', to='doc.Document'), + ), + ] diff --git a/ietf/group/migrations/0014_set_document_m2m_keys.py b/ietf/group/migrations/0014_set_document_m2m_keys.py new file mode 100644 index 000000000..e8324f625 --- /dev/null +++ b/ietf/group/migrations/0014_set_document_m2m_keys.py @@ -0,0 +1,57 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-10 06:48 +from __future__ import unicode_literals + +import sys + +from tqdm import tqdm + +from django.db import migrations + + +def forward(apps, schema_editor): + + Document = apps.get_model('doc','Document') + GroupMilestone = apps.get_model('group', 'GroupMilestone') + GroupMilestoneDocs = apps.get_model('group', 'GroupMilestoneDocs') + GroupMilestoneHistory = apps.get_model('group', 'GroupMilestoneHistory') + GroupMilestoneHistoryDocs = apps.get_model('group', 'GroupMilestoneHistoryDocs') + + # Document id fixup ------------------------------------------------------------ + + objs = Document.objects.in_bulk() + nameid = { o.name: o.id for id, o in objs.iteritems() } + + sys.stderr.write('\n') + + sys.stderr.write(' %s.%s:\n' % (GroupMilestone.__name__, 'docs')) + count = 0 + for m in tqdm(GroupMilestone.objects.all()): + for d in m.docs.all(): + count += 1 + GroupMilestoneDocs.objects.get_or_create(groupmilestone=m, document_id=nameid[d.name]) + sys.stderr.write(' %s GroupMilestoneDocs objects created\n' % (count, )) + + sys.stderr.write(' %s.%s:\n' % (GroupMilestoneHistory.__name__, 'docs')) + count = 0 + for m in tqdm(GroupMilestoneHistory.objects.all()): + for d in m.docs.all(): + count += 1 + GroupMilestoneHistoryDocs.objects.get_or_create(GroupMilestoneHistory=m, document_id=nameid[d.name]) + sys.stderr.write(' %s GroupMilestoneHistoryDocs objects created\n' % (count, )) + + +def reverse(apps, schema_editor): + pass + +class Migration(migrations.Migration): + + dependencies = [ + ('group', '0013_add_groupmilestone_docs2_m2m'), + ('doc', '0014_set_document_docalias_id'), + ] + + operations = [ + migrations.RunPython(forward, reverse), + ] diff --git a/ietf/group/migrations/0015_1_del_docs_m2m_table.py b/ietf/group/migrations/0015_1_del_docs_m2m_table.py new file mode 100644 index 000000000..5b2462ce4 --- /dev/null +++ b/ietf/group/migrations/0015_1_del_docs_m2m_table.py @@ -0,0 +1,41 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-22 08:00 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('group', '0014_set_document_m2m_keys'), + ] + + # The implementation of AlterField in Django 1.11 applies + # 'ALTER TABLE
MODIFY ...;' in order to fix foregn keys + # to the altered field, but as it seems does _not_ fix up m2m + # intermediary tables in an equivalent manner, so here we remove and + # then recreate the m2m tables so they will have the appropriate field + # types. + + operations = [ + migrations.RemoveField( + model_name='groupmilestone', + name='docs', + ), + migrations.RemoveField( + model_name='groupmilestonehistory', + name='docs', + ), + migrations.AddField( + model_name='groupmilestone', + name='docs', + field=models.ManyToManyField(to='doc.Document'), + ), + migrations.AddField( + model_name='groupmilestonehistory', + name='docs', + field=models.ManyToManyField(to='doc.Document'), + ), + ] diff --git a/ietf/group/migrations/0015_2_add_docs_m2m_table.py b/ietf/group/migrations/0015_2_add_docs_m2m_table.py new file mode 100644 index 000000000..cf01621d8 --- /dev/null +++ b/ietf/group/migrations/0015_2_add_docs_m2m_table.py @@ -0,0 +1,41 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-22 08:00 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('group', '0015_1_del_docs_m2m_table'), + ] + + # The implementation of AlterField in Django 1.11 applies + # 'ALTER TABLE
MODIFY ...;' in order to fix foregn keys + # to the altered field, but as it seems does _not_ fix up m2m + # intermediary tables in an equivalent manner, so here we remove and + # then recreate the m2m tables so they will have the appropriate field + # types. + + operations = [ + migrations.RemoveField( + model_name='groupmilestone', + name='docs', + ), + migrations.RemoveField( + model_name='groupmilestonehistory', + name='docs', + ), + migrations.AddField( + model_name='groupmilestone', + name='docs', + field=models.ManyToManyField(blank=True, to='doc.Document'), + ), + migrations.AddField( + model_name='groupmilestonehistory', + name='docs', + field=models.ManyToManyField(blank=True, to='doc.Document'), + ), + ] diff --git a/ietf/group/migrations/0016_copy_docs_m2m_table.py b/ietf/group/migrations/0016_copy_docs_m2m_table.py new file mode 100644 index 000000000..4eef2b618 --- /dev/null +++ b/ietf/group/migrations/0016_copy_docs_m2m_table.py @@ -0,0 +1,58 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-27 05:57 +from __future__ import unicode_literals + +import sys, time + +from tqdm import tqdm + +from django.db import migrations + + +def forward(apps, schema_editor): + + GroupMilestone = apps.get_model('group', 'GroupMilestone') + GroupMilestoneDocs = apps.get_model('group', 'GroupMilestoneDocs') + GroupMilestoneHistory = apps.get_model('group', 'GroupMilestoneHistory') + GroupMilestoneHistoryDocs = apps.get_model('group', 'GroupMilestoneHistoryDocs') + + # Document id fixup ------------------------------------------------------------ + + sys.stderr.write('\n') + + sys.stderr.write(' %s.%s:\n' % (GroupMilestone.__name__, 'docs')) + for m in tqdm(GroupMilestone.objects.all()): + m.docs.set([ d.document for d in GroupMilestoneDocs.objects.filter(groupmilestone=m) ]) + + sys.stderr.write(' %s.%s:\n' % (GroupMilestoneHistory.__name__, 'docs')) + for m in tqdm(GroupMilestoneHistory.objects.all()): + m.docs.set([ d.document for d in GroupMilestoneHistoryDocs.objects.filter(groupmilestonehistory=m) ]) + + +def reverse(apps, schema_editor): + pass + +def timestamp(apps, schema_editor): + sys.stderr.write('\n %s' % time.strftime('%Y-%m-%d %H:%M:%S')) + +class Migration(migrations.Migration): + + dependencies = [ + ('group', '0015_2_add_docs_m2m_table'), + ] + + operations = [ + #migrations.RunPython(forward, reverse), + migrations.RunPython(timestamp, timestamp), + migrations.RunSQL( + "INSERT INTO group_groupmilestone_docs SELECT * FROM group_groupmilestonedocs;", + "" + ), + migrations.RunPython(timestamp, timestamp), + migrations.RunSQL( + "INSERT INTO group_groupmilestonehistory_docs SELECT * FROM group_groupmilestonehistorydocs;", + "" + ), + migrations.RunPython(timestamp, timestamp), + ] diff --git a/ietf/group/migrations/0017_remove_docs2_m2m.py b/ietf/group/migrations/0017_remove_docs2_m2m.py new file mode 100644 index 000000000..26b5784fe --- /dev/null +++ b/ietf/group/migrations/0017_remove_docs2_m2m.py @@ -0,0 +1,46 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-30 03:23 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('group', '0016_copy_docs_m2m_table'), + ] + + operations = [ + migrations.RemoveField( + model_name='groupmilestonedocs', + name='document', + ), + migrations.RemoveField( + model_name='groupmilestonedocs', + name='groupmilestone', + ), + migrations.RemoveField( + model_name='groupmilestonehistorydocs', + name='document', + ), + migrations.RemoveField( + model_name='groupmilestonehistorydocs', + name='groupmilestonehistory', + ), + migrations.RemoveField( + model_name='groupmilestone', + name='docs2', + ), + migrations.RemoveField( + model_name='groupmilestonehistory', + name='docs2', + ), + migrations.DeleteModel( + name='GroupMilestoneDocs', + ), + migrations.DeleteModel( + name='GroupMilestoneHistoryDocs', + ), + ] diff --git a/ietf/group/migrations/0018_remove_old_document_field.py b/ietf/group/migrations/0018_remove_old_document_field.py new file mode 100644 index 000000000..02f85b6d3 --- /dev/null +++ b/ietf/group/migrations/0018_remove_old_document_field.py @@ -0,0 +1,20 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-25 06:51 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('group', '0017_remove_docs2_m2m'), + ] + + operations = [ + migrations.RemoveField( + model_name='group', + name='charter', + ), + ] diff --git a/ietf/group/migrations/0019_rename_field_document2.py b/ietf/group/migrations/0019_rename_field_document2.py new file mode 100644 index 000000000..c4d25d3e5 --- /dev/null +++ b/ietf/group/migrations/0019_rename_field_document2.py @@ -0,0 +1,22 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-25 06:52 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0019_rename_field_document2'), + ('group', '0018_remove_old_document_field'), + ] + + operations = [ + migrations.RenameField( + model_name='group', + old_name='charter2', + new_name='charter', + ), + ] diff --git a/ietf/group/tests.py b/ietf/group/tests.py index 752eb2584..eb0acba7f 100644 --- a/ietf/group/tests.py +++ b/ietf/group/tests.py @@ -1,3 +1,6 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved +# -*- coding: utf-8 -*- + import os from unittest import skipIf @@ -71,7 +74,7 @@ class GroupDocDependencyGraphTests(TestCase): set_coverage_checking(False) a = WgDraftFactory() b = WgDraftFactory() - RelatedDocument.objects.create(source=a,target=b.docalias_set.first(),relationship_id='normref') + RelatedDocument.objects.create(source=a,target=b.docalias.first(),relationship_id='normref') def tearDown(self): set_coverage_checking(True) diff --git a/ietf/group/tests_info.py b/ietf/group/tests_info.py index dcd172e1a..d6ddcf221 100644 --- a/ietf/group/tests_info.py +++ b/ietf/group/tests_info.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2009-2019, All Rights Reserved # -*- coding: utf-8 -*- import os @@ -325,7 +326,7 @@ class GroupPagesTests(TestCase): type_id="slides", ) doc.set_state(State.objects.get(type="slides", slug="active")) - DocAlias.objects.create(name=doc.name, document=doc) + DocAlias.objects.create(name=doc.name).docs.add(doc) for url in group_urlreverse_list(group, 'ietf.group.views.materials'): r = self.client.get(url) diff --git a/ietf/group/tests_review.py b/ietf/group/tests_review.py index 021172a98..36243d598 100644 --- a/ietf/group/tests_review.py +++ b/ietf/group/tests_review.py @@ -1,3 +1,6 @@ +# Copyright The IETF Trust 2016-2019, All Rights Reserved +# -*- coding: utf-8 -*- + import datetime import debug # pyflakes:ignore @@ -237,7 +240,7 @@ class ReviewTests(TestCase): content = """ {% autoescape off %} Reviewer Deadline Draft - {% for r in review_assignments %}{{ r.reviewer.person.plain_name|ljust:"22" }} {{ r.review_request.deadline|date:"Y-m-d" }} {{ r.review_request.doc_id }}-{% if r.review_request.requested_rev %}{{ r.review_request.requested_rev }}{% else %}{{ r.review_request.doc.rev }}{% endif %} + {% for r in review_assignments %}{{ r.reviewer.person.plain_name|ljust:"22" }} {{ r.review_request.deadline|date:"Y-m-d" }} {{ r.review_request.doc.name }}-{% if r.review_request.requested_rev %}{{ r.review_request.requested_rev }}{% else %}{{ r.review_request.doc.rev }}{% endif %} {% endfor %} {% if rotation_list %}Next in the reviewer rotation: @@ -480,13 +483,13 @@ class ReviewTests(TestCase): empty_outbox() email_reviewer_reminder(review_req) self.assertEqual(len(outbox), 1) - self.assertTrue(review_req.doc_id in outbox[0].get_payload(decode=True).decode("utf-8")) + self.assertTrue(review_req.doc.name in outbox[0].get_payload(decode=True).decode("utf-8")) # email secretary empty_outbox() email_secretary_reminder(review_req, secretary_role) self.assertEqual(len(outbox), 1) - self.assertTrue(review_req.doc_id in outbox[0].get_payload(decode=True).decode("utf-8")) + self.assertTrue(review_req.doc.name in outbox[0].get_payload(decode=True).decode("utf-8")) diff --git a/ietf/group/views.py b/ietf/group/views.py index 4aea76267..9dd5c523b 100644 --- a/ietf/group/views.py +++ b/ietf/group/views.py @@ -188,7 +188,7 @@ def fill_in_wg_roles(group): group.secretaries = get_roles("secr", []) def fill_in_wg_drafts(group): - aliases = DocAlias.objects.filter(document__type="draft", document__group=group).select_related('document').order_by("name") + aliases = DocAlias.objects.filter(docs__type="draft", docs__group=group).prefetch_related('docs').order_by("name") group.drafts = [] group.rfcs = [] for a in aliases: @@ -804,7 +804,7 @@ def group_photos(request, group_type=None, acronym=None): # charter.set_state(State.objects.get(used=True, type="charter", slug="notrev")) # # # Create an alias as well -# DocAlias.objects.create(name=charter.name, document=charter) +# DocAlias.objects.create(name=charter.name).docs.add(charter) # # return charter # @@ -1372,7 +1372,7 @@ def reviewer_overview(request, acronym, group_type=None): latest_reqs = [] for d in req_data: if d.state in ["assigned", "accepted"] or len(latest_reqs) < MAX_CLOSED_REQS + open_reqs: - latest_reqs.append((d.assignment_pk, d.doc, d.reviewed_rev, d.assigned_time, d.deadline, + latest_reqs.append((d.assignment_pk, d.doc_name, d.reviewed_rev, d.assigned_time, d.deadline, assignment_state_by_slug.get(d.state), int(math.ceil(d.assignment_to_closure_days)) if d.assignment_to_closure_days is not None else None)) if d.state in ["completed", "completed_in_time", "completed_late"]: @@ -1405,7 +1405,7 @@ def manage_review_requests(request, acronym, group_type=None, assignment_status= document_requests = extract_revision_ordered_review_requests_for_documents_and_replaced( ReviewRequest.objects.filter(state__in=("part-completed", "completed", "assigned"), team=group).prefetch_related("reviewassignment_set__result"), - set(r.doc_id for r in review_requests), + set(r.doc.name for r in review_requests), ) # we need a mutable query dict for resetting upon saving with @@ -1418,7 +1418,7 @@ def manage_review_requests(request, acronym, group_type=None, assignment_status= # add previous requests l = [] rev = None - for r in document_requests.get(req.doc_id, []): + for r in document_requests.get(req.doc.name, []): # take all on the latest reviewed rev for a in r.reviewassignment_set.all(): if l and rev: @@ -1706,7 +1706,7 @@ def change_reviewer_settings(request, acronym, reviewer_email, group_type=None): msg += "{} is currently assigned to review:".format(reviewer_role.person) for r in review_assignments: msg += "\n\n" - msg += "{} (deadline: {})".format(r.review_request.doc_id, r.review_request.deadline.isoformat()) + msg += "{} (deadline: {})".format(r.review_request.doc.name, r.review_request.deadline.isoformat()) else: msg += "{} does not have any assignments currently.".format(reviewer_role.person) diff --git a/ietf/idindex/index.py b/ietf/idindex/index.py index 2846fc17e..547dd6787 100644 --- a/ietf/idindex/index.py +++ b/ietf/idindex/index.py @@ -1,3 +1,6 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved +# -*- coding: utf-8 -*- + # code to generate plain-text index files that are placed on # www.ietf.org in the same directory as the I-Ds @@ -22,17 +25,17 @@ def all_id_txt(): # this returns a lot of data so try to be efficient # precalculations - revision_time = dict(NewRevisionDocEvent.objects.filter(type="new_revision", doc__name__startswith="draft-").order_by('time').values_list("doc_id", "time")) + revision_time = dict(NewRevisionDocEvent.objects.filter(type="new_revision", doc__name__startswith="draft-").order_by('time').values_list("doc__name", "time")) def formatted_rev_date(name): t = revision_time.get(name) return t.strftime("%Y-%m-%d") if t else "" rfc_aliases = dict(DocAlias.objects.filter(name__startswith="rfc", - document__states=State.objects.get(type="draft", slug="rfc")).values_list("document_id", "name")) + docs__states=State.objects.get(type="draft", slug="rfc")).values_list("docs__name", "name")) - replacements = dict(RelatedDocument.objects.filter(target__document__states=State.objects.get(type="draft", slug="repl"), - relationship="replaces").values_list("target__document_id", "source")) + replacements = dict(RelatedDocument.objects.filter(target__docs__states=State.objects.get(type="draft", slug="repl"), + relationship="replaces").values_list("target__name", "source__name")) # we need a distinct to prevent the queries below from multiplying the result @@ -66,7 +69,7 @@ def all_id_txt(): # handle the rest - not_in_process = all_ids.exclude(pk__in=[d.name for d in in_iesg_process]) + not_in_process = all_ids.exclude(pk__in=[d.pk for d in in_iesg_process]) for s in State.objects.filter(type="draft").order_by("order"): for name, rev in not_in_process.filter(states=s).values_list("name", "rev"): @@ -110,21 +113,21 @@ def all_id2_txt(): drafts = drafts.prefetch_related("states") rfc_aliases = dict(DocAlias.objects.filter(name__startswith="rfc", - document__states=State.objects.get(type="draft", slug="rfc")).values_list("document_id", "name")) + docs__states=State.objects.get(type="draft", slug="rfc")).values_list("docs__name", "name")) - replacements = dict(RelatedDocument.objects.filter(target__document__states=State.objects.get(type="draft", slug="repl"), - relationship="replaces").values_list("target__document_id", "source")) + replacements = dict(RelatedDocument.objects.filter(target__docs__states=State.objects.get(type="draft", slug="repl"), + relationship="replaces").values_list("target__name", "source__name")) - revision_time = dict(DocEvent.objects.filter(type="new_revision", doc__name__startswith="draft-").order_by('time').values_list("doc_id", "time")) + revision_time = dict(DocEvent.objects.filter(type="new_revision", doc__name__startswith="draft-").order_by('time').values_list("doc__name", "time")) file_types = file_types_for_drafts() authors = {} for a in DocumentAuthor.objects.filter(document__name__startswith="draft-").order_by("order").select_related("email", "person").iterator(): - if a.document_id not in authors: - l = authors[a.document_id] = [] + if a.document.name not in authors: + l = authors[a.document.name] = [] else: - l = authors[a.document_id] + l = authors[a.document.name] if a.email: l.append(u'%s <%s>' % (a.person.plain_name().replace("@", ""), a.email.address.replace(",", ""))) else: @@ -239,8 +242,8 @@ def active_drafts_index_by_group(extra_values=()): docs_dict[d.name]['group_id'] = individual.id # add initial and latest revision time - for time, doc_id in NewRevisionDocEvent.objects.filter(type="new_revision", doc__states=active_state).order_by('-time').values_list("time", "doc_id"): - d = docs_dict.get(doc_id) + for time, doc_name in NewRevisionDocEvent.objects.filter(type="new_revision", doc__states=active_state).order_by('-time').values_list("time", "doc__name"): + d = docs_dict.get(doc_name) if d: if "rev_time" not in d: d["rev_time"] = time @@ -248,7 +251,7 @@ def active_drafts_index_by_group(extra_values=()): # add authors for a in DocumentAuthor.objects.filter(document__states=active_state).order_by("order").select_related("person"): - d = docs_dict.get(a.document_id) + d = docs_dict.get(a.document.name) if d: if "authors" not in d: d["authors"] = [] diff --git a/ietf/idindex/tests.py b/ietf/idindex/tests.py index d4979087e..b4817d24f 100644 --- a/ietf/idindex/tests.py +++ b/ietf/idindex/tests.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2009-2019, All Rights Reserved # -*- coding: utf-8 -*- import os @@ -47,7 +48,7 @@ class IndexTests(TestCase): # published draft.set_state(State.objects.get(type="draft", slug="rfc")) - DocAlias.objects.create(name="rfc1234", document=draft) + DocAlias.objects.create(name="rfc1234").docs.add(draft) txt = all_id_txt() self.assertTrue(draft.name + "-" + draft.rev in txt) @@ -59,7 +60,7 @@ class IndexTests(TestCase): RelatedDocument.objects.create( relationship=DocRelationshipName.objects.get(slug="replaces"), source=Document.objects.create(type_id="draft", rev="00", name="draft-test-replacement"), - target=draft.docalias_set.get(name__startswith="draft")) + target=draft.docalias.get(name__startswith="draft")) txt = all_id_txt() self.assertTrue(draft.name + "-" + draft.rev in txt) @@ -109,7 +110,7 @@ class IndexTests(TestCase): # test RFC draft.set_state(State.objects.get(type="draft", slug="rfc")) - DocAlias.objects.create(name="rfc1234", document=draft) + DocAlias.objects.create(name="rfc1234").docs.add(draft) t = get_fields(all_id2_txt()) self.assertEqual(t[4], "1234") @@ -118,7 +119,7 @@ class IndexTests(TestCase): RelatedDocument.objects.create( relationship=DocRelationshipName.objects.get(slug="replaces"), source=Document.objects.create(type_id="draft", rev="00", name="draft-test-replacement"), - target=draft.docalias_set.get(name__startswith="draft")) + target=draft.docalias.get(name__startswith="draft")) t = get_fields(all_id2_txt()) self.assertEqual(t[5], "draft-test-replacement") diff --git a/ietf/iesg/agenda.py b/ietf/iesg/agenda.py index 46a22adf3..0b43ef374 100644 --- a/ietf/iesg/agenda.py +++ b/ietf/iesg/agenda.py @@ -1,3 +1,6 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved +# -*- coding: utf-8 -*- + # utilities for constructing agendas for IESG telechats import codecs @@ -182,7 +185,7 @@ def fill_in_agenda_docs(date, sections, docs=None): if e and (e.consensus != None): doc.consensus = "Yes" if e.consensus else "No" - doc.review_assignments = review_assignments_for_docs.get(doc.pk, []) + doc.review_assignments = review_assignments_for_docs.get(doc.name, []) elif doc.type_id == "conflrev": doc.conflictdoc = doc.relateddocument_set.get(relationship__slug='conflrev').target.document elif doc.type_id == "charter": diff --git a/ietf/iesg/tests.py b/ietf/iesg/tests.py index 5f80a74ca..9ef344c40 100644 --- a/ietf/iesg/tests.py +++ b/ietf/iesg/tests.py @@ -1,4 +1,6 @@ +# Copyright The IETF Trust 2009-2019, All Rights Reserved # -*- coding: utf-8 -*- + import os import shutil import json @@ -92,7 +94,7 @@ class IESGAgendaTests(TestCase): mars = GroupFactory(acronym='mars',parent=Group.objects.get(acronym='farfut')) wgdraft = WgDraftFactory(name='draft-ietf-mars-test', group=mars, intended_std_level_id='ps') rfc = IndividualRfcFactory.create(stream_id='irtf', other_aliases=['rfc6666',], states=[('draft','rfc'),('draft-iesg','pub')], std_level_id='inf', ) - wgdraft.relateddocument_set.create(target=rfc.docalias_set.get(name='rfc6666'), relationship_id='refnorm') + wgdraft.relateddocument_set.create(target=rfc.docalias.get(name='rfc6666'), relationship_id='refnorm') ise_draft = IndividualDraftFactory(name='draft-imaginary-independent-submission') ise_draft.stream = StreamName.objects.get(slug="ise") ise_draft.save_with_history([DocEvent(doc=ise_draft, rev=ise_draft.rev, type="changed_stream", by=Person.objects.get(user__username="secretary"), desc="Test")]) @@ -216,7 +218,7 @@ class IESGAgendaTests(TestCase): relation = RelatedDocument.objects.create( source=statchg, - target=DocAlias.objects.filter(name__startswith='rfc', document__std_level="ps")[0], + target=DocAlias.objects.filter(name__startswith='rfc', docs__std_level="ps")[0], relationship_id="tohist") statchg.group = Group.objects.get(acronym="mars") @@ -234,7 +236,7 @@ class IESGAgendaTests(TestCase): 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.target = DocAlias.objects.filter(name__startswith='rfc', docs__std_level="inf")[0] relation.save() statchg.group = Group.objects.get(acronym="mars") @@ -493,7 +495,7 @@ class RescheduleOnAgendaTests(TestCase): e.returning_item = True e.save() - form_id = draft.pk + form_id = draft.name url = urlreverse('ietf.iesg.views.agenda_documents') diff --git a/ietf/ietfauth/tests.py b/ietf/ietfauth/tests.py index e1ff2ed50..5da748bb9 100644 --- a/ietf/ietfauth/tests.py +++ b/ietf/ietfauth/tests.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2017, All Rights Reserved +# Copyright The IETF Trust 2017-2019, All Rights Reserved # -*- coding: utf-8 -*- from __future__ import unicode_literals, print_function @@ -384,7 +384,7 @@ class IetfAuthTests(TestCase): # wish to review r = self.client.post(url, { "action": "add_wish", - 'doc': doc.pk, + 'doc': doc.name, "team": review_req.team_id, }) self.assertEqual(r.status_code, 302) diff --git a/ietf/ipr/admin.py b/ietf/ipr/admin.py index 2656dce90..e47f20679 100644 --- a/ietf/ipr/admin.py +++ b/ietf/ipr/admin.py @@ -1,4 +1,6 @@ -#coding: utf-8 +# Copyright The IETF Trust 2010-2019, All Rights Reserved +# -*- coding: utf-8 -*- + from django import forms from django.contrib import admin from ietf.name.models import DocRelationshipName @@ -91,7 +93,7 @@ admin.site.register(IprDocRel, IprDocRelAdmin) class RelatedIprAdmin(admin.ModelAdmin): list_display = ['source', 'target', 'relationship', ] - search_fields = ['source__name', 'target__name', 'target__document__name', ] + search_fields = ['source__name', 'target__name', 'target__docs__name', ] raw_id_fields = ['source', 'target', ] admin.site.register(RelatedIpr, RelatedIprAdmin) diff --git a/ietf/ipr/factories.py b/ietf/ipr/factories.py index f7c333625..62a96f191 100644 --- a/ietf/ipr/factories.py +++ b/ietf/ipr/factories.py @@ -1,3 +1,6 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved +# -*- coding: utf-8 -*- + import datetime import factory @@ -34,7 +37,7 @@ class IprDisclosureBaseFactory(factory.DjangoModelFactory): return if extracted: for doc in extracted: - IprDocRel.objects.create(disclosure=self,document=doc.docalias_set.first()) + IprDocRel.objects.create(disclosure=self,document=doc.docalias.first()) @factory.post_generation def updates(self, create, extracted, **kwargs): diff --git a/ietf/ipr/migrations/0003_add_ipdocrel_document2_fk.py b/ietf/ipr/migrations/0003_add_ipdocrel_document2_fk.py new file mode 100644 index 000000000..a29cede7d --- /dev/null +++ b/ietf/ipr/migrations/0003_add_ipdocrel_document2_fk.py @@ -0,0 +1,29 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-08 11:58 +from __future__ import unicode_literals + +from django.db import migrations +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0015_1_add_fk_to_document_id'), + ('ipr', '0002_auto_20180225_1207'), + ] + + operations = [ + migrations.AddField( + model_name='iprdocrel', + name='document2', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.DocAlias', to_field=b'id'), + ), + migrations.AlterField( + model_name='iprdocrel', + name='document', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='old_ipr', to='doc.DocAlias', to_field=b'name'), + ), + ] diff --git a/ietf/ipr/migrations/0004_remove_iprdocrel_document.py b/ietf/ipr/migrations/0004_remove_iprdocrel_document.py new file mode 100644 index 000000000..313973632 --- /dev/null +++ b/ietf/ipr/migrations/0004_remove_iprdocrel_document.py @@ -0,0 +1,20 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-20 09:53 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('ipr', '0003_add_ipdocrel_document2_fk'), + ] + + operations = [ + migrations.RemoveField( + model_name='iprdocrel', + name='document', + ), + ] diff --git a/ietf/ipr/migrations/0005_rename_field_document2.py b/ietf/ipr/migrations/0005_rename_field_document2.py new file mode 100644 index 000000000..374e6806e --- /dev/null +++ b/ietf/ipr/migrations/0005_rename_field_document2.py @@ -0,0 +1,22 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-21 05:31 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0019_rename_field_document2'), + ('ipr', '0004_remove_iprdocrel_document'), + ] + + operations = [ + migrations.RenameField( + model_name='iprdocrel', + old_name='document2', + new_name='document', + ), + ] diff --git a/ietf/ipr/migrations/0006_document_primary_key_cleanup.py b/ietf/ipr/migrations/0006_document_primary_key_cleanup.py new file mode 100644 index 000000000..fb31a1b78 --- /dev/null +++ b/ietf/ipr/migrations/0006_document_primary_key_cleanup.py @@ -0,0 +1,23 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-06-10 03:42 +from __future__ import unicode_literals + +from django.db import migrations +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ipr', '0005_rename_field_document2'), + ] + + operations = [ + migrations.AlterField( + model_name='iprdocrel', + name='document', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.DocAlias'), + ), + ] diff --git a/ietf/ipr/tests.py b/ietf/ipr/tests.py index 24a4f3fae..3a36d1438 100644 --- a/ietf/ipr/tests.py +++ b/ietf/ipr/tests.py @@ -1,3 +1,6 @@ +# Copyright The IETF Trust 2009-2019, All Rights Reserved +# -*- coding: utf-8 -*- + import datetime import urllib @@ -157,7 +160,7 @@ class IprTests(TestCase): self.assertTrue(draft.name in unicontent(r)) self.assertTrue(ipr.title not in unicontent(r)) - DocAlias.objects.create(name="rfc321", document=draft) + DocAlias.objects.create(name="rfc321").docs.add(draft) # find RFC r = self.client.get(url + "?submit=rfc&rfc=321") @@ -260,9 +263,9 @@ class IprTests(TestCase): "ietfer_contact_info": "555-555-0101", "iprdocrel_set-TOTAL_FORMS": 2, "iprdocrel_set-INITIAL_FORMS": 0, - "iprdocrel_set-0-document": "%s" % draft.docalias_set.first().pk, + "iprdocrel_set-0-document": "%s" % draft.docalias.first().name, "iprdocrel_set-0-revisions": '00', - "iprdocrel_set-1-document": DocAlias.objects.filter(name__startswith="rfc").first().pk, + "iprdocrel_set-1-document": DocAlias.objects.filter(name__startswith="rfc").first().name, "patent_number": "SE12345678901", "patent_inventor": "A. Nonymous", "patent_title": "A method of transfering bits", @@ -303,9 +306,9 @@ class IprTests(TestCase): "ietfer_contact_info": "555-555-0101", "iprdocrel_set-TOTAL_FORMS": 2, "iprdocrel_set-INITIAL_FORMS": 0, - "iprdocrel_set-0-document": "%s" % draft.docalias_set.first().pk, + "iprdocrel_set-0-document": "%s" % draft.docalias.first().name, "iprdocrel_set-0-revisions": '00', - "iprdocrel_set-1-document": DocAlias.objects.filter(name__startswith="rfc").first().pk, + "iprdocrel_set-1-document": DocAlias.objects.filter(name__startswith="rfc").first().name, "patent_number": "SE12345678901", "patent_inventor": "A. Nonymous", "patent_title": "A method of transfering bits", @@ -351,7 +354,7 @@ class IprTests(TestCase): "holder_legal_name": "Test Legal", "ietfer_contact_info": "555-555-0101", "ietfer_name": "Test Participant", - "iprdocrel_set-0-document": "%s" % draft.docalias_set.first().pk, + "iprdocrel_set-0-document": "%s" % draft.docalias.first().name, "iprdocrel_set-0-revisions": '00', "iprdocrel_set-INITIAL_FORMS": 0, "iprdocrel_set-TOTAL_FORMS": 1, @@ -400,9 +403,9 @@ class IprTests(TestCase): "ietfer_contact_info": "555-555-0101", "iprdocrel_set-TOTAL_FORMS": 2, "iprdocrel_set-INITIAL_FORMS": 0, - "iprdocrel_set-0-document": "%s" % draft.docalias_set.first().pk, + "iprdocrel_set-0-document": "%s" % draft.docalias.first().name, "iprdocrel_set-0-revisions": '00', - "iprdocrel_set-1-document": DocAlias.objects.filter(name__startswith="rfc").first().pk, + "iprdocrel_set-1-document": DocAlias.objects.filter(name__startswith="rfc").first().name, "patent_number": "SE12345678901", "patent_inventor": "A. Nonymous", "patent_title": "A method of transfering bits", @@ -438,7 +441,7 @@ class IprTests(TestCase): "holder_contact_email": "test@holder.com", "iprdocrel_set-TOTAL_FORMS": 1, "iprdocrel_set-INITIAL_FORMS": 0, - "iprdocrel_set-0-document": "%s" % draft.docalias_set.first().pk, + "iprdocrel_set-0-document": "%s" % draft.docalias.first().name, "iprdocrel_set-0-revisions": '00', "patent_number": "SE12345678901", "patent_inventor": "A. Nonymous", @@ -627,7 +630,7 @@ Subject: test 'iprdocrel_set-TOTAL_FORMS' : 1, 'iprdocrel_set-INITIAL_FORMS' : 1, 'iprdocrel_set-0-id': disclosure.pk, - "iprdocrel_set-0-document": disclosure.docs.first().pk, + "iprdocrel_set-0-document": disclosure.docs.first().name, "iprdocrel_set-0-revisions": disclosure.docs.first().document.rev, 'holder_legal_name': disclosure.holder_legal_name, 'patent_number': patent_dict['Number'], diff --git a/ietf/ipr/utils.py b/ietf/ipr/utils.py index 04bab1e39..2cb05aa29 100644 --- a/ietf/ipr/utils.py +++ b/ietf/ipr/utils.py @@ -1,3 +1,8 @@ +# Copyright The IETF Trust 2014-2019, All Rights Reserved +# -*- coding: utf-8 -*- + +import debug # pyflakes:ignore + def get_genitive(name): """Return the genitive form of name""" return name + "'" if name.endswith('s') else name + "'s" @@ -29,23 +34,30 @@ def iprs_from_docs(aliases,**kwargs): """Returns a list of IPRs related to doc aliases""" iprdocrels = [] for alias in aliases: - if alias.document.ipr(**kwargs): - iprdocrels += alias.document.ipr(**kwargs) + for document in alias.docs.all(): + if document.ipr(**kwargs): + iprdocrels += document.ipr(**kwargs) return list(set([i.disclosure for i in iprdocrels])) def related_docs(alias, relationship=('replaces', 'obs')): """Returns list of related documents""" - results = list(alias.document.docalias_set.all()) + + results = [] + for doc in alias.docs.all(): + results += list(doc.docalias.all()) - rels = alias.document.all_relations_that_doc(relationship) + rels = [] + for doc in alias.docs.all(): + rels += list(doc.all_relations_that_doc(relationship)) for rel in rels: - rel_aliases = list(rel.target.document.docalias_set.all()) + rel_aliases = list(rel.target.document.docalias.all()) for x in rel_aliases: x.related = rel x.relation = rel.relationship.revname results += rel_aliases + return list(set(results)) diff --git a/ietf/ipr/views.py b/ietf/ipr/views.py index c5d9614df..2a2a8d139 100644 --- a/ietf/ipr/views.py +++ b/ietf/ipr/views.py @@ -1,4 +1,5 @@ -# Copyright The IETF Trust 2007, All Rights Reserved +# Copyright The IETF Trust 2007-2019, All Rights Reserved +# -*- coding: utf-8 -*- import datetime import itertools @@ -460,16 +461,16 @@ def by_draft_recursive_txt(request): for o in IprDocRel.objects.filter(disclosure__state='posted').select_related('document'): alias = o.document - document = alias.document name = alias.name - related = set(document.docalias_set.all()) | set(document.all_related_that_doc(('obs', 'replaces'))) - for alias in related: - name = alias.name - if name.startswith("rfc"): - name = name.upper() - if not name in docipr: - docipr[name] = [] - docipr[name].append(o.disclosure_id) + for document in alias.docs.all(): + related = set(document.docalias.all()) | set(document.all_related_that_doc(('obs', 'replaces'))) + for alias in related: + name = alias.name + if name.startswith("rfc"): + name = name.upper() + if not name in docipr: + docipr[name] = [] + docipr[name].append(o.disclosure_id) lines = [ u"# Machine-readable list of IPR disclosures by draft name" ] for name, iprs in docipr.iteritems(): @@ -700,7 +701,7 @@ def search(request): # Search by wg acronym # Document list with IPRs elif search_type == "group": - docs = list(DocAlias.objects.filter(document__group=q)) + docs = list(DocAlias.objects.filter(docs__group=q)) related = [] for doc in docs: doc.product_of_this_wg = True @@ -714,7 +715,7 @@ def search(request): # Search by rfc and id title # Document list with IPRs elif search_type == "doctitle": - docs = list(DocAlias.objects.filter(document__title__icontains=q)) + docs = list(DocAlias.objects.filter(docs__title__icontains=q)) related = [] for doc in docs: related += related_docs(doc) diff --git a/ietf/liaisons/forms.py b/ietf/liaisons/forms.py index b059ed5f2..c465c1280 100644 --- a/ietf/liaisons/forms.py +++ b/ietf/liaisons/forms.py @@ -1,3 +1,6 @@ +# Copyright The IETF Trust 2011-2019, All Rights Reserved +# -*- coding: utf-8 -*- + import datetime, os import operator import six @@ -25,7 +28,7 @@ from ietf.liaisons.fields import SearchableLiaisonStatementsField from ietf.group.models import Group from ietf.person.models import Email from ietf.person.fields import SearchableEmailField -from ietf.doc.models import Document +from ietf.doc.models import Document, DocAlias from ietf.utils.fields import DatepickerDateField ''' @@ -370,7 +373,7 @@ class LiaisonModelForm(BetterModelForm): ) ) if created: - attach.docalias_set.create(name=attach.name) + DocAlias.objects.create(name=attach.name).docs.add(attach) LiaisonStatementAttachment.objects.create(statement=self.instance,document=attach) attach_file = open(os.path.join(settings.LIAISON_ATTACH_PATH, attach.name + extension), 'w') attach_file.write(attached_file.read()) diff --git a/ietf/liaisons/migrations/0003_liaison_document2_fk.py b/ietf/liaisons/migrations/0003_liaison_document2_fk.py new file mode 100644 index 000000000..659899d4f --- /dev/null +++ b/ietf/liaisons/migrations/0003_liaison_document2_fk.py @@ -0,0 +1,29 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-08 11:58 +from __future__ import unicode_literals + +from django.db import migrations +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0015_1_add_fk_to_document_id'), + ('liaisons', '0002_auto_20180225_1207'), + ] + + operations = [ + migrations.AddField( + model_name='liaisonstatementattachment', + name='document2', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field=b'id'), + ), + migrations.AlterField( + model_name='liaisonstatementattachment', + name='document', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='old_liaison', to='doc.Document', to_field=b'name'), + ), + ] diff --git a/ietf/liaisons/migrations/0004_remove_liaisonstatementattachment_document.py b/ietf/liaisons/migrations/0004_remove_liaisonstatementattachment_document.py new file mode 100644 index 000000000..b5438e6b7 --- /dev/null +++ b/ietf/liaisons/migrations/0004_remove_liaisonstatementattachment_document.py @@ -0,0 +1,20 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-20 09:53 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('liaisons', '0003_liaison_document2_fk'), + ] + + operations = [ + migrations.RemoveField( + model_name='liaisonstatementattachment', + name='document', + ), + ] diff --git a/ietf/liaisons/migrations/0005_rename_field_document2.py b/ietf/liaisons/migrations/0005_rename_field_document2.py new file mode 100644 index 000000000..e5df89916 --- /dev/null +++ b/ietf/liaisons/migrations/0005_rename_field_document2.py @@ -0,0 +1,22 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-21 05:31 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0019_rename_field_document2'), + ('liaisons', '0004_remove_liaisonstatementattachment_document'), + ] + + operations = [ + migrations.RenameField( + model_name='liaisonstatementattachment', + old_name='document2', + new_name='document', + ), + ] diff --git a/ietf/liaisons/migrations/0006_document_primary_key_cleanup.py b/ietf/liaisons/migrations/0006_document_primary_key_cleanup.py new file mode 100644 index 000000000..c61220811 --- /dev/null +++ b/ietf/liaisons/migrations/0006_document_primary_key_cleanup.py @@ -0,0 +1,23 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-06-10 03:47 +from __future__ import unicode_literals + +from django.db import migrations +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('liaisons', '0005_rename_field_document2'), + ] + + operations = [ + migrations.AlterField( + model_name='liaisonstatementattachment', + name='document', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document'), + ), + ] diff --git a/ietf/meeting/forms.py b/ietf/meeting/forms.py index 645ad6b40..a50965bec 100644 --- a/ietf/meeting/forms.py +++ b/ietf/meeting/forms.py @@ -1,3 +1,6 @@ +# Copyright The IETF Trust 2016-2019, All Rights Reserved +# -*- coding: utf-8 -*- + import os import codecs import datetime @@ -271,7 +274,7 @@ class InterimSessionModelForm(forms.ModelForm): # FIXME: What about agendas in html or markdown format? uploaded_filename='{}-00.txt'.format(filename)) doc.set_state(State.objects.get(type__slug=doc.type.slug, slug='active')) - DocAlias.objects.create(name=doc.name, document=doc) + DocAlias.objects.create(name=doc.name).docs.add(doc) self.instance.sessionpresentation_set.create(document=doc, rev=doc.rev) NewRevisionDocEvent.objects.create( type='new_revision', diff --git a/ietf/meeting/migrations/0015_sessionpresentation_document2_fk.py b/ietf/meeting/migrations/0015_sessionpresentation_document2_fk.py new file mode 100644 index 000000000..bd13536ea --- /dev/null +++ b/ietf/meeting/migrations/0015_sessionpresentation_document2_fk.py @@ -0,0 +1,29 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-08 11:58 +from __future__ import unicode_literals + +from django.db import migrations +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0015_1_add_fk_to_document_id'), + ('meeting', '0014_auto_20190426_0305'), + ] + + operations = [ + migrations.AddField( + model_name='sessionpresentation', + name='document2', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field=b'id'), + ), + migrations.AlterField( + model_name='sessionpresentation', + name='document', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='old_sesspres', to='doc.Document', to_field=b'name'), + ), + ] diff --git a/ietf/meeting/migrations/0016_remove_sessionpresentation_document.py b/ietf/meeting/migrations/0016_remove_sessionpresentation_document.py new file mode 100644 index 000000000..228c63ed2 --- /dev/null +++ b/ietf/meeting/migrations/0016_remove_sessionpresentation_document.py @@ -0,0 +1,34 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-21 03:57 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0018_remove_old_document_field'), + ('meeting', '0015_sessionpresentation_document2_fk'), + ] + + operations = [ + + # We need to get rid of the current through table uniqueness + # constraint before we can remove the document column: The table + # has "UNIQUE KEY `session_id` (`session_id`,`document_id`)" + migrations.RunSQL( + "ALTER TABLE `meeting_session_materials` DROP INDEX `session_id`;", + "CREATE UNIQUE INDEX `session_id` ON `meeting_session_materials` (`session_id`, `document_id`);" + ), + ## This doesn't work: + # migrations.RemoveIndex( + # model_name='sessionpresentation', + # name='session_id' + # ), + migrations.RemoveField( + model_name='sessionpresentation', + name='document', + ), + ] diff --git a/ietf/meeting/migrations/0017_rename_field_document2.py b/ietf/meeting/migrations/0017_rename_field_document2.py new file mode 100644 index 000000000..a857a074f --- /dev/null +++ b/ietf/meeting/migrations/0017_rename_field_document2.py @@ -0,0 +1,26 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-21 05:31 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0019_rename_field_document2'), + ('meeting', '0016_remove_sessionpresentation_document'), + ] + + operations = [ + migrations.RenameField( + model_name='sessionpresentation', + old_name='document2', + new_name='document', + ), + migrations.AlterUniqueTogether( + name='sessionpresentation', + unique_together=set([('session', 'document')]), + ), + ] diff --git a/ietf/meeting/migrations/0018_document_primary_key_cleanup.py b/ietf/meeting/migrations/0018_document_primary_key_cleanup.py new file mode 100644 index 000000000..491a34f93 --- /dev/null +++ b/ietf/meeting/migrations/0018_document_primary_key_cleanup.py @@ -0,0 +1,23 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-06-10 03:47 +from __future__ import unicode_literals + +from django.db import migrations +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('meeting', '0017_rename_field_document2'), + ] + + operations = [ + migrations.AlterField( + model_name='sessionpresentation', + name='document', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document'), + ), + ] diff --git a/ietf/meeting/models.py b/ietf/meeting/models.py index ce8b65b86..5b3478cae 100644 --- a/ietf/meeting/models.py +++ b/ietf/meeting/models.py @@ -1,3 +1,6 @@ +# Copyright The IETF Trust 2007-2019, All Rights Reserved +# -*- coding: utf-8 -*- + # old meeting models can be found in ../proceedings/models.py import pytz @@ -863,6 +866,7 @@ class SessionPresentation(models.Model): class Meta: db_table = 'meeting_session_materials' ordering = ('order',) + unique_together = (('session', 'document'),) def __unicode__(self): return u"%s -> %s-%s" % (self.session, self.document.name, self.rev) diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index 19de5cf03..585dba5a5 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -1,4 +1,5 @@ -# Copyright The IETF Trust 2007-2018, All Rights Reserved +# Copyright The IETF Trust 2007-2019, All Rights Reserved +# -*- coding: utf-8 -*- import csv import datetime @@ -38,7 +39,7 @@ from django.views.generic import RedirectView from ietf.doc.fields import SearchableDocumentsField -from ietf.doc.models import Document, State, DocEvent, NewRevisionDocEvent +from ietf.doc.models import Document, State, DocEvent, NewRevisionDocEvent, DocAlias from ietf.group.models import Group from ietf.group.utils import can_manage_materials from ietf.ietfauth.utils import role_required, has_role @@ -1218,7 +1219,7 @@ def upload_session_bluesheets(request, session_id, num): rev = '00', ) doc.states.add(State.objects.get(type_id='bluesheets',slug='active')) - doc.docalias_set.create(name=doc.name) + DocAlias.objects.create(name=doc.name).docs.add(doc) session.sessionpresentation_set.create(document=doc,rev='00') filename = '%s-%s%s'% ( doc.name, doc.rev, ext) doc.uploaded_filename = filename @@ -1307,7 +1308,7 @@ def upload_session_minutes(request, session_id, num): group = session.group, rev = '00', ) - doc.docalias_set.create(name=doc.name) + DocAlias.objects.create(name=doc.name).docs.add(doc) doc.states.add(State.objects.get(type_id='minutes',slug='active')) if session.sessionpresentation_set.filter(document=doc).exists(): sp = session.sessionpresentation_set.get(document=doc) @@ -1410,7 +1411,7 @@ def upload_session_agenda(request, session_id, num): group = session.group, rev = '00', ) - doc.docalias_set.create(name=doc.name) + DocAlias.objects.create(name=doc.name).docs.add(doc) doc.states.add(State.objects.get(type_id='agenda',slug='active')) if session.sessionpresentation_set.filter(document=doc).exists(): sp = session.sessionpresentation_set.get(document=doc) @@ -1513,7 +1514,7 @@ def upload_session_slides(request, session_id, num, name): group = session.group, rev = '00', ) - doc.docalias_set.create(name=doc.name) + DocAlias.objects.create(name=doc.name).docs.add(doc) doc.states.add(State.objects.get(type_id='slides',slug='active')) doc.states.add(State.objects.get(type_id='reuse_policy',slug='single')) if session.sessionpresentation_set.filter(document=doc).exists(): @@ -2448,7 +2449,7 @@ def approve_proposed_slides(request, slidesubmission_id, num): group = submission.session.group, rev = '00', ) - doc.docalias_set.create(name=doc.name) + DocAlias.objects.create(name=doc.name).docs.add(doc) doc.states.add(State.objects.get(type_id='slides',slug='active')) doc.states.add(State.objects.get(type_id='reuse_policy',slug='single')) if submission.session.sessionpresentation_set.filter(document=doc).exists(): diff --git a/ietf/message/migrations/0002_add_message_docs2_m2m.py b/ietf/message/migrations/0002_add_message_docs2_m2m.py new file mode 100644 index 000000000..6cb7f27a0 --- /dev/null +++ b/ietf/message/migrations/0002_add_message_docs2_m2m.py @@ -0,0 +1,31 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-21 14:23 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('message', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='MessageDocs', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('message', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='message.Message')), + ('document', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field=b'id')), + ], + ), + migrations.AddField( + model_name='message', + name='related_docs2', + field=models.ManyToManyField(blank=True, related_name='messages', through='message.MessageDocs', to='doc.Document'), + ), + ] diff --git a/ietf/message/migrations/0003_set_document_m2m_keys.py b/ietf/message/migrations/0003_set_document_m2m_keys.py new file mode 100644 index 000000000..a6da567d4 --- /dev/null +++ b/ietf/message/migrations/0003_set_document_m2m_keys.py @@ -0,0 +1,47 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-21 14:27 +from __future__ import unicode_literals + +import sys + +from tqdm import tqdm + +from django.db import migrations + + +def forward(apps, schema_editor): + + Document = apps.get_model('doc','Document') + Message = apps.get_model('message', 'Message') + MessageDocs = apps.get_model('message', 'MessageDocs') + + + # Document id fixup ------------------------------------------------------------ + + objs = Document.objects.in_bulk() + nameid = { o.name: o.id for id, o in objs.iteritems() } + + sys.stderr.write('\n') + + sys.stderr.write(' %s.%s:\n' % (Message.__name__, 'related_docs')) + count = 0 + for m in tqdm(Message.objects.all()): + for d in m.related_docs.all(): + count += 1; + MessageDocs.objects.get_or_create(message=m, document_id=nameid[d.name]) + sys.stderr.write(' %s MessageDocs objects created\n' % (count, )) + +def reverse(apps, schema_editor): + pass + +class Migration(migrations.Migration): + + dependencies = [ + ('message', '0002_add_message_docs2_m2m'), + ('doc', '0014_set_document_docalias_id'), + ] + + operations = [ + migrations.RunPython(forward, reverse), + ] diff --git a/ietf/message/migrations/0004_1_del_docs_m2m_table.py b/ietf/message/migrations/0004_1_del_docs_m2m_table.py new file mode 100644 index 000000000..328b6cdcf --- /dev/null +++ b/ietf/message/migrations/0004_1_del_docs_m2m_table.py @@ -0,0 +1,32 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-22 08:01 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('message', '0003_set_document_m2m_keys'), + ] + + # The implementation of AlterField in Django 1.11 applies + # 'ALTER TABLE
MODIFY ...;' in order to fix foregn keys + # to the altered field, but as it seems does _not_ fix up m2m + # intermediary tables in an equivalent manner, so here we remove and + # then recreate the m2m tables so they will have the appropriate field + # types. + + operations = [ + migrations.RemoveField( + model_name='message', + name='related_docs', + ), + migrations.AddField( + model_name='message', + name='related_docs', + field=models.ManyToManyField(to='doc.Document'), + ), + ] diff --git a/ietf/message/migrations/0004_2_add_docs_m2m_table.py b/ietf/message/migrations/0004_2_add_docs_m2m_table.py new file mode 100644 index 000000000..064b2e085 --- /dev/null +++ b/ietf/message/migrations/0004_2_add_docs_m2m_table.py @@ -0,0 +1,32 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-22 08:01 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('message', '0004_1_del_docs_m2m_table'), + ] + + # The implementation of AlterField in Django 1.11 applies + # 'ALTER TABLE
MODIFY ...;' in order to fix foregn keys + # to the altered field, but as it seems does _not_ fix up m2m + # intermediary tables in an equivalent manner, so here we remove and + # then recreate the m2m tables so they will have the appropriate field + # types. + + operations = [ + migrations.RemoveField( + model_name='message', + name='related_docs', + ), + migrations.AddField( + model_name='message', + name='related_docs', + field=models.ManyToManyField(blank=True, to='doc.Document'), + ), + ] diff --git a/ietf/message/migrations/0005_copy_docs_m2m_table.py b/ietf/message/migrations/0005_copy_docs_m2m_table.py new file mode 100644 index 000000000..7959d0365 --- /dev/null +++ b/ietf/message/migrations/0005_copy_docs_m2m_table.py @@ -0,0 +1,28 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-27 05:56 +from __future__ import unicode_literals + +import sys, time + +from django.db import migrations + + +def timestamp(apps, schema_editor): + sys.stderr.write('\n %s' % time.strftime('%Y-%m-%d %H:%M:%S')) + +class Migration(migrations.Migration): + + dependencies = [ + ('message', '0004_2_add_docs_m2m_table'), + ] + + operations = [ + #migrations.RunPython(forward, reverse), + migrations.RunPython(timestamp, timestamp), + migrations.RunSQL( + "INSERT INTO message_message_related_docs SELECT * FROM message_messagedocs;", + "" + ), + migrations.RunPython(timestamp, timestamp), + ] diff --git a/ietf/message/migrations/0006_remove_docs2_m2m.py b/ietf/message/migrations/0006_remove_docs2_m2m.py new file mode 100644 index 000000000..527eb5595 --- /dev/null +++ b/ietf/message/migrations/0006_remove_docs2_m2m.py @@ -0,0 +1,31 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-30 03:32 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('message', '0005_copy_docs_m2m_table'), + ] + + operations = [ + migrations.RemoveField( + model_name='messagedocs', + name='document', + ), + migrations.RemoveField( + model_name='messagedocs', + name='message', + ), + migrations.RemoveField( + model_name='message', + name='related_docs2', + ), + migrations.DeleteModel( + name='MessageDocs', + ), + ] diff --git a/ietf/name/fixtures/names.json b/ietf/name/fixtures/names.json index 8af101227..fde50cdd2 100644 --- a/ietf/name/fixtures/names.json +++ b/ietf/name/fixtures/names.json @@ -2678,13 +2678,13 @@ "fields": { "about_page": "ietf.group.views.group_about", "acts_like_wg": false, - "admin_roles": "[\"chair\"]", + "admin_roles": "[\"chair\",\"advisor\"]", "agenda_type": "side", "create_wiki": true, "custom_group_roles": true, "customize_workflow": false, "default_tab": "ietf.group.views.group_about", - "docman_roles": "[]", + "docman_roles": "[\"chair\"]", "groupman_roles": "[\"chair\",\"advisor\"]", "has_chartering_process": false, "has_default_jabber": false, @@ -10934,11 +10934,2435 @@ "model": "name.topicaudiencename", "pk": "nominees" }, + { + "fields": { + "alias": "AD", + "country": "AD" + }, + "model": "stats.countryalias", + "pk": 1 + }, + { + "fields": { + "alias": "AE", + "country": "AE" + }, + "model": "stats.countryalias", + "pk": 2 + }, + { + "fields": { + "alias": "AF", + "country": "AF" + }, + "model": "stats.countryalias", + "pk": 3 + }, + { + "fields": { + "alias": "AG", + "country": "AG" + }, + "model": "stats.countryalias", + "pk": 4 + }, + { + "fields": { + "alias": "AI", + "country": "AI" + }, + "model": "stats.countryalias", + "pk": 5 + }, + { + "fields": { + "alias": "AL", + "country": "AL" + }, + "model": "stats.countryalias", + "pk": 6 + }, + { + "fields": { + "alias": "AM", + "country": "AM" + }, + "model": "stats.countryalias", + "pk": 7 + }, + { + "fields": { + "alias": "AO", + "country": "AO" + }, + "model": "stats.countryalias", + "pk": 8 + }, + { + "fields": { + "alias": "AQ", + "country": "AQ" + }, + "model": "stats.countryalias", + "pk": 9 + }, + { + "fields": { + "alias": "AR", + "country": "AR" + }, + "model": "stats.countryalias", + "pk": 10 + }, + { + "fields": { + "alias": "AS", + "country": "AS" + }, + "model": "stats.countryalias", + "pk": 11 + }, + { + "fields": { + "alias": "AT", + "country": "AT" + }, + "model": "stats.countryalias", + "pk": 12 + }, + { + "fields": { + "alias": "AU", + "country": "AU" + }, + "model": "stats.countryalias", + "pk": 13 + }, + { + "fields": { + "alias": "AW", + "country": "AW" + }, + "model": "stats.countryalias", + "pk": 14 + }, + { + "fields": { + "alias": "AX", + "country": "AX" + }, + "model": "stats.countryalias", + "pk": 15 + }, + { + "fields": { + "alias": "AZ", + "country": "AZ" + }, + "model": "stats.countryalias", + "pk": 16 + }, + { + "fields": { + "alias": "BA", + "country": "BA" + }, + "model": "stats.countryalias", + "pk": 17 + }, + { + "fields": { + "alias": "BB", + "country": "BB" + }, + "model": "stats.countryalias", + "pk": 18 + }, + { + "fields": { + "alias": "BD", + "country": "BD" + }, + "model": "stats.countryalias", + "pk": 19 + }, + { + "fields": { + "alias": "BE", + "country": "BE" + }, + "model": "stats.countryalias", + "pk": 20 + }, + { + "fields": { + "alias": "BF", + "country": "BF" + }, + "model": "stats.countryalias", + "pk": 21 + }, + { + "fields": { + "alias": "BG", + "country": "BG" + }, + "model": "stats.countryalias", + "pk": 22 + }, + { + "fields": { + "alias": "BH", + "country": "BH" + }, + "model": "stats.countryalias", + "pk": 23 + }, + { + "fields": { + "alias": "BI", + "country": "BI" + }, + "model": "stats.countryalias", + "pk": 24 + }, + { + "fields": { + "alias": "BJ", + "country": "BJ" + }, + "model": "stats.countryalias", + "pk": 25 + }, + { + "fields": { + "alias": "BL", + "country": "BL" + }, + "model": "stats.countryalias", + "pk": 26 + }, + { + "fields": { + "alias": "BM", + "country": "BM" + }, + "model": "stats.countryalias", + "pk": 27 + }, + { + "fields": { + "alias": "BN", + "country": "BN" + }, + "model": "stats.countryalias", + "pk": 28 + }, + { + "fields": { + "alias": "BO", + "country": "BO" + }, + "model": "stats.countryalias", + "pk": 29 + }, + { + "fields": { + "alias": "BQ", + "country": "BQ" + }, + "model": "stats.countryalias", + "pk": 30 + }, + { + "fields": { + "alias": "BR", + "country": "BR" + }, + "model": "stats.countryalias", + "pk": 31 + }, + { + "fields": { + "alias": "BS", + "country": "BS" + }, + "model": "stats.countryalias", + "pk": 32 + }, + { + "fields": { + "alias": "BT", + "country": "BT" + }, + "model": "stats.countryalias", + "pk": 33 + }, + { + "fields": { + "alias": "BV", + "country": "BV" + }, + "model": "stats.countryalias", + "pk": 34 + }, + { + "fields": { + "alias": "BW", + "country": "BW" + }, + "model": "stats.countryalias", + "pk": 35 + }, + { + "fields": { + "alias": "BY", + "country": "BY" + }, + "model": "stats.countryalias", + "pk": 36 + }, + { + "fields": { + "alias": "BZ", + "country": "BZ" + }, + "model": "stats.countryalias", + "pk": 37 + }, + { + "fields": { + "alias": "CA", + "country": "CA" + }, + "model": "stats.countryalias", + "pk": 38 + }, + { + "fields": { + "alias": "CC", + "country": "CC" + }, + "model": "stats.countryalias", + "pk": 39 + }, + { + "fields": { + "alias": "CD", + "country": "CD" + }, + "model": "stats.countryalias", + "pk": 40 + }, + { + "fields": { + "alias": "CF", + "country": "CF" + }, + "model": "stats.countryalias", + "pk": 41 + }, + { + "fields": { + "alias": "CG", + "country": "CG" + }, + "model": "stats.countryalias", + "pk": 42 + }, + { + "fields": { + "alias": "CH", + "country": "CH" + }, + "model": "stats.countryalias", + "pk": 43 + }, + { + "fields": { + "alias": "CI", + "country": "CI" + }, + "model": "stats.countryalias", + "pk": 44 + }, + { + "fields": { + "alias": "CK", + "country": "CK" + }, + "model": "stats.countryalias", + "pk": 45 + }, + { + "fields": { + "alias": "CL", + "country": "CL" + }, + "model": "stats.countryalias", + "pk": 46 + }, + { + "fields": { + "alias": "CM", + "country": "CM" + }, + "model": "stats.countryalias", + "pk": 47 + }, + { + "fields": { + "alias": "CN", + "country": "CN" + }, + "model": "stats.countryalias", + "pk": 48 + }, + { + "fields": { + "alias": "CO", + "country": "CO" + }, + "model": "stats.countryalias", + "pk": 49 + }, + { + "fields": { + "alias": "CR", + "country": "CR" + }, + "model": "stats.countryalias", + "pk": 50 + }, + { + "fields": { + "alias": "CU", + "country": "CU" + }, + "model": "stats.countryalias", + "pk": 51 + }, + { + "fields": { + "alias": "CV", + "country": "CV" + }, + "model": "stats.countryalias", + "pk": 52 + }, + { + "fields": { + "alias": "CW", + "country": "CW" + }, + "model": "stats.countryalias", + "pk": 53 + }, + { + "fields": { + "alias": "CX", + "country": "CX" + }, + "model": "stats.countryalias", + "pk": 54 + }, + { + "fields": { + "alias": "CY", + "country": "CY" + }, + "model": "stats.countryalias", + "pk": 55 + }, + { + "fields": { + "alias": "CZ", + "country": "CZ" + }, + "model": "stats.countryalias", + "pk": 56 + }, + { + "fields": { + "alias": "DE", + "country": "DE" + }, + "model": "stats.countryalias", + "pk": 57 + }, + { + "fields": { + "alias": "DJ", + "country": "DJ" + }, + "model": "stats.countryalias", + "pk": 58 + }, + { + "fields": { + "alias": "DK", + "country": "DK" + }, + "model": "stats.countryalias", + "pk": 59 + }, + { + "fields": { + "alias": "DM", + "country": "DM" + }, + "model": "stats.countryalias", + "pk": 60 + }, + { + "fields": { + "alias": "DO", + "country": "DO" + }, + "model": "stats.countryalias", + "pk": 61 + }, + { + "fields": { + "alias": "DZ", + "country": "DZ" + }, + "model": "stats.countryalias", + "pk": 62 + }, + { + "fields": { + "alias": "EC", + "country": "EC" + }, + "model": "stats.countryalias", + "pk": 63 + }, + { + "fields": { + "alias": "EE", + "country": "EE" + }, + "model": "stats.countryalias", + "pk": 64 + }, + { + "fields": { + "alias": "EG", + "country": "EG" + }, + "model": "stats.countryalias", + "pk": 65 + }, + { + "fields": { + "alias": "EH", + "country": "EH" + }, + "model": "stats.countryalias", + "pk": 66 + }, + { + "fields": { + "alias": "ER", + "country": "ER" + }, + "model": "stats.countryalias", + "pk": 67 + }, + { + "fields": { + "alias": "ES", + "country": "ES" + }, + "model": "stats.countryalias", + "pk": 68 + }, + { + "fields": { + "alias": "ET", + "country": "ET" + }, + "model": "stats.countryalias", + "pk": 69 + }, + { + "fields": { + "alias": "FI", + "country": "FI" + }, + "model": "stats.countryalias", + "pk": 70 + }, + { + "fields": { + "alias": "FJ", + "country": "FJ" + }, + "model": "stats.countryalias", + "pk": 71 + }, + { + "fields": { + "alias": "FK", + "country": "FK" + }, + "model": "stats.countryalias", + "pk": 72 + }, + { + "fields": { + "alias": "FM", + "country": "FM" + }, + "model": "stats.countryalias", + "pk": 73 + }, + { + "fields": { + "alias": "FO", + "country": "FO" + }, + "model": "stats.countryalias", + "pk": 74 + }, + { + "fields": { + "alias": "FR", + "country": "FR" + }, + "model": "stats.countryalias", + "pk": 75 + }, + { + "fields": { + "alias": "GA", + "country": "GA" + }, + "model": "stats.countryalias", + "pk": 76 + }, + { + "fields": { + "alias": "GB", + "country": "GB" + }, + "model": "stats.countryalias", + "pk": 77 + }, + { + "fields": { + "alias": "GD", + "country": "GD" + }, + "model": "stats.countryalias", + "pk": 78 + }, + { + "fields": { + "alias": "GE", + "country": "GE" + }, + "model": "stats.countryalias", + "pk": 79 + }, + { + "fields": { + "alias": "GF", + "country": "GF" + }, + "model": "stats.countryalias", + "pk": 80 + }, + { + "fields": { + "alias": "GG", + "country": "GG" + }, + "model": "stats.countryalias", + "pk": 81 + }, + { + "fields": { + "alias": "GH", + "country": "GH" + }, + "model": "stats.countryalias", + "pk": 82 + }, + { + "fields": { + "alias": "GI", + "country": "GI" + }, + "model": "stats.countryalias", + "pk": 83 + }, + { + "fields": { + "alias": "GL", + "country": "GL" + }, + "model": "stats.countryalias", + "pk": 84 + }, + { + "fields": { + "alias": "GM", + "country": "GM" + }, + "model": "stats.countryalias", + "pk": 85 + }, + { + "fields": { + "alias": "GN", + "country": "GN" + }, + "model": "stats.countryalias", + "pk": 86 + }, + { + "fields": { + "alias": "GP", + "country": "GP" + }, + "model": "stats.countryalias", + "pk": 87 + }, + { + "fields": { + "alias": "GQ", + "country": "GQ" + }, + "model": "stats.countryalias", + "pk": 88 + }, + { + "fields": { + "alias": "GR", + "country": "GR" + }, + "model": "stats.countryalias", + "pk": 89 + }, + { + "fields": { + "alias": "GS", + "country": "GS" + }, + "model": "stats.countryalias", + "pk": 90 + }, + { + "fields": { + "alias": "GT", + "country": "GT" + }, + "model": "stats.countryalias", + "pk": 91 + }, + { + "fields": { + "alias": "GU", + "country": "GU" + }, + "model": "stats.countryalias", + "pk": 92 + }, + { + "fields": { + "alias": "GW", + "country": "GW" + }, + "model": "stats.countryalias", + "pk": 93 + }, + { + "fields": { + "alias": "GY", + "country": "GY" + }, + "model": "stats.countryalias", + "pk": 94 + }, + { + "fields": { + "alias": "HK", + "country": "HK" + }, + "model": "stats.countryalias", + "pk": 95 + }, + { + "fields": { + "alias": "HM", + "country": "HM" + }, + "model": "stats.countryalias", + "pk": 96 + }, + { + "fields": { + "alias": "HN", + "country": "HN" + }, + "model": "stats.countryalias", + "pk": 97 + }, + { + "fields": { + "alias": "HR", + "country": "HR" + }, + "model": "stats.countryalias", + "pk": 98 + }, + { + "fields": { + "alias": "HT", + "country": "HT" + }, + "model": "stats.countryalias", + "pk": 99 + }, + { + "fields": { + "alias": "HU", + "country": "HU" + }, + "model": "stats.countryalias", + "pk": 100 + }, + { + "fields": { + "alias": "ID", + "country": "ID" + }, + "model": "stats.countryalias", + "pk": 101 + }, + { + "fields": { + "alias": "IE", + "country": "IE" + }, + "model": "stats.countryalias", + "pk": 102 + }, + { + "fields": { + "alias": "IL", + "country": "IL" + }, + "model": "stats.countryalias", + "pk": 103 + }, + { + "fields": { + "alias": "IM", + "country": "IM" + }, + "model": "stats.countryalias", + "pk": 104 + }, + { + "fields": { + "alias": "IN", + "country": "IN" + }, + "model": "stats.countryalias", + "pk": 105 + }, + { + "fields": { + "alias": "IO", + "country": "IO" + }, + "model": "stats.countryalias", + "pk": 106 + }, + { + "fields": { + "alias": "IQ", + "country": "IQ" + }, + "model": "stats.countryalias", + "pk": 107 + }, + { + "fields": { + "alias": "IR", + "country": "IR" + }, + "model": "stats.countryalias", + "pk": 108 + }, + { + "fields": { + "alias": "IS", + "country": "IS" + }, + "model": "stats.countryalias", + "pk": 109 + }, + { + "fields": { + "alias": "IT", + "country": "IT" + }, + "model": "stats.countryalias", + "pk": 110 + }, + { + "fields": { + "alias": "JE", + "country": "JE" + }, + "model": "stats.countryalias", + "pk": 111 + }, + { + "fields": { + "alias": "JM", + "country": "JM" + }, + "model": "stats.countryalias", + "pk": 112 + }, + { + "fields": { + "alias": "JO", + "country": "JO" + }, + "model": "stats.countryalias", + "pk": 113 + }, + { + "fields": { + "alias": "JP", + "country": "JP" + }, + "model": "stats.countryalias", + "pk": 114 + }, + { + "fields": { + "alias": "KE", + "country": "KE" + }, + "model": "stats.countryalias", + "pk": 115 + }, + { + "fields": { + "alias": "KG", + "country": "KG" + }, + "model": "stats.countryalias", + "pk": 116 + }, + { + "fields": { + "alias": "KH", + "country": "KH" + }, + "model": "stats.countryalias", + "pk": 117 + }, + { + "fields": { + "alias": "KI", + "country": "KI" + }, + "model": "stats.countryalias", + "pk": 118 + }, + { + "fields": { + "alias": "KM", + "country": "KM" + }, + "model": "stats.countryalias", + "pk": 119 + }, + { + "fields": { + "alias": "KN", + "country": "KN" + }, + "model": "stats.countryalias", + "pk": 120 + }, + { + "fields": { + "alias": "KP", + "country": "KP" + }, + "model": "stats.countryalias", + "pk": 121 + }, + { + "fields": { + "alias": "KR", + "country": "KR" + }, + "model": "stats.countryalias", + "pk": 122 + }, + { + "fields": { + "alias": "KW", + "country": "KW" + }, + "model": "stats.countryalias", + "pk": 123 + }, + { + "fields": { + "alias": "KY", + "country": "KY" + }, + "model": "stats.countryalias", + "pk": 124 + }, + { + "fields": { + "alias": "KZ", + "country": "KZ" + }, + "model": "stats.countryalias", + "pk": 125 + }, + { + "fields": { + "alias": "LA", + "country": "LA" + }, + "model": "stats.countryalias", + "pk": 126 + }, + { + "fields": { + "alias": "LB", + "country": "LB" + }, + "model": "stats.countryalias", + "pk": 127 + }, + { + "fields": { + "alias": "LC", + "country": "LC" + }, + "model": "stats.countryalias", + "pk": 128 + }, + { + "fields": { + "alias": "LI", + "country": "LI" + }, + "model": "stats.countryalias", + "pk": 129 + }, + { + "fields": { + "alias": "LK", + "country": "LK" + }, + "model": "stats.countryalias", + "pk": 130 + }, + { + "fields": { + "alias": "LR", + "country": "LR" + }, + "model": "stats.countryalias", + "pk": 131 + }, + { + "fields": { + "alias": "LS", + "country": "LS" + }, + "model": "stats.countryalias", + "pk": 132 + }, + { + "fields": { + "alias": "LT", + "country": "LT" + }, + "model": "stats.countryalias", + "pk": 133 + }, + { + "fields": { + "alias": "LU", + "country": "LU" + }, + "model": "stats.countryalias", + "pk": 134 + }, + { + "fields": { + "alias": "LV", + "country": "LV" + }, + "model": "stats.countryalias", + "pk": 135 + }, + { + "fields": { + "alias": "LY", + "country": "LY" + }, + "model": "stats.countryalias", + "pk": 136 + }, + { + "fields": { + "alias": "MA", + "country": "MA" + }, + "model": "stats.countryalias", + "pk": 137 + }, + { + "fields": { + "alias": "MC", + "country": "MC" + }, + "model": "stats.countryalias", + "pk": 138 + }, + { + "fields": { + "alias": "MD", + "country": "MD" + }, + "model": "stats.countryalias", + "pk": 139 + }, + { + "fields": { + "alias": "ME", + "country": "ME" + }, + "model": "stats.countryalias", + "pk": 140 + }, + { + "fields": { + "alias": "MF", + "country": "MF" + }, + "model": "stats.countryalias", + "pk": 141 + }, + { + "fields": { + "alias": "MG", + "country": "MG" + }, + "model": "stats.countryalias", + "pk": 142 + }, + { + "fields": { + "alias": "MH", + "country": "MH" + }, + "model": "stats.countryalias", + "pk": 143 + }, + { + "fields": { + "alias": "MK", + "country": "MK" + }, + "model": "stats.countryalias", + "pk": 144 + }, + { + "fields": { + "alias": "ML", + "country": "ML" + }, + "model": "stats.countryalias", + "pk": 145 + }, + { + "fields": { + "alias": "MM", + "country": "MM" + }, + "model": "stats.countryalias", + "pk": 146 + }, + { + "fields": { + "alias": "MN", + "country": "MN" + }, + "model": "stats.countryalias", + "pk": 147 + }, + { + "fields": { + "alias": "MO", + "country": "MO" + }, + "model": "stats.countryalias", + "pk": 148 + }, + { + "fields": { + "alias": "MP", + "country": "MP" + }, + "model": "stats.countryalias", + "pk": 149 + }, + { + "fields": { + "alias": "MQ", + "country": "MQ" + }, + "model": "stats.countryalias", + "pk": 150 + }, + { + "fields": { + "alias": "MR", + "country": "MR" + }, + "model": "stats.countryalias", + "pk": 151 + }, + { + "fields": { + "alias": "MS", + "country": "MS" + }, + "model": "stats.countryalias", + "pk": 152 + }, + { + "fields": { + "alias": "MT", + "country": "MT" + }, + "model": "stats.countryalias", + "pk": 153 + }, + { + "fields": { + "alias": "MU", + "country": "MU" + }, + "model": "stats.countryalias", + "pk": 154 + }, + { + "fields": { + "alias": "MV", + "country": "MV" + }, + "model": "stats.countryalias", + "pk": 155 + }, + { + "fields": { + "alias": "MW", + "country": "MW" + }, + "model": "stats.countryalias", + "pk": 156 + }, + { + "fields": { + "alias": "MX", + "country": "MX" + }, + "model": "stats.countryalias", + "pk": 157 + }, + { + "fields": { + "alias": "MY", + "country": "MY" + }, + "model": "stats.countryalias", + "pk": 158 + }, + { + "fields": { + "alias": "MZ", + "country": "MZ" + }, + "model": "stats.countryalias", + "pk": 159 + }, + { + "fields": { + "alias": "NA", + "country": "NA" + }, + "model": "stats.countryalias", + "pk": 160 + }, + { + "fields": { + "alias": "NC", + "country": "NC" + }, + "model": "stats.countryalias", + "pk": 161 + }, + { + "fields": { + "alias": "NE", + "country": "NE" + }, + "model": "stats.countryalias", + "pk": 162 + }, + { + "fields": { + "alias": "NF", + "country": "NF" + }, + "model": "stats.countryalias", + "pk": 163 + }, + { + "fields": { + "alias": "NG", + "country": "NG" + }, + "model": "stats.countryalias", + "pk": 164 + }, + { + "fields": { + "alias": "NI", + "country": "NI" + }, + "model": "stats.countryalias", + "pk": 165 + }, + { + "fields": { + "alias": "NL", + "country": "NL" + }, + "model": "stats.countryalias", + "pk": 166 + }, + { + "fields": { + "alias": "NO", + "country": "NO" + }, + "model": "stats.countryalias", + "pk": 167 + }, + { + "fields": { + "alias": "NP", + "country": "NP" + }, + "model": "stats.countryalias", + "pk": 168 + }, + { + "fields": { + "alias": "NR", + "country": "NR" + }, + "model": "stats.countryalias", + "pk": 169 + }, + { + "fields": { + "alias": "NU", + "country": "NU" + }, + "model": "stats.countryalias", + "pk": 170 + }, + { + "fields": { + "alias": "NZ", + "country": "NZ" + }, + "model": "stats.countryalias", + "pk": 171 + }, + { + "fields": { + "alias": "OM", + "country": "OM" + }, + "model": "stats.countryalias", + "pk": 172 + }, + { + "fields": { + "alias": "PA", + "country": "PA" + }, + "model": "stats.countryalias", + "pk": 173 + }, + { + "fields": { + "alias": "PE", + "country": "PE" + }, + "model": "stats.countryalias", + "pk": 174 + }, + { + "fields": { + "alias": "PF", + "country": "PF" + }, + "model": "stats.countryalias", + "pk": 175 + }, + { + "fields": { + "alias": "PG", + "country": "PG" + }, + "model": "stats.countryalias", + "pk": 176 + }, + { + "fields": { + "alias": "PH", + "country": "PH" + }, + "model": "stats.countryalias", + "pk": 177 + }, + { + "fields": { + "alias": "PK", + "country": "PK" + }, + "model": "stats.countryalias", + "pk": 178 + }, + { + "fields": { + "alias": "PL", + "country": "PL" + }, + "model": "stats.countryalias", + "pk": 179 + }, + { + "fields": { + "alias": "PM", + "country": "PM" + }, + "model": "stats.countryalias", + "pk": 180 + }, + { + "fields": { + "alias": "PN", + "country": "PN" + }, + "model": "stats.countryalias", + "pk": 181 + }, + { + "fields": { + "alias": "PR", + "country": "PR" + }, + "model": "stats.countryalias", + "pk": 182 + }, + { + "fields": { + "alias": "PS", + "country": "PS" + }, + "model": "stats.countryalias", + "pk": 183 + }, + { + "fields": { + "alias": "PT", + "country": "PT" + }, + "model": "stats.countryalias", + "pk": 184 + }, + { + "fields": { + "alias": "PW", + "country": "PW" + }, + "model": "stats.countryalias", + "pk": 185 + }, + { + "fields": { + "alias": "PY", + "country": "PY" + }, + "model": "stats.countryalias", + "pk": 186 + }, + { + "fields": { + "alias": "QA", + "country": "QA" + }, + "model": "stats.countryalias", + "pk": 187 + }, + { + "fields": { + "alias": "RE", + "country": "RE" + }, + "model": "stats.countryalias", + "pk": 188 + }, + { + "fields": { + "alias": "RO", + "country": "RO" + }, + "model": "stats.countryalias", + "pk": 189 + }, + { + "fields": { + "alias": "RS", + "country": "RS" + }, + "model": "stats.countryalias", + "pk": 190 + }, + { + "fields": { + "alias": "RU", + "country": "RU" + }, + "model": "stats.countryalias", + "pk": 191 + }, + { + "fields": { + "alias": "RW", + "country": "RW" + }, + "model": "stats.countryalias", + "pk": 192 + }, + { + "fields": { + "alias": "SA", + "country": "SA" + }, + "model": "stats.countryalias", + "pk": 193 + }, + { + "fields": { + "alias": "SB", + "country": "SB" + }, + "model": "stats.countryalias", + "pk": 194 + }, + { + "fields": { + "alias": "SC", + "country": "SC" + }, + "model": "stats.countryalias", + "pk": 195 + }, + { + "fields": { + "alias": "SD", + "country": "SD" + }, + "model": "stats.countryalias", + "pk": 196 + }, + { + "fields": { + "alias": "SE", + "country": "SE" + }, + "model": "stats.countryalias", + "pk": 197 + }, + { + "fields": { + "alias": "SG", + "country": "SG" + }, + "model": "stats.countryalias", + "pk": 198 + }, + { + "fields": { + "alias": "SH", + "country": "SH" + }, + "model": "stats.countryalias", + "pk": 199 + }, + { + "fields": { + "alias": "SI", + "country": "SI" + }, + "model": "stats.countryalias", + "pk": 200 + }, + { + "fields": { + "alias": "SJ", + "country": "SJ" + }, + "model": "stats.countryalias", + "pk": 201 + }, + { + "fields": { + "alias": "SK", + "country": "SK" + }, + "model": "stats.countryalias", + "pk": 202 + }, + { + "fields": { + "alias": "SL", + "country": "SL" + }, + "model": "stats.countryalias", + "pk": 203 + }, + { + "fields": { + "alias": "SM", + "country": "SM" + }, + "model": "stats.countryalias", + "pk": 204 + }, + { + "fields": { + "alias": "SN", + "country": "SN" + }, + "model": "stats.countryalias", + "pk": 205 + }, + { + "fields": { + "alias": "SO", + "country": "SO" + }, + "model": "stats.countryalias", + "pk": 206 + }, + { + "fields": { + "alias": "SR", + "country": "SR" + }, + "model": "stats.countryalias", + "pk": 207 + }, + { + "fields": { + "alias": "SS", + "country": "SS" + }, + "model": "stats.countryalias", + "pk": 208 + }, + { + "fields": { + "alias": "ST", + "country": "ST" + }, + "model": "stats.countryalias", + "pk": 209 + }, + { + "fields": { + "alias": "SV", + "country": "SV" + }, + "model": "stats.countryalias", + "pk": 210 + }, + { + "fields": { + "alias": "SX", + "country": "SX" + }, + "model": "stats.countryalias", + "pk": 211 + }, + { + "fields": { + "alias": "SY", + "country": "SY" + }, + "model": "stats.countryalias", + "pk": 212 + }, + { + "fields": { + "alias": "SZ", + "country": "SZ" + }, + "model": "stats.countryalias", + "pk": 213 + }, + { + "fields": { + "alias": "TC", + "country": "TC" + }, + "model": "stats.countryalias", + "pk": 214 + }, + { + "fields": { + "alias": "TD", + "country": "TD" + }, + "model": "stats.countryalias", + "pk": 215 + }, + { + "fields": { + "alias": "TF", + "country": "TF" + }, + "model": "stats.countryalias", + "pk": 216 + }, + { + "fields": { + "alias": "TG", + "country": "TG" + }, + "model": "stats.countryalias", + "pk": 217 + }, + { + "fields": { + "alias": "TH", + "country": "TH" + }, + "model": "stats.countryalias", + "pk": 218 + }, + { + "fields": { + "alias": "TJ", + "country": "TJ" + }, + "model": "stats.countryalias", + "pk": 219 + }, + { + "fields": { + "alias": "TK", + "country": "TK" + }, + "model": "stats.countryalias", + "pk": 220 + }, + { + "fields": { + "alias": "TL", + "country": "TL" + }, + "model": "stats.countryalias", + "pk": 221 + }, + { + "fields": { + "alias": "TM", + "country": "TM" + }, + "model": "stats.countryalias", + "pk": 222 + }, + { + "fields": { + "alias": "TN", + "country": "TN" + }, + "model": "stats.countryalias", + "pk": 223 + }, + { + "fields": { + "alias": "TO", + "country": "TO" + }, + "model": "stats.countryalias", + "pk": 224 + }, + { + "fields": { + "alias": "TR", + "country": "TR" + }, + "model": "stats.countryalias", + "pk": 225 + }, + { + "fields": { + "alias": "TT", + "country": "TT" + }, + "model": "stats.countryalias", + "pk": 226 + }, + { + "fields": { + "alias": "TV", + "country": "TV" + }, + "model": "stats.countryalias", + "pk": 227 + }, + { + "fields": { + "alias": "TW", + "country": "TW" + }, + "model": "stats.countryalias", + "pk": 228 + }, + { + "fields": { + "alias": "TZ", + "country": "TZ" + }, + "model": "stats.countryalias", + "pk": 229 + }, + { + "fields": { + "alias": "UA", + "country": "UA" + }, + "model": "stats.countryalias", + "pk": 230 + }, + { + "fields": { + "alias": "UG", + "country": "UG" + }, + "model": "stats.countryalias", + "pk": 231 + }, + { + "fields": { + "alias": "UM", + "country": "UM" + }, + "model": "stats.countryalias", + "pk": 232 + }, + { + "fields": { + "alias": "US", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 233 + }, + { + "fields": { + "alias": "UY", + "country": "UY" + }, + "model": "stats.countryalias", + "pk": 234 + }, + { + "fields": { + "alias": "UZ", + "country": "UZ" + }, + "model": "stats.countryalias", + "pk": 235 + }, + { + "fields": { + "alias": "VA", + "country": "VA" + }, + "model": "stats.countryalias", + "pk": 236 + }, + { + "fields": { + "alias": "VC", + "country": "VC" + }, + "model": "stats.countryalias", + "pk": 237 + }, + { + "fields": { + "alias": "VE", + "country": "VE" + }, + "model": "stats.countryalias", + "pk": 238 + }, + { + "fields": { + "alias": "VG", + "country": "VG" + }, + "model": "stats.countryalias", + "pk": 239 + }, + { + "fields": { + "alias": "VI", + "country": "VI" + }, + "model": "stats.countryalias", + "pk": 240 + }, + { + "fields": { + "alias": "VN", + "country": "VN" + }, + "model": "stats.countryalias", + "pk": 241 + }, + { + "fields": { + "alias": "VU", + "country": "VU" + }, + "model": "stats.countryalias", + "pk": 242 + }, + { + "fields": { + "alias": "WF", + "country": "WF" + }, + "model": "stats.countryalias", + "pk": 243 + }, + { + "fields": { + "alias": "WS", + "country": "WS" + }, + "model": "stats.countryalias", + "pk": 244 + }, + { + "fields": { + "alias": "YE", + "country": "YE" + }, + "model": "stats.countryalias", + "pk": 245 + }, + { + "fields": { + "alias": "YT", + "country": "YT" + }, + "model": "stats.countryalias", + "pk": 246 + }, + { + "fields": { + "alias": "ZA", + "country": "ZA" + }, + "model": "stats.countryalias", + "pk": 247 + }, + { + "fields": { + "alias": "ZM", + "country": "ZM" + }, + "model": "stats.countryalias", + "pk": 248 + }, + { + "fields": { + "alias": "ZW", + "country": "ZW" + }, + "model": "stats.countryalias", + "pk": 249 + }, + { + "fields": { + "alias": "russian federation", + "country": "RU" + }, + "model": "stats.countryalias", + "pk": 250 + }, + { + "fields": { + "alias": "p. r. china", + "country": "CN" + }, + "model": "stats.countryalias", + "pk": 251 + }, + { + "fields": { + "alias": "p.r. china", + "country": "CN" + }, + "model": "stats.countryalias", + "pk": 252 + }, + { + "fields": { + "alias": "p.r.china", + "country": "CN" + }, + "model": "stats.countryalias", + "pk": 253 + }, + { + "fields": { + "alias": "p.r china", + "country": "CN" + }, + "model": "stats.countryalias", + "pk": 254 + }, + { + "fields": { + "alias": "p.r. of china", + "country": "CN" + }, + "model": "stats.countryalias", + "pk": 255 + }, + { + "fields": { + "alias": "PRC", + "country": "CN" + }, + "model": "stats.countryalias", + "pk": 256 + }, + { + "fields": { + "alias": "P.R.C", + "country": "CN" + }, + "model": "stats.countryalias", + "pk": 257 + }, + { + "fields": { + "alias": "P.R.C.", + "country": "CN" + }, + "model": "stats.countryalias", + "pk": 258 + }, + { + "fields": { + "alias": "beijing", + "country": "CN" + }, + "model": "stats.countryalias", + "pk": 259 + }, + { + "fields": { + "alias": "shenzhen", + "country": "CN" + }, + "model": "stats.countryalias", + "pk": 260 + }, + { + "fields": { + "alias": "R.O.C.", + "country": "TW" + }, + "model": "stats.countryalias", + "pk": 261 + }, + { + "fields": { + "alias": "usa", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 262 + }, + { + "fields": { + "alias": "UAS", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 263 + }, + { + "fields": { + "alias": "USA.", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 264 + }, + { + "fields": { + "alias": "u.s.a.", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 265 + }, + { + "fields": { + "alias": "u. s. a.", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 266 + }, + { + "fields": { + "alias": "u.s.a", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 267 + }, + { + "fields": { + "alias": "u.s.", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 268 + }, + { + "fields": { + "alias": "U.S", + "country": "GB" + }, + "model": "stats.countryalias", + "pk": 269 + }, + { + "fields": { + "alias": "US of A", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 270 + }, + { + "fields": { + "alias": "united sates", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 271 + }, + { + "fields": { + "alias": "united state", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 272 + }, + { + "fields": { + "alias": "united states", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 273 + }, + { + "fields": { + "alias": "unites states", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 274 + }, + { + "fields": { + "alias": "texas", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 275 + }, + { + "fields": { + "alias": "UK", + "country": "GB" + }, + "model": "stats.countryalias", + "pk": 276 + }, + { + "fields": { + "alias": "united kingcom", + "country": "GB" + }, + "model": "stats.countryalias", + "pk": 277 + }, + { + "fields": { + "alias": "great britain", + "country": "GB" + }, + "model": "stats.countryalias", + "pk": 278 + }, + { + "fields": { + "alias": "england", + "country": "GB" + }, + "model": "stats.countryalias", + "pk": 279 + }, + { + "fields": { + "alias": "U.K.", + "country": "GB" + }, + "model": "stats.countryalias", + "pk": 280 + }, + { + "fields": { + "alias": "U.K", + "country": "GB" + }, + "model": "stats.countryalias", + "pk": 281 + }, + { + "fields": { + "alias": "scotland", + "country": "GB" + }, + "model": "stats.countryalias", + "pk": 282 + }, + { + "fields": { + "alias": "republic of korea", + "country": "KR" + }, + "model": "stats.countryalias", + "pk": 283 + }, + { + "fields": { + "alias": "korea", + "country": "KR" + }, + "model": "stats.countryalias", + "pk": 284 + }, + { + "fields": { + "alias": "korea rep", + "country": "KR" + }, + "model": "stats.countryalias", + "pk": 285 + }, + { + "fields": { + "alias": "korea (the republic of)", + "country": "KR" + }, + "model": "stats.countryalias", + "pk": 286 + }, + { + "fields": { + "alias": "the netherlands", + "country": "NL" + }, + "model": "stats.countryalias", + "pk": 287 + }, + { + "fields": { + "alias": "netherland", + "country": "NL" + }, + "model": "stats.countryalias", + "pk": 288 + }, + { + "fields": { + "alias": "danmark", + "country": "DK" + }, + "model": "stats.countryalias", + "pk": 289 + }, + { + "fields": { + "alias": "sweeden", + "country": "SE" + }, + "model": "stats.countryalias", + "pk": 290 + }, + { + "fields": { + "alias": "swede", + "country": "SE" + }, + "model": "stats.countryalias", + "pk": 291 + }, + { + "fields": { + "alias": "belgique", + "country": "BE" + }, + "model": "stats.countryalias", + "pk": 292 + }, + { + "fields": { + "alias": "madrid", + "country": "ES" + }, + "model": "stats.countryalias", + "pk": 293 + }, + { + "fields": { + "alias": "espana", + "country": "ES" + }, + "model": "stats.countryalias", + "pk": 294 + }, + { + "fields": { + "alias": "hellas", + "country": "GR" + }, + "model": "stats.countryalias", + "pk": 295 + }, + { + "fields": { + "alias": "gemany", + "country": "DE" + }, + "model": "stats.countryalias", + "pk": 296 + }, + { + "fields": { + "alias": "deutschland", + "country": "DE" + }, + "model": "stats.countryalias", + "pk": 297 + }, + { + "fields": { + "alias": "italia", + "country": "IT" + }, + "model": "stats.countryalias", + "pk": 298 + }, + { + "fields": { + "alias": "isreal", + "country": "IL" + }, + "model": "stats.countryalias", + "pk": 299 + }, + { + "fields": { + "alias": "tel aviv", + "country": "IL" + }, + "model": "stats.countryalias", + "pk": 300 + }, + { + "fields": { + "alias": "UAE", + "country": "AE" + }, + "model": "stats.countryalias", + "pk": 301 + }, + { + "fields": { + "alias": "grand-duchy of luxembourg", + "country": "LU" + }, + "model": "stats.countryalias", + "pk": 302 + }, + { + "fields": { + "alias": "brasil", + "country": "BR" + }, + "model": "stats.countryalias", + "pk": 303 + }, { "fields": { "command": "xym", "switch": "--version", - "time": "2019-04-28T00:08:08.288", + "time": "2019-06-05T00:08:14.315", "used": true, "version": "xym 0.4" }, @@ -10949,7 +13373,7 @@ "fields": { "command": "pyang", "switch": "--version", - "time": "2019-04-28T00:08:09.335", + "time": "2019-06-05T00:08:15.692", "used": true, "version": "pyang 1.7.8" }, @@ -10960,7 +13384,7 @@ "fields": { "command": "yanglint", "switch": "--version", - "time": "2019-04-28T00:08:09.623", + "time": "2019-06-05T00:08:15.932", "used": true, "version": "yanglint 0.14.80" }, @@ -10971,7 +13395,7 @@ "fields": { "command": "xml2rfc", "switch": "--version", - "time": "2019-04-28T00:08:11.596", + "time": "2019-06-05T00:08:18.757", "used": true, "version": "xml2rfc 2.22.3" }, diff --git a/ietf/review/migrations/0011_review_document2_fk.py b/ietf/review/migrations/0011_review_document2_fk.py new file mode 100644 index 000000000..a18e178da --- /dev/null +++ b/ietf/review/migrations/0011_review_document2_fk.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-08 11:58 +# Copyright The IETF Trust 2019, All Rights Reserved +from __future__ import unicode_literals + +from django.db import migrations +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0015_1_add_fk_to_document_id'), + ('review', '0010_populate_review_assignments'), + ] + + operations = [ + migrations.AddField( + model_name='reviewrequest', + name='doc2', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='reviewrequest_set', to='doc.Document', to_field=b'id'), + ), + migrations.AddField( + model_name='reviewwish', + name='doc2', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field=b'id'), + ), + migrations.AddField( + model_name='reviewrequest', + name='unused_review2', + field=ietf.utils.models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field='id'), + ), + migrations.AddField( + model_name='reviewassignment', + name='review2', + field=ietf.utils.models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field='id'), + ), + migrations.AlterField( + model_name='reviewrequest', + name='doc', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='old_revreq', to='doc.Document', to_field=b'name'), + ), + migrations.AlterField( + model_name='reviewwish', + name='doc', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='old_revwish', to='doc.Document', to_field=b'name'), + ), + migrations.AlterField( + model_name='reviewrequest', + name='unused_review', + field=ietf.utils.models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='old_unused_review', to='doc.Document', to_field=b'name'), + ), + migrations.AlterField( + model_name='reviewassignment', + name='review', + field=ietf.utils.models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='old_reviewassignment', to='doc.Document', to_field=b'name'), + ), + ] diff --git a/ietf/review/migrations/0012_remove_old_document_field.py b/ietf/review/migrations/0012_remove_old_document_field.py new file mode 100644 index 000000000..0028b6bb8 --- /dev/null +++ b/ietf/review/migrations/0012_remove_old_document_field.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-20 09:53 +# Copyright The IETF Trust 2019, All Rights Reserved +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('review', '0011_review_document2_fk'), + ] + + operations = [ + migrations.RemoveField( + model_name='reviewrequest', + name='doc', + ), + migrations.RemoveField( + model_name='reviewrequest', + name='unused_reviewer', + ), + migrations.RemoveField( + model_name='reviewrequest', + name='unused_review', + ), + migrations.RemoveField( + model_name='reviewrequest', + name='unused_review2', + ), + migrations.RemoveField( + model_name='reviewrequest', + name='unused_reviewed_rev', + ), + migrations.RemoveField( + model_name='reviewrequest', + name='unused_result', + ), + migrations.RemoveField( + model_name='reviewwish', + name='doc', + ), + migrations.RemoveField( + model_name='reviewassignment', + name='review', + ), + ] diff --git a/ietf/review/migrations/0013_rename_field_document2.py b/ietf/review/migrations/0013_rename_field_document2.py new file mode 100644 index 000000000..a9ce514ea --- /dev/null +++ b/ietf/review/migrations/0013_rename_field_document2.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-21 05:31 +# Copyright The IETF Trust 2019, All Rights Reserved +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0019_rename_field_document2'), + ('review', '0012_remove_old_document_field'), + ] + + operations = [ + migrations.RenameField( + model_name='reviewrequest', + old_name='doc2', + new_name='doc', + ), + migrations.RenameField( + model_name='reviewwish', + old_name='doc2', + new_name='doc', + ), + migrations.RenameField( + model_name='reviewassignment', + old_name='review2', + new_name='review', + ), + ] diff --git a/ietf/review/migrations/0014_document_primary_key_cleanup.py b/ietf/review/migrations/0014_document_primary_key_cleanup.py new file mode 100644 index 000000000..d54fb3a9c --- /dev/null +++ b/ietf/review/migrations/0014_document_primary_key_cleanup.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-06-10 03:47 +# Copyright The IETF Trust 2019, All Rights Reserved +from __future__ import unicode_literals + +from django.db import migrations +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('review', '0013_rename_field_document2'), + ] + + operations = [ + migrations.AlterField( + model_name='reviewrequest', + name='doc', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='reviewrequest_set', to='doc.Document'), + ), + migrations.AlterField( + model_name='reviewwish', + name='doc', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document'), + ), + ] diff --git a/ietf/review/models.py b/ietf/review/models.py index dab758d50..39373cd04 100644 --- a/ietf/review/models.py +++ b/ietf/review/models.py @@ -1,3 +1,5 @@ +# Copyright The IETF Trust 2016-2019, All Rights Reserved + import datetime from simple_history.models import HistoricalRecords @@ -119,14 +121,6 @@ class ReviewRequest(models.Model): requested_rev = models.CharField(verbose_name="requested revision", max_length=16, blank=True, help_text="Fill in if a specific revision is to be reviewed, e.g. 02") comment = models.TextField(verbose_name="Requester's comments and instructions", max_length=2048, blank=True, help_text="Provide any additional information to show to the review team secretary and reviewer", default='') - # Moved to class ReviewAssignment: - # These exist only to facilitate data migrations. They will be removed in the next release. - unused_reviewer = ForeignKey(Email, blank=True, null=True) - - unused_review = OneToOneField(Document, blank=True, null=True) - unused_reviewed_rev = models.CharField(verbose_name="reviewed revision", max_length=16, blank=True) - unused_result = ForeignKey(ReviewResultName, blank=True, null=True) - def __unicode__(self): return u"%s review on %s by %s %s" % (self.type, self.doc, self.team, self.state) diff --git a/ietf/review/utils.py b/ietf/review/utils.py index 5cef81fbe..3d2754423 100644 --- a/ietf/review/utils.py +++ b/ietf/review/utils.py @@ -167,7 +167,7 @@ def days_needed_to_fulfill_min_interval_for_reviewers(team): return res ReviewAssignmentData = namedtuple("ReviewAssignmentData", [ - "assignment_pk", "doc", "doc_pages", "req_time", "state", "assigned_time", "deadline", "reviewed_rev", "result", "team", "reviewer", + "assignment_pk", "doc_name", "doc_pages", "req_time", "state", "assigned_time", "deadline", "reviewed_rev", "result", "team", "reviewer", "late_days", "request_to_assignment_days", "assignment_to_closure_days", "request_to_closure_days"]) @@ -194,7 +194,7 @@ def extract_review_assignment_data(teams=None, reviewers=None, time_from=None, t event_qs = ReviewAssignment.objects.filter(filters) event_qs = event_qs.values_list( - "pk", "review_request__doc", "review_request__doc__pages", "review_request__time", "state", "review_request__deadline", "reviewed_rev", "result", "review_request__team", + "pk", "review_request__doc__name", "review_request__doc__pages", "review_request__time", "state", "review_request__deadline", "reviewed_rev", "result", "review_request__team", "reviewer__person", "assigned_on", "completed_on" ) @@ -215,7 +215,7 @@ def extract_review_assignment_data(teams=None, reviewers=None, time_from=None, t for assignment in event_qs: - assignment_pk, doc, doc_pages, req_time, state, deadline, reviewed_rev, result, team, reviewer, assigned_on, completed_on = assignment + assignment_pk, doc_name, doc_pages, req_time, state, deadline, reviewed_rev, result, team, reviewer, assigned_on, completed_on = assignment requested_time = req_time assigned_time = assigned_on @@ -226,7 +226,7 @@ def extract_review_assignment_data(teams=None, reviewers=None, time_from=None, t assignment_to_closure_days = positive_days(assigned_time, closed_time) request_to_closure_days = positive_days(requested_time, closed_time) - d = ReviewAssignmentData(assignment_pk, doc, doc_pages, req_time, state, assigned_time, deadline, reviewed_rev, result, team, reviewer, + d = ReviewAssignmentData(assignment_pk, doc_name, doc_pages, req_time, state, assigned_time, deadline, reviewed_rev, result, team, reviewer, late_days, request_to_assignment_days, assignment_to_closure_days, request_to_closure_days) @@ -659,7 +659,7 @@ def suggested_review_requests_for_team(team): # cancelled/moved telechat_events = TelechatDocEvent.objects.filter( # turn into list so we don't get a complex and slow join sent down to the DB - doc__in=list(telechat_docs.values_list("pk", flat=True)), + doc__id__in=list(telechat_docs.values_list("pk", flat=True)), ).values_list( "doc", "pk", "time", "telechat_date" ).order_by("doc", "-time", "-id").distinct() @@ -688,7 +688,7 @@ def suggested_review_requests_for_team(team): # filter those with existing explicit requests existing_requests = defaultdict(list) - for r in ReviewRequest.objects.filter(doc__in=requests.iterkeys(), team=team): + for r in ReviewRequest.objects.filter(doc__id__in=requests.iterkeys(), team=team): existing_requests[r.doc_id].append(r) def blocks(existing, request): @@ -719,8 +719,10 @@ def extract_revision_ordered_review_assignments_for_documents_and_replaced(revie replaces = extract_complete_replaces_ancestor_mapping_for_docs(names) assignments_for_each_doc = defaultdict(list) - for r in review_assignment_queryset.filter(review_request__doc__in=set(e for l in replaces.itervalues() for e in l) | names).order_by("-reviewed_rev","-assigned_on", "-id").iterator(): - assignments_for_each_doc[r.review_request.doc_id].append(r) + replacement_name_set = set(e for l in replaces.itervalues() for e in l) | names + for r in ( review_assignment_queryset.filter(review_request__doc__name__in=replacement_name_set) + .order_by("-reviewed_rev","-assigned_on", "-id").iterator()): + assignments_for_each_doc[r.review_request.doc.name].append(r) # now collect in breadth-first order to keep the revision order intact res = defaultdict(list) @@ -765,8 +767,8 @@ def extract_revision_ordered_review_requests_for_documents_and_replaced(review_r replaces = extract_complete_replaces_ancestor_mapping_for_docs(names) requests_for_each_doc = defaultdict(list) - for r in review_request_queryset.filter(doc__in=set(e for l in replaces.itervalues() for e in l) | names).order_by("-time", "-id").iterator(): - requests_for_each_doc[r.doc_id].append(r) + for r in review_request_queryset.filter(doc__name__in=set(e for l in replaces.itervalues() for e in l) | names).order_by("-time", "-id").iterator(): + requests_for_each_doc[r.doc.name].append(r) # now collect in breadth-first order to keep the revision order intact res = defaultdict(list) @@ -832,7 +834,7 @@ def make_assignment_choices(email_queryset, review_req): possible_emails = list(email_queryset) possible_person_ids = [e.person_id for e in possible_emails] - aliases = DocAlias.objects.filter(document=doc).values_list("name", flat=True) + aliases = DocAlias.objects.filter(docs=doc).values_list("name", flat=True) # settings reviewer_settings = { @@ -990,12 +992,12 @@ def email_reviewer_reminder(review_request): deadline_days = (review_request.deadline - datetime.date.today()).days - subject = "Reminder: deadline for review of {} in {} is {}".format(review_request.doc_id, team.acronym, review_request.deadline.isoformat()) + subject = "Reminder: deadline for review of {} in {} is {}".format(review_request.doc.name, team.acronym, review_request.deadline.isoformat()) import ietf.ietfauth.views overview_url = urlreverse(ietf.ietfauth.views.review_overview) import ietf.doc.views_review - request_url = urlreverse(ietf.doc.views_review.review_request, kwargs={ "name": review_request.doc_id, "request_id": review_request.pk }) + request_url = urlreverse(ietf.doc.views_review.review_request, kwargs={ "name": review_request.doc.name, "request_id": review_request.pk }) domain = Site.objects.get_current().domain @@ -1034,12 +1036,12 @@ def email_secretary_reminder(review_request, secretary_role): deadline_days = (review_request.deadline - datetime.date.today()).days - subject = "Reminder: deadline for review of {} in {} is {}".format(review_request.doc_id, team.acronym, review_request.deadline.isoformat()) + subject = "Reminder: deadline for review of {} in {} is {}".format(review_request.doc.name, team.acronym, review_request.deadline.isoformat()) import ietf.group.views settings_url = urlreverse(ietf.group.views.change_review_secretary_settings, kwargs={ "acronym": team.acronym, "group_type": team.type_id }) import ietf.doc.views_review - request_url = urlreverse(ietf.doc.views_review.review_request, kwargs={ "name": review_request.doc_id, "request_id": review_request.pk }) + request_url = urlreverse(ietf.doc.views_review.review_request, kwargs={ "name": review_request.doc.name, "request_id": review_request.pk }) domain = Site.objects.get_current().domain diff --git a/ietf/secr/drafts/views.py b/ietf/secr/drafts/views.py index 3c0b0f621..f5c343b1b 100644 --- a/ietf/secr/drafts/views.py +++ b/ietf/secr/drafts/views.py @@ -1,3 +1,6 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved +# -*- coding: utf-8 -*- + import datetime import glob import os @@ -579,7 +582,7 @@ def view(request, id): draft.rfc_number = get_rfc_num(draft) # check for replaced bys - qs = Document.objects.filter(relateddocument__target__document=draft, relateddocument__relationship='replaces') + qs = Document.objects.filter(relateddocument__target__docs=draft, relateddocument__relationship='replaces') if qs: draft.replaced_by = qs[0] diff --git a/ietf/secr/proceedings/proc_utils.py b/ietf/secr/proceedings/proc_utils.py index 549d37237..a25777b68 100644 --- a/ietf/secr/proceedings/proc_utils.py +++ b/ietf/secr/proceedings/proc_utils.py @@ -1,3 +1,6 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved +# -*- coding: utf-8 -*- + ''' proc_utils.py @@ -113,10 +116,10 @@ def attach_recording(doc, sessions): document=doc, rev=doc.rev) session.sessionpresentation_set.add(presentation) - if not doc.docalias_set.filter(name__startswith='recording-{}-{}'.format(session.meeting.number,session.group.acronym)): + if not doc.docalias.filter(name__startswith='recording-{}-{}'.format(session.meeting.number,session.group.acronym)): sequence = get_next_sequence(session.group,session.meeting,'recording') name = 'recording-{}-{}-{}'.format(session.meeting.number,session.group.acronym,sequence) - doc.docalias_set.create(name=name) + DocAlias.objects.create(name=name).docs.add(doc) def normalize_room_name(name): '''Returns room name converted to be used as portion of filename''' @@ -150,7 +153,7 @@ def create_recording(session, url, title=None, user=None): type_id='recording') doc.set_state(State.objects.get(type='recording', slug='active')) - doc.docalias_set.create(name=name) + DocAlias.objects.create(name=doc.name).docs.add(doc) # create DocEvent NewRevisionDocEvent.objects.create(type='new_revision', @@ -207,10 +210,10 @@ def get_progress_stats(sdate,edate): new_draft_events = events.filter(newrevisiondocevent__rev='00') new_drafts = list(set([ e.doc_id for e in new_draft_events ])) data['new_drafts_count'] = len(new_drafts) - data['new_drafts_updated_count'] = events.filter(doc__in=new_drafts,newrevisiondocevent__rev='01').count() - data['new_drafts_updated_more_count'] = events.filter(doc__in=new_drafts,newrevisiondocevent__rev='02').count() + data['new_drafts_updated_count'] = events.filter(doc__id__in=new_drafts,newrevisiondocevent__rev='01').count() + data['new_drafts_updated_more_count'] = events.filter(doc__id__in=new_drafts,newrevisiondocevent__rev='02').count() - update_events = events.filter(type='new_revision').exclude(doc__in=new_drafts) + update_events = events.filter(type='new_revision').exclude(doc__id__in=new_drafts) data['updated_drafts_count'] = len(set([ e.doc_id for e in update_events ])) # Calculate Final Four Weeks stats (ffw) @@ -224,7 +227,7 @@ def get_progress_stats(sdate,edate): data['ffw_new_count'] = ffw_new_count data['ffw_new_percent'] = ffw_new_percent - ffw_update_events = events.filter(time__gte=ffwdate,type='new_revision').exclude(doc__in=new_drafts) + ffw_update_events = events.filter(time__gte=ffwdate,type='new_revision').exclude(doc__id__in=new_drafts) ffw_update_count = len(set([ e.doc_id for e in ffw_update_events ])) try: ffw_update_percent = format(ffw_update_count / float(data['updated_drafts_count']),'.0%') diff --git a/ietf/secr/proceedings/tests.py b/ietf/secr/proceedings/tests.py index 8da4b99a8..66cb0b873 100644 --- a/ietf/secr/proceedings/tests.py +++ b/ietf/secr/proceedings/tests.py @@ -1,3 +1,6 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved +# -*- coding: utf-8 -*- + import debug # pyflakes:ignore import json import os @@ -132,8 +135,8 @@ class RecordingTestCase(TestCase): import_audio_files(meeting) doc = mars_session.materials.filter(type='recording').first() self.assertTrue(doc in ames_session.materials.all()) - self.assertTrue(doc.docalias_set.filter(name='recording-42-mars-1')) - self.assertTrue(doc.docalias_set.filter(name='recording-42-ames-1')) + self.assertTrue(doc.docalias.filter(name='recording-42-mars-1')) + self.assertTrue(doc.docalias.filter(name='recording-42-ames-1')) def test_normalize_room_name(self): self.assertEqual(normalize_room_name('Test Room'),'testroom') diff --git a/ietf/secr/telechat/tests.py b/ietf/secr/telechat/tests.py index 3dd066e6e..5b7245191 100644 --- a/ietf/secr/telechat/tests.py +++ b/ietf/secr/telechat/tests.py @@ -1,4 +1,6 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved # -*- coding: utf-8 -*- + import datetime from pyquery import PyQuery @@ -63,7 +65,7 @@ class SecrTelechatTestCase(TestCase): draft = WgDraftFactory(ad=ad, intended_std_level_id='ps', states=[('draft-iesg','pub-req'),]) rfc = IndividualRfcFactory.create(stream_id='irtf', other_aliases=['rfc6666',], states=[('draft','rfc'),('draft-iesg','pub')], std_level_id='inf', ) - draft.relateddocument_set.create(target=rfc.docalias_set.get(name='rfc6666'), + draft.relateddocument_set.create(target=rfc.docalias.get(name='rfc6666'), relationship_id='refnorm') create_ballot_if_not_open(None, draft, ad, 'approve') d = get_next_telechat_date() diff --git a/ietf/secr/utils/document.py b/ietf/secr/utils/document.py index 535758425..72ffbda31 100644 --- a/ietf/secr/utils/document.py +++ b/ietf/secr/utils/document.py @@ -1,3 +1,6 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved +# -*- coding: utf-8 -*- + def get_full_path(doc): ''' Returns for name of file on disk with full path. This should really be a method on doc @@ -10,11 +13,11 @@ def get_full_path(doc): return os.path.join(doc.get_file_path(), doc.uploaded_filename) def get_rfc_num(doc): - qs = doc.docalias_set.filter(name__startswith='rfc') + qs = doc.docalias.filter(name__startswith='rfc') return qs[0].name[3:] if qs else None def is_draft(doc): - if doc.docalias_set.filter(name__startswith='rfc'): + if doc.docalias.filter(name__startswith='rfc'): return False else: return True diff --git a/ietf/settings.py b/ietf/settings.py index ec36da0eb..c5112b202 100644 --- a/ietf/settings.py +++ b/ietf/settings.py @@ -1,4 +1,5 @@ -# Copyright The IETF Trust 2007, All Rights Reserved +# Copyright The IETF Trust 2007-2019, All Rights Reserved +# -*- coding: utf-8 -*- # Django settings for ietf project. # BASE_DIR and "settings_local" are from @@ -21,6 +22,7 @@ warnings.filterwarnings("ignore", message="Deprecated allow_tags attribute used warnings.filterwarnings("ignore", message="You passed a bytestring as `filenames`. This will not work on Python 3.") warnings.filterwarnings("ignore", message="django.forms.extras is deprecated.", module="bootstrap3") warnings.filterwarnings("ignore", message="defusedxml.lxml is no longer supported and will be removed in a future release.", module="tastypie") +warnings.filterwarnings("ignore", message="Duplicate index '.*' defined on the table") try: diff --git a/ietf/stats/backfill_data.py b/ietf/stats/backfill_data.py index 8af30442f..5946abc0c 100755 --- a/ietf/stats/backfill_data.py +++ b/ietf/stats/backfill_data.py @@ -1,4 +1,5 @@ #!/usr/bin/env python +# Copyright The IETF Trust 2017-2019, All Rights Reserved from __future__ import print_function, unicode_literals @@ -68,9 +69,9 @@ def unicode(text): start = time.time() say("Running query for documents to process ...") -for doc in docs_qs.prefetch_related("docalias_set", "formal_languages", "documentauthor_set", "documentauthor_set__person", "documentauthor_set__person__alias_set"): +for doc in docs_qs.prefetch_related("docalias", "formal_languages", "documentauthor_set", "documentauthor_set__person", "documentauthor_set__person__alias_set"): canonical_name = doc.name - for n in doc.docalias_set.all(): + for n in doc.docalias.all(): if n.name.startswith("rfc"): canonical_name = n.name diff --git a/ietf/stats/tests.py b/ietf/stats/tests.py index 13656a723..f0c6888ae 100644 --- a/ietf/stats/tests.py +++ b/ietf/stats/tests.py @@ -1,3 +1,6 @@ +# Copyright The IETF Trust 2016-2019, All Rights Reserved +# -*- coding: utf-8 -*- + import datetime from mock import patch @@ -71,10 +74,10 @@ class StatisticsTests(TestCase): words=100 ) referencing_draft.set_state(State.objects.get(used=True, type="draft", slug="active")) - DocAlias.objects.create(document=referencing_draft, name=referencing_draft.name) + DocAlias.objects.create(name=referencing_draft.name).docs.add(referencing_draft) RelatedDocument.objects.create( source=referencing_draft, - target=draft.docalias_set.first(), + target=draft.docalias.first(), relationship=DocRelationshipName.objects.get(slug="refinfo") ) NewRevisionDocEvent.objects.create( diff --git a/ietf/stats/views.py b/ietf/stats/views.py index 4eeac6506..94e7a30e4 100644 --- a/ietf/stats/views.py +++ b/ietf/stats/views.py @@ -1,3 +1,6 @@ +# Copyright The IETF Trust 2016-2019, All Rights Reserved +# -*- coding: utf-8 -*- + import os import calendar import datetime @@ -205,13 +208,13 @@ def document_stats(request, stats_type=None): if any(stats_type == t[0] for t in possible_document_stats_types): # filter documents - docalias_filters = Q(document__type="draft") + docalias_filters = Q(docs__type="draft") rfc_state = State.objects.get(type="draft", slug="rfc") if document_type == "rfc": - docalias_filters &= Q(document__states=rfc_state) + docalias_filters &= Q(docs__states=rfc_state) elif document_type == "draft": - docalias_filters &= ~Q(document__states=rfc_state) + docalias_filters &= ~Q(docs__states=rfc_state) if from_time: # this is actually faster than joining in the database, @@ -222,7 +225,7 @@ def document_stats(request, stats_type=None): docevent__type__in=["published_rfc", "new_revision"], ).values_list("pk")) - docalias_filters &= Q(document__in=docs_within_time_constraint) + docalias_filters &= Q(docs__in=docs_within_time_constraint) docalias_qs = DocAlias.objects.filter(docalias_filters) @@ -233,10 +236,10 @@ def document_stats(request, stats_type=None): else: doc_label = "document" - total_docs = docalias_qs.values_list("document").distinct().count() + total_docs = docalias_qs.values_list("docs__name").distinct().count() def generate_canonical_names(docalias_qs): - for doc_id, ts in itertools.groupby(docalias_qs.order_by("document"), lambda t: t[0]): + for doc_id, ts in itertools.groupby(docalias_qs.order_by("docs__name"), lambda t: t[0]): chosen = None for t in ts: if chosen is None: @@ -254,7 +257,7 @@ def document_stats(request, stats_type=None): bins = defaultdict(set) - for name, canonical_name, author_count in generate_canonical_names(docalias_qs.values_list("document", "name").annotate(Count("document__documentauthor"))): + for name, canonical_name, author_count in generate_canonical_names(docalias_qs.values_list("docs__name", "name").annotate(Count("docs__documentauthor"))): bins[author_count].add(canonical_name) series_data = [] @@ -270,7 +273,7 @@ def document_stats(request, stats_type=None): bins = defaultdict(set) - for name, canonical_name, pages in generate_canonical_names(docalias_qs.values_list("document", "name", "document__pages")): + for name, canonical_name, pages in generate_canonical_names(docalias_qs.values_list("docs__name", "name", "docs__pages")): bins[pages].add(canonical_name) series_data = [] @@ -289,7 +292,7 @@ def document_stats(request, stats_type=None): bins = defaultdict(set) - for name, canonical_name, words in generate_canonical_names(docalias_qs.values_list("document", "name", "document__words")): + for name, canonical_name, words in generate_canonical_names(docalias_qs.values_list("docs__name", "name", "docs__words")): bins[put_into_bin(words, bin_size)].add(canonical_name) series_data = [] @@ -314,7 +317,7 @@ def document_stats(request, stats_type=None): submission_types[doc_name] = file_types doc_names_with_missing_types = {} - for doc_name, canonical_name, rev in generate_canonical_names(docalias_qs.values_list("document", "name", "document__rev")): + for doc_name, canonical_name, rev in generate_canonical_names(docalias_qs.values_list("docs__name", "name", "docs__rev")): types = submission_types.get(doc_name) if types: for dot_ext in types.split(","): @@ -359,7 +362,7 @@ def document_stats(request, stats_type=None): bins = defaultdict(set) - for name, canonical_name, formal_language_name in generate_canonical_names(docalias_qs.values_list("document", "name", "document__formal_languages__name")): + for name, canonical_name, formal_language_name in generate_canonical_names(docalias_qs.values_list("docs__name", "name", "docs__formal_languages__name")): bins[formal_language_name].add(canonical_name) series_data = [] diff --git a/ietf/submit/migrations/0002_submission_document2_fk.py b/ietf/submit/migrations/0002_submission_document2_fk.py new file mode 100644 index 000000000..153a34559 --- /dev/null +++ b/ietf/submit/migrations/0002_submission_document2_fk.py @@ -0,0 +1,29 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-08 11:58 +from __future__ import unicode_literals + +from django.db import migrations +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0015_1_add_fk_to_document_id'), + ('submit', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='submission', + name='draft2', + field=ietf.utils.models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field=b'id'), + ), + migrations.AlterField( + model_name='submission', + name='draft', + field=ietf.utils.models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='old_submission', to='doc.Document', to_field=b'name'), + ), + ] diff --git a/ietf/submit/migrations/0003_remove_old_document_field.py b/ietf/submit/migrations/0003_remove_old_document_field.py new file mode 100644 index 000000000..8a5cf2104 --- /dev/null +++ b/ietf/submit/migrations/0003_remove_old_document_field.py @@ -0,0 +1,20 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-25 06:44 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('submit', '0002_submission_document2_fk'), + ] + + operations = [ + migrations.RemoveField( + model_name='submission', + name='draft', + ), + ] diff --git a/ietf/submit/migrations/0004_rename_field_document2.py b/ietf/submit/migrations/0004_rename_field_document2.py new file mode 100644 index 000000000..cb8e32f15 --- /dev/null +++ b/ietf/submit/migrations/0004_rename_field_document2.py @@ -0,0 +1,22 @@ +# Copyright The IETF Trust 2019, All Rights Reserved +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-25 06:46 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0019_rename_field_document2'), + ('submit', '0003_remove_old_document_field'), + ] + + operations = [ + migrations.RenameField( + model_name='submission', + old_name='draft2', + new_name='draft', + ), + ] diff --git a/ietf/submit/tests.py b/ietf/submit/tests.py index 50cbcceb8..7a6146584 100644 --- a/ietf/submit/tests.py +++ b/ietf/submit/tests.py @@ -1,5 +1,5 @@ +# Copyright The IETF Trust 2011-2019, All Rights Reserved # -*- coding: utf-8 -*- -# Copyright The IETF Trust 2011, All Rights Reserved from __future__ import unicode_literals, print_function import datetime @@ -181,7 +181,7 @@ class SubmitTests(TestCase): if r.status_code == 302: submission = Submission.objects.get(name=name) self.assertEqual(submission.submitter, email.utils.formataddr((submitter_name, submitter_email))) - self.assertEqual(submission.replaces, ",".join(d.name for d in DocAlias.objects.filter(pk__in=replaces.split(",") if replaces else []))) + self.assertEqual(submission.replaces, ",".join(d.name for d in DocAlias.objects.filter(name__in=replaces.split(",") if replaces else []))) return r @@ -224,8 +224,8 @@ class SubmitTests(TestCase): note="", ) sug_replaced_draft.set_state(State.objects.get(used=True, type="draft", slug="active")) - sug_replaced_alias = DocAlias.objects.create(document=sug_replaced_draft, name=sug_replaced_draft.name) - + sug_replaced_alias = DocAlias.objects.create(name=sug_replaced_draft.name) + sug_replaced_alias.docs.add(sug_replaced_draft) name = "draft-ietf-mars-testing-tests" rev = "00" @@ -235,9 +235,9 @@ class SubmitTests(TestCase): # supply submitter info, then draft should be in and ready for approval mailbox_before = len(outbox) - replaced_alias = draft.docalias_set.first() + replaced_alias = draft.docalias.first() r = self.supply_extra_metadata(name, status_url, author.ascii, author.email().address.lower(), - replaces=str(replaced_alias.pk) + "," + str(sug_replaced_alias.pk)) + replaces=str(replaced_alias.name) + "," + str(sug_replaced_alias.name)) self.assertEqual(r.status_code, 302) status_url = r["Location"] @@ -593,17 +593,17 @@ class SubmitTests(TestCase): rev = '%02d'%(int(draft.rev)+1) status_url, author = self.do_submission(name,rev) mailbox_before = len(outbox) - replaced_alias = draft.docalias_set.first() - r = self.supply_extra_metadata(name, status_url, "Submitter Name", "author@example.com", replaces=str(replaced_alias.pk)) + replaced_alias = draft.docalias.first() + r = self.supply_extra_metadata(name, status_url, "Submitter Name", "author@example.com", replaces=str(replaced_alias.name)) self.assertEqual(r.status_code, 200) self.assertTrue('cannot replace itself' in unicontent(r)) replaced_alias = DocAlias.objects.get(name='draft-ietf-random-thing') - r = self.supply_extra_metadata(name, status_url, "Submitter Name", "author@example.com", replaces=str(replaced_alias.pk)) + r = self.supply_extra_metadata(name, status_url, "Submitter Name", "author@example.com", replaces=str(replaced_alias.name)) self.assertEqual(r.status_code, 200) self.assertTrue('cannot replace an RFC' in unicontent(r)) replaced_alias.document.set_state(State.objects.get(type='draft-iesg',slug='approved')) replaced_alias.document.set_state(State.objects.get(type='draft',slug='active')) - r = self.supply_extra_metadata(name, status_url, "Submitter Name", "author@example.com", replaces=str(replaced_alias.pk)) + r = self.supply_extra_metadata(name, status_url, "Submitter Name", "author@example.com", replaces=str(replaced_alias.name)) self.assertEqual(r.status_code, 200) self.assertTrue('approved by the IESG and cannot' in unicontent(r)) r = self.supply_extra_metadata(name, status_url, "Submitter Name", "author@example.com", replaces='') @@ -737,7 +737,7 @@ class SubmitTests(TestCase): "edit-pages": "123", "submitter-name": "Some Random Test Person", "submitter-email": "random@example.com", - "replaces": str(draft.docalias_set.all().first().pk), + "replaces": str(draft.docalias.first().name), "edit-note": "no comments", "authors-0-name": "Person 1", "authors-0-email": "person1@example.com", @@ -757,7 +757,7 @@ class SubmitTests(TestCase): self.assertEqual(submission.pages, 123) self.assertEqual(submission.note, "no comments") self.assertEqual(submission.submitter, "Some Random Test Person ") - self.assertEqual(submission.replaces, draft.docalias_set.all().first().name) + self.assertEqual(submission.replaces, draft.docalias.first().name) self.assertEqual(submission.state_id, "manual") authors = submission.authors diff --git a/ietf/submit/utils.py b/ietf/submit/utils.py index bced88988..50cd7a0f8 100644 --- a/ietf/submit/utils.py +++ b/ietf/submit/utils.py @@ -264,7 +264,8 @@ def post_submission(request, submission, approvedDesc): events.append(e) # update related objects - DocAlias.objects.get_or_create(name=submission.name, document=draft) + alias, __ = DocAlias.objects.get_or_create(name=submission.name) + alias.docs.add(draft) draft.set_state(State.objects.get(used=True, type="draft", slug="active")) @@ -378,7 +379,7 @@ def update_replaces_from_submission(request, submission, draft): if request.user.is_authenticated: is_chair_of = list(Group.objects.filter(role__person__user=request.user, role__name="chair")) - replaces = DocAlias.objects.filter(name__in=submission.replaces.split(",")).select_related("document", "document__group") + replaces = DocAlias.objects.filter(name__in=submission.replaces.split(",")).prefetch_related("docs", "docs__group") existing_replaces = list(draft.related_that_doc("replaces")) existing_suggested = set(draft.related_that_doc("possibly-replaces")) diff --git a/ietf/sync/rfceditor.py b/ietf/sync/rfceditor.py index aad98a0e5..8ad50da1f 100644 --- a/ietf/sync/rfceditor.py +++ b/ietf/sync/rfceditor.py @@ -1,3 +1,6 @@ +# Copyright The IETF Trust 2012-2019, All Rights Reserved +# -*- coding: utf-8 -*- + import re import base64 import datetime @@ -370,7 +373,7 @@ def update_docs_from_rfc_index(data, skip_older_than_date=None): # make sure we got the document and alias doc = None name = "rfc%s" % rfc_number - a = DocAlias.objects.filter(name=name).select_related("document") + a = DocAlias.objects.filter(name=name) if a: doc = a[0].document else: @@ -385,7 +388,8 @@ def update_docs_from_rfc_index(data, skip_older_than_date=None): doc = Document.objects.create(name=name, type=DocTypeName.objects.get(slug="draft")) # add alias - DocAlias.objects.get_or_create(name=name, document=doc) + alias, __ = DocAlias.objects.get_or_create(name=name) + alias.docs.add(doc) changes.append("created alias %s" % prettify_std_name(name)) # check attributes @@ -458,7 +462,7 @@ def update_docs_from_rfc_index(data, skip_older_than_date=None): if x[:3] in ("NIC", "IEN", "STD", "RTR"): # try translating this to RFCs that we can handle # sensibly; otherwise we'll have to ignore them - l = DocAlias.objects.filter(name__startswith="rfc", document__docalias__name=x.lower()) + l = DocAlias.objects.filter(name__startswith="rfc", docs__docalias__name=x.lower()) else: l = DocAlias.objects.filter(name=x.lower()) @@ -481,7 +485,7 @@ def update_docs_from_rfc_index(data, skip_older_than_date=None): for a in also: a = a.lower() if not DocAlias.objects.filter(name=a): - DocAlias.objects.create(name=a, document=doc) + DocAlias.objects.create(name=a).docs.add(doc) changes.append("created alias %s" % prettify_std_name(a)) if has_errata: diff --git a/ietf/sync/tests.py b/ietf/sync/tests.py index 171bcd065..fd254ab0c 100644 --- a/ietf/sync/tests.py +++ b/ietf/sync/tests.py @@ -1,4 +1,6 @@ +# Copyright The IETF Trust 2012-2019, All Rights Reserved # -*- coding: utf-8 -*- + import os import json import datetime @@ -22,7 +24,7 @@ from ietf.utils.test_utils import TestCase class IANASyncTests(TestCase): def test_protocol_page_sync(self): draft = WgDraftFactory() - DocAlias.objects.create(name="rfc1234", document=draft) + DocAlias.objects.create(name="rfc1234").docs.add(draft) DocEvent.objects.create(doc=draft, rev=draft.rev, type="published_rfc", by=Person.objects.get(name="(System)")) rfc_names = iana.parse_protocol_page('RFC 1234') @@ -234,8 +236,8 @@ class RFCSyncTests(TestCase): # too, but for testing purposes ... updated_doc = Document.objects.create(name="draft-ietf-something") - DocAlias.objects.create(name=updated_doc.name, document=updated_doc) - DocAlias.objects.create(name="rfc123", document=updated_doc) + DocAlias.objects.create(name=updated_doc.name).docs.add(updated_doc) + DocAlias.objects.create(name="rfc123").docs.add(updated_doc) today = datetime.date.today() @@ -337,10 +339,10 @@ class RFCSyncTests(TestCase): self.assertEqual(doc.docevent_set.all()[1].type, "published_rfc") self.assertEqual(doc.docevent_set.all()[1].time.date(), today) self.assertTrue("errata" in doc.tags.all().values_list("slug", flat=True)) - self.assertTrue(DocAlias.objects.filter(name="rfc1234", document=doc)) - self.assertTrue(DocAlias.objects.filter(name="bcp1", document=doc)) - self.assertTrue(DocAlias.objects.filter(name="fyi1", document=doc)) - self.assertTrue(DocAlias.objects.filter(name="std1", document=doc)) + self.assertTrue(DocAlias.objects.filter(name="rfc1234", docs=doc)) + self.assertTrue(DocAlias.objects.filter(name="bcp1", docs=doc)) + self.assertTrue(DocAlias.objects.filter(name="fyi1", docs=doc)) + self.assertTrue(DocAlias.objects.filter(name="std1", docs=doc)) self.assertTrue(RelatedDocument.objects.filter(source=doc, target__name="rfc123", relationship="updates")) self.assertEqual(doc.title, "A Testing RFC") self.assertEqual(doc.abstract, "This is some interesting text.") @@ -478,7 +480,7 @@ class RFCEditorUndoTests(TestCase): # get r = self.client.get(url) self.assertEqual(r.status_code, 200) - self.assertTrue(e2.doc_id in unicontent(r)) + self.assertTrue(e2.doc.name in unicontent(r)) # delete e2 deleted_before = DeletedEvent.objects.count() diff --git a/ietf/templates/community/notification_email.txt b/ietf/templates/community/notification_email.txt index 0fc1c662c..56a859caa 100644 --- a/ietf/templates/community/notification_email.txt +++ b/ietf/templates/community/notification_email.txt @@ -1,10 +1,10 @@ -{% autoescape off %}{% load ietf_filters %} +{# Copyright The IETF Trust 2019, All Rights Reserved #}{% autoescape off %}{% load ietf_filters %} Hello, This is a notification from the {{ clist.long_name }}. Document: {{ event.doc }}, -https://datatracker.ietf.org/doc/{{ event.doc_id }}/ +https://datatracker.ietf.org/doc/{{ event.doc.name }}/ Change by {{ event.by }} on {{ event.time }}: diff --git a/ietf/templates/doc/document_review.html b/ietf/templates/doc/document_review.html index efa13552f..e62fbb7a7 100644 --- a/ietf/templates/doc/document_review.html +++ b/ietf/templates/doc/document_review.html @@ -1,5 +1,5 @@ {% extends "base.html" %} -{# Copyright The IETF Trust 2016, All Rights Reserved #} +{# Copyright The IETF Trust 2016-2019, All Rights Reserved #} {% load origin %} {% load staticfiles %} {% load ietf_filters %} @@ -44,7 +44,7 @@ diff --git a/ietf/templates/doc/review_assignment_summary.html b/ietf/templates/doc/review_assignment_summary.html index e6e9bcca6..de4e82040 100644 --- a/ietf/templates/doc/review_assignment_summary.html +++ b/ietf/templates/doc/review_assignment_summary.html @@ -1,12 +1,12 @@
{% if review_assignment.state_id == "completed" or review_assignment.state_id == "part-completed" %} - - {{ review_assignment.review_request.team.acronym|upper }} {{ review_assignment.review_request.type.name }} Review{% if review_assignment.reviewed_rev and review_assignment.reviewed_rev != current_rev or review_assignment.review_request.doc_id != current_doc_name %} (of {% if review_assignment.review_request.doc_id != current_doc_name %}{{ review_assignment.review_request.doc_id }}{% endif %}-{{ review_assignment.reviewed_rev }}){% endif %}{% if review_assignment.result %}: + + {{ review_assignment.review_request.team.acronym|upper }} {{ review_assignment.review_request.type.name }} Review{% if review_assignment.reviewed_rev and review_assignment.reviewed_rev != current_rev or review_assignment.review_request.doc.name != current_doc_name %} (of {% if review_assignment.review_request.doc.name != current_doc_name %}{{ review_assignment.review_request.doc.name }}{% endif %}-{{ review_assignment.reviewed_rev }}){% endif %}{% if review_assignment.result %}: {{ review_assignment.result.name }}{% endif %} {% if review_assignment.state_id == "part-completed" %}(partially completed){% endif %} {% else %} - {{ review_assignment.review_request.team.acronym|upper }} {{ review_assignment.review_request.type.name }} Review + {{ review_assignment.review_request.team.acronym|upper }} {{ review_assignment.review_request.type.name }} Review - due: {{ review_assignment.review_request.deadline|date:"Y-m-d" }} {% endif %}
diff --git a/ietf/templates/group/manage_review_requests.html b/ietf/templates/group/manage_review_requests.html index 589bbdc9a..a72760a40 100644 --- a/ietf/templates/group/manage_review_requests.html +++ b/ietf/templates/group/manage_review_requests.html @@ -1,5 +1,5 @@ {% extends "base.html" %} -{# Copyright The IETF Trust 2015, All Rights Reserved #} +{# Copyright The IETF Trust 2015-2019, All Rights Reserved #} {% load origin %}{% origin %} {% load ietf_filters staticfiles bootstrap3 %} @@ -63,14 +63,14 @@
{% if alatest.reviewed_rev %} Previous review of - {% if rlatest.doc_id != r.doc_id %}{{ rlatest.doc_id }}{% endif %}-{{ alatest.reviewed_rev }}{% if alatest.reviewed_rev != r.doc.rev %} + {% if rlatest.doc.name != r.doc.name %}{{ rlatest.doc.name }}{% endif %}-{{ alatest.reviewed_rev }}{% if alatest.reviewed_rev != r.doc.rev %} (diff){% endif %}: {% if alatest.result %}{{ alatest.result.name }}{% else %}result unavail.{% endif %} by {{ alatest.reviewer.person }}{% if alatest.closed_review_request_event %} {{ alatest.closed_review_request_event.time.date|date }}{% endif %} {% else %} Previous review of - {% if rlatest.doc_id != r.doc_id %}{{ rlatest.doc_id }}{% else %}this document{% endif %}: - {% if alatest.result %}{{ alatest.result.name }}{% else %}result unavail.{% endif %} + {% if rlatest.doc.name != r.doc.name %}{{ rlatest.doc.name }}{% else %}this document{% endif %}: + {% if alatest.result %}{{ alatest.result.name }}{% else %}result unavail.{% endif %} by {{ alatest.reviewer.person }}{% if alatest.closed_review_request_event %} {{ alatest.closed_review_request_event.time.date|date }}{% endif %} {% endif %}
diff --git a/ietf/templates/iesg/agenda_doc.txt b/ietf/templates/iesg/agenda_doc.txt index c5700d795..247d456a5 100644 --- a/ietf/templates/iesg/agenda_doc.txt +++ b/ietf/templates/iesg/agenda_doc.txt @@ -6,6 +6,6 @@ IANA Review: {{ doc.iana_review_state }}{% endif %}{% if doc.consensus %} Consensus: {{ doc.consensus }}{% endif %}{% if doc.lastcall_expires %} Last call expires: {{ doc.lastcall_expires|date:"Y-m-d" }}{% endif %}{% if doc.review_assignments %} - Reviews: {% for assignment in doc.review_assignments %}{% with current_doc_name=doc.name current_rev=doc.rev %}{% if not forloop.first %} {% endif %}{{ assignment.review_request.team.acronym|upper }} {{ assignment.review_request.type.name }} Review{% if assignment.state_id == "completed" or assignment.state_id == "part-completed" %}{% if assignment.reviewed_rev and assignment.reviewed_rev != current_rev or assignment.review_request.doc_id != current_doc_name %} (of {% if assignment.review_request.doc_id != current_doc_name %}{{ assignment.review_request.doc_id }}{% endif %}-{{ assignment.reviewed_rev }}){% endif %}{% if assignment.result %}: {{ assignment.result.name }}{% endif %} {% if assignment.state_id == "part-completed" %}(partially completed){% endif %}{% else %} - due: {{ assignment.review_request.deadline|date:"Y-m-d" }}{% endif %}{% endwith %} + Reviews: {% for assignment in doc.review_assignments %}{% with current_doc_name=doc.name current_rev=doc.rev %}{% if not forloop.first %} {% endif %}{{ assignment.review_request.team.acronym|upper }} {{ assignment.review_request.type.name }} Review{% if assignment.state_id == "completed" or assignment.state_id == "part-completed" %}{% if assignment.reviewed_rev and assignment.reviewed_rev != current_rev or assignment.review_request.doc.name != current_doc_name %} (of {% if assignment.review_request.doc.name != current_doc_name %}{{ assignment.review_request.doc.name }}{% endif %}-{{ assignment.reviewed_rev }}){% endif %}{% if assignment.result %}: {{ assignment.result.name }}{% endif %} {% if assignment.state_id == "part-completed" %}(partially completed){% endif %}{% else %} - due: {{ assignment.review_request.deadline|date:"Y-m-d" }}{% endif %}{% endwith %} {% endfor %}{% endif %} {% with doc.active_defer_event as defer %}{% if defer %} Was deferred by {{defer.by}} on {{defer.time|date:"Y-m-d"}}{% endif %}{% endwith %} diff --git a/ietf/templates/ietfauth/review_overview.html b/ietf/templates/ietfauth/review_overview.html index e79259a5b..86f503dae 100644 --- a/ietf/templates/ietfauth/review_overview.html +++ b/ietf/templates/ietfauth/review_overview.html @@ -1,5 +1,5 @@ {% extends "base.html" %} -{# Copyright The IETF Trust 2015, All Rights Reserved #} +{# Copyright The IETF Trust 2015-2019, All Rights Reserved #} {% load origin %} {% load bootstrap3 static %} @@ -95,7 +95,7 @@
{% for review_assignment in other_reviews %} - {% include "doc/review_assignment_summary.html" with current_doc_name=review_assignemnt.review_request.doc_id current_rev=review_assignment.reviewed_rev %} + {% include "doc/review_assignment_summary.html" with current_doc_name=review_assignemnt.review_request.doc.name current_rev=review_assignment.reviewed_rev %} {% endfor %}
{% for w in review_wishes %} - + - +
{{ w.doc_id }}{{ w.doc_id }} {{ w.team.acronym }}
diff --git a/ietf/templates/review/reviewer_reminder.txt b/ietf/templates/review/reviewer_reminder.txt index d2fe608cf..a15306d9b 100644 --- a/ietf/templates/review/reviewer_reminder.txt +++ b/ietf/templates/review/reviewer_reminder.txt @@ -1,4 +1,4 @@ -{% load ietf_filters %}{% autoescape off %}{% filter wordwrap:78 %}This is just a friendly reminder that the deadline for the review of {{ review_request.doc_id }} is in {{ deadline_days }} day{{ deadline_days|pluralize }}: +{% load ietf_filters %}{% autoescape off %}{% filter wordwrap:78 %}This is just a friendly reminder that the deadline for the review of {{ review_request.doc.name }} is in {{ deadline_days }} day{{ deadline_days|pluralize }}: {{ review_request_url }} diff --git a/ietf/templates/review/secretary_reminder.txt b/ietf/templates/review/secretary_reminder.txt index 2361489f3..5315b3646 100644 --- a/ietf/templates/review/secretary_reminder.txt +++ b/ietf/templates/review/secretary_reminder.txt @@ -1,4 +1,4 @@ -{% load ietf_filters %}{% autoescape off %}{% filter wordwrap:78 %}This is just a friendly reminder that the deadline for the review of {{ review_request.doc_id }} is in {{ deadline_days }} day{{ deadline_days|pluralize }}: +{% load ietf_filters %}{% autoescape off %}{% filter wordwrap:78 %}This is just a friendly reminder that the deadline for the review of {{ review_request.doc.name }} is in {{ deadline_days }} day{{ deadline_days|pluralize }}: {{ review_request_url }} diff --git a/ietf/templates/sync/rfceditor_undo.html b/ietf/templates/sync/rfceditor_undo.html index 50a3ab951..ca1d70187 100644 --- a/ietf/templates/sync/rfceditor_undo.html +++ b/ietf/templates/sync/rfceditor_undo.html @@ -1,5 +1,5 @@ {% extends "base.html" %} -{# Copyright The IETF Trust 2015, All Rights Reserved #} +{# Copyright The IETF Trust 2015-2019, All Rights Reserved #} {% load origin %} {% block title %}Undo RFC Editor state events{% endblock %} @@ -22,7 +22,7 @@ {% for e in events %}
{{ e.time|date:"Y-m-d H:i:s"}}{{ e.doc_id }}{{ e.doc.name }} {{ e.desc|safe }} diff --git a/ietf/utils/history.py b/ietf/utils/history.py index 85e65024d..992902572 100644 --- a/ietf/utils/history.py +++ b/ietf/utils/history.py @@ -1,3 +1,8 @@ +# Copyright The IETF Trust 2011-2019, All Rights Reserved +# -*- coding: utf-8 -*- + +import debug # pyflakes:ignore + def find_history_active_at(obj, time): """Assumes obj has a corresponding history model (e.g. obj could be Document with a corresponding DocHistory model), then either diff --git a/ietf/utils/test_data.py b/ietf/utils/test_data.py index 04fc0f3a9..94e34a030 100644 --- a/ietf/utils/test_data.py +++ b/ietf/utils/test_data.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2017, All Rights Reserved +# Copyright The IETF Trust 2017-2019, All Rights Reserved # -*- coding: utf-8 -*- from __future__ import unicode_literals @@ -158,10 +158,7 @@ def make_test_data(): charter.set_state(State.objects.get(used=True, slug="approved", type="charter")) group.charter = charter group.save() - DocAlias.objects.create( - name=charter.name, - document=charter - ) + DocAlias.objects.create(name=charter.name).docs.add(charter) setup_default_community_list_for_group(group) # ames WG @@ -183,10 +180,7 @@ def make_test_data(): rev="00", ) charter.set_state(State.objects.get(used=True, slug="infrev", type="charter")) - DocAlias.objects.create( - name=charter.name, - document=charter - ) + DocAlias.objects.create(name=charter.name).docs.add(charter) group.charter = charter group.save() setup_default_community_list_for_group(group) @@ -220,10 +214,7 @@ def make_test_data(): # rev="00", # ) #charter.set_state(State.objects.get(used=True, slug="infrev", type="charter")) - #DocAlias.objects.create( - # name=charter.name, - # document=charter - # ) + #DocAlias.objects.create(name=charter.name).docs.add(charter) #group.charter = charter #group.save() @@ -266,7 +257,8 @@ def make_test_data(): expires=datetime.datetime.now(), ) old_draft.set_state(State.objects.get(used=True, type="draft", slug="expired")) - old_alias = DocAlias.objects.create(document=old_draft, name=old_draft.name) + old_alias = DocAlias.objects.create(name=old_draft.name) + old_alias.docs.add(old_draft) # draft draft = Document.objects.create( @@ -291,10 +283,8 @@ def make_test_data(): draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="pub-req")) draft.set_state(State.objects.get(used=True, type="draft-stream-%s" % draft.stream_id, slug="wg-doc")) - doc_alias = DocAlias.objects.create( - document=draft, - name=draft.name, - ) + doc_alias = DocAlias.objects.create(name=draft.name) + doc_alias.docs.add(draft) RelatedDocument.objects.create(source=draft, target=old_alias, relationship=DocRelationshipName.objects.get(slug='replaces')) old_draft.set_state(State.objects.get(type='draft', slug='repl')) @@ -371,16 +361,17 @@ def make_test_data(): doc = Document.objects.create(name='draft-imaginary-independent-submission',type_id='draft',rev='00', title="Some Independent Notes on Imagination") doc.set_state(State.objects.get(used=True, type="draft", slug="active")) - DocAlias.objects.create(name=doc.name, document=doc) + DocAlias.objects.create(name=doc.name).docs.add(doc) # an irtf submission mid review doc = Document.objects.create(name='draft-imaginary-irtf-submission', type_id='draft',rev='00', stream=StreamName.objects.get(slug='irtf'), title="The Importance of Research Imagination") - docalias = DocAlias.objects.create(name=doc.name, document=doc) + docalias = DocAlias.objects.create(name=doc.name) + docalias.docs.add(doc) doc.set_state(State.objects.get(type="draft", slug="active")) crdoc = Document.objects.create(name='conflict-review-imaginary-irtf-submission', type_id='conflrev', rev='00', notify="fsm@ietf.org", title="Conflict Review of IRTF Imagination Document") - DocAlias.objects.create(name=crdoc.name, document=crdoc) + DocAlias.objects.create(name=crdoc.name).docs.add(crdoc) crdoc.set_state(State.objects.get(name='Needs Shepherd', type__slug='conflrev')) crdoc.relateddocument_set.create(target=docalias,relationship_id='conflrev') @@ -389,14 +380,15 @@ def make_test_data(): doc = Document.objects.create(name='status-change-imaginary-mid-review',type_id='statchg', rev='00', notify="fsm@ietf.org", group=iesg, title="Status Change Review without Imagination") doc.set_state(State.objects.get(slug='needshep',type__slug='statchg')) - docalias = DocAlias.objects.create(name='status-change-imaginary-mid-review',document=doc) + docalias = DocAlias.objects.create(name='status-change-imaginary-mid-review') + docalias.docs.add(doc) # Some things for a status change to affect def rfc_for_status_change_test_factory(name,rfc_num,std_level_id): target_rfc = Document.objects.create(name=name, type_id='draft', std_level_id=std_level_id, notify="%s@ietf.org"%name) target_rfc.set_state(State.objects.get(slug='rfc',type__slug='draft')) - docalias = DocAlias.objects.create(name=name,document=target_rfc) - docalias = DocAlias.objects.create(name='rfc%d'%rfc_num,document=target_rfc) # pyflakes:ignore + DocAlias.objects.create(name=name).docs.add(target_rfc) + DocAlias.objects.create(name='rfc%d'%rfc_num).docs.add(target_rfc) return target_rfc rfc_for_status_change_test_factory('draft-ietf-random-thing',9999,'ps') rfc_for_status_change_test_factory('draft-ietf-random-otherthing',9998,'inf') diff --git a/ietf/utils/test_runner.py b/ietf/utils/test_runner.py index 8bd818ce1..5482de9f7 100644 --- a/ietf/utils/test_runner.py +++ b/ietf/utils/test_runner.py @@ -64,6 +64,7 @@ from django.template import TemplateDoesNotExist from django.template.loaders.base import Loader as BaseLoader from django.test.runner import DiscoverRunner from django.core.management import call_command + from django.urls import RegexURLResolver import debug # pyflakes:ignore @@ -72,7 +73,9 @@ debug.debug = True import ietf import ietf.utils.mail from ietf.checks import maybe_create_svn_symlinks +from ietf.utils.management.commands import pyflakes from ietf.utils.test_smtpserver import SMTPTestServerDriver +from ietf.utils.test_utils import TestCase loaded_templates = set() @@ -121,6 +124,19 @@ def safe_destroy_test_db(*args, **kwargs): settings.DATABASES["default"]["NAME"] = test_database_name return old_destroy(*args, **kwargs) +class PyFlakesTestCase(TestCase): + + def __init__(self, test_runner=None, **kwargs): + self.runner = test_runner + super(PyFlakesTestCase, self).__init__(**kwargs) + + def pyflakes_test(self): + self.maxDiff = None + path = os.path.join(settings.BASE_DIR) + warnings = [] + warnings = pyflakes.checkPaths([path], verbosity=0) + self.assertEqual([], [str(w) for w in warnings]) + class TemplateCoverageLoader(BaseLoader): is_usable = True @@ -375,6 +391,8 @@ class CoverageTest(unittest.TestCase): self.skipTest("Coverage switched off with --skip-coverage") def interleaved_migrations_test(self): + if self.runner.permit_mixed_migrations: + return # from django.apps import apps # unreleased = {} # for appconf in apps.get_app_configs(): @@ -474,12 +492,16 @@ class IetfTestRunner(DiscoverRunner): parser.add_argument('--html-report', action='store_true', default=False, help='Generate a html code coverage report in %s' % settings.TEST_CODE_COVERAGE_REPORT_DIR) + parser.add_argument('--permit-mixed-migrations', + action='store_true', default=False, + help='Permit interleaved unreleased migrations') - def __init__(self, skip_coverage=False, save_version_coverage=None, html_report=None, **kwargs): + def __init__(self, skip_coverage=False, save_version_coverage=None, html_report=None, permit_mixed_migrations=None, **kwargs): # self.check_coverage = not skip_coverage self.save_version_coverage = save_version_coverage self.html_report = html_report + self.permit_mixed_migrations = permit_mixed_migrations # self.root_dir = os.path.dirname(settings.BASE_DIR) self.coverage_file = os.path.join(self.root_dir, settings.TEST_COVERAGE_MASTER_FILE) @@ -668,6 +690,7 @@ class IetfTestRunner(DiscoverRunner): code_coverage_collection = True url_coverage_collection = True extra_tests += [ + PyFlakesTestCase(test_runner=self, methodName='pyflakes_test'), CoverageTest(test_runner=self, methodName='interleaved_migrations_test'), CoverageTest(test_runner=self, methodName='url_coverage_test'), CoverageTest(test_runner=self, methodName='template_coverage_test'), @@ -679,7 +702,7 @@ class IetfTestRunner(DiscoverRunner): # parent classes to later subclasses, the parent classes will # determine the ordering, so use the most specific classes # necessary to get the right ordering: - self.reorder_by += (StaticLiveServerTestCase, TemplateTagTest, CoverageTest, ) + self.reorder_by = (PyFlakesTestCase, ) + self.reorder_by + (StaticLiveServerTestCase, TemplateTagTest, CoverageTest, ) failures = super(IetfTestRunner, self).run_tests(test_labels, extra_tests=extra_tests, **kwargs) diff --git a/ietf/utils/tests.py b/ietf/utils/tests.py index ee318c30f..8be182604 100644 --- a/ietf/utils/tests.py +++ b/ietf/utils/tests.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2014-2018, All Rights Reserved +# Copyright The IETF Trust 2014-2019, All Rights Reserved # -*- coding: utf-8 -*- from __future__ import unicode_literals, print_function @@ -37,7 +37,6 @@ from ietf.utils.bower_storage import BowerStorageFinder from ietf.utils.draft import Draft, getmeta from ietf.utils.log import unreachable, assertion from ietf.utils.mail import send_mail_preformatted, send_mail_text, send_mail_mime, outbox -from ietf.utils.management.commands import pyflakes from ietf.utils.test_runner import get_template_paths, set_coverage_checking from ietf.utils.test_utils import TestCase @@ -51,15 +50,6 @@ except ImportError as e: skip_message = "Skipping trac tests: %s" % e sys.stderr.write(" "+skip_message+'\n') -class PyFlakesTestCase(TestCase): - - def test_pyflakes(self): - self.maxDiff = None - path = os.path.join(settings.BASE_DIR) - warnings = [] - warnings = pyflakes.checkPaths([path], verbosity=0) - self.assertEqual([], [str(w) for w in warnings]) - class SendingMail(TestCase): def test_send_mail_preformatted(self): diff --git a/release-coverage.json.gz b/release-coverage.json.gz index 41103fe2f..49af61deb 100644 Binary files a/release-coverage.json.gz and b/release-coverage.json.gz differ