Python

PyGithubでGitHubのissueを.mdや.pdfに変換する

やること

前回はmdファイルを.docxや.pdf形式に出力してみた。今回はその入力ファイルの.mdファイルをgithubのissueから生成してそこからpdfやdocxに変換してみたいと思う。

準備

pandocのインストール

この記事は前々回の記事でpandocをインストールしている人は不要

GitHubのアクセストークンを取得する

githubにアクセスして右上のアイコンからSettingsを選択します。

左のメニューの最下部のDeveloper settingsを選択します。

次に、Personal access tokensのgenerate new tokenを選択します。

Noteのフォームに適当な名前を入力します。Expirationも適当でよいですが、期間が短ければ短いほどセキュアです。

そしてSelect scopesではrepoを選択します。今回はリポジトリの操作のみ行うので、repoで十分です。

generate tokenのボタンをクリックするとtoken一覧の画面に繊維します。そこでaccess tokenが生成できたことが確認できます。(ここではghp_xxxx)

アクセストークンはこの後使用するので、コピーしておきます。

PyGithubのインストール

pythonでgithubを操作するのに便利なPyGithubをインストールします。

(venv) C:\GeneratePdfFileFromGithubIssue> pip install PyGithub

念のため、pip listでインストールができたことを確認しておきます。

(venv) C:\GeneratePdfFileFromGithubIssue> pip list
>Package            Version
------------------ ---------
certifi            2021.10.8
cffi               1.15.0
charset-normalizer 2.0.11
Deprecated         1.2.13
idna               3.3
pip                21.1.1
pycparser          2.21
PyGithub           1.55
PyJWT              2.3.0
PyNaCl             1.5.0
requests           2.27.1
setuptools         56.0.0
urllib3            1.26.8
wrapt              1.13.3

ソースコード

from pathlib import Path
import subprocess
from subprocess import CompletedProcess

from github import Github

# REPOSITORY = "hy-sksem/GeneratePdfFileFromGithubIssue"
REPOSITORY = "your username/your repository name" 
TOKEN = "ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxx" # Personal access token

def ConvertIssue(issue_num: str, suffix: str):

    def _Md2Docx(tgt_file: Path) -> CompletedProcess:
        docx_file = tgt_file.with_suffix(".docx")
        return subprocess.run(f'pandoc "{tgt_file}" --from=markdown --to=docx -o {docx_file}')

    def _Md2Pdf(tgt_file: Path) -> CompletedProcess:
        pdf_file = tgt_file.with_suffix(".pdf")
        return subprocess.run(f'pandoc "{tgt_file}" -V documentclass=ltjarticle --pdf-engine=lualatex -o {pdf_file}')

    def _Md2Stdout(tgt_file: Path) -> CompletedProcess:
        return subprocess.run(f'pandoc "{tgt_file}"')

    def _Md2Html(tgt_file: Path) -> CompletedProcess:
        html_file = tgt_file.with_suffix(".html")
        return subprocess.run(f'pandoc "{tgt_file}" -o {html_file}')

    issue = Github(TOKEN).get_repo(REPOSITORY).get_issue(int(issue_num))
    md_file = Path(__file__).parent / f"{issue.title}.md"
    with open(md_file, "w", encoding="utf-8", newline="") as f:
        f.write(issue.body)
    if suffix == "1":
        result = _Md2Docx(md_file)
    elif suffix == "2":
        result = _Md2Pdf(md_file)
    elif suffix == "3":
        result = _Md2Stdout(md_file)
    elif suffix == "4":
        result = _Md2Html(md_file)
    return result

def main():
    issue_num = input("Issue番号 :")
    suffix = input("変換先を選択してください。docx:1, PDF:2, Stdout:3, HTML:4 :")
    if suffix != "1" and suffix != "2" and suffix != "3" and suffix != "4":
        print("変換先の指定が不正です")
        exit()
    result = ConvertIssue(issue_num, suffix)
    
        
    status = "成功" if result.returncode == 0 else "失敗"
    print(f"{result.args}の実行に{status}しました")

if __name__ == "__main__":
    main()

1. `GeneratePdfFileFromGithubIssue.py`の`REPOSITORY`と`TOKEN`を適切なものに修正する
1. `GeneratePdfFileFromGithubIssue.py`を実行する

ポイントは

issue = Github(TOKEN).get_repo(REPOSITORY).get_issue(int(issue_num)

でしょうか。

Github(TOKEN)はget_repoメソッドがあり、さらにその返り値は.get_issueメソッドを用意していて、issueの情報が取得できます。

このissueインスタンスは以下のような値を持ちます。

  • assignees
  • body
  • comments
  • id
  • state
  • title
  • url
  • etc…

詳しくは以下を参照してください

https://pygithub.readthedocs.io/en/latest/github_objects/Issue.html

今回はbodyとtitleを使用しています。

issue.titleはファイル名に、issue.bodyはファイルの内容としてます。

実行ファイルがあるディレクトリにmdファイルや指定された出力形式のファイルが格納されます。

終わりに

PyGithubでできることは多いので、github actionなど組み合わせることで威力を発揮しそうです。