Skip to content
Merged
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
137 changes: 137 additions & 0 deletions scripts/resume_text_extractor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
#!/usr/bin/env python3
"""Command-line helper to exercise resume text and link extraction."""
Comment on lines +1 to +2

Copilot AI Mar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says it adds scripts/resume_text_link_test.py, but the actual added file is scripts/resume_text_extractor.py. Please update the PR description (or rename the script) so the documentation matches what was merged.

Copilot uses AI. Check for mistakes.

from __future__ import annotations

import argparse
import json
from dataclasses import dataclass
from pathlib import Path
import sys
from typing import Any

from five08.document_text import extract_document_text
from five08.resume_extractor import ResumeProfileExtractor


@dataclass
class FileResult:
path: str
text_length: int
extracted_text: str
links: list[tuple[str, float]]


def _parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(
description=(
"Extract resume text with shared helpers and print the links discovered "
"by the current resume URL extraction logic."
)
)
parser.add_argument(
"files",
nargs="+",
metavar="FILE",
help="One or more resume files to extract.",
)
parser.add_argument(
"--text-max",
type=int,
default=4000,
help="Max characters of extracted text to print. Set to 0 for full text.",
)
parser.add_argument(
"--json",
action="store_true",
help="Print machine-readable JSON output instead of pretty text.",
)
return parser.parse_args()


def _shorten_text(text: str, limit: int) -> str:
if limit <= 0 or len(text) <= limit:
return text
omitted = len(text) - limit
return f"{text[:limit]}\n... ({omitted} more chars omitted)"


def extract_website_link_candidates(text: str) -> list[tuple[str, float]]:
"""Extract normalized website links and confidence scores from resume text."""
return ResumeProfileExtractor._extract_website_link_candidates(text)


def _process_file(path: Path) -> FileResult:
raw = path.read_bytes()
text = extract_document_text(raw, filename=path.name)
link_candidates = extract_website_link_candidates(text)
return FileResult(
path=str(path),
text_length=len(text),
extracted_text=text,
links=link_candidates,
)


def _print_pretty(results: list[FileResult], text_max: int) -> None:
for index, result in enumerate(results, start=1):
print(f"\n[{index}] {result.path}")
print(f" extracted_text_len={result.text_length}")
print(" extracted_text:")
print(_shorten_text(result.extracted_text, text_max))

if result.links:
print(" extracted_links:")
for link, confidence in result.links:
print(f" - {link} (confidence={confidence:.3f})")
else:
print(" extracted_links: []")


def _print_json(results: list[FileResult], text_max: int) -> None:
payload: list[dict[str, Any]] = []
for result in results:
payload.append(
{
"path": result.path,
"extracted_text_length": result.text_length,
"extracted_text": _shorten_text(result.extracted_text, text_max),
"extracted_links": [
{"url": url, "confidence": confidence}
for url, confidence in result.links
],
}
)
print(json.dumps(payload, indent=2))


def main() -> None:
args = _parse_args()
results: list[FileResult] = []
exit_code = 0

for file_arg in args.files:
path = Path(file_arg)
if not path.is_file():
print(f"error: missing file: {path}", file=sys.stderr)
exit_code = 1
continue
Comment on lines +115 to +118

Copilot AI Mar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In --json mode this print() writes error text to stdout, which will corrupt the JSON output and make it non-machine-readable. Please send error messages to stderr (or use logging configured to stderr) so stdout remains valid JSON when --json is set.

Copilot uses AI. Check for mistakes.
try:
results.append(_process_file(path))
except Exception as exc: # pragma: no cover - runtime diagnostic path
print(f"error: failed to process {path}: {exc}", file=sys.stderr)
exit_code = 1
Comment on lines +121 to +123

Copilot AI Mar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error message is printed to stdout; when running with --json it will break JSON parsing. Please write errors to stderr (e.g., print(..., file=sys.stderr)) so the JSON output on stdout remains clean.

Copilot uses AI. Check for mistakes.

if not results:
raise SystemExit(exit_code or 1)

if args.json:
_print_json(results, args.text_max)
else:
_print_pretty(results, args.text_max)

raise SystemExit(exit_code)


if __name__ == "__main__":
main()