prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Keithley 2400 does not get added to the station cleanly
  The ":read:" command and possibly others does not work when output is off but fails with an error. This is called when getting volt and current are snapshotted 
  
  We should wrap these calls in checking that output is off
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `qcodes/instrument_drivers/tektronix/Keithley_2400.py`
  Content:
  ```
  1 from qcodes import VisaInstrument
  2 from qcodes.utils.validators import Strings, Enum
  3 
  4 
  5 class Keithley_2400(VisaInstrument):
  6     """
  7     QCoDeS driver for the Keithley 2400 voltage source.
  8     """
  9     def __init__(self, name, address, **kwargs):
  10         super().__init__(name, address, terminator='\n', **kwargs)
  11 
  12         self.add_parameter('rangev',
  13                            get_cmd='SENS:VOLT:RANG?',
  14                            get_parser=float,
  15                            set_cmd='SOUR:VOLT:RANG {:f}',
  16                            label='Voltage range')
  17 
  18         self.add_parameter('rangei',
  19                            get_cmd='SENS:CURR:RANG?',
  20                            get_parser=float,
  21                            set_cmd='SOUR:CURR:RANG {:f}',
  22                            label='Current range')
  23 
  24         self.add_parameter('compliancev',
  25                            get_cmd='SENS:VOLT:PROT?',
  26                            get_parser=float,
  27                            set_cmd='SENS:VOLT:PROT {:f}',
  28                            label='Voltage Compliance')
  29 
  30         self.add_parameter('compliancei',
  31                            get_cmd='SENS:CURR:PROT?',
  32                            get_parser=float,
  33                            set_cmd='SENS:CURR:PROT {:f}',
  34                            label='Current Compliance')
  35 
  36         self.add_parameter('volt',
  37                            get_cmd=':READ?',
  38                            get_parser=self._volt_parser,
  39                            set_cmd=':SOUR:VOLT:LEV {:.8f}',
  40                            label='Voltage',
  41                            unit='V')
  42 
  43         self.add_parameter('curr',
  44                            get_cmd=':READ?',
  45                            get_parser=self._curr_parser,
  46                            set_cmd=':SOUR:CURR:LEV {:.8f}',
  47                            label='Current',
  48                            unit='A')
  49 
  50         self.add_parameter('mode',
  51                            vals=Enum('VOLT', 'CURR'),
  52                            get_cmd=':SOUR:FUNC?',
  53                            set_cmd=self._set_mode_and_sense,
  54                            label='Mode')
  55 
  56         self.add_parameter('sense',
  57                            vals=Strings(),
  58                            get_cmd=':SENS:FUNC?',
  59                            set_cmd=':SENS:FUNC "{:s}"',
  60                            label='Sense mode')
  61 
  62         self.add_parameter('output',
  63                            get_parser=int,
  64                            set_cmd=':OUTP:STAT {:d}',
  65                            get_cmd=':OUTP:STAT?')
  66 
  67         self.add_parameter('nplcv',
  68                            get_cmd='SENS:VOLT:NPLC?',
  69                            get_parser=float,
  70                            set_cmd='SENS:VOLT:NPLC {:f}',
  71                            label='Voltage integration time')
  72 
  73         self.add_parameter('nplci',
  74                            get_cmd='SENS:CURR:NPLC?',
  75                            get_parser=float,
  76                            set_cmd='SENS:CURR:NPLC {:f}',
  77                            label='Current integration time')
  78 
  79         self.add_parameter('resistance',
  80                            get_cmd=':READ?',
  81                            get_parser=self._resistance_parser,
  82                            label='Resistance',
  83                            unit='Ohm')
  84 
  85     def _set_mode_and_sense(self, msg):
  86         # This helps set the correct read out curr/volt
  87         if msg == 'VOLT':
  88             self.sense('CURR')
  89         elif msg == 'CURR':
  90             self.sense('VOLT')
  91         else:
  92             raise AttributeError('Mode does not exist')
  93         self.write(':SOUR:FUNC {:s}'.format(msg))
  94 
  95     def reset(self):
  96         """
  97         Reset the instrument. When the instrument is reset, it performs the
  98         following actions.
  99 
  100             Returns the SourceMeter to the GPIB default conditions.
  101 
  102             Cancels all pending commands.
  103 
  104             Cancels all previously send `*OPC` and `*OPC?`
  105         """
  106         self.write(':*RST')
  107 
  108     def _volt_parser(self, msg):
  109         fields = [float(x) for x in msg.split(',')]
  110         return fields[0]
  111 
  112     def _curr_parser(self, msg):
  113         fields = [float(x) for x in msg.split(',')]
  114         return fields[1]
  115 
  116     def _resistance_parser(self, msg):
  117         fields = [float(x) for x in msg.split(',')]
  118         return fields[0]/fields[1]
  119
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/qcodes/instrument_drivers/tektronix/Keithley_2400.py b/qcodes/instrument_drivers/tektronix/Keithley_2400.py
  --- a/qcodes/instrument_drivers/tektronix/Keithley_2400.py
  +++ b/qcodes/instrument_drivers/tektronix/Keithley_2400.py
  @@ -34,18 +34,31 @@
                              label='Current Compliance')
   
           self.add_parameter('volt',
  -                           get_cmd=':READ?',
  +                           get_cmd=self._get_read_output_protected,
                              get_parser=self._volt_parser,
                              set_cmd=':SOUR:VOLT:LEV {:.8f}',
                              label='Voltage',
  -                           unit='V')
  +                           unit='V',
  +                           docstring="Sets voltage in 'VOLT' mode. "
  +                                     "Get returns measured voltage if "
  +                                     "sensing 'VOLT' otherwise it returns "
  +                                     "setpoint value. "
  +                                     "Note that it is an error to read voltage with "
  +                                     "output off")
   
           self.add_parameter('curr',
  -                           get_cmd=':READ?',
  +                           get_cmd=self._get_read_output_protected,
                              get_parser=self._curr_parser,
                              set_cmd=':SOUR:CURR:LEV {:.8f}',
                              label='Current',
  -                           unit='A')
  +                           unit='A',
  +                           docstring = "Sets current in 'CURR' mode. "
  +                                        "Get returns measured current if "
  +                                        "sensing 'CURR' otherwise it returns "
  +                                        "setpoint value. "
  +                                        "Note that it is an error to read current with "
  +                                        "output off")
  +
   
           self.add_parameter('mode',
                              vals=Enum('VOLT', 'CURR'),
  @@ -77,10 +90,32 @@
                              label='Current integration time')
   
           self.add_parameter('resistance',
  -                           get_cmd=':READ?',
  +                           get_cmd=self._get_read_output_protected,
                              get_parser=self._resistance_parser,
                              label='Resistance',
  -                           unit='Ohm')
  +                           unit='Ohm',
  +                           docstring="Measure resistance from current and voltage "
  +                                     "Note that it is an error to read current "
  +                                     "and voltage with output off")
  +
  +    def _get_read_output_protected(self) -> str:
  +        """
  +        This wrapper function around ":READ?" exists because calling
  +        ":READ?" on an instrument with output disabled is an error.
  +        So first we check that output is on and if not we return
  +        nan for volt, curr etc.
  +        """
  +        output = self.output.get_latest()
  +        if output is None:
  +            # if get_latest returns None we have
  +            # to ask the instrument for the status of output
  +            output = self.output.get()
  +
  +        if output == 1:
  +            msg = self.ask(':READ?')
  +        else:
  +            raise RuntimeError("Cannot perform read with output off")
  +        return msg
   
       def _set_mode_and_sense(self, msg):
           # This helps set the correct read out curr/volt
  @@ -115,4 +150,5 @@
   
       def _resistance_parser(self, msg):
           fields = [float(x) for x in msg.split(',')]
  -        return fields[0]/fields[1]
  +        res = fields[0] / fields[1]
  +        return res
  
verification_info: {"golden_diff": "diff --git a/qcodes/instrument_drivers/tektronix/Keithley_2400.py b/qcodes/instrument_drivers/tektronix/Keithley_2400.py\n--- a/qcodes/instrument_drivers/tektronix/Keithley_2400.py\n+++ b/qcodes/instrument_drivers/tektronix/Keithley_2400.py\n@@ -34,18 +34,31 @@\n                            label='Current Compliance')\n \n         self.add_parameter('volt',\n-                           get_cmd=':READ?',\n+                           get_cmd=self._get_read_output_protected,\n                            get_parser=self._volt_parser,\n                            set_cmd=':SOUR:VOLT:LEV {:.8f}',\n                            label='Voltage',\n-                           unit='V')\n+                           unit='V',\n+                           docstring=\"Sets voltage in 'VOLT' mode. \"\n+                                     \"Get returns measured voltage if \"\n+                                     \"sensing 'VOLT' otherwise it returns \"\n+                                     \"setpoint value. \"\n+                                     \"Note that it is an error to read voltage with \"\n+                                     \"output off\")\n \n         self.add_parameter('curr',\n-                           get_cmd=':READ?',\n+                           get_cmd=self._get_read_output_protected,\n                            get_parser=self._curr_parser,\n                            set_cmd=':SOUR:CURR:LEV {:.8f}',\n                            label='Current',\n-                           unit='A')\n+                           unit='A',\n+                           docstring = \"Sets current in 'CURR' mode. \"\n+                                        \"Get returns measured current if \"\n+                                        \"sensing 'CURR' otherwise it returns \"\n+                                        \"setpoint value. \"\n+                                        \"Note that it is an error to read current with \"\n+                                        \"output off\")\n+\n \n         self.add_parameter('mode',\n                            vals=Enum('VOLT', 'CURR'),\n@@ -77,10 +90,32 @@\n                            label='Current integration time')\n \n         self.add_parameter('resistance',\n-                           get_cmd=':READ?',\n+                           get_cmd=self._get_read_output_protected,\n                            get_parser=self._resistance_parser,\n                            label='Resistance',\n-                           unit='Ohm')\n+                           unit='Ohm',\n+                           docstring=\"Measure resistance from current and voltage \"\n+                                     \"Note that it is an error to read current \"\n+                                     \"and voltage with output off\")\n+\n+    def _get_read_output_protected(self) -> str:\n+        \"\"\"\n+        This wrapper function around \":READ?\" exists because calling\n+        \":READ?\" on an instrument with output disabled is an error.\n+        So first we check that output is on and if not we return\n+        nan for volt, curr etc.\n+        \"\"\"\n+        output = self.output.get_latest()\n+        if output is None:\n+            # if get_latest returns None we have\n+            # to ask the instrument for the status of output\n+            output = self.output.get()\n+\n+        if output == 1:\n+            msg = self.ask(':READ?')\n+        else:\n+            raise RuntimeError(\"Cannot perform read with output off\")\n+        return msg\n \n     def _set_mode_and_sense(self, msg):\n         # This helps set the correct read out curr/volt\n@@ -115,4 +150,5 @@\n \n     def _resistance_parser(self, msg):\n         fields = [float(x) for x in msg.split(',')]\n-        return fields[0]/fields[1]\n+        res = fields[0] / fields[1]\n+        return res\n", "issue": "Keithley 2400 does not get added to the station cleanly\nThe \":read:\" command and possibly others does not work when output is off but fails with an error. This is called when getting volt and current are snapshotted \r\n\r\nWe should wrap these calls in checking that output is off\n", "before_files": [{"content": "from qcodes import VisaInstrument\nfrom qcodes.utils.validators import Strings, Enum\n\n\nclass Keithley_2400(VisaInstrument):\n    \"\"\"\n    QCoDeS driver for the Keithley 2400 voltage source.\n    \"\"\"\n    def __init__(self, name, address, **kwargs):\n        super().__init__(name, address, terminator='\\n', **kwargs)\n\n        self.add_parameter('rangev',\n                           get_cmd='SENS:VOLT:RANG?',\n                           get_parser=float,\n                           set_cmd='SOUR:VOLT:RANG {:f}',\n                           label='Voltage range')\n\n        self.add_parameter('rangei',\n                           get_cmd='SENS:CURR:RANG?',\n                           get_parser=float,\n                           set_cmd='SOUR:CURR:RANG {:f}',\n                           label='Current range')\n\n        self.add_parameter('compliancev',\n                           get_cmd='SENS:VOLT:PROT?',\n                           get_parser=float,\n                           set_cmd='SENS:VOLT:PROT {:f}',\n                           label='Voltage Compliance')\n\n        self.add_parameter('compliancei',\n                           get_cmd='SENS:CURR:PROT?',\n                           get_parser=float,\n                           set_cmd='SENS:CURR:PROT {:f}',\n                           label='Current Compliance')\n\n        self.add_parameter('volt',\n                           get_cmd=':READ?',\n                           get_parser=self._volt_parser,\n                           set_cmd=':SOUR:VOLT:LEV {:.8f}',\n                           label='Voltage',\n                           unit='V')\n\n        self.add_parameter('curr',\n                           get_cmd=':READ?',\n                           get_parser=self._curr_parser,\n                           set_cmd=':SOUR:CURR:LEV {:.8f}',\n                           label='Current',\n                           unit='A')\n\n        self.add_parameter('mode',\n                           vals=Enum('VOLT', 'CURR'),\n                           get_cmd=':SOUR:FUNC?',\n                           set_cmd=self._set_mode_and_sense,\n                           label='Mode')\n\n        self.add_parameter('sense',\n                           vals=Strings(),\n                           get_cmd=':SENS:FUNC?',\n                           set_cmd=':SENS:FUNC \"{:s}\"',\n                           label='Sense mode')\n\n        self.add_parameter('output',\n                           get_parser=int,\n                           set_cmd=':OUTP:STAT {:d}',\n                           get_cmd=':OUTP:STAT?')\n\n        self.add_parameter('nplcv',\n                           get_cmd='SENS:VOLT:NPLC?',\n                           get_parser=float,\n                           set_cmd='SENS:VOLT:NPLC {:f}',\n                           label='Voltage integration time')\n\n        self.add_parameter('nplci',\n                           get_cmd='SENS:CURR:NPLC?',\n                           get_parser=float,\n                           set_cmd='SENS:CURR:NPLC {:f}',\n                           label='Current integration time')\n\n        self.add_parameter('resistance',\n                           get_cmd=':READ?',\n                           get_parser=self._resistance_parser,\n                           label='Resistance',\n                           unit='Ohm')\n\n    def _set_mode_and_sense(self, msg):\n        # This helps set the correct read out curr/volt\n        if msg == 'VOLT':\n            self.sense('CURR')\n        elif msg == 'CURR':\n            self.sense('VOLT')\n        else:\n            raise AttributeError('Mode does not exist')\n        self.write(':SOUR:FUNC {:s}'.format(msg))\n\n    def reset(self):\n        \"\"\"\n        Reset the instrument. When the instrument is reset, it performs the\n        following actions.\n\n            Returns the SourceMeter to the GPIB default conditions.\n\n            Cancels all pending commands.\n\n            Cancels all previously send `*OPC` and `*OPC?`\n        \"\"\"\n        self.write(':*RST')\n\n    def _volt_parser(self, msg):\n        fields = [float(x) for x in msg.split(',')]\n        return fields[0]\n\n    def _curr_parser(self, msg):\n        fields = [float(x) for x in msg.split(',')]\n        return fields[1]\n\n    def _resistance_parser(self, msg):\n        fields = [float(x) for x in msg.split(',')]\n        return fields[0]/fields[1]\n", "path": "qcodes/instrument_drivers/tektronix/Keithley_2400.py"}], "after_files": [{"content": "from qcodes import VisaInstrument\nfrom qcodes.utils.validators import Strings, Enum\n\n\nclass Keithley_2400(VisaInstrument):\n    \"\"\"\n    QCoDeS driver for the Keithley 2400 voltage source.\n    \"\"\"\n    def __init__(self, name, address, **kwargs):\n        super().__init__(name, address, terminator='\\n', **kwargs)\n\n        self.add_parameter('rangev',\n                           get_cmd='SENS:VOLT:RANG?',\n                           get_parser=float,\n                           set_cmd='SOUR:VOLT:RANG {:f}',\n                           label='Voltage range')\n\n        self.add_parameter('rangei',\n                           get_cmd='SENS:CURR:RANG?',\n                           get_parser=float,\n                           set_cmd='SOUR:CURR:RANG {:f}',\n                           label='Current range')\n\n        self.add_parameter('compliancev',\n                           get_cmd='SENS:VOLT:PROT?',\n                           get_parser=float,\n                           set_cmd='SENS:VOLT:PROT {:f}',\n                           label='Voltage Compliance')\n\n        self.add_parameter('compliancei',\n                           get_cmd='SENS:CURR:PROT?',\n                           get_parser=float,\n                           set_cmd='SENS:CURR:PROT {:f}',\n                           label='Current Compliance')\n\n        self.add_parameter('volt',\n                           get_cmd=self._get_read_output_protected,\n                           get_parser=self._volt_parser,\n                           set_cmd=':SOUR:VOLT:LEV {:.8f}',\n                           label='Voltage',\n                           unit='V',\n                           docstring=\"Sets voltage in 'VOLT' mode. \"\n                                     \"Get returns measured voltage if \"\n                                     \"sensing 'VOLT' otherwise it returns \"\n                                     \"setpoint value. \"\n                                     \"Note that it is an error to read voltage with \"\n                                     \"output off\")\n\n        self.add_parameter('curr',\n                           get_cmd=self._get_read_output_protected,\n                           get_parser=self._curr_parser,\n                           set_cmd=':SOUR:CURR:LEV {:.8f}',\n                           label='Current',\n                           unit='A',\n                           docstring = \"Sets current in 'CURR' mode. \"\n                                        \"Get returns measured current if \"\n                                        \"sensing 'CURR' otherwise it returns \"\n                                        \"setpoint value. \"\n                                        \"Note that it is an error to read current with \"\n                                        \"output off\")\n\n\n        self.add_parameter('mode',\n                           vals=Enum('VOLT', 'CURR'),\n                           get_cmd=':SOUR:FUNC?',\n                           set_cmd=self._set_mode_and_sense,\n                           label='Mode')\n\n        self.add_parameter('sense',\n                           vals=Strings(),\n                           get_cmd=':SENS:FUNC?',\n                           set_cmd=':SENS:FUNC \"{:s}\"',\n                           label='Sense mode')\n\n        self.add_parameter('output',\n                           get_parser=int,\n                           set_cmd=':OUTP:STAT {:d}',\n                           get_cmd=':OUTP:STAT?')\n\n        self.add_parameter('nplcv',\n                           get_cmd='SENS:VOLT:NPLC?',\n                           get_parser=float,\n                           set_cmd='SENS:VOLT:NPLC {:f}',\n                           label='Voltage integration time')\n\n        self.add_parameter('nplci',\n                           get_cmd='SENS:CURR:NPLC?',\n                           get_parser=float,\n                           set_cmd='SENS:CURR:NPLC {:f}',\n                           label='Current integration time')\n\n        self.add_parameter('resistance',\n                           get_cmd=self._get_read_output_protected,\n                           get_parser=self._resistance_parser,\n                           label='Resistance',\n                           unit='Ohm',\n                           docstring=\"Measure resistance from current and voltage \"\n                                     \"Note that it is an error to read current \"\n                                     \"and voltage with output off\")\n\n    def _get_read_output_protected(self) -> str:\n        \"\"\"\n        This wrapper function around \":READ?\" exists because calling\n        \":READ?\" on an instrument with output disabled is an error.\n        So first we check that output is on and if not we return\n        nan for volt, curr etc.\n        \"\"\"\n        output = self.output.get_latest()\n        if output is None:\n            # if get_latest returns None we have\n            # to ask the instrument for the status of output\n            output = self.output.get()\n\n        if output == 1:\n            msg = self.ask(':READ?')\n        else:\n            raise RuntimeError(\"Cannot perform read with output off\")\n        return msg\n\n    def _set_mode_and_sense(self, msg):\n        # This helps set the correct read out curr/volt\n        if msg == 'VOLT':\n            self.sense('CURR')\n        elif msg == 'CURR':\n            self.sense('VOLT')\n        else:\n            raise AttributeError('Mode does not exist')\n        self.write(':SOUR:FUNC {:s}'.format(msg))\n\n    def reset(self):\n        \"\"\"\n        Reset the instrument. When the instrument is reset, it performs the\n        following actions.\n\n            Returns the SourceMeter to the GPIB default conditions.\n\n            Cancels all pending commands.\n\n            Cancels all previously send `*OPC` and `*OPC?`\n        \"\"\"\n        self.write(':*RST')\n\n    def _volt_parser(self, msg):\n        fields = [float(x) for x in msg.split(',')]\n        return fields[0]\n\n    def _curr_parser(self, msg):\n        fields = [float(x) for x in msg.split(',')]\n        return fields[1]\n\n    def _resistance_parser(self, msg):\n        fields = [float(x) for x in msg.split(',')]\n        res = fields[0] / fields[1]\n        return res\n", "path": "qcodes/instrument_drivers/tektronix/Keithley_2400.py"}]}