Lele Gaifax <[email protected]> writes:

> Let me know how you prefer me going forward: I can easily try out your (now
> reverted) change, but it's up to you.

The following patch:

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.
diff --git a/lib/sqlalchemy/cextension/resultproxy.c b/lib/sqlalchemy/cextension/resultproxy.c
index 9c4d0c7..331fae2 100644
--- a/lib/sqlalchemy/cextension/resultproxy.c
+++ b/lib/sqlalchemy/cextension/resultproxy.c
@@ -263,7 +263,9 @@ 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
 
     if (PyLong_CheckExact(key)) {
@@ -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 cc4ac74..fc94168 100644
--- a/lib/sqlalchemy/engine/result.py
+++ b/lib/sqlalchemy/engine/result.py
@@ -35,7 +35,10 @@ except ImportError:
 
 try:
     from sqlalchemy.cresultproxy import BaseRowProxy
+    _baserowproxy_usecext = True
 except ImportError:
+    _baserowproxy_usecext = False
+
     class BaseRowProxy(object):
         __slots__ = ('_parent', '_row', '_processors', '_keymap')
 
@@ -210,11 +213,21 @@ class ResultMetaData(object):
             context, cursor_description, result_columns,
             num_ctx_cols, cols_are_ordered, textual_ordered)
 
-        # keymap indexes by integer index...
-        self._keymap = dict([
-            (elem[0], (elem[3], elem[4], elem[0]))
-            for elem in raw
-        ])
+        if _baserowproxy_usecext:
+            self._keymap = {}
+        else:
+            # keymap indexes by integer index: we add also negative
+            # indexes to handle the row[-x] case in the pure Python
+            # BaseRowProxy.__getitem__ implementation, avoiding an
+            # expensive isinstance(key, util.int_types) in the most
+            # common case path
+            self._keymap = dict([
+                (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
         # views like __iter__ and slices
diff --git a/test/engine/test_execute.py b/test/engine/test_execute.py
index 5ea5d35..aadd170 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
works for me:

    # Python 3
    
    $ py.test test/
    platform linux -- Python 3.5.1+, pytest-2.8.7, py-1.4.31, pluggy-0.3.1 -- 
/home/lele/wip/sqlalchemy/env/bin/python3
    cachedir: .cache
    rootdir: /home/lele/wip/sqlalchemy, inifile: setup.cfg
    collected 7557 items 
    ...
    == 6799 passed, 758 skipped in 131.56 seconds ==

    $ rm lib/sqlalchemy/*.so
    $ py.test test/
    platform linux -- Python 3.5.1+, pytest-2.8.7, py-1.4.31, pluggy-0.3.1 -- 
/home/lele/wip/sqlalchemy/env/bin/python3
    cachedir: .cache
    rootdir: /home/lele/wip/sqlalchemy, inifile: setup.cfg
    collected 7557 items 
    ...
    == 6776 passed, 781 skipped in 128.30 seconds ==

    # Python 2

    $ py.test test/
    platform linux2 -- Python 2.7.11, pytest-2.8.7, py-1.4.31, pluggy-0.3.1 -- 
/home/lele/wip/sqlalchemy/env2/bin/python
    cachedir: .cache
    rootdir: /home/lele/wip/sqlalchemy, inifile: setup.cfg
    collected 7562 items 
    ...
    == 6800 passed, 762 skipped in 140.81 seconds ==
    
    $ rm lib/sqlalchemy/*.so
    $ py.test test/
    platform linux2 -- Python 2.7.11, pytest-2.8.7, py-1.4.31, pluggy-0.3.1 -- 
/home/lele/wip/sqlalchemy/env2/bin/python
    cachedir: .cache
    rootdir: /home/lele/wip/sqlalchemy, inifile: setup.cfg
    collected 7562 items 
    == 6777 passed, 785 skipped in 135.83 seconds ==

So, what exactly failed for you?

ciao, lele.

PS: BTW, nice to see Py3.5 is faster than 2.7.11 ;-)
-- 
nickname: Lele Gaifax | Quando vivrò di quello che ho pensato ieri
real: Emanuele Gaifas | comincerò ad aver paura di chi mi copia.
[email protected]  |                 -- Fortunato Depero, 1929.

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to