Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multidict views C ext #275

Merged
merged 33 commits into from
Sep 23, 2018
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
61ec3d8
Initial commit multidict_views.
iemelyanov Aug 7, 2018
3a3e1db
Add repr for _ItemsView.
iemelyanov Aug 9, 2018
ba67391
Refactoring.
iemelyanov Aug 13, 2018
f17b398
Multidict base view methods for colling from C extension.
iemelyanov Aug 15, 2018
6a49080
Remove cython _ItemsView.
iemelyanov Aug 15, 2018
4347bb8
Impl all C ItemsView base methods.
iemelyanov Aug 15, 2018
daa949d
Add KeysView repr for calling from C.
iemelyanov Aug 15, 2018
a255550
Add KeysView isdisjoint for calling from C.
iemelyanov Aug 15, 2018
d6b605d
Refactoring names.
iemelyanov Aug 15, 2018
7770cad
Add ItemsView isdisjoint for calling from C.
iemelyanov Aug 15, 2018
445c2dc
Impl call ItemsView isdisjoint from python.
iemelyanov Aug 15, 2018
eda19f0
Add comment.
iemelyanov Aug 15, 2018
216bb40
Rm unused code.
iemelyanov Aug 15, 2018
da79aa1
Rm unused preprocessor.
iemelyanov Aug 15, 2018
3b7bbf8
Fix names.
iemelyanov Aug 15, 2018
1b2f246
Make call impl method faster.
iemelyanov Aug 16, 2018
97e988b
Impl contains for KeysView.
iemelyanov Aug 16, 2018
0a0efb7
Impl repr for KeysView.
iemelyanov Aug 16, 2018
3300af4
Impl isdisjoint for KeysView. Refactoring.
iemelyanov Aug 16, 2018
e206c90
Intergrate C KeysView to cython. Refactoring.
iemelyanov Aug 16, 2018
48f7e25
Add ValuesView repr for calling from C.
iemelyanov Aug 16, 2018
a86946f
Impl repr for ValuesView.
iemelyanov Aug 16, 2018
108e814
Impl contains for ValuesView.
iemelyanov Aug 16, 2018
6eb3baf
Add base methods for ValuesView.
iemelyanov Aug 16, 2018
00d2d27
Intergrate C ValuesView to cython. Refactoring.
iemelyanov Aug 16, 2018
8fa85c0
Fix some mem leak. Add todo comments.
iemelyanov Aug 16, 2018
23f9b4a
Fix c compiler flag.
iemelyanov Aug 16, 2018
f2e101e
Fix style.
iemelyanov Aug 16, 2018
f7a5e67
Make microsoft c89 happy.
iemelyanov Aug 16, 2018
be03d7c
Remove some TODO.
iemelyanov Sep 8, 2018
cbf17b6
Fix PR issues.
iemelyanov Sep 22, 2018
975cc49
Fix PR issues.
iemelyanov Sep 22, 2018
b828f48
Add tp_clear and little refactoring.
iemelyanov Sep 22, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
191 changes: 9 additions & 182 deletions multidict/_multidict.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ from ._abc import MultiMapping, MutableMultiMapping
from ._istr import istr

from ._multidict_iter cimport *
from ._multidict_views cimport *
from ._pair_list cimport *

cdef object _marker = object()
Expand All @@ -18,8 +19,8 @@ upstr = istr # for relaxing backward compatibility problems
cdef object _istr = istr

pair_list_init(istr)
multidict_iter_init()

# multidict_iter_init()
multidict_views_init()

def getversion(_Base md):
return pair_list_version(md._impl)
Expand All @@ -29,6 +30,9 @@ cdef class _Base:

cdef object _impl

def impl(self):
asvetlov marked this conversation as resolved.
Show resolved Hide resolved
return self._impl

def getall(self, key, default=_marker):
"""Return a list of all values matching the key."""
try:
Expand Down Expand Up @@ -78,15 +82,15 @@ cdef class _Base:

cpdef keys(self):
"""Return a new view of the dictionary's keys."""
return _KeysView.__new__(_KeysView, self)
return multidict_keysview_new(self)

def items(self):
"""Return a new view of the dictionary's items *(key, value) pairs)."""
return _ItemsView.__new__(_ItemsView, self)
return multidict_itemsview_new(self)

def values(self):
"""Return a new view of the dictionary's values."""
return _ValuesView.__new__(_ValuesView, self)
return multidict_valuesview_new(self)

def __repr__(self):
lst = []
Expand Down Expand Up @@ -354,182 +358,5 @@ cdef class CIMultiDict(MultiDict):
return ret



MutableMultiMapping.register(CIMultiDict)


cdef class _ViewBase:

cdef _Base _md

def __cinit__(self, _Base md):
self._md = md

def __len__(self):
return pair_list_len(self._md._impl)


cdef class _ViewBaseSet(_ViewBase):

def __richcmp__(self, other, op):
if op == 0: # <
if not isinstance(other, Set):
return NotImplemented
return len(self) < len(other) and self <= other
elif op == 1: # <=
if not isinstance(other, Set):
return NotImplemented
if len(self) > len(other):
return False
for elem in self:
if elem not in other:
return False
return True
elif op == 2: # ==
if not isinstance(other, Set):
return NotImplemented
return len(self) == len(other) and self <= other
elif op == 3: # !=
return not self == other
elif op == 4: # >
if not isinstance(other, Set):
return NotImplemented
return len(self) > len(other) and self >= other
elif op == 5: # >=
if not isinstance(other, Set):
return NotImplemented
if len(self) < len(other):
return False
for elem in other:
if elem not in self:
return False
return True

def __and__(self, other):
if not isinstance(other, Iterable):
return NotImplemented
if isinstance(self, _ViewBaseSet):
self = set(iter(self))
if isinstance(other, _ViewBaseSet):
other = set(iter(other))
if not isinstance(other, Set):
other = set(iter(other))
return self & other

def __or__(self, other):
if not isinstance(other, Iterable):
return NotImplemented
if isinstance(self, _ViewBaseSet):
self = set(iter(self))
if isinstance(other, _ViewBaseSet):
other = set(iter(other))
if not isinstance(other, Set):
other = set(iter(other))
return self | other

def __sub__(self, other):
if not isinstance(other, Iterable):
return NotImplemented
if isinstance(self, _ViewBaseSet):
self = set(iter(self))
if isinstance(other, _ViewBaseSet):
other = set(iter(other))
if not isinstance(other, Set):
other = set(iter(other))
return self - other

def __xor__(self, other):
if not isinstance(other, Iterable):
return NotImplemented
if isinstance(self, _ViewBaseSet):
self = set(iter(self))
if isinstance(other, _ViewBaseSet):
other = set(iter(other))
if not isinstance(other, Set):
other = set(iter(other))
return self ^ other


cdef class _ItemsView(_ViewBaseSet):

def isdisjoint(self, other):
'Return True if two sets have a null intersection.'
for v in other:
if v in self:
return False
return True

def __contains__(self, i):
cdef str key
cdef object value
assert isinstance(i, tuple) or isinstance(i, list)
assert len(i) == 2
key = i[0]
value = i[1]
for k, v in self:
if key == k and value == v:
return True
return False

def __iter__(self):
return multidict_items_iter_new(self._md._impl)

def __repr__(self):
lst = []
for k ,v in self:
lst.append("{!r}: {!r}".format(k, v))
body = ', '.join(lst)
return '{}({})'.format(self.__class__.__name__, body)


abc.ItemsView.register(_ItemsView)


cdef class _ValuesView(_ViewBase):

def __contains__(self, value):
for v in self:
if v == value:
return True
return False

def __iter__(self):
return multidict_values_iter_new(self._md._impl)

def __repr__(self):
lst = []
for v in self:
lst.append("{!r}".format(v))
body = ', '.join(lst)
return '{}({})'.format(self.__class__.__name__, body)


abc.ValuesView.register(_ValuesView)


cdef class _KeysView(_ViewBaseSet):

def isdisjoint(self, other):
'Return True if two sets have a null intersection.'
for k in other:
print('isdisjoint.1', k)
if k in self:
print('isdisjoint.2', k)
return False
return True

def __contains__(self, value):
return self._md._contains(value)

def __iter__(self):
return multidict_keys_iter_new(self._md._impl)

def __repr__(self):
lst = []
for k in self:
lst.append("{!r}".format(k))
body = ', '.join(lst)
return '{}({})'.format(self.__class__.__name__, body)


abc.KeysView.register(_KeysView)
137 changes: 137 additions & 0 deletions multidict/_multidict_base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
from collections import abc
from collections.abc import Set, Iterable


def _abc_itemsview_register(view_cls):
abc.ItemsView.register(view_cls)


def _abc_keysview_register(view_cls):
abc.KeysView.register(view_cls)


def _abc_valuesview_register(view_cls):
abc.ValuesView.register(view_cls)


def _viewbaseset_richcmp(view, other, op):
if op == 0: # <
if not isinstance(other, Set):
return NotImplemented
return len(view) < len(other) and view <= other
elif op == 1: # <=
if not isinstance(other, Set):
return NotImplemented
if len(view) > len(other):
return False
for elem in view:
if elem not in other:
return False
return True
elif op == 2: # ==
if not isinstance(other, Set):
return NotImplemented
return len(view) == len(other) and view <= other
elif op == 3: # !=
return not view == other
elif op == 4: # >
if not isinstance(other, Set):
return NotImplemented
return len(view) > len(other) and view >= other
elif op == 5: # >=
if not isinstance(other, Set):
return NotImplemented
if len(view) < len(other):
return False
for elem in other:
if elem not in view:
return False
return True


def _viewbaseset_and(view, other):
if not isinstance(other, Iterable):
return NotImplemented
if isinstance(view, Set):
view = set(iter(view))
if isinstance(other, Set):
other = set(iter(other))
if not isinstance(other, Set):
other = set(iter(other))
return view & other


def _viewbaseset_or(view, other):
if not isinstance(other, Iterable):
return NotImplemented
if isinstance(view, Set):
view = set(iter(view))
if isinstance(other, Set):
other = set(iter(other))
if not isinstance(other, Set):
other = set(iter(other))
return view | other


def _viewbaseset_sub(view, other):
if not isinstance(other, Iterable):
return NotImplemented
if isinstance(view, Set):
view = set(iter(view))
if isinstance(other, Set):
other = set(iter(other))
if not isinstance(other, Set):
other = set(iter(other))
return view - other


def _viewbaseset_xor(view, other):
if not isinstance(other, Iterable):
return NotImplemented
if isinstance(view, Set):
view = set(iter(view))
if isinstance(other, Set):
other = set(iter(other))
if not isinstance(other, Set):
other = set(iter(other))
return view ^ other


def _itemsview_isdisjoint(view, other):
'Return True if two sets have a null intersection.'
for v in other:
if v in view:
return False
return True


def _itemsview_repr(view):
lst = []
for k, v in view:
lst.append("{!r}: {!r}".format(k, v))
body = ', '.join(lst)
return '{}({})'.format(view.__class__.__name__, body)


def _keysview_isdisjoint(view, other):
'Return True if two sets have a null intersection.'
for k in other:
if k in view:
return False
return True


def _keysview_repr(view):
lst = []
for k in view:
lst.append("{!r}".format(k))
body = ', '.join(lst)
return '{}({})'.format(view.__class__.__name__, body)


def _valuesview_repr(view):
lst = []
for v in view:
lst.append("{!r}".format(v))
body = ', '.join(lst)
return '{}({})'.format(view.__class__.__name__, body)
Loading