Skip to content

Commit a2cafde

Browse files
committed
Changed DocAlias to be many-to-many, in order to be able to handle STD aliases referring to multiple RFCs.
- Legacy-Id: 16249
1 parent 8156023 commit a2cafde

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+228
-203
lines changed

bin/add-old-drafts-from-archive.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@
7979
words=draft.get_wordcount(),
8080
expires=time+datetime.timedelta(settings.INTERNET_DRAFT_DAYS_TO_EXPIRE),
8181
)
82-
doc.docalias_set.create(name=doc.name)
82+
DocAlias.objects.create(name=doc.name).docs.add(doc)
8383
doc.states.add(expired)
8484
# update authors
8585
authors = []

ietf/doc/admin.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ class StateAdmin(admin.ModelAdmin):
1919
filter_horizontal = ["next_states"]
2020
admin.site.register(State, StateAdmin)
2121

22-
class DocAliasInline(admin.TabularInline):
23-
model = DocAlias
24-
extra = 1
22+
# class DocAliasInline(admin.TabularInline):
23+
# model = DocAlias
24+
# extra = 1
2525

2626
class DocAuthorInline(admin.TabularInline):
2727
model = DocumentAuthor
@@ -58,7 +58,7 @@ class DocumentAdmin(admin.ModelAdmin):
5858
search_fields = ['name']
5959
list_filter = ['type']
6060
raw_id_fields = ['group', 'shepherd', 'ad']
61-
inlines = [DocAliasInline, DocAuthorInline, RelatedDocumentInline, ]
61+
inlines = [DocAuthorInline, RelatedDocumentInline, ]
6262
form = DocumentForm
6363

6464
def save_model(self, request, obj, form, change):
@@ -88,9 +88,9 @@ def state(self, instance):
8888
admin.site.register(DocHistory, DocHistoryAdmin)
8989

9090
class DocAliasAdmin(admin.ModelAdmin):
91-
list_display = ['name', 'document_link']
92-
search_fields = ['name', 'document__name']
93-
raw_id_fields = ['document']
91+
# list_display = ['name', 'document_link']
92+
# search_fields = ['name', 'document__name']
93+
raw_id_fields = ['docs']
9494
admin.site.register(DocAlias, DocAliasAdmin)
9595

9696
class DocReminderAdmin(admin.ModelAdmin):
@@ -102,7 +102,7 @@ class DocReminderAdmin(admin.ModelAdmin):
102102
class RelatedDocumentAdmin(admin.ModelAdmin):
103103
list_display = ['source', 'target', 'relationship', ]
104104
list_filter = ['relationship', ]
105-
search_fields = ['source__name', 'target__name', 'target__document__name', ]
105+
search_fields = ['source__name', 'target__name', 'target__docs__name', ]
106106
raw_id_fields = ['source', 'target', ]
107107
admin.site.register(RelatedDocument, RelatedDocumentAdmin)
108108

ietf/doc/factories.py

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,14 @@ def name(self, n):
3333

3434
newrevisiondocevent = factory.RelatedFactory('ietf.doc.factories.NewRevisionDocEventFactory','doc')
3535

36-
alias = factory.RelatedFactory('ietf.doc.factories.DocAliasFactory','document')
37-
3836
@factory.post_generation
3937
def other_aliases(obj, create, extracted, **kwargs): # pylint: disable=no-self-argument
38+
alias = DocAliasFactory(name=obj.name)
39+
alias.docs.add(obj)
4040
if create and extracted:
41-
for alias in extracted:
42-
obj.docalias_set.create(name=alias)
41+
for name in extracted:
42+
alias = DocAliasFactory(name=name)
43+
alias.docs.add(obj)
4344

4445
@factory.post_generation
4546
def states(obj, create, extracted, **kwargs): # pylint: disable=no-self-argument
@@ -61,10 +62,14 @@ def authors(obj, create, extracted, **kwargs): # pylint: disable=no-self-argumen
6162
@factory.post_generation
6263
def relations(obj, create, extracted, **kwargs): # pylint: disable=no-self-argument
6364
if create and extracted:
64-
for (rel_id,docalias) in extracted:
65-
if isinstance(docalias,Document):
66-
docalias = docalias.docalias_set.first()
67-
obj.relateddocument_set.create(relationship_id=rel_id,target=docalias)
65+
for (rel_id, doc) in extracted:
66+
if isinstance(doc, Document):
67+
docalias = doc.docalias.first()
68+
elif isinstance(doc, DocAlias):
69+
docalias = doc
70+
else:
71+
continue
72+
obj.relateddocument_set.create(relationship_id=rel_id, target=docalias)
6873

6974
@classmethod
7075
def _after_postgeneration(cls, obj, create, results=None):
@@ -195,9 +200,9 @@ def review_of(obj, create, extracted, **kwargs):
195200
if not create:
196201
return
197202
if extracted:
198-
obj.relateddocument_set.create(relationship_id='conflrev',target=extracted.docalias_set.first())
203+
obj.relateddocument_set.create(relationship_id='conflrev',target=extracted.docalias.first())
199204
else:
200-
obj.relateddocument_set.create(relationship_id='conflrev',target=DocumentFactory(type_id='draft',group=Group.objects.get(type_id='individ')).docalias_set.first())
205+
obj.relateddocument_set.create(relationship_id='conflrev',target=DocumentFactory(type_id='draft',group=Group.objects.get(type_id='individ')).docalias.first())
201206

202207
@factory.post_generation
203208
def states(obj, create, extracted, **kwargs):
@@ -219,12 +224,19 @@ class DocAliasFactory(factory.DjangoModelFactory):
219224
class Meta:
220225
model = DocAlias
221226

222-
document = factory.SubFactory('ietf.doc.factories.DocumentFactory')
227+
@factory.post_generation
228+
def document(self, create, extracted, **kwargs):
229+
if create and extracted:
230+
self.docs.add(extracted)
231+
self.name = extracted.name
232+
233+
@factory.post_generation
234+
def docs(self, create, extracted, **kwargs):
235+
if create and extracted:
236+
for doc in extracted:
237+
if not doc in self.docs.all():
238+
self.docs.add(doc)
223239

224-
@factory.lazy_attribute
225-
def name(self):
226-
return self.document.name
227-
228240

229241
class DocEventFactory(factory.DjangoModelFactory):
230242
class Meta:

ietf/doc/fields.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def prepare_value(self, value):
5959
value = self.model.objects.filter(Q(name__in=names)|Q(id__in=ids))
6060
filter_args = {}
6161
if self.model == DocAlias:
62-
filter_args["document__type"] = self.doc_type
62+
filter_args["docs__type"] = self.doc_type
6363
else:
6464
filter_args["type"] = self.doc_type
6565
value = value.filter(**filter_args)

ietf/doc/models.py

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ def friendly_state(self):
323323
elif state.slug == "repl":
324324
rs = self.related_that("replaces")
325325
if rs:
326-
return mark_safe("Replaced by " + ", ".join("<a href=\"%s\">%s</a>" % (urlreverse('ietf.doc.views_doc.document_main', kwargs=dict(name=alias.document)), alias.document) for alias in rs))
326+
return mark_safe("Replaced by " + ", ".join("<a href=\"%s\">%s</a>" % (urlreverse('ietf.doc.views_doc.document_main', kwargs=dict(name=alias.document.name)), alias.document) for alias in rs))
327327
else:
328328
return "Replaced"
329329
elif state.slug == "active":
@@ -411,9 +411,9 @@ def relations_that(self, relationship):
411411
if not isinstance(relationship, tuple):
412412
raise TypeError("Expected a string or tuple, received %s" % type(relationship))
413413
if isinstance(self, Document):
414-
return RelatedDocument.objects.filter(target__document=self, relationship__in=relationship).select_related('source')
414+
return RelatedDocument.objects.filter(target__docs=self, relationship__in=relationship).select_related('source')
415415
elif isinstance(self, DocHistory):
416-
return RelatedDocHistory.objects.filter(target__document=self.doc, relationship__in=relationship).select_related('source')
416+
return RelatedDocHistory.objects.filter(target__docs=self.doc, relationship__in=relationship).select_related('source')
417417
else:
418418
raise TypeError("Expected method called on Document or DocHistory")
419419

@@ -434,9 +434,9 @@ def relations_that_doc(self, relationship):
434434
if not isinstance(relationship, tuple):
435435
raise TypeError("Expected a string or tuple, received %s" % type(relationship))
436436
if isinstance(self, Document):
437-
return RelatedDocument.objects.filter(source=self, relationship__in=relationship).select_related('target__document')
437+
return RelatedDocument.objects.filter(source=self, relationship__in=relationship).select_related('target')
438438
elif isinstance(self, DocHistory):
439-
return RelatedDocHistory.objects.filter(source=self, relationship__in=relationship).select_related('target__document')
439+
return RelatedDocHistory.objects.filter(source=self, relationship__in=relationship).select_related('target')
440440
else:
441441
raise TypeError("Expected method called on Document or DocHistory")
442442

@@ -447,14 +447,15 @@ def all_relations_that_doc(self, relationship, related=None):
447447
for r in rels:
448448
if not r in related:
449449
related += ( r, )
450-
related = r.target.document.all_relations_that_doc(relationship, related)
450+
for doc in r.target.docs.all():
451+
related = doc.all_relations_that_doc(relationship, related)
451452
return related
452453

453454
def related_that(self, relationship):
454-
return list(set([x.source.docalias_set.get(name=x.source.name) for x in self.relations_that(relationship)]))
455+
return list(set([x.source.docalias.get(name=x.source.name) for x in self.relations_that(relationship)]))
455456

456457
def all_related_that(self, relationship, related=None):
457-
return list(set([x.source.docalias_set.get(name=x.source.name) for x in self.all_relations_that(relationship)]))
458+
return list(set([x.source.docalias.get(name=x.source.name) for x in self.all_relations_that(relationship)]))
458459

459460
def related_that_doc(self, relationship):
460461
return list(set([x.target for x in self.relations_that_doc(relationship)]))
@@ -463,7 +464,7 @@ def all_related_that_doc(self, relationship, related=None):
463464
return list(set([x.target for x in self.all_relations_that_doc(relationship)]))
464465

465466
def replaces(self):
466-
return set([ r.document for r in self.related_that_doc("replaces")])
467+
return set([ d for r in self.related_that_doc("replaces") for d in r.docs.all() ])
467468

468469
def replaces_canonical_name(self):
469470
s = set([ r.document for r in self.related_that_doc("replaces")])
@@ -657,7 +658,7 @@ def canonical_name(self):
657658
if not hasattr(self, '_canonical_name'):
658659
name = self.name
659660
if self.type_id == "draft" and self.get_state_slug() == "rfc":
660-
a = self.docalias_set.filter(name__startswith="rfc").order_by('-name').first()
661+
a = self.docalias.filter(name__startswith="rfc").order_by('-name').first()
661662
if a:
662663
name = a.name
663664
elif self.type_id == "charter":
@@ -671,7 +672,7 @@ def canonical_name(self):
671672

672673

673674
def canonical_docalias(self):
674-
return self.docalias_set.get(name=self.name)
675+
return self.docalias.get(name=self.name)
675676

676677
def display_name(self):
677678
name = self.canonical_name()
@@ -766,14 +767,14 @@ def displayname_with_link(self):
766767
def ipr(self,states=('posted','removed')):
767768
"""Returns the IPR disclosures against this document (as a queryset over IprDocRel)."""
768769
from ietf.ipr.models import IprDocRel
769-
return IprDocRel.objects.filter(document__document=self,disclosure__state__in=states)
770+
return IprDocRel.objects.filter(document__docs=self, disclosure__state__in=states)
770771

771772
def related_ipr(self):
772773
"""Returns the IPR disclosures against this document and those documents this
773774
document directly or indirectly obsoletes or replaces
774775
"""
775776
from ietf.ipr.models import IprDocRel
776-
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()
777+
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()
777778
return iprs
778779

779780
def future_presentations(self):
@@ -889,8 +890,9 @@ def groupmilestone_set(self):
889890
return self.doc.groupmilestone_set
890891

891892
@property
892-
def docalias_set(self):
893-
return self.doc.docalias_set
893+
def docalias(self):
894+
log.unreachable('2019-06-11')
895+
return self.doc.docalias
894896

895897
def is_dochistory(self):
896898
return True
@@ -909,11 +911,14 @@ class DocAlias(models.Model):
909911
to by RFC number, primarily, after achieving RFC status.
910912
"""
911913
name = models.CharField(max_length=255, unique=True)
912-
document = ForeignKey(Document)
913-
# docs = models.ManyToManyField(Document, related_name='aliases')
914+
docs = models.ManyToManyField(Document, related_name='docalias')
915+
916+
@property
917+
def document(self):
918+
return self.docs.first()
914919

915920
def __unicode__(self):
916-
return "%s-->%s" % (self.name, self.document.name)
921+
return "%s-->%s" % (self.name, ','.join([unicode(d.name) for d in self.docs.all() if isinstance(d, Document) ]))
917922
document_link = admin_link("document")
918923
class Meta:
919924
verbose_name = "document alias"

ietf/doc/tests.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ def test_docs_for_ad(self):
216216
draft.set_state(State.objects.get(type='draft-iesg', slug='lc'))
217217
rfc = IndividualDraftFactory(ad=ad)
218218
rfc.set_state(State.objects.get(type='draft', slug='rfc'))
219-
rfc.docalias_set.create(name='rfc6666')
219+
DocAlias.objects.create(name='rfc6666').docs.add(rfc)
220220
conflrev = DocumentFactory(type_id='conflrev',ad=ad)
221221
conflrev.set_state(State.objects.get(type='conflrev', slug='iesgeval'))
222222
statchg = DocumentFactory(type_id='statchg',ad=ad)
@@ -278,7 +278,7 @@ def test_ajax_search_docs(self):
278278
self.assertEqual(data[0]["id"], draft.pk)
279279

280280
# DocAlias
281-
doc_alias = draft.docalias_set.get()
281+
doc_alias = draft.docalias.first()
282282

283283
url = urlreverse('ietf.doc.views_search.ajax_select2_search_docs', kwargs={
284284
"model_name": "docalias",
@@ -499,7 +499,7 @@ def test_document_draft(self):
499499
draft = WgDraftFactory(name='draft-ietf-mars-test',rev='01')
500500
HolderIprDisclosureFactory(docs=[draft])
501501
replaced = IndividualDraftFactory()
502-
draft.relateddocument_set.create(relationship_id='replaces',source=draft,target=replaced.docalias_set.first())
502+
draft.relateddocument_set.create(relationship_id='replaces',source=draft,target=replaced.docalias.first())
503503

504504
# these tests aren't testing all attributes yet, feel free to
505505
# expand them
@@ -580,7 +580,7 @@ def test_document_draft(self):
580580
shepherd_id=draft.shepherd_id, ad_id=draft.ad_id, expires=draft.expires,
581581
notify=draft.notify, note=draft.note)
582582
rel = RelatedDocument.objects.create(source=replacement,
583-
target=draft.docalias_set.get(name__startswith="draft"),
583+
target=draft.docalias.get(name__startswith="draft"),
584584
relationship_id="replaces")
585585

586586
r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name)))
@@ -595,8 +595,10 @@ def test_document_draft(self):
595595
draft.save_with_history([DocEvent.objects.create(doc=draft, rev=draft.rev, type="published_rfc", by=Person.objects.get(name="(System)"))])
596596

597597

598-
rfc_alias = DocAlias.objects.create(name="rfc123456", document=draft)
599-
bcp_alias = DocAlias.objects.create(name="bcp123456", document=draft)
598+
rfc_alias = DocAlias.objects.create(name="rfc123456")
599+
rfc_alias.docs.add(draft)
600+
bcp_alias = DocAlias.objects.create(name="bcp123456")
601+
bcp_alias.docs.add(draft)
600602

601603
r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name)))
602604
self.assertEqual(r.status_code, 302)
@@ -759,8 +761,8 @@ def test_document_ballot_needed_positions(self):
759761
self.assertFalse('more YES or NO' in unicontent(r))
760762

761763
# status change
762-
IndividualDraftFactory().docalias_set.create(name='rfc9998')
763-
IndividualDraftFactory().docalias_set.create(name='rfc9999')
764+
DocAlias.objects.create(name='rfc9998').docs.add(IndividualDraftFactory())
765+
DocAlias.objects.create(name='rfc9999').docs.add(IndividualDraftFactory())
764766
doc = DocumentFactory(type_id='statchg',name='status-change-imaginary-mid-review')
765767
iesgeval_pk = str(State.objects.get(slug='iesgeval',type__slug='statchg').pk)
766768
self.client.login(username='ad', password='ad+password')
@@ -1003,7 +1005,7 @@ class ReferencesTest(TestCase):
10031005

10041006
def test_references(self):
10051007
doc1 = WgDraftFactory(name='draft-ietf-mars-test')
1006-
doc2 = IndividualDraftFactory(name='draft-imaginary-independent-submission').docalias_set.first()
1008+
doc2 = IndividualDraftFactory(name='draft-imaginary-independent-submission').docalias.first()
10071009
RelatedDocument.objects.get_or_create(source=doc1,target=doc2,relationship=DocRelationshipName.objects.get(slug='refnorm'))
10081010
url = urlreverse('ietf.doc.views_doc.document_references', kwargs=dict(name=doc1.name))
10091011
r = self.client.get(url)

ietf/doc/tests_ballot.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,7 @@ def test_ballot_downref_approve(self):
741741
self.assertTrue("No downward references for" in r.content)
742742

743743
# Add a downref, the page should ask if it should be added to the registry
744-
rel = draft.relateddocument_set.create(target=rfc.docalias_set.get(name='rfc6666'),relationship_id='refnorm')
744+
rel = draft.relateddocument_set.create(target=rfc.docalias.get(name='rfc6666'),relationship_id='refnorm')
745745
d = [rdoc for rdoc in draft.relateddocument_set.all() if rel.is_approved_downref()]
746746
original_len = len(d)
747747
r = self.client.get(url)
@@ -970,7 +970,7 @@ def test_regenerate_last_call(self):
970970
std_level_id='inf',
971971
)
972972

973-
draft.relateddocument_set.create(target=rfc.docalias_set.get(name='rfc6666'),relationship_id='refnorm')
973+
draft.relateddocument_set.create(target=rfc.docalias.get(name='rfc6666'),relationship_id='refnorm')
974974

975975
r = self.client.post(url, dict(regenerate_last_call_text="1"))
976976
self.assertEqual(r.status_code, 200)
@@ -980,7 +980,7 @@ def test_regenerate_last_call(self):
980980
self.assertTrue("rfc6666" in lc_text)
981981
self.assertTrue("Independent Submission Editor stream" in lc_text)
982982

983-
draft.relateddocument_set.create(target=rfc.docalias_set.get(name='rfc6666'),relationship_id='downref-approval')
983+
draft.relateddocument_set.create(target=rfc.docalias.get(name='rfc6666'),relationship_id='downref-approval')
984984

985985
r = self.client.post(url, dict(regenerate_last_call_text="1"))
986986
self.assertEqual(r.status_code, 200)

0 commit comments

Comments
 (0)