From 87bd9bbd6d4339d4ab210d9c18ac1f080a7ae273 Mon Sep 17 00:00:00 2001 From: Jennifer Richards Date: Thu, 10 Aug 2023 10:36:49 -0300 Subject: [PATCH] feat: Use rfc doc type when updating from rfc index --- ietf/sync/rfceditor.py | 181 +++++++++++++++++++++++------------------ 1 file changed, 103 insertions(+), 78 deletions(-) diff --git a/ietf/sync/rfceditor.py b/ietf/sync/rfceditor.py index 0e811c7318..101b333695 100644 --- a/ietf/sync/rfceditor.py +++ b/ietf/sync/rfceditor.py @@ -7,7 +7,7 @@ import re import requests -from typing import Iterator +from typing import Iterator, Optional from urllib.parse import urlencode from xml.dom import pulldom, Node @@ -388,7 +388,7 @@ def update_docs_from_rfc_index( obsoletes, obsoleted_by, also, - draft, + draft_name, has_errata, stream, wg, @@ -403,66 +403,101 @@ def update_docs_from_rfc_index( # we assume two things can happen: we get a new RFC, or an # attribute has been updated at the RFC Editor (RFC Editor # attributes take precedence over our local attributes) - events = [] - changes = [] + rfc_events = [] + rfc_changes = [] rfc_published = False + draft_events = [] + draft_changes = [] + + # Find the document + doc, created_rfc = Document.objects.get_or_create( + rfc_number=rfc_number, + type_id="rfc", + defaults={"name": f"rfc{rfc_number}"} + ) + if created_rfc: + rfc_changes.append(f"created document {prettify_std_name(doc.name)}") + # Create DocAlias (for consistency until we drop DocAlias altogether) + alias, _ = DocAlias.objects.get_or_create(name=doc.name) + alias.docs.add(doc) + rfc_changes.append("created alias %s" % prettify_std_name(doc.name)) - # make sure we got the document and alias - doc = None - name = "rfc%s" % rfc_number - a = DocAlias.objects.filter(name=name) - if a: - doc = a[0].document - else: - if draft: - try: - doc = Document.objects.get(name=draft) - except Document.DoesNotExist: - pass - - if not doc: - changes.append("created document %s" % prettify_std_name(name)) - doc = Document.objects.create( - name=name, type=DocTypeName.objects.get(slug="draft") - ) + if draft_name: + try: + draft = Document.objects.get(name=draft_name) + except Document.DoesNotExist: + pass + else: + # Ensure the draft is in the "rfc" state and move its files to the archive + # if necessary. + if draft.get_state_slug() != "rfc": + draft.set_state(State.objects.get(used=True, type="draft", slug="rfc")) + move_draft_files_to_archive(draft, draft.rev) + draft_changes.append( + f"changed state to {draft.get_state()}" + ) - # add alias - alias, __ = DocAlias.objects.get_or_create(name=name) - alias.docs.add(doc) - changes.append("created alias %s" % prettify_std_name(name)) + # Ensure the draft and rfc are linked with a "became_rfc" relationship + r, created_relateddoc = RelatedDocument.objects.get_or_create( + source=draft, target=doc, relationship_id="became_rfc" + ) + if created_relateddoc: + change = "created {rel_name} relationship between {pretty_draft_name} and {pretty_rfc_name}".format( + rel_name=r.relationship.name.lower(), + pretty_draft_name=prettify_std_name(draft), + pretty_rfc_name=prettify_std_name(doc), + ) + draft_changes.append(change) + rfc_changes.append(change) + + # Ensure draft is in the correct iesg and stream states + for t in ( + "draft-iesg", + "draft-stream-iab", + "draft-stream-irtf", + "draft-stream-ise", + ): + prev_state = draft.get_state(t) + if prev_state is not None: + if prev_state.slug not in ("pub", "idexists"): + new_state = State.objects.select_related("type").get( + used=True, type=t, slug="pub" + ) + draft.set_state(new_state) + draft_changes.append(f"changed {new_state.type.label} to {new_state}") + e = update_action_holders(draft, prev_state, new_state) + if e: + draft_events.append(e) + elif t == "draft-iesg": + draft.set_state(State.objects.get(type_id="draft-iesg", slug="idexists")) # check attributes if title != doc.title: doc.title = title - changes.append("changed title to '%s'" % doc.title) + rfc_changes.append("changed title to '%s'" % doc.title) if abstract and abstract != doc.abstract: doc.abstract = abstract - changes.append("changed abstract to '%s'" % doc.abstract) + rfc_changes.append("changed abstract to '%s'" % doc.abstract) if pages and int(pages) != doc.pages: doc.pages = int(pages) - changes.append("changed pages to %s" % doc.pages) + rfc_changes.append("changed pages to %s" % doc.pages) if std_level_mapping[current_status] != doc.std_level: doc.std_level = std_level_mapping[current_status] - changes.append("changed standardization level to %s" % doc.std_level) - - if doc.get_state_slug() != "rfc": - doc.set_state(State.objects.get(used=True, type="draft", slug="rfc")) - move_draft_files_to_archive(doc, doc.rev) - changes.append("changed state to %s" % doc.get_state()) + rfc_changes.append("changed standardization level to %s" % doc.std_level) if doc.stream != stream_mapping[stream]: doc.stream = stream_mapping[stream] - changes.append("changed stream to %s" % doc.stream) + rfc_changes.append("changed stream to %s" % doc.stream) if ( not doc.group ): # if we have no group assigned, check if RFC Editor has a suggestion if wg: doc.group = Group.objects.get(acronym=wg) - changes.append("set group to %s" % doc.group) + rfc_changes.append("set group to %s" % doc.group) else: doc.group = Group.objects.get( type="individ" @@ -493,35 +528,13 @@ def update_docs_from_rfc_index( e.by = system e.desc = "RFC published" e.save() - events.append(e) + rfc_events.append(e) - changes.append( + rfc_changes.append( "added RFC published event at %s" % e.time.strftime("%Y-%m-%d") ) rfc_published = True - for t in ( - "draft-iesg", - "draft-stream-iab", - "draft-stream-irtf", - "draft-stream-ise", - ): - prev_state = doc.get_state(t) - if prev_state is not None: - if prev_state.slug not in ("pub", "idexists"): - new_state = State.objects.select_related("type").get( - used=True, type=t, slug="pub" - ) - doc.set_state(new_state) - changes.append( - "changed %s to %s" % (new_state.type.label, new_state) - ) - e = update_action_holders(doc, prev_state, new_state) - if e: - events.append(e) - elif t == "draft-iesg": - doc.set_state(State.objects.get(type_id="draft-iesg", slug="idexists")) - def parse_relation_list(l): res = [] for x in l: @@ -547,7 +560,7 @@ def parse_relation_list(l): r = RelatedDocument.objects.create( source=doc, target=x, relationship=relationship_obsoletes ) - changes.append( + rfc_changes.append( "created %s relation between %s and %s" % ( r.relationship.name.lower(), @@ -563,7 +576,7 @@ def parse_relation_list(l): r = RelatedDocument.objects.create( source=doc, target=x, relationship=relationship_updates ) - changes.append( + rfc_changes.append( "created %s relation between %s and %s" % ( r.relationship.name.lower(), @@ -577,16 +590,16 @@ def parse_relation_list(l): a = a.lower() if not DocAlias.objects.filter(name=a): DocAlias.objects.create(name=a).docs.add(doc) - changes.append("created alias %s" % prettify_std_name(a)) + rfc_changes.append("created alias %s" % prettify_std_name(a)) - doc_errata = errata.get("RFC%04d" % rfc_number, []) + doc_errata = errata.get("RFC%04d" % rfc_number, []) # rfc10k problem here all_rejected = doc_errata and all( er["errata_status_code"] == "Rejected" for er in doc_errata ) if has_errata and not all_rejected: if not doc.tags.filter(pk=tag_has_errata.pk).exists(): doc.tags.add(tag_has_errata) - changes.append("added Errata tag") + rfc_changes.append("added Errata tag") has_verified_errata = any( [er["errata_status_code"] == "Verified" for er in doc_errata] ) @@ -595,34 +608,46 @@ def parse_relation_list(l): and not doc.tags.filter(pk=tag_has_verified_errata.pk).exists() ): doc.tags.add(tag_has_verified_errata) - changes.append("added Verified Errata tag") + rfc_changes.append("added Verified Errata tag") else: if doc.tags.filter(pk=tag_has_errata.pk): doc.tags.remove(tag_has_errata) if all_rejected: - changes.append("removed Errata tag (all errata rejected)") + rfc_changes.append("removed Errata tag (all errata rejected)") else: - changes.append("removed Errata tag") + rfc_changes.append("removed Errata tag") if doc.tags.filter(pk=tag_has_verified_errata.pk): doc.tags.remove(tag_has_verified_errata) - changes.append("removed Verified Errata tag") + rfc_changes.append("removed Verified Errata tag") - if changes: - events.append( + # Update the draft first + if draft_changes: + draft_events.append( DocEvent.objects.create( - doc=doc, + doc=draft, rev=doc.rev, by=system, type="sync_from_rfc_editor", desc="Received changes through RFC Editor sync (%s)" - % ", ".join(changes), + % ", ".join(draft_changes), ) ) + draft.save_with_history(draft_events) + yield draft_changes, draft, False # yield changes to the draft - doc.save_with_history(events) - - if changes: - yield changes, doc, rfc_published + if rfc_changes: + rfc_events.append( + DocEvent.objects.create( + doc=doc, + rev=doc.rev, + by=system, + type="sync_from_rfc_editor", + desc="Received changes through RFC Editor sync (%s)" + % ", ".join(rfc_changes), + ) + ) + doc.save_with_history(rfc_events) + yield rfc_changes, doc, rfc_published # yield changes to the RFC def post_approved_draft(url, name):