resultproxy.pyx 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. # cyextension/resultproxy.pyx
  2. # Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
  3. # <see AUTHORS file>
  4. #
  5. # This module is part of SQLAlchemy and is released under
  6. # the MIT License: https://www.opensource.org/licenses/mit-license.php
  7. import operator
  8. cdef class BaseRow:
  9. cdef readonly object _parent
  10. cdef readonly dict _key_to_index
  11. cdef readonly tuple _data
  12. def __init__(self, object parent, object processors, dict key_to_index, object data):
  13. """Row objects are constructed by CursorResult objects."""
  14. self._parent = parent
  15. self._key_to_index = key_to_index
  16. if processors:
  17. self._data = _apply_processors(processors, data)
  18. else:
  19. self._data = tuple(data)
  20. def __reduce__(self):
  21. return (
  22. rowproxy_reconstructor,
  23. (self.__class__, self.__getstate__()),
  24. )
  25. def __getstate__(self):
  26. return {"_parent": self._parent, "_data": self._data}
  27. def __setstate__(self, dict state):
  28. parent = state["_parent"]
  29. self._parent = parent
  30. self._data = state["_data"]
  31. self._key_to_index = parent._key_to_index
  32. def _values_impl(self):
  33. return list(self)
  34. def __iter__(self):
  35. return iter(self._data)
  36. def __len__(self):
  37. return len(self._data)
  38. def __hash__(self):
  39. return hash(self._data)
  40. def __getitem__(self, index):
  41. return self._data[index]
  42. def _get_by_key_impl_mapping(self, key):
  43. return self._get_by_key_impl(key, 0)
  44. cdef _get_by_key_impl(self, object key, int attr_err):
  45. index = self._key_to_index.get(key)
  46. if index is not None:
  47. return self._data[<int>index]
  48. self._parent._key_not_found(key, attr_err != 0)
  49. def __getattr__(self, name):
  50. return self._get_by_key_impl(name, 1)
  51. def _to_tuple_instance(self):
  52. return self._data
  53. cdef tuple _apply_processors(proc, data):
  54. res = []
  55. for i in range(len(proc)):
  56. p = proc[i]
  57. if p is None:
  58. res.append(data[i])
  59. else:
  60. res.append(p(data[i]))
  61. return tuple(res)
  62. def rowproxy_reconstructor(cls, state):
  63. obj = cls.__new__(cls)
  64. obj.__setstate__(state)
  65. return obj
  66. cdef int is_contiguous(tuple indexes):
  67. cdef int i
  68. for i in range(1, len(indexes)):
  69. if indexes[i-1] != indexes[i] -1:
  70. return 0
  71. return 1
  72. def tuplegetter(*indexes):
  73. if len(indexes) == 1 or is_contiguous(indexes) != 0:
  74. # slice form is faster but returns a list if input is list
  75. return operator.itemgetter(slice(indexes[0], indexes[-1] + 1))
  76. else:
  77. return operator.itemgetter(*indexes)