Issue1873

classification
Title: Slice deletion from list incorrectly includes range stop when step is -ve
Type: behaviour Severity: normal
Components: Core Versions: 2.5.3b2, 2.5.2, 2.7a1
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: fwierzbicki, jeff.allen
Priority: Keywords: patch

Created on 2012-04-07.22:03:46 by jeff.allen, last changed 2012-08-10.21:20:06 by fwierzbicki.

Files
File name Uploaded Description Edit Remove
issue1873.patch jeff.allen, 2012-04-12.13:52:30 Patch fixing (and testing for) issue 1873
Messages
msg7037 (view) Author: Jeff Allen (jeff.allen) Date: 2012-04-07.22:03:45
When attempting to delete an extended slice with a negative step, Jython executes one too many removals. __getslice__ and __delslice__ are inconsistent in the slice they identify:

>jython
Jython 2.5.2 (Release_2_5_2:7206, Mar 2 2011, 23:12:06)
[Java HotSpot(TM) 64-Bit Server VM (Sun Microsystems Inc.)] on java1.6.0_26
Type "help", "copyright", "credits" or "license" for more information.
>>> a = list(range(0,10))
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a[5:3:-1]
[5, 4]
>>> del a[5:3:-1]
>>> a
[0, 1, 2, 6, 7, 8, 9]
>>> exit()

Just in case I've misunderstood the semantics, I checked CPython:

>c:\Python\26\python
Python 2.6.6 (r266:84297, Aug 24 2010, 18:13:38) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> a = list(range(0,10))
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a[5:3:-1]
[5, 4]
>>> del a[5:3:-1]
>>> a
[0, 1, 2, 3, 6, 7, 8, 9]
>>> exit()

CPython has the behaviour I expected.

Jython manages to get it right if the stop value is not a "candidate" (and step is necessarily bigger than one):

>jython
Jython 2.5.2 (Release_2_5_2:7206, Mar 2 2011, 23:12:06)
[Java HotSpot(TM) 64-Bit Server VM (Sun Microsystems Inc.)] on java1.6.0_26
Type "help", "copyright", "credits" or "license" for more information.
>>> a = list(range(0,10))
>>> a[8:2:-2]
[8, 6, 4]
>>> del a[8:2:-2]
>>> a
[0, 1, 3, 5, 7, 9]
>>> b = list(range(0,10))
>>> b[8:3:-2]
[8, 6, 4]
>>> del b[8:3:-2]
>>> b
[0, 1, 2, 3, 5, 7, 9]
>>> exit()

I noticed this in unit testing another sequence type. The problem is pretty obviously in SequenceIndexDelegate.delSlice(int, int, int).
msg7049 (view) Author: Jeff Allen (jeff.allen) Date: 2012-04-12.13:52:30
Here is a patch that I believe fixes the problem (by deleting one equals sign). The patch also adds a new test case to Lib/test/test_list_jy.py, with two methods modelled on the CPython test for slice assignment and deletion. The CPython test was insufficient to detect our mistake in Jython.

The problem was with deletion, but I've written a corresponding test for assignment too as it was similar.

I've written the tests with the intention they migrate eventually to the CPython code base (in list_tests.py, to supplement CommonTest.test_extendedslicing() ). This worked in a quick test with Python 2.7.2.

With the new test in place, but before the fix to SequenceIndexDelegate, Jython 2.7+ fails the test like this:

>dist\bin\jython Lib\test\test_list_jy.py
test_recursive_list_slices (__main__.ListTestCase) ... ok
test_setget_override (__main__.ListTestCase) ... ok
test_subclass_richcmp (__main__.ListTestCase) ... ok
test_tuple_equality (__main__.ListTestCase) ... ok
test_append_remove (__main__.ThreadSafetyTestCase) ... ok
test_count_reverse (__main__.ThreadSafetyTestCase) ... ok
test_sort (__main__.ThreadSafetyTestCase) ... ok
test_extended_slice_assign (__main__.ExtendedSliceTestCase) ... ok
test_extended_slice_delete (__main__.ExtendedSliceTestCase) ... FAIL

======================================================================
FAIL: test_extended_slice_delete (__main__.ExtendedSliceTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "Lib\test\test_list_jy.py", line 143, in test_extended_slice_delete
    self.assertEqual(a, expected1)
AssertionError: Lists differ: [0, 1, 2, 3, 4, 10, 11, 12, 13... != [0, 1, 2, 3, 4, 5, 10, 11, 12,...

First differing element 5:
10
5

Second list contains 1 additional elements.
First extra element 9:
13

- [0, 1, 2, 3, 4, 10, 11, 12, 13]
+ [0, 1, 2, 3, 4, 5, 10, 11, 12, 13]
?                +++

The offending call was essentially:
        a = list(range(14))
        del a[9:5:-1]
and element 5 was deleted, incorrectly. Python 2.7.2 passes the test. After the change, Jython passes like this:

>dist\bin\jython Lib\test\test_list_jy.py
test_recursive_list_slices (__main__.ListTestCase) ... ok
test_setget_override (__main__.ListTestCase) ... ok
test_subclass_richcmp (__main__.ListTestCase) ... ok
test_tuple_equality (__main__.ListTestCase) ... ok
test_append_remove (__main__.ThreadSafetyTestCase) ... ok
test_count_reverse (__main__.ThreadSafetyTestCase) ... ok
test_sort (__main__.ThreadSafetyTestCase) ... ok
test_extended_slice_assign (__main__.ExtendedSliceTestCase) ... ok
test_extended_slice_delete (__main__.ExtendedSliceTestCase) ... ok

----------------------------------------------------------------------
Ran 9 tests in 0.936s
msg7381 (view) Author: Frank Wierzbicki (fwierzbicki) Date: 2012-08-10.21:20:06
Jeff has pushed this so I think we can close it now.
History
Date User Action Args
2012-08-10 21:20:06fwierzbickisetstatus: open -> closed
resolution: fixed
messages: + msg7381
2012-04-12 13:52:31jeff.allensetfiles: + issue1873.patch
nosy: + fwierzbicki
messages: + msg7049
keywords: + patch
versions: + 2.7a1, 2.5.3b2
2012-04-07 22:03:46jeff.allencreate