mirror of
https://github.com/arsenetar/send2trash.git
synced 2026-03-12 18:51:38 +00:00
Compare commits
12 Commits
1.7.1
...
69a82a5162
| Author | SHA1 | Date | |
|---|---|---|---|
|
69a82a5162
|
|||
|
2b3f9891c2
|
|||
|
039f92264b
|
|||
|
c2c47610c8
|
|||
|
66fc79695e
|
|||
|
454ebeb072
|
|||
|
7ca68e5473
|
|||
|
484913ba0f
|
|||
|
d249f0106b
|
|||
|
94e1ec007a
|
|||
|
84c220cbd9
|
|||
|
6612545110
|
80
.github/workflows/default.yml
vendored
Normal file
80
.github/workflows/default.yml
vendored
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
# Workflow lints, and checks format in parallel then runs tests on all platforms
|
||||||
|
|
||||||
|
name: Default CI/CD
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Set up Python 3.x
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: 3.x
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install flake8
|
||||||
|
- name: Lint with flake8
|
||||||
|
run: |
|
||||||
|
flake8 .
|
||||||
|
test:
|
||||||
|
needs: lint
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: ubuntu-latest
|
||||||
|
python-version: 3.10.0-alpha - 3.10.0
|
||||||
|
- os: ubuntu-latest
|
||||||
|
python-version: 3.9
|
||||||
|
- os: ubuntu-latest
|
||||||
|
python-version: 3.8
|
||||||
|
- os: ubuntu-latest
|
||||||
|
python-version: 3.7
|
||||||
|
- os: ubuntu-latest
|
||||||
|
python-version: 3.6
|
||||||
|
- os: ubuntu-latest
|
||||||
|
python-version: 3.5
|
||||||
|
- os: ubuntu-latest
|
||||||
|
python-version: 2.7
|
||||||
|
# - os: macos-latest
|
||||||
|
# python-version: 3.9
|
||||||
|
# - os: macos-latest
|
||||||
|
# python-version: 3.8
|
||||||
|
# - os: macos-latest
|
||||||
|
# python-version: 2.7
|
||||||
|
- os: windows-latest
|
||||||
|
python-version: 3.9
|
||||||
|
- os: windows-latest
|
||||||
|
python-version: 3.8
|
||||||
|
- os: windows-latest
|
||||||
|
python-version: 2.7
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: ${{ matrix.python-version }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install pytest
|
||||||
|
- name: Install windows dependencies
|
||||||
|
if: ${{ matrix.os == 'windows-latest' }}
|
||||||
|
run: |
|
||||||
|
pip install pywin32
|
||||||
|
- name: Install macOS dependencies
|
||||||
|
if: ${{ matrix.os == 'macos-latest' }}
|
||||||
|
run: |
|
||||||
|
pip install pyobjc-framework-Cocoa
|
||||||
|
- name: Run tests
|
||||||
|
run: |
|
||||||
|
pytest
|
||||||
25
.travis.yml
25
.travis.yml
@@ -1,30 +1,17 @@
|
|||||||
language: python
|
language: python
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- os: windows
|
|
||||||
language: sh
|
|
||||||
python: "3.8"
|
|
||||||
env: "PATH=/c/Python38:/c/Python38/Scripts:$PATH"
|
|
||||||
# Perform the manual steps on windows to install python3
|
|
||||||
before_install:
|
|
||||||
- choco install python --version=3.8.6
|
|
||||||
- python -m pip install --upgrade pip
|
|
||||||
before_script:
|
|
||||||
- export TOXENV=py38
|
|
||||||
- python: "2.7"
|
|
||||||
- python: "3.4"
|
- python: "3.4"
|
||||||
- python: "3.5"
|
|
||||||
- python: "3.6"
|
|
||||||
- python: "3.7"
|
|
||||||
- python: "3.8"
|
|
||||||
- python: "3.9"
|
|
||||||
- python: "nightly" # 3.10
|
|
||||||
before_script:
|
|
||||||
- export TOXENV=py310
|
|
||||||
- python: "2.7"
|
- python: "2.7"
|
||||||
arch: ppc64le
|
arch: ppc64le
|
||||||
- python: "3.6"
|
- python: "3.6"
|
||||||
arch: ppc64le
|
arch: ppc64le
|
||||||
|
- python: "3.7"
|
||||||
|
arch: ppc64le
|
||||||
|
- python: "3.8"
|
||||||
|
arch: ppc64le
|
||||||
|
- python: "3.9"
|
||||||
|
arch: ppc64le
|
||||||
install:
|
install:
|
||||||
- python -m pip install tox
|
- python -m pip install tox
|
||||||
before_script:
|
before_script:
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
Changes
|
Changes
|
||||||
=======
|
=======
|
||||||
|
|
||||||
|
Version 1.8.0 -- 2021/08/08
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
* Add compatibility with pathlib paths (#49)
|
||||||
|
* Fix thread compatibility of modern windows implementation (#59)
|
||||||
|
* Fix handling of UNC names in legacy windows implementation (#57)
|
||||||
|
|
||||||
Version 1.7.1 -- 2021/06/21
|
Version 1.7.1 -- 2021/06/21
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
|
|||||||
16
README.rst
16
README.rst
@@ -3,11 +3,11 @@ 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
|
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
|
*all platforms*. On OS X, it uses native ``FSMoveObjectToTrashSync`` Cocoa calls or can use pyobjc
|
||||||
uses native ``IFileOperation`` call if on Vista or newer and pywin32 is installed or falls back
|
with NSFileManager. On Windows, it uses native ``IFileOperation`` call if on Vista or newer and
|
||||||
to ``SHFileOperation`` calls. On other platforms, if `PyGObject`_ and `GIO`_ are available, it
|
pywin32 is installed or falls back to ``SHFileOperation`` calls. On other platforms, if `PyGObject`_
|
||||||
will use this. Otherwise, it will fallback to its own implementation of the `trash specifications
|
and `GIO`_ are available, it will use this. Otherwise, it will fallback to its own implementation of
|
||||||
from freedesktop.org`_.
|
the `trash specifications from freedesktop.org`_.
|
||||||
|
|
||||||
``ctypes`` is used to access native libraries, so no compilation is necessary.
|
``ctypes`` is used to access native libraries, so no compilation is necessary.
|
||||||
|
|
||||||
@@ -22,10 +22,14 @@ issues and fixes would be most appreciated.
|
|||||||
Installation
|
Installation
|
||||||
------------
|
------------
|
||||||
|
|
||||||
You can download it with pip::
|
You can download it with pip:
|
||||||
|
|
||||||
python -m pip install -U send2trash
|
python -m pip install -U send2trash
|
||||||
|
|
||||||
|
To install with pywin32 or pyobjc required specify the extra `nativeLib`:
|
||||||
|
|
||||||
|
python -m pip install -U send2trash[nativeLib]
|
||||||
|
|
||||||
or you can download the source from http://github.com/arsenetar/send2trash and install it with::
|
or you can download the source from http://github.com/arsenetar/send2trash and install it with::
|
||||||
|
|
||||||
>>> python setup.py install
|
>>> python setup.py install
|
||||||
|
|||||||
@@ -6,11 +6,11 @@
|
|||||||
|
|
||||||
from gi.repository import GObject, Gio
|
from gi.repository import GObject, Gio
|
||||||
from .exceptions import TrashPermissionError
|
from .exceptions import TrashPermissionError
|
||||||
|
from .util import preprocess_paths
|
||||||
|
|
||||||
|
|
||||||
def send2trash(paths):
|
def send2trash(paths):
|
||||||
if not isinstance(paths, list):
|
paths = preprocess_paths(paths)
|
||||||
paths = [paths]
|
|
||||||
for path in paths:
|
for path in paths:
|
||||||
try:
|
try:
|
||||||
f = Gio.File.new_for_path(path)
|
f = Gio.File.new_for_path(path)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ from ctypes import cdll, byref, Structure, c_char, c_char_p
|
|||||||
from ctypes.util import find_library
|
from ctypes.util import find_library
|
||||||
|
|
||||||
from .compat import binary_type
|
from .compat import binary_type
|
||||||
|
from .util import preprocess_paths
|
||||||
|
|
||||||
Foundation = cdll.LoadLibrary(find_library("Foundation"))
|
Foundation = cdll.LoadLibrary(find_library("Foundation"))
|
||||||
CoreServices = cdll.LoadLibrary(find_library("CoreServices"))
|
CoreServices = cdll.LoadLibrary(find_library("CoreServices"))
|
||||||
@@ -40,8 +41,7 @@ def check_op_result(op_result):
|
|||||||
|
|
||||||
|
|
||||||
def send2trash(paths):
|
def send2trash(paths):
|
||||||
if not isinstance(paths, list):
|
paths = preprocess_paths(paths)
|
||||||
paths = [paths]
|
|
||||||
paths = [
|
paths = [
|
||||||
path.encode("utf-8") if not isinstance(path, binary_type) else path
|
path.encode("utf-8") if not isinstance(path, binary_type) else path
|
||||||
for path in paths
|
for path in paths
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
from Foundation import NSFileManager, NSURL
|
from Foundation import NSFileManager, NSURL
|
||||||
from .compat import text_type
|
from .compat import text_type
|
||||||
|
from .util import preprocess_paths
|
||||||
|
|
||||||
|
|
||||||
def check_op_result(op_result):
|
def check_op_result(op_result):
|
||||||
@@ -16,8 +17,7 @@ def check_op_result(op_result):
|
|||||||
|
|
||||||
|
|
||||||
def send2trash(paths):
|
def send2trash(paths):
|
||||||
if not isinstance(paths, list):
|
paths = preprocess_paths(paths)
|
||||||
paths = [paths]
|
|
||||||
paths = [
|
paths = [
|
||||||
path.decode("utf-8") if not isinstance(path, text_type) else path
|
path.decode("utf-8") if not isinstance(path, text_type) else path
|
||||||
for path in paths
|
for path in paths
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ except ImportError:
|
|||||||
from urllib import quote
|
from urllib import quote
|
||||||
|
|
||||||
from .compat import text_type, environb
|
from .compat import text_type, environb
|
||||||
|
from .util import preprocess_paths
|
||||||
from .exceptions import TrashPermissionError
|
from .exceptions import TrashPermissionError
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -172,8 +173,7 @@ def get_dev(path):
|
|||||||
|
|
||||||
|
|
||||||
def send2trash(paths):
|
def send2trash(paths):
|
||||||
if not isinstance(paths, list):
|
paths = preprocess_paths(paths)
|
||||||
paths = [paths]
|
|
||||||
for path in paths:
|
for path in paths:
|
||||||
if isinstance(path, text_type):
|
if isinstance(path, text_type):
|
||||||
path_b = fsencode(path)
|
path_b = fsencode(path)
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
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 .util import preprocess_paths
|
||||||
|
|
||||||
from ctypes import (
|
from ctypes import (
|
||||||
windll,
|
windll,
|
||||||
Structure,
|
Structure,
|
||||||
@@ -101,8 +103,7 @@ def get_short_path_name(long_name):
|
|||||||
|
|
||||||
|
|
||||||
def send2trash(paths):
|
def send2trash(paths):
|
||||||
if not isinstance(paths, list):
|
paths = preprocess_paths(paths)
|
||||||
paths = [paths]
|
|
||||||
# convert data type
|
# convert data type
|
||||||
paths = [
|
paths = [
|
||||||
text_type(path, "mbcs") if not isinstance(path, text_type) else path
|
text_type(path, "mbcs") if not isinstance(path, text_type) else path
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
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 .util import preprocess_paths
|
||||||
from platform import version
|
from platform import version
|
||||||
import pythoncom
|
import pythoncom
|
||||||
import pywintypes
|
import pywintypes
|
||||||
@@ -15,8 +16,7 @@ from .IFileOperationProgressSink import CreateSink
|
|||||||
|
|
||||||
|
|
||||||
def send2trash(paths):
|
def send2trash(paths):
|
||||||
if not isinstance(paths, list):
|
paths = preprocess_paths(paths)
|
||||||
paths = [paths]
|
|
||||||
# convert data type
|
# convert data type
|
||||||
paths = [
|
paths = [
|
||||||
text_type(path, "mbcs") if not isinstance(path, text_type) else path
|
text_type(path, "mbcs") if not isinstance(path, text_type) else path
|
||||||
@@ -26,6 +26,8 @@ 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]
|
||||||
# remove the leading \\?\ if present
|
# remove the leading \\?\ if present
|
||||||
paths = [path[4:] if path.startswith("\\\\?\\") else path for path in paths]
|
paths = [path[4:] if path.startswith("\\\\?\\") else path for path in paths]
|
||||||
|
# Need to initialize the com before using
|
||||||
|
pythoncom.CoInitialize()
|
||||||
# create instance of file operation object
|
# create instance of file operation object
|
||||||
fileop = pythoncom.CoCreateInstance(
|
fileop = pythoncom.CoCreateInstance(
|
||||||
shell.CLSID_FileOperation, None, pythoncom.CLSCTX_ALL, shell.IID_IFileOperation,
|
shell.CLSID_FileOperation, None, pythoncom.CLSCTX_ALL, shell.IID_IFileOperation,
|
||||||
@@ -65,3 +67,6 @@ def send2trash(paths):
|
|||||||
# convert to standard OS error, allows other code to get a
|
# convert to standard OS error, allows other code to get a
|
||||||
# normal errno
|
# normal errno
|
||||||
raise OSError(None, error.strerror, path, error.hresult)
|
raise OSError(None, error.strerror, path, error.hresult)
|
||||||
|
finally:
|
||||||
|
# Need to make sure we call this once fore every init
|
||||||
|
pythoncom.CoUninitialize()
|
||||||
|
|||||||
16
send2trash/util.py
Normal file
16
send2trash/util.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# encoding: utf-8
|
||||||
|
# Copyright 2017 Virgil Dupras
|
||||||
|
|
||||||
|
# This software is licensed under the "BSD" License as described in the "LICENSE" file,
|
||||||
|
# which should be included with this package. The terms are also available at
|
||||||
|
# http://www.hardcoded.net/licenses/bsd_license
|
||||||
|
|
||||||
|
|
||||||
|
def preprocess_paths(paths):
|
||||||
|
if not isinstance(paths, list):
|
||||||
|
paths = [paths]
|
||||||
|
# Convert items such as pathlib paths to strings
|
||||||
|
paths = [
|
||||||
|
path.__fspath__() if hasattr(path, "__fspath__") else path for path in paths
|
||||||
|
]
|
||||||
|
return paths
|
||||||
12
setup.py
12
setup.py
@@ -24,7 +24,7 @@ with open("README.rst", "rt") as f1, open("CHANGES.rst", "rt") as f2:
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="Send2Trash",
|
name="Send2Trash",
|
||||||
version="1.7.1",
|
version="1.8.0",
|
||||||
author="Andrew Senetar",
|
author="Andrew Senetar",
|
||||||
author_email="arsenetar@voltaicideas.net",
|
author_email="arsenetar@voltaicideas.net",
|
||||||
packages=["send2trash"],
|
packages=["send2trash"],
|
||||||
@@ -34,8 +34,16 @@ setup(
|
|||||||
license="BSD License",
|
license="BSD License",
|
||||||
description="Send file to trash natively under Mac OS X, Windows and Linux.",
|
description="Send file to trash natively under Mac OS X, Windows and Linux.",
|
||||||
long_description=LONG_DESCRIPTION,
|
long_description=LONG_DESCRIPTION,
|
||||||
|
long_description_content_type="text/x-rst",
|
||||||
classifiers=CLASSIFIERS,
|
classifiers=CLASSIFIERS,
|
||||||
extras_require={"win32": ["pywin32"]},
|
extras_require={
|
||||||
|
"win32": ['pywin32; sys_platform == "win32"'],
|
||||||
|
"objc": ['pyobjc-framework-Cocoa; sys_platform == "darwin"'],
|
||||||
|
"nativeLib": [
|
||||||
|
'pywin32; sys_platform == "win32"',
|
||||||
|
'pyobjc-framework-Cocoa; sys_platform == "darwin"',
|
||||||
|
],
|
||||||
|
},
|
||||||
project_urls={"Bug Reports": "https://github.com/arsenetar/send2trash/issues"},
|
project_urls={"Bug Reports": "https://github.com/arsenetar/send2trash/issues"},
|
||||||
entry_points={"console_scripts": ["send2trash=send2trash.__main__:main"]},
|
entry_points={"console_scripts": ["send2trash=send2trash.__main__:main"]},
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user