{ "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.all 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 0:\n", " s = urlread(GH_OPENAPI_URL)\n", " js = loads(s)['paths']\n", " sj = {o['operationId']:o for p in js.values() for o in p.values()}\n", "\n", " j = js['/repos/{owner}/{repo}/issues/{issue_number}/labels']['post']\n", " n = nested_idx(j, *'requestBody content application/json schema'.split())" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#|export\n", "_lu_type = dict(zip(\n", " 'NA string object array boolean number integer'.split(),\n", " map(PrettyString,'object str dict list bool int 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\n", "\n", "def _find_data(d):\n", " if 'properties' in d: return d['properties']\n", " if 'oneOf' in d:\n", " for o in d['oneOf']:\n", " if 'properties' in o: return o['properties']\n", " return {}" ] }, { "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'.split()) or {}\n", " data = _find_data(data)\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": [], "source": [ "from ghapi.metadata import funcs" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "GhMeta(path='/app/hook/config', verb='get', oper_id='apps/get-webhook-config-for-app', summary='Get a webhook configuration for an app', doc_url='rest/reference/apps#get-a-webhook-configuration-for-an-app', params=[], data=[], preview='')" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "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 import nbdev_export\n", "nbdev_export()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" } }, "nbformat": 4, "nbformat_minor": 4 }