research-link-ai / src /researchlink /services /bibtex_parser.py
MHamdan's picture
Deploy Research-Link-AI (Docker Space, offline demo)
a753e74 verified
Raw
History Blame Contribute Delete
2.14 kB
"""BibTeX parsing utilities."""
from __future__ import annotations
try:
import bibtexparser
BIBTEXPARSER_AVAILABLE = True
except ImportError:
BIBTEXPARSER_AVAILABLE = False
PLACEHOLDER_PATTERNS = ["xx", "xxxx", "art. no.", "tbd", "forthcoming", "in press"]
def parse_bibtex(bibtex_str: str) -> list[dict]:
"""Parse BibTeX string into a list of entry dicts."""
if not BIBTEXPARSER_AVAILABLE:
return []
try:
bib_db = bibtexparser.loads(bibtex_str)
return bib_db.entries
except Exception:
return []
def has_placeholder(text: str) -> tuple[bool, list[str]]:
"""Detect placeholder values in a citation field. Returns (found, patterns)."""
found = []
lower = text.lower()
for pattern in PLACEHOLDER_PATTERNS:
if pattern in lower:
found.append(pattern)
return bool(found), found
def entry_to_bibtex(entry: dict) -> str:
"""Convert a bibtexparser entry dict back to a BibTeX string."""
etype = entry.get("ENTRYTYPE", "misc")
key = entry.get("ID", "unknown")
fields = {k: v for k, v in entry.items() if k not in ("ENTRYTYPE", "ID")}
lines = [f"@{etype}{{{key},"]
for k, v in fields.items():
lines.append(f" {k} = {{{v}}},")
lines.append("}")
return "\n".join(lines)
def generate_bibtex_from_metadata(
key: str,
title: str | None,
authors: list[str],
year: str | None,
venue: str | None,
url: str | None,
doi: str | None,
) -> str:
"""Generate a minimal BibTeX entry from known metadata."""
author_str = " and ".join(authors) if authors else "Unknown Author"
lines = [f"@article{{{key},"]
if title:
lines.append(f" title = {{{title}}},")
lines.append(f" author = {{{author_str}}},")
if year:
lines.append(f" year = {{{year}}},")
if venue:
lines.append(f" journal = {{{venue}}},")
if doi:
lines.append(f" doi = {{{doi}}},")
if url:
lines.append(f" url = {{{url}}},")
lines.append(" note = {Citation status: needs-verification},")
lines.append("}")
return "\n".join(lines)