From b0b8050b0c86b523137d6dc6599f562e2d48892a Mon Sep 17 00:00:00 2001 From: Audiobook Producer Date: Sun, 18 Oct 2026 13:27:06 -0500 Subject: [PATCH] Metadata: library-style PDF author 'Last, First, dates' becomes 'First Last' --- _pipeline/meta.py | 14 +++++++++++++- _pipeline/tests/test_meta.py | 7 +++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/_pipeline/meta.py b/_pipeline/meta.py index 83074ff..942fe48 100644 --- a/_pipeline/meta.py +++ b/_pipeline/meta.py @@ -57,6 +57,16 @@ def junk_author(a): return len(re.sub(r"[^A-Za-z]", "", a)) < 3 or a.lower() in JUNK_AUTHORS or bool(re.search(r"\d{3,}", a)) +def info_author_name(a): + """PDF metadata authors often look like 'Lincoln, Abraham, 1809-1865': drop the dates and put the first name first.""" + a = re.sub(r"[,\s]*\(?\b(?:c\.?\s*)?\d{3,4}\s*-\s*(?:\d{3,4})?\)?\.?\s*$", "", clean_text(a)).strip(" ,;") + parts = [p.strip() for p in a.split(",")] + if len(parts) == 2 and all(re.fullmatch(r"[A-Za-z.'’\- ]+", p) for p in parts) and 1 <= len(parts[0].split()) <= 2 \ + and not any(w.lower().strip(".") in NOT_NAME_WORDS | {"inc", "ltd", "llc", "jr", "sr", "corp", "gmbh"} for w in (parts[0] + " " + parts[1]).split()): + a = parts[1] + " " + parts[0] + return a + + def display_name(name): """'YOGI RAMACHARAKA' / 'yogi ramacharaka' -> 'Yogi Ramacharaka'. Mixed case is kept (McDonald).""" out = [] @@ -259,7 +269,9 @@ def detect_from_pdf(cfg, pdf, hint=None): res = {"title": "", "title_source": "", "author": "", "author_source": "", "notes": notes} if info["title"] and not junk_title(info["title"]): res["title"], res["title_source"] = bookio.title_case(clean_text(info["title"])), "pdf-metadata" - info_author = info["author"] if info["author"] and not junk_author(info["author"]) else "" + info_author = info_author_name(info["author"]) if info["author"] else "" + if info_author and junk_author(info_author): + info_author = "" pages, blank = first_pages_text(cfg, pdf, n, notes) page = read_title_page([(p, t) for p, t, _ in pages], hint) diff --git a/_pipeline/tests/test_meta.py b/_pipeline/tests/test_meta.py index bbfdd58..224b414 100644 --- a/_pipeline/tests/test_meta.py +++ b/_pipeline/tests/test_meta.py @@ -158,6 +158,13 @@ class PureTests(unittest.TestCase): self.assertEqual(meta.clean_filename_title("my_book_final"), "my book") self.assertEqual(meta.filename_candidates(["2401.01234.pdf", "Deep Work.url"])[0], "Deep Work") + def test_library_style_metadata_author(self): + self.assertEqual(meta.info_author_name("Lincoln, Abraham, 1809-1865"), "Abraham Lincoln") + self.assertEqual(meta.info_author_name("Pope, Alexander, 1688-1744"), "Alexander Pope") + self.assertEqual(meta.info_author_name("Jane Doe"), "Jane Doe") + self.assertEqual(meta.info_author_name("Doe, Jane Q."), "Jane Q. Doe") + self.assertEqual(meta.info_author_name("Acme Press, Inc."), "Acme Press, Inc.") + def test_author_rules(self): self.assertEqual(meta.first_author("YOGI RAMACHARAKA"), "Yogi Ramacharaka") self.assertEqual(meta.first_author("Glenn Clark and Walter Russell"), "Glenn Clark")