Source code for bibble.bidi.braces

  1#!/usr/bin/env python3
  2"""
  3
  4"""
  5# Imports:
  6from __future__ import annotations
  7
  8# ##-- stdlib imports
  9import datetime
 10import enum
 11import functools as ftz
 12import itertools as itz
 13import logging as logmod
 14import pathlib as pl
 15import re
 16import time
 17import types
 18import collections
 19import contextlib
 20import hashlib
 21from copy import deepcopy
 22from uuid import UUID, uuid1
 23from weakref import ref
 24import atexit # for @atexit.register
 25import faulthandler
 26# ##-- end stdlib imports
 27
 28import jgdv
 29from jgdv import Proto, Mixin
 30from bibble import _interface as API  # noqa: N812
 31from bibble.util.middlecore import IdenBidiMiddleware
 32from bibtexparser import model
 33
 34# ##-- types
 35# isort: off
 36import abc
 37import collections.abc
 38from typing import TYPE_CHECKING, cast, assert_type, assert_never
 39from typing import Generic, NewType, Never
 40# Protocols:
 41from typing import Protocol, runtime_checkable
 42# Typing Decorators:
 43from typing import no_type_check, final, override, overload
 44
 45if TYPE_CHECKING:
 46    from jgdv import Maybe
 47    from typing import Final
 48    from typing import ClassVar, Any, LiteralString
 49    from typing import Self, Literal
 50    from typing import TypeGuard
 51    from collections.abc import Iterable, Iterator, Callable, Generator
 52    from collections.abc import Sequence, Mapping, MutableMapping, Hashable
 53
 54    from bibtexparser import Library
 55    type Entry  = model.Entry
 56    type String = model.String
 57    type Field  = model.Field
 58##--|
 59
 60# isort: on
 61# ##-- end types
 62
 63##-- logging
 64logging = logmod.getLogger(__name__)
 65##-- end logging
 66
 67# Vars:
 68OBRACE : Final[str]           = "{"
 69CBRACE : Final[str]           = "}"
 70DQUOTE : Final[str]           = '"'
 71STRINGS_CAN_BE_UNESCAPED_INTS = False
 72ENTRY_POTENTIALLY_INT_FIELDS  = [
 73    "year",
 74    "month",
 75    "volume",
 76    "number",
 77    "pages",
 78    "edition",
 79    "chapter",
 80    "issue",
 81]
 82# Body:
 83
[docs] 84@Proto(API.BidirectionalMiddleware_p) 85class BraceWrapper(IdenBidiMiddleware): 86 """ a Bidirectional replacement for bibtexparsers 'Add/RemoveEnclosingMiddleware' """ 87 88 def __init__(self, *, wrappers:Maybe[tuple[str,str]]=None, on_ints:bool=True, **kwargs): 89 super().__init__(**kwargs) 90 self._wrapper = wrappers or (OBRACE, CBRACE) 91 self._on_ints = on_ints 92
[docs] 93 def _wrap(self, value: str, *, maybe_int_rule:bool=False) -> str: 94 """ Take 'value' and wrap it in (by default) braces """ 95 if maybe_int_rule and not self._on_ints and value.isdigit(): 96 return value 97 98 ochar, cchar = self._wrapper 99 return f"{ochar}{value}{cchar}"
100
[docs] 101 def _unwrap(self, value: str) -> str: 102 """ remove wrapping (by default) braces """ 103 ochar, cchar = self._wrapper 104 start, end = len(ochar), 0 - len(cchar) 105 value = value.strip() 106 if value.startswith(ochar) and value.endswith(cchar): 107 return value[start:end] 108 else: 109 return value
110
[docs] 111 def write_transform_Entry(self, entry:Entry, *args, **kwargs) -> list[Entry]: 112 for field in entry.fields: 113 field.value = self._wrap(field.value, maybe_int_rule=field.key in ENTRY_POTENTIALLY_INT_FIELDS) 114 else: 115 return [entry]
116
[docs] 117 def write_transform_String(self, string:String, *args, **kwargs) -> list[String]: 118 string.value = self._wrap(string.value, maybe_int_rule=STRINGS_CAN_BE_UNESCAPED_INTS) 119 return [string]
120
[docs] 121 def read_transform_Entry(self, entry: Entry, library: Library) -> list[Entry]: 122 for field in entry.fields: 123 field.value = self._unwrap(field.value) 124 else: 125 return [entry] 126 127 Never()
128
[docs] 129 def read_transform_String(self, string: String, library: Library) -> list[String]: 130 string.value = self._unwrap(string.value) 131 return [string]