prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Support for codecoverage when running Python tests
  Avocado doesn't have a documented and/or supported way for generating code coverage information when running Python based tests.
  
  The first objective is to drop the use of the custom `selftests/run_coverage` script and the additional job, in favor of reusing one already existing CI job with Avocado:
  
   * running code coverage tools
   * keeping the information
   * pushing the information
  
  Even though Python based tests and code coverage is the primary goal of this issue, it's probable that the solution will be about providing a flexible way to add a "wrapper" of sorts before the actual execution of tests.
   
  
  </issue>
  <code>
  [start of avocado/core/runners/avocado_instrumented.py]
  1 import multiprocessing
  2 import tempfile
  3 import time
  4 import traceback
  5 
  6 from avocado.core import nrunner
  7 from avocado.core.runners.utils import messages
  8 from avocado.core.test import TestID
  9 from avocado.core.tree import TreeNodeEnvOnly
  10 from avocado.core.utils import loader
  11 from avocado.core.varianter import is_empty_variant
  12 
  13 
  14 class AvocadoInstrumentedTestRunner(nrunner.BaseRunner):
  15     """
  16     Runner for Avocado INSTRUMENTED tests
  17 
  18     Runnable attributes usage:
  19 
  20      * uri: path to a test file, combined with an Avocado.Test
  21        inherited class name and method.  The test file path and
  22        class and method names should be separated by a ":".  One
  23        example of a valid uri is "mytest.py:Class.test_method".
  24 
  25      * args: not used
  26     """
  27     DEFAULT_TIMEOUT = 86400
  28 
  29     @staticmethod
  30     def _create_params(runnable):
  31         """Create params for the test"""
  32         if runnable.variant is None:
  33             return None
  34 
  35         # rebuild the variant tree
  36         variant_tree_nodes = [TreeNodeEnvOnly(path, env) for path, env
  37                               in runnable.variant['variant']]
  38 
  39         if not is_empty_variant(variant_tree_nodes):
  40             tree_nodes = variant_tree_nodes
  41             paths = runnable.variant['paths']
  42             return tree_nodes, paths
  43 
  44     @staticmethod
  45     def _run_avocado(runnable, queue):
  46         try:
  47             # This assumes that a proper resolution (see resolver module)
  48             # was performed, and that a URI contains:
  49             # 1) path to python module
  50             # 2) class
  51             # 3) method
  52             #
  53             # To be defined: if the resolution uri should be composed like
  54             # this, or broken down and stored into other data fields
  55             module_path, klass_method = runnable.uri.split(':', 1)
  56 
  57             klass, method = klass_method.split('.', 1)
  58 
  59             params = AvocadoInstrumentedTestRunner._create_params(runnable)
  60             result_dir = (runnable.output_dir or
  61                           tempfile.mkdtemp(prefix=".avocado-task"))
  62             test_factory = [klass,
  63                             {'name': TestID(1, runnable.uri),
  64                              'methodName': method,
  65                              'config': runnable.config,
  66                              'modulePath': module_path,
  67                              'params': params,
  68                              'tags': runnable.tags,
  69                              'run.results_dir': result_dir,
  70                              }]
  71 
  72             messages.start_logging(runnable.config, queue)
  73             instance = loader.load_test(test_factory)
  74             early_state = instance.get_state()
  75             early_state['type'] = "early_state"
  76             queue.put(early_state)
  77             instance.run_avocado()
  78             state = instance.get_state()
  79             fail_reason = state.get('fail_reason')
  80             queue.put(messages.WhiteboardMessage.get(state['whiteboard']))
  81             queue.put(messages.FinishedMessage.get(state['status'].lower(),
  82                                                    fail_reason=fail_reason))
  83         except Exception as e:
  84             queue.put(messages.StderrMessage.get(traceback.format_exc()))
  85             queue.put(messages.FinishedMessage.get('error', fail_reason=str(e)))
  86 
  87     def run(self):
  88         yield messages.StartedMessage.get()
  89         try:
  90             queue = multiprocessing.SimpleQueue()
  91             process = multiprocessing.Process(target=self._run_avocado,
  92                                               args=(self.runnable, queue))
  93 
  94             process.start()
  95 
  96             time_started = time.monotonic()
  97 
  98             timeout = float(self.DEFAULT_TIMEOUT)
  99             most_current_execution_state_time = None
  100             while True:
  101                 time.sleep(nrunner.RUNNER_RUN_CHECK_INTERVAL)
  102                 now = time.monotonic()
  103                 if queue.empty():
  104                     if most_current_execution_state_time is not None:
  105                         next_execution_state_mark = (most_current_execution_state_time +
  106                                                      nrunner.RUNNER_RUN_STATUS_INTERVAL)
  107                     if (most_current_execution_state_time is None or
  108                             now > next_execution_state_mark):
  109                         most_current_execution_state_time = now
  110                         yield messages.RunningMessage.get()
  111                     if (now - time_started) > timeout:
  112                         process.terminate()
  113                         yield messages.FinishedMessage.get('interrupted',
  114                                                            'timeout')
  115                         break
  116                 else:
  117                     message = queue.get()
  118                     if message.get('type') == 'early_state':
  119                         timeout = float(message.get('timeout') or
  120                                         self.DEFAULT_TIMEOUT)
  121                     else:
  122                         yield message
  123                     if message.get('status') == 'finished':
  124                         break
  125         except Exception as e:
  126             yield messages.StderrMessage.get(traceback.format_exc())
  127             yield messages.FinishedMessage.get('error', fail_reason=str(e))
  128 
  129 
  130 class RunnerApp(nrunner.BaseRunnerApp):
  131     PROG_NAME = 'avocado-runner-avocado-instrumented'
  132     PROG_DESCRIPTION = 'nrunner application for avocado-instrumented tests'
  133     RUNNABLE_KINDS_CAPABLE = {
  134         'avocado-instrumented': AvocadoInstrumentedTestRunner
  135     }
  136 
  137 
  138 def main():
  139     nrunner.main(RunnerApp)
  140 
  141 
  142 if __name__ == '__main__':
  143     main()
  144
  [end of avocado/core/runners/avocado_instrumented.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/avocado/core/runners/avocado_instrumented.py b/avocado/core/runners/avocado_instrumented.py
  --- a/avocado/core/runners/avocado_instrumented.py
  +++ b/avocado/core/runners/avocado_instrumented.py
  @@ -1,4 +1,5 @@
   import multiprocessing
  +import os
   import tempfile
   import time
   import traceback
  @@ -70,11 +71,22 @@
                                }]
   
               messages.start_logging(runnable.config, queue)
  +
  +            if 'COVERAGE_RUN' in os.environ:
  +                from coverage import Coverage
  +                coverage = Coverage()
  +                coverage.start()
  +
               instance = loader.load_test(test_factory)
               early_state = instance.get_state()
               early_state['type'] = "early_state"
               queue.put(early_state)
               instance.run_avocado()
  +
  +            if 'COVERAGE_RUN' in os.environ:
  +                coverage.stop()
  +                coverage.save()
  +
               state = instance.get_state()
               fail_reason = state.get('fail_reason')
               queue.put(messages.WhiteboardMessage.get(state['whiteboard']))
  
verification_info: {"golden_diff": "diff --git a/avocado/core/runners/avocado_instrumented.py b/avocado/core/runners/avocado_instrumented.py\n--- a/avocado/core/runners/avocado_instrumented.py\n+++ b/avocado/core/runners/avocado_instrumented.py\n@@ -1,4 +1,5 @@\n import multiprocessing\n+import os\n import tempfile\n import time\n import traceback\n@@ -70,11 +71,22 @@\n                              }]\n \n             messages.start_logging(runnable.config, queue)\n+\n+            if 'COVERAGE_RUN' in os.environ:\n+                from coverage import Coverage\n+                coverage = Coverage()\n+                coverage.start()\n+\n             instance = loader.load_test(test_factory)\n             early_state = instance.get_state()\n             early_state['type'] = \"early_state\"\n             queue.put(early_state)\n             instance.run_avocado()\n+\n+            if 'COVERAGE_RUN' in os.environ:\n+                coverage.stop()\n+                coverage.save()\n+\n             state = instance.get_state()\n             fail_reason = state.get('fail_reason')\n             queue.put(messages.WhiteboardMessage.get(state['whiteboard']))\n", "issue": "Support for codecoverage when running Python tests\nAvocado doesn't have a documented and/or supported way for generating code coverage information when running Python based tests.\r\n\r\nThe first objective is to drop the use of the custom `selftests/run_coverage` script and the additional job, in favor of reusing one already existing CI job with Avocado:\r\n\r\n * running code coverage tools\r\n * keeping the information\r\n * pushing the information\r\n\r\nEven though Python based tests and code coverage is the primary goal of this issue, it's probable that the solution will be about providing a flexible way to add a \"wrapper\" of sorts before the actual execution of tests.\r\n \n", "before_files": [{"content": "import multiprocessing\nimport tempfile\nimport time\nimport traceback\n\nfrom avocado.core import nrunner\nfrom avocado.core.runners.utils import messages\nfrom avocado.core.test import TestID\nfrom avocado.core.tree import TreeNodeEnvOnly\nfrom avocado.core.utils import loader\nfrom avocado.core.varianter import is_empty_variant\n\n\nclass AvocadoInstrumentedTestRunner(nrunner.BaseRunner):\n    \"\"\"\n    Runner for Avocado INSTRUMENTED tests\n\n    Runnable attributes usage:\n\n     * uri: path to a test file, combined with an Avocado.Test\n       inherited class name and method.  The test file path and\n       class and method names should be separated by a \":\".  One\n       example of a valid uri is \"mytest.py:Class.test_method\".\n\n     * args: not used\n    \"\"\"\n    DEFAULT_TIMEOUT = 86400\n\n    @staticmethod\n    def _create_params(runnable):\n        \"\"\"Create params for the test\"\"\"\n        if runnable.variant is None:\n            return None\n\n        # rebuild the variant tree\n        variant_tree_nodes = [TreeNodeEnvOnly(path, env) for path, env\n                              in runnable.variant['variant']]\n\n        if not is_empty_variant(variant_tree_nodes):\n            tree_nodes = variant_tree_nodes\n            paths = runnable.variant['paths']\n            return tree_nodes, paths\n\n    @staticmethod\n    def _run_avocado(runnable, queue):\n        try:\n            # This assumes that a proper resolution (see resolver module)\n            # was performed, and that a URI contains:\n            # 1) path to python module\n            # 2) class\n            # 3) method\n            #\n            # To be defined: if the resolution uri should be composed like\n            # this, or broken down and stored into other data fields\n            module_path, klass_method = runnable.uri.split(':', 1)\n\n            klass, method = klass_method.split('.', 1)\n\n            params = AvocadoInstrumentedTestRunner._create_params(runnable)\n            result_dir = (runnable.output_dir or\n                          tempfile.mkdtemp(prefix=\".avocado-task\"))\n            test_factory = [klass,\n                            {'name': TestID(1, runnable.uri),\n                             'methodName': method,\n                             'config': runnable.config,\n                             'modulePath': module_path,\n                             'params': params,\n                             'tags': runnable.tags,\n                             'run.results_dir': result_dir,\n                             }]\n\n            messages.start_logging(runnable.config, queue)\n            instance = loader.load_test(test_factory)\n            early_state = instance.get_state()\n            early_state['type'] = \"early_state\"\n            queue.put(early_state)\n            instance.run_avocado()\n            state = instance.get_state()\n            fail_reason = state.get('fail_reason')\n            queue.put(messages.WhiteboardMessage.get(state['whiteboard']))\n            queue.put(messages.FinishedMessage.get(state['status'].lower(),\n                                                   fail_reason=fail_reason))\n        except Exception as e:\n            queue.put(messages.StderrMessage.get(traceback.format_exc()))\n            queue.put(messages.FinishedMessage.get('error', fail_reason=str(e)))\n\n    def run(self):\n        yield messages.StartedMessage.get()\n        try:\n            queue = multiprocessing.SimpleQueue()\n            process = multiprocessing.Process(target=self._run_avocado,\n                                              args=(self.runnable, queue))\n\n            process.start()\n\n            time_started = time.monotonic()\n\n            timeout = float(self.DEFAULT_TIMEOUT)\n            most_current_execution_state_time = None\n            while True:\n                time.sleep(nrunner.RUNNER_RUN_CHECK_INTERVAL)\n                now = time.monotonic()\n                if queue.empty():\n                    if most_current_execution_state_time is not None:\n                        next_execution_state_mark = (most_current_execution_state_time +\n                                                     nrunner.RUNNER_RUN_STATUS_INTERVAL)\n                    if (most_current_execution_state_time is None or\n                            now > next_execution_state_mark):\n                        most_current_execution_state_time = now\n                        yield messages.RunningMessage.get()\n                    if (now - time_started) > timeout:\n                        process.terminate()\n                        yield messages.FinishedMessage.get('interrupted',\n                                                           'timeout')\n                        break\n                else:\n                    message = queue.get()\n                    if message.get('type') == 'early_state':\n                        timeout = float(message.get('timeout') or\n                                        self.DEFAULT_TIMEOUT)\n                    else:\n                        yield message\n                    if message.get('status') == 'finished':\n                        break\n        except Exception as e:\n            yield messages.StderrMessage.get(traceback.format_exc())\n            yield messages.FinishedMessage.get('error', fail_reason=str(e))\n\n\nclass RunnerApp(nrunner.BaseRunnerApp):\n    PROG_NAME = 'avocado-runner-avocado-instrumented'\n    PROG_DESCRIPTION = 'nrunner application for avocado-instrumented tests'\n    RUNNABLE_KINDS_CAPABLE = {\n        'avocado-instrumented': AvocadoInstrumentedTestRunner\n    }\n\n\ndef main():\n    nrunner.main(RunnerApp)\n\n\nif __name__ == '__main__':\n    main()\n", "path": "avocado/core/runners/avocado_instrumented.py"}]}