Repository: pyccel/pyccel (python)

Issue:
Retrieving sets multiple times doesn't work
### Describe the bug
If the same set is used twice in a Fortran translation then a traceback is seen

### To Reproduce
Provide code to reproduce the behavior:
```python
def update_multiple():
    a = {1, 2, 3}
    a.update({4, 5})

def set_union():
    a = {1,2,3,4,5}
    b = {4,5,6}
    c = a.union(b)
```

### Error details
Provide the generated code, or the error message:
```bash/fortran/c
<pre>Traceback (most recent call last):
  File &quot;/home/emily/.local/bin/pyccel&quot;, line 8, in &lt;module&gt;
    sys.exit(pyccel())
  File &quot;/home/emily/Code/pyccel/pyccel/commands/console.py&quot;, line 266, in pyccel
    execute_pyccel(filename,
  File &quot;/home/emily/Code/pyccel/pyccel/codegen/pipeline.py&quot;, line 263, in execute_pyccel
    fname, prog_name = codegen.export(fname)
  File &quot;/home/emily/Code/pyccel/pyccel/codegen/codegen.py&quot;, line 220, in export
    code = self._printer.doprint(self.ast)
  File &quot;/home/emily/Code/pyccel/pyccel/codegen/printing/codeprinter.py&quot;, line 53, in doprint
    lines = self._print(expr).splitlines(True)
  File &quot;/home/emily/Code/pyccel/pyccel/codegen/printing/codeprinter.py&quot;, line 121, in _print
    obj = getattr(self, print_method)(expr)
  File &quot;/home/emily/Code/pyccel/pyccel/codegen/printing/fcode.py&quot;, line 825, in _print_Module
    func_strings += [&apos;&apos;.join([sep, self._print(i), sep]) for i in expr.funcs]
  File &quot;/home/emily/Code/pyccel/pyccel/codegen/printing/fcode.py&quot;, line 825, in &lt;listcomp&gt;
    func_strings += [&apos;&apos;.join([sep, self._print(i), sep]) for i in expr.funcs]
  File &quot;/home/emily/Code/pyccel/pyccel/codegen/printing/codeprinter.py&quot;, line 121, in _print
    obj = getattr(self, print_method)(expr)
  File &quot;/home/emily/Code/pyccel/pyccel/codegen/printing/fcode.py&quot;, line 2439, in _print_FunctionDef
    body_code = self._print(expr.body)
  File &quot;/home/emily/Code/pyccel/pyccel/codegen/printing/codeprinter.py&quot;, line 121, in _print
    obj = getattr(self, print_method)(expr)
  File &quot;/home/emily/Code/pyccel/pyccel/codegen/printing/fcode.py&quot;, line 2005, in _print_CodeBlock
    line = self._print(b)
  File &quot;/home/emily/Code/pyccel/pyccel/codegen/printing/codeprinter.py&quot;, line 121, in _print
    obj = getattr(self, print_method)(expr)
  File &quot;/home/emily/Code/pyccel/pyccel/codegen/printing/fcode.py&quot;, line 2021, in _print_Assign
    return self._print(rhs)
  File &quot;/home/emily/Code/pyccel/pyccel/codegen/printing/codeprinter.py&quot;, line 121, in _print
    obj = getattr(self, print_method)(expr)
  File &quot;/home/emily/Code/pyccel/pyccel/codegen/printing/fcode.py&quot;, line 1351, in _print_SetUnion
    self.add_import(self._build_gFTL_extension_module(expr_type))
  File &quot;/home/emily/Code/pyccel/pyccel/codegen/printing/fcode.py&quot;, line 690, in _build_gFTL_extension_module
    type_module = matching_expr_type.source_module
AttributeError: &apos;HomogeneousSetType&apos; object has no attribute &apos;source_module&apos;
</pre>
```

### Expected behavior
The handling of `_build_gFTL_extension_module` should be fixed

### Language
Fortran


Pull request:
Fix multiple calls to `_build_gFTL_extension_module`
Fix error when there are multiple calls to `_build_gFTL_extension_module`. Fixes #2103 .
This error is due to illogical usage of `matching_expr_type`. The error was introduced since the last version so this is not added to the CHANGELOG.

Patch:
diff --git a/pyccel/codegen/printing/fcode.py b/pyccel/codegen/printing/fcode.py
index ba551436..065ef709 100644
--- a/pyccel/codegen/printing/fcode.py
+++ b/pyccel/codegen/printing/fcode.py
@@ -677,26 +677,31 @@ class FCodePrinter(CodePrinter):
         Import
             The import which allows the new type to be accessed.
         """
-        # Get the type used in the dict for compatible types (e.g. float vs float64)
-        matching_expr_type = next((t for t in self._generated_gFTL_types if expr_type == t), None)
-        matching_expr_extensions = next((t for t in self._generated_gFTL_extensions if expr_type == t), None)
+        # Get the module describing the type
+        matching_expr_type = next((m for t,m in self._generated_gFTL_types.items() if expr_type == t), None)
+        # Get the module describing the extension
+        matching_expr_extensions = next((m for t,m in self._generated_gFTL_extensions.items() if expr_type == t), None)
         typename = self._print(expr_type)
         mod_name = f'{typename}_extensions_mod'
         if matching_expr_extensions:
-            module = self._generated_gFTL_extensions[matching_expr_extensions]
+            module = matching_expr_extensions
         else:
+            imports_and_macros = []
+
             if matching_expr_type is None:
                 matching_expr_type = self._build_gFTL_module(expr_type)
                 self.add_import(matching_expr_type)
-
-            type_module = matching_expr_type.source_module
+                imports_and_macros.append(matching_expr_type)
+                type_module = matching_expr_type.source_module
+            else:
+                type_module = matching_expr_type
+                imports_and_macros.append(Import(f'gFTL_extensions/{mod_name}', type_module))
 
             if isinstance(expr_type, HomogeneousSetType):
                 set_filename = LiteralString('set/template.inc')
-                imports_and_macros = [Import(LiteralString('Set_extensions.inc'), Module('_', (), ())) \
+                imports_and_macros += [Import(LiteralString('Set_extensions.inc'), Module('_', (), ())) \
                                         if getattr(i, 'source', None) == set_filename else i \
                                         for i in type_module.imports]
-                imports_and_macros.insert(0, matching_expr_type)
                 self.add_import(Import('gFTL_functions/Set_extensions', Module('_', (), ()), ignore_at_print = True))
             else:
                 raise NotImplementedError(f"Unkown gFTL import for type {expr_type}")


Test patch:
diff --git a/tests/epyccel/modules/Module_11.py b/tests/epyccel/modules/Module_11.py
new file mode 100644
index 00000000..0ad5c827
--- /dev/null
+++ b/tests/epyccel/modules/Module_11.py
@@ -0,0 +1,12 @@
+# pylint: disable=missing-function-docstring, missing-module-docstring
+
+def update_multiple():
+    a = {1, 2, 3}
+    a.update({4, 5})
+    return len(a)
+
+def set_union():
+    a = {1,2,3,4,5}
+    b = {4,5,6}
+    c = a.union(b)
+    return len(c)
diff --git a/tests/epyccel/test_epyccel_modules.py b/tests/epyccel/test_epyccel_modules.py
index 67ede7a0..f56a5df6 100644
--- a/tests/epyccel/test_epyccel_modules.py
+++ b/tests/epyccel/test_epyccel_modules.py
@@ -243,3 +243,18 @@ def test_module_type_alias_expression(language):
     assert np.isclose( max_pyt, max_pyc, rtol=1e-14, atol=1e-14 )
     assert np.allclose( x, x_pyc, rtol=1e-14, atol=1e-14 )
     assert np.allclose( y, y_pyc, rtol=1e-14, atol=1e-14 )
+
+def test_module_11(language):
+    import modules.Module_11 as mod
+
+    modnew = epyccel(mod, language=language)
+
+    len_pyt = mod.update_multiple()
+    len_pyc = modnew.update_multiple()
+
+    assert len_pyt == len_pyc
+
+    len_pyt = mod.set_union()
+    len_pyc = modnew.set_union()
+
+    assert len_pyt == len_pyc