Source code for udapi.block.util.findbug

"""Block util.FindBug for debugging.

Usage:
If block xy.Z fails with a Python exception,
insert "util.FindBug block=" into the scenario,
e.g. to debug ``second.Block``, use

  udapy first.Block util.FindBug block=second.Block > bug.conllu

This will create the file bug.conllu with the bundle, which caused the bug.

The second.Block can have any parameters, e.g.
  udapy first.Block util.FindBug block=second.Block param1=value1 param2=value2 > bug.conllu
"""
import copy
import logging

from udapi.core.basewriter import BaseWriter
from udapi.block.write.conllu import Conllu
from udapi.core.run import _parse_block_name


[docs] class FindBug(BaseWriter): """Debug another block by finding a minimal testcase conllu file.""" def __init__(self, block, first_error_only=True, files='-', filehandle=None, docname_as_file=False, encoding='utf-8', newline='\n', overwrite=False, **kwargs): """Args: block, first_error_only. All other parameters (which are not parameters of BaseWriter) will be passed to the block being inspected. """ super().__init__(files, filehandle, docname_as_file, encoding, newline, overwrite) self.block = block self.first_error_only = first_error_only self._kwargs = kwargs
[docs] def process_document(self, document): sub_path, class_name = _parse_block_name(self.block) module = "udapi.block." + sub_path + "." + class_name.lower() try: command = "from " + module + " import " + class_name + " as B" logging.debug("Trying to run command: %s", command) exec(command) # pylint: disable=exec-used except Exception: logging.warning("Error when trying import the block %s", self.block) raise command = "B(**self._kwargs)" logging.debug("Trying to evaluate this: %s", command) new_block = eval(command) # pylint: disable=eval-used doc_copy = copy.deepcopy(document) writer = Conllu(files=self.orig_files) for bundle_no, bundle in enumerate(doc_copy.bundles, 1): logging.debug('Block %s processing bundle #%d (id=%s)', self.block, bundle_no, bundle.bundle_id) try: new_block.process_bundle(bundle) except Exception as exc: # pylint: disable=broad-except logging.warning('util.FindBug found a problem in bundle %d in block %s: %r', bundle_no, self.block, exc) logging.warning('Printing a minimal example to %s', self.orig_files) for tree in document.bundles[bundle_no - 1].trees: writer.process_tree(tree) if self.first_error_only: raise