Source code for bibble.people.name_writer

  1#!/usr/bin/env python3
  2"""
  3
  4See EOF for license/metadata/notes as applicable
  5"""
  6
  7# Imports:
  8from __future__ import annotations
  9
 10# ##-- stdlib imports
 11import datetime
 12import enum
 13import functools as ftz
 14import itertools as itz
 15import logging as logmod
 16import pathlib as pl
 17import re
 18import time
 19import types
 20import weakref
 21from uuid import UUID, uuid1
 22
 23# ##-- end stdlib imports
 24
 25# ##-- 3rd party imports
 26import bibtexparser
 27import bibtexparser.model as model
 28from bibtexparser.middlewares.names import NameParts
 29from jgdv import Mixin, Proto
 30
 31# ##-- end 3rd party imports
 32
 33# ##-- 1st party imports
 34import bibble._interface as API
 35from bibble.util.middlecore import IdenBlockMiddleware
 36from bibble.util.mixins import FieldMatcher_m
 37from bibble.util.name_parts import NameParts_d
 38
 39# ##-- end 1st party imports
 40
 41from . import _interface as API_N
 42
 43# ##-- types
 44# isort: off
 45import abc
 46import collections.abc
 47from typing import TYPE_CHECKING, cast, assert_type, assert_never
 48from typing import Generic, NewType
 49# Protocols:
 50from typing import Protocol, runtime_checkable
 51# Typing Decorators:
 52from typing import no_type_check, final, override, overload
 53
 54if TYPE_CHECKING:
 55    from jgdv import Maybe, Result
 56    from typing import Final
 57    from typing import ClassVar, Any, LiteralString
 58    from typing import Never, Self, Literal
 59    from typing import TypeGuard
 60    from collections.abc import Iterable, Iterator, Callable, Generator
 61    from collections.abc import Sequence, Mapping, MutableMapping, Hashable
 62
 63    type Entry = model.Entry
 64    type Field = model.Field
 65    from bibtexparser import Library
 66
 67##--|
 68
 69# isort: on
 70# ##-- end types
 71
 72##-- logging
 73logging = logmod.getLogger(__name__)
 74##-- end logging
 75
[docs] 76@Proto(API.WriteTime_p) 77@Mixin(FieldMatcher_m) 78class NameWriter(IdenBlockMiddleware): 79 """ Transforms NameParts -> [str] -> str 80 81 on init: 82 - parts : bool = merge name parts together 83 - authors : bool = merge separate authors together 84 """ 85 _whitelist = ("author", "editor", "translator") 86 87 def __init__(self, *, parts:bool, authors:bool, **kwargs): 88 super().__init__(**kwargs) 89 self._merge_parts = parts 90 self._merge_authors = authors 91 self.set_field_matchers(white=self._whitelist, black=[]) 92
[docs] 93 def on_write(self): 94 Never()
95
[docs] 96 def transform_Entry(self, entry:Entry, library:Library) -> list[Entry]: 97 match self.match_on_fields(entry, library): 98 case model.Entry() as x: 99 return [x] 100 case Exception() as err: 101 return [self.make_error_block(entry, err)] 102 case x: 103 raise TypeError(type(x))
104
[docs] 105 def field_h(self, field:Field, entry:Entry) -> Result[list[Field], Exception]: 106 result = [] 107 merger = self._merge_von_last_jr_first 108 match field.value, self._merge_parts, self._merge_authors: 109 case str(), _, _: 110 pass 111 case [*xs], True, False if all(isinstance(x, NameParts|NameParts_d) for x in xs): 112 # Merge nameparts, but not authors 113 merged = [merger(x) for x in xs] 114 result.append(model.Field(field.key, merged, start_line=field.start_line)) 115 case [*xs], True, True if all(isinstance(x, NameParts|NameParts_d) for x in xs): 116 # Merge nameparts, then authors 117 merged = [merger(x) for x in xs] 118 joined = API_N.JOIN_STR.join(merged) 119 result.append(model.Field(field.key, joined, start_line=field.start_line)) 120 case [*xs], _, True if all(isinstance(x, str) for x in xs) and self._merge_authors: 121 # Just merge authors 122 joined = API_N.JOIN_STR.join(xs) 123 result.append(model.Field(field.key, joined, start_line=field.start_line)) 124 case _, False, False: 125 pass 126 case x, _, _: 127 return TypeError("Unexpected name type", entry.key, type(x)) 128 129 return result
130
[docs] 131 def _merge_von_last_jr_first(self, name:NameParts|NameParts_d) -> str: 132 match name: 133 case NameParts() | NameParts_d(): 134 pass 135 case x: 136 raise TypeError(type(x)) 137 138 result = [] 139 if name.von: 140 result.append(" ".join(name.von)) 141 result.append(" ") 142 143 if name.last: 144 result.append(" ".join(name.last)) 145 result.append(", ") 146 147 if name.jr: 148 result.append(" ".join(name.jr)) 149 result.append(", ") 150 151 result.append(" ".join(name.first)) 152 153 full_name = "".join(result).removesuffix(", ").strip() 154 return full_name