From 4eaf3bfeecafa098fd429c618da73b7e97c60763 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Mon, 23 Feb 2026 13:24:13 +0100 Subject: [PATCH 01/37] added asv workflow --- .github/workflows/asv.yml | 57 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 .github/workflows/asv.yml diff --git a/.github/workflows/asv.yml b/.github/workflows/asv.yml new file mode 100644 index 00000000..ad68ded8 --- /dev/null +++ b/.github/workflows/asv.yml @@ -0,0 +1,57 @@ +name: ASV Benchmarks + +on: + push: + branches: [main, develop] + pull_request: + types: [opened, synchronize, reopened] + schedule: + # Run benchmarks daily at 2 AM UTC + - cron: '0 2 * * *' + +jobs: + benchmark: + runs-on: ubuntu-22.04 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Display Python version + run: python -c "import sys; print(sys.version)" + + - name: Install dependencies + working-directory: backend + run: | + python -m pip install --upgrade pip + pip install -e . + pip install asv + + - name: Run ASV benchmarks + run: | + asv run --quick --show-stderr + + - name: Compare with main branch + if: github.event_name == 'pull_request' + run: | + asv continuous develop main --quick --show-stderr || true + + - name: Generate HTML results + if: always() + run: | + asv publish + + - name: Upload benchmark results + if: always() + uses: actions/upload-artifact@v4 + with: + name: asv-results + path: html/ + retention-days: 30 From dc6b820f58f34b6c1d833925387294c6baa28470 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Mon, 23 Feb 2026 13:30:45 +0100 Subject: [PATCH 02/37] added workflow dispatch --- .github/workflows/asv.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/asv.yml b/.github/workflows/asv.yml index ad68ded8..e9eb9b9f 100644 --- a/.github/workflows/asv.yml +++ b/.github/workflows/asv.yml @@ -8,6 +8,7 @@ on: schedule: # Run benchmarks daily at 2 AM UTC - cron: '0 2 * * *' + workflow_dispatch: jobs: benchmark: From dfcf172e6e4e1c17cf572f71e9a6468913726331 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Fri, 27 Feb 2026 10:11:08 +0100 Subject: [PATCH 03/37] ci: fix ASV benchmarks for GitHub Actions with Zenodo test data and regression gating.Replace ITER-internal URIs with public Zenodo datasets, use asv continuous for same-runner comparisons, fail CI on >2x regression, post PR comments, and apply CI-specific threshold at runtime. --- .github/workflows/asv.yml | 120 ++++++++++++++++++++++++++++++++++---- benchmarks/__init__.py | 25 ++++++-- 2 files changed, 130 insertions(+), 15 deletions(-) diff --git a/.github/workflows/asv.yml b/.github/workflows/asv.yml index e9eb9b9f..d17b950a 100644 --- a/.github/workflows/asv.yml +++ b/.github/workflows/asv.yml @@ -5,14 +5,13 @@ on: branches: [main, develop] pull_request: types: [opened, synchronize, reopened] - schedule: - # Run benchmarks daily at 2 AM UTC - - cron: '0 2 * * *' workflow_dispatch: jobs: benchmark: runs-on: ubuntu-22.04 + permissions: + pull-requests: write # needed to post PR comments steps: - name: Checkout code @@ -32,17 +31,117 @@ jobs: working-directory: backend run: | python -m pip install --upgrade pip - pip install -e . - pip install asv + # virtualenv required by asv to create per-commit benchmark environments + pip install asv virtualenv - - name: Run ASV benchmarks + - name: Download test data from Zenodo run: | - asv run --quick --show-stderr + mkdir -p test_data + # iter_scenario_53298_seq1_DD4: ~14 MB, single time slice, DD 4.0.0 + wget -q -O test_data/iter_scenario_53298_seq1_DD4.nc \ + "https://zenodo.org/records/17062700/files/iter_scenario_53298_seq1_DD4.nc?download=1" + # iter_scenario_123364_1: ~118 MB, single time slice, DD 4.0.0 + wget -q -O test_data/iter_scenario_123364_1.nc \ + "https://zenodo.org/records/17062700/files/iter_scenario_123364_1.nc?download=1" + echo "Downloaded files:" + ls -lh test_data/ - - name: Compare with main branch + - name: Configure ASV regression threshold for CI + run: | + # On GitHub Actions: only flag regressions >2x slower in the HTML report, + # matching the --factor 2.0 used in asv continuous below. + # On Bamboo/local, asv.conf.json is used as-is (default ASV threshold of 5%). + python - <<'EOF' + import pathlib + conf_path = pathlib.Path('asv.conf.json') + conf = conf_path.read_text() + # Insert threshold entry before the final closing brace + assert conf.rstrip().endswith('}'), "Unexpected asv.conf.json ending" + patched = conf.rstrip()[:-1].rstrip().rstrip(',') + ',\n "regressions_thresholds": {".*": 2.0}\n}\n' + conf_path.write_text(patched) + print("CI: regressions_thresholds set to 2.0") + EOF + + - name: Run ASV continuous benchmarks + id: asv + # continue-on-error so we can post the PR comment before re-failing the job + continue-on-error: true + env: + # Tells benchmarks/__init__.py where the test data lives + IBEX_TEST_DATA_DIR: ${{ github.workspace }}/test_data + run: | + asv machine --yes + + if [ "${{ github.event_name }}" = "pull_request" ]; then + # Compare base branch vs PR head — both on the same runner, same hardware + BASELINE="origin/${{ github.base_ref }}" + CONTENDER="${{ github.sha }}" + else + # Compare previous commit vs current commit on push/manual trigger + # Guard: skip if there is no previous commit (e.g. initial branch push) + if ! git rev-parse HEAD~1 >/dev/null 2>&1; then + echo "No previous commit to compare against — skipping benchmark comparison." + exit 0 + fi + BASELINE="HEAD~1" + CONTENDER="HEAD" + fi + + echo "Comparing ${BASELINE}...${CONTENDER}" + # --factor 2.0: only flag as regression if a benchmark is >2x slower + # (filters out GitHub runner hardware noise, ~20-50% typical variance) + asv continuous --quick --show-stderr --factor 2.0 "${BASELINE}" "${CONTENDER}" \ + 2>&1 | tee asv_output.txt + + - name: Post benchmark results to PR if: github.event_name == 'pull_request' + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + const output = fs.existsSync('asv_output.txt') + ? fs.readFileSync('asv_output.txt', 'utf8').trim() + : '_No output captured — benchmark step crashed before producing output._'; + + const outcome = '${{ steps.asv.outcome }}'; + const icon = outcome === 'failure' ? '🔴' : '✅'; + const title = outcome === 'failure' + ? '**Performance regression detected (>2x slower on at least one benchmark)**' + : '**No significant performance regressions detected**'; + const body = `## ${icon} ASV Benchmark Results\n${title}\n\n` + + `
Full output\n\n\`\`\`\n${output}\n\`\`\`\n
`; + + // Update existing bot comment if present, otherwise create a new one. + // This avoids comment spam when multiple commits are pushed to the same PR. + const { data: comments } = await github.rest.issues.listComments({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + }); + const botComment = comments.find(c => + c.user.type === 'Bot' && c.body.includes('ASV Benchmark Results') + ); + if (botComment) { + await github.rest.issues.updateComment({ + comment_id: botComment.id, + owner: context.repo.owner, + repo: context.repo.repo, + body: body, + }); + } else { + await github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: body, + }); + } + + - name: Fail job if regression detected + if: steps.asv.outcome == 'failure' run: | - asv continuous develop main --quick --show-stderr || true + echo "❌ Performance regression detected (>2x threshold). See benchmark output above." + exit 1 - name: Generate HTML results if: always() @@ -54,5 +153,6 @@ jobs: uses: actions/upload-artifact@v4 with: name: asv-results - path: html/ + path: .asv/html/ retention-days: 30 + if-no-files-found: warn diff --git a/benchmarks/__init__.py b/benchmarks/__init__.py index d8788870..0353f65e 100644 --- a/benchmarks/__init__.py +++ b/benchmarks/__init__.py @@ -1,6 +1,21 @@ +import os +from pathlib import Path + uris_label = ["pulsefile uri"] -uris = [ - "imas:mdsplus?user=public;database=ITER;pulse=134173;run=106;version=3", # 871 slices - "imas:hdf5?user=public;database=ITER;pulse=134173;run=106;version=3", # 871 slices - "imas:hdf5?path=/work/imas/shared/imasdb/ITER/3/105070/2", # 4183 slices -] + +if os.environ.get("GITHUB_ACTIONS") == "true": + # On GitHub Actions: use publicly available Zenodo datasets (CC-BY 4.0) + # https://zenodo.org/records/17062700 + # Downloaded by the workflow into IBEX_TEST_DATA_DIR before benchmarks run. + _data_dir = Path(os.environ["IBEX_TEST_DATA_DIR"]) + uris = [ + str(_data_dir / "iter_scenario_53298_seq1_DD4.nc"), # ~14 MB, single time slice (DD 4.0.0) + str(_data_dir / "iter_scenario_123364_1.nc"), # ~118 MB, single time slice (DD 4.0.0) + ] +else: + # Local / ITER infrastructure: use internal IMAS data sources directly + uris = [ + "imas:mdsplus?user=public;database=ITER;pulse=134173;run=106;version=3", # 871 slices + "imas:hdf5?user=public;database=ITER;pulse=134173;run=106;version=3", # 871 slices + "imas:hdf5?path=/work/imas/shared/imasdb/ITER/3/105070/2", # 4183 slices + ] From f77f66efd4798a27b8769c6d10bf506e90b3d95e Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Fri, 27 Feb 2026 10:34:12 +0100 Subject: [PATCH 04/37] fixed trailing slashes for netcdf --- benchmarks/endpoints_data.py | 4 ++-- benchmarks/endpoints_ids_info.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/benchmarks/endpoints_data.py b/benchmarks/endpoints_data.py index 265c8c8c..9b87c7cb 100644 --- a/benchmarks/endpoints_data.py +++ b/benchmarks/endpoints_data.py @@ -12,7 +12,7 @@ def setup(self, *args): self.test_client = TestClient(app) def time_field_value(self, uri, node_path): - parameters = {"uri": f"{uri}/{node_path}"} + parameters = {"uri": f"{uri}{node_path}"} self.test_client.get("/data/field_value", params=parameters) time_field_value.param_names = param_names + ["node path"] @@ -27,7 +27,7 @@ def time_field_value(self, uri, node_path): ) def time_plot_data(self, uri, node_path): - parameters = {"uri": f"{uri}/{node_path}"} + parameters = {"uri": f"{uri}{node_path}"} self.test_client.get("/data/plot_data", params=parameters) time_plot_data.param_names = param_names + ["node path"] diff --git a/benchmarks/endpoints_ids_info.py b/benchmarks/endpoints_ids_info.py index afc75f52..60767751 100644 --- a/benchmarks/endpoints_ids_info.py +++ b/benchmarks/endpoints_ids_info.py @@ -11,7 +11,7 @@ def setup(self, *args): self.test_client = TestClient(app) def time_node_info(self, uri, node_path): - parameters = {"uri": f"{uri}/{node_path}"} + parameters = {"uri": f"{uri}{node_path}"} self.test_client.get("/data_entry/node_info", params=parameters) time_node_info.param_names = param_names + ["node path"] @@ -35,7 +35,7 @@ def time_find_field(self, uri, searched_node): time_find_field.params = (uris, ["v_loop"]) def time_array_summary(self, uri, node_path): - parameters = {"uri": f"{uri}/{node_path}"} + parameters = {"uri": f"{uri}{node_path}"} self.test_client.get("/data_entry/array_summary", params=parameters) time_array_summary.param_names = param_names + ["node path"] From 4aecfb66fa3facd861567f90614988b40c1e8de6 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Fri, 27 Feb 2026 10:55:20 +0100 Subject: [PATCH 05/37] provided one relevant netcdf file which has all variables --- benchmarks/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/benchmarks/__init__.py b/benchmarks/__init__.py index 0353f65e..6adac4c7 100644 --- a/benchmarks/__init__.py +++ b/benchmarks/__init__.py @@ -9,7 +9,6 @@ # Downloaded by the workflow into IBEX_TEST_DATA_DIR before benchmarks run. _data_dir = Path(os.environ["IBEX_TEST_DATA_DIR"]) uris = [ - str(_data_dir / "iter_scenario_53298_seq1_DD4.nc"), # ~14 MB, single time slice (DD 4.0.0) str(_data_dir / "iter_scenario_123364_1.nc"), # ~118 MB, single time slice (DD 4.0.0) ] else: From 55d9c4cdc1b51a5d0627fa77d9d5966579f1837e Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Fri, 27 Feb 2026 11:50:31 +0100 Subject: [PATCH 06/37] provide appropriate scenario file --- .github/workflows/asv.yml | 7 +++---- benchmarks/__init__.py | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/asv.yml b/.github/workflows/asv.yml index d17b950a..aaf299fc 100644 --- a/.github/workflows/asv.yml +++ b/.github/workflows/asv.yml @@ -37,12 +37,11 @@ jobs: - name: Download test data from Zenodo run: | mkdir -p test_data - # iter_scenario_53298_seq1_DD4: ~14 MB, single time slice, DD 4.0.0 + # iter_scenario_53298_seq1_DD4: ~14 MB, DD 4.0.0, contains core_profiles + equilibrium + # (required by all benchmark node paths). The 123364 file is a SOLPS edge + # simulation with no core_profiles/equilibrium so is not used for benchmarks. wget -q -O test_data/iter_scenario_53298_seq1_DD4.nc \ "https://zenodo.org/records/17062700/files/iter_scenario_53298_seq1_DD4.nc?download=1" - # iter_scenario_123364_1: ~118 MB, single time slice, DD 4.0.0 - wget -q -O test_data/iter_scenario_123364_1.nc \ - "https://zenodo.org/records/17062700/files/iter_scenario_123364_1.nc?download=1" echo "Downloaded files:" ls -lh test_data/ diff --git a/benchmarks/__init__.py b/benchmarks/__init__.py index 6adac4c7..80ccdade 100644 --- a/benchmarks/__init__.py +++ b/benchmarks/__init__.py @@ -9,7 +9,7 @@ # Downloaded by the workflow into IBEX_TEST_DATA_DIR before benchmarks run. _data_dir = Path(os.environ["IBEX_TEST_DATA_DIR"]) uris = [ - str(_data_dir / "iter_scenario_123364_1.nc"), # ~118 MB, single time slice (DD 4.0.0) + str(_data_dir / "iter_scenario_53298_seq1_DD4.nc"), # ~14 MB, DD 4.0.0, core_profiles+equilibrium ] else: # Local / ITER infrastructure: use internal IMAS data sources directly From d09c3bbaab54fbae17aff33a22321101dd6a8552 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Fri, 27 Feb 2026 11:55:55 +0100 Subject: [PATCH 07/37] fix: resolve ASV CI issues with permissions, branch resolution and test data --- .github/workflows/asv.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/asv.yml b/.github/workflows/asv.yml index aaf299fc..414b1a02 100644 --- a/.github/workflows/asv.yml +++ b/.github/workflows/asv.yml @@ -12,6 +12,7 @@ jobs: runs-on: ubuntu-22.04 permissions: pull-requests: write # needed to post PR comments + issues: write # PR comments use the Issues API (createComment endpoint) steps: - name: Checkout code @@ -145,6 +146,10 @@ jobs: - name: Generate HTML results if: always() run: | + # asv publish resolves branch names from asv.conf.json via git rev-list. + # On PR checkouts only the PR branch is a local ref — fetch develop/main + # so git can resolve them; ignore errors if a branch doesn't exist yet. + git fetch origin develop main 2>/dev/null || true asv publish - name: Upload benchmark results From c4f46381c05e38f71fa4a31662ce32269c656931 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Fri, 27 Feb 2026 12:01:29 +0100 Subject: [PATCH 08/37] fix: use profiles_1d[:] instead of [0:100] in benchmark paths DD4 netCDF file has only 1 time slice; IBEX iterates [0:100] via __getitem__ and raises IndexError at index 1. Use [:] (all elements) which IBEX handles correctly, consistent with how equilibrium [:] works. --- benchmarks/endpoints_data.py | 4 +- scripts/test_netcdf_paths.py | 133 +++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 scripts/test_netcdf_paths.py diff --git a/benchmarks/endpoints_data.py b/benchmarks/endpoints_data.py index 9b87c7cb..6f2bfb17 100644 --- a/benchmarks/endpoints_data.py +++ b/benchmarks/endpoints_data.py @@ -21,7 +21,7 @@ def time_field_value(self, uri, node_path): [ "#core_profiles:0/time", # LEAF "#core_profiles:0/profiles_1d[0]/t_i_average", # LEAF IN AoS, - "#core_profiles:0/profiles_1d[0:100]/t_i_average", # LEAF IN AoS SLICE, + "#core_profiles:0/profiles_1d[:]/t_i_average", # LEAF IN AoS SLICE, "#equilibrium:0/time_slice[:]/profiles_2d[:]/psi", # 2D QUANTITY, ], ) @@ -36,7 +36,7 @@ def time_plot_data(self, uri, node_path): [ "#core_profiles:0/time", # LEAF "#core_profiles:0/profiles_1d[0]/t_i_average", # LEAF IN AoS, - "#core_profiles:0/profiles_1d[0:100]/t_i_average", # LEAF IN AoS SLICE, + "#core_profiles:0/profiles_1d[:]/t_i_average", # LEAF IN AoS SLICE, "#equilibrium:0/time_slice[:]/profiles_2d[:]/psi", # 2D QUANTITY, ], ) diff --git a/scripts/test_netcdf_paths.py b/scripts/test_netcdf_paths.py new file mode 100644 index 00000000..6944288c --- /dev/null +++ b/scripts/test_netcdf_paths.py @@ -0,0 +1,133 @@ +""" +Smoke-test script: verifies that all node paths used in IBEX benchmarks +are accessible in the Zenodo netCDF file. + +Uses iter_scenario_53298_seq1_DD4.nc — a JINTRAC core-edge simulation +containing core_profiles + equilibrium (required by all benchmark paths). + +Note: iter_scenario_123364_1.nc is a SOLPS edge simulation. It contains +only edge_profiles/edge_transport/etc. and has NO core_profiles or +equilibrium, so it cannot be used for the current benchmark node paths. + +Usage: + python scripts/test_netcdf_paths.py [path/to/file.nc] + +Defaults to test_data/iter_scenario_53298_seq1_DD4.nc relative to repo root. +""" + +import sys +from pathlib import Path + +import numpy as np +import imas + +# --------------------------------------------------------------------------- +# Resolve file path +# --------------------------------------------------------------------------- +_repo_root = Path(__file__).parent.parent +_default_nc = _repo_root / "test_data" / "iter_scenario_53298_seq1_DD4.nc" +NC_FILE = Path(sys.argv[1]) if len(sys.argv) > 1 else _default_nc + +if not NC_FILE.exists(): + sys.exit( + f"ERROR: file not found: {NC_FILE}\n" + "Download it with:\n" + " wget -O test_data/iter_scenario_53298_seq1_DD4.nc \\\n" + ' "https://zenodo.org/records/17062700/files/iter_scenario_53298_seq1_DD4.nc?download=1"' + ) + +print(f"Opening: {NC_FILE}\n") + + +# --------------------------------------------------------------------------- +# Helper — print result of accessing a node +# --------------------------------------------------------------------------- +def check(label: str, fn): + try: + node = fn() + if isinstance(node, np.ndarray): # numpy array (leaf data) + desc = f"array shape={node.shape} dtype={node.dtype}" + elif hasattr(node, "__len__") and not isinstance(node, str): # AoS / list + desc = f"{type(node).__name__} len={len(node)}" + else: + desc = f"{type(node).__name__} = {node!r}" + print(f" ✅ {label}") + print(f" result: {desc}") + except Exception as exc: + print(f" ❌ {label}") + print(f" error : {exc}") + print() + + +# --------------------------------------------------------------------------- +# Open file and run checks +# --------------------------------------------------------------------------- +with imas.DBEntry(str(NC_FILE), "r") as entry: + + # ---- core_profiles -------------------------------------------------------- + print("=" * 60) + print("IDS: core_profiles (occurrence 0)") + print("=" * 60) + cp = entry.get("core_profiles") + + # Used in: endpoints_ids_info — time_node_info params + check("IDS_BASE — core_profiles root (the IDS object itself)", + lambda: cp) + + check("STRUCTURE — ids_properties", + lambda: cp.ids_properties) + + # Note: returns 'N/A' (empty string) in this file — no error raised + check("LEAF — ids_properties/version_put/access_layer", + lambda: cp.ids_properties.version_put.access_layer) + + check("AoS — profiles_1d [len=1, single time-slice file]", + lambda: cp.profiles_1d) + + check("AoS elem — profiles_1d[0]", + lambda: cp.profiles_1d[0]) + + check("LEAF — profiles_1d[0]/t_i_average", + lambda: cp.profiles_1d[0].t_i_average) + + # Used in: endpoints_data — time_field_value / time_plot_data + check("LEAF — time", + lambda: cp.time) + + # IBEX handles [:] slice notation by iterating all available elements. + # This file has 1 time slice so profiles_1d[:] yields [profiles_1d[0]]. + # NOTE: [0:100] would cause IndexError if IBEX iterates indices 0..99 via + # __getitem__ and the array has fewer than 100 elements — use [:] instead. + check("LEAF IN AoS SLICE — profiles_1d[:]/t_i_average [all slices]", + lambda: [p.t_i_average for p in list(cp.profiles_1d)[:]]) + + # ---- equilibrium ---------------------------------------------------------- + print("=" * 60) + print("IDS: equilibrium (occurrence 0)") + print("=" * 60) + eq = entry.get("equilibrium") + + check("time_slice len", + lambda: eq.time_slice) + + check("time_slice[0]/profiles_2d len", + lambda: eq.time_slice[0].profiles_2d) + + # Used in: endpoints_data — 2D QUANTITY + # IBEX's path parser handles [:] internally; in IMAS-Python we iterate. + check("2D QUANTITY — time_slice[0]/profiles_2d[0]/psi", + lambda: eq.time_slice[0].profiles_2d[0].psi) + + check("2D QUANTITY — all psi arrays via [:] iteration", + lambda: [p.psi for ts in list(eq.time_slice)[:] + for p in list(ts.profiles_2d)[:]]) + + +print("=" * 60) +print("SUMMARY") +print("=" * 60) +print("File IDSes confirmed present: core_profiles, equilibrium") +print("All benchmark node paths are accessible in this file.") +print() +print("NOTE: iter_scenario_123364_1.nc (SOLPS edge sim) does NOT contain") +print("core_profiles or equilibrium — use DD4 file for these benchmarks.") From c7f23c7c1c86166b21628b9882885b6cafcd7f18 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Fri, 27 Feb 2026 12:06:32 +0100 Subject: [PATCH 09/37] fix: create local branches for asv publish using fetch refspec syntax --- .github/workflows/asv.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/asv.yml b/.github/workflows/asv.yml index 414b1a02..ead8b579 100644 --- a/.github/workflows/asv.yml +++ b/.github/workflows/asv.yml @@ -147,9 +147,12 @@ jobs: if: always() run: | # asv publish resolves branch names from asv.conf.json via git rev-list. - # On PR checkouts only the PR branch is a local ref — fetch develop/main - # so git can resolve them; ignore errors if a branch doesn't exist yet. - git fetch origin develop main 2>/dev/null || true + # On PR checkouts only the PR branch is a local ref. Using + # refspec : creates local branches directly so that + # git rev-list develop / main succeeds (plain fetch only makes + # remotes/origin/develop which asv does not resolve). + git fetch origin develop:develop 2>/dev/null || true + git fetch origin main:main 2>/dev/null || true asv publish - name: Upload benchmark results From ae3fdbe9c91d5480d71999fb50f83632745d0009 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Fri, 27 Feb 2026 12:36:14 +0100 Subject: [PATCH 10/37] do not update PR --- .github/workflows/asv.yml | 111 +++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 54 deletions(-) diff --git a/.github/workflows/asv.yml b/.github/workflows/asv.yml index ead8b579..28576e80 100644 --- a/.github/workflows/asv.yml +++ b/.github/workflows/asv.yml @@ -11,8 +11,7 @@ jobs: benchmark: runs-on: ubuntu-22.04 permissions: - pull-requests: write # needed to post PR comments - issues: write # PR comments use the Issues API (createComment endpoint) + contents: write # needed to push HTML report to gh-pages branch steps: - name: Checkout code @@ -87,55 +86,52 @@ jobs: CONTENDER="HEAD" fi - echo "Comparing ${BASELINE}...${CONTENDER}" + # Resolve to full SHAs for clarity in the log + BASELINE_SHA=$(git rev-parse "${BASELINE}" 2>/dev/null || echo "${BASELINE}") + CONTENDER_SHA=$(git rev-parse "${CONTENDER}" 2>/dev/null || echo "${CONTENDER}") + echo "Comparing commits:" + echo " BASELINE : ${BASELINE} → ${BASELINE_SHA}" + echo " CONTENDER : ${CONTENDER} → ${CONTENDER_SHA}" + # --factor 2.0: only flag as regression if a benchmark is >2x slower # (filters out GitHub runner hardware noise, ~20-50% typical variance) - asv continuous --quick --show-stderr --factor 2.0 "${BASELINE}" "${CONTENDER}" \ + asv continuous --quick --show-stderr --factor 2.0 "${BASELINE_SHA}" "${CONTENDER_SHA}" \ 2>&1 | tee asv_output.txt - - name: Post benchmark results to PR - if: github.event_name == 'pull_request' - uses: actions/github-script@v7 - with: - script: | - const fs = require('fs'); - const output = fs.existsSync('asv_output.txt') - ? fs.readFileSync('asv_output.txt', 'utf8').trim() - : '_No output captured — benchmark step crashed before producing output._'; - - const outcome = '${{ steps.asv.outcome }}'; - const icon = outcome === 'failure' ? '🔴' : '✅'; - const title = outcome === 'failure' - ? '**Performance regression detected (>2x slower on at least one benchmark)**' - : '**No significant performance regressions detected**'; - const body = `## ${icon} ASV Benchmark Results\n${title}\n\n` - + `
Full output\n\n\`\`\`\n${output}\n\`\`\`\n
`; - - // Update existing bot comment if present, otherwise create a new one. - // This avoids comment spam when multiple commits are pushed to the same PR. - const { data: comments } = await github.rest.issues.listComments({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - }); - const botComment = comments.find(c => - c.user.type === 'Bot' && c.body.includes('ASV Benchmark Results') - ); - if (botComment) { - await github.rest.issues.updateComment({ - comment_id: botComment.id, - owner: context.repo.owner, - repo: context.repo.repo, - body: body, - }); - } else { - await github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: body, - }); - } + - name: Print benchmark results to log + # Always print to the job log and GitHub Actions job summary. + # For fork PRs (where write access is blocked) this is the only place + # results are visible — open the Actions run to see them. + if: always() + run: | + OUTPUT=$(cat asv_output.txt 2>/dev/null || echo "(no output captured)") + OUTCOME="${{ steps.asv.outcome }}" + if [ "${OUTCOME}" = "failure" ]; then + ICON="❌" + TITLE="Performance regression detected (>2x slower on at least one benchmark)" + else + ICON="✅" + TITLE="No significant performance regressions detected" + fi + echo "" + echo "======================================================" + echo " ${ICON} ASV Benchmark Results — ${TITLE}" + echo "======================================================" + echo "${OUTPUT}" + echo "" + # Also write to GitHub Actions job summary (visible in the Actions UI + # for all runs, including fork PRs, without any write permissions). + { + echo "## ${ICON} ASV Benchmark Results" + echo "**${TITLE}**" + echo "" + echo "
Full output" + echo "" + echo '```' + echo "${OUTPUT}" + echo '```' + echo "
" + } >> "${GITHUB_STEP_SUMMARY}" - name: Fail job if regression detected if: steps.asv.outcome == 'failure' @@ -155,11 +151,18 @@ jobs: git fetch origin main:main 2>/dev/null || true asv publish - - name: Upload benchmark results - if: always() - uses: actions/upload-artifact@v4 + - name: Deploy HTML report to GitHub Pages + # Pushes .asv/html/ to the gh-pages branch so the report is browsable at + # https://.github.io/IBEX/ + # Skipped for fork PRs: they cannot push to the upstream repo. + if: > + always() && ( + github.event_name != 'pull_request' || + github.event.pull_request.head.repo.full_name == github.repository + ) + uses: peaceiris/actions-gh-pages@v3 with: - name: asv-results - path: .asv/html/ - retention-days: 30 - if-no-files-found: warn + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: .asv/html + destination_dir: benchmarks + keep_files: false From 1970b0e39ce185fc0fd360e5398f82573e581be8 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Fri, 27 Feb 2026 12:55:17 +0100 Subject: [PATCH 11/37] show --split log --- .github/workflows/asv.yml | 37 ++++--------------------------------- 1 file changed, 4 insertions(+), 33 deletions(-) diff --git a/.github/workflows/asv.yml b/.github/workflows/asv.yml index 28576e80..5fb30d9a 100644 --- a/.github/workflows/asv.yml +++ b/.github/workflows/asv.yml @@ -98,40 +98,11 @@ jobs: asv continuous --quick --show-stderr --factor 2.0 "${BASELINE_SHA}" "${CONTENDER_SHA}" \ 2>&1 | tee asv_output.txt - - name: Print benchmark results to log - # Always print to the job log and GitHub Actions job summary. - # For fork PRs (where write access is blocked) this is the only place - # results are visible — open the Actions run to see them. - if: always() - run: | - OUTPUT=$(cat asv_output.txt 2>/dev/null || echo "(no output captured)") - OUTCOME="${{ steps.asv.outcome }}" - if [ "${OUTCOME}" = "failure" ]; then - ICON="❌" - TITLE="Performance regression detected (>2x slower on at least one benchmark)" - else - ICON="✅" - TITLE="No significant performance regressions detected" - fi - echo "" - echo "======================================================" - echo " ${ICON} ASV Benchmark Results — ${TITLE}" - echo "======================================================" - echo "${OUTPUT}" + # Print a direct before/after comparison table (ratio per benchmark). + # This makes it easy to see which benchmarks changed and by how much. echo "" - # Also write to GitHub Actions job summary (visible in the Actions UI - # for all runs, including fork PRs, without any write permissions). - { - echo "## ${ICON} ASV Benchmark Results" - echo "**${TITLE}**" - echo "" - echo "
Full output" - echo "" - echo '```' - echo "${OUTPUT}" - echo '```' - echo "
" - } >> "${GITHUB_STEP_SUMMARY}" + echo "=== Before vs After comparison ===" + asv compare --factor 2.0 --split "${BASELINE_SHA}" "${CONTENDER_SHA}" 2>&1 | tee -a asv_output.txt - name: Fail job if regression detected if: steps.asv.outcome == 'failure' From e801b74448093cd27eaa57535e63b6aadd314040 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Fri, 27 Feb 2026 13:00:12 +0100 Subject: [PATCH 12/37] deploy only on pull request --- .github/workflows/asv.yml | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/.github/workflows/asv.yml b/.github/workflows/asv.yml index 5fb30d9a..051f4565 100644 --- a/.github/workflows/asv.yml +++ b/.github/workflows/asv.yml @@ -107,11 +107,14 @@ jobs: - name: Fail job if regression detected if: steps.asv.outcome == 'failure' run: | - echo "❌ Performance regression detected (>2x threshold). See benchmark output above." + echo "FAILED: Performance regression detected (>2x threshold). See benchmark output above." exit 1 - name: Generate HTML results - if: always() + # Only meaningful on push to develop/main — asv publish builds the branch + # timeline, so PR commits (not yet on any branch) are simply skipped with + # "Couldn't find in branches". Run only after a merge to avoid noise. + if: github.event_name != 'pull_request' run: | # asv publish resolves branch names from asv.conf.json via git rev-list. # On PR checkouts only the PR branch is a local ref. Using @@ -123,14 +126,8 @@ jobs: asv publish - name: Deploy HTML report to GitHub Pages - # Pushes .asv/html/ to the gh-pages branch so the report is browsable at - # https://.github.io/IBEX/ - # Skipped for fork PRs: they cannot push to the upstream repo. - if: > - always() && ( - github.event_name != 'pull_request' || - github.event.pull_request.head.repo.full_name == github.repository - ) + # Only run on push to develop/main, same reasoning as Generate HTML above. + if: github.event_name != 'pull_request' uses: peaceiris/actions-gh-pages@v3 with: github_token: ${{ secrets.GITHUB_TOKEN }} From 4763d863de5bbeea23e035d2bacc76a595e25d04 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Fri, 27 Feb 2026 14:13:07 +0100 Subject: [PATCH 13/37] removed test script --- scripts/test_netcdf_paths.py | 133 ----------------------------------- 1 file changed, 133 deletions(-) delete mode 100644 scripts/test_netcdf_paths.py diff --git a/scripts/test_netcdf_paths.py b/scripts/test_netcdf_paths.py deleted file mode 100644 index 6944288c..00000000 --- a/scripts/test_netcdf_paths.py +++ /dev/null @@ -1,133 +0,0 @@ -""" -Smoke-test script: verifies that all node paths used in IBEX benchmarks -are accessible in the Zenodo netCDF file. - -Uses iter_scenario_53298_seq1_DD4.nc — a JINTRAC core-edge simulation -containing core_profiles + equilibrium (required by all benchmark paths). - -Note: iter_scenario_123364_1.nc is a SOLPS edge simulation. It contains -only edge_profiles/edge_transport/etc. and has NO core_profiles or -equilibrium, so it cannot be used for the current benchmark node paths. - -Usage: - python scripts/test_netcdf_paths.py [path/to/file.nc] - -Defaults to test_data/iter_scenario_53298_seq1_DD4.nc relative to repo root. -""" - -import sys -from pathlib import Path - -import numpy as np -import imas - -# --------------------------------------------------------------------------- -# Resolve file path -# --------------------------------------------------------------------------- -_repo_root = Path(__file__).parent.parent -_default_nc = _repo_root / "test_data" / "iter_scenario_53298_seq1_DD4.nc" -NC_FILE = Path(sys.argv[1]) if len(sys.argv) > 1 else _default_nc - -if not NC_FILE.exists(): - sys.exit( - f"ERROR: file not found: {NC_FILE}\n" - "Download it with:\n" - " wget -O test_data/iter_scenario_53298_seq1_DD4.nc \\\n" - ' "https://zenodo.org/records/17062700/files/iter_scenario_53298_seq1_DD4.nc?download=1"' - ) - -print(f"Opening: {NC_FILE}\n") - - -# --------------------------------------------------------------------------- -# Helper — print result of accessing a node -# --------------------------------------------------------------------------- -def check(label: str, fn): - try: - node = fn() - if isinstance(node, np.ndarray): # numpy array (leaf data) - desc = f"array shape={node.shape} dtype={node.dtype}" - elif hasattr(node, "__len__") and not isinstance(node, str): # AoS / list - desc = f"{type(node).__name__} len={len(node)}" - else: - desc = f"{type(node).__name__} = {node!r}" - print(f" ✅ {label}") - print(f" result: {desc}") - except Exception as exc: - print(f" ❌ {label}") - print(f" error : {exc}") - print() - - -# --------------------------------------------------------------------------- -# Open file and run checks -# --------------------------------------------------------------------------- -with imas.DBEntry(str(NC_FILE), "r") as entry: - - # ---- core_profiles -------------------------------------------------------- - print("=" * 60) - print("IDS: core_profiles (occurrence 0)") - print("=" * 60) - cp = entry.get("core_profiles") - - # Used in: endpoints_ids_info — time_node_info params - check("IDS_BASE — core_profiles root (the IDS object itself)", - lambda: cp) - - check("STRUCTURE — ids_properties", - lambda: cp.ids_properties) - - # Note: returns 'N/A' (empty string) in this file — no error raised - check("LEAF — ids_properties/version_put/access_layer", - lambda: cp.ids_properties.version_put.access_layer) - - check("AoS — profiles_1d [len=1, single time-slice file]", - lambda: cp.profiles_1d) - - check("AoS elem — profiles_1d[0]", - lambda: cp.profiles_1d[0]) - - check("LEAF — profiles_1d[0]/t_i_average", - lambda: cp.profiles_1d[0].t_i_average) - - # Used in: endpoints_data — time_field_value / time_plot_data - check("LEAF — time", - lambda: cp.time) - - # IBEX handles [:] slice notation by iterating all available elements. - # This file has 1 time slice so profiles_1d[:] yields [profiles_1d[0]]. - # NOTE: [0:100] would cause IndexError if IBEX iterates indices 0..99 via - # __getitem__ and the array has fewer than 100 elements — use [:] instead. - check("LEAF IN AoS SLICE — profiles_1d[:]/t_i_average [all slices]", - lambda: [p.t_i_average for p in list(cp.profiles_1d)[:]]) - - # ---- equilibrium ---------------------------------------------------------- - print("=" * 60) - print("IDS: equilibrium (occurrence 0)") - print("=" * 60) - eq = entry.get("equilibrium") - - check("time_slice len", - lambda: eq.time_slice) - - check("time_slice[0]/profiles_2d len", - lambda: eq.time_slice[0].profiles_2d) - - # Used in: endpoints_data — 2D QUANTITY - # IBEX's path parser handles [:] internally; in IMAS-Python we iterate. - check("2D QUANTITY — time_slice[0]/profiles_2d[0]/psi", - lambda: eq.time_slice[0].profiles_2d[0].psi) - - check("2D QUANTITY — all psi arrays via [:] iteration", - lambda: [p.psi for ts in list(eq.time_slice)[:] - for p in list(ts.profiles_2d)[:]]) - - -print("=" * 60) -print("SUMMARY") -print("=" * 60) -print("File IDSes confirmed present: core_profiles, equilibrium") -print("All benchmark node paths are accessible in this file.") -print() -print("NOTE: iter_scenario_123364_1.nc (SOLPS edge sim) does NOT contain") -print("core_profiles or equilibrium — use DD4 file for these benchmarks.") From fd7bb373f0b19bab9dc97f027c897dcb1a052f4a Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Fri, 27 Feb 2026 14:37:05 +0100 Subject: [PATCH 14/37] fix: bamboo upstream branches for benchmarks --- backend/ci/run_benchmarks.sh | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/backend/ci/run_benchmarks.sh b/backend/ci/run_benchmarks.sh index 4a55c7ac..85139688 100755 --- a/backend/ci/run_benchmarks.sh +++ b/backend/ci/run_benchmarks.sh @@ -1,13 +1,19 @@ #!/bin/bash -# Bamboo CI script for linting +# Bamboo CI script for benchmarks +set -euo pipefail -# Fetch develop and main for `ASV compare` -git fetch origin develop -git fetch origin main +# Always fetch develop/main from the canonical upstream repo, not from origin +UPSTREAM="https://github.com/iterorganization/IBEX" +git remote remove upstream 2>/dev/null || true +git remote add upstream "${UPSTREAM}" +git fetch upstream -# Debuggging: -set -e -o pipefail +git checkout -B develop upstream/develop +git checkout -B main upstream/main + +# Go back to the triggering branch +git checkout ${bamboo.planRepository.branch} # Set up environment s BACKEND_ROOT_DIR=$(realpath "$(dirname "$(realpath "${BASH_SOURCE[0]}")")/..") @@ -47,8 +53,8 @@ asv run --skip-existing-successful develop^! asv run --skip-existing-successful main^! # Compare results -if [ `git rev-parse --abbrev-ref HEAD` == develop ] -then +CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) +if [ "${CURRENT_BRANCH}" = "develop" ]; then asv compare main develop --machine $(hostname) || echo "asv compare failed" else asv compare develop HEAD --machine $(hostname) || echo "asv compare failed" From 1fca973a0f6940bdba0bc49b218a059af4fe2900 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Fri, 27 Feb 2026 14:46:39 +0100 Subject: [PATCH 15/37] fix: bamboo_planRepository_branch --- backend/ci/run_benchmarks.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/ci/run_benchmarks.sh b/backend/ci/run_benchmarks.sh index 85139688..8f70720e 100755 --- a/backend/ci/run_benchmarks.sh +++ b/backend/ci/run_benchmarks.sh @@ -13,7 +13,7 @@ git checkout -B develop upstream/develop git checkout -B main upstream/main # Go back to the triggering branch -git checkout ${bamboo.planRepository.branch} +git checkout "${bamboo_planRepository_branch}" # Set up environment s BACKEND_ROOT_DIR=$(realpath "$(dirname "$(realpath "${BASH_SOURCE[0]}")")/..") From ec2aa0b279022004a484c6883e0b9386308907c8 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Fri, 27 Feb 2026 14:53:40 +0100 Subject: [PATCH 16/37] fix set script variables --- backend/ci/run_benchmarks.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/ci/run_benchmarks.sh b/backend/ci/run_benchmarks.sh index 8f70720e..fc1b2504 100755 --- a/backend/ci/run_benchmarks.sh +++ b/backend/ci/run_benchmarks.sh @@ -1,7 +1,7 @@ #!/bin/bash # Bamboo CI script for benchmarks -set -euo pipefail +set -e -o pipefail # Always fetch develop/main from the canonical upstream repo, not from origin UPSTREAM="https://github.com/iterorganization/IBEX" @@ -21,7 +21,6 @@ source ${BACKEND_ROOT_DIR}/ci/configure_env.sh BENCHMARKS_DIR=$(realpath "$PWD/ibex_benchmarks") if [[ "$(uname -n)" == *"bamboo"* ]]; then - set -e -o pipefail # create BENCHMARKS_DIR=$(realpath "/mnt/bamboo_deploy/ibex/benchmarks/") fi From 0a21855f09f2d38eb2d0e12d6919f31210eb8bd5 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Fri, 27 Feb 2026 15:06:27 +0100 Subject: [PATCH 17/37] fix for spdx --- asv.conf.json | 12 ++++++++---- backend/pyproject.toml | 4 ++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/asv.conf.json b/asv.conf.json index 349fe3e9..492cb9e3 100644 --- a/asv.conf.json +++ b/asv.conf.json @@ -20,11 +20,15 @@ // Customizable commands for building the project. // See asv.conf.json documentation. - // To build the package using pyproject.toml (PEP518), uncomment the following lines + // --no-isolation: skip creating a fresh /tmp/build-env-xxx virtualenv. + // On ITER/EasyBuild infrastructure, that isolated venv uses the EasyBuild + // Python's stdlib importlib.metadata which discovers pbr from EasyBuild + // site-packages; pbr then fails with "No module named pkg_resources". + // Running without isolation uses ASV's own clean virtualenv instead. + // build_requirements below ensures setuptools_scm and wheel are present. "build_command": [ - "python -m pip install build", - "python -m build --wheel -o {build_cache_dir} {build_dir}", - //"python -m pip wheel --no-deps -w {build_cache_dir} {build_dir}" + "python -m pip install build setuptools>=61 setuptools_scm[toml]>=6.2 wheel", + "python -m build --no-isolation --wheel -o {build_cache_dir} {build_dir}" ], // Customizable commands for installing and uninstalling the project. // See asv.conf.json documentation. diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 6b70335c..cfce0361 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -13,6 +13,7 @@ authors = [ description = "Data visualization for IMAS IDS data" readme = {file = "README.md", content-type = "text/markdown"} requires-python = ">=3.7" +license = "LGPL-3.0-only" license-files = ["LICENSE.txt"] classifiers = [ "Development Status :: 3 - Alpha", @@ -39,8 +40,7 @@ classifiers = [ "Topic :: Scientific/Engineering", "Topic :: Scientific/Engineering :: Physics", "Topic :: Software Development :: Libraries", - "Topic :: Software Development :: Libraries :: Python Modules", - "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)" + "Topic :: Software Development :: Libraries :: Python Modules" ] dynamic = ["version"] dependencies = [ From bb4d0158243e379a24f635198026d89c32852ce1 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Fri, 27 Feb 2026 15:16:38 +0100 Subject: [PATCH 18/37] fix toml --- backend/pyproject.toml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/backend/pyproject.toml b/backend/pyproject.toml index cfce0361..63bd6226 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -13,8 +13,7 @@ authors = [ description = "Data visualization for IMAS IDS data" readme = {file = "README.md", content-type = "text/markdown"} requires-python = ">=3.7" -license = "LGPL-3.0-only" -license-files = ["LICENSE.txt"] +license = {text = "LGPL-3.0-only"} classifiers = [ "Development Status :: 3 - Alpha", "Environment :: Console", @@ -84,6 +83,10 @@ benchmark = [ [project.urls] homepage = "https://github.com/iterorganization/IBEX" +[tool.setuptools] +# license-files must be here, not in [project], for setuptools <77 compatibility +license-files = ["LICENSE.txt"] + [tool.setuptools.packages.find] where = ["."] include = ["ibex*"] From 8cbdab9daf1b378f9cd7f8e0f887384db8c1ff2e Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Fri, 27 Feb 2026 15:55:19 +0100 Subject: [PATCH 19/37] fix forbuild command for main branch --- asv.conf.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asv.conf.json b/asv.conf.json index 492cb9e3..7c099cfe 100644 --- a/asv.conf.json +++ b/asv.conf.json @@ -27,7 +27,7 @@ // Running without isolation uses ASV's own clean virtualenv instead. // build_requirements below ensures setuptools_scm and wheel are present. "build_command": [ - "python -m pip install build setuptools>=61 setuptools_scm[toml]>=6.2 wheel", + "python -m pip install 'setuptools>=77' build wheel 'setuptools_scm[toml]>=6.2'", "python -m build --no-isolation --wheel -o {build_cache_dir} {build_dir}" ], // Customizable commands for installing and uninstalling the project. From a6d9be5ccac2a9ec8809f4fc162dcbc04ea9a2c6 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Fri, 27 Feb 2026 16:10:19 +0100 Subject: [PATCH 20/37] fix: install pbr in ASV venv to shadow EasyBuild's pbr and fix pkg_resources error --- asv.conf.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/asv.conf.json b/asv.conf.json index 7c099cfe..c5ad9470 100644 --- a/asv.conf.json +++ b/asv.conf.json @@ -25,9 +25,11 @@ // Python's stdlib importlib.metadata which discovers pbr from EasyBuild // site-packages; pbr then fails with "No module named pkg_resources". // Running without isolation uses ASV's own clean virtualenv instead. + // pbr is installed explicitly so the venv's pbr (which has pkg_resources + // via setuptools) takes precedence over EasyBuild's pbr in sys.path. // build_requirements below ensures setuptools_scm and wheel are present. "build_command": [ - "python -m pip install 'setuptools>=77' build wheel 'setuptools_scm[toml]>=6.2'", + "python -m pip install 'setuptools>=77' pbr build wheel 'setuptools_scm[toml]>=6.2'", "python -m build --no-isolation --wheel -o {build_cache_dir} {build_dir}" ], // Customizable commands for installing and uninstalling the project. From ba9a7239d23b8ebdaa5901bd5b06e0d0e369ec70 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Fri, 27 Feb 2026 16:45:58 +0100 Subject: [PATCH 21/37] fixed ci script and reverted asv config --- asv.conf.json | 15 +++++---------- backend/ci/configure_env.sh | 3 ++- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/asv.conf.json b/asv.conf.json index c5ad9470..3ce75734 100644 --- a/asv.conf.json +++ b/asv.conf.json @@ -20,17 +20,12 @@ // Customizable commands for building the project. // See asv.conf.json documentation. - // --no-isolation: skip creating a fresh /tmp/build-env-xxx virtualenv. - // On ITER/EasyBuild infrastructure, that isolated venv uses the EasyBuild - // Python's stdlib importlib.metadata which discovers pbr from EasyBuild - // site-packages; pbr then fails with "No module named pkg_resources". - // Running without isolation uses ASV's own clean virtualenv instead. - // pbr is installed explicitly so the venv's pbr (which has pkg_resources - // via setuptools) takes precedence over EasyBuild's pbr in sys.path. - // build_requirements below ensures setuptools_scm and wheel are present. + // To build the package using pyproject.toml (PEP518), uncomment the following lines "build_command": [ - "python -m pip install 'setuptools>=77' pbr build wheel 'setuptools_scm[toml]>=6.2'", - "python -m build --no-isolation --wheel -o {build_cache_dir} {build_dir}" + "python -m pip install build", + "python -m build", + "python -m build --wheel -o {build_cache_dir} {build_dir}", + //"python -m pip wheel --no-deps -w {build_cache_dir} {build_dir}" ], // Customizable commands for installing and uninstalling the project. // See asv.conf.json documentation. diff --git a/backend/ci/configure_env.sh b/backend/ci/configure_env.sh index cfb1cae5..c78fe4cc 100755 --- a/backend/ci/configure_env.sh +++ b/backend/ci/configure_env.sh @@ -7,7 +7,8 @@ source /etc/profile.d/modules.sh module purge # Set up environment -module load IDStools/2.1.0-intel-2023b IMAS-Python/2.0.0-intel-2023b +module load IDStools/2.4.0-intel-2023b +module unload Python-bundle-PyPI # Debuggging: echo "Done loading modules" From fe91a604bd1d5ac588b5554d66087894b94609c3 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Mon, 2 Mar 2026 11:56:41 +0100 Subject: [PATCH 22/37] pinned documentation requirements --- backend/ci/build_docs.sh | 3 +-- backend/pyproject.toml | 4 ++-- docs/requirements.txt | 8 ++++++++ 3 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 docs/requirements.txt diff --git a/backend/ci/build_docs.sh b/backend/ci/build_docs.sh index a711c6b4..8a546455 100755 --- a/backend/ci/build_docs.sh +++ b/backend/ci/build_docs.sh @@ -19,8 +19,7 @@ python -m venv venv echo "PWD: " `pwd` # PREPARE THE ENVIRONMENT -pip install --upgrade pip setuptools wheel build pytest-cov -pip install --upgrade sphinx sphinx-autosummary-accessors sphinx_immaterial +pip install --upgrade -r ../docs/requirements.txt pip install --upgrade .[docs] # RUN PYTEST diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 63bd6226..55c2ae3e 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -71,8 +71,8 @@ linting = [ ] docs =[ - "sphinx", - "sphinx-autosummary-accessors", + "sphinx>=7,<9", + "sphinx-autosummary-accessors==2025.3.1", "sphinx_immaterial", ] diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 00000000..e6c75cf7 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,8 @@ +pip +setuptools +wheel +build +pytest-cov +sphinx>=7,<9 +sphinx_immaterial +sphinx-autosummary-accessors==2025.3.1 From 51f0ce9abc9d165cd1728868ab0a8d0b94e79af0 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Mon, 2 Mar 2026 13:27:35 +0100 Subject: [PATCH 23/37] fix pytest --- backend/ci/run_pytest.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/ci/run_pytest.sh b/backend/ci/run_pytest.sh index 916b3e88..1b7be6bb 100755 --- a/backend/ci/run_pytest.sh +++ b/backend/ci/run_pytest.sh @@ -19,8 +19,8 @@ python -m venv venv echo "PWD: " `pwd` # PREPARE THE ENVIRONMENT -pip install --upgrade pip setuptools wheel pytest-cov +pip install --upgrade pip setuptools wheel pytest-cov pytest-xdist pip install --upgrade . # RUN PYTEST -python -m pytest -n=auto --cov=ibex --cov-report=term-missing --cov-report=html --junit-xml=test-reports/pytest-report.xml ${BACKEND_ROOT_DIR}/tests \ No newline at end of file +python -m pytest -n auto --cov=ibex --cov-report=term-missing --cov-report=html --junit-xml=test-reports/pytest-report.xml ${BACKEND_ROOT_DIR}/tests \ No newline at end of file From 47fa3823c2dc3a1a59dc6345a8c7e497a11efda1 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Mon, 2 Mar 2026 15:34:44 +0100 Subject: [PATCH 24/37] fix e2e test --- frontend/ci/configure-env.sh | 2 ++ frontend/ci/run-e2e-test.sh | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/frontend/ci/configure-env.sh b/frontend/ci/configure-env.sh index acb619c0..77483e16 100755 --- a/frontend/ci/configure-env.sh +++ b/frontend/ci/configure-env.sh @@ -8,6 +8,8 @@ module purge # Set up environment module load nodejs +module load Python +module load IDStools/2.4.0-intel-2023b # Debuggging: echo "Done loading modules" diff --git a/frontend/ci/run-e2e-test.sh b/frontend/ci/run-e2e-test.sh index 9e84bcf0..2d102245 100755 --- a/frontend/ci/run-e2e-test.sh +++ b/frontend/ci/run-e2e-test.sh @@ -1,11 +1,28 @@ #!/bin/bash # Script to run E2E tests +FRONTEND_ROOT_DIR=$(realpath "$(dirname "$(realpath "${BASH_SOURCE[0]}")")/..") + +BACKEND_ROOT_DIR=$(realpath "$(dirname "$(realpath "${BASH_SOURCE[0]}")")/../../backend") + +echo "FRONTEND_ROOT_DIR: ${FRONTEND_ROOT_DIR}" +echo "BACKEND_ROOT_DIR: ${BACKEND_ROOT_DIR}" # Root directory of the frontend -FRONTEND_ROOT_DIR=$(realpath "$(dirname "$(realpath "${BASH_SOURCE[0]}")")/..") source ${FRONTEND_ROOT_DIR}/ci/configure-env.sh +cd ${BACKEND_ROOT_DIR} +which python +python --version + +python -m venv venv +. venv/bin/activate +echo "PWD: " `pwd` + +# PREPARE THE ENVIRONMENT +pip install --upgrade pip setuptools wheel pytest-cov pytest-xdist +pip install --upgrade . + # Set up environment cd ${FRONTEND_ROOT_DIR} From 4504a645a5a28614cce8725caa369c7569494252 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Mon, 2 Mar 2026 15:54:01 +0100 Subject: [PATCH 25/37] fix cross-env: command not found issue --- frontend/ci/run-e2e-test.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/ci/run-e2e-test.sh b/frontend/ci/run-e2e-test.sh index 2d102245..d07a1ee5 100755 --- a/frontend/ci/run-e2e-test.sh +++ b/frontend/ci/run-e2e-test.sh @@ -26,6 +26,10 @@ pip install --upgrade . # Set up environment cd ${FRONTEND_ROOT_DIR} +# Install frontend dependencies (required for cross-env and other local binaries) +echo "Installing frontend npm dependencies..." +npm ci + # Start Electron app echo "Starting Electron app for E2E tests..." npm run start:e2e & From 121bb487ff9173c5bc9b282dce74f09aa464e250 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Mon, 2 Mar 2026 16:12:18 +0100 Subject: [PATCH 26/37] provide xvfb --- frontend/ci/run-e2e-test.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/frontend/ci/run-e2e-test.sh b/frontend/ci/run-e2e-test.sh index d07a1ee5..e899ab73 100755 --- a/frontend/ci/run-e2e-test.sh +++ b/frontend/ci/run-e2e-test.sh @@ -30,6 +30,13 @@ cd ${FRONTEND_ROOT_DIR} echo "Installing frontend npm dependencies..." npm ci +# Start a virtual framebuffer so Electron can run headlessly in CI (no $DISPLAY) +echo "Starting Xvfb virtual display..." +Xvfb :99 -screen 0 1920x1080x24 & +XVFB_PID=$! +export DISPLAY=:99 +sleep 2 # give Xvfb time to initialise + # Start Electron app echo "Starting Electron app for E2E tests..." npm run start:e2e & @@ -65,6 +72,12 @@ else echo "App stopped successfully." fi +# Stop Xvfb virtual display +if [ -n "$XVFB_PID" ]; then + echo "Stopping Xvfb (PID $XVFB_PID)..." + kill $XVFB_PID || true +fi + if [ $TEST_RESULT -eq 0 ]; then echo "✅ E2E tests passed!" else From 741132e6a2dcef11dfce1878030ed94465dde2a1 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Mon, 2 Mar 2026 16:20:19 +0100 Subject: [PATCH 27/37] added xvfb --- frontend/ci/configure-env.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/ci/configure-env.sh b/frontend/ci/configure-env.sh index 77483e16..67314607 100755 --- a/frontend/ci/configure-env.sh +++ b/frontend/ci/configure-env.sh @@ -8,6 +8,7 @@ module purge # Set up environment module load nodejs +module load Xvfb/21.1.9-GCCcore-13.2.0 module load Python module load IDStools/2.4.0-intel-2023b From 46126ad0f48cdf2745a7665b4a590bd934492546 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Wed, 11 Mar 2026 17:31:29 +0100 Subject: [PATCH 28/37] added readthedocs --- .readthedocs.yaml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .readthedocs.yaml diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 00000000..6f7e3035 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,21 @@ +version: 2 + +build: + os: ubuntu-24.04 + tools: + python: "3.11" + jobs: + pre_build: + - cp LICENSE.txt LICENSE.md + +sphinx: + configuration: docs/source/conf.py + fail_on_warning: true + +python: + install: + - requirements: docs/requirements.txt + - method: pip + path: backend + extra_requirements: + - docs \ No newline at end of file From 9f2717c94c5c9cda1b051be651e1fe6d13fa5572 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Thu, 12 Mar 2026 09:07:29 +0100 Subject: [PATCH 29/37] fixed license file and warning --- .readthedocs.yaml | 3 --- backend/ibex/core/ibex_service.py | 1 - backend/ibex/endpoints/data.py | 3 +++ docs/source/index.rst | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 6f7e3035..59a3d18a 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -4,9 +4,6 @@ build: os: ubuntu-24.04 tools: python: "3.11" - jobs: - pre_build: - - cp LICENSE.txt LICENSE.md sphinx: configuration: docs/source/conf.py diff --git a/backend/ibex/core/ibex_service.py b/backend/ibex/core/ibex_service.py index 91e1a39e..b6233dd4 100644 --- a/backend/ibex/core/ibex_service.py +++ b/backend/ibex/core/ibex_service.py @@ -34,7 +34,6 @@ class IMAS_URI: def __init__(self, full_uri): """ IMAS_URI constructor - :param full_uri: pulsefile uri along with #fragment part """ self.full_uri = full_uri diff --git a/backend/ibex/endpoints/data.py b/backend/ibex/endpoints/data.py index 0cc0f8c4..a9e363bc 100644 --- a/backend/ibex/endpoints/data.py +++ b/backend/ibex/endpoints/data.py @@ -17,6 +17,9 @@ class CustomORJSONResponse(ORJSONResponse): Custom ORJSON serializer. Uses serializer from data_source to transform arbitrary types (e.g. IDSNumericArray) to ones supported by ORJSON serializer (e.g. np.array). """ + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + def render(self, content) -> bytes: return orjson.dumps( content, default=ibex_service.data_source.data_serializer_custom, option=orjson.OPT_SERIALIZE_NUMPY diff --git a/docs/source/index.rst b/docs/source/index.rst index 848cfe37..db2de683 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -34,5 +34,5 @@ Manual LICENSE ------- -.. literalinclude:: ../../LICENSE.md +.. literalinclude:: ../../LICENSE.txt :language: text \ No newline at end of file From efa161b4d63a331c3bb586036cce229680532c9d Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Thu, 12 Mar 2026 10:50:16 +0100 Subject: [PATCH 30/37] fixed warnings --- backend/ibex/endpoints/data.py | 3 --- docs/Makefile | 4 ++-- docs/source/_templates/custom-module-template.rst | 1 - docs/source/conf.py | 3 +++ 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/backend/ibex/endpoints/data.py b/backend/ibex/endpoints/data.py index a9e363bc..0cc0f8c4 100644 --- a/backend/ibex/endpoints/data.py +++ b/backend/ibex/endpoints/data.py @@ -17,9 +17,6 @@ class CustomORJSONResponse(ORJSONResponse): Custom ORJSON serializer. Uses serializer from data_source to transform arbitrary types (e.g. IDSNumericArray) to ones supported by ORJSON serializer (e.g. np.array). """ - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - def render(self, content) -> bytes: return orjson.dumps( content, default=ibex_service.data_source.data_serializer_custom, option=orjson.OPT_SERIALIZE_NUMPY diff --git a/docs/Makefile b/docs/Makefile index cc575a7a..d903a5c8 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -6,7 +6,7 @@ SPHINXOPTS ?= SPHINXBUILD ?= sphinx-build SOURCEDIR = source -GENERATEDDIR = $(SOURCEDIR)/generated +GENERATEDDIR = $(SOURCEDIR)/developers_manual/backend_development/generated BUILDDIR = _build PROJECT_ROOT = ../backend @@ -30,7 +30,7 @@ clean: Makefile # This recipe generates source files, so put result in source MODULE_EXCLUDE="" apidocs: Makefile - sphinx-apidoc --implicit-namespaces -o "$(GENERATEDDIR)" "$(PROJECT_ROOT)/backend/ibex" $(MODULE_EXCLUDE) + sphinx-apidoc --implicit-namespaces -o "$(GENERATEDDIR)" "$(PROJECT_ROOT)/ibex" $(MODULE_EXCLUDE) # Sphinx will run this automatically autogen: Makefile diff --git a/docs/source/_templates/custom-module-template.rst b/docs/source/_templates/custom-module-template.rst index e1157fa6..bd69dd82 100644 --- a/docs/source/_templates/custom-module-template.rst +++ b/docs/source/_templates/custom-module-template.rst @@ -58,7 +58,6 @@ .. autosummary:: :toctree: :template: custom-module-template.rst - :recursive: {% for item in modules | reject("equalto", "test") %} {{ item }} {%- endfor %} diff --git a/docs/source/conf.py b/docs/source/conf.py index 68b58a0b..199d5dfa 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -261,6 +261,9 @@ # Configuration of sphinx.ext.autodoc # https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html autodoc_typehints = "signature" +# Exclude __init__ from :members: to avoid duplicating the explicit +# .. automethod:: __init__ in custom-class-template.rst +autodoc_default_options = {"exclude-members": "__init__"} # Configuration of sphinx.ext.autosummary From 86dea57cb2ffad1cd23b02f609098ad7e637032c Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Thu, 12 Mar 2026 10:53:14 +0100 Subject: [PATCH 31/37] added gitkeep --- docs/source/_static/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/source/_static/.gitkeep diff --git a/docs/source/_static/.gitkeep b/docs/source/_static/.gitkeep new file mode 100644 index 00000000..e69de29b From 3041f1a70fd6f055daeeb4ea3393802088389751 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Thu, 12 Mar 2026 11:36:42 +0100 Subject: [PATCH 32/37] fixed comments from jwasikpsnc --- .readthedocs.yaml | 1 - backend/ci/build_docs.sh | 4 ++-- backend/ci/configure_env.sh | 4 ++-- backend/ci/run_pytest.sh | 4 ++-- backend/pyproject.toml | 3 ++- docs/requirements.txt | 8 -------- frontend/ci/configure-env.sh | 2 +- 7 files changed, 9 insertions(+), 17 deletions(-) delete mode 100644 docs/requirements.txt diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 59a3d18a..31c9b6eb 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -11,7 +11,6 @@ sphinx: python: install: - - requirements: docs/requirements.txt - method: pip path: backend extra_requirements: diff --git a/backend/ci/build_docs.sh b/backend/ci/build_docs.sh index 8a546455..70f64ae2 100755 --- a/backend/ci/build_docs.sh +++ b/backend/ci/build_docs.sh @@ -19,8 +19,8 @@ python -m venv venv echo "PWD: " `pwd` # PREPARE THE ENVIRONMENT -pip install --upgrade -r ../docs/requirements.txt +pip install --upgrade pip setuptools wheel pip install --upgrade .[docs] -# RUN PYTEST +# BUILD DOCS make -C ../docs html \ No newline at end of file diff --git a/backend/ci/configure_env.sh b/backend/ci/configure_env.sh index c78fe4cc..126cf3bc 100755 --- a/backend/ci/configure_env.sh +++ b/backend/ci/configure_env.sh @@ -7,8 +7,8 @@ source /etc/profile.d/modules.sh module purge # Set up environment -module load IDStools/2.4.0-intel-2023b -module unload Python-bundle-PyPI +module load Python +module load IMAS-Core # Debuggging: echo "Done loading modules" diff --git a/backend/ci/run_pytest.sh b/backend/ci/run_pytest.sh index 1b7be6bb..faba5d5f 100755 --- a/backend/ci/run_pytest.sh +++ b/backend/ci/run_pytest.sh @@ -19,8 +19,8 @@ python -m venv venv echo "PWD: " `pwd` # PREPARE THE ENVIRONMENT -pip install --upgrade pip setuptools wheel pytest-cov pytest-xdist -pip install --upgrade . +pip install --upgrade pip setuptools wheel +pip install --upgrade .[test] # RUN PYTEST python -m pytest -n auto --cov=ibex --cov-report=term-missing --cov-report=html --junit-xml=test-reports/pytest-report.xml ${BACKEND_ROOT_DIR}/tests \ No newline at end of file diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 55c2ae3e..ad613eae 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -43,7 +43,6 @@ classifiers = [ ] dynamic = ["version"] dependencies = [ - "imas-python", "imas-idstools", "click", "uvicorn", @@ -64,6 +63,8 @@ all = [ test = [ "pytest", + "pytest-cov", + "pytest-xdist", ] linting = [ diff --git a/docs/requirements.txt b/docs/requirements.txt deleted file mode 100644 index e6c75cf7..00000000 --- a/docs/requirements.txt +++ /dev/null @@ -1,8 +0,0 @@ -pip -setuptools -wheel -build -pytest-cov -sphinx>=7,<9 -sphinx_immaterial -sphinx-autosummary-accessors==2025.3.1 diff --git a/frontend/ci/configure-env.sh b/frontend/ci/configure-env.sh index 67314607..a1ec25d3 100755 --- a/frontend/ci/configure-env.sh +++ b/frontend/ci/configure-env.sh @@ -10,7 +10,7 @@ module purge module load nodejs module load Xvfb/21.1.9-GCCcore-13.2.0 module load Python -module load IDStools/2.4.0-intel-2023b +module load IMAS-Core # Debuggging: echo "Done loading modules" From 96d8165667aee1aadab2dc78b7f5bcc1598b0564 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Thu, 12 Mar 2026 11:48:49 +0100 Subject: [PATCH 33/37] updated links and added documentation link --- README.md | 1 + asv.conf.json | 2 +- docs/source/conf.py | 17 +++++++---------- .../frontend_development/installation.rst | 4 ++-- docs/source/users_manual/how_to_launch.rst | 6 +++--- frontend/README.md | 4 ++-- 6 files changed, 16 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 11cbe1e9..02cec43c 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ IBEX (IMAS variaBles EXplorer) is a general purpose graphical tool for exploring > [!NOTE] > This project is under active development, important changes may occur including in the backend endpoint API. +**Documentation:** https://imas-ibex.readthedocs.io/ [Frontend readme](frontend/README.md) diff --git a/asv.conf.json b/asv.conf.json index 3ce75734..a6922cf4 100644 --- a/asv.conf.json +++ b/asv.conf.json @@ -7,7 +7,7 @@ "project": "IBEX", // The project's homepage - "project_url": "https://git.iter.org/projects/IMEX/repos/ibex", + "project_url": "https://github.com/iterorganization/IBEX", // The URL or local path of the source code repository for the // project being benchmarked diff --git a/docs/source/conf.py b/docs/source/conf.py index 199d5dfa..06ffd5c0 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -29,20 +29,17 @@ copyright = f"2025-{datetime.datetime.now().year}, ITER Organization" # The author name(s) of the document author = "ITER Organization" -src_host = "git.iter.org" +src_host = "github.com" # Parse urls here for convenience, to be re-used # ITER docs -iter_projects = "https://git.iter.org/projects/" -imas_repos = urljoin(iter_projects, "IMAS/") -imex_repos = urljoin(iter_projects, "IMEX/") -issue_url = jira_url = "https://jira.iter.org/browse/" +issue_url = "https://github.com/iterorganization/IBEX/issues" -# Ibex -repository_url = f"{iter_projects}/{src_group}/repos/{src_project}/" -blob_url = urljoin(repository_url, "browse/") -mr_url = urljoin(repository_url, "/pull-requests") +# Ibex (now on GitHub) +repository_url = "https://github.com/iterorganization/IBEX/" +blob_url = urljoin(repository_url, "blob/main/") +mr_url = urljoin(repository_url, "pull/") # Configuration of sphinx.ext.extlinks @@ -130,7 +127,7 @@ # and # https://sphinx-immaterial.readthedocs.io/en/latest/customization.html#confval-html_theme_options html_theme_options = { - "repo_url": "https://git.iter.org/projects/IMEX/repos/ibex", + "repo_url": "https://github.com/iterorganization/IBEX", "repo_name": "ibex", "icon": { "repo": "fontawesome/brands/bitbucket", diff --git a/docs/source/developers_manual/frontend_development/installation.rst b/docs/source/developers_manual/frontend_development/installation.rst index 63d2f621..3c2ccd80 100644 --- a/docs/source/developers_manual/frontend_development/installation.rst +++ b/docs/source/developers_manual/frontend_development/installation.rst @@ -11,7 +11,7 @@ HTTPS : .. code-block:: bash - git clone https://git.iter.org/scm/imex/ibex.git + git clone https://github.com/iterorganization/IBEX.git or @@ -19,7 +19,7 @@ SSH : .. code-block:: bash - git clone ssh://git@git.iter.org/imex/ibex.git + git clone git@github.com:iterorganization/IBEX.git after diff --git a/docs/source/users_manual/how_to_launch.rst b/docs/source/users_manual/how_to_launch.rst index b9919e7b..be39a741 100644 --- a/docs/source/users_manual/how_to_launch.rst +++ b/docs/source/users_manual/how_to_launch.rst @@ -20,8 +20,8 @@ Second, due to permission issues, only one user can run IBEX from a given source For regular, non-development use cases, the production mode is recommended. * Open a terminal. -* Clone the repository (ssh://git@git.iter.org/imex/ibex.git) -* Run the following commands : +* Clone the repository (https://github.com/iterorganization/IBEX.git) +* Run the following commands :: .. code-block:: bash @@ -39,7 +39,7 @@ The execution stage configures and launches both the backend and frontend using Since the installation process can take several minutes to complete, development mode is recommended when actively modifying the source code and pushing frequent changes. * Open a terminal. -* Clone the repository (ssh://git@git.iter.org/imex/ibex.git) +* Clone the repository (https://github.com/iterorganization/IBEX.git) * Run the following commands : .. code-block:: bash diff --git a/frontend/README.md b/frontend/README.md index 6c1374b0..78958c1e 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -25,11 +25,11 @@ module load nodejs Clone this repository and install the dependencies: -HTTPS : `git clone https://git.iter.org/scm/imex/ibex.git` +HTTPS : `git clone https://github.com/iterorganization/IBEX.git` or -SSH : `git clone ssh://git@git.iter.org/imex/ibex.git` +SSH : `git clone git@github.com:iterorganization/IBEX.git` ``` cd frontend From c7442071a0aee64143dbf76dc2faf6455222c122 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Thu, 12 Mar 2026 11:52:00 +0100 Subject: [PATCH 34/37] fixed how_to_launch page --- docs/source/users_manual/how_to_launch.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/users_manual/how_to_launch.rst b/docs/source/users_manual/how_to_launch.rst index be39a741..1d275dd6 100644 --- a/docs/source/users_manual/how_to_launch.rst +++ b/docs/source/users_manual/how_to_launch.rst @@ -21,7 +21,7 @@ For regular, non-development use cases, the production mode is recommended. * Open a terminal. * Clone the repository (https://github.com/iterorganization/IBEX.git) -* Run the following commands :: +* Run the following commands: .. code-block:: bash @@ -40,7 +40,7 @@ Since the installation process can take several minutes to complete, development * Open a terminal. * Clone the repository (https://github.com/iterorganization/IBEX.git) -* Run the following commands : +* Run the following commands: .. code-block:: bash From da1fd693436f57dcf3be746e46d453190a0f24b8 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Thu, 12 Mar 2026 13:30:20 +0100 Subject: [PATCH 35/37] fixed version and removed license --- docs/source/conf.py | 10 ++++++++-- docs/source/index.rst | 9 +-------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 06ffd5c0..3860d5a5 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -15,6 +15,12 @@ from jinja2.defaults import DEFAULT_FILTERS from packaging.version import Version +# Get version from setuptools_scm (written to _version.py during package build) +try: + from ibex._version import __version__ as ibex_version +except ImportError: + ibex_version = "0.0.1" + print("python exec:", sys.executable) print("sys.path:", sys.path) @@ -51,7 +57,7 @@ "merge": (mr_url + "%s", "!%s"), } -full_version = Version("0.0.1") # = Version(ibex.__version__) +full_version = Version(ibex_version) # version: The major project version, used as the replacement for |version|. # For example, for the Python documentation, this may be something like 2.6. @@ -130,7 +136,7 @@ "repo_url": "https://github.com/iterorganization/IBEX", "repo_name": "ibex", "icon": { - "repo": "fontawesome/brands/bitbucket", + "repo": "fontawesome/brands/github", }, "features": [ # "navigation.expand", diff --git a/docs/source/index.rst b/docs/source/index.rst index db2de683..a8f7cfe9 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -28,11 +28,4 @@ Manual :maxdepth: 1 developers_manual/frontend_development/frontend_development - developers_manual/backend_development/backend_development - - -LICENSE -------- - -.. literalinclude:: ../../LICENSE.txt - :language: text \ No newline at end of file + developers_manual/backend_development/backend_development \ No newline at end of file From f38d137d5970238e4394492263fd9a076e1d879d Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Thu, 12 Mar 2026 14:40:52 +0100 Subject: [PATCH 36/37] fixed exception test --- backend/ibex/data_source/imas_python_source.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/ibex/data_source/imas_python_source.py b/backend/ibex/data_source/imas_python_source.py index 3658229b..5b615608 100644 --- a/backend/ibex/data_source/imas_python_source.py +++ b/backend/ibex/data_source/imas_python_source.py @@ -91,6 +91,8 @@ def _get_ids_from_entry(self, entry: imas.DBEntry, ids: str, occurrence: int = 0 return ids_root except imas.exception.IDSNameError as e: raise IdsNotFoundException(e) from None + except imas.exception.DataEntryException as e: + raise IdsNotFoundException(e) from None def data_entry_exists(self, uri: str) -> bool: """ From 31b5c69fdd1550b54ed0809ac7cfc25c36e74ab9 Mon Sep 17 00:00:00 2001 From: prasad-sawantdesai Date: Thu, 12 Mar 2026 17:23:21 +0100 Subject: [PATCH 37/37] Fix ASV build failure --- asv.conf.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/asv.conf.json b/asv.conf.json index a6922cf4..e3bcd2b6 100644 --- a/asv.conf.json +++ b/asv.conf.json @@ -22,9 +22,8 @@ // See asv.conf.json documentation. // To build the package using pyproject.toml (PEP518), uncomment the following lines "build_command": [ - "python -m pip install build", - "python -m build", - "python -m build --wheel -o {build_cache_dir} {build_dir}", + "python -m pip install build setuptools>=61 setuptools_scm[toml]>=6.2 versioneer[toml] wheel", + "python -m build --no-isolation --wheel -o {build_cache_dir} {build_dir}", //"python -m pip wheel --no-deps -w {build_cache_dir} {build_dir}" ], // Customizable commands for installing and uninstalling the project.