Skip to content

Commit c2a3f14

Browse files
committed
add with-default-value overload to __getitem__()
1 parent 71ff7a1 commit c2a3f14

File tree

5 files changed

+57
-3
lines changed

5 files changed

+57
-3
lines changed

doc/api/types_linq.enumerable.rst

+24
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,30 @@ Example
8686
8787
----
8888

89+
instancemethod ``__getitem__[TDefault](__index_and_default)``
90+
---------------------------------------------------------------
91+
92+
Parameters
93+
- `__index_and_default` (``Tuple[int, TDefault]``)
94+
95+
Returns
96+
- ``Union[TSource_co, TDefault]``
97+
98+
Returns the element at specified index in the sequence or returns the default value if it does not
99+
exist. Prefers calling `__getitem__()` on the wrapped iterable if available, otherwise, calls
100+
`self.element_at()`.
101+
102+
Example
103+
.. code-block:: python
104+
105+
>>> def gen():
106+
... yield 1; yield 10; yield 100
107+
108+
>>> Enumerable(gen())[3, 1000]
109+
1000
110+
111+
----
112+
89113
instancemethod ``__getitem__(index)``
90114
---------------------------------------
91115

doc/to-start/differences.rst

+2
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,5 @@ Limitations:
4343
* To deal with overloads, some method parameters are positional-only, e.g. those starting with double
4444
underscores. Some of them can be improved.
4545
* ``OrderedEnumerable`` exposing unnecessary type parameter ``TKey``.
46+
* ``Lookup.__getitem__()``, ``Lookup.contains()``, ``Lookup.count`` are incompatible with the superclass methods they
47+
are overriding.

tests/test_usage.py

+4
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,10 @@ def test_fallback(self):
370370
with pytest.raises(IndexOutOfRangeError):
371371
en3[1]
372372

373+
def test_not_fallback_and_with_default(self):
374+
en = Enumerable([])
375+
assert en[1, 'haha'] == 'haha'
376+
373377

374378
class OnlyHasGetItem(BasicIterable[TSource_co], Sequence[TSource_co]):
375379
# note: we get into troubles if Sequence is the first superclass

types_linq/enumerable.py

+10-3
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,16 @@ def inner(s: slice = index):
126126
return Enumerable(inner)
127127

128128
def __getitem__(self, # type: ignore[override]
129-
index: Union[int, slice],
130-
) -> Union[TSource_co, Enumerable[TSource_co]]:
131-
return self._getitem_impl(index, fallback=False)
129+
index: Union[int, slice, Tuple[int, TDefault]],
130+
) -> Union[TSource_co, Enumerable[TSource_co], TDefault]:
131+
if isinstance(index, tuple):
132+
idx, default = index
133+
try:
134+
return self._getitem_impl(idx, fallback=False)
135+
except IndexOutOfRangeError:
136+
return default
137+
else: # isinstance(index, (int, slice))
138+
return self._getitem_impl(index, fallback=False)
132139

133140
def __iter__(self) -> Iterator[TSource_co]:
134141
return iter(self._get_iterable())

types_linq/enumerable.pyi

+17
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,23 @@ class Enumerable(Sequence[TSource_co], Generic[TSource_co]):
7575
10
7676
'''
7777

78+
@overload
79+
def __getitem__(self, __index_and_default: Tuple[int, TDefault]) -> Union[TSource_co, TDefault]:
80+
'''
81+
Returns the element at specified index in the sequence or returns the default value if it does not
82+
exist. Prefers calling `__getitem__()` on the wrapped iterable if available, otherwise, calls
83+
`self.element_at()`.
84+
85+
Example
86+
.. code-block:: python
87+
88+
>>> def gen():
89+
... yield 1; yield 10; yield 100
90+
91+
>>> Enumerable(gen())[3, 1000]
92+
1000
93+
'''
94+
7895
@overload
7996
def __getitem__(self, index: slice) -> Enumerable[TSource_co]:
8097
'''

0 commit comments

Comments
 (0)