You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
107 lines
2.6 KiB
107 lines
2.6 KiB
# TODO: this is mostly just copied over from the python implementation
|
|
# more improvements are likely possible
|
|
import operator
|
|
|
|
cdef int MD_INDEX = 0 # integer index in cursor.description
|
|
cdef int _KEY_OBJECTS_ONLY = 1
|
|
|
|
KEY_INTEGER_ONLY = 0
|
|
KEY_OBJECTS_ONLY = _KEY_OBJECTS_ONLY
|
|
|
|
cdef class BaseRow:
|
|
cdef readonly object _parent
|
|
cdef readonly tuple _data
|
|
cdef readonly dict _keymap
|
|
cdef readonly int _key_style
|
|
|
|
def __init__(self, object parent, object processors, dict keymap, int key_style, object data):
|
|
"""Row objects are constructed by CursorResult objects."""
|
|
|
|
self._parent = parent
|
|
|
|
if processors:
|
|
self._data = tuple(
|
|
[
|
|
proc(value) if proc else value
|
|
for proc, value in zip(processors, data)
|
|
]
|
|
)
|
|
else:
|
|
self._data = tuple(data)
|
|
|
|
self._keymap = keymap
|
|
|
|
self._key_style = key_style
|
|
|
|
def __reduce__(self):
|
|
return (
|
|
rowproxy_reconstructor,
|
|
(self.__class__, self.__getstate__()),
|
|
)
|
|
|
|
def __getstate__(self):
|
|
return {
|
|
"_parent": self._parent,
|
|
"_data": self._data,
|
|
"_key_style": self._key_style,
|
|
}
|
|
|
|
def __setstate__(self, dict state):
|
|
self._parent = state["_parent"]
|
|
self._data = state["_data"]
|
|
self._keymap = self._parent._keymap
|
|
self._key_style = state["_key_style"]
|
|
|
|
def _values_impl(self):
|
|
return list(self)
|
|
|
|
def __iter__(self):
|
|
return iter(self._data)
|
|
|
|
def __len__(self):
|
|
return len(self._data)
|
|
|
|
def __hash__(self):
|
|
return hash(self._data)
|
|
|
|
def __getitem__(self, index):
|
|
return self._data[index]
|
|
|
|
cpdef _get_by_key_impl_mapping(self, key):
|
|
try:
|
|
rec = self._keymap[key]
|
|
except KeyError as ke:
|
|
rec = self._parent._key_fallback(key, ke)
|
|
|
|
mdindex = rec[MD_INDEX]
|
|
if mdindex is None:
|
|
self._parent._raise_for_ambiguous_column_name(rec)
|
|
elif (
|
|
self._key_style == _KEY_OBJECTS_ONLY
|
|
and isinstance(key, int)
|
|
):
|
|
raise KeyError(key)
|
|
|
|
return self._data[mdindex]
|
|
|
|
def __getattr__(self, name):
|
|
try:
|
|
return self._get_by_key_impl_mapping(name)
|
|
except KeyError as e:
|
|
raise AttributeError(e.args[0]) from e
|
|
|
|
|
|
def rowproxy_reconstructor(cls, state):
|
|
obj = cls.__new__(cls)
|
|
obj.__setstate__(state)
|
|
return obj
|
|
|
|
|
|
def tuplegetter(*indexes):
|
|
it = operator.itemgetter(*indexes)
|
|
|
|
if len(indexes) > 1:
|
|
return it
|
|
else:
|
|
return lambda row: (it(row),)
|