Repository: pyccel/pyccel (python)

Issue:
[Bug] export-compiler-config flag requires Python file
### Is there an existing issue for this?

- [x] I have searched the existing issues

### Is this issue mentioned in the CHANGELOG?

- [x] I have searched the CHANGELOG and expect the bug to be reproducible on the `devel` branch

### Describe the bug

Since the flags were updated the FILE argument has become compulsory. This means that an arbitrary irrelevant (existing) FILE must be provided in order to use the `--export-compiler-config` flag 

### Expected behavior

The FILE should be used as the export file, or no FILE should be required if the flag is used

### Add Screenshots

_No response_

### Record

- [x] I have read the [Contributing Guidelines](https://github.com/pyccel/pyccel/blob/devel/docs/CONTRIBUTING.md).
- [x] I have starred the repository

Pull request:
Fix the use of the `--export-compiler-config` flag.
Fix the use of the `--export-compiler-config` flag. Fixes #2364

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6f297a92..80adc2c5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,8 @@ All notable changes to this project will be documented in this file.
 
 ### Fixed
 
+-   #2364 : Fix the use of the `--export-compiler-config` flag.
+
 ### Changed
 
 ### Deprecated
diff --git a/pyccel/codegen/compiling/compilers.py b/pyccel/codegen/compiling/compilers.py
index a3d4fccb..c779aca5 100644
--- a/pyccel/codegen/compiling/compilers.py
+++ b/pyccel/codegen/compiling/compilers.py
@@ -9,6 +9,7 @@ Module handling everything related to the compilers used to compile the various
 """
 import json
 import os
+import pathlib
 import shutil
 import subprocess
 import platform
@@ -589,7 +590,7 @@ class Compiler:
 
         return cmd
 
-    def export_compiler_info(self, compiler_export_file):
+    def export_compiler_info(self, compiler_export_filename):
         """
         Export the compiler configuration to a json file.
 
@@ -601,10 +602,13 @@ class Compiler:
 
         Parameters
         ----------
-        compiler_export_file : str
+        compiler_export_filename : str | Path
             The name of the file where the compiler configuration
             should be printed.
         """
+        compiler_export_file = pathlib.Path(compiler_export_filename)
+        folder = compiler_export_file.parent
+        os.makedirs(folder, exist_ok=True)
         with open(compiler_export_file,'w', encoding="utf-8") as out_file:
             print(json.dumps(self._compiler_info, indent=4),
                     file=out_file)
diff --git a/pyccel/commands/console.py b/pyccel/commands/console.py
index dc304aaa..5ef9f3dc 100644
--- a/pyccel/commands/console.py
+++ b/pyccel/commands/console.py
@@ -149,7 +149,7 @@ def pyccel() -> None:
                         help='Print the time spent in each section of the execution.')
     group.add_argument('--developer-mode', action='store_true', \
                         help='Show internal messages.')
-    group.add_argument('--export-compiler-config', metavar='CONFIG.json', type=pathlib.Path, default = None, \
+    group.add_argument('--export-compiler-config', action='store_true', \
                         help='Export all compiler information to a JSON file with the given path (relative or absolute).')
     group.add_argument('--conda-warnings', choices=('off', 'basic', 'verbose'),
                         help='Specify the level of Conda warnings to display (default: basic).')
@@ -176,12 +176,28 @@ def pyccel() -> None:
     if not args.conda_warnings:
         args.conda_warnings = 'basic'
 
-    if args.convert_only or args.syntax_only or args.semantic_only:
-        compiler = None
     # ...
+    if args.export_compiler_config:
+        cext = filename.suffix
+        if cext == '':
+            filename = filename.with_suffix('.json')
+        elif cext != '.json':
+            errors = Errors()
+            # severity is error to avoid needing to catch exception
+            errors.report('Wrong file extension. Expecting `json`, but found',
+                          symbol=cext,
+                          severity='error')
+            errors.check()
+            sys.exit(1)
+
+        execute_pyccel('',
+                       compiler_family = str(compiler) if compiler is not None else None,
+                       compiler_export_file = filename)
+        sys.exit(0)
 
     # ...
-    compiler_export_file = args.export_compiler_config
+    if args.convert_only or args.syntax_only or args.semantic_only:
+        compiler = None
 
     # ... report error
     if filename.is_file():
@@ -205,19 +221,6 @@ def pyccel() -> None:
         sys.exit(1)
     # ...
 
-    if compiler_export_file is not None:
-        cext = compiler_export_file.suffix
-        if cext == '':
-            compiler_export_file = compiler_export_file.with_suffix('.json')
-        elif cext != '.json':
-            errors = Errors()
-            # severity is error to avoid needing to catch exception
-            errors.report('Wrong file extension. Expecting `json`, but found',
-                          symbol=cext,
-                          severity='error')
-            errors.check()
-            sys.exit(1)
-
     accelerators = []
     if mpi:
         accelerators.append("mpi")
@@ -263,7 +266,6 @@ def pyccel() -> None:
                        debug           = args.debug,
                        accelerators    = accelerators,
                        folder          = str(output) if output is not None else None,
-                       compiler_export_file = compiler_export_file,
                        conda_warnings  = args.conda_warnings)
     except PyccelError:
         sys.exit(1)


Test patch:
diff --git a/tests/pyccel/test_pyccel.py b/tests/pyccel/test_pyccel.py
index 026a6547..32076f05 100644
--- a/tests/pyccel/test_pyccel.py
+++ b/tests/pyccel/test_pyccel.py
@@ -1124,24 +1124,48 @@ def test_inline_import(language):
                 language = language)
 
 #------------------------------------------------------------------------------
-@pytest.mark.xdist_incompatible
 def test_json():
-    pyccel_test("scripts/runtest_funcs.py", language = 'fortran',
-            pyccel_commands='--export-compiler-config test.json')
-    with open(get_abs_path('scripts/test.json'), 'r') as f:
+    output_dir = get_abs_path(insert_pyccel_folder('scripts/'))
+    cmd = [shutil.which("pyccel"), '--export-compiler-config', f'{output_dir}/test.json', '--compiler-family', 'intel']
+    subprocess.run(cmd, check=True)
+    with open(get_abs_path(f'{output_dir}/test.json'), 'r', encoding='utf-8') as f:
+        dict_1 = json.load(f)
+    assert dict_1['c']['exec'] == 'icx'
+    cmd = [shutil.which("pyccel"),
+           '--compiler-config',
+           f'{output_dir}/test.json',
+           '--export-compiler-config',
+           f'{output_dir}/test2.json']
+    subprocess.run(cmd, check=True)
+    with open(get_abs_path(f'{output_dir}/test2.json'), 'r', encoding='utf-8') as f:
+        dict_2 = json.load(f)
+
+    assert dict_1 == dict_2
+
+#------------------------------------------------------------------------------
+def test_ambiguous_json():
+    output_dir = get_abs_path(insert_pyccel_folder('scripts/'))
+    cmd = [shutil.which("pyccel"), '--export-compiler-config', f'{output_dir}/test']
+    subprocess.run(cmd, check=True)
+    with open(get_abs_path(f'{output_dir}/test.json'), 'r', encoding='utf-8') as f:
         dict_1 = json.load(f)
-    pyccel_test("scripts/runtest_funcs.py", language = 'fortran',
-        pyccel_commands='--compiler-config test.json --export-compiler-config test2.json')
-    with open(get_abs_path('scripts/test2.json'), 'r') as f:
+    cmd = [shutil.which("pyccel"),
+           '--compiler-config',
+           f'{output_dir}/test.json',
+           '--export-compiler-config',
+           f'{output_dir}/test2']
+    subprocess.run(cmd, check=True)
+    with open(get_abs_path(f'{output_dir}/test2.json'), 'r', encoding='utf-8') as f:
         dict_2 = json.load(f)
 
     assert dict_1 == dict_2
 
 @pytest.mark.xdist_incompatible
 def test_json_relative_path():
-    pyccel_test("scripts/runtest_funcs.py", language = 'fortran',
-            pyccel_commands='--export-compiler-config test.json')
-    shutil.move(get_abs_path('scripts/test.json'), get_abs_path('scripts/hope_benchmarks/test.json'))
+    output_dir = get_abs_path(insert_pyccel_folder('scripts/'))
+    cmd = [shutil.which("pyccel"), '--export-compiler-config', f'{output_dir}/test.json']
+    subprocess.run(cmd, check=True)
+    shutil.move(get_abs_path(f'{output_dir}/test.json'), get_abs_path('scripts/hope_benchmarks/test.json'))
     compile_pyccel(get_abs_path('scripts/hope_benchmarks'), "../runtest_funcs.py", '--compiler-config test.json')
 
 #------------------------------------------------------------------------------