Skip to content

Commit 61f4d84

Browse files
fix: exclude examples.html from conformance tests and make Python blocks self-contained
- Add "examples.html" to NON_PLAYGROUND_PAGES in tests/playground.test.ts and tests-e2e/playground-cells.test.ts (it's an index/gallery page, not an interactive playground) - Prepend data-setup code to each playground-python textarea block so every block runs independently without depending on variables from the JS editor or other blocks (fixes 18 Python validation failures) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 5ce6df0 commit 61f4d84

12 files changed

Lines changed: 163 additions & 3 deletions

playground/example_ab_test.html

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,13 @@ <h2>1 · Conversion rate by variant</h2>
193193
const lift = ((b - a) / a) * 100;
194194
console.log(`\nLift in conversion rate: ${lift.toFixed(1)}%`);</textarea>
195195
<textarea class="playground-python" style="display:none">import pandas as pd
196+
sessions = pd.DataFrame({
197+
"variant": ["A"]*20 + ["B"]*20,
198+
"converted": [0,1,0,0,1,0,0,0,1,0,1,0,0,0,1,0,0,1,0,0,
199+
1,1,0,1,0,1,1,0,1,0,1,1,0,1,1,0,0,1,1,1],
200+
"order_value": [0,42,0,0,35,0,0,0,51,0,28,0,0,0,60,0,0,33,0,0,
201+
47,51,0,39,0,64,38,0,55,0,41,47,0,33,58,0,0,49,36,52],
202+
})
196203
summary = sessions.groupby("variant", as_index=False).agg(
197204
conv_rate=("converted", "mean"),
198205
avg_order_value=("order_value", "mean"),
@@ -240,6 +247,11 @@ <h2>2 · Order value distribution per variant</h2>
240247
console.log("\nVariant B order values:");
241248
console.log(describe(b).toString());</textarea>
242249
<textarea class="playground-python" style="display:none">import pandas as pd
250+
sessions = pd.DataFrame({
251+
"variant": ["A"]*20 + ["B"]*20,
252+
"order_value": [0,42,0,0,35,0,0,0,51,0,28,0,0,0,60,0,0,33,0,0,
253+
47,51,0,39,0,64,38,0,55,0,41,47,0,33,58,0,0,49,36,52],
254+
})
243255
converted = sessions[sessions["order_value"] &gt; 0]
244256
print(converted[converted["variant"]=="A"]["order_value"].describe())
245257
print(converted[converted["variant"]=="B"]["order_value"].describe())</textarea>

playground/example_customer_cohorts.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,13 @@ <h2>1 · Monthly signups & cumulative growth</h2>
194194
console.log("");
195195
console.log(out.toString());</textarea>
196196
<textarea class="playground-python" style="display:none">import pandas as pd
197+
events = pd.DataFrame({
198+
"customer_id": list(range(1000, 1060)),
199+
"signup_month": (
200+
["2024-01"]*4 + ["2024-02"]*6 + ["2024-03"]*5 + ["2024-04"]*8 +
201+
["2024-05"]*7 + ["2024-06"]*9 + ["2024-07"]*11 + ["2024-08"]*10
202+
),
203+
})
197204
monthly = events.groupby("signup_month", as_index=False).size()
198205
monthly["cumulative"] = monthly["size"].cumsum()
199206
monthly["mom_growth_pct"] = (monthly["size"].pct_change() * 100).round(1)
@@ -241,6 +248,10 @@ <h2>2 · Visualise cohort growth</h2>
241248
console.log(`\nTotal customers: ${total}`);
242249
console.log(`Best cohort : ${best}`);</textarea>
243250
<textarea class="playground-python" style="display:none">import pandas as pd
251+
monthly = pd.DataFrame({
252+
"month": ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug"],
253+
"signups": [4, 6, 5, 8, 7, 9, 11, 10],
254+
})
244255
print(monthly)
245256
print("Total:", monthly["signups"].sum())
246257
print("Best :", monthly.loc[monthly["signups"].idxmax(), "month"])</textarea>

playground/example_log_analysis.html

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,20 @@ <h2>1 · Parse and bucket access logs</h2>
199199
console.log("Requests per hour by status class:");
200200
console.log(piv.toString());</textarea>
201201
<textarea class="playground-python" style="display:none">import pandas as pd
202+
log = pd.DataFrame({
203+
"ts": [
204+
"10:01","10:03","10:09","10:14","10:22","10:31","10:47","10:55",
205+
"11:02","11:04","11:09","11:18","11:25","11:33","11:41","11:50","11:55","11:58",
206+
"12:01","12:03","12:08","12:14","12:22","12:31","12:38","12:45",
207+
"13:02","13:09","13:14","13:25","13:31","13:48","13:55",
208+
],
209+
"status": [
210+
200,200,200,404,200,500,200,200,
211+
200,500,500,500,200,200,404,500,500,500,
212+
200,200,200,200,200,200,404,200,
213+
200,500,200,200,200,200,200,
214+
],
215+
})
202216
log["hour"] = log["ts"].str.slice(0, 2).astype(int)
203217
log["cls"] = log["status"].apply(lambda s: "5xx" if s&gt;=500 else ("4xx" if s&gt;=400 else "2xx"))
204218
piv = log.groupby(["hour","cls"]).size().unstack(fill_value=0)
@@ -245,6 +259,12 @@ <h2>2 · Error rate per hour & alert threshold</h2>
245259
}
246260
if (flagged === 0) console.log(" (all hours healthy)");</textarea>
247261
<textarea class="playground-python" style="display:none">import pandas as pd
262+
by_hour = pd.DataFrame({
263+
"hour": [10, 11, 12, 13],
264+
"2xx": [6, 5, 7, 6],
265+
"4xx": [1, 1, 1, 0],
266+
"5xx": [1, 6, 0, 1],
267+
})
248268
by_hour["total"] = by_hour[["2xx","4xx","5xx"]].sum(axis=1)
249269
by_hour["5xx_pct"] = (by_hour["5xx"] / by_hour["total"] * 100).round(1)
250270
print(by_hour)

playground/example_pricing_buckets.html

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,11 @@ <h2>1 · Bucket products into price tiers</h2>
180180
console.log("\nProducts per tier:");
181181
console.log(valueCounts(enriched.col("tier")).toString());</textarea>
182182
<textarea class="playground-python" style="display:none">import pandas as pd
183+
catalogue = pd.DataFrame({
184+
"sku": ["A1","A2","A3","B1","B2","B3","C1","C2","C3","D1","D2","D3","E1","E2","E3"],
185+
"price": [9.99,14.50,19.00,22.00,29.50,39.00,49.00,65.00,79.99,99.00,129.00,149.00,199.00,249.00,349.00],
186+
"margin": [0.30,0.32,0.28,0.34,0.36,0.40,0.42,0.45,0.46,0.48,0.50,0.52,0.55,0.58,0.60],
187+
})
183188
catalogue["tier"] = pd.cut(
184189
catalogue["price"],
185190
bins=[0, 25, 75, 150, 1000],
@@ -244,6 +249,13 @@ <h2>2 · Avg margin by tier</h2>
244249
console.log("");
245250
chart("Avg margin % per tier", rows);</textarea>
246251
<textarea class="playground-python" style="display:none">import pandas as pd
252+
enriched = pd.DataFrame({
253+
"sku": ["A1","A2","A3","B1","B2","B3","C1","C2","C3","D1","D2","D3","E1","E2","E3"],
254+
"price": [9.99,14.50,19.00,22.00,29.50,39.00,49.00,65.00,79.99,99.00,129.00,149.00,199.00,249.00,349.00],
255+
"margin": [0.30,0.32,0.28,0.34,0.36,0.40,0.42,0.45,0.46,0.48,0.50,0.52,0.55,0.58,0.60],
256+
"tier": ["Budget","Budget","Budget","Budget","Mid","Mid","Mid","Mid",
257+
"Premium","Premium","Premium","Premium","Luxury","Luxury","Luxury"],
258+
})
247259
by_tier = enriched.groupby("tier", as_index=False).agg(
248260
avg_price=("price","mean"),
249261
avg_margin=("margin","mean"),

playground/example_sales_dashboard.html

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,20 @@ <h2>1 · Load the sales CSV</h2>
188188

189189
csv = """order_id,date,region,product,units,unit_price
190190
1001,2024-01-03,North,Widget,4,19.99
191-
..."""
191+
1002,2024-01-05,South,Gadget,2,49.50
192+
1003,2024-01-09,East,Widget,7,19.99
193+
1004,2024-01-12,West,Gizmo,1,129.00
194+
1005,2024-01-18,North,Gadget,3,49.50
195+
1006,2024-01-22,South,Widget,5,19.99
196+
1007,2024-02-02,East,Gizmo,2,129.00
197+
1008,2024-02-08,North,Widget,6,19.99
198+
1009,2024-02-14,West,Gadget,4,49.50
199+
1010,2024-02-19,South,Gizmo,1,129.00
200+
1011,2024-03-01,East,Widget,8,19.99
201+
1012,2024-03-05,North,Gizmo,2,129.00
202+
1013,2024-03-11,West,Widget,3,19.99
203+
1014,2024-03-17,South,Gadget,6,49.50
204+
1015,2024-03-25,East,Gadget,2,49.50"""
192205
sales = pd.read_csv(StringIO(csv))
193206
print("Rows:", sales.shape[0], "Columns:", list(sales.columns))
194207
print(sales.head(5))</textarea>
@@ -258,6 +271,25 @@ <h2>2 · Compute revenue & rank regions</h2>
258271
console.log("");
259272
chart("Revenue by region ($)", rows);</textarea>
260273
<textarea class="playground-python" style="display:none">import pandas as pd
274+
from io import StringIO
275+
276+
csv = """order_id,region,product,units,unit_price
277+
1001,North,Widget,4,19.99
278+
1002,South,Gadget,2,49.50
279+
1003,East,Widget,7,19.99
280+
1004,West,Gizmo,1,129.00
281+
1005,North,Gadget,3,49.50
282+
1006,South,Widget,5,19.99
283+
1007,East,Gizmo,2,129.00
284+
1008,North,Widget,6,19.99
285+
1009,West,Gadget,4,49.50
286+
1010,South,Gizmo,1,129.00
287+
1011,East,Widget,8,19.99
288+
1012,North,Gizmo,2,129.00
289+
1013,West,Widget,3,19.99
290+
1014,South,Gadget,6,49.50
291+
1015,East,Gadget,2,49.50"""
292+
sales = pd.read_csv(StringIO(csv))
261293

262294
sales["revenue"] = sales["units"] * sales["unit_price"]
263295
by_region = sales.groupby("region", as_index=False)["revenue"].sum()
@@ -316,6 +348,25 @@ <h2>3 · Top products & best single order</h2>
316348
console.log("\nTop 3 single orders by revenue:");
317349
console.log(top3.toString());</textarea>
318350
<textarea class="playground-python" style="display:none">import pandas as pd
351+
from io import StringIO
352+
353+
csv = """order_id,region,product,units,unit_price
354+
1001,North,Widget,4,19.99
355+
1002,South,Gadget,2,49.50
356+
1003,East,Widget,7,19.99
357+
1004,West,Gizmo,1,129.00
358+
1005,North,Gadget,3,49.50
359+
1006,South,Widget,5,19.99
360+
1007,East,Gizmo,2,129.00
361+
1008,North,Widget,6,19.99
362+
1009,West,Gadget,4,49.50
363+
1010,South,Gizmo,1,129.00
364+
1011,East,Widget,8,19.99
365+
1012,North,Gizmo,2,129.00
366+
1013,West,Widget,3,19.99
367+
1014,South,Gadget,6,49.50
368+
1015,East,Gadget,2,49.50"""
369+
sales = pd.read_csv(StringIO(csv))
319370

320371
sales["revenue"] = sales["units"] * sales["unit_price"]
321372
by_product = sales.groupby("product", as_index=False).agg(

playground/example_sports_standings.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,12 @@ <h2>1 · Build the standings table</h2>
205205
console.log("League table:");
206206
console.log(withRank.toString());</textarea>
207207
<textarea class="playground-python" style="display:none">import pandas as pd
208+
matches = pd.DataFrame({
209+
"home": ["Lions","Tigers","Bears","Wolves","Lions","Bears","Tigers","Wolves","Lions","Tigers","Bears","Wolves"],
210+
"away": ["Tigers","Bears","Wolves","Lions","Wolves","Tigers","Lions","Bears","Bears","Wolves","Lions","Tigers"],
211+
"home_goals": [2,1,3,0,4,2,1,2,1,2,3,1],
212+
"away_goals": [1,1,2,2,0,2,3,1,1,1,2,1],
213+
})
208214
home = matches.rename(columns={"home":"team","home_goals":"gf","away_goals":"ga"})[["team","gf","ga"]]
209215
away = matches.rename(columns={"away":"team","away_goals":"gf","home_goals":"ga"})[["team","gf","ga"]]
210216
team_matches = pd.concat([home, away], ignore_index=True)

playground/example_stock_returns.html

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,15 @@ <h2>1 · Daily prices and returns</h2>
182182
console.log("\nMean daily return:", meanRet.toFixed(3) + "%");
183183
console.log("Std daily return:", stdRet.toFixed(3) + "%");</textarea>
184184
<textarea class="playground-python" style="display:none">import pandas as pd
185-
prices = pd.DataFrame({"date": [...], "close": [...]})
185+
prices = pd.DataFrame({
186+
"date": [
187+
"2024-01-02","2024-01-03","2024-01-04","2024-01-05","2024-01-08",
188+
"2024-01-09","2024-01-10","2024-01-11","2024-01-12","2024-01-16",
189+
"2024-01-17","2024-01-18","2024-01-19","2024-01-22","2024-01-23",
190+
],
191+
"close": [100.0,101.5,99.8,102.1,103.4,102.7,104.0,105.6,104.9,
192+
106.3,107.0,106.2,108.5,109.1,110.0],
193+
})
186194
prices["return"] = prices["close"].pct_change()
187195
print(prices.head(8))
188196
print("Mean:", prices["return"].mean()*100, "%")
@@ -236,6 +244,11 @@ <h2>2 · Rolling stats & SMA crossover signal</h2>
236244
if (signals.length === 0) console.log(" (no crossovers in window)");
237245
for (const s of signals) console.log(" " + s);</textarea>
238246
<textarea class="playground-python" style="display:none">import pandas as pd
247+
prices = pd.DataFrame({
248+
"day": list(range(1, 16)),
249+
"close": [100.0,101.5,99.8,102.1,103.4,102.7,104.0,105.6,104.9,
250+
106.3,107.0,106.2,108.5,109.1,110.0],
251+
})
239252
close = prices["close"]
240253
prices["sma3"] = close.rolling(3).mean()
241254
prices["sma5"] = close.rolling(5).mean()

playground/example_survey_crosstab.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@ <h2>1 · Build the crosstab</h2>
176176
console.log("Counts (rows = experience, cols = language):");
177177
console.log(ct.toString());</textarea>
178178
<textarea class="playground-python" style="display:none">import pandas as pd
179+
langs = ["Python","JavaScript","Rust","Go","Python","JavaScript","Python","Rust","Go","JavaScript","Python","JavaScript","Rust","Python","Go","JavaScript","Python","Rust","Python","JavaScript","Go","Python","JavaScript","Rust","Python","Go","JavaScript","Python","Python","Rust"]
180+
exp = ["Junior","Junior","Senior","Mid","Mid","Senior","Junior","Senior","Junior","Mid","Senior","Junior","Senior","Mid","Senior","Senior","Mid","Mid","Junior","Senior","Mid","Senior","Mid","Senior","Mid","Junior","Senior","Junior","Senior","Mid"]
179181
survey = pd.DataFrame({"language": langs, "experience": exp})
180182
ct = pd.crosstab(survey["experience"], survey["language"])
181183
print(ct)</textarea>
@@ -211,6 +213,9 @@ <h2>2 · Row percentages</h2>
211213

212214
console.log("\nObservation: the largest cell in each row tells you that cohort's favourite language.");</textarea>
213215
<textarea class="playground-python" style="display:none">import pandas as pd
216+
langs = ["Python","JavaScript","Rust","Go","Python","JavaScript","Python","Rust","Go","JavaScript","Python","JavaScript","Rust","Python","Go","JavaScript","Python","Rust","Python","JavaScript","Go","Python","JavaScript","Rust","Python","Go","JavaScript","Python","Python","Rust"]
217+
exp = ["Junior","Junior","Senior","Mid","Mid","Senior","Junior","Senior","Junior","Mid","Senior","Junior","Senior","Mid","Senior","Senior","Mid","Mid","Junior","Senior","Mid","Senior","Mid","Senior","Mid","Junior","Senior","Junior","Senior","Mid"]
218+
survey = pd.DataFrame({"language": langs, "experience": exp})
214219
ct = pd.crosstab(survey["experience"], survey["language"], normalize="index")
215220
print(ct.round(3))</textarea>
216221
<div class="playground-output">Click ▶ Run to execute</div>

0 commit comments

Comments
 (0)