{ "cells": [ { "cell_type": "markdown", "id": "cb54a2c7", "metadata": {}, "source": [ "# Validate your requirements.yaml file\n", "\n", "You might have created your `requirements.yaml` file manually or using the requirements generator notebook and you have modified it. Use this notebook to validate that the file is correctly formatted. You can use this notebook to validate your `requirements.yaml` file before uploading it to your repository.\n", "\n", "> **NOTE**: You do not need to run this notebook in the same environment as the one used to run the notebook you are uploading." ] }, { "cell_type": "code", "execution_count": null, "id": "4bd33249", "metadata": { "cellView": "form", "collapsed": false, "jupyter": { "source_hidden": true }, "jupyterlabHideCode": { "locked": true } }, "outputs": [], "source": [ "# @markdown Validate your requirements.yaml file\n", "\n", "import yaml\n", "from pathlib import Path\n", "import ipywidgets as widgets\n", "from IPython.display import display\n", "\n", "required_keys = {\"dependencies\", \"python_version\", \"description\"}\n", "alt_python_key = \"python\"\n", "\n", "def validate_requirements(path: Path):\n", " if not path.exists():\n", " return False, [f\"File not found: {path}\"]\n", " try:\n", " with path.open(\"r\", encoding=\"utf-8\") as f:\n", " data = yaml.safe_load(f)\n", " except Exception as exc:\n", " return False, [f\"YAML read error: {exc}\"]\n", " if not isinstance(data, dict):\n", " return False, [\"YAML root must be a mapping (key/value pairs).\"]\n", "\n", " keys = set(data.keys())\n", " missing = required_keys - keys\n", " messages = []\n", " python_key = \"python_version\"\n", " if \"python_version\" not in data and alt_python_key in data:\n", " python_key = alt_python_key\n", " missing -= {\"python_version\"}\n", " if missing:\n", " messages.append(\"Missing required keys: \" + \", \".join(sorted(missing)))\n", "\n", " deps = data.get(\"dependencies\")\n", " if deps is None:\n", " messages.append(\"Key 'dependencies' is required.\")\n", " elif not isinstance(deps, list):\n", " messages.append(\"'dependencies' must be a YAML list (lines prefixed with '- ').\")\n", " else:\n", " for d in deps:\n", " if not isinstance(d, str):\n", " messages.append(f\"{d} (is not a string)\")\n", " elif not d.strip():\n", " messages.append(f\"{d} (is an empty string)\")\n", " elif ' - ' in d:\n", " messages.append(f\"{d} (contains ' - ': possible indentation error in YAML)\")\n", "\n", " if python_key not in data:\n", " messages.append(\"'python_version' is required.\")\n", " elif not isinstance(data.get(python_key), str) or not data.get(python_key).strip():\n", " messages.append(f\"'{python_key}' must be a non-empty string (for example: 3.10.13).\")\n", "\n", " if \"description\" not in data or not isinstance(data.get(\"description\"), str) or not data.get(\"description\").strip():\n", " messages.append(\"'description' must be a non-empty string.\")\n", "\n", " return len(messages) == 0, messages\n", "\n", "path_input = widgets.Text(\n", " value=\"requirements.yaml\",\n", " description=\"Path:\",\n", " layout=widgets.Layout(width=\"99%\"),\n", " style={\"description_width\": \"initial\"},\n", ")\n", "validate_btn = widgets.Button(\n", " description=\"Validate requirements.yaml\",\n", " button_style=\"success\",\n", " layout=widgets.Layout(width=\"99%\"),\n", ")\n", "output_html = widgets.HTML()\n", "\n", "def on_validate(_):\n", " path = Path(path_input.value).expanduser().resolve()\n", " ok, messages = validate_requirements(path)\n", " if ok:\n", " output_html.value = f\"✅ Validation passed for {path.name}.\"\n", " else:\n", " output_html.value = f\"⚠️ Issues found in the given {path.name}: