{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#default_exp event" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# The events API\n", "\n", "> Helpers for getting GitHub API events" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#export\n", "from fastcore.utils import *\n", "from fastcore.foundation import *\n", "from fastcore.meta import *\n", "from ghapi.core import *\n", "from ghapi.page import *\n", "\n", "import time,json,gzip\n", "from itertools import islice" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "api = GhApi()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#export\n", "def _list_events(g, username=None, org=None, owner=None, repo=None):\n", " if (username or org or owner) and \\\n", " not (bool(username) ^ bool(org) ^ bool(owner)): raise Exception('Can not pass more than one of username, org, and owner')\n", " if (owner and not repo): owner,repo = repo.split('/')\n", " if owner: return g.list_public_events_for_repo_network,{'owner':owner,'repo':repo}\n", " if org: return g.list_public_org_events,{'org':org}\n", " if username: return g.list_public_events_for_user,{'username':username}\n", " return g.list_public_events,{}" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#export\n", "def _id2int(x):\n", " x.id = int(x.id)\n", " return x" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#export\n", "@patch\n", "@delegates(_list_events)\n", "def list_events(self:GhApi, per_page=30, page=1, **kwargs):\n", " \"Fetch public events for repo network, org, user, or all\"\n", " oper,kw = _list_events(self.activity, **kwargs)\n", " return oper(per_page=per_page, page=page, **kw).map(_id2int)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#export\n", "@patch\n", "@delegates(_list_events)\n", "def list_events_parallel(self:GhApi, per_page=30, n_pages=8, **kwargs):\n", " \"Fetch as many events from `list_events` in parallel as available\"\n", " oper,kw = _list_events(self.activity, **kwargs)\n", " return pages(oper, n_pages, per_page=per_page, **kw).concat().map(_id2int)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`list_events` and `list_events_parallel` support the following:\n", "\n", "|Events from|Example|\n", "|:-|:-|\n", "|Organization|`api.list_events_parallel(org='fastai')`\n", "|User|`api.list_events_parallel(username='jph00')`\n", "|Repository network|`api.list_events_parallel(owner='fastai', repo='fastcore')`\n", "|All public|`api.list_events_parallel()`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#export\n", "_bot_re = re.compile('b[o0]t')\n", "def _want_evt(o, types, incl_bot):\n", " if not incl_bot and _bot_re.search(nested_attr(o, 'actor.login') or ''): return False\n", " if types and o.type not in types: return False\n", " return True" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#export\n", "@patch\n", "@delegates(_list_events)\n", "def fetch_events(self:GhApi, n_pages=3, pause=0.4, per_page=30, types=None, incl_bot=False, **kwargs):\n", " \"Generate an infinite stream of events, optionally filtered to `types, with `pause` seconds between requests\"\n", " seen = set()\n", " if types: types=setify(types or None)\n", " while True:\n", " evts = self.list_events_parallel(n_pages=n_pages, per_page=per_page, **kwargs)\n", " new_evts = L(o for o in evts if o.id not in seen and _want_evt(o, types, incl_bot))\n", " seen.update(new_evts.attrgot('id'))\n", " yield from new_evts\n", " if pause: time.sleep(pause)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['PushEvent', 'PushEvent', 'PushEvent', 'PushEvent', 'IssuesEvent']" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "[o.type for o in islice(api.fetch_events(username='jph00'), 5)]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#export\n", "def load_sample_events():\n", " \"Load sample events, downloading if needed\"\n", " name = 'sample_evts.json.gz'\n", " url = f'https://raw.githubusercontent.com/fastai/ghapi/master/examples/{name}'\n", " try: path = Path(__file__).parent\n", " except NameError: path = Path()/'examples'\n", " path = path/name\n", " if not path.exists(): path.write_bytes(urlread(url, decode=False))\n", " return dict2obj(json.load(open_file(path)))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#export\n", "def save_sample_events(n=1000):\n", " \"Save the most recent `n` events as compressed JSON\"\n", " evts = list(islice(api.fetch_events(incl_bot=True), 1000))\n", " with gzip.open('sample_evts.json.gz', 'wt') as f: json.dump(obj2dict(evts), f)" ] }, { "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 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 }