Repository: numba/numba

Issue:
Error deleting list elements after printing
From stackoverflow:
http://stackoverflow.com/questions/37030082/notimplementederror-while-trying-to-run-with-numba-python

If you attempt to print a full list, you get a NotImplementedError for the `del`:

``` python
import numba as nb

@nb.jit
def my_function():

    my_list = []

    my_list.append(4)
    my_list.append(1)
    my_list.append(6)
    my_list.append(7)
    my_list.append(2)

    print(my_list)    
    del my_list[:]
    return my_list

my_list = my_function()
```

Traceback:

```
---------------------------------------------------------------------------
LoweringError                             Traceback (most recent call last)
<ipython-input-3-2bd055618797> in <module>()
     16     return my_list
     17 
---> 18 my_list = my_function()

/Users/zzz/anaconda/lib/python2.7/site-packages/numba/dispatcher.pyc in _compile_for_args(self, *args, **kws)
    286             else:
    287                 real_args.append(self.typeof_pyval(a))
--> 288         return self.compile(tuple(real_args))
    289 
    290     def inspect_llvm(self, signature=None):

/Users/zzz/anaconda/lib/python2.7/site-packages/numba/dispatcher.pyc in compile(self, sig)
    504 
    505             self._cache_misses[sig] += 1
--> 506             cres = self._compiler.compile(args, return_type)
    507             self.add_overload(cres)
    508             self._cache.save_overload(sig, cres)

/Users/zzz/anaconda/lib/python2.7/site-packages/numba/dispatcher.pyc in compile(self, args, return_type)
     83                                       impl,
     84                                       args=args, return_type=return_type,
---> 85                                       flags=flags, locals=self.locals)
     86         # Check typing error if object mode is used
     87         if cres.typing_error is not None and not flags.enable_pyobject:

/Users/zzz/anaconda/lib/python2.7/site-packages/numba/compiler.pyc in compile_extra(typingctx, targetctx, func, args, return_type, flags, locals, library)
    688     pipeline = Pipeline(typingctx, targetctx, library,
    689                         args, return_type, flags, locals)
--> 690     return pipeline.compile_extra(func)
    691 
    692 

/Users/zzz/anaconda/lib/python2.7/site-packages/numba/compiler.pyc in compile_extra(self, func)
    376                 raise e
    377 
--> 378         return self.compile_bytecode(bc, func_attr=self.func_attr)
    379 
    380     def compile_bytecode(self, bc, lifted=(), lifted_from=None,

/Users/zzz/anaconda/lib/python2.7/site-packages/numba/compiler.pyc in compile_bytecode(self, bc, lifted, lifted_from, func_attr)
    385         self.lifted_from = lifted_from
    386         self.func_attr = func_attr
--> 387         return self._compile_bytecode()
    388 
    389     def compile_internal(self, bc, func_attr=DEFAULT_FUNCTION_ATTRIBUTES):

/Users/zzz/anaconda/lib/python2.7/site-packages/numba/compiler.pyc in _compile_bytecode(self)
    669 
    670         pm.finalize()
--> 671         res = pm.run(self.status)
    672         if res is not None:
    673             # Early pipeline completion

/Users/zzz/anaconda/lib/python2.7/site-packages/numba/compiler.pyc in run(self, status)
    255                     # No more fallback pipelines?
    256                     if is_final_pipeline:
--> 257                         raise patched_exception
    258                     # Go to next fallback pipeline
    259                     else:

LoweringError: Caused By:
Traceback (most recent call last):
  File "/Users/zzz/anaconda/lib/python2.7/site-packages/numba/compiler.py", line 249, in run
    stage()
  File "/Users/zzz/anaconda/lib/python2.7/site-packages/numba/compiler.py", line 594, in stage_objectmode_backend
    self._backend(lowerfn, objectmode=True)
  File "/Users/zzz/anaconda/lib/python2.7/site-packages/numba/compiler.py", line 571, in _backend
    lowered = lowerfn()
  File "/Users/zzz/anaconda/lib/python2.7/site-packages/numba/compiler.py", line 545, in backend_object_mode
    self.flags)
  File "/Users/zzz/anaconda/lib/python2.7/site-packages/numba/compiler.py", line 840, in py_lowering_stage
    lower.lower()
  File "/Users/zzz/anaconda/lib/python2.7/site-packages/numba/lowering.py", line 123, in lower
    self.lower_normal_function(self.fndesc)
  File "/Users/zzz/anaconda/lib/python2.7/site-packages/numba/lowering.py", line 158, in lower_normal_function
    entry_block_tail = self.lower_function_body()
  File "/Users/zzz/anaconda/lib/python2.7/site-packages/numba/lowering.py", line 183, in lower_function_body
    self.lower_block(block)
  File "/Users/zzz/anaconda/lib/python2.7/site-packages/numba/lowering.py", line 201, in lower_block
    raise LoweringError(msg, inst.loc)
LoweringError: Internal error:
NotImplementedError: (<class 'numba.ir.DelItem'>, del my_list[$0.29])
File "<ipython-input-3-2bd055618797>", line 15

Failed at object (object mode backend)
Internal error:
NotImplementedError: (<class 'numba.ir.DelItem'>, del my_list[$0.29])
File "<ipython-input-3-2bd055618797>", line 15
```

If you only print a single element of `my_list`, the function works as expected.



Discussion:

Resolving patch:
diff --git a/numba/objmode.py b/numba/objmode.py
--- a/numba/objmode.py
+++ b/numba/objmode.py
@@ -72,6 +72,12 @@ def lower_inst(self, inst):
             ok = self.pyapi.object_setitem(target, index, value)
             self.check_int_status(ok)
 
+        elif isinstance(inst, ir.DelItem):
+            target = self.loadvar(inst.target.name)
+            index = self.loadvar(inst.index.name)
+            ok = self.pyapi.object_delitem(target, index)
+            self.check_int_status(ok)
+
         elif isinstance(inst, ir.SetAttr):
             target = self.loadvar(inst.target.name)
             value = self.loadvar(inst.value.name)
diff --git a/numba/pythonapi.py b/numba/pythonapi.py
--- a/numba/pythonapi.py
+++ b/numba/pythonapi.py
@@ -1061,15 +1061,29 @@ def object_delattr(self, obj, attr):
         return self.object_setattr(obj, attr, self.get_null_object())
 
     def object_getitem(self, obj, key):
+        """
+        Return obj[key]
+        """
         fnty = Type.function(self.pyobj, [self.pyobj, self.pyobj])
         fn = self._get_function(fnty, name="PyObject_GetItem")
         return self.builder.call(fn, (obj, key))
 
     def object_setitem(self, obj, key, val):
+        """
+        obj[key] = val
+        """
         fnty = Type.function(Type.int(), [self.pyobj, self.pyobj, self.pyobj])
         fn = self._get_function(fnty, name="PyObject_SetItem")
         return self.builder.call(fn, (obj, key, val))
 
+    def object_delitem(self, obj, key):
+        """
+        del obj[key]
+        """
+        fnty = Type.function(Type.int(), [self.pyobj, self.pyobj])
+        fn = self._get_function(fnty, name="PyObject_DelItem")
+        return self.builder.call(fn, (obj, key))
+
     def string_as_string(self, strobj):
         fnty = Type.function(self.cstring, [self.pyobj])
         if PYVERSION >= (3, 0):


Test patch:
diff --git a/numba/tests/test_object_mode.py b/numba/tests/test_object_mode.py
--- a/numba/tests/test_object_mode.py
+++ b/numba/tests/test_object_mode.py
@@ -19,6 +19,9 @@ def complex_constant(n):
 def long_constant(n):
     return n + 100000000000000000000000000000000000000000000000
 
+def delitem_usecase(x):
+    del x[:]
+
 
 forceobj = Flags()
 forceobj.set("force_pyobject")
@@ -93,6 +96,17 @@ def foo(x, y):
 
         self.assertIn("is not iterable", str(raises.exception))
 
+    def test_delitem(self):
+        pyfunc = delitem_usecase
+        cres = compile_isolated(pyfunc, (), flags=forceobj)
+        cfunc = cres.entry_point
+
+        l = [3, 4, 5]
+        cfunc(l)
+        self.assertPreciseEqual(l, [])
+        with self.assertRaises(TypeError):
+            cfunc(42)
+
 
 if __name__ == '__main__':
     unittest.main()