From 69cefbbb5661a8ae9859db6c28337df7ea06640f Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 15 Oct 2020 21:55:07 +0530 Subject: [PATCH] Allow detaching and creating handles in python --- src/calibre/test_build.py | 8 +++++++- src/calibre/utils/windows/winutil.cpp | 28 ++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/calibre/test_build.py b/src/calibre/test_build.py index cce8541144..6d80cd53d9 100644 --- a/src/calibre/test_build.py +++ b/src/calibre/test_build.py @@ -190,6 +190,12 @@ class BuildTest(unittest.TestCase): sz = 23 data = os.urandom(sz) open(path, 'wb').write(data) + h = winutil.Handle(0, winutil.ModuleHandle, 'moo') + r = repr(h) + h2 = winutil.Handle(h.detach(), winutil.ModuleHandle, 'moo') + self.assertEqual(r, repr(h2)) + h2.close() + h = winutil.create_file( path, winutil.GENERIC_READ | winutil.GENERIC_WRITE, 0, winutil.OPEN_ALWAYS, winutil.FILE_ATTRIBUTE_NORMAL) self.assertEqual(winutil.get_file_size(h), sz) @@ -238,7 +244,7 @@ class BuildTest(unittest.TestCase): t.start() testp = os.path.join(dpath, 'test') open(testp, 'w').close() - t.join(2) + t.join(4) self.assertTrue(events) for actions, path in events: self.assertEqual(os.path.join(dpath, path), testp) diff --git a/src/calibre/utils/windows/winutil.cpp b/src/calibre/utils/windows/winutil.cpp index 422bdf6199..59d5cee249 100644 --- a/src/calibre/utils/windows/winutil.cpp +++ b/src/calibre/utils/windows/winutil.cpp @@ -103,6 +103,29 @@ Handle_create(void *handle, WinHandleType handle_type = NormalHandle, PyObject * return self; } +static PyObject * +Handle_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { + PyObject *h = NULL, *name = NULL; + int htype = NormalHandle; + if (!PyArg_ParseTuple(args, "|O!iU", &PyLong_Type, &h, &htype, &name)) return NULL; + switch(htype) { + case NormalHandle: + case IconHandle: + case ModuleHandle: + break; + default: + PyErr_Format(PyExc_TypeError, "unknown handle type: %d", type); + return NULL; + } + Handle *self = (Handle *) HandleType.tp_alloc(type, 0); + if (self) { + self->handle = h ? PyLong_AsVoidPtr(h) : NULL; + self->handle_type = static_cast(htype); + self->associated_name = name; + } + return (PyObject*)self; +} + static int convert_handle(Handle *obj, void **output) { if (Py_TYPE(obj) != &HandleType) { @@ -1160,7 +1183,7 @@ CALIBRE_MODINIT_FUNC PyInit_winutil(void) { HandleType.tp_repr = (reprfunc)Handle_repr; HandleType.tp_as_number = &HandleNumberMethods; HandleType.tp_str = (reprfunc)Handle_repr; - HandleType.tp_new = PyType_GenericNew; + HandleType.tp_new = Handle_new; HandleType.tp_methods = Handle_methods; HandleType.tp_dealloc = (destructor)Handle_dealloc; if (PyType_Ready(&HandleType) < 0) return NULL; @@ -1265,6 +1288,9 @@ CALIBRE_MODINIT_FUNC PyInit_winutil(void) { PyModule_AddIntConstant(m, "ERROR_LOCK_VIOLATION", ERROR_LOCK_VIOLATION); PyModule_AddIntConstant(m, "ERROR_ALREADY_EXISTS", ERROR_ALREADY_EXISTS); PyModule_AddIntConstant(m, "ERROR_BROKEN_PIPE", ERROR_BROKEN_PIPE); + PyModule_AddIntConstant(m, "NormalHandle", NormalHandle); + PyModule_AddIntConstant(m, "ModuleHandle", ModuleHandle); + PyModule_AddIntConstant(m, "IconHandle", IconHandle); return m; }