Skip to content

Commit 388fd97

Browse files
authored
Colab again and again... (#595)
* remove git chapters * force build * update * rm feature selection * remove failing notebook * ::: also * argparse * clean them * temp eval false * remove file * bulding again * also 4 : * remove backticks * also _*files * all files * change * remove arg * update * update * typo * Ajoute fontawesome * script block * Colab false * remove eval false * script
1 parent b9a4025 commit 388fd97

File tree

9 files changed

+2402
-249
lines changed

9 files changed

+2402
-249
lines changed

.github/workflows/colab.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ on:
55
branches:
66
- main
77
- master
8-
- colab
8+
- colab2
99

1010
jobs:
1111
enonces:
@@ -33,7 +33,7 @@ jobs:
3333
rm -rf content/git/ # ignore git chapters
3434
rm content/modelisation/4_featureselection.qmd
3535
rm content/NLP/02_exoclean.qmd
36-
python build/colab/tweak_quarto_project.py
36+
python build/colab/tweak_quarto_project.py --overwrite
3737
quarto render --to ipynb
3838
- name: Move to expected directory
3939
env:

build/colab/callout_colab.py

Lines changed: 64 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,25 @@
11
import os
22
import re
33
import markdown
4+
import argparse
45
from loguru import logger
56

7+
parser = argparse.ArgumentParser(description="Tweak qmd files for colab.")
8+
9+
parser.add_argument(
10+
"--overwrite",
11+
action="store_true", # This makes it a boolean flag that defaults to False
12+
help="Enable overwrite mode (default: False)"
13+
)
14+
parser.add_argument(
15+
"--input_file_path",
16+
type=str,
17+
default="./content/getting-started/01_environment.qmd",
18+
help="Which file should we tweak ?"
19+
)
20+
21+
args = parser.parse_args()
22+
623

724
def create_python_snippet(title, content, callout_type):
825
"""
@@ -30,12 +47,34 @@ def create_python_snippet(title, content, callout_type):
3047
</style>
3148
"""
3249

33-
content = content.replace("{python}", "python")
50+
# Define a dictionary mapping callout types to their respective icons
51+
icon_mapping = {
52+
"tip": '<i class="fa-solid fa-lightbulb"></i>',
53+
"warning": '<i class="fa-solid fa-triangle-exclamation"></i>',
54+
"important": '<i class="fa-solid fa-circle-exclamation"></i>',
55+
"caution": '<i class="fa-solid fa-circle-exclamation"></i>',
56+
"exercise": '<i class="fa-solid fa-pen-fancy"></i>',
57+
}
58+
59+
# Use the dictionary to get the icon, with a default value if the type is not found
60+
icon = icon_mapping.get(callout_type, '<i class="fa-solid fa-comment"></i>')
61+
62+
content = (
63+
"\n"
64+
.join(line for line in content.splitlines() if not line.strip().startswith("#|"))
65+
)
66+
67+
content = (
68+
content
69+
.replace("{python}", "python")
70+
)
71+
72+
content = re.sub(r"```(python)\n(.*?)\n```", r"~~~\1\n\2\n~~~", content, flags=re.DOTALL)
3473

3574
content_html = f"""
3675
<div class="callout callout-{callout_type}">
3776
<div class="callout-header-{callout_type}">
38-
{title}
77+
{icon} {title}
3978
</div>
4079
<div class="callout-body">
4180
{markdown.markdown(content)}
@@ -45,16 +84,18 @@ def create_python_snippet(title, content, callout_type):
4584

4685
content_html = content_html.replace("'", "\\'")
4786

87+
4888
full_html = (
4989
"\n"
5090
"```{python}\n"
5191
"from IPython.display import HTML\n"
5292
f"style = '''\n{style}\n'''\n"
5393
f"content_html = '''\n{content_html}\n'''\n"
54-
'HTML(f"{style}\\n{content_html}")\n'
94+
'HTML(f"<script src="https://kit.fontawesome.com/3c27c932d3.js" crossorigin="anonymous"></script>\\n{style}\\n{content_html}")\n'
5595
"\n```"
5696
"\n"
5797
)
98+
5899
return full_html
59100

60101

@@ -96,7 +137,10 @@ def replacement(match):
96137
return regex.sub(replacement, content)
97138

98139

99-
def process_file(input_file_path, regex_pattern, output_file_path=None):
140+
def process_file(
141+
input_file_path, regex_pattern, output_file_path=None,
142+
overwrite: bool = False
143+
):
100144
"""
101145
Reads a file, performs snippet substitutions, and writes the updated content to a new file.
102146
@@ -109,8 +153,15 @@ def process_file(input_file_path, regex_pattern, output_file_path=None):
109153
None
110154
"""
111155

112-
if output_file_path is None:
113-
output_file_path = input_file_path.replace(".qmd", "_modified.qmd")
156+
157+
if overwrite is True:
158+
logger.debug("Since overwrite argument is True, forcing output_file_path value")
159+
output_file_path = input_file_path
160+
else:
161+
logger.debug("Overwrite argument is False")
162+
if output_file_path is None:
163+
output_file_path = input_file_path.replace(".qmd", "_modified.qmd")
164+
114165

115166
# Check if the input file exists
116167
if not os.path.exists(input_file_path):
@@ -142,6 +193,12 @@ def process_file(input_file_path, regex_pattern, output_file_path=None):
142193
# Example usage
143194
if __name__ == "__main__":
144195
process_file(
145-
input_file_path="./content/getting-started/01_environment.qmd",
196+
input_file_path=args.input_file_path,
197+
regex_pattern=r"::::\s*\{(?:\.note|\.caution|\.warning|\.important|\.tip|\.exercise)\}([\s\S]*?)::::",
198+
overwrite=args.overwrite
199+
)
200+
process_file(
201+
input_file_path=args.input_file_path,
146202
regex_pattern=r":::\s*\{(?:\.note|\.caution|\.warning|\.important|\.tip|\.exercise)\}([\s\S]*?):::",
203+
overwrite=args.overwrite
147204
)

build/colab/tweak_quarto_project.py

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,21 @@
11
import os
22
import yaml
3+
import glob
4+
import argparse
35
from loguru import logger
46
from callout_colab import process_file
57

8+
parser = argparse.ArgumentParser(description="Tweak quarto project for Google colab notebooks")
9+
10+
parser.add_argument(
11+
"--overwrite",
12+
action="store_true", # This makes it a boolean flag that defaults to False
13+
help="Enable override mode (default: False)"
14+
)
15+
parser.set_defaults(overwrite=False)
16+
17+
args = parser.parse_args()
18+
619

720
def read_quarto_yaml(file_path):
821
"""
@@ -31,36 +44,49 @@ def read_quarto_yaml(file_path):
3144

3245
def list_render_files(file_path):
3346
"""
34-
Reads and logs the content of the `_quarto.yml` file.
47+
Reads the `_quarto.yml` file and extracts the list of files to render.
3548
3649
Args:
3750
file_path (str): Path to the `_quarto.yml` file.
3851
3952
Returns:
40-
None
53+
list: List of file paths from `_quarto.yml`.
4154
"""
4255
yaml_content = read_quarto_yaml(file_path)
4356

4457
if not yaml_content:
4558
raise FileNotFoundError("No content to process.")
4659

47-
files = yaml_content.get("project").get("render")
60+
return yaml_content.get("project", {}).get("render", [])
61+
62+
63+
def find_qmd_files(directory):
64+
"""
65+
Finds all `_*.qmd` files in the given directory and its subdirectories.
66+
67+
Args:
68+
directory (str): Path to the root directory.
4869
49-
return files
70+
Returns:
71+
list: List of `_*.qmd` file paths.
72+
"""
73+
return glob.glob(os.path.join(directory, "**", "_*.qmd"), recursive=True)
5074

5175

5276
if __name__ == "__main__":
53-
5477
files = list_render_files("_quarto.yml")
5578

56-
for file in files:
57-
process_file(
58-
input_file_path=file,
59-
regex_pattern=r"::::\s*\{(?:\.note|\.caution|\.warning|\.important|\.tip|\.exercise)\}([\s\S]*?)::::",
60-
output_file_path=file,
61-
)
79+
# Find all _*.qmd files in ./content/ recursively
80+
qmd_files = find_qmd_files("./content/")
81+
82+
logger.debug(qmd_files)
83+
84+
# Combine both lists and remove duplicates
85+
all_files = list(set(files + qmd_files))
86+
87+
for file in all_files:
6288
process_file(
6389
input_file_path=file,
6490
regex_pattern=r":::\s*\{(?:\.note|\.caution|\.warning|\.important|\.tip|\.exercise)\}([\s\S]*?):::",
65-
output_file_path=file,
91+
overwrite=args.overwrite
6692
)

0 commit comments

Comments
 (0)