Skip to content

Commit f994145

Browse files
committed
Fixed the incorrect behavior of the * and *= operators
Details: * Fixed the incorrect behavior of the `*` and `*=` operators to now validate that the number is an integer and raise TypeError otherwise, consistent with the built-in list class. (See issue #27) * The `*=` operator now modifies the left hand operand list in place, instead of returning a new list. Note that both is correct behavior. (Part of issue #27) Signed-off-by: Andreas Maier <andreas.r.maier@gmx.de>
1 parent 108e855 commit f994145

File tree

3 files changed

+74
-10
lines changed

3 files changed

+74
-10
lines changed

docs/changes.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ Released: not yet
2121
(incorrectly) as a single item. For '+', the right hand operand now must
2222
be a list, consistent with the built-in list class. (See issue #25)
2323

24+
* Fixed the incorrect behavior of the `*` and `*=` operators to now validate
25+
that the number is an integer and raise TypeError otherwise, consistent with
26+
the built-in list class. (See issue #27)
27+
2428
**Enhancements:**
2529

2630
* Test: Coveralls now runs on all python versions, merging the result.
@@ -46,9 +50,14 @@ Released: not yet
4650
list class as of Python 3.8, including all methods that have been added since
4751
Python 2.7, on all Python versions.
4852

53+
<<<<<<< HEAD
4954
* Improved the performance of initializing a NocaseList object by copying
5055
the internal lower-cased list when possible, instead of rebuilding it from
5156
the original list.
57+
=======
58+
* The `*=` operator now modifies the left hand operand list in place, instead of
59+
returning a new list. Note that both is correct behavior. (Part of issue #27)
60+
>>>>>>> 76dc790... Fixed the incorrect behavior of the `*` and `*=` operators
5261

5362
**Cleanup:**
5463

nocaselist/_nocaselist.py

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,16 @@
44

55
from __future__ import print_function, absolute_import
66

7+
import sys
8+
79
__all__ = ['NocaseList']
810

11+
if sys.version_info[0] == 2:
12+
# pylint: disable=undefined-variable
13+
_INTEGER_TYPES = (long, int) # noqa: F821
14+
else:
15+
_INTEGER_TYPES = (int,)
16+
917

1018
def _lc_list(lst):
1119
"""
@@ -154,22 +162,34 @@ def __iadd__(self, other):
154162

155163
def __mul__(self, number):
156164
"""
157-
Return a shallow copy of the list, that has the items from the original
158-
list as many times as specified by number (including 0). The original
159-
list is not changed.
165+
Return a new :class:`NocaseList` object that contains the items from
166+
the left hand operand (``self``) as many times as specified by the right
167+
hand operand (``number``).
168+
169+
A number <= 0 causes the returned list to be empty.
170+
171+
The left hand operand (``self``) is not changed.
160172
161173
Invoked using ``ncl * number``.
162174
"""
175+
if not isinstance(number, _INTEGER_TYPES):
176+
raise TypeError(
177+
"Cannot multiply NocaseList by non-integer of type {t}".
178+
format(t=type(number)))
163179
lst = NocaseList()
164180
for _ in range(0, number):
165181
lst.extend(self)
166182
return lst
167183

168184
def __rmul__(self, number):
169185
"""
170-
Return a shallow copy of the list, that has the items from the original
171-
list as many times as specified by number (including 0). The original
172-
list is not changed.
186+
Return a new :class:`NocaseList` object that contains the items from
187+
the right hand operand (``self``) as many times as specified by the left
188+
hand operand (``number``).
189+
190+
A number <= 0 causes the returned list to be empty.
191+
192+
The right hand operand (``self``) is not changed.
173193
174194
Invoked using ``number * ncl``.
175195
"""
@@ -178,15 +198,28 @@ def __rmul__(self, number):
178198

179199
def __imul__(self, number):
180200
"""
181-
Replace the original list by a list that has the items from the original
182-
list as many times as specified by number (including 0).
201+
Change the left hand operand (``self``) so that it contains the items
202+
from the original left hand operand (``self``) as many times as
203+
specified by the right hand operand (``number``).
204+
205+
A number <= 0 will empty the left hand operand.
183206
184207
Invoked using ``ncl *= number``.
185208
"""
186209
# Note: It is unusual that the method has to return self, but it was
187210
# verified that this is necessary.
188-
lst = self * number # Delegates to __mul__()
189-
return lst
211+
if not isinstance(number, _INTEGER_TYPES):
212+
raise TypeError(
213+
"Cannot multiply NocaseList by non-integer of type {t}".
214+
format(t=type(number)))
215+
if number <= 0:
216+
del self[:]
217+
del self._lc_list[:]
218+
else:
219+
self_items = list(self)
220+
for _ in range(0, number - 1):
221+
self.extend(self_items)
222+
return self
190223

191224
def __reversed__(self):
192225
"""

tests/unittest/test_nocaselist.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,24 @@ def test_NocaseList_iadd(testcase, nclist, other, exp_result):
11811181
),
11821182
None, None, True
11831183
),
1184+
(
1185+
"Empty list times -0.5 (must be integer)",
1186+
dict(
1187+
nclist=NocaseList(),
1188+
number=-0.5,
1189+
exp_result=NocaseList(),
1190+
),
1191+
TypeError, None, True
1192+
),
1193+
(
1194+
"Empty list times +0.5 (must be integer)",
1195+
dict(
1196+
nclist=NocaseList(),
1197+
number=+0.5,
1198+
exp_result=NocaseList(),
1199+
),
1200+
TypeError, None, True
1201+
),
11841202
(
11851203
"List with two items times -1",
11861204
dict(
@@ -1279,6 +1297,7 @@ def test_NocaseList_imul(testcase, nclist, number, exp_result):
12791297

12801298
# Don't change the testcase data, but a copy
12811299
nclist_copy = NocaseList(nclist)
1300+
nclist_copy_id = id(nclist_copy)
12821301

12831302
# The code to be tested
12841303
nclist_copy *= number
@@ -1287,6 +1306,9 @@ def test_NocaseList_imul(testcase, nclist, number, exp_result):
12871306
# are not mistaken as expected exceptions
12881307
assert testcase.exp_exc_types is None
12891308

1309+
# Verify the object has been changed in place
1310+
assert id(nclist_copy) == nclist_copy_id
1311+
12901312
assert_equal(nclist_copy, exp_result)
12911313

12921314

0 commit comments

Comments
 (0)