Repository: wright-group/WrightTools

Issue:
Use the builtin temporary file directory libraries
https://docs.python.org/3.6/library/tempfile.html

Currently we roll our own, which results in the temp folder being in with the code, which is inelegant and confusing. This library will handle cross platform support in expected locations for temp files.

We do need to be careful not to break anything and to ensure that files are not deleted if the program crashes. That was a core part of how the current system was designed, and should not be lost. All that is intended is that the location of the temp folder is changed


Discussion:
Note that doing so in this way will enable us to more properly import our libraries in `__init__` and thus avoid flake8 warnings. Currently moving the imports above the code that creates the temp folder causes it to fail unless the temp folder is already present

Resolving patch:
diff --git a/WrightTools/__init__.py b/WrightTools/__init__.py
--- a/WrightTools/__init__.py
+++ b/WrightTools/__init__.py
@@ -10,16 +10,6 @@
 import matplotlib as _matplotlib
 
 
-# --- temp directory ------------------------------------------------------------------------------
-
-
-_here = _os.path.abspath(_os.path.dirname(__file__))
-
-_temp_dir = _os.path.join(_here, 'temp')
-if not _os.path.isdir(_temp_dir):
-    _os.mkdir(_temp_dir)
-
-
 # --- import --------------------------------------------------------------------------------------
 
 
@@ -38,6 +28,7 @@
 
 
 # read from VERSION file
+_here = _os.path.abspath(_os.path.dirname(__file__))
 with open(_os.path.join(_os.path.dirname(_here), 'VERSION')) as _version_file:
     __version__ = _version_file.read().strip()
 
diff --git a/WrightTools/google_drive.py b/WrightTools/google_drive.py
--- a/WrightTools/google_drive.py
+++ b/WrightTools/google_drive.py
@@ -9,6 +9,9 @@
 import os
 import time
 import datetime
+import tempfile
+import appdirs
+from glob import glob
 
 
 # --- define --------------------------------------------------------------------------------------
@@ -17,18 +20,6 @@
 directory = os.path.dirname(os.path.abspath(__file__))
 
 
-# --- ensure google drive creds folder populated --------------------------------------------------
-
-
-creds_dir = os.path.join(directory, 'temp', 'google drive')
-if not os.path.isdir(creds_dir):
-    os.mkdir(creds_dir)
-
-mycreds_path = os.path.join(creds_dir, 'mycreds.txt')
-if not os.path.isfile(mycreds_path):
-    open(mycreds_path, 'a').close()
-
-
 # --- helper methods ------------------------------------------------------------------------------
 
 
@@ -54,10 +45,31 @@ def id_to_url(driveid):
 class Drive:
     """Google Drive class."""
 
-    def __init__(self):
+    def __init__(self, account_id='default'):
         """init."""
-        # authenticate
-        self.mycreds_path = mycreds_path
+        # Define the temp directory and file name format
+        configDir = appdirs.user_data_dir('WrightTools', 'WrightGroup')
+        if not os.path.isdir(configDir):
+            os.makedirs(configDir)
+        prefix = 'google-drive-'
+        suffix = '-' + account_id + '.txt'
+        # Check for existing file
+        lis = glob(os.path.join(configDir, prefix + "*" + suffix))
+        self.mycreds_path = ''
+        if len(lis) > 0:
+            for f in lis:
+                # Check that for read and write access (or is bitwise, checking both)
+                # Note this check is probably not needed with appdirs, but is not
+                #     harmful and provides additional insurance against crashes.
+                if os.access(f, os.W_OK | os.R_OK):
+                    self.mycreds_path = f
+                    break
+        # Make a new file if one does not exist with sufficent permissions
+        if self.mycreds_path == '':
+            self.mycreds_path = tempfile.mkstemp(prefix=prefix,
+                                                 suffix=suffix,
+                                                 text=True,
+                                                 dir=configDir)[1]
         self._authenticate()
 
     def _authenticate(self):


Test patch: