We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Unused `six` import in monitor code
In `openhtf/core/monitors.py`, it looks like there is an unused import of the `six` module:
https://github.com/google/openhtf/blob/c85fb069a1ce407e82bb47a8fb1b64220e974c5f/openhtf/core/monitors.py#L58

If the aforementioned import is in fact not needed, then it should be deleted.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `openhtf/core/monitors.py`
Content:
```
1 # Copyright 2014 Google Inc. All Rights Reserved.
2 
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 """Monitors provide a mechanism for periodically collecting a measurement.
15 
16 Monitors are implemented similar to phase functions - they are decorated
17 with plugs.plug() to pass plugs in.  The return value of a monitor
18 function, however, will be used to append a value to a measurement.
19 
20 Monitors by default poll at a rate of 1 second between invocations of
21 the monitor function.  The poll interval (given in milliseconds) determines the
22 approximate frequency at which values will be sampled.  A sample is considered
23 to have been taken at the time when the monitor function *returns*, not when
24 it is called.
25 
26 The approximate average duration of calls to the monitor function is taken into
27 account, so that samples are obtained on as close to interval_ms boundaries as
28 can be.  A poll interval of 0 will cause the monitor function to be called in a
29 tight loop with no delays.
30 
31 Example:
32 
33 @plugs.plug(current_meter=current_meter.CurrentMeter)
34 def CurrentMonitor(test, current_meter):
35   return current_meter.GetReading()
36 
37 @monitors.monitors('current_draw', CurrentMonitor, units=units.AMPERE)
38 def MyPhase(test):
39   # Do some stuff for a while...
40 
41 # MyPhase will have a dimensioned measurement on it, with units of 'AMPERE' and
42 # a single dimension of 'MILLISECONDS', and will have values for roughly every
43 # second while MyPhase was executing.
44 """
45 
46 import functools
47 import inspect
48 import time
49 from typing import Any, Callable, Dict, Optional, Text
50 
51 import openhtf
52 from openhtf import plugs
53 from openhtf.core import measurements
54 from openhtf.core import phase_descriptor
55 from openhtf.core import test_state as core_test_state
56 from openhtf.util import threads
57 from openhtf.util import units as uom
58 import six
59 
60 
61 class _MonitorThread(threads.KillableThread):
62   """Background thread that runs a monitor."""
63 
64   daemon = True
65 
66   def __init__(self, measurement_name: Text,
67                monitor_desc: phase_descriptor.PhaseDescriptor,
68                extra_kwargs: Dict[Any, Any],
69                test_state: core_test_state.TestState, interval_ms: int):
70     super(_MonitorThread,
71           self).__init__(name='%s_MonitorThread' % measurement_name)
72     self.measurement_name = measurement_name
73     self.monitor_desc = monitor_desc
74     self.test_state = test_state
75     self.interval_ms = interval_ms
76     self.extra_kwargs = extra_kwargs
77 
78   def get_value(self) -> Any:
79     argspec = inspect.getfullargspec(self.monitor_desc.func)
80     argspec_args = argspec.args
81     argspec_keywords = argspec.varkw
82     if argspec_keywords:
83       # Monitor phase takes **kwargs, so just pass everything in.
84       kwargs = self.extra_kwargs
85     else:
86       # Only pass in args that the monitor phase takes.
87       kwargs = {
88           arg: val for arg, val in self.extra_kwargs if arg in argspec_args
89       }
90     return self.monitor_desc.with_args(**kwargs)(self.test_state)
91 
92   def _thread_proc(self):
93     measurement = getattr(self.test_state.test_api.measurements,
94                           self.measurement_name)
95     start_time = time.time()
96 
97     # Special case tight-loop monitoring.
98     if not self.interval_ms:
99       while True:
100         measurement[(time.time() - start_time) * 1000] = self.get_value()
101 
102     # Helper to take sample, return sample number and sample duration.
103     def _take_sample():
104       pre_time, value, post_time = time.time(), self.get_value(), time.time()
105       measurement[(post_time - start_time) * 1000] = value
106       return (int((post_time - start_time) * 1000 / self.interval_ms),
107               (post_time - pre_time) * 1000)
108 
109     # Track the last sample number, and an approximation of the mean time
110     # it takes to sample (so we can account for it in how long we sleep).
111     last_sample, mean_sample_ms = _take_sample()
112     while True:
113       # Find what sample number (float) we would be on if we sampled now.
114       current_time = time.time()
115       new_sample = ((((current_time - start_time) * 1000) + mean_sample_ms) /
116                     self.interval_ms)
117       if new_sample < last_sample + 1:
118         time.sleep(start_time - current_time +
119                    ((last_sample + 1) * self.interval_ms / 1000.0) -
120                    (mean_sample_ms / 1000.0))
121         continue
122       elif new_sample > last_sample + 2:
123         self.test_state.state_logger.warning(
124             'Monitor for "%s" skipping %s sample(s).', self.measurement_name,
125             new_sample - last_sample - 1)
126       last_sample, cur_sample_ms = _take_sample()
127       # Approximate 10-element sliding window average.
128       mean_sample_ms = ((9 * mean_sample_ms) + cur_sample_ms) / 10.0
129 
130 
131 def monitors(
132     measurement_name: Text,
133     monitor_func: phase_descriptor.PhaseT,
134     units: Optional[uom.UnitDescriptor] = None,
135     poll_interval_ms: int = 1000
136 ) -> Callable[[phase_descriptor.PhaseT], phase_descriptor.PhaseDescriptor]:
137   """Returns a decorator that wraps a phase with a monitor."""
138   monitor_desc = openhtf.PhaseDescriptor.wrap_or_copy(monitor_func)
139 
140   def wrapper(
141       phase_func: phase_descriptor.PhaseT) -> phase_descriptor.PhaseDescriptor:
142     phase_desc = openhtf.PhaseDescriptor.wrap_or_copy(phase_func)
143 
144     # Re-key this dict so we don't have to worry about collisions with
145     # plug.plug() decorators on the phase function.  Since we aren't
146     # updating kwargs here, we don't have to worry about collisions with
147     # kwarg names.
148     monitor_plugs = {('_' * idx) + measurement_name + '_monitor': plug.cls
149                      for idx, plug in enumerate(monitor_desc.plugs, start=1)}
150 
151     @openhtf.PhaseOptions(requires_state=True)
152     @plugs.plug(update_kwargs=False, **monitor_plugs)
153     @openhtf.measures(
154         measurements.Measurement(measurement_name).with_units(
155             units).with_dimensions(uom.MILLISECOND))
156     @functools.wraps(phase_desc.func)
157     def monitored_phase_func(test_state, *args, **kwargs):
158       # Start monitor thread, it will run monitor_desc periodically.
159       monitor_thread = _MonitorThread(measurement_name, monitor_desc,
160                                       phase_desc.extra_kwargs, test_state,
161                                       poll_interval_ms)
162       monitor_thread.start()
163       try:
164         return phase_desc(test_state, *args, **kwargs)
165       finally:
166         monitor_thread.kill()
167         monitor_thread.join()
168 
169     return monitored_phase_func
170 
171   return wrapper
172
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/openhtf/core/monitors.py b/openhtf/core/monitors.py
--- a/openhtf/core/monitors.py
+++ b/openhtf/core/monitors.py
@@ -55,7 +55,6 @@
 from openhtf.core import test_state as core_test_state
 from openhtf.util import threads
 from openhtf.util import units as uom
-import six
 
 
 class _MonitorThread(threads.KillableThread):

{"golden_diff": "diff --git a/openhtf/core/monitors.py b/openhtf/core/monitors.py\n--- a/openhtf/core/monitors.py\n+++ b/openhtf/core/monitors.py\n@@ -55,7 +55,6 @@\n from openhtf.core import test_state as core_test_state\n from openhtf.util import threads\n from openhtf.util import units as uom\n-import six\n \n \n class _MonitorThread(threads.KillableThread):\n", "issue": "Unused `six` import in monitor code\nIn `openhtf/core/monitors.py`, it looks like there is an unused import of the `six` module:\r\nhttps://github.com/google/openhtf/blob/c85fb069a1ce407e82bb47a8fb1b64220e974c5f/openhtf/core/monitors.py#L58\r\n\r\nIf the aforementioned import is in fact not needed, then it should be deleted.\n", "before_files": [{"content": "# Copyright 2014 Google Inc. All Rights Reserved.\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n\n#     http://www.apache.org/licenses/LICENSE-2.0\n\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Monitors provide a mechanism for periodically collecting a measurement.\n\nMonitors are implemented similar to phase functions - they are decorated\nwith plugs.plug() to pass plugs in.  The return value of a monitor\nfunction, however, will be used to append a value to a measurement.\n\nMonitors by default poll at a rate of 1 second between invocations of\nthe monitor function.  The poll interval (given in milliseconds) determines the\napproximate frequency at which values will be sampled.  A sample is considered\nto have been taken at the time when the monitor function *returns*, not when\nit is called.\n\nThe approximate average duration of calls to the monitor function is taken into\naccount, so that samples are obtained on as close to interval_ms boundaries as\ncan be.  A poll interval of 0 will cause the monitor function to be called in a\ntight loop with no delays.\n\nExample:\n\n@plugs.plug(current_meter=current_meter.CurrentMeter)\ndef CurrentMonitor(test, current_meter):\n  return current_meter.GetReading()\n\n@monitors.monitors('current_draw', CurrentMonitor, units=units.AMPERE)\ndef MyPhase(test):\n  # Do some stuff for a while...\n\n# MyPhase will have a dimensioned measurement on it, with units of 'AMPERE' and\n# a single dimension of 'MILLISECONDS', and will have values for roughly every\n# second while MyPhase was executing.\n\"\"\"\n\nimport functools\nimport inspect\nimport time\nfrom typing import Any, Callable, Dict, Optional, Text\n\nimport openhtf\nfrom openhtf import plugs\nfrom openhtf.core import measurements\nfrom openhtf.core import phase_descriptor\nfrom openhtf.core import test_state as core_test_state\nfrom openhtf.util import threads\nfrom openhtf.util import units as uom\nimport six\n\n\nclass _MonitorThread(threads.KillableThread):\n  \"\"\"Background thread that runs a monitor.\"\"\"\n\n  daemon = True\n\n  def __init__(self, measurement_name: Text,\n               monitor_desc: phase_descriptor.PhaseDescriptor,\n               extra_kwargs: Dict[Any, Any],\n               test_state: core_test_state.TestState, interval_ms: int):\n    super(_MonitorThread,\n          self).__init__(name='%s_MonitorThread' % measurement_name)\n    self.measurement_name = measurement_name\n    self.monitor_desc = monitor_desc\n    self.test_state = test_state\n    self.interval_ms = interval_ms\n    self.extra_kwargs = extra_kwargs\n\n  def get_value(self) -> Any:\n    argspec = inspect.getfullargspec(self.monitor_desc.func)\n    argspec_args = argspec.args\n    argspec_keywords = argspec.varkw\n    if argspec_keywords:\n      # Monitor phase takes **kwargs, so just pass everything in.\n      kwargs = self.extra_kwargs\n    else:\n      # Only pass in args that the monitor phase takes.\n      kwargs = {\n          arg: val for arg, val in self.extra_kwargs if arg in argspec_args\n      }\n    return self.monitor_desc.with_args(**kwargs)(self.test_state)\n\n  def _thread_proc(self):\n    measurement = getattr(self.test_state.test_api.measurements,\n                          self.measurement_name)\n    start_time = time.time()\n\n    # Special case tight-loop monitoring.\n    if not self.interval_ms:\n      while True:\n        measurement[(time.time() - start_time) * 1000] = self.get_value()\n\n    # Helper to take sample, return sample number and sample duration.\n    def _take_sample():\n      pre_time, value, post_time = time.time(), self.get_value(), time.time()\n      measurement[(post_time - start_time) * 1000] = value\n      return (int((post_time - start_time) * 1000 / self.interval_ms),\n              (post_time - pre_time) * 1000)\n\n    # Track the last sample number, and an approximation of the mean time\n    # it takes to sample (so we can account for it in how long we sleep).\n    last_sample, mean_sample_ms = _take_sample()\n    while True:\n      # Find what sample number (float) we would be on if we sampled now.\n      current_time = time.time()\n      new_sample = ((((current_time - start_time) * 1000) + mean_sample_ms) /\n                    self.interval_ms)\n      if new_sample < last_sample + 1:\n        time.sleep(start_time - current_time +\n                   ((last_sample + 1) * self.interval_ms / 1000.0) -\n                   (mean_sample_ms / 1000.0))\n        continue\n      elif new_sample > last_sample + 2:\n        self.test_state.state_logger.warning(\n            'Monitor for \"%s\" skipping %s sample(s).', self.measurement_name,\n            new_sample - last_sample - 1)\n      last_sample, cur_sample_ms = _take_sample()\n      # Approximate 10-element sliding window average.\n      mean_sample_ms = ((9 * mean_sample_ms) + cur_sample_ms) / 10.0\n\n\ndef monitors(\n    measurement_name: Text,\n    monitor_func: phase_descriptor.PhaseT,\n    units: Optional[uom.UnitDescriptor] = None,\n    poll_interval_ms: int = 1000\n) -> Callable[[phase_descriptor.PhaseT], phase_descriptor.PhaseDescriptor]:\n  \"\"\"Returns a decorator that wraps a phase with a monitor.\"\"\"\n  monitor_desc = openhtf.PhaseDescriptor.wrap_or_copy(monitor_func)\n\n  def wrapper(\n      phase_func: phase_descriptor.PhaseT) -> phase_descriptor.PhaseDescriptor:\n    phase_desc = openhtf.PhaseDescriptor.wrap_or_copy(phase_func)\n\n    # Re-key this dict so we don't have to worry about collisions with\n    # plug.plug() decorators on the phase function.  Since we aren't\n    # updating kwargs here, we don't have to worry about collisions with\n    # kwarg names.\n    monitor_plugs = {('_' * idx) + measurement_name + '_monitor': plug.cls\n                     for idx, plug in enumerate(monitor_desc.plugs, start=1)}\n\n    @openhtf.PhaseOptions(requires_state=True)\n    @plugs.plug(update_kwargs=False, **monitor_plugs)\n    @openhtf.measures(\n        measurements.Measurement(measurement_name).with_units(\n            units).with_dimensions(uom.MILLISECOND))\n    @functools.wraps(phase_desc.func)\n    def monitored_phase_func(test_state, *args, **kwargs):\n      # Start monitor thread, it will run monitor_desc periodically.\n      monitor_thread = _MonitorThread(measurement_name, monitor_desc,\n                                      phase_desc.extra_kwargs, test_state,\n                                      poll_interval_ms)\n      monitor_thread.start()\n      try:\n        return phase_desc(test_state, *args, **kwargs)\n      finally:\n        monitor_thread.kill()\n        monitor_thread.join()\n\n    return monitored_phase_func\n\n  return wrapper\n", "path": "openhtf/core/monitors.py"}], "after_files": [{"content": "# Copyright 2014 Google Inc. All Rights Reserved.\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n\n#     http://www.apache.org/licenses/LICENSE-2.0\n\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Monitors provide a mechanism for periodically collecting a measurement.\n\nMonitors are implemented similar to phase functions - they are decorated\nwith plugs.plug() to pass plugs in.  The return value of a monitor\nfunction, however, will be used to append a value to a measurement.\n\nMonitors by default poll at a rate of 1 second between invocations of\nthe monitor function.  The poll interval (given in milliseconds) determines the\napproximate frequency at which values will be sampled.  A sample is considered\nto have been taken at the time when the monitor function *returns*, not when\nit is called.\n\nThe approximate average duration of calls to the monitor function is taken into\naccount, so that samples are obtained on as close to interval_ms boundaries as\ncan be.  A poll interval of 0 will cause the monitor function to be called in a\ntight loop with no delays.\n\nExample:\n\n@plugs.plug(current_meter=current_meter.CurrentMeter)\ndef CurrentMonitor(test, current_meter):\n  return current_meter.GetReading()\n\n@monitors.monitors('current_draw', CurrentMonitor, units=units.AMPERE)\ndef MyPhase(test):\n  # Do some stuff for a while...\n\n# MyPhase will have a dimensioned measurement on it, with units of 'AMPERE' and\n# a single dimension of 'MILLISECONDS', and will have values for roughly every\n# second while MyPhase was executing.\n\"\"\"\n\nimport functools\nimport inspect\nimport time\nfrom typing import Any, Callable, Dict, Optional, Text\n\nimport openhtf\nfrom openhtf import plugs\nfrom openhtf.core import measurements\nfrom openhtf.core import phase_descriptor\nfrom openhtf.core import test_state as core_test_state\nfrom openhtf.util import threads\nfrom openhtf.util import units as uom\n\n\nclass _MonitorThread(threads.KillableThread):\n  \"\"\"Background thread that runs a monitor.\"\"\"\n\n  daemon = True\n\n  def __init__(self, measurement_name: Text,\n               monitor_desc: phase_descriptor.PhaseDescriptor,\n               extra_kwargs: Dict[Any, Any],\n               test_state: core_test_state.TestState, interval_ms: int):\n    super(_MonitorThread,\n          self).__init__(name='%s_MonitorThread' % measurement_name)\n    self.measurement_name = measurement_name\n    self.monitor_desc = monitor_desc\n    self.test_state = test_state\n    self.interval_ms = interval_ms\n    self.extra_kwargs = extra_kwargs\n\n  def get_value(self) -> Any:\n    argspec = inspect.getfullargspec(self.monitor_desc.func)\n    argspec_args = argspec.args\n    argspec_keywords = argspec.varkw\n    if argspec_keywords:\n      # Monitor phase takes **kwargs, so just pass everything in.\n      kwargs = self.extra_kwargs\n    else:\n      # Only pass in args that the monitor phase takes.\n      kwargs = {\n          arg: val for arg, val in self.extra_kwargs if arg in argspec_args\n      }\n    return self.monitor_desc.with_args(**kwargs)(self.test_state)\n\n  def _thread_proc(self):\n    measurement = getattr(self.test_state.test_api.measurements,\n                          self.measurement_name)\n    start_time = time.time()\n\n    # Special case tight-loop monitoring.\n    if not self.interval_ms:\n      while True:\n        measurement[(time.time() - start_time) * 1000] = self.get_value()\n\n    # Helper to take sample, return sample number and sample duration.\n    def _take_sample():\n      pre_time, value, post_time = time.time(), self.get_value(), time.time()\n      measurement[(post_time - start_time) * 1000] = value\n      return (int((post_time - start_time) * 1000 / self.interval_ms),\n              (post_time - pre_time) * 1000)\n\n    # Track the last sample number, and an approximation of the mean time\n    # it takes to sample (so we can account for it in how long we sleep).\n    last_sample, mean_sample_ms = _take_sample()\n    while True:\n      # Find what sample number (float) we would be on if we sampled now.\n      current_time = time.time()\n      new_sample = ((((current_time - start_time) * 1000) + mean_sample_ms) /\n                    self.interval_ms)\n      if new_sample < last_sample + 1:\n        time.sleep(start_time - current_time +\n                   ((last_sample + 1) * self.interval_ms / 1000.0) -\n                   (mean_sample_ms / 1000.0))\n        continue\n      elif new_sample > last_sample + 2:\n        self.test_state.state_logger.warning(\n            'Monitor for \"%s\" skipping %s sample(s).', self.measurement_name,\n            new_sample - last_sample - 1)\n      last_sample, cur_sample_ms = _take_sample()\n      # Approximate 10-element sliding window average.\n      mean_sample_ms = ((9 * mean_sample_ms) + cur_sample_ms) / 10.0\n\n\ndef monitors(\n    measurement_name: Text,\n    monitor_func: phase_descriptor.PhaseT,\n    units: Optional[uom.UnitDescriptor] = None,\n    poll_interval_ms: int = 1000\n) -> Callable[[phase_descriptor.PhaseT], phase_descriptor.PhaseDescriptor]:\n  \"\"\"Returns a decorator that wraps a phase with a monitor.\"\"\"\n  monitor_desc = openhtf.PhaseDescriptor.wrap_or_copy(monitor_func)\n\n  def wrapper(\n      phase_func: phase_descriptor.PhaseT) -> phase_descriptor.PhaseDescriptor:\n    phase_desc = openhtf.PhaseDescriptor.wrap_or_copy(phase_func)\n\n    # Re-key this dict so we don't have to worry about collisions with\n    # plug.plug() decorators on the phase function.  Since we aren't\n    # updating kwargs here, we don't have to worry about collisions with\n    # kwarg names.\n    monitor_plugs = {('_' * idx) + measurement_name + '_monitor': plug.cls\n                     for idx, plug in enumerate(monitor_desc.plugs, start=1)}\n\n    @openhtf.PhaseOptions(requires_state=True)\n    @plugs.plug(update_kwargs=False, **monitor_plugs)\n    @openhtf.measures(\n        measurements.Measurement(measurement_name).with_units(\n            units).with_dimensions(uom.MILLISECOND))\n    @functools.wraps(phase_desc.func)\n    def monitored_phase_func(test_state, *args, **kwargs):\n      # Start monitor thread, it will run monitor_desc periodically.\n      monitor_thread = _MonitorThread(measurement_name, monitor_desc,\n                                      phase_desc.extra_kwargs, test_state,\n                                      poll_interval_ms)\n      monitor_thread.start()\n      try:\n        return phase_desc(test_state, *args, **kwargs)\n      finally:\n        monitor_thread.kill()\n        monitor_thread.join()\n\n    return monitored_phase_func\n\n  return wrapper\n", "path": "openhtf/core/monitors.py"}]}