Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Link citations cannot be disambiguated #5016

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
13 changes: 12 additions & 1 deletion cl/citations/annotate_citations.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@
import re
from typing import Dict, List

from django.urls import reverse
from eyecite import annotate_citations, clean_text

from cl.citations.match_citations import NO_MATCH_RESOURCE
from cl.citations.match_citations import (
MULTIPLE_MATCHES_RESOURCE,
NO_MATCH_RESOURCE,
)
from cl.citations.types import MatchedResourceType, SupportedCitationType
from cl.custom_filters.templatetags.text_filters import best_case_name
from cl.lib.string_utils import trunc
Expand Down Expand Up @@ -62,6 +66,13 @@ def generate_annotations(
'<span class="citation no-link">',
"</span>",
]
elif opinion is MULTIPLE_MATCHES_RESOURCE: # If multiple matches,
# can't disambiguate...
annotation = [
'<span class="citation multiple-matches">'
f'<a href="{reverse("citation_redirector", args=[citations[0].groups["reporter"], citations[0].groups["volume"], citations[0].groups["page"]])}">',
quevon24 marked this conversation as resolved.
Show resolved Hide resolved
"</a></span>",
]
else: # If successfully matched...
case_name = trunc(best_case_name(opinion.cluster), 60, "...")
safe_case_name = html.escape(case_name)
Expand Down
10 changes: 10 additions & 0 deletions cl/citations/match_citations.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@


NO_MATCH_RESOURCE = Resource(case_citation(source_text="UNMATCHED_CITATION"))
MULTIPLE_MATCHES_RESOURCE = Resource(
case_citation(
source_text="MULTIPLE_MATCHES", page="999999", volume="999999"
)
)


def filter_by_matching_antecedent(
Expand Down Expand Up @@ -56,6 +61,11 @@ def resolve_fullcase_citation(
if type(full_citation) is FullCaseCitation:
db_search_results: list[Hit]
db_search_results, _ = es_search_db_for_full_citation(full_citation)
# If there is more than one result, return a placeholder with the
# citation with multiple results
if len(db_search_results) > 1:
return MULTIPLE_MATCHES_RESOURCE

# If there is one search result, try to return it
if len(db_search_results) == 1:
result_id = db_search_results[0]["id"]
Expand Down
11 changes: 6 additions & 5 deletions cl/citations/match_citations_queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,9 +214,9 @@ def es_search_db_for_full_citation(
full_citation,
full_citation.citing_opinion,
)
return results, citation_found
# Give up.
return [], citation_found

# Return all possible results
return results, citation_found


def es_get_query_citation(
Expand Down Expand Up @@ -244,6 +244,7 @@ def es_get_query_citation(
missing_citations.append(citation)

if len(citations) == 1 and matches and len(matches) == 1:
# If more than one match, don't show the tip
# If only one match, show the tip
return matches[0], missing_citations
return matches, missing_citations
# No exact match, don't show the tip
return None, missing_citations
4 changes: 4 additions & 0 deletions cl/citations/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
is_parenthetical_descriptive,
)
from cl.citations.match_citations import (
MULTIPLE_MATCHES_RESOURCE,
NO_MATCH_RESOURCE,
do_resolve_citations,
)
Expand Down Expand Up @@ -163,6 +164,9 @@ def store_opinion_citations_and_update_parentheticals(
# Delete the unmatched citations
citation_resolutions.pop(NO_MATCH_RESOURCE, None)

# Delete citations with multiple matches
citation_resolutions.pop(MULTIPLE_MATCHES_RESOURCE, None)

# Increase the citation count for the cluster of each matched opinion
# if that cluster has not already been cited by this opinion. First,
# calculate a list of the IDs of every opinion whose cluster will need
Expand Down
34 changes: 34 additions & 0 deletions cl/citations/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
get_representative_parenthetical,
)
from cl.citations.match_citations import (
MULTIPLE_MATCHES_RESOURCE,
NO_MATCH_RESOURCE,
do_resolve_citations,
resolve_fullcase_citation,
Expand Down Expand Up @@ -503,6 +504,7 @@ def setUpTestData(cls) -> None:
# Courts
cls.court_scotus = CourtFactory(id="scotus")
court_ca1 = CourtFactory(id="ca1")
cls.court_ca5 = CourtFactory(id="ca5")

# Citation 1
cls.citation1 = CitationWithParentsFactory.create(
Expand Down Expand Up @@ -579,6 +581,29 @@ def setUpTestData(cls) -> None:
),
),
)

cls.citation6 = CitationWithParentsFactory.create(
volume="114",
reporter="F.3d",
page="1182",
cluster=OpinionClusterFactoryWithChildrenAndParents(
docket=DocketFactory(court=cls.court_ca5),
case_name="Foo v. Bar",
date_filed=date(1997, 4, 10),
),
)

cls.citation7 = CitationWithParentsFactory.create(
volume="114",
reporter="F.3d",
page="1182",
cluster=OpinionClusterFactoryWithChildrenAndParents(
docket=DocketFactory(court=cls.court_ca5),
case_name="Lorem v. Ipsum",
date_filed=date(1997, 4, 8),
),
)

call_command(
"cl_index_parent_and_child_docs",
search_type=SEARCH_TYPES.OPINION,
Expand Down Expand Up @@ -897,6 +922,15 @@ def test_citation_matching_issue621(self) -> None:
results = resolve_fullcase_citation(citation)
self.assertEqual(NO_MATCH_RESOURCE, results)

def test_citation_multiple_matches(self) -> None:
"""Make sure that we can identify multiple matches for a single citation"""
citation_str = "114 F.3d 1182"
citation = get_citations(citation_str, tokenizer=HYPERSCAN_TOKENIZER)[
0
]
results = resolve_fullcase_citation(citation)
self.assertEqual(MULTIPLE_MATCHES_RESOURCE, results)

def test_citation_increment(self) -> None:
"""Make sure that found citations update the increment on the cited
opinion's citation count"""
Expand Down