WPD: Implement deleting objects

This commit is contained in:
Kovid Goyal 2012-08-22 17:36:09 +05:30
parent b63dd79142
commit 41f8e96740
5 changed files with 86 additions and 8 deletions

View File

@ -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)

View File

@ -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

View File

@ -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}
}; };

View File

@ -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))

View File

@ -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);
} }