Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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,078 changes: 4,078 additions & 0 deletions test/stdlib_basics/legal/cases_metadata/va_report_vol_10_CasesMetadata.json

Large diffs are not rendered by default.

13,045 changes: 13,045 additions & 0 deletions test/stdlib_basics/legal/cases_metadata/va_report_vol_1_CasesMetadata.json

Large diffs are not rendered by default.

19,911 changes: 19,911 additions & 0 deletions test/stdlib_basics/legal/cases_metadata/va_report_vol_2_CasesMetadata.json

Large diffs are not rendered by default.

4,760 changes: 4,760 additions & 0 deletions test/stdlib_basics/legal/cases_metadata/va_report_vol_3_CasesMetadata.json

Large diffs are not rendered by default.

14,013 changes: 14,013 additions & 0 deletions test/stdlib_basics/legal/cases_metadata/va_report_vol_4_CasesMetadata.json

Large diffs are not rendered by default.

9,878 changes: 9,878 additions & 0 deletions test/stdlib_basics/legal/cases_metadata/va_report_vol_5_CasesMetadata.json

Large diffs are not rendered by default.

7,845 changes: 7,845 additions & 0 deletions test/stdlib_basics/legal/cases_metadata/va_report_vol_6_CasesMetadata.json

Large diffs are not rendered by default.

10,702 changes: 10,702 additions & 0 deletions test/stdlib_basics/legal/cases_metadata/va_report_vol_7_CasesMetadata.json

Large diffs are not rendered by default.

7,483 changes: 7,483 additions & 0 deletions test/stdlib_basics/legal/cases_metadata/va_report_vol_8_CasesMetadata.json

Large diffs are not rendered by default.

6,557 changes: 6,557 additions & 0 deletions test/stdlib_basics/legal/cases_metadata/va_report_vol_9_CasesMetadata.json

Large diffs are not rendered by default.

96 changes: 96 additions & 0 deletions test/stdlib_basics/legal/citation_exists.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
from mellea.stdlib.base import Context
from mellea.stdlib.requirement import Requirement, ValidationResult

import json
import os
import re

def normalize_case_name(name) -> str:
"""
Converts a case name to a standard format.

Args:
name: A string representing the case name.

Returns:
A normalized case name.
"""
# 1. Lowercase everything
name = name.lower()

# 2. Normalize 'vs', 'vs.', 'v', 'versus' to 'v.'
name = re.sub(r'\b(vs\.?|versus|v)(?!\.)\b', 'v.', name)

# 3. Remove all non-alphanumeric characters except periods, spaces, and apostrophes
name = re.sub(r"[^a-z0-9.& ']+", '', name)

# 4. Replace multiple spaces with a single space
name = re.sub(r'\s+', ' ', name)

return name.strip()

def citation_exists(ctx: Context, folder_path: str) -> ValidationResult:
"""
Given a case name and a directory, checks all of the CasesMetadata files in that directory
to see if the given case name can be found in it.

Args:
ctx: Context
folder_path: a string representing the path to the database directory

Returns:
A validation result indicating if a match was found between given case name and database
"""
# not sure about this line
case_name = ctx.last_output().value

if not case_name or not isinstance(case_name, str):
return ValidationResult(False, reason="No case name provided in output")

normalized_input = normalize_case_name(case_name)

# Search in all files in the folder
try:
files = os.listdir(folder_path)
except FileNotFoundError:
return ValidationResult(False, reason=f"Folder '{folder_path}' not found")

case_names = set()
case_name_abb = set()

# Iterate over all json files in the directory and extract info
for file in files:
if not file.endswith(".json"):
continue
try:
with open(os.path.join(folder_path, file), 'r') as f:
data = json.load(f)

# Collect all case names (including abbreviated version)
for case in data:
if 'name' in case:
case_names.add(normalize_case_name(case['name']))
if 'name_abbreviation' in case:
case_name_abb.add(normalize_case_name(case['name_abbreviation']))

except Exception as e:
return ValidationResult(False, reason=f"Error loading '{file}': {e!s}")

# Check both name and name_abbreviation
if normalized_input in case_names or normalized_input in case_name_abb:
return ValidationResult(True, reason=f"'{case_name}' found in database")
else:
return ValidationResult(False, reason=f"'{case_name}' not found in database")


class CaseNameExistsInDatabase(Requirement):
"""
Checks if the output case name exists in the provided case metadata database.
"""

def __init__(self, folder_path: str):
self._folder_path = folder_path
super().__init__(
description="The case name should exist in the provided case metadata database.",
validation_fn=lambda ctx: citation_exists(ctx, self._folder_path),
)
54 changes: 54 additions & 0 deletions test/stdlib_basics/legal/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import pytest

from citation_exists import normalize_case_name, citation_exists

# Mock context for testing citation_exists (not sure if this is implemented correctly)
class MockContext:
def __init__(self, case_name):
self._case_name = case_name

def last_output(self):
return type("MockOutput", (), {"value": self._case_name})()

# region: normalize_case_name tests

# NOTE: investigate how to handle apostrophe and ampersand
@pytest.mark.parametrize("raw_name,expected", [
("BOB VS SHMEEGUS", "bob v. shmeegus"),
("William Payne, Executor of John Payne v. William Dudley Executor of Fleet", "william payne executor of john payne v. william dudley executor of fleet"),
("Ozwald v. Dickinson's Ex'rs", "ozwald v. dickinson's ex'rs"),
("Fox & al. v. Cosby", "fox & al. v. cosby"),
("Groves v. Graves", "groves v. graves"),
("Ozwald, Deniston, & Co. v. Dickinson's Ex'rs", "ozwald deniston & co. v. dickinson's ex'rs"),
("Bobby- versus shmeegy", "bobby v. shmeegy")
])

def test_normalize_case_name(raw_name, expected):
assert normalize_case_name(raw_name) == expected

# endregion

# region: citation_exists tests

@pytest.mark.parametrize("case_name,expected", [
("Bob v. Shmeegus", False),
("Gimli versus Legolas", False),
("Groves v. Graves", True),
("William Payne, Executor of John Payne v. William Dudley Executor of Fleet", True),
("Payne v. Dudley", True),
("Fox & al. v. Cosby", True),
("Fox v. Cosby", True),
])

def test_citation_exists(tmp_path, case_name, expected):
# create mock context
ctx = MockContext(case_name)

# path to metadata folder
db_folder = "cases_metadata"


result = citation_exists(ctx, db_folder)
assert result.as_bool() == expected, result.reason

# endregion