winrt-runtime 2.1.0__tar.gz → 2.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {winrt_runtime-2.1.0 → winrt_runtime-2.2.0}/PKG-INFO +2 -2
- {winrt_runtime-2.1.0 → winrt_runtime-2.2.0}/_winrt.cpp +219 -45
- {winrt_runtime-2.1.0 → winrt_runtime-2.2.0}/_winrt_array.cpp +4 -26
- {winrt_runtime-2.1.0 → winrt_runtime-2.2.0}/pyproject.toml +4 -3
- winrt_runtime-2.2.0/pywinrt-version.txt +1 -0
- {winrt_runtime-2.1.0 → winrt_runtime-2.2.0}/runtime.cpp +136 -21
- {winrt_runtime-2.1.0 → winrt_runtime-2.2.0}/src/winrt/_winrt.pyi +2 -0
- {winrt_runtime-2.1.0 → winrt_runtime-2.2.0}/src/winrt/system/__init__.py +30 -0
- {winrt_runtime-2.1.0 → winrt_runtime-2.2.0}/src/winrt_runtime.egg-info/PKG-INFO +2 -2
- winrt_runtime-2.1.0/pywinrt-version.txt +0 -1
- {winrt_runtime-2.1.0 → winrt_runtime-2.2.0}/README.md +0 -0
- {winrt_runtime-2.1.0 → winrt_runtime-2.2.0}/setup.cfg +0 -0
- {winrt_runtime-2.1.0 → winrt_runtime-2.2.0}/setup.py +0 -0
- {winrt_runtime-2.1.0 → winrt_runtime-2.2.0}/src/winrt/py.typed +0 -0
- {winrt_runtime-2.1.0 → winrt_runtime-2.2.0}/src/winrt_runtime.egg-info/SOURCES.txt +0 -0
- {winrt_runtime-2.1.0 → winrt_runtime-2.2.0}/src/winrt_runtime.egg-info/dependency_links.txt +0 -0
- {winrt_runtime-2.1.0 → winrt_runtime-2.2.0}/src/winrt_runtime.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: winrt-runtime
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: Python projection of Windows Runtime (WinRT) APIs
|
|
5
5
|
License: MIT
|
|
6
6
|
Project-URL: Documentation, https://pywinrt.readthedocs.io
|
|
@@ -10,7 +10,7 @@ Classifier: Operating System :: Microsoft :: Windows
|
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
11
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
13
|
-
Requires-Python: <3.
|
|
13
|
+
Requires-Python: <3.14,>=3.9
|
|
14
14
|
Description-Content-Type: text/markdown
|
|
15
15
|
|
|
16
16
|
# winrt-runtime
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
// must be included before winrt to avoid compile errors
|
|
2
2
|
#include <Shobjidl.h>
|
|
3
|
+
#include <libloaderapi.h>
|
|
3
4
|
|
|
4
5
|
#define PYWINRT_RUNTIME_MODULE
|
|
5
6
|
#include "pybase.h"
|
|
7
|
+
#include "pyruntime.h"
|
|
6
8
|
#include <winrt/base.h>
|
|
7
9
|
|
|
8
10
|
namespace py::cpp::_winrt
|
|
@@ -128,6 +130,7 @@ namespace py::cpp::_winrt
|
|
|
128
130
|
{
|
|
129
131
|
PyObject_HEAD;
|
|
130
132
|
PyObject* _iter;
|
|
133
|
+
PyObject* _key;
|
|
131
134
|
};
|
|
132
135
|
|
|
133
136
|
static PyMemberDef MappingIter_members[]
|
|
@@ -136,6 +139,7 @@ namespace py::cpp::_winrt
|
|
|
136
139
|
offsetof(MappingIter_object, _iter),
|
|
137
140
|
0,
|
|
138
141
|
PyDoc_STR("base KeyValuePair iterator")},
|
|
142
|
+
{"_key", T_OBJECT, offsetof(MappingIter_object, _key), 0, nullptr},
|
|
139
143
|
{}};
|
|
140
144
|
|
|
141
145
|
static int MappingIter_init(PyObject* self, PyObject* args, PyObject* kwds) noexcept
|
|
@@ -165,30 +169,41 @@ namespace py::cpp::_winrt
|
|
|
165
169
|
return -1;
|
|
166
170
|
}
|
|
167
171
|
|
|
172
|
+
py::pyobj_handle key{PyUnicode_FromString("key")};
|
|
173
|
+
if (!key)
|
|
174
|
+
{
|
|
175
|
+
return -1;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (PyObject_SetAttrString(self, "_key", key.get()) == -1)
|
|
179
|
+
{
|
|
180
|
+
return -1;
|
|
181
|
+
}
|
|
182
|
+
|
|
168
183
|
return 0;
|
|
169
184
|
}
|
|
170
185
|
|
|
171
|
-
static PyObject* MappingIter_iternext(
|
|
186
|
+
static PyObject* MappingIter_iternext(MappingIter_object* self) noexcept
|
|
172
187
|
{
|
|
173
|
-
|
|
174
|
-
py::pyobj_handle base_iter{PyObject_GetAttrString(self, "_iter")};
|
|
175
|
-
|
|
176
|
-
if (!base_iter)
|
|
188
|
+
if (!self->_iter)
|
|
177
189
|
{
|
|
190
|
+
PyErr_SetString(PyExc_RuntimeError, "_iter was deleted");
|
|
178
191
|
return nullptr;
|
|
179
192
|
}
|
|
180
193
|
|
|
181
|
-
|
|
182
|
-
py::pyobj_handle next{PyIter_Next(base_iter.get())};
|
|
183
|
-
|
|
194
|
+
py::pyobj_handle next{PyIter_Next(self->_iter)};
|
|
184
195
|
if (!next)
|
|
185
196
|
{
|
|
186
197
|
return nullptr;
|
|
187
198
|
}
|
|
188
199
|
|
|
189
|
-
|
|
190
|
-
|
|
200
|
+
if (!self->_key)
|
|
201
|
+
{
|
|
202
|
+
PyErr_SetString(PyExc_RuntimeError, "_key was deleted");
|
|
203
|
+
return nullptr;
|
|
204
|
+
}
|
|
191
205
|
|
|
206
|
+
py::pyobj_handle key{PyObject_GetAttr(next.get(), self->_key)};
|
|
192
207
|
if (!key)
|
|
193
208
|
{
|
|
194
209
|
return nullptr;
|
|
@@ -222,10 +237,13 @@ namespace py::cpp::_winrt
|
|
|
222
237
|
.abi_version_major = py::runtime_abi_version_major,
|
|
223
238
|
.abi_version_minor = py::runtime_abi_version_minor,
|
|
224
239
|
.register_python_type = py::register_python_type,
|
|
240
|
+
.get_python_type = py::get_python_type,
|
|
225
241
|
.wrap_mapping_iter = py::wrap_mapping_iter,
|
|
226
242
|
.is_buffer_compatible = py::is_buffer_compatible,
|
|
227
243
|
.convert_datetime = py::convert_datetime,
|
|
228
244
|
.convert_to_datetime = py::convert_to_datetime,
|
|
245
|
+
.convert_guid = py::convert_guid,
|
|
246
|
+
.convert_to_guid = py::convert_to_guid,
|
|
229
247
|
.get_object_type = py::get_object_type,
|
|
230
248
|
.array_new = py::cpp::_winrt::Array_New,
|
|
231
249
|
.array_assign = &py::cpp::_winrt::Array_Assign,
|
|
@@ -291,6 +309,148 @@ namespace py::cpp::_winrt
|
|
|
291
309
|
Py_RETURN_NONE;
|
|
292
310
|
}
|
|
293
311
|
|
|
312
|
+
static PyObject* add_dll_directory(PyObject* /*unused*/, PyObject* obj) noexcept
|
|
313
|
+
{
|
|
314
|
+
std::unique_ptr<wchar_t, decltype(&PyMem_Free)> path{
|
|
315
|
+
PyUnicode_AsWideCharString(obj, nullptr), &PyMem_Free};
|
|
316
|
+
|
|
317
|
+
if (!path)
|
|
318
|
+
{
|
|
319
|
+
return nullptr;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
auto cookie = AddDllDirectory(path.get());
|
|
323
|
+
|
|
324
|
+
if (!cookie)
|
|
325
|
+
{
|
|
326
|
+
PyErr_SetFromWindowsErr(GetLastError());
|
|
327
|
+
return nullptr;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return PyLong_FromVoidPtr(cookie);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
static PyObject* remove_dll_directory(PyObject* /*unused*/, PyObject* obj) noexcept
|
|
334
|
+
{
|
|
335
|
+
auto cookie = PyLong_AsVoidPtr(obj);
|
|
336
|
+
if (!cookie && PyErr_Occurred())
|
|
337
|
+
{
|
|
338
|
+
return nullptr;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if (!RemoveDllDirectory(cookie))
|
|
342
|
+
{
|
|
343
|
+
PyErr_SetFromWindowsErr(GetLastError());
|
|
344
|
+
return nullptr;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
Py_RETURN_NONE;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Equivalent to functools.cache(functools.partial(uuid.UUID, None))
|
|
352
|
+
*
|
|
353
|
+
* This is a performance optimization since the UUID constructor is expensive.
|
|
354
|
+
*/
|
|
355
|
+
static PyObject* wrap_uuid_constructor() noexcept
|
|
356
|
+
{
|
|
357
|
+
pyobj_handle uuid_module{PyImport_ImportModule("uuid")};
|
|
358
|
+
if (!uuid_module)
|
|
359
|
+
{
|
|
360
|
+
return nullptr;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
pyobj_handle uuid_type{PyObject_GetAttrString(uuid_module.get(), "UUID")};
|
|
364
|
+
if (!uuid_type)
|
|
365
|
+
{
|
|
366
|
+
return nullptr;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
pyobj_handle functools_module{PyImport_ImportModule("functools")};
|
|
370
|
+
if (!functools_module)
|
|
371
|
+
{
|
|
372
|
+
return nullptr;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
pyobj_handle partial_func{
|
|
376
|
+
PyObject_GetAttrString(functools_module.get(), "partial")};
|
|
377
|
+
if (!partial_func)
|
|
378
|
+
{
|
|
379
|
+
return nullptr;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
pyobj_handle partial_uuid_func{PyObject_CallFunctionObjArgs(
|
|
383
|
+
partial_func.get(), uuid_type.get(), Py_None, nullptr)};
|
|
384
|
+
if (!partial_uuid_func)
|
|
385
|
+
{
|
|
386
|
+
return nullptr;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// REVISIT: we could probably implement a cache function in C++ that
|
|
390
|
+
// would even more performant
|
|
391
|
+
pyobj_handle cache_func{
|
|
392
|
+
PyObject_GetAttrString(functools_module.get(), "cache")};
|
|
393
|
+
if (!cache_func)
|
|
394
|
+
{
|
|
395
|
+
return nullptr;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
return PyObject_CallOneArg(cache_func.get(), partial_uuid_func.get());
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
static int module_traverse(PyObject* module, visitproc visit, void* arg) noexcept
|
|
402
|
+
{
|
|
403
|
+
auto state = reinterpret_cast<module_state*>(PyModule_GetState(module));
|
|
404
|
+
|
|
405
|
+
Py_VISIT(state->object_type);
|
|
406
|
+
Py_VISIT(state->array_type);
|
|
407
|
+
Py_VISIT(state->mapping_iter_type);
|
|
408
|
+
Py_VISIT(state->to_uuid_func);
|
|
409
|
+
|
|
410
|
+
for (const auto& [key, value] : state->type_cache)
|
|
411
|
+
{
|
|
412
|
+
Py_VISIT(value);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
return 0;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
static int module_clear(PyObject* module) noexcept
|
|
419
|
+
{
|
|
420
|
+
auto state = reinterpret_cast<module_state*>(PyModule_GetState(module));
|
|
421
|
+
|
|
422
|
+
Py_CLEAR(state->object_type);
|
|
423
|
+
Py_CLEAR(state->array_type);
|
|
424
|
+
Py_CLEAR(state->mapping_iter_type);
|
|
425
|
+
Py_CLEAR(state->to_uuid_func);
|
|
426
|
+
|
|
427
|
+
auto type_cache = std::move(state->type_cache);
|
|
428
|
+
|
|
429
|
+
for (auto& [key, value] : type_cache)
|
|
430
|
+
{
|
|
431
|
+
Py_XDECREF(value);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
return 0;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
static void module_free(PyObject* module) noexcept
|
|
438
|
+
{
|
|
439
|
+
auto state = reinterpret_cast<module_state*>(PyModule_GetState(module));
|
|
440
|
+
|
|
441
|
+
Py_XDECREF(state->object_type);
|
|
442
|
+
Py_XDECREF(state->array_type);
|
|
443
|
+
Py_XDECREF(state->mapping_iter_type);
|
|
444
|
+
Py_XDECREF(state->to_uuid_func);
|
|
445
|
+
|
|
446
|
+
for (auto& [key, value] : state->type_cache)
|
|
447
|
+
{
|
|
448
|
+
Py_XDECREF(value);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
std::destroy_at(&state->type_cache);
|
|
452
|
+
}
|
|
453
|
+
|
|
294
454
|
PyDoc_STRVAR(module_doc, "_winrt");
|
|
295
455
|
|
|
296
456
|
static PyMethodDef module_methods[]{
|
|
@@ -298,23 +458,33 @@ namespace py::cpp::_winrt
|
|
|
298
458
|
{"uninit_apartment",
|
|
299
459
|
uninit_apartment,
|
|
300
460
|
METH_NOARGS,
|
|
301
|
-
"uninitialize the apartment"},
|
|
461
|
+
PyDoc_STR("uninitialize the apartment")},
|
|
302
462
|
{"initialize_with_window",
|
|
303
463
|
initialize_with_window,
|
|
304
464
|
METH_VARARGS,
|
|
305
|
-
|
|
465
|
+
PyDoc_STR(
|
|
466
|
+
"interop function to invoke IInitializeWithWindow::Initialize on an object")},
|
|
467
|
+
{"_add_dll_directory",
|
|
468
|
+
add_dll_directory,
|
|
469
|
+
METH_O,
|
|
470
|
+
PyDoc_STR("Adds a directory to the DLL search path.")},
|
|
471
|
+
{"_remove_dll_directory",
|
|
472
|
+
remove_dll_directory,
|
|
473
|
+
METH_O,
|
|
474
|
+
PyDoc_STR(
|
|
475
|
+
"Removes a directory that was added to the process DLL search path by using _add_dll_directory.")},
|
|
306
476
|
{}};
|
|
307
477
|
|
|
308
478
|
static PyModuleDef module_def
|
|
309
479
|
= {PyModuleDef_HEAD_INIT,
|
|
310
480
|
"_winrt",
|
|
311
481
|
module_doc,
|
|
312
|
-
|
|
482
|
+
sizeof(module_state),
|
|
313
483
|
module_methods,
|
|
314
484
|
nullptr,
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
485
|
+
module_traverse,
|
|
486
|
+
module_clear,
|
|
487
|
+
reinterpret_cast<freefunc>(module_free)};
|
|
318
488
|
|
|
319
489
|
static PyObject* module_init() noexcept
|
|
320
490
|
{
|
|
@@ -324,27 +494,31 @@ namespace py::cpp::_winrt
|
|
|
324
494
|
= static_cast<long>(winrt::apartment_type::single_threaded);
|
|
325
495
|
|
|
326
496
|
py::pyobj_handle module{PyModule_Create(&module_def)};
|
|
327
|
-
|
|
328
497
|
if (!module)
|
|
329
498
|
{
|
|
330
499
|
return nullptr;
|
|
331
500
|
}
|
|
332
501
|
|
|
333
|
-
|
|
334
|
-
|
|
502
|
+
auto state = reinterpret_cast<module_state*>(PyModule_GetState(module.get()));
|
|
503
|
+
std::construct_at(&state->type_cache);
|
|
504
|
+
|
|
505
|
+
py::pytype_handle object_type{py::register_python_type(
|
|
506
|
+
module.get(), &Object_type_spec, nullptr, nullptr)};
|
|
507
|
+
if (!object_type)
|
|
335
508
|
{
|
|
336
509
|
return nullptr;
|
|
337
510
|
}
|
|
338
511
|
|
|
339
|
-
|
|
340
|
-
|
|
512
|
+
py::pytype_handle array_type{
|
|
513
|
+
py::register_python_type(module.get(), &Array_type_spec, nullptr, nullptr)};
|
|
514
|
+
if (!array_type)
|
|
341
515
|
{
|
|
342
516
|
return nullptr;
|
|
343
517
|
}
|
|
344
518
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
519
|
+
py::pytype_handle mapping_iter_type{py::register_python_type(
|
|
520
|
+
module.get(), &MappingIter_type_spec, nullptr, nullptr)};
|
|
521
|
+
if (!mapping_iter_type)
|
|
348
522
|
{
|
|
349
523
|
return nullptr;
|
|
350
524
|
}
|
|
@@ -375,6 +549,17 @@ namespace py::cpp::_winrt
|
|
|
375
549
|
return nullptr;
|
|
376
550
|
}
|
|
377
551
|
|
|
552
|
+
pyobj_handle to_uuid_func{wrap_uuid_constructor()};
|
|
553
|
+
if (!to_uuid_func)
|
|
554
|
+
{
|
|
555
|
+
return nullptr;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
state->object_type = object_type.detach();
|
|
559
|
+
state->array_type = array_type.detach();
|
|
560
|
+
state->mapping_iter_type = mapping_iter_type.detach();
|
|
561
|
+
state->to_uuid_func = to_uuid_func.detach();
|
|
562
|
+
|
|
378
563
|
return module.detach();
|
|
379
564
|
}
|
|
380
565
|
} // namespace py::cpp::_winrt
|
|
@@ -384,35 +569,24 @@ PyMODINIT_FUNC PyInit__winrt(void) noexcept
|
|
|
384
569
|
return py::cpp::_winrt::module_init();
|
|
385
570
|
}
|
|
386
571
|
|
|
387
|
-
|
|
572
|
+
py::cpp::_winrt::module_state* py::cpp::_winrt::get_module_state() noexcept
|
|
388
573
|
{
|
|
389
|
-
py::
|
|
390
|
-
|
|
391
|
-
if (!system_module)
|
|
574
|
+
auto module = PyState_FindModule(&py::cpp::_winrt::module_def);
|
|
575
|
+
if (!module)
|
|
392
576
|
{
|
|
393
577
|
return nullptr;
|
|
394
578
|
}
|
|
395
579
|
|
|
396
|
-
py::
|
|
397
|
-
|
|
398
|
-
if (!object_type)
|
|
399
|
-
{
|
|
400
|
-
return nullptr;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
if (!PyType_Check(object_type.get()))
|
|
404
|
-
{
|
|
405
|
-
PyErr_SetString(PyExc_TypeError, "winrt.system.Object is not a type object!");
|
|
406
|
-
return nullptr;
|
|
407
|
-
}
|
|
580
|
+
return reinterpret_cast<py::cpp::_winrt::module_state*>(PyModule_GetState(module));
|
|
581
|
+
}
|
|
408
582
|
|
|
409
|
-
|
|
410
|
-
|
|
583
|
+
PyTypeObject* py::get_object_type() noexcept
|
|
584
|
+
{
|
|
585
|
+
auto state = py::cpp::_winrt::get_module_state();
|
|
586
|
+
if (!state)
|
|
411
587
|
{
|
|
412
|
-
PyErr_SetString(
|
|
413
|
-
PyExc_TypeError, "winrt.system.Object is not the expected type!");
|
|
414
588
|
return nullptr;
|
|
415
589
|
}
|
|
416
590
|
|
|
417
|
-
return
|
|
591
|
+
return state->object_type;
|
|
418
592
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#define PYWINRT_RUNTIME_MODULE
|
|
2
2
|
#include "pybase.h"
|
|
3
|
+
#include "pyruntime.h"
|
|
3
4
|
#include "py.Windows.Foundation.h"
|
|
4
5
|
#include <winrt/base.h>
|
|
5
6
|
|
|
@@ -538,36 +539,13 @@ namespace py::cpp::_winrt
|
|
|
538
539
|
|
|
539
540
|
static PyTypeObject* get_array_type() noexcept
|
|
540
541
|
{
|
|
541
|
-
py::
|
|
542
|
-
|
|
543
|
-
if (!system_module)
|
|
544
|
-
{
|
|
545
|
-
return nullptr;
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
py::pyobj_handle array_type{
|
|
549
|
-
PyObject_GetAttrString(system_module.get(), "Array")};
|
|
550
|
-
|
|
551
|
-
if (!array_type)
|
|
552
|
-
{
|
|
553
|
-
return nullptr;
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
if (!PyType_Check(array_type.get()))
|
|
557
|
-
{
|
|
558
|
-
PyErr_SetString(
|
|
559
|
-
PyExc_TypeError, "winrt.system.Array is not a type object!");
|
|
560
|
-
return nullptr;
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
if (reinterpret_cast<PyTypeObject*>(array_type.get())->tp_new != Array_tp_new)
|
|
542
|
+
auto state = py::cpp::_winrt::get_module_state();
|
|
543
|
+
if (!state)
|
|
564
544
|
{
|
|
565
|
-
PyErr_SetString(
|
|
566
|
-
PyExc_TypeError, "winrt.system.Array is not the expected type!");
|
|
567
545
|
return nullptr;
|
|
568
546
|
}
|
|
569
547
|
|
|
570
|
-
return
|
|
548
|
+
return state->array_type;
|
|
571
549
|
}
|
|
572
550
|
|
|
573
551
|
} // namespace py::cpp::_winrt
|
|
@@ -16,7 +16,7 @@ classifiers = [
|
|
|
16
16
|
"Intended Audience :: Developers",
|
|
17
17
|
]
|
|
18
18
|
dynamic = ["version"]
|
|
19
|
-
requires-python = ">=3.9,<3.
|
|
19
|
+
requires-python = ">=3.9,<3.14"
|
|
20
20
|
|
|
21
21
|
[project.urls]
|
|
22
22
|
# Homepage = "https://github.com/pywinrt/pywinrt"
|
|
@@ -37,7 +37,8 @@ where = ["src"]
|
|
|
37
37
|
# use local winrt-sdk build dependency
|
|
38
38
|
environment = { PYTHONPATH="../winrt-sdk/src" }
|
|
39
39
|
# don't install winrt-sdk from PyPI
|
|
40
|
-
build-frontend = { name = "build", args = ["--skip-dependency-check", "--no-isolation"] }
|
|
40
|
+
build-frontend = { name = "build[uv]", args = ["--skip-dependency-check", "--no-isolation"] }
|
|
41
|
+
before-build = "uv pip install setuptools"
|
|
41
42
|
# don't build for PyPy
|
|
42
43
|
skip = "pp*"
|
|
43
44
|
# suppress warnings about ARM64 testing
|
|
@@ -45,4 +46,4 @@ test-skip = "*-win_arm64"
|
|
|
45
46
|
|
|
46
47
|
[tool.cibuildwheel.windows]
|
|
47
48
|
archs = ["x86", "AMD64", "ARM64"]
|
|
48
|
-
repair-wheel-command = "python scripts/
|
|
49
|
+
repair-wheel-command = "python scripts/add_msvcp140_dll.py {wheel} {dest_dir}"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.2.0
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
#define PYWINRT_RUNTIME_MODULE
|
|
8
8
|
#include "pybase.h"
|
|
9
|
+
#include "pyruntime.h"
|
|
9
10
|
|
|
10
11
|
// "backport" of Python 3.12 function.
|
|
11
12
|
#if PY_VERSION_HEX < 0x030C0000
|
|
@@ -168,30 +169,93 @@ static PyObject* PyType_FromMetaclass(
|
|
|
168
169
|
* @param base_type The base type, a tuple of base types or nullptr to use the base
|
|
169
170
|
* slot.
|
|
170
171
|
* @param metaclass Optional metaclass for the type.
|
|
171
|
-
* @returns
|
|
172
|
+
* @returns New reference on success or nullptr on error.
|
|
172
173
|
*/
|
|
173
174
|
|
|
174
|
-
|
|
175
|
+
PyTypeObject* py::register_python_type(
|
|
175
176
|
PyObject* module,
|
|
176
177
|
PyType_Spec* type_spec,
|
|
177
178
|
PyObject* base_type,
|
|
178
179
|
PyTypeObject* metaclass) noexcept
|
|
179
180
|
{
|
|
180
|
-
py::
|
|
181
|
-
PyType_FromMetaclass(metaclass, module, type_spec, base_type)};
|
|
181
|
+
py::pytype_handle type_object{reinterpret_cast<PyTypeObject*>(
|
|
182
|
+
PyType_FromMetaclass(metaclass, module, type_spec, base_type))};
|
|
182
183
|
|
|
183
184
|
if (!type_object)
|
|
184
185
|
{
|
|
185
|
-
return
|
|
186
|
+
return nullptr;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (PyModule_AddType(module, type_object.get()) == -1)
|
|
190
|
+
{
|
|
191
|
+
return nullptr;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return type_object.detach();
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
PyTypeObject* py::get_python_type(std::string_view qualified_name) noexcept
|
|
198
|
+
{
|
|
199
|
+
auto state = py::cpp::_winrt::get_module_state();
|
|
200
|
+
if (!state)
|
|
201
|
+
{
|
|
202
|
+
return nullptr;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
auto it = state->type_cache.find(qualified_name);
|
|
206
|
+
if (it != state->type_cache.end())
|
|
207
|
+
{
|
|
208
|
+
return it->second;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
auto pos = qualified_name.find_last_of('.');
|
|
212
|
+
if (pos == std::string_view::npos)
|
|
213
|
+
{
|
|
214
|
+
PyErr_Format(
|
|
215
|
+
PyExc_ValueError, "invalid qualified name: %s", qualified_name.data());
|
|
216
|
+
return nullptr;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
std::string module_name{qualified_name.substr(0, pos)};
|
|
220
|
+
std::string type_name{qualified_name.substr(pos + 1)};
|
|
221
|
+
|
|
222
|
+
pyobj_handle module{PyImport_ImportModule(module_name.c_str())};
|
|
223
|
+
if (!module)
|
|
224
|
+
{
|
|
225
|
+
return nullptr;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
pyobj_handle type{PyObject_GetAttrString(module.get(), type_name.c_str())};
|
|
229
|
+
if (!type)
|
|
230
|
+
{
|
|
231
|
+
return nullptr;
|
|
186
232
|
}
|
|
187
233
|
|
|
188
|
-
if (
|
|
189
|
-
|
|
234
|
+
if (!PyType_Check(type.get()))
|
|
235
|
+
{
|
|
236
|
+
PyErr_Format(
|
|
237
|
+
PyExc_TypeError,
|
|
238
|
+
"'%s.%s' is not a type",
|
|
239
|
+
module_name.c_str(),
|
|
240
|
+
type_name.c_str());
|
|
241
|
+
return nullptr;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// TODO: verify that the Python type is compatible with the winrt
|
|
245
|
+
// runtime module version and that it actually matches the C++ type
|
|
246
|
+
|
|
247
|
+
try
|
|
248
|
+
{
|
|
249
|
+
state->type_cache[qualified_name]
|
|
250
|
+
= reinterpret_cast<PyTypeObject*>(Py_NewRef(type.get()));
|
|
251
|
+
}
|
|
252
|
+
catch (...)
|
|
190
253
|
{
|
|
191
|
-
|
|
254
|
+
to_PyErr();
|
|
255
|
+
return nullptr;
|
|
192
256
|
}
|
|
193
257
|
|
|
194
|
-
return
|
|
258
|
+
return reinterpret_cast<PyTypeObject*>(type.get());
|
|
195
259
|
}
|
|
196
260
|
|
|
197
261
|
/**
|
|
@@ -202,22 +266,14 @@ int py::register_python_type(
|
|
|
202
266
|
*/
|
|
203
267
|
PyObject* py::wrap_mapping_iter(PyObject* iter) noexcept
|
|
204
268
|
{
|
|
205
|
-
py::
|
|
206
|
-
|
|
207
|
-
if (!winrt_module)
|
|
208
|
-
{
|
|
209
|
-
return nullptr;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
py::pyobj_handle mapping_iter_type{
|
|
213
|
-
PyObject_GetAttrString(winrt_module.get(), "MappingIter")};
|
|
214
|
-
|
|
215
|
-
if (!mapping_iter_type)
|
|
269
|
+
auto state = py::cpp::_winrt::get_module_state();
|
|
270
|
+
if (!state)
|
|
216
271
|
{
|
|
217
272
|
return nullptr;
|
|
218
273
|
}
|
|
219
274
|
|
|
220
|
-
py::pyobj_handle wrapper{PyObject_CallOneArg(
|
|
275
|
+
py::pyobj_handle wrapper{PyObject_CallOneArg(
|
|
276
|
+
reinterpret_cast<PyObject*>(state->mapping_iter_type), iter)};
|
|
221
277
|
|
|
222
278
|
if (!wrapper)
|
|
223
279
|
{
|
|
@@ -393,3 +449,62 @@ winrt::Windows::Foundation::DateTime py::convert_to_datetime(PyObject* obj)
|
|
|
393
449
|
|
|
394
450
|
return value;
|
|
395
451
|
}
|
|
452
|
+
|
|
453
|
+
PyObject* py::convert_guid(winrt::guid value) noexcept
|
|
454
|
+
{
|
|
455
|
+
auto state = py::cpp::_winrt::get_module_state();
|
|
456
|
+
if (!state)
|
|
457
|
+
{
|
|
458
|
+
return nullptr;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// It is faster to swap in C++ rather than using bytes_le in Python since
|
|
462
|
+
// Python stores the bytes in a different order.
|
|
463
|
+
alignas(4) char buffer[sizeof(winrt::guid)];
|
|
464
|
+
*reinterpret_cast<uint32_t*>(buffer) = _byteswap_ulong(value.Data1);
|
|
465
|
+
*reinterpret_cast<uint16_t*>(buffer + 4) = _byteswap_ushort(value.Data2);
|
|
466
|
+
*reinterpret_cast<uint16_t*>(buffer + 6) = _byteswap_ushort(value.Data3);
|
|
467
|
+
std::memcpy(buffer + 8, value.Data4, sizeof(value.Data4));
|
|
468
|
+
|
|
469
|
+
pyobj_handle value_as_bytes{PyBytes_FromStringAndSize(buffer, sizeof(buffer))};
|
|
470
|
+
if (!value_as_bytes)
|
|
471
|
+
{
|
|
472
|
+
return nullptr;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
return PyObject_CallOneArg(state->to_uuid_func, value_as_bytes.get());
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
winrt::guid py::convert_to_guid(PyObject* obj)
|
|
479
|
+
{
|
|
480
|
+
throw_if_pyobj_null(obj);
|
|
481
|
+
|
|
482
|
+
pyobj_handle bytes{PyObject_GetAttrString(obj, "bytes")};
|
|
483
|
+
if (!bytes)
|
|
484
|
+
{
|
|
485
|
+
throw python_exception();
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
char* buffer;
|
|
489
|
+
Py_ssize_t size;
|
|
490
|
+
if (PyBytes_AsStringAndSize(bytes.get(), &buffer, &size) == -1)
|
|
491
|
+
{
|
|
492
|
+
throw python_exception();
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
if (size != sizeof(winrt::guid))
|
|
496
|
+
{
|
|
497
|
+
PyErr_SetString(PyExc_ValueError, "bytes is wrong size");
|
|
498
|
+
throw python_exception();
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// It is faster to swap in C++ rather than using bytes_le in Python since
|
|
502
|
+
// Python stores the bytes in a different order.
|
|
503
|
+
winrt::guid result;
|
|
504
|
+
result.Data1 = _byteswap_ulong(*reinterpret_cast<uint32_t*>(buffer));
|
|
505
|
+
result.Data2 = _byteswap_ushort(*reinterpret_cast<uint16_t*>(buffer + 4));
|
|
506
|
+
result.Data3 = _byteswap_ushort(*reinterpret_cast<uint16_t*>(buffer + 6));
|
|
507
|
+
std::memcpy(result.Data4, buffer + 8, sizeof(result.Data4));
|
|
508
|
+
|
|
509
|
+
return result;
|
|
510
|
+
}
|
|
@@ -24,6 +24,8 @@ STA: int
|
|
|
24
24
|
def init_apartment(apartment_type: int) -> None: ...
|
|
25
25
|
def uninit_apartment() -> None: ...
|
|
26
26
|
def initialize_with_window(obj: Object, hwnd: int) -> None: ...
|
|
27
|
+
def _add_dll_directory(path: str) -> int: ...
|
|
28
|
+
def _remove_dll_directory(cookie: int) -> None: ...
|
|
27
29
|
|
|
28
30
|
_Self = TypeVar("_Self")
|
|
29
31
|
_T = TypeVar("_T")
|
|
@@ -1,8 +1,38 @@
|
|
|
1
1
|
from collections.abc import Mapping, MutableMapping, MutableSequence, Sequence
|
|
2
|
+
from pathlib import Path
|
|
2
3
|
from typing import Annotated
|
|
3
4
|
|
|
4
5
|
from .. import _winrt
|
|
5
6
|
|
|
7
|
+
|
|
8
|
+
class _DllCookie:
|
|
9
|
+
def __init__(self, cookie: int) -> None:
|
|
10
|
+
self.cookie = cookie
|
|
11
|
+
|
|
12
|
+
def close(self):
|
|
13
|
+
if self.cookie:
|
|
14
|
+
_winrt._remove_dll_directory(self.cookie)
|
|
15
|
+
self.cookie = None
|
|
16
|
+
|
|
17
|
+
def __del__(self):
|
|
18
|
+
self.close()
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _register_dll_search_path(module_path) -> _DllCookie:
|
|
22
|
+
"""
|
|
23
|
+
Register a module's directory as a DLL search path.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
module_path: The path to a module file (i.e. ``__file__``)
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
An cookie object that will remove the search path when closed.
|
|
30
|
+
"""
|
|
31
|
+
return _DllCookie(
|
|
32
|
+
_winrt._add_dll_directory(str(Path(module_path).parent.resolve()))
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
6
36
|
# NB: The types implemented in C cannot inherit from abc.ABC since Python 3.12
|
|
7
37
|
# so we have to implement the protocols like this instead.
|
|
8
38
|
# https://github.com/python/cpython/issues/103968#issuecomment-1589928055
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: winrt-runtime
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: Python projection of Windows Runtime (WinRT) APIs
|
|
5
5
|
License: MIT
|
|
6
6
|
Project-URL: Documentation, https://pywinrt.readthedocs.io
|
|
@@ -10,7 +10,7 @@ Classifier: Operating System :: Microsoft :: Windows
|
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
11
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
13
|
-
Requires-Python: <3.
|
|
13
|
+
Requires-Python: <3.14,>=3.9
|
|
14
14
|
Description-Content-Type: text/markdown
|
|
15
15
|
|
|
16
16
|
# winrt-runtime
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
2.1.0
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|