We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
error when saving to drive other than current path
This is due to windows handling of drives. A minimal example:
``` python
import qcodes,os

datadir = r'd:\Temp'
qcodes.DataSet.default_io = qcodes.DiskIO(datadir)

p=qcodes.Parameter('p', set_cmd=None)
q=qcodes.Parameter('q', set_cmd=None)
ds=qcodes.Loop(p[0:10:1]).each(q).run() # fine
 
qcodes.DataSet.default_io = qcodes.DiskIO(r'c:\Temp')

ds=qcodes.Loop(p[0:10:1]).each(p).run() # error
```
This generates the error `ValueError: path is on mount 'd:', start on mount 'c:'`

Also see https://bugs.python.org/issue7195



--- 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/data/io.py`
Content:
```
1 """
2 IO managers for QCodes.
3 
4 IO managers wrap whatever physical storage layer the user wants to use
5 in an interface mimicking the built-in <open> context manager, with
6 some restrictions to minimize the overhead in creating new IO managers.
7 
8 The main thing these managers need to implement is the open context manager:
9 
10 - Only the context manager needs to be implemented, not separate
11   open function and close methods.
12 
13 - open takes the standard parameters:
14 
15     - filename: (string)
16     - mode: (string) only 'r' (read), 'w' (write), and 'a' (append) are
17       expected to be implemented. As with normal file objects, the only
18       difference between write and append is that write empties the file
19       before adding new data, and append leaves the existing contents in
20       place but starts writing at the end.
21     - encoding: If a special output encoding is desired. i.e. 'utf8
22 
23 - the file-like object returned should implement a minimal set of operations.
24 
25   In read mode:
26     - read([size]): read to the end or at most size bytes into a string
27     - readline([size]): read until a newline or up to size bytes, into a string
28     - iter(): usually return self, but can be any iterator over lines
29     - next(): assuming iter() returns self, this yields the next line.
30 
31   In write or append mode:
32     - write(s): add string s to the end of the file.
33     - writelines(seq): add a sequence of strings
34 
35 IO managers should also implement:
36 
37 - a join method, ala os.path.join(\*args).
38 - a list method, that returns all objects matching location
39 - a remove method, ala os.remove(path) except that it will remove directories
40   as well as files, since we're allowing "locations" to be directories
41   or files.
42 """
43 
44 from contextlib import contextmanager
45 import os
46 import re
47 import shutil
48 from fnmatch import fnmatch
49 
50 ALLOWED_OPEN_MODES = ('r', 'w', 'a')
51 
52 
53 class DiskIO:
54 
55     """
56     Simple IO object to wrap disk operations with a custom base location.
57 
58     Also accepts both forward and backward slashes at any point, and
59     normalizes both to the OS we are currently on.
60 
61     Args:
62         base_location (str): a path to the root data folder.
63             Converted to an absolute path immediately, so even if you supply a
64             relative path, later changes to the OS working directory will not
65             affect data paths.
66     """
67 
68     def __init__(self, base_location):
69         if base_location is None:
70             self.base_location = None
71         else:
72             base_location = self._normalize_slashes(base_location)
73             self.base_location = os.path.abspath(base_location)
74 
75     @contextmanager
76     def open(self, filename, mode, encoding=None):
77         """
78         Mimic the interface of the built in open context manager.
79 
80         Args:
81             filename (str): path relative to base_location.
82 
83             mode (str): 'r' (read), 'w' (write), or 'a' (append).
84                 Other open modes are not supported because we don't want
85                 to force all IO managers to support others.
86 
87         Returns:
88             context manager yielding the open file
89         """
90         if mode not in ALLOWED_OPEN_MODES:
91             raise ValueError('mode {} not allowed in IO managers'.format(mode))
92 
93         filepath = self.to_path(filename)
94 
95         # make directories if needed
96         dirpath = os.path.dirname(filepath)
97         if not os.path.exists(dirpath):
98             os.makedirs(dirpath)
99 
100         # normally we'd construct this context manager with try/finally, but
101         # here we already have a context manager for open so we just wrap it
102         with open(filepath, mode, encoding=encoding) as f:
103             yield f
104 
105     def _normalize_slashes(self, location):
106         # note that this is NOT os.path.join - the difference is os.path.join
107         # discards empty strings, so if you use it on a re.split absolute
108         # path you will get a relative path!
109         return os.sep.join(re.split('[\\\\/]', location))
110 
111     def to_path(self, location):
112         """
113         Convert a location string into a path on the local file system.
114 
115         For DiskIO this just fixes slashes and prepends the base location,
116         doing nothing active with the file. But for other io managers that
117         refer to remote storage, this method may actually fetch the file and
118         put it at a temporary local path.
119 
120         Args:
121             location (str): A location string for a complete dataset or
122                 a file within it.
123 
124         Returns:
125             path (str): The path on disk to which this location maps.
126         """
127         location = self._normalize_slashes(location)
128         if self.base_location:
129             return os.path.join(self.base_location, location)
130         else:
131             return location
132 
133     def to_location(self, path):
134         """
135         Convert a local filesystem path into a location string.
136 
137         Args:
138             path (str): a path on the local file system.
139 
140         Returns:
141             location (str): the location string corresponding to this path.
142         """
143         if self.base_location:
144             return os.path.relpath(path, self.base_location)
145         else:
146             return path
147 
148     def __repr__(self):
149         """Show the base location in the repr."""
150         return '<DiskIO, base_location={}>'.format(repr(self.base_location))
151 
152     def join(self, *args):
153         """Context-dependent os.path.join for this io manager."""
154         return os.path.join(*list(map(self._normalize_slashes, args)))
155 
156     def isfile(self, location):
157         """Check whether this location matches a file."""
158         path = self.to_path(location)
159         return os.path.isfile(path)
160 
161     def list(self, location, maxdepth=1, include_dirs=False):
162         """
163         Return all files that match location.
164 
165         This is either files whose names match up to an arbitrary extension,
166         or any files within an exactly matching directory name.
167 
168         Args:
169             location (str): the location to match.
170                 May contain the usual path wildcards * and ?
171 
172             maxdepth (int, optional): maximum levels of directory nesting to
173                 recurse into looking for files. Default 1.
174 
175             include_dirs (bool, optional): whether to allow directories in
176                 the results or just files. Default False.
177 
178         Returns:
179             A list of matching files and/or directories, as locations
180             relative to our base_location.
181         """
182         location = self._normalize_slashes(location)
183         search_dir, pattern = os.path.split(location)
184         path = self.to_path(search_dir)
185 
186         if not os.path.isdir(path):
187             return []
188 
189         matches = [fn for fn in os.listdir(path) if fnmatch(fn, pattern + '*')]
190         out = []
191 
192         for match in matches:
193             matchpath = self.join(path, match)
194             if os.path.isdir(matchpath) and fnmatch(match, pattern):
195                 if maxdepth > 0:
196                     # exact directory match - walk down to maxdepth
197                     for root, dirs, files in os.walk(matchpath, topdown=True):
198                         depth = root[len(path):].count(os.path.sep)
199                         if depth == maxdepth:
200                             dirs[:] = []  # don't recurse any further
201 
202                         for fn in files + (dirs if include_dirs else []):
203                             out.append(self.to_location(self.join(root, fn)))
204 
205                 elif include_dirs:
206                     out.append(self.join(search_dir, match))
207 
208             elif (os.path.isfile(matchpath) and
209                   (fnmatch(match, pattern) or
210                    fnmatch(os.path.splitext(match)[0], pattern))):
211                 # exact filename match, or match up to an extension
212                 # note that we need fnmatch(match, pattern) in addition to the
213                 # splitext test to cover the case of the base filename itself
214                 # containing a dot.
215                 out.append(self.join(search_dir, match))
216 
217         return out
218 
219     def remove(self, filename):
220         """Delete a file or folder and prune the directory tree."""
221         path = self.to_path(filename)
222         if os.path.isdir(path):
223             shutil.rmtree(path)
224         else:
225             os.remove(path)
226 
227         filepath = os.path.split(path)[0]
228         try:
229             os.removedirs(filepath)
230         except OSError:
231             # directory was not empty - good that we're not removing it!
232             pass
233 
234     def remove_all(self, location):
235         """
236         Delete all files/directories in the dataset at this location.
237 
238         Afterward prunes the directory tree.
239         """
240         for fn in self.list(location):
241             self.remove(fn)
242
```
--- 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/data/io.py b/qcodes/data/io.py
--- a/qcodes/data/io.py
+++ b/qcodes/data/io.py
@@ -141,7 +141,7 @@
             location (str): the location string corresponding to this path.
         """
         if self.base_location:
-            return os.path.relpath(path, self.base_location)
+            return os.path.join(self.base_location, path)
         else:
             return path

{"golden_diff": "diff --git a/qcodes/data/io.py b/qcodes/data/io.py\n--- a/qcodes/data/io.py\n+++ b/qcodes/data/io.py\n@@ -141,7 +141,7 @@\n             location (str): the location string corresponding to this path.\n         \"\"\"\n         if self.base_location:\n-            return os.path.relpath(path, self.base_location)\n+            return os.path.join(self.base_location, path)\n         else:\n             return path\n", "issue": "error when saving to drive other than current path\nThis is due to windows handling of drives. A minimal example:\r\n``` python\r\nimport qcodes,os\r\n\r\ndatadir = r'd:\\Temp'\r\nqcodes.DataSet.default_io = qcodes.DiskIO(datadir)\r\n\r\np=qcodes.Parameter('p', set_cmd=None)\r\nq=qcodes.Parameter('q', set_cmd=None)\r\nds=qcodes.Loop(p[0:10:1]).each(q).run() # fine\r\n \r\nqcodes.DataSet.default_io = qcodes.DiskIO(r'c:\\Temp')\r\n\r\nds=qcodes.Loop(p[0:10:1]).each(p).run() # error\r\n```\r\nThis generates the error `ValueError: path is on mount 'd:', start on mount 'c:'`\r\n\r\nAlso see https://bugs.python.org/issue7195\r\n\r\n\n", "before_files": [{"content": "\"\"\"\nIO managers for QCodes.\n\nIO managers wrap whatever physical storage layer the user wants to use\nin an interface mimicking the built-in <open> context manager, with\nsome restrictions to minimize the overhead in creating new IO managers.\n\nThe main thing these managers need to implement is the open context manager:\n\n- Only the context manager needs to be implemented, not separate\n  open function and close methods.\n\n- open takes the standard parameters:\n\n    - filename: (string)\n    - mode: (string) only 'r' (read), 'w' (write), and 'a' (append) are\n      expected to be implemented. As with normal file objects, the only\n      difference between write and append is that write empties the file\n      before adding new data, and append leaves the existing contents in\n      place but starts writing at the end.\n    - encoding: If a special output encoding is desired. i.e. 'utf8\n\n- the file-like object returned should implement a minimal set of operations.\n\n  In read mode:\n    - read([size]): read to the end or at most size bytes into a string\n    - readline([size]): read until a newline or up to size bytes, into a string\n    - iter(): usually return self, but can be any iterator over lines\n    - next(): assuming iter() returns self, this yields the next line.\n\n  In write or append mode:\n    - write(s): add string s to the end of the file.\n    - writelines(seq): add a sequence of strings\n\nIO managers should also implement:\n\n- a join method, ala os.path.join(\\*args).\n- a list method, that returns all objects matching location\n- a remove method, ala os.remove(path) except that it will remove directories\n  as well as files, since we're allowing \"locations\" to be directories\n  or files.\n\"\"\"\n\nfrom contextlib import contextmanager\nimport os\nimport re\nimport shutil\nfrom fnmatch import fnmatch\n\nALLOWED_OPEN_MODES = ('r', 'w', 'a')\n\n\nclass DiskIO:\n\n    \"\"\"\n    Simple IO object to wrap disk operations with a custom base location.\n\n    Also accepts both forward and backward slashes at any point, and\n    normalizes both to the OS we are currently on.\n\n    Args:\n        base_location (str): a path to the root data folder.\n            Converted to an absolute path immediately, so even if you supply a\n            relative path, later changes to the OS working directory will not\n            affect data paths.\n    \"\"\"\n\n    def __init__(self, base_location):\n        if base_location is None:\n            self.base_location = None\n        else:\n            base_location = self._normalize_slashes(base_location)\n            self.base_location = os.path.abspath(base_location)\n\n    @contextmanager\n    def open(self, filename, mode, encoding=None):\n        \"\"\"\n        Mimic the interface of the built in open context manager.\n\n        Args:\n            filename (str): path relative to base_location.\n\n            mode (str): 'r' (read), 'w' (write), or 'a' (append).\n                Other open modes are not supported because we don't want\n                to force all IO managers to support others.\n\n        Returns:\n            context manager yielding the open file\n        \"\"\"\n        if mode not in ALLOWED_OPEN_MODES:\n            raise ValueError('mode {} not allowed in IO managers'.format(mode))\n\n        filepath = self.to_path(filename)\n\n        # make directories if needed\n        dirpath = os.path.dirname(filepath)\n        if not os.path.exists(dirpath):\n            os.makedirs(dirpath)\n\n        # normally we'd construct this context manager with try/finally, but\n        # here we already have a context manager for open so we just wrap it\n        with open(filepath, mode, encoding=encoding) as f:\n            yield f\n\n    def _normalize_slashes(self, location):\n        # note that this is NOT os.path.join - the difference is os.path.join\n        # discards empty strings, so if you use it on a re.split absolute\n        # path you will get a relative path!\n        return os.sep.join(re.split('[\\\\\\\\/]', location))\n\n    def to_path(self, location):\n        \"\"\"\n        Convert a location string into a path on the local file system.\n\n        For DiskIO this just fixes slashes and prepends the base location,\n        doing nothing active with the file. But for other io managers that\n        refer to remote storage, this method may actually fetch the file and\n        put it at a temporary local path.\n\n        Args:\n            location (str): A location string for a complete dataset or\n                a file within it.\n\n        Returns:\n            path (str): The path on disk to which this location maps.\n        \"\"\"\n        location = self._normalize_slashes(location)\n        if self.base_location:\n            return os.path.join(self.base_location, location)\n        else:\n            return location\n\n    def to_location(self, path):\n        \"\"\"\n        Convert a local filesystem path into a location string.\n\n        Args:\n            path (str): a path on the local file system.\n\n        Returns:\n            location (str): the location string corresponding to this path.\n        \"\"\"\n        if self.base_location:\n            return os.path.relpath(path, self.base_location)\n        else:\n            return path\n\n    def __repr__(self):\n        \"\"\"Show the base location in the repr.\"\"\"\n        return '<DiskIO, base_location={}>'.format(repr(self.base_location))\n\n    def join(self, *args):\n        \"\"\"Context-dependent os.path.join for this io manager.\"\"\"\n        return os.path.join(*list(map(self._normalize_slashes, args)))\n\n    def isfile(self, location):\n        \"\"\"Check whether this location matches a file.\"\"\"\n        path = self.to_path(location)\n        return os.path.isfile(path)\n\n    def list(self, location, maxdepth=1, include_dirs=False):\n        \"\"\"\n        Return all files that match location.\n\n        This is either files whose names match up to an arbitrary extension,\n        or any files within an exactly matching directory name.\n\n        Args:\n            location (str): the location to match.\n                May contain the usual path wildcards * and ?\n\n            maxdepth (int, optional): maximum levels of directory nesting to\n                recurse into looking for files. Default 1.\n\n            include_dirs (bool, optional): whether to allow directories in\n                the results or just files. Default False.\n\n        Returns:\n            A list of matching files and/or directories, as locations\n            relative to our base_location.\n        \"\"\"\n        location = self._normalize_slashes(location)\n        search_dir, pattern = os.path.split(location)\n        path = self.to_path(search_dir)\n\n        if not os.path.isdir(path):\n            return []\n\n        matches = [fn for fn in os.listdir(path) if fnmatch(fn, pattern + '*')]\n        out = []\n\n        for match in matches:\n            matchpath = self.join(path, match)\n            if os.path.isdir(matchpath) and fnmatch(match, pattern):\n                if maxdepth > 0:\n                    # exact directory match - walk down to maxdepth\n                    for root, dirs, files in os.walk(matchpath, topdown=True):\n                        depth = root[len(path):].count(os.path.sep)\n                        if depth == maxdepth:\n                            dirs[:] = []  # don't recurse any further\n\n                        for fn in files + (dirs if include_dirs else []):\n                            out.append(self.to_location(self.join(root, fn)))\n\n                elif include_dirs:\n                    out.append(self.join(search_dir, match))\n\n            elif (os.path.isfile(matchpath) and\n                  (fnmatch(match, pattern) or\n                   fnmatch(os.path.splitext(match)[0], pattern))):\n                # exact filename match, or match up to an extension\n                # note that we need fnmatch(match, pattern) in addition to the\n                # splitext test to cover the case of the base filename itself\n                # containing a dot.\n                out.append(self.join(search_dir, match))\n\n        return out\n\n    def remove(self, filename):\n        \"\"\"Delete a file or folder and prune the directory tree.\"\"\"\n        path = self.to_path(filename)\n        if os.path.isdir(path):\n            shutil.rmtree(path)\n        else:\n            os.remove(path)\n\n        filepath = os.path.split(path)[0]\n        try:\n            os.removedirs(filepath)\n        except OSError:\n            # directory was not empty - good that we're not removing it!\n            pass\n\n    def remove_all(self, location):\n        \"\"\"\n        Delete all files/directories in the dataset at this location.\n\n        Afterward prunes the directory tree.\n        \"\"\"\n        for fn in self.list(location):\n            self.remove(fn)\n", "path": "qcodes/data/io.py"}], "after_files": [{"content": "\"\"\"\nIO managers for QCodes.\n\nIO managers wrap whatever physical storage layer the user wants to use\nin an interface mimicking the built-in <open> context manager, with\nsome restrictions to minimize the overhead in creating new IO managers.\n\nThe main thing these managers need to implement is the open context manager:\n\n- Only the context manager needs to be implemented, not separate\n  open function and close methods.\n\n- open takes the standard parameters:\n\n    - filename: (string)\n    - mode: (string) only 'r' (read), 'w' (write), and 'a' (append) are\n      expected to be implemented. As with normal file objects, the only\n      difference between write and append is that write empties the file\n      before adding new data, and append leaves the existing contents in\n      place but starts writing at the end.\n    - encoding: If a special output encoding is desired. i.e. 'utf8\n\n- the file-like object returned should implement a minimal set of operations.\n\n  In read mode:\n    - read([size]): read to the end or at most size bytes into a string\n    - readline([size]): read until a newline or up to size bytes, into a string\n    - iter(): usually return self, but can be any iterator over lines\n    - next(): assuming iter() returns self, this yields the next line.\n\n  In write or append mode:\n    - write(s): add string s to the end of the file.\n    - writelines(seq): add a sequence of strings\n\nIO managers should also implement:\n\n- a join method, ala os.path.join(\\*args).\n- a list method, that returns all objects matching location\n- a remove method, ala os.remove(path) except that it will remove directories\n  as well as files, since we're allowing \"locations\" to be directories\n  or files.\n\"\"\"\n\nfrom contextlib import contextmanager\nimport os\nimport re\nimport shutil\nfrom fnmatch import fnmatch\n\nALLOWED_OPEN_MODES = ('r', 'w', 'a')\n\n\nclass DiskIO:\n\n    \"\"\"\n    Simple IO object to wrap disk operations with a custom base location.\n\n    Also accepts both forward and backward slashes at any point, and\n    normalizes both to the OS we are currently on.\n\n    Args:\n        base_location (str): a path to the root data folder.\n            Converted to an absolute path immediately, so even if you supply a\n            relative path, later changes to the OS working directory will not\n            affect data paths.\n    \"\"\"\n\n    def __init__(self, base_location):\n        if base_location is None:\n            self.base_location = None\n        else:\n            base_location = self._normalize_slashes(base_location)\n            self.base_location = os.path.abspath(base_location)\n\n    @contextmanager\n    def open(self, filename, mode, encoding=None):\n        \"\"\"\n        Mimic the interface of the built in open context manager.\n\n        Args:\n            filename (str): path relative to base_location.\n\n            mode (str): 'r' (read), 'w' (write), or 'a' (append).\n                Other open modes are not supported because we don't want\n                to force all IO managers to support others.\n\n        Returns:\n            context manager yielding the open file\n        \"\"\"\n        if mode not in ALLOWED_OPEN_MODES:\n            raise ValueError('mode {} not allowed in IO managers'.format(mode))\n\n        filepath = self.to_path(filename)\n\n        # make directories if needed\n        dirpath = os.path.dirname(filepath)\n        if not os.path.exists(dirpath):\n            os.makedirs(dirpath)\n\n        # normally we'd construct this context manager with try/finally, but\n        # here we already have a context manager for open so we just wrap it\n        with open(filepath, mode, encoding=encoding) as f:\n            yield f\n\n    def _normalize_slashes(self, location):\n        # note that this is NOT os.path.join - the difference is os.path.join\n        # discards empty strings, so if you use it on a re.split absolute\n        # path you will get a relative path!\n        return os.sep.join(re.split('[\\\\\\\\/]', location))\n\n    def to_path(self, location):\n        \"\"\"\n        Convert a location string into a path on the local file system.\n\n        For DiskIO this just fixes slashes and prepends the base location,\n        doing nothing active with the file. But for other io managers that\n        refer to remote storage, this method may actually fetch the file and\n        put it at a temporary local path.\n\n        Args:\n            location (str): A location string for a complete dataset or\n                a file within it.\n\n        Returns:\n            path (str): The path on disk to which this location maps.\n        \"\"\"\n        location = self._normalize_slashes(location)\n        if self.base_location:\n            return os.path.join(self.base_location, location)\n        else:\n            return location\n\n    def to_location(self, path):\n        \"\"\"\n        Convert a local filesystem path into a location string.\n\n        Args:\n            path (str): a path on the local file system.\n\n        Returns:\n            location (str): the location string corresponding to this path.\n        \"\"\"\n        if self.base_location:\n            return os.path.join(self.base_location, path)\n        else:\n            return path\n\n    def __repr__(self):\n        \"\"\"Show the base location in the repr.\"\"\"\n        return '<DiskIO, base_location={}>'.format(repr(self.base_location))\n\n    def join(self, *args):\n        \"\"\"Context-dependent os.path.join for this io manager.\"\"\"\n        return os.path.join(*list(map(self._normalize_slashes, args)))\n\n    def isfile(self, location):\n        \"\"\"Check whether this location matches a file.\"\"\"\n        path = self.to_path(location)\n        return os.path.isfile(path)\n\n    def list(self, location, maxdepth=1, include_dirs=False):\n        \"\"\"\n        Return all files that match location.\n\n        This is either files whose names match up to an arbitrary extension,\n        or any files within an exactly matching directory name.\n\n        Args:\n            location (str): the location to match.\n                May contain the usual path wildcards * and ?\n\n            maxdepth (int, optional): maximum levels of directory nesting to\n                recurse into looking for files. Default 1.\n\n            include_dirs (bool, optional): whether to allow directories in\n                the results or just files. Default False.\n\n        Returns:\n            A list of matching files and/or directories, as locations\n            relative to our base_location.\n        \"\"\"\n        location = self._normalize_slashes(location)\n        search_dir, pattern = os.path.split(location)\n        path = self.to_path(search_dir)\n\n        if not os.path.isdir(path):\n            return []\n\n        matches = [fn for fn in os.listdir(path) if fnmatch(fn, pattern + '*')]\n        out = []\n\n        for match in matches:\n            matchpath = self.join(path, match)\n            if os.path.isdir(matchpath) and fnmatch(match, pattern):\n                if maxdepth > 0:\n                    # exact directory match - walk down to maxdepth\n                    for root, dirs, files in os.walk(matchpath, topdown=True):\n                        depth = root[len(path):].count(os.path.sep)\n                        if depth == maxdepth:\n                            dirs[:] = []  # don't recurse any further\n\n                        for fn in files + (dirs if include_dirs else []):\n                            out.append(self.to_location(self.join(root, fn)))\n\n                elif include_dirs:\n                    out.append(self.join(search_dir, match))\n\n            elif (os.path.isfile(matchpath) and\n                  (fnmatch(match, pattern) or\n                   fnmatch(os.path.splitext(match)[0], pattern))):\n                # exact filename match, or match up to an extension\n                # note that we need fnmatch(match, pattern) in addition to the\n                # splitext test to cover the case of the base filename itself\n                # containing a dot.\n                out.append(self.join(search_dir, match))\n\n        return out\n\n    def remove(self, filename):\n        \"\"\"Delete a file or folder and prune the directory tree.\"\"\"\n        path = self.to_path(filename)\n        if os.path.isdir(path):\n            shutil.rmtree(path)\n        else:\n            os.remove(path)\n\n        filepath = os.path.split(path)[0]\n        try:\n            os.removedirs(filepath)\n        except OSError:\n            # directory was not empty - good that we're not removing it!\n            pass\n\n    def remove_all(self, location):\n        \"\"\"\n        Delete all files/directories in the dataset at this location.\n\n        Afterward prunes the directory tree.\n        \"\"\"\n        for fn in self.list(location):\n            self.remove(fn)\n", "path": "qcodes/data/io.py"}]}