Skip to content

Commit aaa8231

Browse files
updatd
1 parent fb9458f commit aaa8231

File tree

4 files changed

+148
-20
lines changed

4 files changed

+148
-20
lines changed

README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@
3737

3838
## 📚 Chapter Checklist
3939

40-
---
41-
4240
[Bro Code Python YouTube Class](https://youtu.be/ix9cRaBkVe0?feature=shared)
4341

4442
Learn Python in 1 HOUR ⏱ : [Learn Python in 1 hour! 🐍. (2024)](https://youtu.be/ix9cRaBkVe0?feature=shared)

docs/19-nested-loops.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ create_tic_tac_toe()
482482
```
483483

484484
### Application 6: ASCII Art Generator
485-
```{code-cell} python
485+
```text
486486
def draw_box(width, height):
487487
# Top border
488488
print("┌" + "─" * (width - 2) + "┐")

docs/30-dice-roller-program.md

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ Example of a dice showing 3:
6060

6161
These special characters create the dice borders:
6262

63-
```{code-cell} python
63+
```text
6464
# Unicode characters
6565
print("\u25CF") # ● (bullet/dot)
6666
print("\u250C") # ┌ (top-left corner)
@@ -75,7 +75,7 @@ print("\u2500") # ─ (horizontal line)
7575

7676
The program uses a clever data structure:
7777

78-
```python
78+
```text
7979
dice_art = {
8080
1: ("┌─────────┐",
8181
"│ │",
@@ -149,7 +149,7 @@ if num_dice < 1:
149149

150150
### Why Use Tuples for Dice Art?
151151

152-
```{code-cell} python
152+
```text
153153
# Each dice face is a tuple of 5 strings
154154
dice_face = (
155155
"┌─────────┐", # Line 0
@@ -171,7 +171,7 @@ Tuples ensure:
171171
## Examples
172172

173173
### Example 1: Basic Unicode Characters
174-
```{code-cell} python
174+
```text
175175
# Box drawing characters
176176
print("┌─────────┐")
177177
print("│ Hello │")
@@ -189,7 +189,7 @@ print("└─────────┘")
189189
```
190190

191191
### Example 2: Storing Dice Art in Tuple
192-
```{code-cell} python
192+
```text
193193
# Single dice face as tuple of strings
194194
dice_one = (
195195
"┌─────────┐",
@@ -212,7 +212,7 @@ for line in dice_one:
212212
```
213213

214214
### Example 3: Dictionary of Dice Faces
215-
```{code-cell} python
215+
```text
216216
dice_art = {
217217
1: ("┌─────────┐",
218218
"│ │",
@@ -237,7 +237,7 @@ for line in dice_art[2]:
237237
```
238238

239239
### Example 4: Rolling Random Dice
240-
```python
240+
```text
241241
import random
242242
243243
dice_art = {
@@ -257,7 +257,7 @@ for line in dice_art[roll]:
257257
```
258258

259259
### Example 5: Displaying Multiple Dice Side-by-Side
260-
```{code-cell} python
260+
```text
261261
import random
262262
263263
dice_art = {
@@ -316,9 +316,7 @@ print(f"Total: {sum(results)}")
316316
```
317317

318318
### Example 7: Complete Dice Roller (Simplified)
319-
```{code-cell} python
320-
:tags: [skip-execution]
321-
319+
```text
322320
import random
323321
324322
# Complete dice art dictionary
@@ -425,7 +423,7 @@ while True:
425423
### Mistake 1: Incorrect Line Indexing
426424

427425
**Wrong:**
428-
```{code-cell} python
426+
```text
429427
# Only 3 lines (missing top and bottom)
430428
dice_face = (
431429
"│ ● ● │",
@@ -438,7 +436,7 @@ for line_idx in range(5): # Trying to access 5 lines!
438436
```
439437

440438
**Correct:**
441-
```{code-cell} python
439+
```text
442440
# All 5 lines included
443441
dice_face = (
444442
"┌─────────┐", # Line 0
@@ -457,7 +455,7 @@ for line_idx in range(5):
457455
### Mistake 2: Not Adding Spacing Between Dice
458456

459457
**Wrong:**
460-
```{code-cell} python
458+
```text
461459
for line_idx in range(5):
462460
line = ""
463461
for result in results:
@@ -469,7 +467,7 @@ for line_idx in range(5):
469467
```
470468

471469
**Correct:**
472-
```{code-cell} python
470+
```text
473471
for line_idx in range(5):
474472
line = ""
475473
for result in results:
@@ -485,15 +483,15 @@ for line_idx in range(5):
485483
### Mistake 3: Using List Instead of Tuple
486484

487485
**Wrong:**
488-
```{code-cell} python
486+
```text
489487
dice_art = {
490488
1: ["┌─────────┐", "│ ● │", "└─────────┘"] # List!
491489
}
492490
# Works but semantically wrong - dice faces shouldn't change
493491
```
494492

495493
**Correct:**
496-
```{code-cell} python
494+
```text
497495
dice_art = {
498496
1: ("┌─────────┐", "│ ● │", "└─────────┘") # Tuple!
499497
}

scripts/generate_docs.py

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,31 @@
66
GITHUB_REPO = "PavanMudigonda/python-bro-code"
77
GITHUB_BRANCH = "main"
88

9+
MYSTNB_FRONTMATTER = """\
10+
---
11+
jupytext:
12+
text_representation:
13+
format_name: myst
14+
kernelspec:
15+
display_name: Python 3
16+
language: python
17+
name: python3
18+
---
19+
20+
"""
21+
22+
# Markers that indicate a code block is pseudocode / not runnable
23+
SKIP_MARKERS = [
24+
"# ...",
25+
"# calculator code here",
26+
"# Create calculator",
27+
"# Parse and calculate",
28+
"# Allow user",
29+
"# your code here",
30+
"# TODO",
31+
"pass #",
32+
]
33+
934
# Pattern to match old badge lines that LINK TO Colab/Kaggle (preserves YouTube badges)
1035
OLD_BADGE_RE = re.compile(
1136
r'^\s*\[!\[.*?\]\(.*?\)\]\(https?://(?:colab\.research\.google\.com|kaggle\.com/kernels).*?\)\s*'
@@ -72,6 +97,110 @@ def extract_markdown_from_notebook(nb_path):
7297
return '\n\n'.join(parts)
7398

7499

100+
# ── Post-processing helpers applied to every generated doc ──────────────
101+
102+
103+
def remove_duplicate_video_tutorial(content):
104+
"""Remove the second '## 📺 Video Tutorial' block if duplicated."""
105+
VT_HEADING = "## 📺 Video Tutorial"
106+
first = content.find(VT_HEADING)
107+
if first == -1:
108+
return content
109+
second = content.find(VT_HEADING, first + len(VT_HEADING))
110+
if second == -1:
111+
return content
112+
# Find the end of the duplicate block (heading + optional blank + badge line)
113+
end = second
114+
lines = content[second:].split('\n')
115+
remove_count = 0
116+
for line in lines:
117+
remove_count += 1
118+
# Stop after the badge line (or after 4 lines max)
119+
if 'Watch on YouTube' in line or remove_count >= 4:
120+
break
121+
end = second + len('\n'.join(lines[:remove_count]))
122+
# Also consume the blank line before the heading
123+
if second > 0 and content[second - 1] == '\n':
124+
second -= 1
125+
return content[:second] + content[end:]
126+
127+
128+
def _should_convert(code_lines):
129+
"""Return True if a python code block looks runnable."""
130+
code = "\n".join(code_lines)
131+
stripped = [l for l in code_lines if l.strip()]
132+
if not stripped:
133+
return False
134+
for marker in SKIP_MARKERS:
135+
if marker in code:
136+
return False
137+
if all(l.strip().startswith("#") or not l.strip() for l in code_lines):
138+
return False
139+
return True
140+
141+
142+
def _has_box_drawing(code_lines):
143+
"""Return True if the block contains box-drawing characters."""
144+
return any(ch in line for line in code_lines for ch in "│└├─")
145+
146+
147+
def convert_python_to_code_cells(content):
148+
"""Convert ```python blocks to ```{code-cell} python where appropriate.
149+
150+
Blocks with box-drawing chars become ```text.
151+
Blocks using input() get :tags: [skip-execution].
152+
Pseudocode blocks stay as ```python.
153+
"""
154+
lines = content.split("\n")
155+
new_lines = []
156+
i = 0
157+
while i < len(lines):
158+
if re.match(r"^```python\s*$", lines[i]):
159+
code_lines = []
160+
i += 1
161+
while i < len(lines) and not re.match(r"^```\s*$", lines[i]):
162+
code_lines.append(lines[i])
163+
i += 1
164+
closing = lines[i] if i < len(lines) else "```"
165+
166+
if _has_box_drawing(code_lines):
167+
new_lines.append("```text")
168+
elif _should_convert(code_lines):
169+
if any("input(" in l for l in code_lines):
170+
new_lines.append("```{code-cell} python")
171+
new_lines.append(":tags: [skip-execution]")
172+
new_lines.append("")
173+
else:
174+
new_lines.append("```{code-cell} python")
175+
else:
176+
new_lines.append("```python")
177+
178+
new_lines.extend(code_lines)
179+
new_lines.append(closing)
180+
i += 1
181+
else:
182+
new_lines.append(lines[i])
183+
i += 1
184+
return "\n".join(new_lines)
185+
186+
187+
def add_mystnb_frontmatter(content):
188+
"""Prepend myst-nb YAML frontmatter if the doc has code-cell blocks."""
189+
if "{code-cell}" not in content:
190+
return content
191+
if content.startswith("---"):
192+
return content
193+
return MYSTNB_FRONTMATTER + content
194+
195+
196+
def postprocess_doc(content):
197+
"""Apply all post-processing steps to generated doc content."""
198+
content = remove_duplicate_video_tutorial(content)
199+
content = convert_python_to_code_cells(content)
200+
content = add_mystnb_frontmatter(content)
201+
return content
202+
203+
75204
def main():
76205
base_dir = "."
77206
docs_dir = "docs"
@@ -137,6 +266,9 @@ def main():
137266
else:
138267
content += "\n" + notebook_badges
139268

269+
# Post-process: deduplicate, convert code cells, add frontmatter
270+
content = postprocess_doc(content)
271+
140272
with open(doc_path, 'w', encoding='utf-8') as wf:
141273
wf.write(content)
142274

0 commit comments

Comments
 (0)