diff --git a/ietf/doc/models.py b/ietf/doc/models.py index e35eb1261..15e882e71 100644 --- a/ietf/doc/models.py +++ b/ietf/doc/models.py @@ -676,39 +676,59 @@ class RelatedDocument(models.Model): return u"%s %s %s" % (self.source.name, self.relationship.name.lower(), self.target.name) def is_downref(self): - - if self.source.type.slug!='draft' or self.relationship.slug not in ['refnorm','refold','refunk']: + if self.source.type.slug != "draft" or self.relationship.slug not in [ + "refnorm", + "refold", + "refunk", + ]: return None state = self.source.get_state() - if state and state.slug == 'rfc': + if state and state.slug == "rfc": source_lvl = self.source.std_level.slug if self.source.std_level else None elif self.source.intended_std_level: source_lvl = self.source.intended_std_level.slug else: source_lvl = None - if source_lvl not in ['bcp','ps','ds','std']: + if source_lvl not in ["bcp", "ps", "ds", "std", "unkn"]: return None - if self.target.document.get_state().slug == 'rfc': + if self.target.document.get_state().slug == "rfc": if not self.target.document.std_level: - target_lvl = 'unkn' + target_lvl = "unkn" else: target_lvl = self.target.document.std_level.slug else: if not self.target.document.intended_std_level: - target_lvl = 'unkn' + target_lvl = "unkn" else: target_lvl = self.target.document.intended_std_level.slug - rank = { 'ps':1, 'ds':2, 'std':3, 'bcp':3 } + if self.relationship.slug not in ["refnorm", "refunk"]: + return None - if ( target_lvl not in rank ) or ( rank[target_lvl] < rank[source_lvl] ): - if self.relationship.slug == 'refnorm' and target_lvl!='unkn': - return "Downref" - else: - return "Possible Downref" + if source_lvl in ["inf", "exp"]: + return None + + pos_downref = ( + "Downref" if self.relationship.slug != "refunk" else "Possible Downref" + ) + + if source_lvl in ["bcp", "ps", "ds", "std"] and target_lvl in ["inf", "exp"]: + return pos_downref + + if source_lvl == "ds" and target_lvl == "ps": + return pos_downref + + if source_lvl == "std" and target_lvl in ["ps", "ds"]: + return pos_downref + + if source_lvl not in ["inf", "exp"] and target_lvl == "unkn": + return "Possible Downref" + + if source_lvl == "unkn" and target_lvl in ["ps", "ds"]: + return "Possible Downref" return None diff --git a/ietf/doc/tests_models.py b/ietf/doc/tests_models.py new file mode 100644 index 000000000..419574c09 --- /dev/null +++ b/ietf/doc/tests_models.py @@ -0,0 +1,113 @@ +# Copyright The IETF Trust 2016-2023, All Rights Reserved +# -*- coding: utf-8 -*- + +import itertools + +from ietf.doc.factories import WgRfcFactory +from ietf.doc.models import RelatedDocument +from ietf.utils.test_utils import TestCase + + +class RelatedDocumentTests(TestCase): + def test_is_downref(self): + rfcs = [ + WgRfcFactory(std_level_id=lvl) + for lvl in ["inf", "exp", "bcp", "ps", "ds", "std", "unkn"] + ] + + result_matrix = { + # source + "inf": { + "inf": None, # target + "exp": None, # target + "bcp": None, # target + "ps": None, # target + "ds": None, # target + "std": None, # target + "unkn": None, # target + }, + # source + "exp": { + "inf": None, # target + "exp": None, # target + "bcp": None, # target + "ps": None, # target + "ds": None, # target + "std": None, # target + "unkn": None, # target + }, + # source + "bcp": { + "inf": "Downref", # target + "exp": "Downref", # target + "bcp": None, # target + "ps": None, # target + "ds": None, # target + "std": None, # target + "unkn": "Possible Downref", # target + }, + # source + "ps": { + "inf": "Downref", # target + "exp": "Downref", # target + "bcp": None, # target + "ps": None, # target + "ds": None, # target + "std": None, # target + "unkn": "Possible Downref", # target + }, + # source + "ds": { + "inf": "Downref", # target + "exp": "Downref", # target + "bcp": None, # target + "ps": "Downref", # target + "ds": None, # target + "std": None, # target + "unkn": "Possible Downref", # target + }, + # source + "std": { + "inf": "Downref", # target + "exp": "Downref", # target + "bcp": None, # target + "ps": "Downref", # target + "ds": "Downref", # target + "std": None, # target + "unkn": "Possible Downref", # target + }, + # source + "unkn": { + "inf": None, # target + "exp": None, # target + "bcp": None, # target + "ps": "Possible Downref", # target + "ds": "Possible Downref", # target + "std": None, # target + "unkn": "Possible Downref", # target + }, + } + + for rel in ["refnorm", "refinfo", "refunk", "refold"]: + for source, target in itertools.product(rfcs, rfcs): + ref = RelatedDocument.objects.create( + source=source, + target=target.docalias.first(), + relationship_id=rel, + ) + + result = ref.is_downref() + + desired_result = ( + result_matrix[source.std_level_id][target.std_level_id] + if ref.relationship.slug in ["refnorm", "refunk"] + else None + ) + if ( + ref.relationship.slug == "refunk" + and desired_result is not None + and not desired_result.startswith("Possible") + ): + desired_result = f"Possible {desired_result}" + + self.assertEqual(desired_result, result)