Skip to content

Commit 899a454

Browse files
committed
Add update_link_outputs
1 parent 896d5b6 commit 899a454

File tree

3 files changed

+144
-4
lines changed

3 files changed

+144
-4
lines changed
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#!/usr/bin/env python3
2+
3+
import json
4+
import re
5+
import sys
6+
from pathlib import Path
7+
8+
LINK_PATTERN = re.compile(
9+
r"Quantum program link: https://platform\.classiq\.io/circuit/\S+\n"
10+
)
11+
12+
# cell index ; output index ; the link itself
13+
Link = tuple[int, int, str]
14+
15+
16+
def extract_links(cells: list[dict]) -> list[Link]:
17+
links = []
18+
for cell_index, cell in enumerate(cells):
19+
if cell.get("cell_type", "") == "code":
20+
outputs = cell.get("outputs", [])
21+
for output_index, output in enumerate(outputs):
22+
text = (
23+
"".join(output.get("text", []))
24+
if isinstance(output.get("text"), list)
25+
else output.get("text", "")
26+
)
27+
match = LINK_PATTERN.search(text)
28+
if match:
29+
links.append((cell_index, output_index, match.group(0)))
30+
return links
31+
32+
33+
def update_links(
34+
cells: list[dict], old_links: list[Link], new_links: list[Link]
35+
) -> bool:
36+
for (cell_index, output_index, old_link), (_, _, new_link) in zip(
37+
old_links, new_links
38+
):
39+
output = cells[cell_index]["outputs"][output_index]
40+
text = output["text"]
41+
for index, line in enumerate(text):
42+
if old_link in line:
43+
text[index] = line.replace(old_link, new_link)
44+
break
45+
else:
46+
print("Couldn't find link. This shouldn't happen.")
47+
return False
48+
return True
49+
50+
51+
def validate_links_list(
52+
old_links: list[Link], new_links: list[Link], force: bool
53+
) -> bool:
54+
# verify list length
55+
if len(old_links) != len(new_links):
56+
print("Error: Link count mismatch in force mode")
57+
return False
58+
59+
if force:
60+
# verify cell index
61+
old_indices = [i for i, _ in old_links]
62+
new_indices = [i for i, _ in new_links]
63+
if old_indices != new_indices:
64+
print("Error: Link cell indices mismatch")
65+
return False
66+
67+
# verify link pattern
68+
if not all(LINK_PATTERN.match(link) for _, link in new_links):
69+
print("Error: Not all new links match expected pattern")
70+
return False
71+
72+
return True
73+
74+
75+
def main(dest_file: str, source_file: str, force: bool = False) -> bool:
76+
with open(dest_file) as f:
77+
old_nb = json.load(f)
78+
with open(source_file) as f:
79+
new_nb = json.load(f)
80+
81+
old_links = extract_links(old_nb["cells"])
82+
new_links = extract_links(new_nb["cells"])
83+
84+
if not validate_links_list(old_links, new_links, force):
85+
return False
86+
87+
if not update_links(old_nb["cells"], old_links, new_links):
88+
return False
89+
90+
with open(dest_file, "w") as f:
91+
json.dump(old_nb, f, indent=1)
92+
93+
print(f"Updated notebook written to: {dest_file}")
94+
return True
95+
96+
97+
if __name__ == "__main__":
98+
force = False
99+
if "--force" in sys.argv:
100+
force = True
101+
sys.argv.remove("--force")
102+
103+
if len(sys.argv) != 3:
104+
print(
105+
f"Usage: {sys.argv[0]} <file in which we'll update the links> <file from which to take the links> [--force]"
106+
)
107+
sys.exit(1)
108+
109+
if not main(sys.argv[1], sys.argv[2], force):
110+
sys.exit(1)

.internal/update_outputs/update_notebooks.sh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ current_folder="$(realpath "$(dirname "$0")")"
3232

3333
# note: there's a max of 3 running jobs per user, so we limit the threads to 3
3434
# # test all bernstein-vazirani notebooks
35-
find . -type f -name "*bernstein*.ipynb" | xargs -P2 -I{} "$current_folder/update_single_notebook.sh" {}
35+
find . -type f -name "*bernstein*.ipynb" | xargs -P2 -I{} "$current_folder/update_single_notebook_links.sh" {}
3636
# test all algorithms
37-
# find algorithms/ -type f -name "*.ipynb" | xargs -P3 -I{} "$current_folder/update_single_notebook.sh" {}
37+
# find algorithms/ -type f -name "*.ipynb" | xargs -P3 -I{} "$current_folder/update_single_notebook_links.sh" {}
3838
# # test 3 notebooks
39-
# find . -type f -name "*.ipynb" | head -n 3 | xargs -P3 -I{} "$current_folder/update_single_notebook.sh" {}
39+
# find . -type f -name "*.ipynb" | head -n 3 | xargs -P3 -I{} "$current_folder/update_single_notebook_links.sh" {}
4040
# # test all notebooks
41-
# find algorithms applications tutorials -type f -name "*.ipynb" | xargs -P3 -I{} "$current_folder/update_single_notebook.sh" {}
41+
# find algorithms applications tutorials -type f -name "*.ipynb" | xargs -P3 -I{} "$current_folder/update_single_notebook_links.sh" {}
4242

4343
#
4444
# 3) Commit the changes + open PR
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/bin/bash
2+
3+
notebook_relative_path="$1"
4+
notebook_path="$(realpath "$notebook_relative_path")"
5+
6+
notebook_dir=$(dirname "$notebook_path")
7+
notebook_name=$(basename "$notebook_path")
8+
9+
10+
current_folder="$(realpath "$(dirname "$0")")"
11+
12+
# disable popping browser for `show(qprog)`
13+
export BROWSER="$current_folder/fake_browser.sh"
14+
15+
# make a copy
16+
notebook_copy_path="$notebook_path.temp.ipynb"
17+
notebook_copy_name=$(basename "$notebook_copy_path")
18+
cp "$notebook_path" "$notebook_copy_path"
19+
20+
"$current_folder/hook_add_random_seed.py" "$notebook_copy_path"
21+
22+
pushd "$notebook_dir" > /dev/null
23+
jupyter nbconvert --to notebook --execute --inplace "$notebook_copy_name"
24+
popd > /dev/null
25+
26+
"$current_folder/hook_remove_random_seed.py" "$notebook_copy_path"
27+
28+
"$current_folder/update_links.py" "$notebook_path" "$notebook_copy_path"
29+
30+
rm "$notebook_copy_path"

0 commit comments

Comments
 (0)