|
658 | 658 | "## Gists and github" |
659 | 659 | ] |
660 | 660 | }, |
661 | | - { |
662 | | - "cell_type": "code", |
663 | | - "execution_count": null, |
664 | | - "id": "eb4c6bf4", |
665 | | - "metadata": {}, |
666 | | - "outputs": [], |
667 | | - "source": [ |
668 | | - "#| export\n", |
669 | | - "@allow\n", |
670 | | - "def load_gist(gist_id:str):\n", |
671 | | - " \"Retrieve a gist\"\n", |
672 | | - " api = GhApi()\n", |
673 | | - " if '/' in gist_id: *_,user,gist_id = gist_id.split('/')\n", |
674 | | - " else: user = None\n", |
675 | | - " return api.gists.get(gist_id, user=user)" |
676 | | - ] |
677 | | - }, |
678 | | - { |
679 | | - "cell_type": "code", |
680 | | - "execution_count": null, |
681 | | - "id": "3ab7586f", |
682 | | - "metadata": {}, |
683 | | - "outputs": [ |
684 | | - { |
685 | | - "data": { |
686 | | - "text/plain": [ |
687 | | - "'https://gist.github.com/jph00/e7cfd4ded593e8ef6217e78a0131960c'" |
688 | | - ] |
689 | | - }, |
690 | | - "execution_count": null, |
691 | | - "metadata": {}, |
692 | | - "output_type": "execute_result" |
693 | | - } |
694 | | - ], |
695 | | - "source": [ |
696 | | - "gistid = 'jph00/e7cfd4ded593e8ef6217e78a0131960c'\n", |
697 | | - "gist = load_gist(gistid)\n", |
698 | | - "gist.html_url" |
699 | | - ] |
700 | | - }, |
701 | | - { |
702 | | - "cell_type": "code", |
703 | | - "execution_count": null, |
704 | | - "id": "3b151f8f", |
705 | | - "metadata": {}, |
706 | | - "outputs": [], |
707 | | - "source": [ |
708 | | - "#| export\n", |
709 | | - "def gist_file(gist_id:str):\n", |
710 | | - " \"Get the first file from a gist\"\n", |
711 | | - " gist = load_gist(gist_id)\n", |
712 | | - " return first(gist.files.values())" |
713 | | - ] |
714 | | - }, |
715 | | - { |
716 | | - "cell_type": "code", |
717 | | - "execution_count": null, |
718 | | - "id": "ea33969d", |
719 | | - "metadata": {}, |
720 | | - "outputs": [ |
721 | | - { |
722 | | - "name": "stdout", |
723 | | - "output_type": "stream", |
724 | | - "text": [ |
725 | | - "\"This is a test module which makes some simple tools available.\"\n", |
726 | | - "__all__ = [\"hi\",\"whoami\"]\n", |
727 | | - "\n", |
728 | | - "testfoo=…\n" |
729 | | - ] |
730 | | - } |
731 | | - ], |
732 | | - "source": [ |
733 | | - "gfile = gist_file(gistid)\n", |
734 | | - "print(gfile.content[:100]+\"…\")" |
735 | | - ] |
736 | | - }, |
737 | 661 | { |
738 | 662 | "cell_type": "code", |
739 | 663 | "execution_count": null, |
|
838 | 762 | " create_msg:bool=False # Add a message that lists usable tools\n", |
839 | 763 | "):\n", |
840 | 764 | " \"Import gist directly from string without saving to disk\"\n", |
841 | | - " fil = gist_file(gist_id)\n", |
| 765 | + " fil = GhApi().gist_file(gist_id)\n", |
842 | 766 | " mod_name = mod_name or Path(fil['filename']).stem\n", |
843 | 767 | " module = import_string(fil['content'], mod_name)\n", |
844 | 768 | " glbs = currentframe().f_back.f_globals\n", |
|
872 | 796 | } |
873 | 797 | ], |
874 | 798 | "source": [ |
| 799 | + "gistid = 'jph00/e7cfd4ded593e8ef6217e78a0131960c'\n", |
875 | 800 | "import_gist(gistid)\n", |
876 | 801 | "importtest.testfoo" |
877 | 802 | ] |
|
961 | 886 | "importtest.__all__" |
962 | 887 | ] |
963 | 888 | }, |
964 | | - { |
965 | | - "cell_type": "code", |
966 | | - "execution_count": null, |
967 | | - "id": "f790682a", |
968 | | - "metadata": {}, |
969 | | - "outputs": [], |
970 | | - "source": [ |
971 | | - "#| export\n", |
972 | | - "def update_gist(gist_id:str, content:str):\n", |
973 | | - " \"Update the first file in a gist with new content\"\n", |
974 | | - " api = GhApi()\n", |
975 | | - " if '/' in gist_id: *_,user,gist_id = gist_id.split('/')\n", |
976 | | - " gist = api.gists.get(gist_id)\n", |
977 | | - " fname = first(gist.files.keys())\n", |
978 | | - " res = api.gists.update(gist_id, files={fname: {'content': content}})\n", |
979 | | - " return res['html_url']" |
980 | | - ] |
981 | | - }, |
982 | | - { |
983 | | - "cell_type": "code", |
984 | | - "execution_count": null, |
985 | | - "id": "3afa7bdb", |
986 | | - "metadata": {}, |
987 | | - "outputs": [], |
988 | | - "source": [ |
989 | | - "#| export\n", |
990 | | - "def _filter_diff(diff, folder='solveit/', skip_files=('_modidx.py',)):\n", |
991 | | - " \"Filter unified diff to only include files under `folder`, skipping `skip_files`\"\n", |
992 | | - " sections = re.split(r'(?=^diff --git )', diff, flags=re.MULTILINE)\n", |
993 | | - " return ''.join(s for s in sections\n", |
994 | | - " if s.startswith(f'diff --git a/{folder}')\n", |
995 | | - " and not any(f'/{f} ' in s.split('\\n')[0] for f in skip_files))\n", |
996 | | - "\n", |
997 | | - "def _reduce_ctx(diff):\n", |
998 | | - " \"Keep only diff headers and changed lines (optionally with `n` context lines)\"\n", |
999 | | - " lines = diff.splitlines(True)\n", |
1000 | | - " return ''.join(l for l in lines if l[0:1] in ('+','-','d','i','@') or not l.strip())\n", |
1001 | | - "\n", |
1002 | | - "def _fmt_replies(api, owner, repo, num):\n", |
1003 | | - " \"Format issue/PR comment replies\"\n", |
1004 | | - " comments = api.issues.list_comments(owner, repo, num)\n", |
1005 | | - " if not comments: return ''\n", |
1006 | | - " return '\\n\\n## Replies\\n' + '\\n\\n---\\n'.join(f\"**@{c.user.login}** ({c.created_at[:10]}):\\n{c.body}\" for c in comments)" |
1007 | | - ] |
1008 | | - }, |
1009 | | - { |
1010 | | - "cell_type": "code", |
1011 | | - "execution_count": null, |
1012 | | - "id": "6d26d0ed", |
1013 | | - "metadata": {}, |
1014 | | - "outputs": [], |
1015 | | - "source": [ |
1016 | | - "#| export\n", |
1017 | | - "@allow\n", |
1018 | | - "def read_pr(\n", |
1019 | | - " pr_number:int|str, # Issue/PR number, or GitHub issue/PR URL\n", |
1020 | | - " owner:str='answerdotai', # Owner\n", |
1021 | | - " repo:str=None, # Repo\n", |
1022 | | - " folder:str='', # For diffs, limit to only to files in `folder`\n", |
1023 | | - " replies:bool=False # Include replies\n", |
1024 | | - "):\n", |
1025 | | - " \"Fetch a GitHub PR or issue's title, body, optionally replies, and diff (if PR)\"\n", |
1026 | | - " if '/' in str(pr_number): *_,owner,repo,typ,pr_number = str(pr_number).rstrip('/').split('/')\n", |
1027 | | - " pr_number = int(pr_number)\n", |
1028 | | - " if folder: folder = f\"{folder}/\"\n", |
1029 | | - " api = GhApi()\n", |
1030 | | - " res = None\n", |
1031 | | - " try: pr = api.pulls.get(owner, repo, pr_number)\n", |
1032 | | - " except:\n", |
1033 | | - " try: iss = api.issues.get(owner, repo, pr_number)\n", |
1034 | | - " except Exception as e: return f\"Err: {e}\"\n", |
1035 | | - " title,body = iss.title, iss.body or ''\n", |
1036 | | - " evts = api.issues.list_events(owner, repo, pr_number)\n", |
1037 | | - " sha = first(e.commit_id for e in evts if e.commit_id)\n", |
1038 | | - " if not sha: res = f\"# {title}\\n\\n{body}\"\n", |
1039 | | - " else:\n", |
1040 | | - " try: diff = api.repos.get_commit(owner, repo, sha, headers={'Accept': 'application/vnd.github.v3.diff'})\n", |
1041 | | - " except Exception as e: res = f\"# {title}\\n\\n{body}\\n\\n(No diff: {e})\"\n", |
1042 | | - " else:\n", |
1043 | | - " title,body = pr.title, pr.body or ''\n", |
1044 | | - " try: diff = api.pulls.get(owner, repo, pr_number, headers={'Accept': 'application/vnd.github.v3.diff'})\n", |
1045 | | - " except Exception as e: res = f\"# {title}\\n\\n{body}\\n\\n(No diff: {e})\"\n", |
1046 | | - " if res is None:\n", |
1047 | | - " diff = _reduce_ctx(_filter_diff(diff, folder=folder))\n", |
1048 | | - " res = f\"# {title}\\n\\n{body}\\n\\n## Diff\\n```diff\\n{diff}\\n```\"\n", |
1049 | | - " if replies: res += _fmt_replies(api, owner, repo, pr_number)\n", |
1050 | | - " return res" |
1051 | | - ] |
1052 | | - }, |
1053 | 889 | { |
1054 | 890 | "cell_type": "markdown", |
1055 | 891 | "id": "3d8cb87c", |
|
0 commit comments