Implement SingleKey._replace

This commit is contained in:
Kovid Goyal 2022-08-12 09:40:58 +05:30
parent f228f8368a
commit af48547d8b
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 39 additions and 6 deletions

View File

@ -2,7 +2,7 @@ import termios
from ctypes import Array, c_ubyte
from typing import (
Any, AnyStr, Callable, Dict, List, NewType, Optional, Tuple, TypedDict,
Union
Union, Iterator
)
from kitty.boss import Boss
@ -1470,7 +1470,7 @@ class AES256GCMDecrypt:
class SingleKey:
def __init__(self, mods: int = 0, is_native: bool = False, key: int = -1): ...
def __init__(self, mods: int = 0, is_native: object = False, key: int = -1): ...
def __hash__(self) -> int: ...
def __len__(self) -> int: ...
def __getitem__(self, x: int) -> int: ...
@ -1480,3 +1480,5 @@ class SingleKey:
def is_native(self) -> bool: ...
@property
def key(self) -> int: ...
def __iter__(self) -> Iterator[int]: ...
def _replace(self, mods: int = 0, is_native: object = False, key: int = -1) -> 'SingleKey': ...

View File

@ -304,11 +304,12 @@ typedef struct {
Key key;
} SingleKey;
static PyObject *
SingleKey_new(PyTypeObject *type, PyObject *args, PyObject *kw) {
static char *kwds[] = {"mods", "is_native", "key", NULL};
long key = -1; unsigned short mods = 0; int is_native = 0;
if (!PyArg_ParseTupleAndKeywords(args, kw, "|Hpl", kwds, &mods, &is_native, &key)) return NULL;
static char *SingleKey_kwds[] = {"mods", "is_native", "key", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kw, "|Hpl", SingleKey_kwds, &mods, &is_native, &key)) return NULL;
SingleKey *self = (SingleKey *)type->tp_alloc(type, 0);
if (self) {
if (key > 0 && key <= 0x10FFFF) {
@ -408,6 +409,34 @@ static PySequenceMethods SingleKey_sequence_methods = {
.sq_item = SingleKey_item,
};
static bool
dict_has_key(PyObject *dict, const char *key) {
PyObject *k = PyUnicode_FromString(key);
if (!k) { PyErr_Print(); return false; }
int ret = PyDict_Contains(dict, k);
Py_DECREF(k);
return ret != 0;
}
static PyObject*
SingleKey_replace(SingleKey *self, PyObject *args, PyObject *kw) {
SingleKey *r = (SingleKey*)SingleKey_new(&SingleKey_Type, args, kw);
if (!r) return NULL;
SingleKey *ans = (SingleKey*)SingleKey_Type.tp_alloc(&SingleKey_Type, 0);
if (!ans) { Py_DECREF(r); return NULL; }
ans->key.val = self->key.val;
if (dict_has_key(kw, "mods")) ans->key.mods = r->key.mods;
if (dict_has_key(kw, "is_native")) ans->key.is_native = r->key.is_native;
if (dict_has_key(kw, "key")) ans->key.key = r->key.key;
Py_DECREF(r);
return (PyObject*)ans;
}
static PyMethodDef SingleKey_methods[] = {
{"_replace", (PyCFunction)(void (*) (void))SingleKey_replace, METH_VARARGS | METH_KEYWORDS, ""},
{NULL} /* Sentinel */
};
static PyTypeObject SingleKey_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
@ -421,7 +450,7 @@ static PyTypeObject SingleKey_Type = {
.tp_richcompare = SingleKey_richcompare,
.tp_as_sequence = &SingleKey_sequence_methods,
.tp_repr = SingleKey_repr,
/* .tp_methods = methods, */
.tp_methods = SingleKey_methods,
.tp_getset = SingleKey_getsetters,
}; // }}}

View File

@ -538,9 +538,11 @@ def test_SingleKey(self):
for m in (GLFW_MOD_NUM_LOCK, GLFW_MOD_SHIFT):
s = SingleKey(mods=m)
self.ae(s.mods, m)
self.ae(tuple(SingleKey()), (0, False, -1))
self.ae(tuple(iter(SingleKey())), (0, False, -1))
self.ae(tuple(SingleKey(key=0x10ffff, mods=GLFW_MOD_SHIFT, is_native=True)), (GLFW_MOD_SHIFT, True, 0x10ffff))
self.ae(repr(SingleKey()), 'SingleKey()')
self.ae(repr(SingleKey(key=23, mods=2, is_native=True)), 'SingleKey(mods=2, is_native=True, key=23)')
self.ae(repr(SingleKey(key=23, mods=2)), 'SingleKey(mods=2, key=23)')
self.ae(repr(SingleKey(key=23)), 'SingleKey(key=23)')
self.ae(repr(SingleKey(key=23)._replace(mods=2)), 'SingleKey(mods=2, key=23)')
self.ae(repr(SingleKey(key=23)._replace(key=-1, mods=2)), 'SingleKey(mods=2)')