We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
IPInstrument._send() could not send all its data
I was browsing the instruments code and found out that in the `IPInstrument` class the `socket.send(...)` function is implemented wrongly:

```python
    def _send(self, cmd):
        data = cmd + self._terminator
        self._socket.send(data.encode())
```

This is what the documentation says about `socket.send(...)`:

> socket.send(bytes[, flags])
Send data to the socket. The socket must be connected to a remote socket. The optional flags argument has the same meaning as for recv() above. Returns the number of bytes sent. Applications are responsible for checking that all data has been sent; if only some of the data was transmitted, the application needs to attempt delivery of the remaining data. 
https://docs.python.org/3.6/library/socket.html

At this moment, if `send(...)` fails, only a part of the message is transmitted. Which will create strange bugs.

A better solution is to use `socket.sendall(...)` or as the example shows:
```python
    def mysend(self, msg):
        totalsent = 0
        while totalsent < MSGLEN:
            sent = self.sock.send(msg[totalsent:])
            if sent == 0:
                raise RuntimeError("socket connection broken")
            totalsent = totalsent + sent
```
https://docs.python.org/3.6/howto/sockets.html#socket-howto
IPInstrument._send() could not send all its data
I was browsing the instruments code and found out that in the `IPInstrument` class the `socket.send(...)` function is implemented wrongly:

```python
    def _send(self, cmd):
        data = cmd + self._terminator
        self._socket.send(data.encode())
```

This is what the documentation says about `socket.send(...)`:

> socket.send(bytes[, flags])
Send data to the socket. The socket must be connected to a remote socket. The optional flags argument has the same meaning as for recv() above. Returns the number of bytes sent. Applications are responsible for checking that all data has been sent; if only some of the data was transmitted, the application needs to attempt delivery of the remaining data. 
https://docs.python.org/3.6/library/socket.html

At this moment, if `send(...)` fails, only a part of the message is transmitted. Which will create strange bugs.

A better solution is to use `socket.sendall(...)` or as the example shows:
```python
    def mysend(self, msg):
        totalsent = 0
        while totalsent < MSGLEN:
            sent = self.sock.send(msg[totalsent:])
            if sent == 0:
                raise RuntimeError("socket connection broken")
            totalsent = totalsent + sent
```
https://docs.python.org/3.6/howto/sockets.html#socket-howto

--- 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/ip.py`
Content:
```
1 """Ethernet instrument driver class based on sockets."""
2 import socket
3 
4 from .base import Instrument
5 
6 
7 class IPInstrument(Instrument):
8 
9     r"""
10     Bare socket ethernet instrument implementation.
11 
12     Args:
13         name (str): What this instrument is called locally.
14 
15         address (Optional[str]): The IP address or name. If not given on
16             construction, must be provided before any communication.
17 
18         port (Optional[int]): The IP port. If not given on construction, must
19             be provided before any communication.
20 
21         timeout (number): Seconds to allow for responses. Default 5.
22 
23         terminator (str): Character(s) to terminate each send. Default '\n'.
24 
25         persistent (bool): Whether to leave the socket open between calls.
26             Default True.
27 
28         write_confirmation (bool): Whether the instrument acknowledges writes
29             with some response we should read. Default True.
30 
31         metadata (Optional[Dict]): additional static metadata to add to this
32             instrument's JSON snapshot.
33 
34     See help for ``qcodes.Instrument`` for additional information on writing
35     instrument subclasses.
36     """
37 
38     def __init__(self, name, address=None, port=None, timeout=5,
39                  terminator='\n', persistent=True, write_confirmation=True, testing=False,
40                  **kwargs):
41         super().__init__(name, testing=testing, **kwargs)
42 
43         self._address = address
44         self._port = port
45         self._timeout = timeout
46         self._terminator = terminator
47         self._confirmation = write_confirmation
48 
49         self._ensure_connection = EnsureConnection(self)
50         self._buffer_size = 1400
51 
52         self._socket = None
53 
54         self.set_persistent(persistent)
55 
56     def set_address(self, address=None, port=None):
57         """
58         Change the IP address and/or port of this instrument.
59 
60         Args:
61             address (Optional[str]): The IP address or name.
62             port (Optional[number]): The IP port.
63         """
64         if address is not None:
65             self._address = address
66         elif not hasattr(self, '_address'):
67             raise TypeError('This instrument doesn\'t have an address yet, '
68                             'you must provide one.')
69         if port is not None:
70             self._port = port
71         elif not hasattr(self, '_port'):
72             raise TypeError('This instrument doesn\'t have a port yet, '
73                             'you must provide one.')
74 
75         self._disconnect()
76         self.set_persistent(self._persistent)
77 
78     def set_persistent(self, persistent):
79         """
80         Change whether this instrument keeps its socket open between calls.
81 
82         Args:
83             persistent (bool): Set True to keep the socket open all the time.
84         """
85         self._persistent = persistent
86         if persistent:
87             self._connect()
88         else:
89             self._disconnect()
90 
91     def flush_connection(self):
92         if not self._testing:
93             self._recv()
94 
95     def _connect(self):
96         if self._testing:
97             return
98 
99         if self._socket is not None:
100             self._disconnect()
101 
102         try:
103             self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
104             self._socket.connect((self._address, self._port))
105             self.set_timeout(self._timeout)
106         except ConnectionRefusedError:
107             self._socket.close()
108             self._socket = None
109 
110     def _disconnect(self):
111         if getattr(self, '_socket', None) is None:
112             return
113 
114         self._socket.shutdown(socket.SHUT_RDWR)
115         self._socket.close()
116         self._socket = None
117 
118     def set_timeout(self, timeout=None):
119         """
120         Change the read timeout for the socket.
121 
122         Args:
123             timeout (number): Seconds to allow for responses.
124         """
125         self._timeout = timeout
126 
127         if self._socket is not None:
128             self._socket.settimeout(float(self._timeout))
129 
130     def set_terminator(self, terminator):
131         r"""
132         Change the write terminator to use.
133 
134         Args:
135             terminator (str): Character(s) to terminate each send.
136                 Default '\n'.
137         """
138         self._terminator = terminator
139 
140     def _send(self, cmd):
141         data = cmd + self._terminator
142         self._socket.send(data.encode())
143 
144     def _recv(self):
145         return self._socket.recv(self._buffer_size).decode()
146 
147     def close(self):
148         """Disconnect and irreversibly tear down the instrument."""
149         self._disconnect()
150         super().close()
151 
152     def write_raw(self, cmd):
153         """
154         Low-level interface to send a command that gets no response.
155 
156         Args:
157             cmd (str): The command to send to the instrument.
158         """
159 
160         with self._ensure_connection:
161             self._send(cmd)
162             if self._confirmation:
163                 self._recv()
164 
165     def ask_raw(self, cmd):
166         """
167         Low-level interface to send a command an read a response.
168 
169         Args:
170             cmd (str): The command to send to the instrument.
171 
172         Returns:
173             str: The instrument's response.
174         """
175         with self._ensure_connection:
176             self._send(cmd)
177             return self._recv()
178 
179     def __del__(self):
180         self.close()
181 
182     def snapshot_base(self, update=False):
183         """
184         State of the instrument as a JSON-compatible dict.
185 
186         Args:
187             update (bool): If True, update the state by querying the
188                 instrument. If False, just use the latest values in memory.
189 
190         Returns:
191             dict: base snapshot
192         """
193         snap = super().snapshot_base(update=update)
194 
195         snap['port'] = self._port
196         snap['confirmation'] = self._confirmation
197         snap['address'] = self._address
198         snap['terminator'] = self._terminator
199         snap['timeout'] = self._timeout
200         snap['persistent'] = self._persistent
201 
202         return snap
203 
204 
205 class EnsureConnection:
206 
207     """
208     Context manager to ensure an instrument is connected when needed.
209 
210     Uses ``instrument._persistent`` to determine whether or not to close
211     the connection immediately on completion.
212 
213     Args:
214         instrument (IPInstrument): the instance to connect.
215     """
216 
217     def __init__(self, instrument):
218         self.instrument = instrument
219 
220     def __enter__(self):
221         """Make sure we connect when entering the context."""
222         if not self.instrument._persistent or self.instrument._socket is None:
223             self.instrument._connect()
224 
225     def __exit__(self, type, value, tb):
226         """Possibly disconnect on exiting the context."""
227         if not self.instrument._persistent:
228             self.instrument._disconnect()
229
```
--- 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/qcodes/instrument/ip.py b/qcodes/instrument/ip.py
--- a/qcodes/instrument/ip.py
+++ b/qcodes/instrument/ip.py
@@ -1,8 +1,10 @@
 """Ethernet instrument driver class based on sockets."""
 import socket
+import logging
 
 from .base import Instrument
 
+log = logging.getLogger(__name__)
 
 class IPInstrument(Instrument):
 
@@ -139,10 +141,14 @@
 
     def _send(self, cmd):
         data = cmd + self._terminator
-        self._socket.send(data.encode())
+        self._socket.sendall(data.encode())
 
     def _recv(self):
-        return self._socket.recv(self._buffer_size).decode()
+        result = self._socket.recv(self._buffer_size)
+        if result == b'':
+            log.warning("Got empty response from Socket recv() "
+                        "Connection broken.")
+        return result.decode()
 
     def close(self):
         """Disconnect and irreversibly tear down the instrument."""

{"golden_diff": "diff --git a/qcodes/instrument/ip.py b/qcodes/instrument/ip.py\n--- a/qcodes/instrument/ip.py\n+++ b/qcodes/instrument/ip.py\n@@ -1,8 +1,10 @@\n \"\"\"Ethernet instrument driver class based on sockets.\"\"\"\n import socket\n+import logging\n \n from .base import Instrument\n \n+log = logging.getLogger(__name__)\n \n class IPInstrument(Instrument):\n \n@@ -139,10 +141,14 @@\n \n     def _send(self, cmd):\n         data = cmd + self._terminator\n-        self._socket.send(data.encode())\n+        self._socket.sendall(data.encode())\n \n     def _recv(self):\n-        return self._socket.recv(self._buffer_size).decode()\n+        result = self._socket.recv(self._buffer_size)\n+        if result == b'':\n+            log.warning(\"Got empty response from Socket recv() \"\n+                        \"Connection broken.\")\n+        return result.decode()\n \n     def close(self):\n         \"\"\"Disconnect and irreversibly tear down the instrument.\"\"\"\n", "issue": "IPInstrument._send() could not send all its data\nI was browsing the instruments code and found out that in the `IPInstrument` class the `socket.send(...)` function is implemented wrongly:\r\n\r\n```python\r\n    def _send(self, cmd):\r\n        data = cmd + self._terminator\r\n        self._socket.send(data.encode())\r\n```\r\n\r\nThis is what the documentation says about `socket.send(...)`:\r\n\r\n> socket.send(bytes[, flags])\r\nSend data to the socket. The socket must be connected to a remote socket. The optional flags argument has the same meaning as for recv() above. Returns the number of bytes sent. Applications are responsible for checking that all data has been sent; if only some of the data was transmitted, the application needs to attempt delivery of the remaining data. \r\nhttps://docs.python.org/3.6/library/socket.html\r\n\r\nAt this moment, if `send(...)` fails, only a part of the message is transmitted. Which will create strange bugs.\r\n\r\nA better solution is to use `socket.sendall(...)` or as the example shows:\r\n```python\r\n    def mysend(self, msg):\r\n        totalsent = 0\r\n        while totalsent < MSGLEN:\r\n            sent = self.sock.send(msg[totalsent:])\r\n            if sent == 0:\r\n                raise RuntimeError(\"socket connection broken\")\r\n            totalsent = totalsent + sent\r\n```\r\nhttps://docs.python.org/3.6/howto/sockets.html#socket-howto\nIPInstrument._send() could not send all its data\nI was browsing the instruments code and found out that in the `IPInstrument` class the `socket.send(...)` function is implemented wrongly:\r\n\r\n```python\r\n    def _send(self, cmd):\r\n        data = cmd + self._terminator\r\n        self._socket.send(data.encode())\r\n```\r\n\r\nThis is what the documentation says about `socket.send(...)`:\r\n\r\n> socket.send(bytes[, flags])\r\nSend data to the socket. The socket must be connected to a remote socket. The optional flags argument has the same meaning as for recv() above. Returns the number of bytes sent. Applications are responsible for checking that all data has been sent; if only some of the data was transmitted, the application needs to attempt delivery of the remaining data. \r\nhttps://docs.python.org/3.6/library/socket.html\r\n\r\nAt this moment, if `send(...)` fails, only a part of the message is transmitted. Which will create strange bugs.\r\n\r\nA better solution is to use `socket.sendall(...)` or as the example shows:\r\n```python\r\n    def mysend(self, msg):\r\n        totalsent = 0\r\n        while totalsent < MSGLEN:\r\n            sent = self.sock.send(msg[totalsent:])\r\n            if sent == 0:\r\n                raise RuntimeError(\"socket connection broken\")\r\n            totalsent = totalsent + sent\r\n```\r\nhttps://docs.python.org/3.6/howto/sockets.html#socket-howto\n", "before_files": [{"content": "\"\"\"Ethernet instrument driver class based on sockets.\"\"\"\nimport socket\n\nfrom .base import Instrument\n\n\nclass IPInstrument(Instrument):\n\n    r\"\"\"\n    Bare socket ethernet instrument implementation.\n\n    Args:\n        name (str): What this instrument is called locally.\n\n        address (Optional[str]): The IP address or name. If not given on\n            construction, must be provided before any communication.\n\n        port (Optional[int]): The IP port. If not given on construction, must\n            be provided before any communication.\n\n        timeout (number): Seconds to allow for responses. Default 5.\n\n        terminator (str): Character(s) to terminate each send. Default '\\n'.\n\n        persistent (bool): Whether to leave the socket open between calls.\n            Default True.\n\n        write_confirmation (bool): Whether the instrument acknowledges writes\n            with some response we should read. Default True.\n\n        metadata (Optional[Dict]): additional static metadata to add to this\n            instrument's JSON snapshot.\n\n    See help for ``qcodes.Instrument`` for additional information on writing\n    instrument subclasses.\n    \"\"\"\n\n    def __init__(self, name, address=None, port=None, timeout=5,\n                 terminator='\\n', persistent=True, write_confirmation=True, testing=False,\n                 **kwargs):\n        super().__init__(name, testing=testing, **kwargs)\n\n        self._address = address\n        self._port = port\n        self._timeout = timeout\n        self._terminator = terminator\n        self._confirmation = write_confirmation\n\n        self._ensure_connection = EnsureConnection(self)\n        self._buffer_size = 1400\n\n        self._socket = None\n\n        self.set_persistent(persistent)\n\n    def set_address(self, address=None, port=None):\n        \"\"\"\n        Change the IP address and/or port of this instrument.\n\n        Args:\n            address (Optional[str]): The IP address or name.\n            port (Optional[number]): The IP port.\n        \"\"\"\n        if address is not None:\n            self._address = address\n        elif not hasattr(self, '_address'):\n            raise TypeError('This instrument doesn\\'t have an address yet, '\n                            'you must provide one.')\n        if port is not None:\n            self._port = port\n        elif not hasattr(self, '_port'):\n            raise TypeError('This instrument doesn\\'t have a port yet, '\n                            'you must provide one.')\n\n        self._disconnect()\n        self.set_persistent(self._persistent)\n\n    def set_persistent(self, persistent):\n        \"\"\"\n        Change whether this instrument keeps its socket open between calls.\n\n        Args:\n            persistent (bool): Set True to keep the socket open all the time.\n        \"\"\"\n        self._persistent = persistent\n        if persistent:\n            self._connect()\n        else:\n            self._disconnect()\n\n    def flush_connection(self):\n        if not self._testing:\n            self._recv()\n\n    def _connect(self):\n        if self._testing:\n            return\n\n        if self._socket is not None:\n            self._disconnect()\n\n        try:\n            self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n            self._socket.connect((self._address, self._port))\n            self.set_timeout(self._timeout)\n        except ConnectionRefusedError:\n            self._socket.close()\n            self._socket = None\n\n    def _disconnect(self):\n        if getattr(self, '_socket', None) is None:\n            return\n\n        self._socket.shutdown(socket.SHUT_RDWR)\n        self._socket.close()\n        self._socket = None\n\n    def set_timeout(self, timeout=None):\n        \"\"\"\n        Change the read timeout for the socket.\n\n        Args:\n            timeout (number): Seconds to allow for responses.\n        \"\"\"\n        self._timeout = timeout\n\n        if self._socket is not None:\n            self._socket.settimeout(float(self._timeout))\n\n    def set_terminator(self, terminator):\n        r\"\"\"\n        Change the write terminator to use.\n\n        Args:\n            terminator (str): Character(s) to terminate each send.\n                Default '\\n'.\n        \"\"\"\n        self._terminator = terminator\n\n    def _send(self, cmd):\n        data = cmd + self._terminator\n        self._socket.send(data.encode())\n\n    def _recv(self):\n        return self._socket.recv(self._buffer_size).decode()\n\n    def close(self):\n        \"\"\"Disconnect and irreversibly tear down the instrument.\"\"\"\n        self._disconnect()\n        super().close()\n\n    def write_raw(self, cmd):\n        \"\"\"\n        Low-level interface to send a command that gets no response.\n\n        Args:\n            cmd (str): The command to send to the instrument.\n        \"\"\"\n\n        with self._ensure_connection:\n            self._send(cmd)\n            if self._confirmation:\n                self._recv()\n\n    def ask_raw(self, cmd):\n        \"\"\"\n        Low-level interface to send a command an read a response.\n\n        Args:\n            cmd (str): The command to send to the instrument.\n\n        Returns:\n            str: The instrument's response.\n        \"\"\"\n        with self._ensure_connection:\n            self._send(cmd)\n            return self._recv()\n\n    def __del__(self):\n        self.close()\n\n    def snapshot_base(self, update=False):\n        \"\"\"\n        State of the instrument as a JSON-compatible dict.\n\n        Args:\n            update (bool): If True, update the state by querying the\n                instrument. If False, just use the latest values in memory.\n\n        Returns:\n            dict: base snapshot\n        \"\"\"\n        snap = super().snapshot_base(update=update)\n\n        snap['port'] = self._port\n        snap['confirmation'] = self._confirmation\n        snap['address'] = self._address\n        snap['terminator'] = self._terminator\n        snap['timeout'] = self._timeout\n        snap['persistent'] = self._persistent\n\n        return snap\n\n\nclass EnsureConnection:\n\n    \"\"\"\n    Context manager to ensure an instrument is connected when needed.\n\n    Uses ``instrument._persistent`` to determine whether or not to close\n    the connection immediately on completion.\n\n    Args:\n        instrument (IPInstrument): the instance to connect.\n    \"\"\"\n\n    def __init__(self, instrument):\n        self.instrument = instrument\n\n    def __enter__(self):\n        \"\"\"Make sure we connect when entering the context.\"\"\"\n        if not self.instrument._persistent or self.instrument._socket is None:\n            self.instrument._connect()\n\n    def __exit__(self, type, value, tb):\n        \"\"\"Possibly disconnect on exiting the context.\"\"\"\n        if not self.instrument._persistent:\n            self.instrument._disconnect()\n", "path": "qcodes/instrument/ip.py"}], "after_files": [{"content": "\"\"\"Ethernet instrument driver class based on sockets.\"\"\"\nimport socket\nimport logging\n\nfrom .base import Instrument\n\nlog = logging.getLogger(__name__)\n\nclass IPInstrument(Instrument):\n\n    r\"\"\"\n    Bare socket ethernet instrument implementation.\n\n    Args:\n        name (str): What this instrument is called locally.\n\n        address (Optional[str]): The IP address or name. If not given on\n            construction, must be provided before any communication.\n\n        port (Optional[int]): The IP port. If not given on construction, must\n            be provided before any communication.\n\n        timeout (number): Seconds to allow for responses. Default 5.\n\n        terminator (str): Character(s) to terminate each send. Default '\\n'.\n\n        persistent (bool): Whether to leave the socket open between calls.\n            Default True.\n\n        write_confirmation (bool): Whether the instrument acknowledges writes\n            with some response we should read. Default True.\n\n        metadata (Optional[Dict]): additional static metadata to add to this\n            instrument's JSON snapshot.\n\n    See help for ``qcodes.Instrument`` for additional information on writing\n    instrument subclasses.\n    \"\"\"\n\n    def __init__(self, name, address=None, port=None, timeout=5,\n                 terminator='\\n', persistent=True, write_confirmation=True, testing=False,\n                 **kwargs):\n        super().__init__(name, testing=testing, **kwargs)\n\n        self._address = address\n        self._port = port\n        self._timeout = timeout\n        self._terminator = terminator\n        self._confirmation = write_confirmation\n\n        self._ensure_connection = EnsureConnection(self)\n        self._buffer_size = 1400\n\n        self._socket = None\n\n        self.set_persistent(persistent)\n\n    def set_address(self, address=None, port=None):\n        \"\"\"\n        Change the IP address and/or port of this instrument.\n\n        Args:\n            address (Optional[str]): The IP address or name.\n            port (Optional[number]): The IP port.\n        \"\"\"\n        if address is not None:\n            self._address = address\n        elif not hasattr(self, '_address'):\n            raise TypeError('This instrument doesn\\'t have an address yet, '\n                            'you must provide one.')\n        if port is not None:\n            self._port = port\n        elif not hasattr(self, '_port'):\n            raise TypeError('This instrument doesn\\'t have a port yet, '\n                            'you must provide one.')\n\n        self._disconnect()\n        self.set_persistent(self._persistent)\n\n    def set_persistent(self, persistent):\n        \"\"\"\n        Change whether this instrument keeps its socket open between calls.\n\n        Args:\n            persistent (bool): Set True to keep the socket open all the time.\n        \"\"\"\n        self._persistent = persistent\n        if persistent:\n            self._connect()\n        else:\n            self._disconnect()\n\n    def flush_connection(self):\n        if not self._testing:\n            self._recv()\n\n    def _connect(self):\n        if self._testing:\n            return\n\n        if self._socket is not None:\n            self._disconnect()\n\n        try:\n            self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n            self._socket.connect((self._address, self._port))\n            self.set_timeout(self._timeout)\n        except ConnectionRefusedError:\n            self._socket.close()\n            self._socket = None\n\n    def _disconnect(self):\n        if getattr(self, '_socket', None) is None:\n            return\n\n        self._socket.shutdown(socket.SHUT_RDWR)\n        self._socket.close()\n        self._socket = None\n\n    def set_timeout(self, timeout=None):\n        \"\"\"\n        Change the read timeout for the socket.\n\n        Args:\n            timeout (number): Seconds to allow for responses.\n        \"\"\"\n        self._timeout = timeout\n\n        if self._socket is not None:\n            self._socket.settimeout(float(self._timeout))\n\n    def set_terminator(self, terminator):\n        r\"\"\"\n        Change the write terminator to use.\n\n        Args:\n            terminator (str): Character(s) to terminate each send.\n                Default '\\n'.\n        \"\"\"\n        self._terminator = terminator\n\n    def _send(self, cmd):\n        data = cmd + self._terminator\n        self._socket.sendall(data.encode())\n\n    def _recv(self):\n        result = self._socket.recv(self._buffer_size)\n        if result == b'':\n            log.warning(\"Got empty response from Socket recv() \"\n                        \"Connection broken.\")\n        return result.decode()\n\n    def close(self):\n        \"\"\"Disconnect and irreversibly tear down the instrument.\"\"\"\n        self._disconnect()\n        super().close()\n\n    def write_raw(self, cmd):\n        \"\"\"\n        Low-level interface to send a command that gets no response.\n\n        Args:\n            cmd (str): The command to send to the instrument.\n        \"\"\"\n\n        with self._ensure_connection:\n            self._send(cmd)\n            if self._confirmation:\n                self._recv()\n\n    def ask_raw(self, cmd):\n        \"\"\"\n        Low-level interface to send a command an read a response.\n\n        Args:\n            cmd (str): The command to send to the instrument.\n\n        Returns:\n            str: The instrument's response.\n        \"\"\"\n        with self._ensure_connection:\n            self._send(cmd)\n            return self._recv()\n\n    def __del__(self):\n        self.close()\n\n    def snapshot_base(self, update=False):\n        \"\"\"\n        State of the instrument as a JSON-compatible dict.\n\n        Args:\n            update (bool): If True, update the state by querying the\n                instrument. If False, just use the latest values in memory.\n\n        Returns:\n            dict: base snapshot\n        \"\"\"\n        snap = super().snapshot_base(update=update)\n\n        snap['port'] = self._port\n        snap['confirmation'] = self._confirmation\n        snap['address'] = self._address\n        snap['terminator'] = self._terminator\n        snap['timeout'] = self._timeout\n        snap['persistent'] = self._persistent\n\n        return snap\n\n\nclass EnsureConnection:\n\n    \"\"\"\n    Context manager to ensure an instrument is connected when needed.\n\n    Uses ``instrument._persistent`` to determine whether or not to close\n    the connection immediately on completion.\n\n    Args:\n        instrument (IPInstrument): the instance to connect.\n    \"\"\"\n\n    def __init__(self, instrument):\n        self.instrument = instrument\n\n    def __enter__(self):\n        \"\"\"Make sure we connect when entering the context.\"\"\"\n        if not self.instrument._persistent or self.instrument._socket is None:\n            self.instrument._connect()\n\n    def __exit__(self, type, value, tb):\n        \"\"\"Possibly disconnect on exiting the context.\"\"\"\n        if not self.instrument._persistent:\n            self.instrument._disconnect()\n", "path": "qcodes/instrument/ip.py"}]}