Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ietf/doc/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,8 @@ def is_downref(self):

if self.source.type_id == "rfc":
source_lvl = self.source.std_level_id
elif self.source.type_id in ["bcp","std"]:
source_lvl = self.source.type_id
else:
source_lvl = self.source.intended_std_level_id

Expand All @@ -711,6 +713,8 @@ def is_downref(self):
target_lvl = 'unkn'
else:
target_lvl = self.target.std_level_id
elif self.target.type_id in ["bcp", "std"]:
target_lvl = self.target.type_id
else:
if not self.target.intended_std_level:
target_lvl = 'unkn'
Expand Down
6 changes: 6 additions & 0 deletions ietf/doc/tests_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,12 @@ def do_fuzzy_find_documents_rfc_test(self, name):
found = fuzzy_find_documents(draft.name, '22')
self.assertCountEqual(found.documents, [draft],
'Should find document even if rev does not exist')

# by rfc name mistakenly trying to provide a revision
found = fuzzy_find_documents(rfc.name+"-22")
self.assertCountEqual(found.documents, [rfc], "Should ignore versions when fuzzyfinding RFCs" )
found = fuzzy_find_documents(rfc.name,"22")
self.assertCountEqual(found.documents, [rfc], "Should ignore versions when fuzzyfinding RFCs" )


def test_fuzzy_find_documents(self):
Expand Down
7 changes: 4 additions & 3 deletions ietf/doc/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1209,14 +1209,15 @@ def fuzzy_find_documents(name, rev=None):

if name.startswith("rfc"):
sought_type = "rfc"
log.assertion("rev is None")
name = name.split("-")[0] # strip any noise (like a revision) at and after the first hyphen
rev = None # If someone is looking for an RFC and supplies a version, ignore it.
else:
sought_type = "draft"

# see if we can find a document using this name
docs = Document.objects.filter(name=name, type_id=sought_type)
if rev and not docs.exists():
# No document found, see if the name/rev split has been misidentified.
if sought_type == "draft" and rev and not docs.exists():
# No draft found, see if the name/rev split has been misidentified.
# Handles some special cases, like draft-ietf-tsvwg-ieee-802-11.
name = '%s-%s' % (name, rev)
docs = Document.objects.filter(name=name, type_id='draft')
Expand Down
46 changes: 31 additions & 15 deletions ietf/group/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -740,23 +740,40 @@ def dependencies(request, acronym, group_type=None):
source__type="draft",
relationship__slug__startswith="ref",
)

both_rfcs = Q(source__type_id="rfc", target__type_id="rfc")
inactive = Q(source__states__slug__in=["expired", "repl"])
rfc_or_subseries = {"rfc", "bcp", "fyi", "std"}
both_rfcs = Q(source__type_id="rfc", target__type_id__in=rfc_or_subseries)
pre_rfc_draft_to_rfc = Q(
source__states__type="draft",
source__states__slug="rfc",
target__type_id__in=rfc_or_subseries,
)
both_pre_rfcs = Q(
source__states__type="draft",
source__states__slug="rfc",
target__type_id="draft",
target__states__type="draft",
target__states__slug="rfc",
)
inactive = Q(
source__states__type="draft",
source__states__slug__in=["expired", "repl"],
)
attractor = Q(target__name__in=["rfc5000", "rfc5741"])
removed = Q(source__states__slug__in=["auth-rm", "ietf-rm"])
removed = Q(source__states__type="draft", source__states__slug__in=["auth-rm", "ietf-rm"])
relations = (
RelatedDocument.objects.filter(references)
.exclude(both_rfcs)
.exclude(pre_rfc_draft_to_rfc)
.exclude(both_pre_rfcs)
.exclude(inactive)
.exclude(attractor)
.exclude(removed)
)

links = set()
for x in relations:
target_state = x.target.get_state_slug("draft")
if target_state != "rfc" or x.is_downref():
always_include = x.target.type_id not in rfc_or_subseries and x.target.get_state_slug("draft") != "rfc"
if always_include or x.is_downref():
links.add(x)

replacements = RelatedDocument.objects.filter(
Expand All @@ -771,13 +788,12 @@ def dependencies(request, acronym, group_type=None):
graph = {
"nodes": [
{
"id": x.name,
"rfc": x.get_state("draft").slug == "rfc",
"post-wg": not x.get_state("draft-iesg").slug
in ["idexists", "watching", "dead"],
"expired": x.get_state("draft").slug == "expired",
"replaced": x.get_state("draft").slug == "repl",
"group": x.group.acronym if x.group.acronym != "none" else "",
"id": x.became_rfc().name if x.became_rfc() else x.name,
"rfc": x.type_id == "rfc" or x.became_rfc() is not None,
"post-wg": x.get_state_slug("draft-iesg") not in ["idexists", "watching", "dead"],
"expired": x.get_state_slug("draft") == "expired",
"replaced": x.get_state_slug("draft") == "repl",
"group": x.group.acronym if x.group and x.group.acronym != "none" else "",
"url": x.get_absolute_url(),
"level": x.intended_std_level.name
if x.intended_std_level
Expand All @@ -789,8 +805,8 @@ def dependencies(request, acronym, group_type=None):
],
"links": [
{
"source": x.source.name,
"target": x.target.name,
"source": x.source.became_rfc().name if x.source.became_rfc() else x.source.name,
"target": x.target.became_rfc().name if x.target.became_rfc() else x.target.name,
"rel": "downref" if x.is_downref() else x.relationship.slug,
}
for x in links
Expand Down
28 changes: 22 additions & 6 deletions ietf/stats/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.core.cache import cache
from django.db.models import Count, Q
from django.db.models import Count, Q, Subquery, OuterRef
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse as urlreverse
Expand All @@ -34,7 +34,7 @@
from ietf.person.models import Person
from ietf.name.models import ReviewResultName, CountryName, DocRelationshipName, ReviewAssignmentStateName
from ietf.person.name import plain_name
from ietf.doc.models import Document, State, DocEvent
from ietf.doc.models import Document, RelatedDocument, State, DocEvent
from ietf.meeting.models import Meeting
from ietf.stats.models import MeetingRegistration, CountryAlias
from ietf.stats.utils import get_aliased_affiliations, get_aliased_countries, compute_hirsch_index
Expand Down Expand Up @@ -607,15 +607,31 @@ def build_document_stats_url(stats_type_override=Ellipsis, get_overrides=None):

doc_years = defaultdict(set)

docevent_qs = DocEvent.objects.filter(
draftevent_qs = DocEvent.objects.filter(
doc__type="draft",
type__in=["published_rfc", "new_revision"],
).values_list("doc", "time").order_by("doc")
type = "new_revision",
).values_list("doc","time").order_by("doc")

for doc_id, time in docevent_qs.iterator():
for doc_id, time in draftevent_qs.iterator():
# RPC_TZINFO is used to match the timezone handling in Document.pub_date()
doc_years[doc_id].add(time.astimezone(RPC_TZINFO).year)

rfcevent_qs = (
DocEvent.objects.filter(doc__type="rfc", type="published_rfc")
.annotate(
draft=Subquery(
RelatedDocument.objects.filter(
target=OuterRef("doc__pk"), relationship_id="became_rfc"
).values_list("source", flat=True)[:1]
)
)
.values_list("draft", "time")
.order_by("draft")
)

for doc_id, time in rfcevent_qs.iterator():
doc_years[doc_id].add(time.astimezone(RPC_TZINFO).year)

person_qs = Person.objects.filter(person_filters)

if document_type == "rfc":
Expand Down