| from __future__ import annotations |
|
|
| import json |
| from pathlib import Path |
|
|
|
|
| ROOT = Path(__file__).resolve().parents[1] |
| NOTEBOOK_DIR = ROOT / "notebooks" |
| USERNAME = "Sami94" |
| STUDENT_NAME = "Sami Chellia" |
|
|
|
|
| def source(text: str) -> list[str]: |
| return text.splitlines(keepends=True) |
|
|
|
|
| def noop(reason: str) -> list[str]: |
| return source(f"# Local patch for {STUDENT_NAME} ({USERNAME})\n# Skipped: {reason}\n") |
|
|
|
|
| def hf_whoami() -> list[str]: |
| return source( |
| "from huggingface_hub import HfApi\n" |
| "print('HF user:', HfApi().whoami().get('name'))\n" |
| ) |
|
|
|
|
| def read_nb(path: Path) -> dict: |
| return json.loads(path.read_text(encoding="utf-8")) |
|
|
|
|
| def write_nb(path: Path, nb: dict) -> None: |
| nb.setdefault("metadata", {}) |
| nb["metadata"]["student_name"] = STUDENT_NAME |
| nb["metadata"]["hf_username"] = USERNAME |
| path.write_text(json.dumps(nb, ensure_ascii=False, indent=1), encoding="utf-8") |
|
|
|
|
| def replace_in_all_cells(nb: dict, replacements: dict[str, str]) -> None: |
| for cell in nb.get("cells", []): |
| if "source" not in cell: |
| continue |
| text = "".join(cell["source"]) |
| for old, new in replacements.items(): |
| text = text.replace(old, new) |
| cell["source"] = source(text) |
|
|
|
|
| def set_cell(nb: dict, one_based_index: int, text: list[str]) -> None: |
| nb["cells"][one_based_index - 1]["source"] = text |
|
|
|
|
| def patch_unit1(nb: dict) -> None: |
| set_cell(nb, 15, noop("apt install swig/cmake is Linux-only; install Windows dependencies outside the notebook.")) |
| set_cell(nb, 18, noop("Linux OpenGL/Xvfb setup is not needed in this Windows local run.")) |
| set_cell(nb, 20, noop("Colab kernel restart would kill local execution.")) |
| set_cell(nb, 21, noop("pyvirtualdisplay/Xvfb is Linux-only.")) |
| set_cell(nb, 39, noop("placeholder cell; solution cell below is used.")) |
| set_cell(nb, 43, noop("placeholder cell; solution cell below is used.")) |
| set_cell(nb, 47, noop("placeholder cell; solution cell below is used.")) |
| set_cell(nb, 54, hf_whoami()) |
| set_cell(nb, 58, noop("duplicate placeholder push cell; completed push cell below is used.")) |
| replace_in_all_cells( |
| nb, |
| { |
| 'repo_id = "ThomasSimonini/ppo-LunarLander-v2"': 'repo_id = "Sami94/ppo-LunarLander-v2"', |
| 'repo_id = "Classroom-workshop/assignment2-omar"': 'repo_id = "Sami94/ppo-LunarLander-v2"', |
| }, |
| ) |
|
|
|
|
| def patch_unit2(nb: dict) -> None: |
| set_cell(nb, 15, noop("Linux OpenGL/Xvfb setup is not needed in this Windows local run.")) |
| set_cell(nb, 17, noop("Colab kernel restart would kill local execution.")) |
| set_cell(nb, 18, noop("pyvirtualdisplay/Xvfb is Linux-only.")) |
| for index in [25, 35, 36, 43, 47, 53]: |
| set_cell(nb, index, noop("placeholder cell; solution cell below is used.")) |
| set_cell(nb, 72, hf_whoami()) |
| replace_in_all_cells( |
| nb, |
| { |
| 'username = "" # FILL THIS': 'username = "Sami94"', |
| 'repo_name = "" # FILL THIS': 'repo_name = "q-Taxi-v3"', |
| 'repo_id="ThomasSimonini/q-Taxi-v3"': 'repo_id="Sami94/q-Taxi-v3"', |
| 'repo_id="ThomasSimonini/q-FrozenLake-v1-no-slippery"': 'repo_id="Sami94/q-FrozenLake-v1-4x4-noSlippery"', |
| }, |
| ) |
|
|
|
|
| def patch_unit3(nb: dict) -> None: |
| for index in [16, 20]: |
| set_cell(nb, index, noop("Linux apt/OpenGL/Xvfb setup is not needed in this Windows local run.")) |
| for index in [26, 30, 41]: |
| set_cell(nb, index, noop("placeholder command; completed command below is used.")) |
| set_cell(nb, 37, hf_whoami()) |
| replace_in_all_cells(nb, {'-orga ThomasSimonini': '-orga Sami94'}) |
|
|
|
|
| def patch_unit4(nb: dict) -> None: |
| set_cell(nb, 14, noop("Linux OpenGL/Xvfb setup is not needed in this Windows local run.")) |
| set_cell(nb, 15, noop("pyvirtualdisplay/Xvfb is Linux-only.")) |
| for index in [32, 45, 74]: |
| set_cell(nb, index, noop("placeholder cell; solution cell below is used.")) |
| set_cell(nb, 63, hf_whoami()) |
| set_cell( |
| nb, |
| 66, |
| source( |
| 'repo_id = "Sami94/Reinforce-CartPole-v1"\n' |
| "push_to_hub(repo_id,\n" |
| " cartpole_policy,\n" |
| " cartpole_hyperparameters,\n" |
| " eval_env,\n" |
| " video_fps=30\n" |
| " )\n" |
| ), |
| ) |
| set_cell( |
| nb, |
| 83, |
| source( |
| 'repo_id = "Sami94/Reinforce-Pixelcopter-PLE-v0"\n' |
| "push_to_hub(repo_id,\n" |
| " pixelcopter_policy,\n" |
| " pixelcopter_hyperparameters,\n" |
| " eval_env,\n" |
| " video_fps=30\n" |
| " )\n" |
| ), |
| ) |
|
|
|
|
| def patch_unit5(nb: dict) -> None: |
| replace_in_all_cells( |
| nb, |
| { |
| '--repo-id="ThomasSimonini/ppo-SnowballTarget"': '--repo-id="Sami94/ppo-SnowballTarget"', |
| }, |
| ) |
| set_cell(nb, 44, noop("placeholder push command; fill only after local Unity training exists.")) |
| set_cell(nb, 61, noop("placeholder push command; fill only after local Unity training exists.")) |
|
|
|
|
| def patch_unit6(nb: dict) -> None: |
| set_cell(nb, 13, noop("Linux OpenGL/Xvfb setup is not needed in this Windows local run.")) |
| set_cell(nb, 14, noop("pyvirtualdisplay/Xvfb is Linux-only.")) |
| for index in [29, 33]: |
| set_cell(nb, index, noop("placeholder cell; solution cell below is used.")) |
| set_cell(nb, 44, hf_whoami()) |
| replace_in_all_cells(nb, {'repo_id=f"ThomasSimonini/a2c-{env_id}"': 'repo_id=f"Sami94/a2c-{env_id}"'}) |
|
|
|
|
| def patch_unit8_part1(nb: dict) -> None: |
| set_cell(nb, 14, noop("Linux OpenGL/Xvfb/swig setup is not needed in this Windows local run.")) |
| set_cell(nb, 34, hf_whoami()) |
| replace_in_all_cells( |
| nb, |
| { |
| '--repo-id="YOUR_REPO_ID"': '--repo-id="Sami94/ppo-LunarLander-v2-cleanrl"', |
| 'default="ThomasSimonini/ppo-CartPole-v1"': 'default="Sami94/ppo-CartPole-v1"', |
| }, |
| ) |
|
|
|
|
| def patch_unit8_part2(nb: dict) -> None: |
| set_cell(nb, 11, noop("ViZDoom apt dependencies are Linux-only and cannot run in this Windows notebook.")) |
| set_cell(nb, 28, hf_whoami()) |
| replace_in_all_cells(nb, {'hf_username = "ThomasSimonini"': 'hf_username = "Sami94"'}) |
|
|
|
|
| def patch_bonus(nb: dict) -> None: |
| replace_in_all_cells(nb, {'--repo-id="ThomasSimonini/ppo-Huggy"': '--repo-id="Sami94/ppo-Huggy"'}) |
|
|
|
|
| PATCHERS = { |
| "notebooks__bonus-unit1__bonus-unit1.ipynb": patch_bonus, |
| "notebooks__bonus-unit1__bonus_unit1.ipynb": patch_bonus, |
| "notebooks__unit1__unit1.ipynb": patch_unit1, |
| "notebooks__unit2__unit2.ipynb": patch_unit2, |
| "notebooks__unit3__unit3.ipynb": patch_unit3, |
| "notebooks__unit4__unit4.ipynb": patch_unit4, |
| "notebooks__unit5__unit5.ipynb": patch_unit5, |
| "notebooks__unit6__unit6.ipynb": patch_unit6, |
| "notebooks__unit8__unit8_part1.ipynb": patch_unit8_part1, |
| "notebooks__unit8__unit8_part2.ipynb": patch_unit8_part2, |
| } |
|
|
|
|
| def main() -> None: |
| for filename, patcher in PATCHERS.items(): |
| path = NOTEBOOK_DIR / filename |
| nb = read_nb(path) |
| patcher(nb) |
| write_nb(path, nb) |
| print(f"patched {path}") |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|