diff --git a/.gitignore b/.gitignore index 1c09dc2..4f61cd2 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,5 @@ playwright-report/ test-results/ runongpu-chrome-profile/ + +.ruff_cache/ \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index d27b4c9..3325438 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ name = "runongpu" version = "1.0.2" description = "A CLI tool that runs GitHub projects on free cloud GPUs" -requires-python = ">=3.12" +requires-python = ">=3.10" readme = "README.md" # Runtime dependencies for the CLI. diff --git a/runongpu.txt b/runongpu.txt index 9dd96ba..b4a81bf 100644 --- a/runongpu.txt +++ b/runongpu.txt @@ -31,9 +31,9 @@ [setup] [build] -cd cuda/vector-add && nvcc main.cu -o vector_add +nvcc test_cuda.cu -o test_cuda [test] [run] -cd cuda/vector-add && ./vector_add \ No newline at end of file +./test_cuda \ No newline at end of file diff --git a/runongpu/cli.py b/runongpu/cli.py index 82a3a4e..3477749 100644 --- a/runongpu/cli.py +++ b/runongpu/cli.py @@ -4,11 +4,17 @@ # Prints styled terminal output for a better CLI experience. from rich.console import Console -# Project helpers for saving local config, creating runongpu.txt, and loading user settings. -from runongpu.config import create_runongpu_template_file, get_folder_name_from_repo_url, save_notebook_url, save_repo_url, load_config from runongpu.colab import open_colab -from runongpu.parser import parse_config +# Project helpers for saving local config, creating runongpu.txt, and loading user settings. +from runongpu.config import ( + create_runongpu_template_file, + get_folder_name_from_repo_url, + load_config, + save_notebook_url, + save_repo_url, +) +from runongpu.parser import parse_config app = typer.Typer() console = Console() @@ -16,10 +22,9 @@ @app.command() def doctor(): - - # Verifies that the user's local RunOnGPU setup has the required pieces installed. - console.print("[bold cyan]Checking RunOnGPU setup...[/bold cyan]") + """Verifies that the user's local RunOnGPU setup has the required pieces installed.""" + console.print("[bold cyan]Checking RunOnGPU setup...[/bold cyan]") console.print("[green]✓ CLI is running[/green]") console.print("[green]✓ Typer is installed[/green]") console.print("[green]✓ Rich is installed[/green]") @@ -31,10 +36,11 @@ def doctor(): console.print("[yellow]Run: runongpu init[/yellow]") else: console.print("[green]✓ Repo URL is saved[/green]") - console.print(f"[green] Repo URL: {saved_config["repo_url"]}") + console.print(f"[green]✓ Repo URL: {saved_config['repo_url']}[/green]") try: - import playwright + import playwright # noqa: F401 + console.print("[green]✓ Playwright is installed[/green]") except ImportError: console.print("[red]✗ Playwright is not installed[/red]") @@ -43,7 +49,8 @@ def doctor(): @app.command() def init(): - # Store the GitHub repo that RunOnGPU should clone inside Colab. + """Save the repository configuration and create runongpu.txt.""" + repo_url = typer.prompt("Enter your Github repo URL") console.print("[yellow]Deriving folder name[/yellow]") @@ -60,7 +67,8 @@ def init(): @app.command() def config(): - # Show the saved local settings without opening Colab. + """Show the saved local settings without opening Colab.""" + saved_config = load_config() if saved_config is None: @@ -80,7 +88,14 @@ def config(): @app.command() def run(): - # Main workflow: parse project commands, open Colab, write the notebook cell, and save the notebook URL. + """ + Main workflow: + - parse project commands, + - open Colab, + - write the notebook cell, + - save the notebook URL. + """ + saved_config = load_config() if saved_config is None: @@ -105,4 +120,4 @@ def run(): if __name__ == "__main__": - app() \ No newline at end of file + app() diff --git a/runongpu/config.py b/runongpu/config.py index 26d84be..848775f 100644 --- a/runongpu/config.py +++ b/runongpu/config.py @@ -4,6 +4,7 @@ import json from pathlib import Path + from rich.console import Console console = Console() @@ -16,12 +17,9 @@ def save_repo_url(repo_url: str, folder_name: str) -> None: + CONFIG_DIR.mkdir(exist_ok=True) - config = { - "repo_url": repo_url, - "notebook_url": "", - "folder_name": folder_name - } + config = {"repo_url": repo_url, "notebook_url": "", "folder_name": folder_name} # Persist the selected project so future `runongpu run` calls know what to clone. with open(CONFIG_FILE, "w", encoding="utf-8") as file: @@ -58,7 +56,6 @@ def create_runongpu_template_file() -> None: txt_path = Path("runongpu.txt") if not txt_path.exists(): - txt_path.write_text( """# RunOnGPU Configuration # @@ -102,10 +99,12 @@ def create_runongpu_template_file() -> None: ) console.print("[green]✓ Added runongpu.txt to the repo. [/green]") else: - console.print("[yellow]runongpu.txt already exists. Good job! Proud of you! [/yellow]") + console.print( + "[yellow]runongpu.txt already exists. Good job! Proud of you! [/yellow]" + ) def get_folder_name_from_repo_url(repo_url: str) -> str: # Git clones repositories into a folder named after the repo, so derive that # folder name from the URL instead of asking the user to type it manually. - return repo_url.rstrip("/").split("/")[-1].replace(".git", "") \ No newline at end of file + return repo_url.rstrip("/").split("/")[-1].replace(".git", "") diff --git a/runongpu/parser.py b/runongpu/parser.py index 5db8801..5edb329 100644 --- a/runongpu/parser.py +++ b/runongpu/parser.py @@ -43,4 +43,4 @@ def parse_config() -> dict: config[current_section].append(line) - return config \ No newline at end of file + return config diff --git a/tests/test_config.py b/tests/test_config.py index a8e6eea..e4508c6 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -25,4 +25,4 @@ def test_get_folder_name_from_url_with_trailing_slash(): "https://github.com/MashrafeeAryan/runongpu-examples/" ) - assert result == "runongpu-examples" \ No newline at end of file + assert result == "runongpu-examples" diff --git a/tests/test_config_persistance.py b/tests/test_config_persistance.py index 92eeb70..6539799 100644 --- a/tests/test_config_persistance.py +++ b/tests/test_config_persistance.py @@ -40,4 +40,4 @@ def test_save_notebook_url_updates_existing_config(tmp_path, monkeypatch): assert result["repo_url"] == "https://github.com/MashrafeeAryan/RunOnGPU.git" assert result["folder_name"] == "RunOnGPU" - assert result["notebook_url"] == "https://colab.research.google.com/drive/test" \ No newline at end of file + assert result["notebook_url"] == "https://colab.research.google.com/drive/test" diff --git a/tests/test_parser.py b/tests/test_parser.py index 6b4ba11..d66276e 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -92,4 +92,4 @@ def test_command_before_section_raises_error(tmp_path, monkeypatch): monkeypatch.chdir(tmp_path) with pytest.raises(ValueError, match="Command found before any section header"): - parse_config() \ No newline at end of file + parse_config() diff --git a/tests/test_template.py b/tests/test_template.py index 5574976..d7c4795 100644 --- a/tests/test_template.py +++ b/tests/test_template.py @@ -22,7 +22,9 @@ def test_create_runongpu_template_file(tmp_path, monkeypatch): assert "[run]" in contents -def test_create_runongpu_template_file_does_not_overwrite_existing_file(tmp_path, monkeypatch): +def test_create_runongpu_template_file_does_not_overwrite_existing_file( + tmp_path, monkeypatch +): # Existing user configs should be preserved instead of overwritten. monkeypatch.chdir(tmp_path) @@ -31,4 +33,4 @@ def test_create_runongpu_template_file_does_not_overwrite_existing_file(tmp_path create_runongpu_template_file() - assert template_file.read_text(encoding="utf-8") == "[run]\npython main.py\n" \ No newline at end of file + assert template_file.read_text(encoding="utf-8") == "[run]\npython main.py\n"