{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#default_exp build_lib"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#export\n",
    "from fastcore.utils import *\n",
    "from fastcore.foundation import *\n",
    "\n",
    "import pprint\n",
    "# from json import loads\n",
    "from jsonref import loads\n",
    "from collections import namedtuple"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Internal - OpenAPI Parser"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This library leverages the [OpenAPI Specification](https://github.com/OAI/OpenAPI-Specification) to create a python client for the GitHub API.  The OpenAPI specification contains metadata on all of the endpoints and how to access them properly.  Using this metadata, we can construct a python client dynamically that updates automatically along with the OpenAPI Spec. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#export\n",
    "GH_OPENAPI_URL = 'https://github.com/github/rest-api-description/raw/main/descriptions/api.github.com/api.github.com.json?raw=true'\n",
    "_DOC_URL = 'https://docs.github.com/'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#hide\n",
    "if 1:\n",
    "    s = urlread(GH_OPENAPI_URL)\n",
    "    js = loads(s)['paths']\n",
    "\n",
    "    t = js['/repos/{owner}/{repo}/hooks']\n",
    "    params = nested_idx(t, 'get','parameters')\n",
    "    [o['name'] for o in params if o['in']=='query']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#export\n",
    "_lu_type = dict(zip(\n",
    "    'NA string object array boolean integer'.split(),\n",
    "    map(PrettyString,'object str dict list bool int'.split())\n",
    "))\n",
    "\n",
    "def _detls(k,v):\n",
    "    res = [_lu_type[v.get('type', 'NA')]]\n",
    "    try: res.append(v['default'])\n",
    "    except KeyError: pass\n",
    "    return [k]+res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#export\n",
    "def build_funcs(nm='ghapi/metadata.py', url=GH_OPENAPI_URL, docurl=_DOC_URL):\n",
    "    \"Build module metadata.py from an Open API spec and optionally filter by a path `pre`\"\n",
    "    def _get_detls(o):\n",
    "        data = nested_idx(o, *'requestBody content application/json schema properties'.split()) or {}\n",
    "        url = o['externalDocs']['url'][len(docurl):]\n",
    "        params = o.get('parameters',None)\n",
    "        qparams = [p['name'] for p in params if p['in']=='query'] if params else []\n",
    "        d = [_detls(*o) for o in data.items()]\n",
    "        preview = nested_idx(o, 'x-github','previews',0,'name') or ''\n",
    "        return (o['operationId'], o['summary'], url, qparams, d, preview)\n",
    "\n",
    "    js = loads(urlread(url))\n",
    "    _funcs = [(path, verb) + _get_detls(detls)\n",
    "              for path,verbs in js['paths'].items() for verb,detls in verbs.items()\n",
    "              if 'externalDocs' in detls]\n",
    "    Path(nm).write_text(\"funcs = \" + pprint.pformat(_funcs, width=360))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#hide\n",
    "build_funcs()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This module created by `build_funcs` contains a list of metadata for each endpoint, containing the path, verb, operation id, summary, documentation relative URL, and list of parameters (if any), e.g:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#export\n",
    "GhMeta = namedtuple('GhMeta', 'path verb oper_id summary doc_url params data preview'.split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "GhMeta(path='/app/hook/config', verb='patch', oper_id='apps/update-webhook-config-for-app', summary='Update a webhook configuration for an app', doc_url='v3/apps#update-a-webhook-configuration-for-an-app', params=[], data=[['url', <class 'str'>], ['content_type', <class 'str'>], ['secret', <class 'str'>], ['insecure_ssl', <class 'str'>]], preview='')"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from ghapi.metadata import funcs\n",
    "GhMeta(*funcs[3])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Export -"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Converted 00_core.ipynb.\n",
      "Converted 01_actions.ipynb.\n",
      "Converted 02_auth.ipynb.\n",
      "Converted 03_page.ipynb.\n",
      "Converted 04_event.ipynb.\n",
      "Converted 10_cli.ipynb.\n",
      "Converted 50_fullapi.ipynb.\n",
      "Converted 80_tutorial_actions.ipynb.\n",
      "Converted 90_build_lib.ipynb.\n",
      "Converted Untitled.ipynb.\n",
      "Converted ghapi demo.ipynb.\n",
      "Converted index.ipynb.\n"
     ]
    }
   ],
   "source": [
    "#hide\n",
    "from nbdev.export import notebook2script\n",
    "notebook2script()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
