Add windows version check, legacy list support

- Add check for windows version for IFileOperation
- Add list support to legacy version
- Remove some debugging code
- Fix bug in path converson

Not sure if there is a better way to layout this file
This commit is contained in:
Andrew Senetar 2020-05-22 00:10:13 -05:00
parent 629c2403e9
commit 6a1b47bc5e
Signed by: arsenetar
GPG Key ID: C63300DCE48AB2F1
1 changed files with 81 additions and 65 deletions

View File

@ -7,13 +7,16 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import os.path as op import os.path as op
from .compat import text_type from .compat import text_type
from platform import version
try: legacy = False
# if windows is vista or newer and pywin32 is available use IFileOperation
if int(version().split(".", 1)[0]) >= 6:
try:
# Attempt to use pywin32 to use IFileOperation # Attempt to use pywin32 to use IFileOperation
import pythoncom import pythoncom
import pywintypes import pywintypes
from win32com.shell import shell, shellcon from win32com.shell import shell, shellcon
from platform import version
def send2trash(path): def send2trash(path):
if not isinstance(path, list): if not isinstance(path, list):
@ -26,7 +29,7 @@ try:
# convert to full paths # convert to full paths
path = [op.abspath(item) if not op.isabs(item) else item for item in path] path = [op.abspath(item) if not op.isabs(item) else item for item in path]
# remove the leading \\?\ if present # remove the leading \\?\ if present
path = [item[4:] for item in path if item.startswith("\\\\?\\")] path = [item[4:] if item.startswith("\\\\?\\") else item for item in path]
# create instance of file operation object # create instance of file operation object
fileop = pythoncom.CoCreateInstance( fileop = pythoncom.CoCreateInstance(
shell.CLSID_FileOperation, shell.CLSID_FileOperation,
@ -43,7 +46,7 @@ try:
) )
# determine rest of the flags based on OS version # determine rest of the flags based on OS version
# use newer recommended flags if available # use newer recommended flags if available
if int(version().split(".", 1)[0]) >= 8 and False: if int(version().split(".", 1)[0]) >= 8:
flags |= ( flags |= (
0x20000000 # FOFX_ADDUNDORECORD win 8+ 0x20000000 # FOFX_ADDUNDORECORD win 8+
| 0x00080000 # FOFX_RECYCLEONDELETE win 8+ | 0x00080000 # FOFX_RECYCLEONDELETE win 8+
@ -71,8 +74,13 @@ try:
# normal errno # normal errno
raise OSError(None, error.strerror, path, error.hresult) raise OSError(None, error.strerror, path, error.hresult)
except ImportError:
legacy = True
else:
legacy = True
except ImportError: # use SHFileOperation as fallback
if legacy:
from ctypes import ( from ctypes import (
windll, windll,
Structure, Structure,
@ -128,11 +136,19 @@ except ImportError:
return output.value[4:] # Remove '\\?\' for SHFileOperationW return output.value[4:] # Remove '\\?\' for SHFileOperationW
def send2trash(path): def send2trash(path):
if not isinstance(path, text_type): if not isinstance(path, list):
path = text_type(path, "mbcs") path = [path]
if not op.isabs(path): # convert data type
path = op.abspath(path) path = [
path = get_short_path_name(path) text_type(item, "mbcs") if not isinstance(item, text_type) else item
for item in path
]
# convert to full paths
path = [op.abspath(item) if not op.isabs(item) else item for item in path]
# get short path to handle path length issues
path = [get_short_path_name(item) for item in path]
# convert to a single string of null terminated paths
path = "\0".join(path)
fileop = SHFILEOPSTRUCTW() fileop = SHFILEOPSTRUCTW()
fileop.hwnd = 0 fileop.hwnd = 0
fileop.wFunc = FO_DELETE fileop.wFunc = FO_DELETE