mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
WPD: Implement deleting objects
This commit is contained in:
parent
b63dd79142
commit
41f8e96740
@ -20,12 +20,13 @@ class FileOrFolder(object):
|
|||||||
self.object_id = entry['id']
|
self.object_id = entry['id']
|
||||||
self.is_folder = entry['is_folder']
|
self.is_folder = entry['is_folder']
|
||||||
self.name = force_unicode(entry.get('name', '___'), 'utf-8')
|
self.name = force_unicode(entry.get('name', '___'), 'utf-8')
|
||||||
|
self.storage_id = entry.get('storage_id', None)
|
||||||
self.persistent_id = entry.get('persistent_id', self.object_id)
|
self.persistent_id = entry.get('persistent_id', self.object_id)
|
||||||
self.size = entry.get('size', 0)
|
self.size = entry.get('size', 0)
|
||||||
# self.parent_id is None for storage objects
|
# self.parent_id is None for storage objects
|
||||||
self.parent_id = entry.get('parent_id', None)
|
self.parent_id = entry.get('parent_id', None)
|
||||||
if self.parent_id == 0:
|
if self.parent_id == 0:
|
||||||
sid = entry['storage_id']
|
sid = self.storage_id
|
||||||
if sid not in all_storage_ids:
|
if sid not in all_storage_ids:
|
||||||
sid = all_storage_ids[0]
|
sid = all_storage_ids[0]
|
||||||
self.parent_id = sid
|
self.parent_id = sid
|
||||||
@ -79,7 +80,17 @@ class FilesystemCache(object):
|
|||||||
FileOrFolder(entry, self, all_storage_ids)
|
FileOrFolder(entry, self, all_storage_ids)
|
||||||
|
|
||||||
for item in self.id_map.itervalues():
|
for item in self.id_map.itervalues():
|
||||||
p = item.parent
|
try:
|
||||||
|
p = item.parent
|
||||||
|
except KeyError:
|
||||||
|
# Parent does not exist, set the parent to be the storage
|
||||||
|
# object
|
||||||
|
sid = p.storage_id
|
||||||
|
if sid not in all_storage_ids:
|
||||||
|
sid = all_storage_ids[0]
|
||||||
|
item.parent_id = sid
|
||||||
|
p = item.parent
|
||||||
|
|
||||||
if p is not None:
|
if p is not None:
|
||||||
t = p.folders if item.is_folder else p.files
|
t = p.folders if item.is_folder else p.files
|
||||||
t.append(item)
|
t.append(item)
|
||||||
|
@ -572,4 +572,44 @@ end:
|
|||||||
|
|
||||||
} // }}}
|
} // }}}
|
||||||
|
|
||||||
|
PyObject* wpd::delete_object(IPortableDevice *device, const wchar_t *object_id) { // {{{
|
||||||
|
IPortableDeviceContent *content = NULL;
|
||||||
|
HRESULT hr;
|
||||||
|
BOOL ok = FALSE;
|
||||||
|
PROPVARIANT pv;
|
||||||
|
IPortableDevicePropVariantCollection *object_ids = NULL;
|
||||||
|
|
||||||
|
PropVariantInit(&pv);
|
||||||
|
pv.vt = VT_LPWSTR;
|
||||||
|
|
||||||
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
|
hr = CoCreateInstance(CLSID_PortableDevicePropVariantCollection, NULL,
|
||||||
|
CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&object_ids));
|
||||||
|
Py_END_ALLOW_THREADS;
|
||||||
|
if (FAILED(hr)) { hresult_set_exc("Failed to create propvariantcollection", hr); goto end; }
|
||||||
|
pv.pwszVal = (wchar_t*)object_id;
|
||||||
|
hr = object_ids->Add(&pv);
|
||||||
|
pv.pwszVal = NULL;
|
||||||
|
if (FAILED(hr)) { hresult_set_exc("Failed to add device id to propvariantcollection", hr); goto end; }
|
||||||
|
|
||||||
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
|
hr = device->Content(&content);
|
||||||
|
Py_END_ALLOW_THREADS;
|
||||||
|
if (FAILED(hr)) { hresult_set_exc("Failed to create content interface", hr); goto end; }
|
||||||
|
|
||||||
|
hr = content->Delete(PORTABLE_DEVICE_DELETE_NO_RECURSION, object_ids, NULL);
|
||||||
|
if (hr == E_ACCESSDENIED) PyErr_SetString(WPDError, "Do not have permission to delete this object");
|
||||||
|
else if (hr == HRESULT_FROM_WIN32(ERROR_DIR_NOT_EMPTY) || hr == HRESULT_FROM_WIN32(ERROR_INVALID_OPERATION)) PyErr_SetString(WPDError, "Cannot delete object as it has children");
|
||||||
|
else if (hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND) || SUCCEEDED(hr)) ok = TRUE;
|
||||||
|
else hresult_set_exc("Cannot delete object", hr);
|
||||||
|
|
||||||
|
end:
|
||||||
|
PropVariantClear(&pv);
|
||||||
|
if (content != NULL) content->Release();
|
||||||
|
if (object_ids != NULL) object_ids->Release();
|
||||||
|
if (!ok) return NULL;
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
|
||||||
|
} // }}}
|
||||||
|
|
||||||
} // namespace wpd
|
} // namespace wpd
|
||||||
|
@ -78,20 +78,22 @@ update_data(Device *self, PyObject *args, PyObject *kwargs) {
|
|||||||
// get_filesystem() {{{
|
// get_filesystem() {{{
|
||||||
static PyObject*
|
static PyObject*
|
||||||
py_get_filesystem(Device *self, PyObject *args, PyObject *kwargs) {
|
py_get_filesystem(Device *self, PyObject *args, PyObject *kwargs) {
|
||||||
PyObject *storage_id;
|
PyObject *storage_id, *ret;
|
||||||
wchar_t *storage;
|
wchar_t *storage;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "O", &storage_id)) return NULL;
|
if (!PyArg_ParseTuple(args, "O", &storage_id)) return NULL;
|
||||||
storage = unicode_to_wchar(storage_id);
|
storage = unicode_to_wchar(storage_id);
|
||||||
if (storage == NULL) return NULL;
|
if (storage == NULL) return NULL;
|
||||||
|
|
||||||
return wpd::get_filesystem(self->device, storage, self->bulk_properties);
|
ret = wpd::get_filesystem(self->device, storage, self->bulk_properties);
|
||||||
|
free(storage);
|
||||||
|
return ret;
|
||||||
} // }}}
|
} // }}}
|
||||||
|
|
||||||
// get_file() {{{
|
// get_file() {{{
|
||||||
static PyObject*
|
static PyObject*
|
||||||
py_get_file(Device *self, PyObject *args, PyObject *kwargs) {
|
py_get_file(Device *self, PyObject *args, PyObject *kwargs) {
|
||||||
PyObject *object_id, *stream, *callback = NULL;
|
PyObject *object_id, *stream, *callback = NULL, *ret;
|
||||||
wchar_t *object;
|
wchar_t *object;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "OO|O", &object_id, &stream, &callback)) return NULL;
|
if (!PyArg_ParseTuple(args, "OO|O", &object_id, &stream, &callback)) return NULL;
|
||||||
@ -100,13 +102,15 @@ py_get_file(Device *self, PyObject *args, PyObject *kwargs) {
|
|||||||
|
|
||||||
if (callback == NULL || !PyCallable_Check(callback)) callback = NULL;
|
if (callback == NULL || !PyCallable_Check(callback)) callback = NULL;
|
||||||
|
|
||||||
return wpd::get_file(self->device, object, stream, callback);
|
ret = wpd::get_file(self->device, object, stream, callback);
|
||||||
|
free(object);
|
||||||
|
return ret;
|
||||||
} // }}}
|
} // }}}
|
||||||
|
|
||||||
// create_folder() {{{
|
// create_folder() {{{
|
||||||
static PyObject*
|
static PyObject*
|
||||||
py_create_folder(Device *self, PyObject *args, PyObject *kwargs) {
|
py_create_folder(Device *self, PyObject *args, PyObject *kwargs) {
|
||||||
PyObject *pparent_id, *pname;
|
PyObject *pparent_id, *pname, *ret;
|
||||||
wchar_t *parent_id, *name;
|
wchar_t *parent_id, *name;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "OO", &pparent_id, &pname)) return NULL;
|
if (!PyArg_ParseTuple(args, "OO", &pparent_id, &pname)) return NULL;
|
||||||
@ -114,7 +118,24 @@ py_create_folder(Device *self, PyObject *args, PyObject *kwargs) {
|
|||||||
name = unicode_to_wchar(pname);
|
name = unicode_to_wchar(pname);
|
||||||
if (parent_id == NULL || name == NULL) return NULL;
|
if (parent_id == NULL || name == NULL) return NULL;
|
||||||
|
|
||||||
return wpd::create_folder(self->device, parent_id, name);
|
ret = wpd::create_folder(self->device, parent_id, name);
|
||||||
|
free(parent_id); free(name);
|
||||||
|
return ret;
|
||||||
|
} // }}}
|
||||||
|
|
||||||
|
// delete_object() {{{
|
||||||
|
static PyObject*
|
||||||
|
py_delete_object(Device *self, PyObject *args, PyObject *kwargs) {
|
||||||
|
PyObject *pobject_id, *ret;
|
||||||
|
wchar_t *object_id;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "O", &pobject_id)) return NULL;
|
||||||
|
object_id = unicode_to_wchar(pobject_id);
|
||||||
|
if (object_id == NULL) return NULL;
|
||||||
|
|
||||||
|
ret = wpd::delete_object(self->device, object_id);
|
||||||
|
free(object_id);
|
||||||
|
return ret;
|
||||||
} // }}}
|
} // }}}
|
||||||
|
|
||||||
static PyMethodDef Device_methods[] = {
|
static PyMethodDef Device_methods[] = {
|
||||||
@ -134,6 +155,10 @@ static PyMethodDef Device_methods[] = {
|
|||||||
"create_folder(parent_id, name) -> Create a folder. Returns the folder metadata."
|
"create_folder(parent_id, name) -> Create a folder. Returns the folder metadata."
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{"delete_object", (PyCFunction)py_delete_object, METH_VARARGS,
|
||||||
|
"delete_object(object_id) -> Delete the object identified by object_id. Note that trying to delete a non-empty folder will raise an error."
|
||||||
|
},
|
||||||
|
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -156,6 +156,7 @@ class MTP_DEVICE(MTPDeviceBase):
|
|||||||
storage = {'id':storage_id, 'size':capacity, 'name':name,
|
storage = {'id':storage_id, 'size':capacity, 'name':name,
|
||||||
'is_folder':True}
|
'is_folder':True}
|
||||||
id_map = self.dev.get_filesystem(storage_id)
|
id_map = self.dev.get_filesystem(storage_id)
|
||||||
|
for x in id_map.itervalues(): x['storage_id'] = storage_id
|
||||||
all_storage.append(storage)
|
all_storage.append(storage)
|
||||||
items.append(id_map.itervalues())
|
items.append(id_map.itervalues())
|
||||||
self._filesystem_cache = FilesystemCache(all_storage, chain(*items))
|
self._filesystem_cache = FilesystemCache(all_storage, chain(*items))
|
||||||
|
@ -59,6 +59,7 @@ extern PyObject* get_device_information(IPortableDevice *device, IPortableDevice
|
|||||||
extern PyObject* get_filesystem(IPortableDevice *device, const wchar_t *storage_id, IPortableDevicePropertiesBulk *bulk_properties);
|
extern PyObject* get_filesystem(IPortableDevice *device, const wchar_t *storage_id, IPortableDevicePropertiesBulk *bulk_properties);
|
||||||
extern PyObject* get_file(IPortableDevice *device, const wchar_t *object_id, PyObject *dest, PyObject *callback);
|
extern PyObject* get_file(IPortableDevice *device, const wchar_t *object_id, PyObject *dest, PyObject *callback);
|
||||||
extern PyObject* create_folder(IPortableDevice *device, const wchar_t *parent_id, const wchar_t *name);
|
extern PyObject* create_folder(IPortableDevice *device, const wchar_t *parent_id, const wchar_t *name);
|
||||||
|
extern PyObject* delete_object(IPortableDevice *device, const wchar_t *object_id);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user