Repository: pyccel/pyccel (python)

Issue:
pop: removes and returns the last value from the list or the given index value.
### Feature Description
Add support for pop() method for lists in the Python translation.

### Test Code
This code should work when this issue is fixed:
```python
>> a = [1, 3]
>> b = a.pop(3)
>> print(b)
>> 3
```

### Proposed Solution
See description in https://github.com/pyccel/pyccel/issues/1529

Pull request:
List support: pop method
Add support for the pop() method of Python lists to the semantic stage. Add handling of that method to the Python printer. This fixes #1690.

Patch:
diff --git a/AUTHORS b/AUTHORS
index 52548d7c..8416d060 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -29,3 +29,4 @@ Contributors
 * Mudit Loya
 * Priyabrata Mondal
 * Farouk Ech-Charef
+* Mustapha Belbiad
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 202f5f8e..624d360a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file.
 ### Added
 
 -   #1529 : Add Python support for list method `append()`
+-   #1690 : Add support for `pop()` method of list class
 -   #1575 : Add support for homogeneous tuple type annotations on variables.
 
 ### Fixed
diff --git a/pyccel/ast/builtin_methods/list_methods.py b/pyccel/ast/builtin_methods/list_methods.py
index d9e3451d..859f7dc5 100644
--- a/pyccel/ast/builtin_methods/list_methods.py
+++ b/pyccel/ast/builtin_methods/list_methods.py
@@ -14,7 +14,7 @@ from pyccel.ast.datatypes import NativeVoid, NativeGeneric, NativeHomogeneousLis
 from pyccel.ast.internals import PyccelInternalFunction
 
 
-__all__ = ('ListAppend',)
+__all__ = ('ListAppend','ListPop')
 
 
 class ListAppend(PyccelInternalFunction):
@@ -79,3 +79,54 @@ class ListAppend(PyccelInternalFunction):
         Get the argument which is passed to append().
         """
         return self._append_arg
+
+#==============================================================================
+class ListPop(PyccelInternalFunction) :
+    """
+    Represents a call to the .pop() method.
+    
+    Represents a call to the .pop() method which
+    removes the item at the specified index. 
+    The method also returns the removed item.
+
+    Parameters
+    ----------
+    list_variable : TypedAstNode
+        The name of the list.
+
+    index_element : TypedAstNode
+        The current index value for the element to be popped.
+    """
+    __slots__ = ('_dtype','_precision', '_index','_list_variable')
+    _attribute_nodes = ('_index','_list_variable')
+    _rank = 0
+    _order = None
+    _shape = None
+    _class_type = NativeHomogeneousList()
+    name = 'pop'
+
+    def __init__(self, list_variable, index_element=None):
+        self._index = index_element
+        self._list_variable = list_variable
+        self._dtype = list_variable.dtype
+        self._precision = list_variable.precision
+        super().__init__()
+
+    @property
+    def pop_index(self):
+        """
+        The current index value for the element to be popped.
+
+        The current index value for the element to be popped.
+        """
+        return self._index
+
+    @property
+    def list_variable(self):
+        """
+        Provide the name of the list as the return value.
+        
+        Provide the name of the list as the return value.
+        """
+        return self._list_variable
+
diff --git a/pyccel/ast/class_defs.py b/pyccel/ast/class_defs.py
index 6693646e..1a9abba8 100644
--- a/pyccel/ast/class_defs.py
+++ b/pyccel/ast/class_defs.py
@@ -6,7 +6,7 @@
 This module contains all types which define a python class which is automatically recognised by pyccel
 """
 
-from pyccel.ast.builtin_methods.list_methods import ListAppend
+from pyccel.ast.builtin_methods.list_methods import ListAppend, ListPop
 
 
 from .builtins  import PythonImag, PythonReal, PythonConjugate
@@ -139,6 +139,8 @@ ListClass = ClassDef('list', class_type = NativeHomogeneousList(),
         methods=[
             PyccelFunctionDef('append', func_class = ListAppend,
                 decorators = {}),
+            PyccelFunctionDef('pop', func_class = ListPop,
+                decorators = {}),
         ])
 
 #=======================================================================================
diff --git a/pyccel/codegen/printing/pycode.py b/pyccel/codegen/printing/pycode.py
index f2e0546b..b8bdc3a6 100644
--- a/pyccel/codegen/printing/pycode.py
+++ b/pyccel/codegen/printing/pycode.py
@@ -1143,6 +1143,11 @@ class PythonCodePrinter(CodePrinter):
         annotation = self._print(expr.arg)
         return f'const {annotation}'
 
+    def _print_ListPop(self, expr):
+        args = self._print(expr.pop_index) if expr.pop_index else ""
+        name = self._print(expr.list_variable)
+        return f"{name}.pop({args})"
+
 #==============================================================================
 def pycode(expr, assign_to=None, **settings):
     """ Converts an expr to a string of Python code


Test patch:
diff --git a/tests/epyccel/test_epyccel_lists.py b/tests/epyccel/test_epyccel_lists.py
old mode 100755
new mode 100644
index 7147954e..f5950364
--- a/tests/epyccel/test_epyccel_lists.py
+++ b/tests/epyccel/test_epyccel_lists.py
@@ -1,10 +1,6 @@
-# pylint: disable=missing-function-docstring, missing-module-docstring, missing-class-docstring
-# coding: utf-8
-""" Tests for list methods.
-"""
-
+# pylint: disable=missing-function-docstring, missing-module-docstring
 import pytest
-from pyccel.epyccel import epyccel
+from  pyccel.epyccel import epyccel
 
 @pytest.fixture( params=[
         pytest.param("fortran", marks = [
@@ -20,6 +16,48 @@ from pyccel.epyccel import epyccel
 def language(request):
     return request.param
 
+def test_pop_last_element(language) :
+    def pop_last_element():
+        a = [1,3,45]
+        return a.pop()
+    epyc_last_element = epyccel(pop_last_element, language = language)
+    pyccel_result = epyc_last_element()
+    python_result = pop_last_element()
+    assert isinstance(python_result, type(pyccel_result))
+    assert python_result == pyccel_result
+
+
+def test_pop_specific_index(language) :
+    def pop_specific_index():
+        a = [1j,3j,45j]
+        return a.pop(1)
+    epyc_specific_index = epyccel(pop_specific_index, language = language)
+    python_result = pop_specific_index()
+    pyccel_result = epyc_specific_index()
+    assert isinstance(python_result, type(pyccel_result))
+    assert python_result == pyccel_result
+
+def test_pop_negative_index(language) :
+    def pop_negative_index():
+        a = [1j,3j,45j]
+        return a.pop(-1)
+    epyc_negative_index = epyccel(pop_negative_index, language = language)
+    python_result = pop_negative_index()
+    pyccel_result = epyc_negative_index()
+    assert isinstance(python_result, type(pyccel_result))
+    assert python_result == pyccel_result
+
+def test_pop_2(language) :
+    def pop_2():
+        a = [1.7,2.7,45.0]
+        a.pop()
+        return a.pop(-1)
+    pop_2_epyc = epyccel(pop_2, language = language)
+    python_result = pop_2()
+    pyccel_result = pop_2_epyc()
+    assert isinstance(python_result, type(pyccel_result))
+    assert python_result == pyccel_result
+
 def test_append_basic(language):
     def f():
         a = [1, 2, 3]