#!/usr/bin/env python3 # -*- coding: utf-8 -*- # # Copyright (C) 1998-2026 Stephane Galland # # This program is free library; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as # published by the Free Software Foundation; either version 3 of the # License, or any later version. # # This library is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; see the file COPYING. If not, # write to the Free Software Foundation, Inc., 59 Temple Place - Suite # 330, Boston, MA 02111-1307, USA. """ Biber tools. """ import re from typing import Any, override from autolatex2.tex.abstractbibliography import BibliographyErrorParser class BiberErrorParser(BibliographyErrorParser): """ Parser for errors generated by Biber. """ def __init__(self): """ Construct the parser. """ pass @override def parse_log(self, default_filename : str, log : str) -> dict[str,Any] | None: """ Parse the Biber log and replies the discovered error. :param default_filename: The name of the Biber file to parse. :type default_filename: str :param log: Content of the log. :type log: str :return: the error from Biber. :rtype: str | None """ current_error = dict() for line in re.split(r'[\n\r]', log): m = re.search(r'^\s*ERROR\s*-\s*.*subsystem:\s*(.+?),\s*line\s+([0-9]+),\s*(.*?)\s*$', line, re.S | re.IGNORECASE) if m: filename = m.group(1) lineno = int(m.group(2)) message = m.group(3) m = re.search(r'^(.+)_[0-9]+\.[a-zA-Z0-9_-]+$', filename, re.S) if m: filename = m.group(1) current_error = { 'filename': filename , 'lineno': lineno, 'message': message } return current_error else: m = re.search(r'^\s*ERROR\s*-\s*(.+?)\s*$', line, re.S | re.IGNORECASE) if m: message = m.group(1) current_error = { 'filename': default_filename , 'lineno': 0, 'message': message } return current_error if current_error: return current_error return None