Merge pull request #5941 from rjsparks/fixups4

fix: various fixes in ietf.doc
This commit is contained in:
Jennifer Richards 2023-07-07 17:55:04 -03:00 committed by GitHub
commit 1bec64fa10
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 243 additions and 156 deletions

View file

@ -24,6 +24,7 @@ from ietf.doc.models import Document
from ietf.group.utils import get_group_role_emails, get_group_ad_emails
from ietf.utils.aliases import dump_sublist
from utils.mail import parseaddr
from ietf.utils import log
DEFAULT_YEARS = 2
@ -120,16 +121,19 @@ class Command(BaseCommand):
vfile.write("%s anything\n" % settings.DRAFT_VIRTUAL_DOMAIN)
# Internet-Drafts with active status or expired within DEFAULT_YEARS
drafts = Document.objects.filter(name__startswith='draft-')
drafts = Document.objects.filter(type_id="draft")
active_drafts = drafts.filter(states__slug='active')
inactive_recent_drafts = drafts.exclude(states__slug='active').filter(expires__gte=show_since)
interesting_drafts = active_drafts | inactive_recent_drafts
alias_domains = ['ietf.org', ]
for draft in interesting_drafts.distinct().iterator():
# Omit RFCs, unless they were published in the last DEFAULT_YEARS
if draft.docalias.filter(name__startswith='rfc'):
if draft.latest_event(type='published_rfc').time < show_since:
# Omit drafts that became RFCs, unless they were published in the last DEFAULT_YEARS
if draft.get_state_slug()=="rfc":
rfc_alias = next(iter(draft.related_that_doc("became_rfc")), None)
log.assertion("rfc_alias is not None")
rfc = rfc_alias.document
if rfc.latest_event(type='published_rfc').time < show_since:
continue
alias = draft.name

View file

@ -172,7 +172,7 @@ class DocumentInfo(models.Model):
if not hasattr(self, '_cached_base_name'):
if self.uploaded_filename:
self._cached_base_name = self.uploaded_filename
if self.type_id == 'rfc':
elif self.type_id == 'rfc':
self._cached_base_name = "%s.txt" % self.canonical_name()
elif self.type_id == 'draft':
if self.is_dochistory():

View file

@ -1421,6 +1421,8 @@ Man Expires September 22, 2015 [Page 3]
self.assert_correct_wg_group_link(r, group)
rfc = WgRfcFactory(group=group)
draft = WgDraftFactory(group=group)
draft.relateddocument_set.create(relationship_id="became_rfc", target=rfc.docalias.first())
DocEventFactory.create(doc=rfc, type='published_rfc', time=event_datetime)
r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=rfc.name)))
self.assertEqual(r.status_code, 200)
@ -1433,7 +1435,9 @@ Man Expires September 22, 2015 [Page 3]
self.assertEqual(r.status_code, 200)
self.assert_correct_non_wg_group_link(r, group)
rfc = WgRfcFactory(name='draft-rfc-document-%s' % group_type_id, group=group)
rfc = WgRfcFactory(group=group)
draft = WgDraftFactory(name='draft-rfc-document-%s'% group_type_id, group=group)
draft.relateddocument_set.create(relationship_id="became_rfc", target=rfc.docalias.first())
DocEventFactory.create(doc=rfc, type='published_rfc', time=event_datetime)
r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=rfc.name)))
self.assertEqual(r.status_code, 200)
@ -1536,8 +1540,8 @@ class DocTestCase(TestCase):
statchg = StatusChangeFactory()
r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=statchg.name)))
self.assertEqual(r.status_code, 200)
r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=statchg.relateddocument_set.first().target.document)))
self.assertEqual(r.status_code, 200) # What was this even trying to prove?
r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=statchg.relateddocument_set.first().target.document.name)))
self.assertEqual(r.status_code, 200)
def test_document_charter(self):
CharterFactory(name='charter-ietf-mars')
@ -2045,124 +2049,168 @@ class ReferencesTest(TestCase):
self.assertContains(r, doc1.name)
class GenerateDraftAliasesTests(TestCase):
def setUp(self):
super().setUp()
self.doc_aliases_file = NamedTemporaryFile(delete=False, mode='w+')
self.doc_aliases_file.close()
self.doc_virtual_file = NamedTemporaryFile(delete=False, mode='w+')
self.doc_virtual_file.close()
self.saved_draft_aliases_path = settings.DRAFT_ALIASES_PATH
self.saved_draft_virtual_path = settings.DRAFT_VIRTUAL_PATH
settings.DRAFT_ALIASES_PATH = self.doc_aliases_file.name
settings.DRAFT_VIRTUAL_PATH = self.doc_virtual_file.name
def setUp(self):
super().setUp()
self.doc_aliases_file = NamedTemporaryFile(delete=False, mode="w+")
self.doc_aliases_file.close()
self.doc_virtual_file = NamedTemporaryFile(delete=False, mode="w+")
self.doc_virtual_file.close()
self.saved_draft_aliases_path = settings.DRAFT_ALIASES_PATH
self.saved_draft_virtual_path = settings.DRAFT_VIRTUAL_PATH
settings.DRAFT_ALIASES_PATH = self.doc_aliases_file.name
settings.DRAFT_VIRTUAL_PATH = self.doc_virtual_file.name
def tearDown(self):
settings.DRAFT_ALIASES_PATH = self.saved_draft_aliases_path
settings.DRAFT_VIRTUAL_PATH = self.saved_draft_virtual_path
os.unlink(self.doc_aliases_file.name)
os.unlink(self.doc_virtual_file.name)
super().tearDown()
def tearDown(self):
settings.DRAFT_ALIASES_PATH = self.saved_draft_aliases_path
settings.DRAFT_VIRTUAL_PATH = self.saved_draft_virtual_path
os.unlink(self.doc_aliases_file.name)
os.unlink(self.doc_virtual_file.name)
super().tearDown()
def testManagementCommand(self):
a_month_ago = (timezone.now() - datetime.timedelta(30)).astimezone(RPC_TZINFO)
a_month_ago = a_month_ago.replace(hour=0, minute=0, second=0, microsecond=0)
ad = RoleFactory(name_id='ad', group__type_id='area', group__state_id='active').person
shepherd = PersonFactory()
author1 = PersonFactory()
author2 = PersonFactory()
author3 = PersonFactory()
author4 = PersonFactory()
author5 = PersonFactory()
author6 = PersonFactory()
mars = GroupFactory(type_id='wg', acronym='mars')
marschairman = PersonFactory(user__username='marschairman')
mars.role_set.create(name_id='chair', person=marschairman, email=marschairman.email())
doc1 = IndividualDraftFactory(authors=[author1], shepherd=shepherd.email(), ad=ad)
doc2 = WgDraftFactory(name='draft-ietf-mars-test', group__acronym='mars', authors=[author2], ad=ad)
doc3 = WgRfcFactory.create(name='draft-ietf-mars-finished', group__acronym='mars', authors=[author3], ad=ad, std_level_id='ps', states=[('draft','rfc'),('draft-iesg','pub')], time=a_month_ago)
DocEventFactory.create(doc=doc3, type='published_rfc', time=a_month_ago)
doc4 = WgRfcFactory.create(authors=[author4,author5], ad=ad, std_level_id='ps', states=[('draft','rfc'),('draft-iesg','pub')], time=datetime.datetime(2010,10,10, tzinfo=ZoneInfo(settings.TIME_ZONE)))
DocEventFactory.create(doc=doc4, type='published_rfc', time=datetime.datetime(2010, 10, 10, tzinfo=RPC_TZINFO))
doc5 = IndividualDraftFactory(authors=[author6])
def testManagementCommand(self):
a_month_ago = (timezone.now() - datetime.timedelta(30)).astimezone(RPC_TZINFO)
a_month_ago = a_month_ago.replace(hour=0, minute=0, second=0, microsecond=0)
ad = RoleFactory(
name_id="ad", group__type_id="area", group__state_id="active"
).person
shepherd = PersonFactory()
author1 = PersonFactory()
author2 = PersonFactory()
author3 = PersonFactory()
author4 = PersonFactory()
author5 = PersonFactory()
author6 = PersonFactory()
mars = GroupFactory(type_id="wg", acronym="mars")
marschairman = PersonFactory(user__username="marschairman")
mars.role_set.create(
name_id="chair", person=marschairman, email=marschairman.email()
)
doc1 = IndividualDraftFactory(
authors=[author1], shepherd=shepherd.email(), ad=ad
)
doc2 = WgDraftFactory(
name="draft-ietf-mars-test", group__acronym="mars", authors=[author2], ad=ad
)
doc3 = WgDraftFactory.create(
name="draft-ietf-mars-finished",
group__acronym="mars",
authors=[author3],
ad=ad,
std_level_id="ps",
states=[("draft", "rfc"), ("draft-iesg", "pub")],
time=a_month_ago,
)
rfc3 = WgRfcFactory()
DocEventFactory.create(doc=rfc3, type="published_rfc", time=a_month_ago)
doc3.relateddocument_set.create(
relationship_id="became_rfc", target=rfc3.docalias.first()
)
doc4 = WgDraftFactory.create(
authors=[author4, author5],
ad=ad,
std_level_id="ps",
states=[("draft", "rfc"), ("draft-iesg", "pub")],
time=datetime.datetime(2010, 10, 10, tzinfo=ZoneInfo(settings.TIME_ZONE)),
)
rfc4 = WgRfcFactory()
DocEventFactory.create(
doc=rfc4,
type="published_rfc",
time=datetime.datetime(2010, 10, 10, tzinfo=RPC_TZINFO),
)
doc4.relateddocument_set.create(
relationship_id="became_rfc", target=rfc4.docalias.first()
)
doc5 = IndividualDraftFactory(authors=[author6])
args = [ ]
kwargs = { }
out = io.StringIO()
call_command("generate_draft_aliases", *args, **kwargs, stdout=out, stderr=out)
self.assertFalse(out.getvalue())
args = []
kwargs = {}
out = io.StringIO()
call_command("generate_draft_aliases", *args, **kwargs, stdout=out, stderr=out)
self.assertFalse(out.getvalue())
with open(settings.DRAFT_ALIASES_PATH) as afile:
acontent = afile.read()
self.assertTrue(all([x in acontent for x in [
'xfilter-' + doc1.name,
'xfilter-' + doc1.name + '.ad',
'xfilter-' + doc1.name + '.authors',
'xfilter-' + doc1.name + '.shepherd',
'xfilter-' + doc1.name + '.all',
'xfilter-' + doc2.name,
'xfilter-' + doc2.name + '.ad',
'xfilter-' + doc2.name + '.authors',
'xfilter-' + doc2.name + '.chairs',
'xfilter-' + doc2.name + '.all',
'xfilter-' + doc3.name,
'xfilter-' + doc3.name + '.ad',
'xfilter-' + doc3.name + '.authors',
'xfilter-' + doc3.name + '.chairs',
'xfilter-' + doc5.name,
'xfilter-' + doc5.name + '.authors',
'xfilter-' + doc5.name + '.all',
]]))
self.assertFalse(all([x in acontent for x in [
'xfilter-' + doc1.name + '.chairs',
'xfilter-' + doc2.name + '.shepherd',
'xfilter-' + doc3.name + '.shepherd',
'xfilter-' + doc4.name,
'xfilter-' + doc5.name + '.shepherd',
'xfilter-' + doc5.name + '.ad',
]]))
with open(settings.DRAFT_ALIASES_PATH) as afile:
acontent = afile.read()
for x in [
"xfilter-" + doc1.name,
"xfilter-" + doc1.name + ".ad",
"xfilter-" + doc1.name + ".authors",
"xfilter-" + doc1.name + ".shepherd",
"xfilter-" + doc1.name + ".all",
"xfilter-" + doc2.name,
"xfilter-" + doc2.name + ".ad",
"xfilter-" + doc2.name + ".authors",
"xfilter-" + doc2.name + ".chairs",
"xfilter-" + doc2.name + ".all",
"xfilter-" + doc3.name,
"xfilter-" + doc3.name + ".ad",
"xfilter-" + doc3.name + ".authors",
"xfilter-" + doc3.name + ".chairs",
"xfilter-" + doc5.name,
"xfilter-" + doc5.name + ".authors",
"xfilter-" + doc5.name + ".all",
]:
self.assertIn(x, acontent)
with open(settings.DRAFT_VIRTUAL_PATH) as vfile:
vcontent = vfile.read()
self.assertTrue(all([x in vcontent for x in [
ad.email_address(),
shepherd.email_address(),
marschairman.email_address(),
author1.email_address(),
author2.email_address(),
author3.email_address(),
author6.email_address(),
]]))
self.assertFalse(all([x in vcontent for x in [
author4.email_address(),
author5.email_address(),
]]))
self.assertTrue(all([x in vcontent for x in [
'xfilter-' + doc1.name,
'xfilter-' + doc1.name + '.ad',
'xfilter-' + doc1.name + '.authors',
'xfilter-' + doc1.name + '.shepherd',
'xfilter-' + doc1.name + '.all',
'xfilter-' + doc2.name,
'xfilter-' + doc2.name + '.ad',
'xfilter-' + doc2.name + '.authors',
'xfilter-' + doc2.name + '.chairs',
'xfilter-' + doc2.name + '.all',
'xfilter-' + doc3.name,
'xfilter-' + doc3.name + '.ad',
'xfilter-' + doc3.name + '.authors',
'xfilter-' + doc3.name + '.chairs',
'xfilter-' + doc5.name,
'xfilter-' + doc5.name + '.authors',
'xfilter-' + doc5.name + '.all',
]]))
self.assertFalse(all([x in vcontent for x in [
'xfilter-' + doc1.name + '.chairs',
'xfilter-' + doc2.name + '.shepherd',
'xfilter-' + doc3.name + '.shepherd',
'xfilter-' + doc4.name,
'xfilter-' + doc5.name + '.shepherd',
'xfilter-' + doc5.name + '.ad',
]]))
for x in [
"xfilter-" + doc1.name + ".chairs",
"xfilter-" + doc2.name + ".shepherd",
"xfilter-" + doc3.name + ".shepherd",
"xfilter-" + doc4.name,
"xfilter-" + doc5.name + ".shepherd",
"xfilter-" + doc5.name + ".ad",
]:
self.assertNotIn(x, acontent)
with open(settings.DRAFT_VIRTUAL_PATH) as vfile:
vcontent = vfile.read()
for x in [
ad.email_address(),
shepherd.email_address(),
marschairman.email_address(),
author1.email_address(),
author2.email_address(),
author3.email_address(),
author6.email_address(),
]:
self.assertIn(x, vcontent)
for x in [
author4.email_address(),
author5.email_address(),
]:
self.assertNotIn(x, vcontent)
for x in [
"xfilter-" + doc1.name,
"xfilter-" + doc1.name + ".ad",
"xfilter-" + doc1.name + ".authors",
"xfilter-" + doc1.name + ".shepherd",
"xfilter-" + doc1.name + ".all",
"xfilter-" + doc2.name,
"xfilter-" + doc2.name + ".ad",
"xfilter-" + doc2.name + ".authors",
"xfilter-" + doc2.name + ".chairs",
"xfilter-" + doc2.name + ".all",
"xfilter-" + doc3.name,
"xfilter-" + doc3.name + ".ad",
"xfilter-" + doc3.name + ".authors",
"xfilter-" + doc3.name + ".chairs",
"xfilter-" + doc5.name,
"xfilter-" + doc5.name + ".authors",
"xfilter-" + doc5.name + ".all",
]:
self.assertIn(x, vcontent)
for x in [
"xfilter-" + doc1.name + ".chairs",
"xfilter-" + doc2.name + ".shepherd",
"xfilter-" + doc3.name + ".shepherd",
"xfilter-" + doc4.name,
"xfilter-" + doc5.name + ".shepherd",
"xfilter-" + doc5.name + ".ad",
]:
self.assertNotIn(x, vcontent)
class EmailAliasesTests(TestCase):
@ -2595,10 +2643,10 @@ class Idnits2SupportTests(TestCase):
settings_temp_path_overrides = TestCase.settings_temp_path_overrides + ['DERIVED_DIR']
def test_obsoleted(self):
rfc = WgRfcFactory(alias2__name='rfc1001')
WgRfcFactory(alias2__name='rfc1003',relations=[('obs',rfc)])
rfc = WgRfcFactory(alias2__name='rfc1005')
WgRfcFactory(alias2__name='rfc1007',relations=[('obs',rfc)])
rfc = WgRfcFactory(rfc_number=1001)
WgRfcFactory(rfc_number=1003,relations=[('obs',rfc)])
rfc = WgRfcFactory(rfc_number=1005)
WgRfcFactory(rfc_number=1007,relations=[('obs',rfc)])
url = urlreverse('ietf.doc.views_doc.idnits2_rfcs_obsoleted')
r = self.client.get(url)
@ -2623,6 +2671,8 @@ class Idnits2SupportTests(TestCase):
def test_idnits2_state(self):
rfc = WgRfcFactory()
draft = WgDraftFactory()
draft.relateddocument_set.create(relationship_id="became_rfc", target=rfc.docalias.first())
url = urlreverse('ietf.doc.views_doc.idnits2_state', kwargs=dict(name=rfc.canonical_name()))
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
@ -2681,16 +2731,12 @@ class RawIdTests(TestCase):
self.should_succeed(dict(name=draft.name, rev='00',ext='txt'))
self.should_404(dict(name=draft.name, rev='00',ext='html'))
def test_raw_id_rfc(self):
rfc = WgRfcFactory()
dir = settings.INTERNET_ALL_DRAFTS_ARCHIVE_DIR
(Path(dir) / f'{rfc.name}-{rfc.rev}.txt').touch()
self.should_succeed(dict(name=rfc.name))
self.should_404(dict(name=rfc.canonical_name()))
# test_raw_id_rfc intentionally removed
# an rfc is no longer a pseudo-version of a draft.
def test_non_draft(self):
charter = CharterFactory()
self.should_404(dict(name=charter.name))
for doc in [CharterFactory(), WgRfcFactory()]:
self.should_404(dict(name=doc.name))
class PdfizedTests(TestCase):
@ -2709,24 +2755,27 @@ class PdfizedTests(TestCase):
r = self.client.get(url)
self.assertEqual(r.status_code, 404)
# This takes a _long_ time (32s on a 2022 m1 macbook pro) - is it worth what it covers?
def test_pdfized(self):
rfc = WgRfcFactory(create_revisions=range(0,2))
rfc = WgRfcFactory()
draft = WgDraftFactory(create_revisions=range(0,2))
draft.relateddocument_set.create(relationship_id="became_rfc", target=rfc.docalias.first())
dir = settings.RFC_PATH
with (Path(dir) / f'{rfc.canonical_name()}.txt').open('w') as f:
with (Path(dir) / f'{rfc.name}.txt').open('w') as f:
f.write('text content')
dir = settings.INTERNET_ALL_DRAFTS_ARCHIVE_DIR
for r in range(0,2):
with (Path(dir) / f'{rfc.name}-{r:02d}.txt').open('w') as f:
with (Path(dir) / f'{draft.name}-{r:02d}.txt').open('w') as f:
f.write('text content')
self.should_succeed(dict(name=rfc.canonical_name()))
self.should_succeed(dict(name=rfc.name))
self.should_succeed(dict(name=draft.name))
for r in range(0,2):
self.should_succeed(dict(name=rfc.name,rev=f'{r:02d}'))
self.should_succeed(dict(name=draft.name,rev=f'{r:02d}'))
for ext in ('pdf','txt','html','anythingatall'):
self.should_succeed(dict(name=rfc.name,rev=f'{r:02d}',ext=ext))
self.should_404(dict(name=rfc.name,rev='02'))
self.should_succeed(dict(name=draft.name,rev=f'{r:02d}',ext=ext))
self.should_404(dict(name=draft.name,rev='02'))
class NotifyValidationTests(TestCase):
def test_notify_validation(self):

View file

@ -1110,7 +1110,7 @@ def generate_idnits2_rfc_status():
'unkn': 'U',
}
rfcs = Document.objects.filter(type_id='rfc',states__slug='published',states__type='rfc')
rfcs = Document.objects.filter(type_id='rfc')
for rfc in rfcs:
offset = int(rfc.rfc_number)-1
blob[offset] = symbols[rfc.std_level_id]

View file

@ -2129,9 +2129,16 @@ def idnits2_rfc_status(request):
def idnits2_state(request, name, rev=None):
doc = get_object_or_404(Document, docalias__name=name)
if doc.type_id!='draft':
if doc.type_id not in ["draft", "rfc"]:
raise Http404
zero_revision = NewRevisionDocEvent.objects.filter(doc=doc,rev='00').first()
zero_revision = None
if doc.type_id == "rfc":
draft_alias = next(iter(doc.related_that('became_rfc')), None)
if draft_alias:
draft = draft_alias.document
zero_revision = NewRevisionDocEvent.objects.filter(doc=draft,rev='00').first()
else:
zero_revision = NewRevisionDocEvent.objects.filter(doc=doc,rev='00').first()
if zero_revision:
doc.created = zero_revision.time
else:

View file

@ -409,7 +409,7 @@ def shorten_group_name(name):
def ad_dashboard_sort_key(doc):
if doc.type.slug=='rfc' and doc.get_state_slug('rfc') == 'published':
if doc.type.slug=='rfc':
return "21%04d" % int(doc.rfc_number)
if doc.type.slug=='statchg' and doc.get_state_slug('statchg') == 'appr-sent':
return "22%d" % 0 # TODO - get the date of the transition into this state here
@ -805,21 +805,20 @@ def recent_drafts(request, days=7):
})
def index_all_drafts(request):
def index_all_drafts(request): # Should we rename this
# try to be efficient since this view returns a lot of data
categories = []
for s in ("active", "rfc", "expired", "repl", "auth-rm", "ietf-rm"):
# Gather drafts
for s in ("active", "expired", "repl", "auth-rm", "ietf-rm"):
state = State.objects.get(type="draft", slug=s)
if state.slug == "rfc":
heading = "RFCs"
elif state.slug in ("ietf-rm", "auth-rm"):
if state.slug in ("ietf-rm", "auth-rm"):
heading = "Internet-Drafts %s" % state.name
else:
heading = "%s Internet-Drafts" % state.name
draft_names = DocAlias.objects.filter(docs__states=state).values_list("name", "docs__name")
draft_names = DocAlias.objects.filter(docs__type_id="draft", docs__states=state).values_list("name", "docs__name")
names = []
names_to_skip = set()
@ -828,24 +827,52 @@ def index_all_drafts(request):
if name != doc:
if not name.startswith("rfc"):
name, doc = doc, name
names_to_skip.add(doc)
if name.startswith("rfc"):
name = name.upper()
sort_key = '%09d' % (100000000-int(name[3:]))
names_to_skip.add(doc) # this is filtering out subseries docaliases (which we will delete, so TODO clean this out after doing so)
names.append((name, sort_key))
names.sort(key=lambda t: t[1])
names = [f'<a href=\"{urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=n))}\">{n}</a>'
for n, __ in names if n not in names_to_skip]
for n, __ in names if n not in names_to_skip]
categories.append((state,
heading,
len(names),
"<br>".join(names)
))
# gather RFCs
rfc_names = DocAlias.objects.filter(docs__type_id="rfc").values_list("name", "docs__name")
names = []
names_to_skip = set()
for name, doc in rfc_names:
sort_key = name
if name != doc: # There are some std docalias that pointed to rfc names pre-migration.
if not name.startswith("rfc"):
name, doc = doc, name
names_to_skip.add(doc) # this is filtering out those std docaliases (which we will delete, so TODO clean this out after doing so)
name = name.upper()
sort_key = '%09d' % (100000000-int(name[3:]))
names.append((name, sort_key))
names.sort(key=lambda t: t[1])
names = [f'<a href=\"{urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=n))}\">{n}</a>'
for n, __ in names if n not in names_to_skip]
state = State.objects.get(type_id="rfc", slug="published")
categories.append((state,
"RFCs",
len(names),
"<br>".join(names)
))
# Return to the previous section ordering
categories = categories[0:1]+categories[5:]+categories[1:5]
return render(request, 'doc/index_all_drafts.html', { "categories": categories })
def index_active_drafts(request):