Skip to content

Commit 7d34c96

Browse files
committed
Added get() method for TarantoolTuple
1 parent a2ddc24 commit 7d34c96

File tree

3 files changed

+110
-52
lines changed

3 files changed

+110
-52
lines changed

asynctnt/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
Iterator, Response, TarantoolTuple, PushIterator
44
)
55

6-
__version__ = '1.0b1'
6+
__version__ = '1.0b2'

asynctnt/iproto/tupleobj/tupleobj.c

Lines changed: 91 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,52 @@ ttuple_item(AtntTupleObject *o, Py_ssize_t i)
258258
}
259259

260260

261+
static int
262+
ttuple_item_by_name(AtntTupleObject *o, PyObject *item, PyObject **result)
263+
{
264+
if (o->fields == NULL) {
265+
goto noitem;
266+
}
267+
268+
PyObject *mapped;
269+
Py_ssize_t i;
270+
PyObject *value;
271+
272+
mapped = PyObject_GetItem(o->fields->_mapping, item);
273+
if (mapped == NULL) {
274+
goto noitem;
275+
}
276+
277+
if (!PyIndex_Check(mapped)) {
278+
Py_DECREF(mapped);
279+
goto noitem;
280+
}
281+
282+
i = PyNumber_AsSsize_t(mapped, PyExc_IndexError);
283+
Py_DECREF(mapped);
284+
285+
if (i < 0) {
286+
if (PyErr_Occurred()) {
287+
PyErr_Clear();
288+
}
289+
goto noitem;
290+
}
291+
292+
value = ttuple_item(o, i);
293+
if (result == NULL) {
294+
PyErr_Clear();
295+
goto noitem;
296+
}
297+
298+
*result = value;
299+
return 0;
300+
301+
noitem:
302+
PyErr_SetObject(PyExc_KeyError, item);
303+
return -1;
304+
}
305+
306+
261307
static PyObject *
262308
ttuple_subscript(AtntTupleObject* o, PyObject* item)
263309
{
@@ -287,58 +333,29 @@ ttuple_subscript(AtntTupleObject* o, PyObject* item)
287333
if (slicelength <= 0) {
288334
return PyTuple_New(0);
289335
}
290-
else {
291-
result = PyTuple_New(slicelength);
292-
if (!result) return NULL;
293-
294-
src = o->ob_item;
295-
dest = ((PyTupleObject *)result)->ob_item;
296-
for (cur = start, i = 0; i < slicelength; cur += step, i++) {
297-
it = src[cur];
298-
Py_INCREF(it);
299-
dest[i] = it;
300-
}
301-
302-
return result;
303-
}
304-
}
305-
else if (o->fields != NULL) {
306-
PyObject *mapped;
307-
mapped = PyObject_GetItem(o->fields->_mapping, item);
308-
if (mapped != NULL) {
309-
Py_ssize_t i;
310-
PyObject *result;
311-
312-
if (!PyIndex_Check(mapped)) {
313-
Py_DECREF(mapped);
314-
goto noitem;
315-
}
316336

317-
i = PyNumber_AsSsize_t(mapped, PyExc_IndexError);
318-
Py_DECREF(mapped);
337+
result = PyTuple_New(slicelength);
338+
if (!result) return NULL;
319339

320-
if (i < 0) {
321-
if (PyErr_Occurred()) {
322-
PyErr_Clear();
323-
}
324-
goto noitem;
325-
}
326-
327-
result = ttuple_item(o, i);
328-
if (result == NULL) {
329-
PyErr_Clear();
330-
goto noitem;
331-
}
332-
return result;
333-
}
334-
else {
335-
goto noitem;
340+
src = o->ob_item;
341+
dest = ((PyTupleObject *)result)->ob_item;
342+
for (cur = start, i = 0; i < slicelength; cur += step, i++) {
343+
it = src[cur];
344+
Py_INCREF(it);
345+
dest[i] = it;
336346
}
347+
348+
return result;
337349
}
350+
else {
351+
/* map by name */
352+
PyObject *result = NULL;
353+
if (ttuple_item_by_name(o, item, &result) < 0) {
354+
return NULL;
355+
}
338356

339-
noitem:
340-
_PyErr_SetKeyError(item);
341-
return NULL;
357+
return result;
358+
}
342359
}
343360

344361

@@ -511,6 +528,28 @@ ttuple_contains(AtntTupleObject *o, PyObject *arg)
511528
}
512529

513530

531+
static PyObject *
532+
ttuple_get(AtntTupleObject* o, PyObject* args)
533+
{
534+
PyObject *key;
535+
PyObject *defval = Py_None;
536+
PyObject *val = NULL;
537+
int res;
538+
539+
if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &defval))
540+
return NULL;
541+
542+
res = ttuple_item_by_name(o, key, &val);
543+
if (res < 0) {
544+
PyErr_Clear();
545+
Py_INCREF(defval);
546+
val = defval;
547+
}
548+
549+
return val;
550+
}
551+
552+
514553
static PySequenceMethods ttuple_as_sequence = {
515554
(lenfunc)ttuple_length, /* sq_length */
516555
0, /* sq_concat */
@@ -531,10 +570,11 @@ static PyMappingMethods ttuple_as_mapping = {
531570

532571

533572
static PyMethodDef ttuple_methods[] = {
534-
{"values", (PyCFunction)ttuple_values, METH_NOARGS},
535-
{"keys", (PyCFunction)ttuple_keys, METH_NOARGS},
536-
{"items", (PyCFunction)ttuple_items, METH_NOARGS},
537-
{NULL, NULL} /* sentinel */
573+
{"values", (PyCFunction) ttuple_values, METH_NOARGS},
574+
{"keys", (PyCFunction) ttuple_keys, METH_NOARGS},
575+
{"items", (PyCFunction) ttuple_items, METH_NOARGS},
576+
{"get", (PyCFunction) ttuple_get, METH_VARARGS},
577+
{NULL, NULL} /* sentinel */
538578
};
539579

540580

tests/test_response.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,24 @@ async def test__response_tuple_contains(self):
129129
self.assertTrue('f5' in res)
130130
self.assertFalse('f6' in res)
131131

132+
async def test__response_tuple_key_error(self):
133+
data = [0, 'hello', 5, 6, 'help', 'common', 'yo']
134+
res = await self.conn.insert(self.TESTER_SPACE_ID, data)
135+
res = res[0]
136+
137+
with self.assertRaises(KeyError):
138+
_ = res['f100']
139+
140+
async def test__response_tuple_get(self):
141+
data = [0, 'hello', 5, 6, 'help', 'common', 'yo']
142+
res = await self.conn.insert(self.TESTER_SPACE_ID, data)
143+
res = res[0]
144+
145+
self.assertEqual(res.get('f1'), 0)
146+
self.assertEqual(res.get('f2'), 'hello')
147+
self.assertEqual(res.get('f100'), None)
148+
self.assertEqual(res.get('f100', 'zz'), 'zz')
149+
132150
async def test__response_with_no_space_format(self):
133151
res = await self.conn.insert('no_schema_space', [0, 'one'])
134152

0 commit comments

Comments
 (0)