mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Remove pywin32 from filenames.py
This commit is contained in:
parent
5701a6c2c5
commit
e087f086bd
@ -185,6 +185,7 @@ class BuildTest(unittest.TestCase):
|
|||||||
self.assertRaises(OSError, winutil.delete_file, path)
|
self.assertRaises(OSError, winutil.delete_file, path)
|
||||||
self.assertRaises(OSError, winutil.create_file,
|
self.assertRaises(OSError, winutil.create_file,
|
||||||
os.path.join(path, 'cannot'), winutil.GENERIC_READ, 0, winutil.OPEN_ALWAYS, winutil.FILE_ATTRIBUTE_NORMAL)
|
os.path.join(path, 'cannot'), winutil.GENERIC_READ, 0, winutil.OPEN_ALWAYS, winutil.FILE_ATTRIBUTE_NORMAL)
|
||||||
|
self.assertTrue(winutil.supports_hardlinks(os.path.abspath(os.getcwd())[0] + ':\\'))
|
||||||
sz = 23
|
sz = 23
|
||||||
data = os.urandom(sz)
|
data = os.urandom(sz)
|
||||||
open(path, 'wb').write(data)
|
open(path, 'wb').write(data)
|
||||||
|
@ -9,7 +9,7 @@ import os
|
|||||||
import shutil
|
import shutil
|
||||||
import time
|
import time
|
||||||
from math import ceil
|
from math import ceil
|
||||||
from contextlib import suppress
|
from contextlib import suppress, closing
|
||||||
|
|
||||||
from calibre import force_unicode, isbytestring, prints, sanitize_file_name
|
from calibre import force_unicode, isbytestring, prints, sanitize_file_name
|
||||||
from calibre.constants import (
|
from calibre.constants import (
|
||||||
@ -272,25 +272,19 @@ def windows_get_size(path):
|
|||||||
''' On windows file sizes are only accurately stored in the actual file,
|
''' On windows file sizes are only accurately stored in the actual file,
|
||||||
not in the directory entry (which could be out of date). So we open the
|
not in the directory entry (which could be out of date). So we open the
|
||||||
file, and get the actual size. '''
|
file, and get the actual size. '''
|
||||||
import win32file
|
from calibre_extensions import winutil
|
||||||
if isbytestring(path):
|
if isbytestring(path):
|
||||||
path = path.decode(filesystem_encoding)
|
path = path.decode(filesystem_encoding)
|
||||||
h = win32file.CreateFileW(
|
with closing(winutil.create_file(
|
||||||
path, 0, win32file.FILE_SHARE_READ | win32file.FILE_SHARE_WRITE | win32file.FILE_SHARE_DELETE,
|
path, 0, winutil.FILE_SHARE_READ | winutil.FILE_SHARE_WRITE | winutil.FILE_SHARE_DELETE,
|
||||||
None, win32file.OPEN_EXISTING, 0, None)
|
winutil.OPEN_EXISTING, 0)
|
||||||
try:
|
) as h:
|
||||||
return win32file.GetFileSize(h)
|
return winutil.get_file_size(h)
|
||||||
finally:
|
|
||||||
win32file.CloseHandle(h)
|
|
||||||
|
|
||||||
|
|
||||||
def windows_hardlink(src, dest):
|
def windows_hardlink(src, dest):
|
||||||
import win32file, pywintypes
|
from calibre_extensions import winutil
|
||||||
try:
|
winutil.create_hard_link(dest, src)
|
||||||
win32file.CreateHardLink(dest, src)
|
|
||||||
except pywintypes.error as e:
|
|
||||||
msg = 'Creating hardlink from %s to %s failed: %%s' % (src, dest)
|
|
||||||
raise OSError(msg % e)
|
|
||||||
src_size = os.path.getsize(src)
|
src_size = os.path.getsize(src)
|
||||||
# We open and close dest, to ensure its directory entry is updated
|
# We open and close dest, to ensure its directory entry is updated
|
||||||
# see http://blogs.msdn.com/b/oldnewthing/archive/2011/12/26/10251026.aspx
|
# see http://blogs.msdn.com/b/oldnewthing/archive/2011/12/26/10251026.aspx
|
||||||
@ -311,12 +305,8 @@ def windows_hardlink(src, dest):
|
|||||||
|
|
||||||
|
|
||||||
def windows_fast_hardlink(src, dest):
|
def windows_fast_hardlink(src, dest):
|
||||||
import win32file, pywintypes
|
from calibre_extensions import winutil
|
||||||
try:
|
winutil.create_hard_link(dest, src)
|
||||||
win32file.CreateHardLink(dest, src)
|
|
||||||
except pywintypes.error as e:
|
|
||||||
msg = 'Creating hardlink from %s to %s failed: %%s' % (src, dest)
|
|
||||||
raise OSError(msg % e)
|
|
||||||
ssz, dsz = windows_get_size(src), windows_get_size(dest)
|
ssz, dsz = windows_get_size(src), windows_get_size(dest)
|
||||||
if ssz != dsz:
|
if ssz != dsz:
|
||||||
msg = 'Creating hardlink from %s to %s failed: %%s' % (src, dest)
|
msg = 'Creating hardlink from %s to %s failed: %%s' % (src, dest)
|
||||||
@ -324,15 +314,10 @@ def windows_fast_hardlink(src, dest):
|
|||||||
|
|
||||||
|
|
||||||
def windows_nlinks(path):
|
def windows_nlinks(path):
|
||||||
import win32file
|
from calibre_extensions import winutil
|
||||||
dwFlagsAndAttributes = win32file.FILE_FLAG_BACKUP_SEMANTICS if os.path.isdir(path) else 0
|
|
||||||
if isbytestring(path):
|
if isbytestring(path):
|
||||||
path = path.decode(filesystem_encoding)
|
path = path.decode(filesystem_encoding)
|
||||||
handle = win32file.CreateFileW(path, win32file.GENERIC_READ, win32file.FILE_SHARE_READ, None, win32file.OPEN_EXISTING, dwFlagsAndAttributes, None)
|
return winutil.nlinks(path)
|
||||||
try:
|
|
||||||
return win32file.GetFileInformationByHandle(handle)[7]
|
|
||||||
finally:
|
|
||||||
handle.Close()
|
|
||||||
|
|
||||||
|
|
||||||
class WindowsAtomicFolderMove(object):
|
class WindowsAtomicFolderMove(object):
|
||||||
@ -346,11 +331,9 @@ class WindowsAtomicFolderMove(object):
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, path):
|
def __init__(self, path):
|
||||||
self.handle_map = {}
|
|
||||||
|
|
||||||
import win32file, winerror
|
|
||||||
from pywintypes import error
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
from calibre_extensions import winutil
|
||||||
|
self.handle_map = {}
|
||||||
|
|
||||||
if isbytestring(path):
|
if isbytestring(path):
|
||||||
path = path.decode(filesystem_encoding)
|
path = path.decode(filesystem_encoding)
|
||||||
@ -368,18 +351,16 @@ class WindowsAtomicFolderMove(object):
|
|||||||
f = os.path.normcase(os.path.abspath(os.path.join(path, x)))
|
f = os.path.normcase(os.path.abspath(os.path.join(path, x)))
|
||||||
if not os.path.isfile(f):
|
if not os.path.isfile(f):
|
||||||
continue
|
continue
|
||||||
try:
|
with suppress(OSError):
|
||||||
# Ensure the file is not read-only
|
# Ensure the file is not read-only
|
||||||
win32file.SetFileAttributes(f, win32file.FILE_ATTRIBUTE_NORMAL)
|
winutil.set_file_attributes(f, winutil.FILE_ATTRIBUTE_NORMAL)
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
h = win32file.CreateFileW(f, win32file.GENERIC_READ,
|
h = winutil.create_file(f, winutil.GENERIC_READ,
|
||||||
win32file.FILE_SHARE_DELETE, None,
|
winutil.FILE_SHARE_DELETE,
|
||||||
win32file.OPEN_EXISTING, win32file.FILE_FLAG_SEQUENTIAL_SCAN, 0)
|
winutil.OPEN_EXISTING, winutil.FILE_FLAG_SEQUENTIAL_SCAN)
|
||||||
except error as e:
|
except OSError as e:
|
||||||
if getattr(e, 'winerror', 0) == winerror.ERROR_SHARING_VIOLATION:
|
if e.winerror == winutil.ERROR_SHARING_VIOLATION:
|
||||||
# The file could be a hardlink to an already opened file,
|
# The file could be a hardlink to an already opened file,
|
||||||
# in which case we use the same handle for both files
|
# in which case we use the same handle for both files
|
||||||
fileid = name_to_fileid[x]
|
fileid = name_to_fileid[x]
|
||||||
@ -395,7 +376,7 @@ class WindowsAtomicFolderMove(object):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
self.close_handles()
|
self.close_handles()
|
||||||
if getattr(e, 'winerror', 0) == winerror.ERROR_SHARING_VIOLATION:
|
if e.winerror == winutil.ERROR_SHARING_VIOLATION:
|
||||||
err = IOError(errno.EACCES,
|
err = IOError(errno.EACCES,
|
||||||
_('File is open in another process'))
|
_('File is open in another process'))
|
||||||
err.filename = f
|
err.filename = f
|
||||||
@ -409,9 +390,9 @@ class WindowsAtomicFolderMove(object):
|
|||||||
self.handle_map[f] = h
|
self.handle_map[f] = h
|
||||||
|
|
||||||
def copy_path_to(self, path, dest):
|
def copy_path_to(self, path, dest):
|
||||||
import win32file
|
from calibre_extensions import winutil
|
||||||
handle = None
|
handle = None
|
||||||
for p, h in iteritems(self.handle_map):
|
for p, h in self.handle_map.items():
|
||||||
if samefile_windows(path, p):
|
if samefile_windows(path, p):
|
||||||
handle = h
|
handle = h
|
||||||
break
|
break
|
||||||
@ -421,18 +402,16 @@ class WindowsAtomicFolderMove(object):
|
|||||||
' operation was started'%path)
|
' operation was started'%path)
|
||||||
else:
|
else:
|
||||||
raise ValueError('The file %r does not exist'%path)
|
raise ValueError('The file %r does not exist'%path)
|
||||||
try:
|
|
||||||
|
with suppress(OSError):
|
||||||
windows_hardlink(path, dest)
|
windows_hardlink(path, dest)
|
||||||
return
|
return
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
win32file.SetFilePointer(handle, 0, win32file.FILE_BEGIN)
|
winutil.set_file_pointer(handle, 0, winutil.FILE_BEGIN)
|
||||||
with lopen(dest, 'wb') as f:
|
with lopen(dest, 'wb') as f:
|
||||||
|
sz = 1024 * 1024
|
||||||
while True:
|
while True:
|
||||||
hr, raw = win32file.ReadFile(handle, 1024*1024)
|
raw = winutil.read_file(handle, sz)
|
||||||
if hr != 0:
|
|
||||||
raise IOError(hr, 'Error while reading from %r'%path)
|
|
||||||
if not raw:
|
if not raw:
|
||||||
break
|
break
|
||||||
f.write(raw)
|
f.write(raw)
|
||||||
@ -445,22 +424,20 @@ class WindowsAtomicFolderMove(object):
|
|||||||
key = (p, h)
|
key = (p, h)
|
||||||
break
|
break
|
||||||
if key is not None:
|
if key is not None:
|
||||||
import win32file
|
key[1].close()
|
||||||
win32file.CloseHandle(key[1])
|
|
||||||
remove = [f for f, h in iteritems(self.handle_map) if h is key[1]]
|
remove = [f for f, h in iteritems(self.handle_map) if h is key[1]]
|
||||||
for x in remove:
|
for x in remove:
|
||||||
self.handle_map.pop(x)
|
self.handle_map.pop(x)
|
||||||
|
|
||||||
def close_handles(self):
|
def close_handles(self):
|
||||||
import win32file
|
|
||||||
for h in itervalues(self.handle_map):
|
for h in itervalues(self.handle_map):
|
||||||
win32file.CloseHandle(h)
|
h.close()
|
||||||
self.handle_map = {}
|
self.handle_map = {}
|
||||||
|
|
||||||
def delete_originals(self):
|
def delete_originals(self):
|
||||||
import win32file
|
from calibre_extensions import winutil
|
||||||
for path in self.handle_map:
|
for path in self.handle_map:
|
||||||
win32file.DeleteFileW(path)
|
winutil.delete_file(path)
|
||||||
self.close_handles()
|
self.close_handles()
|
||||||
|
|
||||||
|
|
||||||
@ -567,20 +544,12 @@ def copyfile(src, dest):
|
|||||||
|
|
||||||
|
|
||||||
def get_hardlink_function(src, dest):
|
def get_hardlink_function(src, dest):
|
||||||
if iswindows:
|
if not iswindows:
|
||||||
import win32file, win32api
|
return os.link
|
||||||
colon = b':' if isinstance(dest, bytes) else ':'
|
from calibre_extensions import winutil
|
||||||
root = dest[0] + colon
|
root = dest[0] + ':\\'
|
||||||
try:
|
if src[0].lower() == dest[0].lower() and hasattr(winutil, 'supports_hardlinks') and winutil.supports_hardlinks(root):
|
||||||
is_suitable = win32file.GetDriveType(root) not in (win32file.DRIVE_REMOTE, win32file.DRIVE_CDROM)
|
return windows_fast_hardlink
|
||||||
# See https://msdn.microsoft.com/en-us/library/windows/desktop/aa364993(v=vs.85).aspx
|
|
||||||
supports_hard_links = win32api.GetVolumeInformation(root + os.sep)[3] & 0x00400000
|
|
||||||
except Exception:
|
|
||||||
supports_hard_links = is_suitable = False
|
|
||||||
hardlink = windows_fast_hardlink if is_suitable and supports_hard_links and src[0].lower() == dest[0].lower() else None
|
|
||||||
else:
|
|
||||||
hardlink = os.link
|
|
||||||
return hardlink
|
|
||||||
|
|
||||||
|
|
||||||
def copyfile_using_links(path, dest, dest_is_dir=True, filecopyfunc=copyfile):
|
def copyfile_using_links(path, dest, dest_is_dir=True, filecopyfunc=copyfile):
|
||||||
|
@ -510,6 +510,18 @@ winutil_delete_file(PyObject *self, PyObject *args) {
|
|||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
supports_hardlinks(PyObject *self, PyObject *args) {
|
||||||
|
wchar_raii path;
|
||||||
|
if (!PyArg_ParseTuple(args, "O&", py_to_wchar_no_none, &path)) return NULL;
|
||||||
|
UINT dt = GetDriveType(path.ptr());
|
||||||
|
if (dt == DRIVE_REMOTE || dt == DRIVE_CDROM) Py_RETURN_FALSE;
|
||||||
|
DWORD max_component_length, flags;
|
||||||
|
if (!GetVolumeInformationW(path.ptr(), NULL, 0, NULL, &max_component_length, &flags, NULL, 0)) return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, 0, PyTuple_GET_ITEM(args, 0));
|
||||||
|
if (flags & FILE_SUPPORTS_HARD_LINKS) Py_RETURN_TRUE;
|
||||||
|
Py_RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
winutil_create_hard_link(PyObject *self, PyObject *args) {
|
winutil_create_hard_link(PyObject *self, PyObject *args) {
|
||||||
wchar_raii path, existing_path;
|
wchar_raii path, existing_path;
|
||||||
@ -550,8 +562,8 @@ winutil_nlinks(PyObject *self, PyObject *args) {
|
|||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
winutil_set_file_attributes(PyObject *self, PyObject *args) {
|
winutil_set_file_attributes(PyObject *self, PyObject *args) {
|
||||||
wchar_raii path; unsigned long attrs;
|
wchar_raii path; unsigned long attrs = FILE_ATTRIBUTE_NORMAL;
|
||||||
if (!PyArg_ParseTuple(args, "O&k", py_to_wchar_no_none, &path, &attrs)) return NULL;
|
if (!PyArg_ParseTuple(args, "O&|k", py_to_wchar_no_none, &path, &attrs)) return NULL;
|
||||||
if (!SetFileAttributes(path.ptr(), attrs)) return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, 0, PyTuple_GET_ITEM(args, 0));
|
if (!SetFileAttributes(path.ptr(), attrs)) return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, 0, PyTuple_GET_ITEM(args, 0));
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
@ -1026,6 +1038,7 @@ static PyMethodDef winutil_methods[] = {
|
|||||||
M(is_wow64_process, METH_NOARGS),
|
M(is_wow64_process, METH_NOARGS),
|
||||||
M(get_dll_directory, METH_NOARGS),
|
M(get_dll_directory, METH_NOARGS),
|
||||||
M(create_mutex, METH_VARARGS),
|
M(create_mutex, METH_VARARGS),
|
||||||
|
M(supports_hardlinks, METH_VARARGS),
|
||||||
M(get_async_key_state, METH_VARARGS),
|
M(get_async_key_state, METH_VARARGS),
|
||||||
M(create_named_pipe, METH_VARARGS),
|
M(create_named_pipe, METH_VARARGS),
|
||||||
M(connect_named_pipe, METH_VARARGS),
|
M(connect_named_pipe, METH_VARARGS),
|
||||||
@ -1125,7 +1138,7 @@ static PyMethodDef winutil_methods[] = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
{"read_file", (PyCFunction)winutil_read_file, METH_VARARGS,
|
{"read_file", (PyCFunction)winutil_read_file, METH_VARARGS,
|
||||||
"set_file_pointer(handle, chunk_size=16KB)\n\nWrapper for ReadFile"
|
"read_file(handle, chunk_size=16KB)\n\nWrapper for ReadFile"
|
||||||
},
|
},
|
||||||
|
|
||||||
{"get_disk_free_space", (PyCFunction)winutil_get_disk_free_space, METH_VARARGS,
|
{"get_disk_free_space", (PyCFunction)winutil_get_disk_free_space, METH_VARARGS,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user