]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blobdiff - src/allmydata/util/fileutil.py
remove dead code: NamedTemporaryDirectory
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / util / fileutil.py
index 466361d992e1cdd51509c78275e1fadf8444c338..a2c3841f7837d28032988b4656e266209eb9056d 100644 (file)
@@ -87,34 +87,6 @@ class ReopenableNamedTemporaryFile:
     def shutdown(self):
         remove(self.name)
 
-class NamedTemporaryDirectory:
-    """
-    This calls tempfile.mkdtemp(), stores the name of the dir in
-    self.name, and rmrf's the dir when it gets garbage collected or
-    "shutdown()".
-    """
-    def __init__(self, cleanup=True, *args, **kwargs):
-        """ If cleanup, then the directory will be rmrf'ed when the object is shutdown. """
-        self.cleanup = cleanup
-        self.name = tempfile.mkdtemp(*args, **kwargs)
-
-    def __repr__(self):
-        return "<%s instance at %x %s>" % (self.__class__.__name__, id(self), self.name)
-
-    def __str__(self):
-        return self.__repr__()
-
-    def __del__(self):
-        try:
-            self.shutdown()
-        except:
-            import traceback
-            traceback.print_exc()
-
-    def shutdown(self):
-        if self.cleanup and hasattr(self, 'name'):
-            rm_dir(self.name)
-
 class EncryptedTemporaryFile:
     # not implemented: next, readline, readlines, xreadlines, writelines
 
@@ -315,13 +287,17 @@ def abspath_expanduser_unicode(path, base=None):
     if base is not None:
         precondition_abspath(base)
 
-    path = os.path.expanduser(path)
+    path = expanduser(path)
 
     if _getfullpathname:
-        # On Windows, os.path.isabs will return True for paths without a drive letter,
+        # On Windows, os.path.isabs will incorrectly return True
+        # for paths without a drive letter (that are not UNC paths),
         # e.g. "\\". See <http://bugs.python.org/issue1669539>.
         try:
-            path = _getfullpathname(path or u".")
+            if base is None:
+                path = _getfullpathname(path or u".")
+            else:
+                path = _getfullpathname(os.path.join(base, path))
         except OSError:
             pass
 
@@ -359,25 +335,95 @@ def to_windows_long_path(path):
 
 have_GetDiskFreeSpaceExW = False
 if sys.platform == "win32":
-    try:
-        from ctypes import WINFUNCTYPE, windll, POINTER, byref, c_ulonglong
-        from ctypes.wintypes import BOOL, DWORD, LPCWSTR
+    from ctypes import WINFUNCTYPE, windll, POINTER, byref, c_ulonglong, create_unicode_buffer, \
+        get_last_error
+    from ctypes.wintypes import BOOL, DWORD, LPCWSTR, LPWSTR
 
+    # <http://msdn.microsoft.com/en-us/library/windows/desktop/ms683188%28v=vs.85%29.aspx>
+    GetEnvironmentVariableW = WINFUNCTYPE(
+        DWORD,
+          LPCWSTR, LPWSTR, DWORD,
+        use_last_error=True
+      )(("GetEnvironmentVariableW", windll.kernel32))
+
+    try:
         # <http://msdn.microsoft.com/en-us/library/aa383742%28v=VS.85%29.aspx>
         PULARGE_INTEGER = POINTER(c_ulonglong)
 
         # <http://msdn.microsoft.com/en-us/library/aa364937%28VS.85%29.aspx>
-        GetDiskFreeSpaceExW = WINFUNCTYPE(BOOL, LPCWSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER)(
-            ("GetDiskFreeSpaceExW", windll.kernel32))
-
-        # <http://msdn.microsoft.com/en-us/library/ms679360%28v=VS.85%29.aspx>
-        GetLastError = WINFUNCTYPE(DWORD)(("GetLastError", windll.kernel32))
+        GetDiskFreeSpaceExW = WINFUNCTYPE(
+            BOOL,
+              LPCWSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER,
+            use_last_error=True
+          )(("GetDiskFreeSpaceExW", windll.kernel32))
 
         have_GetDiskFreeSpaceExW = True
     except Exception:
         import traceback
         traceback.print_exc()
 
+def expanduser(path):
+    # os.path.expanduser is hopelessly broken for Unicode paths on Windows (ticket #1674).
+    if sys.platform == "win32":
+        return windows_expanduser(path)
+    else:
+        return os.path.expanduser(path)
+
+def windows_expanduser(path):
+    if not path.startswith('~'):
+        return path
+
+    home_dir = windows_getenv(u'USERPROFILE')
+    if home_dir is None:
+        home_drive = windows_getenv(u'HOMEDRIVE')
+        home_path = windows_getenv(u'HOMEPATH')
+        if home_drive is None or home_path is None:
+            raise OSError("Could not find home directory: neither %USERPROFILE% nor (%HOMEDRIVE% and %HOMEPATH%) are set.")
+        home_dir = os.path.join(home_drive, home_path)
+
+    if path == '~':
+        return home_dir
+    elif path.startswith('~/') or path.startswith('~\\'):
+        return os.path.join(home_dir, path[2 :])
+    else:
+        return path
+
+# <https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382%28v=vs.85%29.aspx>
+ERROR_ENVVAR_NOT_FOUND = 203
+
+def windows_getenv(name):
+    # Based on <http://stackoverflow.com/questions/2608200/problems-with-umlauts-in-python-appdata-environvent-variable/2608368#2608368>,
+    # with improved error handling. Returns None if there is no enivronment variable of the given name.
+    if not isinstance(name, unicode):
+        raise AssertionError("name must be Unicode")
+
+    n = GetEnvironmentVariableW(name, None, 0)
+    # GetEnvironmentVariableW returns DWORD, so n cannot be negative.
+    if n == 0:
+        err = get_last_error()
+        if err == ERROR_ENVVAR_NOT_FOUND:
+            return None
+        raise OSError("Windows error %d attempting to read size of environment variable %r"
+                      % (err, name))
+    if n == 1:
+        # Avoid an ambiguity between a zero-length string and an error in the return value of the
+        # call to GetEnvironmentVariableW below.
+        return u""
+
+    buf = create_unicode_buffer(u'\0'*n)
+    retval = GetEnvironmentVariableW(name, buf, n)
+    if retval == 0:
+        err = get_last_error()
+        if err == ERROR_ENVVAR_NOT_FOUND:
+            return None
+        raise OSError("Windows error %d attempting to read environment variable %r"
+                      % (err, name))
+    if retval >= n:
+        raise OSError("Unexpected result %d (expected less than %d) from GetEnvironmentVariableW attempting to read environment variable %r"
+                      % (retval, n, name))
+
+    return buf.value
+
 def get_disk_stats(whichdir, reserved_space=0):
     """Return disk statistics for the storage disk, in the form of a dict
     with the following fields.
@@ -414,7 +460,7 @@ def get_disk_stats(whichdir, reserved_space=0):
                                                byref(n_free_for_root))
         if retval == 0:
             raise OSError("Windows error %d attempting to get disk statistics for %r"
-                          % (GetLastError(), whichdir))
+                          % (get_last_error(), whichdir))
         free_for_nonroot = n_free_for_nonroot.value
         total            = n_total.value
         free_for_root    = n_free_for_root.value