We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
wt.google_drive.Drive.download() calls `self._list_folder()` when it should call `self.list_folder()`
See offending [line](https://github.com/wright-group/WrightTools/blob/039507d95561fd237dc7ba66b4d4f37ce6148397/WrightTools/google_drive.py#L248).

[Line](https://github.com/wright-group/WrightTools/blob/039507d95561fd237dc7ba66b4d4f37ce6148397/WrightTools/google_drive.py#L281) where correct method is defined. 


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `WrightTools/google_drive.py`
Content:
```
1 """Interact with google drive using the pydrive package."""
2 
3 
4 # --- import --------------------------------------------------------------------------------------
5 
6 
7 from __future__ import absolute_import, division, print_function, unicode_literals
8 
9 import os
10 import time
11 import datetime
12 import tempfile
13 import appdirs
14 from glob import glob
15 
16 
17 # --- define --------------------------------------------------------------------------------------
18 
19 
20 directory = os.path.dirname(os.path.abspath(__file__))
21 
22 
23 # --- helper methods ------------------------------------------------------------------------------
24 
25 
26 def id_to_url(driveid):
27     """Generate a url from a Google Drive id.
28 
29     Parameters
30     ----------
31     id : string
32         ID.
33 
34     Returns
35     -------
36     string
37         url.
38     """
39     return 'https://drive.google.com/open?id=' + driveid
40 
41 
42 # --- drive class ---------------------------------------------------------------------------------
43 
44 
45 class Drive:
46     """Google Drive class."""
47 
48     def __init__(self, account_id='default'):
49         """init."""
50         # Define the temp directory and file name format
51         configDir = appdirs.user_data_dir('WrightTools', 'WrightGroup')
52         if not os.path.isdir(configDir):
53             os.makedirs(configDir)
54         prefix = 'google-drive-'
55         suffix = '-' + account_id + '.txt'
56         # Check for existing file
57         lis = glob(os.path.join(configDir, prefix + "*" + suffix))
58         self.mycreds_path = ''
59         if len(lis) > 0:
60             for f in lis:
61                 # Check that for read and write access (or is bitwise, checking both)
62                 # Note this check is probably not needed with appdirs, but is not
63                 #     harmful and provides additional insurance against crashes.
64                 if os.access(f, os.W_OK | os.R_OK):
65                     self.mycreds_path = f
66                     break
67         # Make a new file if one does not exist with sufficent permissions
68         if self.mycreds_path == '':
69             self.mycreds_path = tempfile.mkstemp(prefix=prefix,
70                                                  suffix=suffix,
71                                                  text=True,
72                                                  dir=configDir)[1]
73         self._authenticate()
74 
75     def _authenticate(self):
76         """Authenticate the user via a web browser.
77 
78         This function, once run, will open up a login window in a web browser.
79         The user must then athenticate via email and password to authorize the
80         API for usage with that particular account. Note that 'mycreds.txt' may
81         just be an empty text file. This function will create the correct
82         dictionary structure in the file upon completion.
83         """
84         # This function requires a Client_secrets.json file to be in the
85         # working directory.
86         old_cwd = os.getcwd()
87         os.chdir(directory)
88         # import
89         from pydrive.auth import GoogleAuth
90         from pydrive.drive import GoogleDrive
91         # load
92         self.gauth = GoogleAuth()
93         self.gauth.LoadCredentialsFile(self.mycreds_path)
94         if self.gauth.credentials is None:
95             # authenticate if credentials are not found
96             self.gauth.LocalWebserverAuth()
97         elif self.gauth.access_token_expired:
98             # refresh credentials if they are expired
99             self.gauth.Refresh()
100         else:
101             # initialize the saved credentials
102             self.gauth.Authorize()
103         # finish
104         self.gauth.SaveCredentialsFile(self.mycreds_path)
105         self.api = GoogleDrive(self.gauth)
106         os.chdir(old_cwd)
107 
108     def _upload_file(self, filepath, parentid, overwrite=False,
109                      delete_local=False, verbose=True):
110         """Upload file.
111 
112         Parameters
113         ----------
114         filepath : string
115             Filepath.
116         parentid : string
117             Parent ID.
118         overwrite : boolean (optional)
119             Toggle remote overwrite. Default is False.
120         delete_local : boolean (optional).
121             Toggle local deletion after upload. Default is False.
122         verbose : boolean (optional)
123             Toggle talkback. Default is True.
124         """
125         self._authenticate()
126         title = filepath.split(os.path.sep)[-1]
127         # check if remote file already exists
128         q = {'q': "'{}' in parents and trashed=false".format(parentid)}
129         fs = self.api.ListFile(q).GetList()
130         f = None
131         for fi in fs:
132             # dont want to look at folders
133             if 'folder' in fi['mimeType']:
134                 continue
135             if fi['title'] == title:
136                 print(title, 'found in upload file')
137                 f = fi
138         if f is not None:
139             remove = False
140             statinfo = os.stat(filepath)
141             # filesize different
142             if not int(statinfo.st_size) == int(f['fileSize']):
143                 remove = True
144             # modified since creation
145             remote_stamp = f['modifiedDate'].split('.')[0]  # UTC
146             remote_stamp = time.mktime(datetime.datetime.strptime(
147                 remote_stamp, '%Y-%m-%dT%H:%M:%S').timetuple())
148             local_stamp = os.path.getmtime(filepath)  # local
149             local_stamp += time.timezone  # UTC
150             if local_stamp > remote_stamp:
151                 remove = True
152             # overwrite toggle
153             if overwrite:
154                 remove = True
155             # remove
156             if remove:
157                 f.Trash()
158                 f = None
159         # upload
160         if f is None:
161             f = self.api.CreateFile({'title': title,
162                                      'parents': [{"id": parentid}]})
163             f.SetContentFile(filepath)
164             f.Upload()
165             f.content.close()
166             if verbose:
167                 print('file uploaded from {}'.format(filepath))
168         # delete local
169         if delete_local:
170             os.remove(filepath)
171         # finish
172         return f['id']
173 
174     def create_folder(self, name, parentid):
175         """Create a new folder in Google Drive.
176 
177         Attributes
178         ----------
179         name : string or list of string
180             Name of new folder to be created or list of new folders and
181             subfolders.
182         parentID : string
183             Google Drive ID of folder that is to be the parent of new folder.
184 
185         Returns
186         -------
187         string
188             The unique Google Drive ID of the bottom-most newly created folder.
189         """
190         import time
191         t = time.time()
192         self._authenticate()
193         print(time.time() - t, "Authenticate")
194         t = time.time()
195         # clean inputs
196         if isinstance(name, str):
197             name = [name]
198         # create
199         parent = parentid
200         for n in name:
201             # check if folder with that name already exists
202             q = {
203                 'q': "'{}' in parents and trashed=false and mimeType contains \'folder\'".format(
204                     parent)}
205             fs = self.api.ListFile(q).GetList()
206             found = False
207             for f in fs:
208                 if f['title'] == n:
209                     found = True
210                     parent = f['id']
211                     continue
212             if found:
213                 continue
214             # if no folder was found, create one
215             f = self.api.CreateFile({'title': n,
216                                      "parents": [{"id": parent}],
217                                      "mimeType": "application/vnd.google-apps.folder"})
218             f.Upload()
219             parent = f['id']
220             print(time.time() - t, "created", n)
221             t = time.time()
222         return parent
223 
224     def download(self, fileid, directory='cwd', overwrite=False, verbose=True):
225         """Recursively download from Google Drive into a local directory.
226 
227         By default, will not re-download if file passes following checks:
228 
229         1. same size as remote file
230 
231         2. local file last modified after remote file
232 
233         Parameters
234         ----------
235         fileid : str
236             Google drive id for file or folder.
237         directory : str (optional)
238             Local directory to save content into. By default saves to cwd.
239         overwrite : bool (optional)
240             Toggle forcing file overwrites. Default is False.
241         verbose : bool (optional)s
242             Toggle talkback. Default is True.
243 
244         Returns
245         -------
246         pydrive.files.GoogleDriveFile
247         """
248         self._authenticate()
249         # get directory
250         if directory == 'cwd':
251             directory = os.getcwd()
252         # get file object
253         f = self.api.CreateFile({'id': fileid})
254         f_path = os.path.join(directory, f['title'])
255         if f['mimeType'].split('.')[-1] == 'folder':  # folder
256             # create folder
257             if not os.path.isdir(f_path):
258                 os.mkdir(f_path)
259             # fill contents
260             for child_id in self._list_folder(fileid):
261                 self.download(child_id, directory=f_path)
262         else:  # single file
263             # check if file exists
264             if os.path.isfile(f_path):
265                 remove = False
266                 statinfo = os.stat(f_path)
267                 # filesize different
268                 if not int(statinfo.st_size) == int(f['fileSize']):
269                     remove = True
270                 # modified since creation
271                 remote_stamp = f['modifiedDate'].split('.')[0]  # UTC
272                 remote_stamp = time.mktime(datetime.datetime.strptime(
273                     remote_stamp, '%Y-%m-%dT%H:%M:%S').timetuple())
274                 local_stamp = os.path.getmtime(f_path)  # local
275                 local_stamp += time.timezone  # UTC
276                 if local_stamp < remote_stamp:
277                     remove = True
278                 # overwrite toggle
279                 if overwrite:
280                     remove = True
281                 # remove
282                 if remove:
283                     os.remove(f_path)
284                 else:
285                     return f
286             # download
287             f.GetContentFile(f_path)
288             if verbose:
289                 print('file downloaded to {}'.format(f_path))
290             # finish
291             return f
292 
293     def list_folder(self, folderid):
294         """List contents of a remote folder.
295 
296         Parameters
297         ----------
298         folderid : string
299             Folder ID.
300 
301         Returns
302         -------
303         list of strings
304             List of contained IDs.
305         """
306         # adapted from https://github.com/googledrive/PyDrive/issues/37
307         # folder_id: GoogleDriveFile['id']
308         self._authenticate()
309         q = {'q': "'{}' in parents and trashed=false".format(folderid)}
310         raw_sub_contents = self.api.ListFile(q).GetList()
311         return [i['id'] for i in raw_sub_contents]
312 
313     def upload(self, path, parentid, overwrite=False, delete_local=False,
314                verbose=True):
315         """Upload local file(s) to Google Drive.
316 
317         Parameters
318         ----------
319         path : str
320             Path to local file or folder.
321         parentid : str
322             Google Drive ID of remote folder.
323         overwrite : bool (optional)
324             Toggle forcing overwrite of remote files. Default is False.
325         delete_local : bool (optional)
326             Toggle deleting local files and folders once uploaded. Default is
327             False.
328         verbose : bool (optional)
329             Toggle talkback. Default is True.
330 
331         Returns
332         -------
333         driveid : str
334             Google Drive ID of folder or file uploaded
335         """
336         self._authenticate()
337         if os.path.isfile(path):
338             return self._upload_file(path, parentid, overwrite=overwrite,
339                                      delete_local=delete_local,
340                                      verbose=verbose)
341         elif os.path.isdir(path):
342             top_path_length = len(path.split(os.path.sep))
343             for tup in os.walk(path, topdown=False):
344                 self._authenticate()
345                 folder_path, _, file_names = tup
346                 print(folder_path)
347                 # create folder on google drive
348                 name = folder_path.split(os.path.sep)[top_path_length - 1:]
349                 folderid = self.create_folder(name, parentid)
350                 # upload files
351                 for file_name in file_names:
352                     p = os.path.join(folder_path, file_name)
353                     self._upload_file(p, folderid, overwrite=overwrite,
354                                       delete_local=delete_local,
355                                       verbose=verbose)
356                 # remove folder
357                 if delete_local:
358                     os.rmdir(folder_path)
359             # finish
360             return folderid
361         else:
362             raise Exception('path {0} not valid in Drive.upload'.format(path))
363
```
--- 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/WrightTools/google_drive.py b/WrightTools/google_drive.py
--- a/WrightTools/google_drive.py
+++ b/WrightTools/google_drive.py
@@ -245,7 +245,7 @@
             if not os.path.isdir(f_path):
                 os.mkdir(f_path)
             # fill contents
-            for child_id in self._list_folder(fileid):
+            for child_id in self.list_folder(fileid):
                 self.download(child_id, directory=f_path)
         else:  # single file
             # check if file exists

{"golden_diff": "diff --git a/WrightTools/google_drive.py b/WrightTools/google_drive.py\n--- a/WrightTools/google_drive.py\n+++ b/WrightTools/google_drive.py\n@@ -245,7 +245,7 @@\n             if not os.path.isdir(f_path):\n                 os.mkdir(f_path)\n             # fill contents\n-            for child_id in self._list_folder(fileid):\n+            for child_id in self.list_folder(fileid):\n                 self.download(child_id, directory=f_path)\n         else:  # single file\n             # check if file exists\n", "issue": "wt.google_drive.Drive.download() calls `self._list_folder()` when it should call `self.list_folder()`\nSee offending [line](https://github.com/wright-group/WrightTools/blob/039507d95561fd237dc7ba66b4d4f37ce6148397/WrightTools/google_drive.py#L248).\r\n\r\n[Line](https://github.com/wright-group/WrightTools/blob/039507d95561fd237dc7ba66b4d4f37ce6148397/WrightTools/google_drive.py#L281) where correct method is defined. \r\n\n", "before_files": [{"content": "\"\"\"Interact with google drive using the pydrive package.\"\"\"\n\n\n# --- import --------------------------------------------------------------------------------------\n\n\nfrom __future__ import absolute_import, division, print_function, unicode_literals\n\nimport os\nimport time\nimport datetime\nimport tempfile\nimport appdirs\nfrom glob import glob\n\n\n# --- define --------------------------------------------------------------------------------------\n\n\ndirectory = os.path.dirname(os.path.abspath(__file__))\n\n\n# --- helper methods ------------------------------------------------------------------------------\n\n\ndef id_to_url(driveid):\n    \"\"\"Generate a url from a Google Drive id.\n\n    Parameters\n    ----------\n    id : string\n        ID.\n\n    Returns\n    -------\n    string\n        url.\n    \"\"\"\n    return 'https://drive.google.com/open?id=' + driveid\n\n\n# --- drive class ---------------------------------------------------------------------------------\n\n\nclass Drive:\n    \"\"\"Google Drive class.\"\"\"\n\n    def __init__(self, account_id='default'):\n        \"\"\"init.\"\"\"\n        # Define the temp directory and file name format\n        configDir = appdirs.user_data_dir('WrightTools', 'WrightGroup')\n        if not os.path.isdir(configDir):\n            os.makedirs(configDir)\n        prefix = 'google-drive-'\n        suffix = '-' + account_id + '.txt'\n        # Check for existing file\n        lis = glob(os.path.join(configDir, prefix + \"*\" + suffix))\n        self.mycreds_path = ''\n        if len(lis) > 0:\n            for f in lis:\n                # Check that for read and write access (or is bitwise, checking both)\n                # Note this check is probably not needed with appdirs, but is not\n                #     harmful and provides additional insurance against crashes.\n                if os.access(f, os.W_OK | os.R_OK):\n                    self.mycreds_path = f\n                    break\n        # Make a new file if one does not exist with sufficent permissions\n        if self.mycreds_path == '':\n            self.mycreds_path = tempfile.mkstemp(prefix=prefix,\n                                                 suffix=suffix,\n                                                 text=True,\n                                                 dir=configDir)[1]\n        self._authenticate()\n\n    def _authenticate(self):\n        \"\"\"Authenticate the user via a web browser.\n\n        This function, once run, will open up a login window in a web browser.\n        The user must then athenticate via email and password to authorize the\n        API for usage with that particular account. Note that 'mycreds.txt' may\n        just be an empty text file. This function will create the correct\n        dictionary structure in the file upon completion.\n        \"\"\"\n        # This function requires a Client_secrets.json file to be in the\n        # working directory.\n        old_cwd = os.getcwd()\n        os.chdir(directory)\n        # import\n        from pydrive.auth import GoogleAuth\n        from pydrive.drive import GoogleDrive\n        # load\n        self.gauth = GoogleAuth()\n        self.gauth.LoadCredentialsFile(self.mycreds_path)\n        if self.gauth.credentials is None:\n            # authenticate if credentials are not found\n            self.gauth.LocalWebserverAuth()\n        elif self.gauth.access_token_expired:\n            # refresh credentials if they are expired\n            self.gauth.Refresh()\n        else:\n            # initialize the saved credentials\n            self.gauth.Authorize()\n        # finish\n        self.gauth.SaveCredentialsFile(self.mycreds_path)\n        self.api = GoogleDrive(self.gauth)\n        os.chdir(old_cwd)\n\n    def _upload_file(self, filepath, parentid, overwrite=False,\n                     delete_local=False, verbose=True):\n        \"\"\"Upload file.\n\n        Parameters\n        ----------\n        filepath : string\n            Filepath.\n        parentid : string\n            Parent ID.\n        overwrite : boolean (optional)\n            Toggle remote overwrite. Default is False.\n        delete_local : boolean (optional).\n            Toggle local deletion after upload. Default is False.\n        verbose : boolean (optional)\n            Toggle talkback. Default is True.\n        \"\"\"\n        self._authenticate()\n        title = filepath.split(os.path.sep)[-1]\n        # check if remote file already exists\n        q = {'q': \"'{}' in parents and trashed=false\".format(parentid)}\n        fs = self.api.ListFile(q).GetList()\n        f = None\n        for fi in fs:\n            # dont want to look at folders\n            if 'folder' in fi['mimeType']:\n                continue\n            if fi['title'] == title:\n                print(title, 'found in upload file')\n                f = fi\n        if f is not None:\n            remove = False\n            statinfo = os.stat(filepath)\n            # filesize different\n            if not int(statinfo.st_size) == int(f['fileSize']):\n                remove = True\n            # modified since creation\n            remote_stamp = f['modifiedDate'].split('.')[0]  # UTC\n            remote_stamp = time.mktime(datetime.datetime.strptime(\n                remote_stamp, '%Y-%m-%dT%H:%M:%S').timetuple())\n            local_stamp = os.path.getmtime(filepath)  # local\n            local_stamp += time.timezone  # UTC\n            if local_stamp > remote_stamp:\n                remove = True\n            # overwrite toggle\n            if overwrite:\n                remove = True\n            # remove\n            if remove:\n                f.Trash()\n                f = None\n        # upload\n        if f is None:\n            f = self.api.CreateFile({'title': title,\n                                     'parents': [{\"id\": parentid}]})\n            f.SetContentFile(filepath)\n            f.Upload()\n            f.content.close()\n            if verbose:\n                print('file uploaded from {}'.format(filepath))\n        # delete local\n        if delete_local:\n            os.remove(filepath)\n        # finish\n        return f['id']\n\n    def create_folder(self, name, parentid):\n        \"\"\"Create a new folder in Google Drive.\n\n        Attributes\n        ----------\n        name : string or list of string\n            Name of new folder to be created or list of new folders and\n            subfolders.\n        parentID : string\n            Google Drive ID of folder that is to be the parent of new folder.\n\n        Returns\n        -------\n        string\n            The unique Google Drive ID of the bottom-most newly created folder.\n        \"\"\"\n        import time\n        t = time.time()\n        self._authenticate()\n        print(time.time() - t, \"Authenticate\")\n        t = time.time()\n        # clean inputs\n        if isinstance(name, str):\n            name = [name]\n        # create\n        parent = parentid\n        for n in name:\n            # check if folder with that name already exists\n            q = {\n                'q': \"'{}' in parents and trashed=false and mimeType contains \\'folder\\'\".format(\n                    parent)}\n            fs = self.api.ListFile(q).GetList()\n            found = False\n            for f in fs:\n                if f['title'] == n:\n                    found = True\n                    parent = f['id']\n                    continue\n            if found:\n                continue\n            # if no folder was found, create one\n            f = self.api.CreateFile({'title': n,\n                                     \"parents\": [{\"id\": parent}],\n                                     \"mimeType\": \"application/vnd.google-apps.folder\"})\n            f.Upload()\n            parent = f['id']\n            print(time.time() - t, \"created\", n)\n            t = time.time()\n        return parent\n\n    def download(self, fileid, directory='cwd', overwrite=False, verbose=True):\n        \"\"\"Recursively download from Google Drive into a local directory.\n\n        By default, will not re-download if file passes following checks:\n\n        1. same size as remote file\n\n        2. local file last modified after remote file\n\n        Parameters\n        ----------\n        fileid : str\n            Google drive id for file or folder.\n        directory : str (optional)\n            Local directory to save content into. By default saves to cwd.\n        overwrite : bool (optional)\n            Toggle forcing file overwrites. Default is False.\n        verbose : bool (optional)s\n            Toggle talkback. Default is True.\n\n        Returns\n        -------\n        pydrive.files.GoogleDriveFile\n        \"\"\"\n        self._authenticate()\n        # get directory\n        if directory == 'cwd':\n            directory = os.getcwd()\n        # get file object\n        f = self.api.CreateFile({'id': fileid})\n        f_path = os.path.join(directory, f['title'])\n        if f['mimeType'].split('.')[-1] == 'folder':  # folder\n            # create folder\n            if not os.path.isdir(f_path):\n                os.mkdir(f_path)\n            # fill contents\n            for child_id in self._list_folder(fileid):\n                self.download(child_id, directory=f_path)\n        else:  # single file\n            # check if file exists\n            if os.path.isfile(f_path):\n                remove = False\n                statinfo = os.stat(f_path)\n                # filesize different\n                if not int(statinfo.st_size) == int(f['fileSize']):\n                    remove = True\n                # modified since creation\n                remote_stamp = f['modifiedDate'].split('.')[0]  # UTC\n                remote_stamp = time.mktime(datetime.datetime.strptime(\n                    remote_stamp, '%Y-%m-%dT%H:%M:%S').timetuple())\n                local_stamp = os.path.getmtime(f_path)  # local\n                local_stamp += time.timezone  # UTC\n                if local_stamp < remote_stamp:\n                    remove = True\n                # overwrite toggle\n                if overwrite:\n                    remove = True\n                # remove\n                if remove:\n                    os.remove(f_path)\n                else:\n                    return f\n            # download\n            f.GetContentFile(f_path)\n            if verbose:\n                print('file downloaded to {}'.format(f_path))\n            # finish\n            return f\n\n    def list_folder(self, folderid):\n        \"\"\"List contents of a remote folder.\n\n        Parameters\n        ----------\n        folderid : string\n            Folder ID.\n\n        Returns\n        -------\n        list of strings\n            List of contained IDs.\n        \"\"\"\n        # adapted from https://github.com/googledrive/PyDrive/issues/37\n        # folder_id: GoogleDriveFile['id']\n        self._authenticate()\n        q = {'q': \"'{}' in parents and trashed=false\".format(folderid)}\n        raw_sub_contents = self.api.ListFile(q).GetList()\n        return [i['id'] for i in raw_sub_contents]\n\n    def upload(self, path, parentid, overwrite=False, delete_local=False,\n               verbose=True):\n        \"\"\"Upload local file(s) to Google Drive.\n\n        Parameters\n        ----------\n        path : str\n            Path to local file or folder.\n        parentid : str\n            Google Drive ID of remote folder.\n        overwrite : bool (optional)\n            Toggle forcing overwrite of remote files. Default is False.\n        delete_local : bool (optional)\n            Toggle deleting local files and folders once uploaded. Default is\n            False.\n        verbose : bool (optional)\n            Toggle talkback. Default is True.\n\n        Returns\n        -------\n        driveid : str\n            Google Drive ID of folder or file uploaded\n        \"\"\"\n        self._authenticate()\n        if os.path.isfile(path):\n            return self._upload_file(path, parentid, overwrite=overwrite,\n                                     delete_local=delete_local,\n                                     verbose=verbose)\n        elif os.path.isdir(path):\n            top_path_length = len(path.split(os.path.sep))\n            for tup in os.walk(path, topdown=False):\n                self._authenticate()\n                folder_path, _, file_names = tup\n                print(folder_path)\n                # create folder on google drive\n                name = folder_path.split(os.path.sep)[top_path_length - 1:]\n                folderid = self.create_folder(name, parentid)\n                # upload files\n                for file_name in file_names:\n                    p = os.path.join(folder_path, file_name)\n                    self._upload_file(p, folderid, overwrite=overwrite,\n                                      delete_local=delete_local,\n                                      verbose=verbose)\n                # remove folder\n                if delete_local:\n                    os.rmdir(folder_path)\n            # finish\n            return folderid\n        else:\n            raise Exception('path {0} not valid in Drive.upload'.format(path))\n", "path": "WrightTools/google_drive.py"}], "after_files": [{"content": "\"\"\"Interact with google drive using the pydrive package.\"\"\"\n\n\n# --- import --------------------------------------------------------------------------------------\n\n\nfrom __future__ import absolute_import, division, print_function, unicode_literals\n\nimport os\nimport time\nimport datetime\n\n\n# --- define --------------------------------------------------------------------------------------\n\n\ndirectory = os.path.dirname(os.path.abspath(__file__))\n\n\n# --- ensure google drive creds folder populated --------------------------------------------------\n\n\ncreds_dir = os.path.join(directory, 'temp', 'google drive')\nif not os.path.isdir(creds_dir):\n    os.mkdir(creds_dir)\n\nmycreds_path = os.path.join(creds_dir, 'mycreds.txt')\nif not os.path.isfile(mycreds_path):\n    open(mycreds_path, 'a').close()\n\n\n# --- helper methods ------------------------------------------------------------------------------\n\n\ndef id_to_url(driveid):\n    \"\"\"Generate a url from a Google Drive id.\n\n    Parameters\n    ----------\n    id : string\n        ID.\n\n    Returns\n    -------\n    string\n        url.\n    \"\"\"\n    return 'https://drive.google.com/open?id=' + driveid\n\n\n# --- drive class ---------------------------------------------------------------------------------\n\n\nclass Drive:\n    \"\"\"Google Drive class.\"\"\"\n\n    def __init__(self):\n        \"\"\"init.\"\"\"\n        # authenticate\n        self.mycreds_path = mycreds_path\n        self._authenticate()\n\n    def _authenticate(self):\n        \"\"\"Authenticate the user via a web browser.\n\n        This function, once run, will open up a login window in a web browser.\n        The user must then athenticate via email and password to authorize the\n        API for usage with that particular account. Note that 'mycreds.txt' may\n        just be an empty text file. This function will create the correct\n        dictionary structure in the file upon completion.\n        \"\"\"\n        # This function requires a Client_secrets.json file to be in the\n        # working directory.\n        old_cwd = os.getcwd()\n        os.chdir(directory)\n        # import\n        from pydrive.auth import GoogleAuth\n        from pydrive.drive import GoogleDrive\n        # load\n        self.gauth = GoogleAuth()\n        self.gauth.LoadCredentialsFile(self.mycreds_path)\n        if self.gauth.credentials is None:\n            # authenticate if credentials are not found\n            self.gauth.LocalWebserverAuth()\n        elif self.gauth.access_token_expired:\n            # refresh credentials if they are expired\n            self.gauth.Refresh()\n        else:\n            # initialize the saved credentials\n            self.gauth.Authorize()\n        # finish\n        self.gauth.SaveCredentialsFile(self.mycreds_path)\n        self.api = GoogleDrive(self.gauth)\n        os.chdir(old_cwd)\n\n    def _upload_file(self, filepath, parentid, overwrite=False,\n                     delete_local=False, verbose=True):\n        \"\"\"Upload file.\n\n        Parameters\n        ----------\n        filepath : string\n            Filepath.\n        parentid : string\n            Parent ID.\n        overwrite : boolean (optional)\n            Toggle remote overwrite. Default is False.\n        delete_local : boolean (optional).\n            Toggle local deletion after upload. Default is False.\n        verbose : boolean (optional)\n            Toggle talkback. Default is True.\n        \"\"\"\n        self._authenticate()\n        title = filepath.split(os.path.sep)[-1]\n        # check if remote file already exists\n        q = {'q': \"'{}' in parents and trashed=false\".format(parentid)}\n        fs = self.api.ListFile(q).GetList()\n        f = None\n        for fi in fs:\n            # dont want to look at folders\n            if 'folder' in fi['mimeType']:\n                continue\n            if fi['title'] == title:\n                print(title, 'found in upload file')\n                f = fi\n        if f is not None:\n            remove = False\n            statinfo = os.stat(filepath)\n            # filesize different\n            if not int(statinfo.st_size) == int(f['fileSize']):\n                remove = True\n            # modified since creation\n            remote_stamp = f['modifiedDate'].split('.')[0]  # UTC\n            remote_stamp = time.mktime(datetime.datetime.strptime(\n                remote_stamp, '%Y-%m-%dT%H:%M:%S').timetuple())\n            local_stamp = os.path.getmtime(filepath)  # local\n            local_stamp += time.timezone  # UTC\n            if local_stamp > remote_stamp:\n                remove = True\n            # overwrite toggle\n            if overwrite:\n                remove = True\n            # remove\n            if remove:\n                f.Trash()\n                f = None\n        # upload\n        if f is None:\n            f = self.api.CreateFile({'title': title,\n                                     'parents': [{\"id\": parentid}]})\n            f.SetContentFile(filepath)\n            f.Upload()\n            f.content.close()\n            if verbose:\n                print('file uploaded from {}'.format(filepath))\n        # delete local\n        if delete_local:\n            os.remove(filepath)\n        # finish\n        return f['id']\n\n    def create_folder(self, name, parentid):\n        \"\"\"Create a new folder in Google Drive.\n\n        Attributes\n        ----------\n        name : string or list of string\n            Name of new folder to be created or list of new folders and\n            subfolders.\n        parentID : string\n            Google Drive ID of folder that is to be the parent of new folder.\n\n        Returns\n        -------\n        string\n            The unique Google Drive ID of the bottom-most newly created folder.\n        \"\"\"\n        import time\n        t = time.time()\n        self._authenticate()\n        print(time.time() - t, \"Authenticate\")\n        t = time.time()\n        # clean inputs\n        if isinstance(name, str):\n            name = [name]\n        # create\n        parent = parentid\n        for n in name:\n            # check if folder with that name already exists\n            q = {\n                'q': \"'{}' in parents and trashed=false and mimeType contains \\'folder\\'\".format(\n                    parent)}\n            fs = self.api.ListFile(q).GetList()\n            found = False\n            for f in fs:\n                if f['title'] == n:\n                    found = True\n                    parent = f['id']\n                    continue\n            if found:\n                continue\n            # if no folder was found, create one\n            f = self.api.CreateFile({'title': n,\n                                     \"parents\": [{\"id\": parent}],\n                                     \"mimeType\": \"application/vnd.google-apps.folder\"})\n            f.Upload()\n            parent = f['id']\n            print(time.time() - t, \"created\", n)\n            t = time.time()\n        return parent\n\n    def download(self, fileid, directory='cwd', overwrite=False, verbose=True):\n        \"\"\"Recursively download from Google Drive into a local directory.\n\n        By default, will not re-download if file passes following checks:\n\n        1. same size as remote file\n\n        2. local file last modified after remote file\n\n        Parameters\n        ----------\n        fileid : str\n            Google drive id for file or folder.\n        directory : str (optional)\n            Local directory to save content into. By default saves to cwd.\n        overwrite : bool (optional)\n            Toggle forcing file overwrites. Default is False.\n        verbose : bool (optional)s\n            Toggle talkback. Default is True.\n\n        Returns\n        -------\n        pydrive.files.GoogleDriveFile\n        \"\"\"\n        self._authenticate()\n        # get directory\n        if directory == 'cwd':\n            directory = os.getcwd()\n        # get file object\n        f = self.api.CreateFile({'id': fileid})\n        f_path = os.path.join(directory, f['title'])\n        if f['mimeType'].split('.')[-1] == 'folder':  # folder\n            # create folder\n            if not os.path.isdir(f_path):\n                os.mkdir(f_path)\n            # fill contents\n            for child_id in self.list_folder(fileid):\n                self.download(child_id, directory=f_path)\n        else:  # single file\n            # check if file exists\n            if os.path.isfile(f_path):\n                remove = False\n                statinfo = os.stat(f_path)\n                # filesize different\n                if not int(statinfo.st_size) == int(f['fileSize']):\n                    remove = True\n                # modified since creation\n                remote_stamp = f['modifiedDate'].split('.')[0]  # UTC\n                remote_stamp = time.mktime(datetime.datetime.strptime(\n                    remote_stamp, '%Y-%m-%dT%H:%M:%S').timetuple())\n                local_stamp = os.path.getmtime(f_path)  # local\n                local_stamp += time.timezone  # UTC\n                if local_stamp < remote_stamp:\n                    remove = True\n                # overwrite toggle\n                if overwrite:\n                    remove = True\n                # remove\n                if remove:\n                    os.remove(f_path)\n                else:\n                    return f\n            # download\n            f.GetContentFile(f_path)\n            if verbose:\n                print('file downloaded to {}'.format(f_path))\n            # finish\n            return f\n\n    def list_folder(self, folderid):\n        \"\"\"List contents of a remote folder.\n\n        Parameters\n        ----------\n        folderid : string\n            Folder ID.\n\n        Returns\n        -------\n        list of strings\n            List of contained IDs.\n        \"\"\"\n        # adapted from https://github.com/googledrive/PyDrive/issues/37\n        # folder_id: GoogleDriveFile['id']\n        self._authenticate()\n        q = {'q': \"'{}' in parents and trashed=false\".format(folderid)}\n        raw_sub_contents = self.api.ListFile(q).GetList()\n        return [i['id'] for i in raw_sub_contents]\n\n    def upload(self, path, parentid, overwrite=False, delete_local=False,\n               verbose=True):\n        \"\"\"Upload local file(s) to Google Drive.\n\n        Parameters\n        ----------\n        path : str\n            Path to local file or folder.\n        parentid : str\n            Google Drive ID of remote folder.\n        overwrite : bool (optional)\n            Toggle forcing overwrite of remote files. Default is False.\n        delete_local : bool (optional)\n            Toggle deleting local files and folders once uploaded. Default is\n            False.\n        verbose : bool (optional)\n            Toggle talkback. Default is True.\n\n        Returns\n        -------\n        driveid : str\n            Google Drive ID of folder or file uploaded\n        \"\"\"\n        self._authenticate()\n        if os.path.isfile(path):\n            return self._upload_file(path, parentid, overwrite=overwrite,\n                                     delete_local=delete_local,\n                                     verbose=verbose)\n        elif os.path.isdir(path):\n            top_path_length = len(path.split(os.path.sep))\n            for tup in os.walk(path, topdown=False):\n                self._authenticate()\n                folder_path, _, file_names = tup\n                print(folder_path)\n                # create folder on google drive\n                name = folder_path.split(os.path.sep)[top_path_length - 1:]\n                folderid = self.create_folder(name, parentid)\n                # upload files\n                for file_name in file_names:\n                    p = os.path.join(folder_path, file_name)\n                    self._upload_file(p, folderid, overwrite=overwrite,\n                                      delete_local=delete_local,\n                                      verbose=verbose)\n                # remove folder\n                if delete_local:\n                    os.rmdir(folder_path)\n            # finish\n            return folderid\n        else:\n            raise Exception('path {0} not valid in Drive.upload'.format(path))\n", "path": "WrightTools/google_drive.py"}]}