Python library to natively send files to Trash (or Recycle bin) on all platforms.

Overview

Send2Trash -- Send files to trash on all platforms

Send2Trash is a small package that sends files to the Trash (or Recycle Bin) natively and on all platforms. On OS X, it uses native FSMoveObjectToTrashSync Cocoa calls. On Windows, it uses native IFileOperation call if on Vista or newer and pywin32 is installed or falls back to SHFileOperation calls. On other platforms, if PyGObject and GIO are available, it will use this. Otherwise, it will fallback to its own implementation of the trash specifications from freedesktop.org.

ctypes is used to access native libraries, so no compilation is necessary.

Send2Trash supports Python 2.7 and up (Python 3 is supported).

Status: Additional Help Welcome

Additional help is welcome for supporting this package. Specifically help with the OSX and Linux issues and fixes would be most appreciated.

Installation

You can download it with pip:

python -m pip install -U send2trash

or you can download the source from http://github.com/arsenetar/send2trash and install it with:

>>> python setup.py install

Usage

>>> from send2trash import send2trash
>>> send2trash('some_file')
>>> send2trash(['some_file1', 'some_file2'])

On Freedesktop platforms (Linux, BSD, etc.), you may not be able to efficiently trash some files. In these cases, an exception send2trash.TrashPermissionError is raised, so that the application can handle this case. This inherits from PermissionError (OSError on Python 2). Specifically, this affects files on a different device to the user's home directory, where the root of the device does not have a .Trash directory, and we don't have permission to create a .Trash-$UID directory.

For any other problem, OSError is raised.

Comments
  • Windows Performance Improvement & Multi-Item support

    Windows Performance Improvement & Multi-Item support

    • Use pywin32 to implement IFileOperation
    • Add ability to allow passing a list of files to send2trash across all platforms
    • Batch trash operations on windows for both IFileOperation and SHFileOperation

    Notes:

    • My code format plugin formatted the contents of the files I changed, let me know if this is an issue and I can back those out (it fixed some flake8 style issues as well)
    • IFileOperation should open up the ability to address #28 but I'll add in the extras for that in another PR.
    opened by arsenetar 11
  • Fails with python 3.6.3 on windows

    Fails with python 3.6.3 on windows

    I get the following when calling send2trash on python 3.6.3 on windows 7: File "...\AppData\Local\Programs\Python\Python36\lib\site-packages\send2trash\plat_win.py", line 49, in send2trash fileop.pFrom = LPCWSTR(path + '\0') ValueError: embedded null character

    I'm pretty sure it didn't fail until I switched to 3.6.3. My guess is that this fix is responsible.

    opened by rkhwaja 11
  • Error while running send2trash on Python 3.7.0 beta 2

    Error while running send2trash on Python 3.7.0 beta 2

    I have a small script that uses send2trash and works very well in Python 3.6 (Mac OS X 10.11 El Capitan). However, when I try to run it in Python 3.7.0 beta 2, it fails with the traceback bellow.

    best regards, victor

    Traceback (most recent call last):
      File "/Users/fact/Dropbox/Aplicativos/Filemaker_backups/NPK-Backup/remove_old_archives.py", line 26, in <module>
        from send2trash import send2trash
      File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/send2trash/__init__.py", line 12, in <module>
        from .plat_osx import send2trash
      File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/send2trash/plat_osx.py", line 17, in <module>
        GetMacOSStatusCommentString = Foundation.GetMacOSStatusCommentString
      File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ctypes/__init__.py", line 369, in __getattr__
        func = self.__getitem__(name)
      File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ctypes/__init__.py", line 374, in __getitem__
        func = self._FuncPtr((name_or_ordinal, self))
    AttributeError: dlsym(RTLD_DEFAULT, GetMacOSStatusCommentString): symbol not found
    
    opened by victordomingos 9
  • Use bytes paths in plat_other

    Use bytes paths in plat_other

    This fixes issues with non-ascii paths when using the fallback freedesktop trash implementation.

    This is a rather ugly set of changes, but it's based on two things:

    1. urllib.quote() on Python 2 requires bytes. On Python 3, it can handle unicode or bytes.
    2. Paths on Unix filesystems are really bytes. We can usually represent them as unicode, but for 100% fidelity, they should be passed around as bytes.

    So this is a complete switch around from #12: rather than converting all paths to unicode when they're passed in, convert them all to bytes.

    I added tests for passing in a path as unicode or as bytes. Before the changes, both tests fail under Python 2. Afterwards, everything passes, on both versions of Python.

    opened by takluyver 9
  • "OSError: [Errno 120] This function is not supported by the system."

    Hi! Whenever I try running create_project.py i get this error:

    Traceback (most recent call last):
      File "test_project.py", line 14, in <module>
        add_on = create_project.CreateProject( "myaddon","mya")  #This Class Will create the project
      File "C:\Users\Retcy\Downloads\8. Coding Fun\neptune_api\neptune_lib\core\create_project.py", line 108, in __init__
        send2trash.send2trash(self.name)
      File "C:\Users\Retcy\AppData\Local\Programs\Python\Python37-32\lib\site-packages\send2trash\plat_win_legacy.py", line 146, in send2trash
        raise WindowsError(result, FormatError(result), paths)
    OSError: [Errno 120] This function is not supported by the system.: ['C:\\Users\\Retcy\\DOWNLO~1\\8. Coding Fun\\neptune_api\\builds\\myaddon'] 
    

    Code: create_project.txt

    opened by retr0cube 7
  • File not move to Recycle Bin in Windows

    File not move to Recycle Bin in Windows

    I try to use send2trash('file_path') but file still not move to my Recycle Bin with no any error message.

    It's look like the issue came from get_short_path_name() because it return u'' But when I bypass get_short_path_name() method, send2trash() seem working for me.

    def get_short_path_name(long_name):
        return long_name
        # if not long_name.startswith('\\\\?\\'):
        #     long_name = '\\\\?\\' + long_name
        # buf_size = GetShortPathNameW(long_name, None, 0)
        # output = create_unicode_buffer(buf_size)
        # GetShortPathNameW(long_name, output, buf_size)
        # return output.value[4:]  # Remove '\\?\' for SHFileOperationW
    

    I'm using python 2.7.14 on Windows 10.0.16299 .

    opened by Shayen 7
  • 🚧 WIP: macOS trash

    🚧 WIP: macOS trash "put back" feature [ctypes]

    This is a WIP!


    This is my initial attempt at using ctypes, just putting it up online so we have a record of it, and also to help catch if I've done anything wrong.

    I was hopeful about the progress I was making, until I came across some hurdles that have blocked this approach. At the moment running it causes a segmentation fault (I believe because of the incorrectly initialised AEDesc). We need:

    • Need to find a way to initialise:
      • [ ] AEDesc
      • [ ] AEDataStorage
    • Need to confirm how the following values should be defined:
      • [ ] typeKernelProcessID
      • [ ] typeWildCard
      • [ ] keyDirectObject
      • [ ] pid_t

    If this turns out to be too arch-dependent, or too much of a hack, I'll open a different PR using some compiled Objective-C.

    Fixes #9.

    /cc @BoboTiG @hsoft

    opened by acheronfail 7
  • ImportError: no module named mac

    ImportError: no module named mac

    After cloning the directory, entering it, and typing 'pip install .' I got what seemed to be a successful build and install, ending in:

    Successfully built Send2Trash
    Installing collected packages: Send2Trash
    Successfully installed Send2Trash-1.8.1b0
    

    But when I try to run my Python 2.7 script I get an error message:

    Traceback (most recent call last):
      File "/Users/larryy/Dropbox/src/file_rename.py", line 8, in <module>
        from send2trash import send2trash
      File "/usr/local/lib/python2.7/site-packages/send2trash/__init__.py", line 12, in <module>
        from .mac import send2trash
    ImportError: No module named mac
    

    As shown, the line of code in question is a standard import:

    from send2trash import send2trash
    

    This is macOS Monterey 12.4 (latest) and the latest Send2Trash (1.8.1b0). Apologies if I've just done something stupid setting things up.

    opened by larryy 6
  • Add CLI Using __main__.py

    Add CLI Using __main__.py

    Great project. I wish this functionality were included in the standard library. Thank you.

    I'm curious how the methodology here compares with this JavaScript package: https://github.com/sindresorhus/trash

    If you have time, what are your thoughts?

    opened by grantjenks 6
  • Fix Windows compatibility with multithreading

    Fix Windows compatibility with multithreading

    Hi.

    I've faced with some tests of Jupyterhub Notebook repo are failing:

    Traceback (most recent call last):
      File "c:\hostedtoolcache\windows\python\3.6.8\x64\lib\site-packages\tornado\web.py", line 1704, in _execute
        result = await result
      File "c:\hostedtoolcache\windows\python\3.6.8\x64\lib\site-packages\tornado\gen.py", line 234, in wrapper
        yielded = ctx_run(next, result)
      File "c:\hostedtoolcache\windows\python\3.6.8\x64\lib\site-packages\tornado\gen.py", line 162, in _fake_ctx_run
        return f(*args, **kw)
      File "D:\a\notebook\notebook\notebook\services\contents\handlers.py", line 237, in delete
        yield maybe_future(cm.delete(path))
      File "D:\a\notebook\notebook\notebook\services\contents\manager.py", line 279, in delete
        self.delete_file(path)
      File "D:\a\notebook\notebook\notebook\services\contents\filemanager.py", line 533, in delete_file
        send2trash(os_path)
      File "c:\hostedtoolcache\windows\python\3.6.8\x64\lib\site-packages\send2trash\plat_win_modern.py", line 31, in send2trash
        shell.CLSID_FileOperation, None, pythoncom.CLSCTX_ALL, shell.IID_IFileOperation,
    pywintypes.com_error: (-2147221008, 'CoInitialize has not been called.', None, None)
    

    According to https://stackoverflow.com/questions/37258257/why-does-this-script-not-work-with-threading-python, it is important to call .CoInitialize() method to allow win32 API calls in multithread mode.

    opened by dolfinus 5
  • fix trash_move

    fix trash_move

    the same as https://github.com/arsenetar/send2trash/pull/41

    this bug prevents using jupyter* in research environments where file systems aren't always local

    e.g. https://github.com/jupyterlab/jupyterlab/issues/5781 and our own use at https://cri.uchicago.edu/

    cc @annawoodard

    opened by makslevental 4
  • Can't delete files or folders on OneDrive

    Can't delete files or folders on OneDrive

    I'm using JupyterLab and OneDrive on an M1 Macbook Air with Macos 12.6.1. I get an OSError when trying to delete a file or folder on Onedrive with JupyterLab. Maybe OneDrive's Files On-Demand is causing the problem.

          File "/opt/homebrew/Caskroom/mambaforge/base/lib/python3.10/site-packages/tornado/web.py", line 1713, in _execute
            result = await result
          File "/opt/homebrew/Caskroom/mambaforge/base/lib/python3.10/site-packages/jupyter_server/services/contents/handlers.py", line 275, in delete
            await ensure_async(cm.delete(path))
          File "/opt/homebrew/Caskroom/mambaforge/base/lib/python3.10/site-packages/jupyter_server/services/contents/manager.py", line 417, in delete
            self.delete_file(path)
          File "/opt/homebrew/Caskroom/mambaforge/base/lib/python3.10/site-packages/jupyter_server/services/contents/filemanager.py", line 511, in delete_file
            send2trash(os_path)
          File "/opt/homebrew/Caskroom/mambaforge/base/lib/python3.10/site-packages/send2trash/plat_osx_pyobjc.py", line 29, in send2trash
            check_op_result(op_result)
          File "/opt/homebrew/Caskroom/mambaforge/base/lib/python3.10/site-packages/send2trash/plat_osx_pyobjc.py", line 16, in check_op_result
            raise OSError(op_result[2].localizedFailureReason())
        OSError: None```
    opened by peccator085 0
  • Failed to move files to trash in overlayfs

    Failed to move files to trash in overlayfs

    In overlayfs, directories always have st_dev from lower filesystem whereas files can have st_dev either from lower filesystem or upper filesystem. Due to this behavior, https://github.com/arsenetar/send2trash/blob/1.8.1b0/send2trash/plat_other.py#L178 always fails when the file's st_dev is from the upper filesystem. gio already tackled this issue, by avoiding comparison b/w file_dev and trash_dev, instead, it compares parent_dir(file).dev to trash_dev (ref: https://gitlab.gnome.org/GNOME/glib/-/blob/main/gio/glocalfile.c#L2019). I think send2trash also can adapt the same approach.

    opened by pjknkda 1
  • Module not callable

    Module not callable

    Working through the Automate the Boring stuff book and came across Send2Trash. Tried following the tutorial but found that the module was not callable.

    my code is

    send to trash

    I am doing this in VSCode and pylint keeps giving the error that the module is not callable:

    I have tried reinstalling send2trash and restarting the computer.

    opened by PeterCLarsen 1
  • send2trash function failed to delete a directory with unknown error

    send2trash function failed to delete a directory with unknown error

    This function is referred in Jupyter server folder deletion logic. We observed the error in jupyterlab app and here in this description we try to simplify the scenario and reproduce it in a windows command prompt.

    In python interpreter, we import the send2trash: from send2trash import send2trash

    And run this code line, deleting the directory: send2trash('C:\\Users\\traveler\\AppData\\Local\\projects\\Untitled Folder') In this case the "Untitled Folder" is newly created under a jlabapp project and there is a newly created ipynb file in it, it failed to delete "Untitled Folder" and throws message:

    >>> send2trash('C:\Users\traveler\AppData\Local\projects\Untitled Folder') Traceback (most recent call last): File "C:\Users\traveler\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\send2trash\plat_win_modern.py", line 61, in send2trash result = fileop.PerformOperations() pywintypes.com_error: (-2144927705, 'OLE error 0x80270027', None, None)

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last): File "", line 1, in File "C:\Users\traveler\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\send2trash\plat_win_modern.py", line 69, in send2trash raise OSError(None, error.strerror, path, error.hresult) OSError: [WinError -2144927705] OLE error 0x80270027: 'C:\Users\traveler\AppData\Local\projects\Untitled Folder'

    However, when we close the project tab and reopen it. The above code line (exactly the same func and path) works and was able to delete "Untitled Folder".

    Watching "Untitled Folder" in File Explorer and it seems there is no visible difference between the above two cases.

    opened by WentingTan 2
  • Five tests error/fail in a testing chroot on Linux with bizarre error messages

    Five tests error/fail in a testing chroot on Linux with bizarre error messages

    Hi! As part of the Debian build, the package tests are run in a minimal chroot environment. I've set the HOME environment variable first:

    (sid-sbuild)[email protected]:/build/send2trash-IKQvlF/send2trash-1.8.1~b0$ export HOME=$(mktemp -p)
    (sid-sbuild)[email protected]:/build/send2trash-IKQvlF/send2trash-1.8.1~b0$ echo $HOME
    /tmp/tmp.CSc9dofzh7/
    (sid-sbuild)[email protected]:/build/send2trash-IKQvlF/send2trash-1.8.1~b0$ mkdir -p $HOME/.local/share/Trash
    (sid-sbuild)[email protected]:/build/send2trash-IKQvlF/send2trash-1.8.1~b0$ dpkg-buildpackage -b -us -uc
    dpkg-buildpackage: info: source package send2trash
    dpkg-buildpackage: info: source version 1.8.1~b0-1
    dpkg-buildpackage: info: source distribution unstable
    dpkg-buildpackage: info: source changed by Julian Gilbey <[email protected]>
    dpkg-buildpackage: info: host architecture amd64
    [... build the python package, snipped ...]
    Successfully built Send2Trash-1.8.1b0-py3-none-any.whl
    I: pybuild plugin_pyproject:123: Unpacking wheel built for python3.10 with "installer" module
    [... do the same for Python 3.9, snipped ...]
    Successfully built Send2Trash-1.8.1b0-py3-none-any.whl
    I: pybuild plugin_pyproject:123: Unpacking wheel built for python3.9 with "installer" module
       dh_auto_test -O--buildsystem=pybuild
    I: pybuild base:237: cd '/build/send2trash-IKQvlF/send2trash-1.8.1~b0/.pybuild/cpython3_3.10/build'; python3.10 -m pytest tests
    ============================= test session starts ==============================
    platform linux -- Python 3.10.2, pytest-6.2.5, py-1.10.0, pluggy-0.13.0
    rootdir: /build/send2trash-IKQvlF/send2trash-1.8.1~b0/.pybuild/cpython3_3.10/build
    collected 10 items / 1 skipped / 9 selected                                    
    
    tests/test_plat_other.py ....FFFEF                                       [ 80%]
    tests/test_script_main.py ..                                             [100%]
    
    ==================================== ERRORS ====================================
    ________________ ERROR at teardown of test_trash_topdir_failure ________________
    
        @pytest.fixture
        def testExtVol():
            trashTopdir = mkdtemp(prefix="s2t")
            volume = ExtVol(trashTopdir)
            fileName = "test.txt"
            filePath = op.join(volume.trashTopdir, fileName)
            touch(filePath)
            assert op.exists(filePath) is True
            yield volume, fileName, filePath
    >       volume.cleanup()
    
    tests/test_plat_other.py:156: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    tests/test_plat_other.py:144: in cleanup
        shutil.rmtree(self.trashTopdir)
    /usr/lib/python3.10/shutil.py:717: in rmtree
        _rmtree_safe_fd(fd, path, onerror)
    /usr/lib/python3.10/shutil.py:674: in _rmtree_safe_fd
        onerror(os.unlink, fullname, sys.exc_info())
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    
    topfd = 11, path = '/tmp/s2tw916afk4'
    onerror = <function rmtree.<locals>.onerror at 0x7fa2915feef0>
    
        def _rmtree_safe_fd(topfd, path, onerror):
            try:
                with os.scandir(topfd) as scandir_it:
                    entries = list(scandir_it)
            except OSError as err:
                err.filename = path
                onerror(os.scandir, path, sys.exc_info())
                return
            for entry in entries:
                fullname = os.path.join(path, entry.name)
                try:
                    is_dir = entry.is_dir(follow_symlinks=False)
                except OSError:
                    is_dir = False
                else:
                    if is_dir:
                        try:
                            orig_st = entry.stat(follow_symlinks=False)
                            is_dir = stat.S_ISDIR(orig_st.st_mode)
                        except OSError:
                            onerror(os.lstat, fullname, sys.exc_info())
                            continue
                if is_dir:
                    try:
                        dirfd = os.open(entry.name, os.O_RDONLY, dir_fd=topfd)
                    except OSError:
                        onerror(os.open, fullname, sys.exc_info())
                    else:
                        try:
                            if os.path.samestat(orig_st, os.fstat(dirfd)):
                                _rmtree_safe_fd(dirfd, fullname, onerror)
                                try:
                                    os.rmdir(entry.name, dir_fd=topfd)
                                except OSError:
                                    onerror(os.rmdir, fullname, sys.exc_info())
                            else:
                                try:
                                    # This can only happen if someone replaces
                                    # a directory with a symlink after the call to
                                    # os.scandir or stat.S_ISDIR above.
                                    raise OSError("Cannot call rmtree on a symbolic "
                                                  "link")
                                except OSError:
                                    onerror(os.path.islink, fullname, sys.exc_info())
                        finally:
                            os.close(dirfd)
                else:
                    try:
    >                   os.unlink(entry.name, dir_fd=topfd)
    E                   PermissionError: [Errno 13] Permission denied: 'test.txt'
    
    /usr/lib/python3.10/shutil.py:672: PermissionError
    =================================== FAILURES ===================================
    ______________________________ test_trash_topdir _______________________________
    
    testExtVol = (<tests.test_plat_other.ExtVol object at 0x7fa2915df430>, 'test.txt', '/tmp/s2t1_l_qvbt/test.txt')
    
        def test_trash_topdir(testExtVol):
            trashDir = op.join(testExtVol[0].trashTopdir, ".Trash")
            os.mkdir(trashDir, 0o777 | stat.S_ISVTX)
        
    >       s2t(testExtVol[2])
    
    tests/test_plat_other.py:163: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    send2trash/plat_other.py:213: in send2trash
        dest_trash = find_ext_volume_trash(topdir)
    send2trash/plat_other.py:169: in find_ext_volume_trash
        trash_dir = find_ext_volume_fallback_trash(volume_root)
    send2trash/plat_other.py:158: in find_ext_volume_fallback_trash
        check_create(trash_dir)
    send2trash/plat_other.py:96: in check_create
        os.makedirs(dir, 0o700)
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    
    name = b'/tmp/s2t1_l_qvbt/test.txt/.Trash-1000', mode = 448, exist_ok = False
    
        def makedirs(name, mode=0o777, exist_ok=False):
            """makedirs(name [, mode=0o777][, exist_ok=False])
        
            Super-mkdir; create a leaf directory and all intermediate ones.  Works like
            mkdir, except that any intermediate path segment (not just the rightmost)
            will be created if it does not exist. If the target directory already
            exists, raise an OSError if exist_ok is False. Otherwise no exception is
            raised.  This is recursive.
        
            """
            head, tail = path.split(name)
            if not tail:
                head, tail = path.split(head)
            if head and tail and not path.exists(head):
                try:
                    makedirs(head, exist_ok=exist_ok)
                except FileExistsError:
                    # Defeats race condition when another thread created the path
                    pass
                cdir = curdir
                if isinstance(tail, bytes):
                    cdir = bytes(curdir, 'ASCII')
                if tail == cdir:           # xxx/newdir/. exists if xxx/newdir exists
                    return
            try:
    >           mkdir(name, mode)
    E           NotADirectoryError: [Errno 20] Not a directory: b'/tmp/s2t1_l_qvbt/test.txt/.Trash-1000'
    
    /usr/lib/python3.10/os.py:225: NotADirectoryError
    __________________________ test_trash_topdir_fallback __________________________
    
    testExtVol = (<tests.test_plat_other.ExtVol object at 0x7fa291497a60>, 'test.txt', '/tmp/s2tmx3ups_b/test.txt')
    
        def test_trash_topdir_fallback(testExtVol):
    >       s2t(testExtVol[2])
    
    tests/test_plat_other.py:175: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    send2trash/plat_other.py:213: in send2trash
        dest_trash = find_ext_volume_trash(topdir)
    send2trash/plat_other.py:169: in find_ext_volume_trash
        trash_dir = find_ext_volume_fallback_trash(volume_root)
    send2trash/plat_other.py:158: in find_ext_volume_fallback_trash
        check_create(trash_dir)
    send2trash/plat_other.py:96: in check_create
        os.makedirs(dir, 0o700)
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    
    name = b'/tmp/s2tmx3ups_b/test.txt/.Trash-1000', mode = 448, exist_ok = False
    
        def makedirs(name, mode=0o777, exist_ok=False):
            """makedirs(name [, mode=0o777][, exist_ok=False])
        
            Super-mkdir; create a leaf directory and all intermediate ones.  Works like
            mkdir, except that any intermediate path segment (not just the rightmost)
            will be created if it does not exist. If the target directory already
            exists, raise an OSError if exist_ok is False. Otherwise no exception is
            raised.  This is recursive.
        
            """
            head, tail = path.split(name)
            if not tail:
                head, tail = path.split(head)
            if head and tail and not path.exists(head):
                try:
                    makedirs(head, exist_ok=exist_ok)
                except FileExistsError:
                    # Defeats race condition when another thread created the path
                    pass
                cdir = curdir
                if isinstance(tail, bytes):
                    cdir = bytes(curdir, 'ASCII')
                if tail == cdir:           # xxx/newdir/. exists if xxx/newdir exists
                    return
            try:
    >           mkdir(name, mode)
    E           NotADirectoryError: [Errno 20] Not a directory: b'/tmp/s2tmx3ups_b/test.txt/.Trash-1000'
    
    /usr/lib/python3.10/os.py:225: NotADirectoryError
    __________________________ test_trash_topdir_failure ___________________________
    
    testExtVol = (<tests.test_plat_other.ExtVol object at 0x7fa2914756c0>, 'test.txt', '/tmp/s2tw916afk4/test.txt')
    
        def test_trash_topdir_failure(testExtVol):
            os.chmod(testExtVol[0].trashTopdir, 0o500)  # not writable to induce the exception
    >       pytest.raises(TrashPermissionError, s2t, [testExtVol[2]])
    
    tests/test_plat_other.py:182: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    send2trash/plat_other.py:213: in send2trash
        dest_trash = find_ext_volume_trash(topdir)
    send2trash/plat_other.py:169: in find_ext_volume_trash
        trash_dir = find_ext_volume_fallback_trash(volume_root)
    send2trash/plat_other.py:158: in find_ext_volume_fallback_trash
        check_create(trash_dir)
    send2trash/plat_other.py:96: in check_create
        os.makedirs(dir, 0o700)
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    
    name = b'/tmp/s2tw916afk4/test.txt/.Trash-1000', mode = 448, exist_ok = False
    
        def makedirs(name, mode=0o777, exist_ok=False):
            """makedirs(name [, mode=0o777][, exist_ok=False])
        
            Super-mkdir; create a leaf directory and all intermediate ones.  Works like
            mkdir, except that any intermediate path segment (not just the rightmost)
            will be created if it does not exist. If the target directory already
            exists, raise an OSError if exist_ok is False. Otherwise no exception is
            raised.  This is recursive.
        
            """
            head, tail = path.split(name)
            if not tail:
                head, tail = path.split(head)
            if head and tail and not path.exists(head):
                try:
                    makedirs(head, exist_ok=exist_ok)
                except FileExistsError:
                    # Defeats race condition when another thread created the path
                    pass
                cdir = curdir
                if isinstance(tail, bytes):
                    cdir = bytes(curdir, 'ASCII')
                if tail == cdir:           # xxx/newdir/. exists if xxx/newdir exists
                    return
            try:
    >           mkdir(name, mode)
    E           NotADirectoryError: [Errno 20] Not a directory: b'/tmp/s2tw916afk4/test.txt/.Trash-1000'
    
    /usr/lib/python3.10/os.py:225: NotADirectoryError
    ______________________________ test_trash_symlink ______________________________
    
    testExtVol = (<tests.test_plat_other.ExtVol object at 0x7fa2915da8c0>, 'test.txt', '/tmp/s2t9qns8us6/test.txt')
    
        def test_trash_symlink(testExtVol):
            # Use mktemp (race conditioney but no symlink equivalent)
            # Since is_parent uses realpath(), and our getdev uses is_parent,
            # this should work
            slDir = mktemp(prefix="s2t", dir=op.expanduser("~"))
            os.mkdir(op.join(testExtVol[0].trashTopdir, "subdir"), 0o700)
            filePath = op.join(testExtVol[0].trashTopdir, "subdir", testExtVol[1])
            touch(filePath)
            os.symlink(op.join(testExtVol[0].trashTopdir, "subdir"), slDir)
    >       s2t(op.join(slDir, testExtVol[1]))
    
    tests/test_plat_other.py:195: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    send2trash/plat_other.py:213: in send2trash
        dest_trash = find_ext_volume_trash(topdir)
    send2trash/plat_other.py:169: in find_ext_volume_trash
        trash_dir = find_ext_volume_fallback_trash(volume_root)
    send2trash/plat_other.py:158: in find_ext_volume_fallback_trash
        check_create(trash_dir)
    send2trash/plat_other.py:96: in check_create
        os.makedirs(dir, 0o700)
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    
    name = b'/tmp/s2t9qns8us6/subdir/test.txt/.Trash-1000', mode = 448
    exist_ok = False
    
        def makedirs(name, mode=0o777, exist_ok=False):
            """makedirs(name [, mode=0o777][, exist_ok=False])
        
            Super-mkdir; create a leaf directory and all intermediate ones.  Works like
            mkdir, except that any intermediate path segment (not just the rightmost)
            will be created if it does not exist. If the target directory already
            exists, raise an OSError if exist_ok is False. Otherwise no exception is
            raised.  This is recursive.
        
            """
            head, tail = path.split(name)
            if not tail:
                head, tail = path.split(head)
            if head and tail and not path.exists(head):
                try:
                    makedirs(head, exist_ok=exist_ok)
                except FileExistsError:
                    # Defeats race condition when another thread created the path
                    pass
                cdir = curdir
                if isinstance(tail, bytes):
                    cdir = bytes(curdir, 'ASCII')
                if tail == cdir:           # xxx/newdir/. exists if xxx/newdir exists
                    return
            try:
    >           mkdir(name, mode)
    E           NotADirectoryError: [Errno 20] Not a directory: b'/tmp/s2t9qns8us6/subdir/test.txt/.Trash-1000'
    
    /usr/lib/python3.10/os.py:225: NotADirectoryError
    =========================== short test summary info ============================
    FAILED tests/test_plat_other.py::test_trash_topdir - NotADirectoryError: [Err...
    FAILED tests/test_plat_other.py::test_trash_topdir_fallback - NotADirectoryEr...
    FAILED tests/test_plat_other.py::test_trash_topdir_failure - NotADirectoryErr...
    FAILED tests/test_plat_other.py::test_trash_symlink - NotADirectoryError: [Er...
    ERROR tests/test_plat_other.py::test_trash_topdir_failure - PermissionError: ...
    =============== 4 failed, 6 passed, 1 skipped, 1 error in 0.20s ================
    E: pybuild pybuild:367: test: plugin pyproject failed with: exit code=1: cd '/build/send2trash-IKQvlF/send2trash-1.8.1~b0/.pybuild/cpython3_3.10/build'; python3.10 -m pytest tests
    [... similar errors with Python 3.9 snipped ...]
    

    The thing that seems so weird to me is the strange filenames/directories it's trying to work with, such as b'/tmp/s2t9qns8us6/subdir/test.txt/.Trash-1000'. It strikes me that something has gone wrong in the calculation of the trash directory name. (And there's no sign of the HOME directory I so carefully set up!)

    opened by juliangilbey 7
Releases(1.8.1b0)
  • 1.8.1b0(Aug 21, 2021)

  • 1.8.0(Aug 9, 2021)

    • Add compatibility with pathlib paths (#49)
    • Fix thread compatibility of modern windows implementation (#59)
    • Fix handling of UNC names in legacy windows implementation (#57)
    Source code(tar.gz)
    Source code(zip)
  • 1.7.1(Jun 23, 2021)

    • Release stable version with changes from last 3 releases including:
      • Changed conditional for when to try to use pyobjc version (#51)
      • Add console_script entry point (#50)
      • Increased python CI versions (#52, #54)
      • Fix minor issue in setup.py (#53)
      • Fix issue with windows tests importing modules on non-windows (#55)
      • Unit test cleanups, rewrites, and flake8 cleanups
      • Windows: Fix legacy windows platform for multi-byte unicode and add tests
      • macOS: Add alternative pyobjc version to potentially improve compatibility (#51)
      • Add main method which allows calling via python -m send2trash somefile
      • Windows: Add support for using IFileOperation when pywin32 is present on Vista and newer
      • Add support for passing multiple files at once in a list
      • Windows: Batch multi-file calls to improve performance (#42)
      • Windows: Fix issue with SHFileOperation failing silently when path is not found (#33)
    • Fix handling of UNC names (#57)
    Source code(tar.gz)
    Source code(zip)
  • 1.7.0a1(Jun 23, 2021)

  • 1.7.0a0(Jun 23, 2021)

    • Add console_script entry point (#50)
    • Increased python CI versions (#52, #54)
    • Fix minor issue in setup.py (#53)
    • Fix issue with windows tests importing modules on non-windows (#55)
    • Unit test cleanups, rewrites, and flake8 cleanups
    • Windows: Fix legacy windows platform for multi-byte unicode and add tests
    • macOS: Add alternative pyobjc version to potentially improve compatibility (#51)
    Source code(tar.gz)
    Source code(zip)
  • 1.6.0b1(Jun 19, 2020)

    This is a beta version including the following changes:

    • Add main method which allows calling via python -m send2trash somefile
    • Windows: Add support for using IFileOperation when pywin32 is present on Vista and newer
    • Add support for passing multiple files at once in a list
    • Windows: Batch multi-file calls to improve performance (#42)
    • Windows: Fix issue with SHFileOperation failing silently when path is not found (#33)
    Source code(tar.gz)
    Source code(zip)
Owner
Andrew Senetar
Andrew Senetar
A working roblox account generator it doesnt bypass the capcha stuff cuz these didnt showed up in my test runs

A working roblox account generator (state 11.5.2021) it doesnt bypass the capcha stuff cuz these didnt showed up in my test runs

TerrificTable 22 Jan 03, 2023
This simple script generates a backup of a given Python and R environment

Python Environment Backup It’s always good to maintain your Python and R Anaconda environment packages properly listed and well-kept in case you have

Andrew Laganaro 1 Jul 13, 2022
Mixtaper - Web app to make mixtapes

Mixtaper A web app which allows you to input songs in the form of youtube links

suryansh 1 Feb 14, 2022
Google Foobar challenge solutions from my experience and other's on the web.

Google Foobar challenge Google Foobar challenge solutions from my experience and other's on the web. Note: Problems indicated with "Mine" are tested a

Islam Ayman 6 Jan 20, 2022
My solution for a MARL problem on a Grid Environment with Q-tables.

To run the project, run: conda create --name env python=3.7 pip install -r requirements.txt python run.py To-do: Add direction to the state space Take

Merve Noyan 12 Dec 25, 2021
Collaboration project to creating bank application maded by Anzhelica Sakun and Yuriy Konyukh

Collaboration project to creating bank application maded by Anzhelica Sakun and Yuriy Konyukh

Yuriy 1 Jan 08, 2022
Demo scripts for the Kubernetes Security Webinar

Kubernetes Security Webinar [in Russian] YouTube video (October 13, 2021) Authors: Artem Yushkovsky (LinkedIn, GitHub) Maxim Mosharov @ Whitespots.io

Slurm 34 Dec 06, 2022
Program Input Data Mahasiswa Oop

PROGRAM INPUT NILAI MAHASISWA MENGGUNAKAN OOP PENGERTIAN OOP object-oriented-programing/OOP adalah paradigma pemrograman berdasarkan konsep "objek", y

Maulana Reza Badrudin 1 Jan 05, 2022
Keep your company's passwords behind the firewall

TeamVault TeamVault is an open-source web-based shared password manager for behind-the-firewall installation. It requires Python 3.3+ and Postgres (wi

//SEIBERT/MEDIA GmbH 38 Feb 20, 2022
Bionic is Python Framework for crafting beautiful, fast user experiences for web and is free and open source.

Bionic is Python Framework for crafting beautiful, fast user experiences for web and is free and open source. Getting Started This is an example of ho

14 Apr 10, 2022
Utility/Raiding selfbot made by Shell and Roover.

Utility/Raiding selfbot made by Shell and Roover. We are open to suggestions and ideas.

Shell 2 Dec 08, 2021
Streamlit Component, for a Chatbot UI

st-chat Streamlit Component, for a Chat-bot UI, example app authors - @yashppawar & @YashVardhan-AI Installation Install streamlit-chat with pip pip i

Yash AI 99 Jan 07, 2023
a package that provides a marketstrategy for whitelisting on golem

filterms a package that provides a marketstrategy for whitelisting on golem watching requestor logs distribute 10 tasks asynchronously is fun. but you

KJM 3 Aug 03, 2022
Airbrake Python

airbrake-python Note. Python 3.4+ are advised to use new Airbrake Python notifier which supports async API and code hunks. Python 2.7 users should con

Airbrake 51 Dec 22, 2022
データサイエンスチャレンジ2021 サンプル

データサイエンスチャレンジ2021 サンプル 概要 線形補間と Catmull–Rom Spline 補間のサンプル Python スクリプトです。 データサイエンスチャレンジ2021の出題意図としましては、訓練用データ(train.csv)から機械学習モデルを作成して、そのモデルに推論させてモーシ

Bandai Namco Research Inc. 5 Oct 17, 2022
This repo is a collection of programs and websites templates too

📢 Register here for Hacktoberfest and make four pull requests (PRs) between October 1st-31st to grab free SWAGS 🔥 . IMPORTANT While making pull requ

Binayak Jha - 2 7 Oct 03, 2022
This is a repository built by the community for the community.

Nutshell Machine Learning Machines can see, hear and learn. Welcome to the future 🌍 The repository was built with a tree-like structure in mind, it c

Edem Gold 82 Nov 18, 2022
A collection of convenient parsers for Advent of Code problems.

Advent of Code Parsers A collection of convenient Python parsers for Advent of Code problems. Installation pip install aocp Quickstart You can import

Miguel Blanco Marcos 3 Dec 13, 2021
Mechanized literally means automation.

Mechanized literally means automation. And this branch which you are now observing is automated by the python script. This python project actually automates my workflow related to Git & Github.

Shreejan Dolai 4 Nov 11, 2022
AutoMetamon: Simple program to play Metamon automatically

AutoMetamon: Simple program to play Metamon automatically

Ngô Văn Tuấn 2 Sep 13, 2022