diff options
author | Lele Gaifax <lele@metapensiero.it> | 2016-01-28 09:04:40 +0100 |
---|---|---|
committer | Lele Gaifax <lele@metapensiero.it> | 2016-01-28 09:04:40 +0100 |
commit | f84ef1f83cc64a5ea3a910b8d1bdf00b05e9ceab (patch) | |
tree | 88ea72eea39fd076dc730a304a9ec9823dfb6aa3 | |
parent | 086ad9ce6413e73f93506523d4eb8e23710443dc (diff) | |
download | sqlalchemy-f84ef1f83cc64a5ea3a910b8d1bdf00b05e9ceab.tar.gz |
- properly handle negative indexes in RowProxy.__getitem__()pr/231
-rw-r--r-- | lib/sqlalchemy/cextension/resultproxy.c | 4 | ||||
-rw-r--r-- | lib/sqlalchemy/engine/result.py | 9 | ||||
-rw-r--r-- | test/engine/test_execute.py | 19 |
3 files changed, 31 insertions, 1 deletions
diff --git a/lib/sqlalchemy/cextension/resultproxy.c b/lib/sqlalchemy/cextension/resultproxy.c index a87fe7b56..331fae2b2 100644 --- a/lib/sqlalchemy/cextension/resultproxy.c +++ b/lib/sqlalchemy/cextension/resultproxy.c @@ -263,6 +263,8 @@ BaseRowProxy_subscript(BaseRowProxy *self, PyObject *key) #if PY_MAJOR_VERSION < 3 if (PyInt_CheckExact(key)) { index = PyInt_AS_LONG(key); + if (index < 0) + index += BaseRowProxy_length(self); } else #endif @@ -271,6 +273,8 @@ BaseRowProxy_subscript(BaseRowProxy *self, PyObject *key) if ((index == -1) && PyErr_Occurred()) /* -1 can be either the actual value, or an error flag. */ return NULL; + if (index < 0) + index += BaseRowProxy_length(self); } else if (PySlice_Check(key)) { values = PyObject_GetItem(self->row, key); if (values == NULL) diff --git a/lib/sqlalchemy/engine/result.py b/lib/sqlalchemy/engine/result.py index 39f4fc50c..9208686e1 100644 --- a/lib/sqlalchemy/engine/result.py +++ b/lib/sqlalchemy/engine/result.py @@ -215,10 +215,17 @@ class ResultMetaData(object): self._keymap = {} if not _baserowproxy_usecext: - # keymap indexes by integer index... + # keymap indexes by integer index: this is only used + # in the pure Python BaseRowProxy.__getitem__ + # implementation to avoid an expensive + # isinstance(key, util.int_types) in the most common + # case path self._keymap.update([ (elem[0], (elem[3], elem[4], elem[0])) for elem in raw + ] + [ + (elem[0] - num_ctx_cols, (elem[3], elem[4], elem[0])) + for elem in raw ]) # processors in key order for certain per-row diff --git a/test/engine/test_execute.py b/test/engine/test_execute.py index 5ea5d3515..aadd170f3 100644 --- a/test/engine/test_execute.py +++ b/test/engine/test_execute.py @@ -951,6 +951,25 @@ class ResultProxyTest(fixtures.TestBase): {'key': (None, None, 0), 0: (None, None, 0)}) assert isinstance(row, collections.Sequence) + def test_rowproxy_getitem(self): + metadata = MetaData() + metadata.bind = 'sqlite://' + values = Table('users', metadata, + Column('key', String(10), primary_key=True), + Column('value', String(10))) + values.create() + + values.insert().execute(key='One', value='Uno') + row = values.select().execute().fetchone() + + assert row['key'] == 'One' + assert row['value'] == 'Uno' + assert row[0] == 'One' + assert row[1] == 'Uno' + assert row[-2] == 'One' + assert row[-1] == 'Uno' + assert row[1:0:-1] == ('Uno',) + @testing.requires.cextensions def test_row_c_sequence_check(self): import csv |