Streamlined some code in the filesystem utilities module. eric7

Tue, 18 Mar 2025 18:14:12 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Tue, 18 Mar 2025 18:14:12 +0100
branch
eric7
changeset 11173
d63911a89570
parent 11172
a5bbcf506ef0
child 11174
ab097070aedf

Streamlined some code in the filesystem utilities module.

src/eric7/SystemUtilities/FileSystemUtilities.py file | annotate | diff | comparison | revisions
--- a/src/eric7/SystemUtilities/FileSystemUtilities.py	Mon Mar 17 17:58:39 2025 +0100
+++ b/src/eric7/SystemUtilities/FileSystemUtilities.py	Tue Mar 18 18:14:12 2025 +0100
@@ -8,7 +8,6 @@
 """
 
 import contextlib
-import ctypes
 import fnmatch
 import os
 import pathlib
@@ -533,7 +532,7 @@
         return []
 
 
-def findVolume(volumeName, findAll=False):
+def findVolume(volumeName, findAll=False, markerFile=None):
     """
     Function to find the directory belonging to a given volume name.
 
@@ -542,87 +541,81 @@
     @param findAll flag indicating to get the directories for all volumes
         starting with the given name (defaults to False)
     @type bool (optional)
+    @param markerFile name of a file to check for its existence (defaults to None)
+    @type str (optional)
     @return directory path or list of directory paths for the given volume
         name
     @rtype str or list of str
     """
-    volumeDirectories = []
-    volumeDirectory = None
-
     if OSUtilities.isWindowsPlatform():
         # we are on a Windows platform
-        def getVolumeName(diskName):
-            """
-            Local function to determine the volume of a disk or device.
-
-            Each disk or external device connected to windows has an
-            attribute called "volume name". This function returns the
-            volume name for the given disk/device.
+        drives = []
+        output = subprocess.run(
+            [
+                "wmic",
+                "PATH",
+                "Win32_LogicalDisk",
+                "get",
+                "DeviceID,",
+                "DriveType,",
+                "FileSystem,",
+                "VolumeName",
+            ],
+            check=True,
+            capture_output=True,
+            text=True,
+            encoding="utf-8",
+        ).stdout.splitlines()
 
-            Code from http://stackoverflow.com/a/12056414
-            """
-            volumeNameBuffer = ctypes.create_unicode_buffer(1024)
-            ctypes.windll.kernel32.GetVolumeInformationW(
-                ctypes.c_wchar_p(diskName),
-                volumeNameBuffer,
-                ctypes.sizeof(volumeNameBuffer),
-                None,
-                None,
-                None,
-                None,
-                0,
-            )
-            return volumeNameBuffer.value
+        for line in output:
+            words = line.split()
+            if len(words) >= 4 and words[1] == "2" and words[2] == "FAT":
+                drive = words[0]
+                volume = " ".join(words[3:])
+                if findAll:
+                    if volume.startswith(volumeName):
+                        drives.append(f"{drive}\\")
+                else:
+                    if volume == volumeName:
+                        return f"{drive}\\"
 
-        #
-        # In certain circumstances, volumes are allocated to USB
-        # storage devices which cause a Windows popup to raise if their
-        # volume contains no media. Wrapping the check in SetErrorMode
-        # with SEM_FAILCRITICALERRORS (1) prevents this popup.
-        #
-        oldMode = ctypes.windll.kernel32.SetErrorMode(1)
-        try:
-            for disk in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
-                dirpath = "{0}:\\".format(disk)
-                if os.path.exists(dirpath):
-                    if findAll:
-                        if getVolumeName(dirpath).startswith(volumeName):
-                            volumeDirectories.append(dirpath)
-                    else:
-                        if getVolumeName(dirpath) == volumeName:
-                            volumeDirectory = dirpath
-                            break
-        finally:
-            ctypes.windll.kernel32.SetErrorMode(oldMode)
+        return drives
     else:
         # we are on a Linux, FreeBSD or macOS platform
-        for mountCommand in ["mount", "/sbin/mount", "/usr/sbin/mount"]:
-            with contextlib.suppress(FileNotFoundError):
-                mountOutput = subprocess.run(  # secok
-                    mountCommand, check=True, capture_output=True, text=True
-                ).stdout.splitlines()
-                mountedVolumes = [
-                    x.split(" type", 1)[0].split(" (", 1)[0].split(maxsplit=2)[-1]
-                    for x in mountOutput
-                ]
-                if findAll:
-                    for volume in mountedVolumes:
-                        if os.path.basename(volume).startswith(volumeName):
-                            volumeDirectories.append(volume)
-                    if volumeDirectories:
-                        break
-                else:
-                    for volume in mountedVolumes:
-                        if os.path.basename(volume) == volumeName:
-                            volumeDirectory = volume
-                            break
-                    if volumeDirectory:
-                        break
+        # FreeBSD needs a marker file because it does not use the volume name.
+        directories = []
+        if OSUtilities.isMacPlatform():
+            # macOS
+            mountPathStart = "/Volumes"
+        elif OSUtilities.isLinuxPlatform():
+            # Linux
+            mountPathStart = "/media/{0}/".format(OSUtilities.getUserName())
+            if not os.path.isdir(mountPathStart):
+                # no user mount available
+                return [] if findAll else None
+        elif OSUtilities.isFreeBsdPlatform():
+            # FreeBSD
+            mountPathStart = "/media/"
+        else:
+            # unsupported platform
+            return [] if findAll else None
 
-    if findAll:
-        return volumeDirectories
-    else:
-        return volumeDirectory
+        for d in os.listdir(mountPathStart):
+            dPath = os.path.join(mountPathStart, d)
+            if findAll:
+                if d.startswith(volumeName) or (
+                    markerFile is not None
+                    and os.path.exists(os.path.join(dPath, markerFile))
+                ):
+                    directories.append(dPath)
+            else:
+                if d == volumeName or (
+                    markerFile is not None
+                    and os.path.exists(os.path.join(dPath, markerFile))
+                ):
+                    return dPath
+
+        return directories
 
 
 def getUserMounts():
@@ -634,14 +627,13 @@
     @return list of user mounts or drives
     @rtype list of str
     """
-    mountedPaths = []
-
     if OSUtilities.isWindowsPlatform():
         # we are on a Windows platform
-        for disk in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
-            dirpath = "{0}:\\".format(disk)
-            if os.path.exists(dirpath):
-                mountedPaths.append(dirpath)
+        return [
+            f"{disk}:\\"
+            for disk in "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+            if os.path.exists(f"{disk}:\\")
+        ]
     else:
         # we are on a Linux, FreeBSD or macOS platform
         if OSUtilities.isMacPlatform():
@@ -650,6 +642,9 @@
         elif OSUtilities.isLinuxPlatform():
             # Linux
             mountPathStart = "/media/{0}/".format(OSUtilities.getUserName())
+            if not os.path.isdir(mountPathStart):
+                # no user mount available
+                return []
         elif OSUtilities.isFreeBsdPlatform():
             # FreeBSD
             mountPathStart = "/media/"
@@ -657,19 +652,7 @@
             # unsupported platform
             return []
 
-        for mountCommand in ["mount", "/sbin/mount", "/usr/sbin/mount"]:
-            with contextlib.suppress(FileNotFoundError):
-                mountOutput = subprocess.run(  # secok
-                    mountCommand, check=True, capture_output=True, text=True
-                ).stdout.splitlines()
-                mounts = [
-                    x.split(" type", 1)[0].split(" (", 1)[0].split(maxsplit=2)[-1]
-                    for x in mountOutput
-                ]
-                mountedPaths = [x for x in mounts if x.startswith(mountPathStart)]
-                break
-
-    return mountedPaths
+        return [os.path.join(mountPathStart, d) for d in os.listdir(mountPathStart)]
 
 
 def startfile(filePath):

eric ide

mercurial