mirror of
https://github.com/arsenetar/send2trash.git
synced 2025-08-30 12:39:43 +00:00
Compare commits
3 Commits
af0c1ba704
...
10c7693d11
Author | SHA1 | Date | |
---|---|---|---|
10c7693d11 | |||
356509120b | |||
f9fcdb8d8c |
@ -77,8 +77,6 @@ def send2trash(paths):
|
|||||||
paths = [op.abspath(path) if not op.isabs(path) else path for path in paths]
|
paths = [op.abspath(path) if not op.isabs(path) else path for path in paths]
|
||||||
# get short path to handle path length issues
|
# get short path to handle path length issues
|
||||||
paths = [get_short_path_name(path) for path in paths]
|
paths = [get_short_path_name(path) for path in paths]
|
||||||
# convert to a single string of null terminated paths
|
|
||||||
paths = "\0".join(paths)
|
|
||||||
fileop = SHFILEOPSTRUCTW()
|
fileop = SHFILEOPSTRUCTW()
|
||||||
fileop.hwnd = 0
|
fileop.hwnd = 0
|
||||||
fileop.wFunc = FO_DELETE
|
fileop.wFunc = FO_DELETE
|
||||||
@ -93,7 +91,15 @@ def send2trash(paths):
|
|||||||
# NOTE: based on how python allocates memory for these types they should
|
# NOTE: based on how python allocates memory for these types they should
|
||||||
# always be zero, if this is ever not true we can go back to explicitly
|
# always be zero, if this is ever not true we can go back to explicitly
|
||||||
# setting the last two characters to null using buffer[index] = '\0'.
|
# setting the last two characters to null using buffer[index] = '\0'.
|
||||||
buffer = create_unicode_buffer(paths, len(paths) + 2)
|
# Additional note on another issue here, unicode_buffer expects length in
|
||||||
|
# bytes essentially, so having multi-byte characters causes issues if just
|
||||||
|
# passing pythons string length. Instead of dealing with this difference we
|
||||||
|
# just create a buffer then a new one with an extra null. Since the non-length
|
||||||
|
# specified version apparently stops after the first null, join with a space first.
|
||||||
|
buffer = create_unicode_buffer(" ".join(paths))
|
||||||
|
# convert to a single string of null terminated paths
|
||||||
|
path_string = "\0".join(paths)
|
||||||
|
buffer = create_unicode_buffer(path_string, len(buffer) + 1)
|
||||||
fileop.pFrom = LPCWSTR(addressof(buffer))
|
fileop.pFrom = LPCWSTR(addressof(buffer))
|
||||||
fileop.pTo = None
|
fileop.pTo = None
|
||||||
fileop.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT
|
fileop.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT
|
||||||
|
@ -32,6 +32,7 @@ def testfile():
|
|||||||
dir=op.expanduser("~"), prefix="send2trash_test", delete=False
|
dir=op.expanduser("~"), prefix="send2trash_test", delete=False
|
||||||
)
|
)
|
||||||
file.close()
|
file.close()
|
||||||
|
assert op.exists(file.name) is True
|
||||||
yield file
|
yield file
|
||||||
# Cleanup trash files on supported platforms
|
# Cleanup trash files on supported platforms
|
||||||
if sys.platform != "win32":
|
if sys.platform != "win32":
|
||||||
@ -57,6 +58,7 @@ def testfiles():
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
[file.close() for file in files]
|
[file.close() for file in files]
|
||||||
|
assert all([op.exists(file.name) for file in files]) is True
|
||||||
yield files
|
yield files
|
||||||
filenames = [op.basename(file.name) for file in files]
|
filenames = [op.basename(file.name) for file in files]
|
||||||
[os.remove(op.join(HOMETRASH, "files", filename)) for filename in filenames]
|
[os.remove(op.join(HOMETRASH, "files", filename)) for filename in filenames]
|
||||||
@ -93,6 +95,7 @@ def testUnicodefile():
|
|||||||
name = u"send2trash_tést1"
|
name = u"send2trash_tést1"
|
||||||
file = op.join(op.expanduser(b"~"), name.encode("utf-8"))
|
file = op.join(op.expanduser(b"~"), name.encode("utf-8"))
|
||||||
touch(file)
|
touch(file)
|
||||||
|
assert op.exists(file) is True
|
||||||
yield file
|
yield file
|
||||||
# Cleanup trash files on supported platforms
|
# Cleanup trash files on supported platforms
|
||||||
if sys.platform != "win32":
|
if sys.platform != "win32":
|
||||||
@ -158,6 +161,7 @@ def testExtVol():
|
|||||||
fileName = "test.txt"
|
fileName = "test.txt"
|
||||||
filePath = op.join(volume.trashTopdir, fileName)
|
filePath = op.join(volume.trashTopdir, fileName)
|
||||||
touch(filePath)
|
touch(filePath)
|
||||||
|
assert op.exists(filePath) is True
|
||||||
yield volume, fileName, filePath
|
yield volume, fileName, filePath
|
||||||
volume.cleanup()
|
volume.cleanup()
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ def _create_tree(path):
|
|||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def testdir(tmp_path):
|
def testdir(tmp_path):
|
||||||
dirname = "\\\\?\\" + str(tmp_path)
|
dirname = "\\\\?\\" + str(tmp_path)
|
||||||
|
assert op.exists(dirname) is True
|
||||||
yield dirname
|
yield dirname
|
||||||
shutil.rmtree(dirname, ignore_errors=True)
|
shutil.rmtree(dirname, ignore_errors=True)
|
||||||
|
|
||||||
@ -34,6 +35,7 @@ def testdir(tmp_path):
|
|||||||
def testfile(testdir):
|
def testfile(testdir):
|
||||||
file = op.join(testdir, "testfile.txt")
|
file = op.join(testdir, "testfile.txt")
|
||||||
_create_tree(file)
|
_create_tree(file)
|
||||||
|
assert op.exists(file) is True
|
||||||
yield file
|
yield file
|
||||||
# Note dir will cleanup the file
|
# Note dir will cleanup the file
|
||||||
|
|
||||||
@ -42,6 +44,7 @@ def testfile(testdir):
|
|||||||
def testfiles(testdir):
|
def testfiles(testdir):
|
||||||
files = [op.join(testdir, "testfile{}.txt".format(index)) for index in range(10)]
|
files = [op.join(testdir, "testfile{}.txt".format(index)) for index in range(10)]
|
||||||
[_create_tree(file) for file in files]
|
[_create_tree(file) for file in files]
|
||||||
|
assert all([op.exists(file) for file in files]) is True
|
||||||
yield files
|
yield files
|
||||||
# Note dir will cleanup the files
|
# Note dir will cleanup the files
|
||||||
|
|
||||||
@ -66,6 +69,19 @@ def _file_not_found(dir, fcn):
|
|||||||
pytest.raises(OSError, fcn, file)
|
pytest.raises(OSError, fcn, file)
|
||||||
|
|
||||||
|
|
||||||
|
def _multi_byte_unicode(dir, fcn):
|
||||||
|
single_file = op.join(dir, "😇.txt")
|
||||||
|
_create_tree(single_file)
|
||||||
|
assert op.exists(single_file) is True
|
||||||
|
fcn(single_file)
|
||||||
|
assert op.exists(single_file) is False
|
||||||
|
files = [op.join(dir, "😇{}.txt".format(index)) for index in range(10)]
|
||||||
|
[_create_tree(file) for file in files]
|
||||||
|
assert all([op.exists(file) for file in files]) is True
|
||||||
|
fcn(files)
|
||||||
|
assert any([op.exists(file) for file in files]) is False
|
||||||
|
|
||||||
|
|
||||||
def test_trash_folder(testdir):
|
def test_trash_folder(testdir):
|
||||||
_trash_folder(testdir, s2t)
|
_trash_folder(testdir, s2t)
|
||||||
|
|
||||||
@ -98,6 +114,10 @@ def test_file_not_found_modern(testdir):
|
|||||||
_file_not_found(testdir, s2t_modern)
|
_file_not_found(testdir, s2t_modern)
|
||||||
|
|
||||||
|
|
||||||
|
def test_multi_byte_unicode_modern(testdir):
|
||||||
|
_multi_byte_unicode(testdir, s2t_modern)
|
||||||
|
|
||||||
|
|
||||||
def test_trash_folder_legacy(testdir):
|
def test_trash_folder_legacy(testdir):
|
||||||
_trash_folder(testdir, s2t_legacy)
|
_trash_folder(testdir, s2t_legacy)
|
||||||
|
|
||||||
@ -114,6 +134,10 @@ def test_file_not_found_legacy(testdir):
|
|||||||
_file_not_found(testdir, s2t_legacy)
|
_file_not_found(testdir, s2t_legacy)
|
||||||
|
|
||||||
|
|
||||||
|
def test_multi_byte_unicode_legacy(testdir):
|
||||||
|
_multi_byte_unicode(testdir, s2t_legacy)
|
||||||
|
|
||||||
|
|
||||||
# Long path tests
|
# Long path tests
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def longdir(tmp_path):
|
def longdir(tmp_path):
|
||||||
@ -129,6 +153,7 @@ def longfile(longdir):
|
|||||||
path = op.join(longdir, name + "{}.txt")
|
path = op.join(longdir, name + "{}.txt")
|
||||||
file = path.format("")
|
file = path.format("")
|
||||||
_create_tree(file)
|
_create_tree(file)
|
||||||
|
assert op.exists(file) is True
|
||||||
yield file
|
yield file
|
||||||
|
|
||||||
|
|
||||||
@ -138,11 +163,14 @@ def longfiles(longdir):
|
|||||||
path = op.join(longdir, name + "{}.txt")
|
path = op.join(longdir, name + "{}.txt")
|
||||||
files = [path.format(index) for index in range(10)]
|
files = [path.format(index) for index in range(10)]
|
||||||
[_create_tree(file) for file in files]
|
[_create_tree(file) for file in files]
|
||||||
|
assert all([op.exists(file) for file in files]) is True
|
||||||
yield files
|
yield files
|
||||||
|
|
||||||
|
|
||||||
# NOTE: both legacy and modern test "pass" on windows, but actually are not moving files to the
|
# NOTE: both legacy and modern test "pass" on windows, however sometimes with the same path
|
||||||
# recycle bin, this was tested on latest windows 10, thought to have worked previously
|
# they do not actually recycle files but delete them. Noticed this when testing with the
|
||||||
|
# recycle bin open, noticed later tests actually worked, modern version can actually detect
|
||||||
|
# when this happens but not stop it at this moment, and we need a way to verify it when testing.
|
||||||
def test_trash_long_file_modern(longfile):
|
def test_trash_long_file_modern(longfile):
|
||||||
_trash_file(longfile, s2t_modern)
|
_trash_file(longfile, s2t_modern)
|
||||||
|
|
||||||
|
@ -18,6 +18,8 @@ def file():
|
|||||||
dir=op.expanduser("~"), prefix="send2trash_test", delete=False
|
dir=op.expanduser("~"), prefix="send2trash_test", delete=False
|
||||||
)
|
)
|
||||||
file.close()
|
file.close()
|
||||||
|
# Verify file was actually created
|
||||||
|
assert op.exists(file.name) is True
|
||||||
yield file.name
|
yield file.name
|
||||||
# Cleanup trash files on supported platforms
|
# Cleanup trash files on supported platforms
|
||||||
if sys.platform != "win32":
|
if sys.platform != "win32":
|
||||||
|
Loading…
x
Reference in New Issue
Block a user