Repository: pyccel/pyccel
Pull request #1898 (2024-05-21 19:03:39)

fixed list function implementation
Fix list() issue mentioned in https://github.com/pyccel/pyccel/issues/1892 . This PR fixes the list() implementation when using a list or a tuple as a parameter

Commit Summary
- Created PythonListFunction class which acts as a wrapper for PythonList and handles such cases.
- Created unit tests using the newly implemented class.

pyccel-bot[bot]: Hello! Welcome to Pyccel! Thank you very much for your contribution :heart:.

I am the GitHub bot. I will help guide you through the different stages necessary to validate a review in Pyccel. If you haven't yet seen our developer docs make sure you check them out [here](https://github.com/pyccel/pyccel/tree/devel/developer_docs). Amongst other things they describe the [review process](https://github.com/pyccel/pyccel/blob/devel/developer_docs/review_process.md) that we have just started. You can also get in touch with our other developers on our [Pyccel Discord Server](https://discord.gg/2Q6hwjfFVb).

To begin with I will give you a short checklist to make sure your pull request is complete. Please tick items off when you have completed them or determined that they are not necessary for this pull request. If you want me to run any specific tests to check out corner cases that you can't easily check on your computer, you can request this using the command `/bot run X`. Use the command `/bot show tests` to see a full list of the tests I can run. Once you have finished preparing your pull request and are ready to request reviews just take your PR out of draft, or let me know with the command `/bot mark as ready`. I will then run the full suite of tests to check that everything is as neat as you think before asking other contributors for reviews. Tests will not run automatically before this point to avoid wasting resources. You can get a full list of commands that I understand using `/bot commands`.

Please begin by requesting your checklist using the command `/bot checklist`.

pyccel-bot[bot]: @yguclu, @EmilyBourne, @bauom, please can you check if I can trust this user. If you are happy, let me know with `/bot trust user`
shoaib-moeen: /bot commands
pyccel-bot[bot]: This bot reacts to all comments which begin with `/bot`. This phrase can be followed by any of these commands:
- `show tests` : Lists the tests which can be triggered
- `run X` : Triggers the test X (acceptable values for X can be seen using `show tests`). Multiple tests can be specified separated by spaces.
- `try V X` : Triggers the test X (acceptable values for X can be seen using `show tests`) using Python version V. Multiple tests can be specified separated by spaces, but all will use the same Python version.
- `mark as ready` : Runs the PR tests. If they pass then it adds the appropriate review flag and requests reviews. This command should be used when the PR is first ready for review, or when a review has been answered.
- `commands` : Shows this list detailing all the commands which are understood.
- `trust user X` : Tells the bot that a new user X is trusted to run workflows (prevents misuse of GitHub actions for mining etc). This command can only be used by a trusted reviewer.

Beware: if you have never contributed to this repository and you are not a member of the Pyccel organisation, the bot will ignore all requests to run tests until permitted by a trusted reviewer.

shoaib-moeen: /bot show tests
pyccel-bot[bot]: The following is a list of keywords which can be used to run tests. Tests in bold are run by pull requests when they are marked as ready for review:
- **linux** : Runs the unit tests on a Linux system.
- **windows** : Runs the unit tests on a Windows system.
- **macosx** : Runs the unit tests on a MacOS X system.
- **coverage** : Runs the unit tests on a Linux system and checks the coverage of the tests.
- **docs** : Checks if the documentation follows the numpydoc format.
- **pylint** : Runs pylint on files which are too big to be handled by codacy.
- **pyccel_lint** : Runs a linter to check that Pyccel's best practices are followed.
- **spelling** : Checks if everything in the documentation is spelled (and capitalised) correctly.
- pr_tests : Runs all the tests marked in bold.
- pickle : Checks that .pyccel files have been correctly generated and installed by the installation process.
- editable_pickle : Checks that .pyccel files have been correctly generated and installed by the editable installation process.
- pickle_wheel : Checks that .pyccel files have been correctly generated and packaged into the wheel.
- anaconda_linux : Runs the unit tests on a linux system using anaconda for python.
- anaconda_windows : Runs the unit tests on a windows system using anaconda for python.
- intel : Runs the unit tests on a linux system using the intel compiler.

These tests can be run with the command `/bot run X` (multiple tests can be specified separated by spaces), or with `try V X` to test on Python version V.

shoaib-moeen: /bot run linux
pyccel-bot[bot]: Thank you for your request. Unfortunately I am not allowed to run tests for you as you have never contributed to this repository and haven't been approved on this Pull Request.

shoaib-moeen: /bot run coverage
pyccel-bot[bot]: Thank you for your request. Unfortunately I am not allowed to run tests for you as you have never contributed to this repository and haven't been approved on this Pull Request.

shoaib-moeen: /bot run docs spelling pylint pyccel_lint coverage
pyccel-bot[bot]: Thank you for your request. Unfortunately I am not allowed to run tests for you as you have never contributed to this repository and haven't been approved on this Pull Request.

EmilyBourne: /bot trust user shoaib-moeen 
shoaib-moeen: /bot run linux
EmilyBourne: /bot run docs spelling pylint pyccel_lint coverage
shoaib-moeen: /bot run docs spelling pylint pyccel_lint coverage
shoaib-moeen: /bot run docs spelling pylint pyccel_lint coverage
pyccel-bot[bot]: It seems like you may have forgotten to write a detailed description for this pull request. Please could you fix that and anything else missing from your checklist. Let me know when this is fixed with `/bot mark as ready`.

shoaib-moeen: /bot checklist
shoaib-moeen: @EmilyBourne , I could not find the authors file. Can you tell me where I have to update it? Everything else on the checklist is completed
Farouk-Echaref: @shoaib-moeen it's in the root directory called AUTHORS
shoaib-moeen: /bot run docs spelling pylint pyccel_lint coverage
pyccel-bot[bot]: Hey @pyccel/pyccel-dev ! @shoaib-moeen has just created this great new pull request! Check it out and let me know what you think!

EmilyBourne: @shoaib-moeen Do you plan to come back and finish this PR or can I pick it up and complete it?
shoaib-moeen: Sorry. I have been busy since last two months. You can go ahead and
complete it.

On Thu, 25 Jul 2024 at 5:27 PM, Emily Bourne ***@***.***>
wrote:

> @shoaib-moeen <https://github.com/shoaib-moeen> Do you plan to come back
> and finish this PR or can I pick it up and complete it?
>
> —
> Reply to this email directly, view it on GitHub
> <https://github.com/pyccel/pyccel/pull/1898#issuecomment-2250203059>, or
> unsubscribe
> <https://github.com/notifications/unsubscribe-auth/BH5V476IBRN4VTOQ3WCDYWDZODVMDAVCNFSM6AAAAABICGHSPOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDENJQGIYDGMBVHE>
> .
> You are receiving this because you were mentioned.Message ID:
> ***@***.***>
>

pyccel-bot[bot]: Unfortunately your PR is not passing the tests so it is not quite ready for review yet. Let me know when it is fixed with `/bot mark as ready`.

pyccel-bot[bot]: @EmilyBourne, @shoaib-moeen has been working hard and thinks that they have now replied to or fixed all your comments. Could you take another look at the PR and see if you can approve now?

EmilyBourne: /bot run pr_tests
pyccel-bot[bot]: @EmilyBourne, @jalalium, @shoaib-moeen has been working hard and thinks that they have now replied to or fixed all your comments. Could you take another look at the PR and see if you can approve now?

EmilyBourne: /bot run pr_tests

Patch:
diff --git a/AUTHORS b/AUTHORS
index 3dbaa2f2..9602cb90 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -32,3 +32,4 @@ Contributors
 * Mustapha Belbiad
 * Varadarajan Rengaraj
 * Said Mazouz
+* Shoaib Moeen
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2401a8ef..e3d4d5a7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -54,6 +54,7 @@ All notable changes to this project will be documented in this file.
 -   #1933 : Improve code printing speed.
 -   #1930 : Preserve ordering of import targets.
 -   #1951 : Fix return type for class whose argument cannot be wrapped.
+-   #1892 : Fix implementation of list function when an iterable is passed as parameter.
 
 ### Changed
 
diff --git a/pyccel/ast/builtins.py b/pyccel/ast/builtins.py
index 5bb3f66b..31016282 100644
--- a/pyccel/ast/builtins.py
+++ b/pyccel/ast/builtins.py
@@ -46,6 +46,7 @@ __all__ = (
     'PythonInt',
     'PythonLen',
     'PythonList',
+    'PythonListFunction',
     'PythonMap',
     'PythonMax',
     'PythonMin',
@@ -719,6 +720,47 @@ class PythonList(TypedAstNode):
         """
         return True
 
+
+class PythonListFunction(PyccelFunction):
+    """
+    Class representing a call to the `list` function.
+
+    Class representing a call to the `list` function. This is
+    different to the `[,]' syntax as it only takes one argument
+    and unpacks any variables.
+
+    Parameters
+    ----------
+    arg : TypedAstNode
+        The argument passed to the function call.
+    """
+    name = 'list'
+    __slots__ = ('_class_type', '_shape')
+    _attribute_nodes = ()
+
+    def __new__(cls, arg):
+        if isinstance(arg, PythonList):
+            return arg
+        elif isinstance(arg.shape[0], LiteralInteger):
+            return PythonList(*[arg[i] for i in range(arg.shape[0])])
+        else:
+            return super().__new__(cls)
+
+    def __init__(self, copied_obj):
+        self._class_type = copied_obj.class_type
+        self._shape = copied_obj.shape
+        super().__init__(copied_obj)
+
+    @property
+    def copied_obj(self):
+        """
+        The object being copied.
+
+        The object being copied to create a new list instance.
+        """
+        return self._args[0]
+
+
 #==============================================================================
 class PythonSet(TypedAstNode):
     """
@@ -1382,7 +1424,7 @@ builtin_functions_dict = {
     'float'    : PythonFloat,
     'int'      : PythonInt,
     'len'      : PythonLen,
-    'list'     : PythonList,
+    'list'     : PythonListFunction,
     'map'      : PythonMap,
     'max'      : PythonMax,
     'min'      : PythonMin,
diff --git a/pyccel/parser/semantic.py b/pyccel/parser/semantic.py
index e95a376a..bbdddcff 100644
--- a/pyccel/parser/semantic.py
+++ b/pyccel/parser/semantic.py
@@ -22,7 +22,7 @@ from pyccel.utilities.strings import random_string
 from pyccel.ast.basic         import PyccelAstNode, TypedAstNode, ScopedAstNode
 
 from pyccel.ast.builtins import PythonPrint, PythonTupleFunction, PythonSetFunction
-from pyccel.ast.builtins import PythonComplex, PythonDict, PythonDictFunction
+from pyccel.ast.builtins import PythonComplex, PythonDict, PythonDictFunction, PythonListFunction
 from pyccel.ast.builtins import builtin_functions_dict, PythonImag, PythonReal
 from pyccel.ast.builtins import PythonList, PythonConjugate , PythonSet
 from pyccel.ast.builtins import (PythonRange, PythonZip, PythonEnumerate,
@@ -148,7 +148,7 @@ pyccel_stage = PyccelStage()
 
 type_container = {
                    PythonTupleFunction : HomogeneousTupleType,
-                   PythonList : HomogeneousListType,
+                   PythonListFunction : HomogeneousListType,
                    PythonSetFunction : HomogeneousSetType,
                   }
 
@@ -1969,7 +1969,7 @@ class SemanticParser(BasicParser):
             if (len(args) == 2 and args[1] is LiteralEllipsis()) or len(args) == 1:
                 syntactic_annotation = self._convert_syntactic_object_to_type_annotation(args[0])
                 internal_datatypes = self._visit(syntactic_annotation)
-                if dtype_cls in type_container :
+                if dtype_cls in type_container:
                     class_type = type_container[dtype_cls]
                 else:
                     raise errors.report(f"Unknown annotation base {base}\n"+PYCCEL_RESTRICTION_TODO,


Test patch:
diff --git a/tests/epyccel/test_epyccel_lists.py b/tests/epyccel/test_epyccel_lists.py
index b7897297..19d71084 100644
--- a/tests/epyccel/test_epyccel_lists.py
+++ b/tests/epyccel/test_epyccel_lists.py
@@ -690,3 +690,70 @@ def test_mutable_multi_level_indexing(stc_language):
 
     epyc_f = epyccel(f, language=stc_language)
     assert f() == epyc_f()
+
+def test_homogenous_list_int_copy(language):
+    def homogeneous_list_int():
+        return list([1, 2, 3, 4])
+    f1 = homogeneous_list_int
+    f2 = epyccel( f1 , language=language)
+
+    python_out = f1()
+    pyccel_out = f2()
+    print(pyccel_out)
+    print(python_out)
+
+    assert python_out == pyccel_out
+
+def test_homogenous_list_bool_copy(language):
+    def homogeneous_list_bool():
+        return list([True, False, True, False])
+    f1 = homogeneous_list_bool
+    f2 = epyccel( f1 , language=language)
+
+    python_out = f1()
+    pyccel_out = f2()
+    print(pyccel_out)
+    print(python_out)
+
+    assert python_out == pyccel_out
+
+def test_homogenous_list_float_copy(language):
+    def homogeneous_list_float():
+        return list([1.0, 2.0, 3.0, 4.0])
+    f1 = homogeneous_list_float
+    f2 = epyccel( f1 , language=language)
+
+    python_out = f1()
+    pyccel_out = f2()
+    print(pyccel_out)
+    print(python_out)
+
+    assert python_out == pyccel_out
+
+def test_homogenous_list_int_tuple_copy(language):
+    def homogeneous_list_int_tuple():
+        return list((1, 2, 3, 4))
+    f1 = homogeneous_list_int_tuple
+    f2 = epyccel( f1 , language=language)
+
+    python_out = f1()
+    pyccel_out = f2()
+    print(pyccel_out)
+    print(python_out)
+
+    assert python_out == pyccel_out
+
+def test_homogenous_list_unknown_size_copy(language):
+    def homogeneous_list_unknown_size_copy(n : int):
+        a = (3,)*n
+        b = list(a)
+        return b[0]
+    f1 = homogeneous_list_unknown_size_copy
+    f2 = epyccel( f1 , language=language)
+
+    python_out = f1(5)
+    pyccel_out = f2(5)
+    print(pyccel_out)
+    print(python_out)
+
+    assert python_out == pyccel_out