{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "cell-23-07-00",
   "metadata": {},
   "source": [
    "# 23-07 · Parsowanie argumentów w wierszu poleceń\n",
    "\n",
    "Praktyka do sekcji [„pyproject.toml i instalacja projektu”](/pl/chapters/rozdzial-23/23-05-pyproject-toml.html) i sekcji [„Komandna łańcuch znaków SafeSort”](/pl/chapters/rozdzial-23/23-06-komandnaya-stroka.html). Niniejszy plik — `projects/python/safesort/src/safesort/cli.py`."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cell-23-07-01",
   "metadata": {},
   "source": [
    "## Cel\n",
    "\n",
    "Zbuduj parser, który odwzoruje kształt prawdziwego elementu `safesort.cli.build_parser()`: pięć podkomend, każde z argumentem pozycyjnym `root`, a `undo` wie, jak się obyć bez kłótni."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cell-23-07-02",
   "metadata": {},
   "source": [
    "## Example"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cell-23-07-03",
   "metadata": {},
   "outputs": [],
   "source": [
    "import argparse\n",
    "from pathlib import Path\n",
    "\n",
    "\n",
    "def build_parser():\n",
    "    parser = argparse.ArgumentParser(\n",
    "        prog=\"safesort\",\n",
    "        description=(\n",
    "            \"SafeSort: a safe, non-destructive file organizer. \"\n",
    "            \"scan/plan/duplicates are read-only; 'apply' sorts and 'undo' restores files.\"\n",
    "        ),\n",
    "    )\n",
    "    subparsers = parser.add_subparsers(dest=\"command\", required=True)\n",
    "\n",
    "    for name in (\"scan\", \"plan\", \"apply\", \"duplicates\"):\n",
    "        sub = subparsers.add_parser(name)\n",
    "        sub.add_argument(\"root\", type=Path)\n",
    "\n",
    "    undo_parser = subparsers.add_parser(\"undo\")\n",
    "    undo_parser.add_argument(\"root\", type=Path, nargs=\"?\", default=Path(\".\"))\n",
    "\n",
    "    return parser\n",
    "\n",
    "\n",
    "parser = build_parser()\n",
    "\n",
    "args_scan = parser.parse_args([\"scan\", \"/home/anna/Downloads\"])\n",
    "args_apply = parser.parse_args([\"apply\", \"/home/anna/Downloads\"])\n",
    "args_undo_default = parser.parse_args([\"undo\"])\n",
    "args_undo_explicit = parser.parse_args([\"undo\", \"/home/anna/Downloads\"])\n",
    "\n",
    "print(args_scan)\n",
    "print(args_undo_default)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cell-23-07-04",
   "metadata": {},
   "source": [
    "## Sprawdzenie wyniku"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cell-23-07-05",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert args_scan.command == \"scan\"\n",
    "assert args_scan.root == Path(\"/home/anna/Downloads\")\n",
    "assert args_apply.command == \"apply\"\n",
    "assert args_undo_default.command == \"undo\"\n",
    "assert args_undo_default.root == Path(\".\")\n",
    "assert args_undo_explicit.root == Path(\"/home/anna/Downloads\")\n",
    "print(\"Верно: пять подкоманд разобраны, а undo получает root по умолчанию, если он не передан.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cell-23-07-06",
   "metadata": {},
   "source": [
    "## Eksperyment - Bez podpolecenia argparse sam zgłasza błąd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cell-23-07-07",
   "metadata": {},
   "outputs": [],
   "source": [
    "import contextlib\n",
    "import io\n",
    "\n",
    "buffer = io.StringIO()\n",
    "try:\n",
    "    with contextlib.redirect_stderr(buffer):\n",
    "        parser.parse_args([])\n",
    "    kod_zaversheniya = None\n",
    "except SystemExit as exc:\n",
    "    kod_zaversheniya = exc.code\n",
    "\n",
    "print(\"Код завершения:\", kod_zaversheniya)\n",
    "assert kod_zaversheniya is not None and kod_zaversheniya != 0\n",
    "print(\"Верно: dest=\\\"command\\\", required=True сам формирует понятную ошибку без ручных проверок.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cell-23-07-08",
   "metadata": {},
   "source": [
    "## Starter\n",
    "\n",
    "Wypełnij zaznaczone miejsce. Niezmieniony starter nie przechodzi tests."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "task-23-07",
   "metadata": {
    "tags": [
     "exercise",
     "starter"
    ]
   },
   "outputs": [],
   "source": [
    "def razobrat_duplicates(path_text: str):\n",
    "    \"\"\"Parse `safesort duplicates PATH` with the existing parser.\"\"\"\n",
    "    # TODO: return parser.parse_args([...]).\n",
    "    raise NotImplementedError\n",
    "\n",
    "\n",
    "zadanie_args = razobrat_duplicates(\"/home/anna/Photos\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cell-23-07-10",
   "metadata": {},
   "source": [
    "## Task\n",
    "\n",
    "Napisz funkcję, która analizuje podpokomendę `duplicates` dla dowolnej ścieżki tekstowej."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cell-23-07-11",
   "metadata": {},
   "source": [
    "## Tests\n",
    "\n",
    "Run After task cell: jest podstawowy przykład i przynajmniej jeden skrajny przypadek."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "tests-23-07",
   "metadata": {
    "tags": [
     "exercise-tests"
    ]
   },
   "outputs": [],
   "source": [
    "assert zadanie_args.command == \"duplicates\"\n",
    "assert zadanie_args.root == Path(\"/home/anna/Photos\")\n",
    "assert razobrat_duplicates(\"/tmp/Photo Archive\").root == Path(\"/tmp/Photo Archive\")\n",
    "print(\"Tests passed\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cell-23-07-13",
   "metadata": {},
   "source": [
    "## Hint\n",
    "\n",
    "Lista argv zawiera dokładnie dwa elementy: nazwę podpolecenia i ścieżkę."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cell-23-07-14",
   "metadata": {},
   "source": [
    "## Solution\n",
    "\n",
    "Pokaż rozwiązanie po własnej próbie</summary>\n",
    "\n",
    "```python\n",
    "def razobrat_duplicates(path_text: str):\n",
    "    return parser.parse_args([\"duplicates\", path_text])\n",
    "\n",
    "\n",
    "zadanie_args = razobrat_duplicates(\"/home/anna/Photos\")\n",
    "```\n",
    "\n",
    "</details>"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Cartesian Python 3.14",
   "language": "python",
   "name": "cartesian-python314"
  },
  "language_info": {
   "name": "python",
   "version": "3.14.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
