Skip to content

Commit df0a7ca

Browse files
Merge branch 'develop' into fix/329-rois-created-by-detection-cannot-be-modified
2 parents 77637e4 + a92ae7c commit df0a7ca

98 files changed

Lines changed: 11904 additions & 875 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/pages.yml

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,33 @@ jobs:
117117
for LNG in fr en; do
118118
python -m sphinx -b html -D language=$LNG doc "site/$LNG"
119119
done
120-
# Top-level index redirecting to the English version.
120+
# Top-level index redirecting to the user's language: French when the
121+
# browser prefers `fr*`, English otherwise. A <noscript> meta refresh
122+
# falls back to English when JavaScript is disabled.
121123
cat > site/index.html <<'EOF'
122124
<!doctype html>
123-
<meta http-equiv="refresh" content="0; url=./en/">
124-
<link rel="canonical" href="./en/">
125+
<html lang="en">
126+
<head>
127+
<meta charset="utf-8">
128+
<title>DataLab</title>
129+
<script>
130+
(function () {
131+
var langs = navigator.languages || [navigator.language || "en"];
132+
var fr = langs.some(function (l) { return /^fr\b/i.test(l); });
133+
location.replace(fr ? "./fr/" : "./en/");
134+
})();
135+
</script>
136+
<noscript>
137+
<meta http-equiv="refresh" content="0; url=./en/">
138+
</noscript>
139+
<link rel="alternate" hreflang="fr" href="./fr/">
140+
<link rel="alternate" hreflang="en" href="./en/">
141+
<link rel="alternate" hreflang="x-default" href="./en/">
142+
</head>
143+
<body>
144+
<p>Redirecting… <a href="./en/">English</a> · <a href="./fr/">Français</a></p>
145+
</body>
146+
</html>
125147
EOF
126148
127149
- name: Upload built site as artifact
@@ -156,6 +178,10 @@ jobs:
156178
publish_branch: main
157179
publish_dir: ./site
158180
keep_files: false
181+
# Re-write the apex CNAME on every deploy: peaceiris wipes the target
182+
# with keep_files=false, and the built site has no root CNAME, so
183+
# without this the custom domain binding is lost (site 404s).
184+
cname: datalab-platform.com
159185
commit_message: "Update documentation from ${{ github.repository }}@${{ github.sha }}"
160186

161187
- name: Deploy to DataLab-Platform.github.io (via SSH deploy key)
@@ -167,4 +193,8 @@ jobs:
167193
publish_branch: main
168194
publish_dir: ./site
169195
keep_files: false
196+
# Re-write the apex CNAME on every deploy: peaceiris wipes the target
197+
# with keep_files=false, and the built site has no root CNAME, so
198+
# without this the custom domain binding is lost (site 404s).
199+
cname: datalab-platform.com
170200
commit_message: "Update documentation from ${{ github.repository }}@${{ github.sha }}"

.github/workflows/release-rc.yml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ jobs:
5353
uses: pypa/gh-action-pypi-publish@release/v1
5454
with:
5555
repository-url: https://test.pypi.org/legacy/
56+
# RC validation may be re-run on the same version (e.g. after fixing
57+
# a later job). TestPyPI versions are immutable, so skip already
58+
# uploaded files instead of failing the whole workflow.
59+
skip-existing: true
5660

5761
github-prerelease:
5862
needs: build
@@ -90,10 +94,14 @@ jobs:
9094
- name: Generate SHA256SUMS
9195
run: |
9296
cd assets
97+
# Published release assets are flat, so SHA256SUMS must reference bare
98+
# filenames. Run sha256sum from each file's own directory so the
99+
# checksum line contains the basename (not dists/…, msi/…, pdfs/…).
93100
find dists msi pdfs -type f \
94101
\( -name '*.whl' -o -name '*.tar.gz' -o -name '*.msi' -o -name '*.pdf' \) \
95-
-printf '%P\n' | sort | xargs -I{} sha256sum {} \
96-
> SHA256SUMS
102+
-printf '%p\n' | sort | while read -r f; do
103+
( cd "$(dirname "$f")" && sha256sum "$(basename "$f")" )
104+
done > SHA256SUMS
97105
cat SHA256SUMS
98106
99107
- name: Attest build provenance

.github/workflows/release.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,14 @@ jobs:
100100
# release. Users verify with: `sha256sum -c SHA256SUMS`.
101101
run: |
102102
cd assets
103+
# Published release assets are flat, so SHA256SUMS must reference bare
104+
# filenames. Run sha256sum from each file's own directory so the
105+
# checksum line contains the basename (not dists/…, msi/…, pdfs/…).
103106
find dists msi pdfs -type f \
104107
\( -name '*.whl' -o -name '*.tar.gz' -o -name '*.msi' -o -name '*.pdf' \) \
105-
-printf '%P\n' | sort | xargs -I{} sha256sum {} \
106-
> SHA256SUMS
108+
-printf '%p\n' | sort | while read -r f; do
109+
( cd "$(dirname "$f")" && sha256sum "$(basename "$f")" )
110+
done > SHA256SUMS
107111
echo "--- SHA256SUMS ---"
108112
cat SHA256SUMS
109113

.pylintrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
[MASTER]
2+
ignore-paths=^datalab/gui/macros_templates/.*$
3+
14
[FORMAT]
25
# Essential to be able to compare code side-by-side (`black` default setting)
36
# and best compromise to minimize file size

datalab/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
# this module is imported more than once, e.g. when running tests)
2525
pass
2626

27-
__version__ = "1.2.1"
27+
__version__ = "1.3.0"
2828
__docurl__ = __homeurl__ = "https://datalab-platform.com/"
2929
__supporturl__ = "https://github.com/DataLab-Platform/DataLab/issues/new/choose"
3030

datalab/adapters_metadata/common.py

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,27 @@
2626
from qtpy.QtWidgets import QWidget
2727

2828

29+
def alpha_label(index: int) -> str:
30+
"""Return an alphabetic label for a 0-based index.
31+
32+
Mapping: ``0 → "a"``, ``1 → "b"``, ..., ``25 → "z"``, ``26 → "aa"``, ...
33+
34+
Used to label axis-marker cursors (X_MARKERS / Y_MARKERS) and the
35+
corresponding rows in the merged result label, so they can be matched
36+
to the dashed cursors drawn on the plot.
37+
"""
38+
if index < 0:
39+
return ""
40+
label = ""
41+
n = index
42+
while True:
43+
label = chr(ord("a") + (n % 26)) + label
44+
n = n // 26 - 1
45+
if n < 0:
46+
break
47+
return label
48+
49+
2950
@dataclasses.dataclass
3051
class ResultData:
3152
"""Result data associated to a shapetype"""
@@ -355,6 +376,32 @@ def resultadapter_to_html(
355376
# Remove roi_index column for display calculations
356377
display_df = df.drop(columns=["roi_index"]) if "roi_index" in df.columns else df
357378

379+
# If this is a marker result (XY/X/Y_MARKERS) and the user opted in,
380+
# prepend a "marker label" column so each row in the displayed table
381+
# can be matched with the cross / dashed cursor drawn on the plot
382+
# (XY markers use numeric labels ``#1, #2, ...``; axis markers use
383+
# alphabetic labels ``a, b, c, ...``). Forces the fast HTML path
384+
# below to honor the injected column (the standard ``adapter.to_html``
385+
# path does not see DataFrame mutations made here).
386+
marker_labels_injected = False
387+
result = adapter.result
388+
if ( # pylint: disable=too-many-boolean-expressions
389+
Conf.view.show_marker_labels_in_table.get(True)
390+
and hasattr(result, "is_xy_markers")
391+
and (
392+
result.is_xy_markers()
393+
or result.is_x_markers()
394+
or (hasattr(result, "is_y_markers") and result.is_y_markers())
395+
)
396+
):
397+
if result.is_xy_markers():
398+
marker_col = [f"#{i + 1}" for i in range(len(display_df))]
399+
else:
400+
marker_col = [alpha_label(i) for i in range(len(display_df))]
401+
display_df = display_df.copy()
402+
display_df.insert(0, _("Marker"), marker_col)
403+
marker_labels_injected = True
404+
358405
# For merged labels, limit display columns for readability
359406
max_display_cols = Conf.view.max_cols_in_label.get(20)
360407
num_cols = len(display_df.columns)
@@ -369,7 +416,7 @@ def resultadapter_to_html(
369416
num_cells = num_rows * num_cols
370417

371418
# Check if truncation is needed BEFORE calling to_html()
372-
if num_cells > max_cells or cols_truncated:
419+
if num_cells > max_cells or cols_truncated or marker_labels_injected:
373420
# Calculate how many rows we can display given max_cells
374421
max_rows = max(1, max_cells // num_cols) if num_cols > 0 else num_rows
375422

@@ -379,6 +426,10 @@ def resultadapter_to_html(
379426
# Generate HTML directly from truncated DataFrame for performance
380427
# This is MUCH faster than calling adapter.to_html() on full data
381428
html_kwargs = {"border": 0}
429+
if marker_labels_injected:
430+
# Hide pandas' numeric index since the injected "Marker"
431+
# column already provides per-row identification.
432+
html_kwargs["index"] = False
382433
html_kwargs.update(kwargs)
383434

384435
# Format numeric columns efficiently

0 commit comments

Comments
 (0)