6
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Python] Redmine APIで情報を読み込む

Last updated at Posted at 2021-01-19

初めに

プロジェクト管理SWであるRedmineに関して、Pythonを用いて情報を読み込む操作をまとめた。
以下の環境で実施した。

os windows
python 3.7.1
python-redmine 2.3.0
anaconda 4.8.5

python-redmineとは

PythonからRedmineを操作できるAPI。
チケットやプロジェクトの作成、読み込み、更新、削除が可能。
本記事は読み込みのみを対象とする。

インストール方法

anaconda cloud からインストール。

$ conda install -c auto python-redmine

接続設定

Redmineへ接続するにはRemine側とpython側で設定する必要がある。

Redmine側

管理者権限を有するユーザが、Redmine設定を行う。
[管理] → [設定] → [REST APIによるWebサービスを有効にする] を有効にする。

Python側

アクセスするユーザの情報(ユーザ名およびパスワード)もしくは、APIアクセスキーを使用する。

from redminelib import Redmine
REDMINE_URL = r'http://user/redmine' # Redmineのパス
REDMINE_KEY = 'xxxxxx' # APIアクセスキー
redmine = Redmine(REDMINE_URL, key = REDMINE_KEY)

もしくは

from redminelib import Redmine
REDMINE_URL = r'http://user/redmine' # Redmineのパス
USER = 'hoge' # ユーザ名
PASS = 'hogehoge' # パスワード
redmine = Redmine(REDMINE_URL, username = USER, password = PASS)

チケット情報の取得

Redmineのチケット情報を取得するには、get()かall()かfilter()の3通りで取得できる。
特定のチケットのみを取得する場合はredmine.issue.get(チケットID)で取得する。
取得したチケット内の情報は戻り値になっているオブジェクト内にある。
対象とするチケットIDのチケットが存在しない場合は、redmine.exceptions.ResourceNotFoundError例外が発生する。

from redminelib import Redmine
from redminelib.exceptions import ResourceNotFoundError
REDMINE_URL = r'http://user/redmine' # Redmineのパス
REDMINE_KEY = 'xxxxxx' # APIアクセスキー
redmine = Redmine(REDMINE_URL, key = REDMINE_KEY)

ticket_id = 4 # チケットのID
try:
    issue = redmine.issue.get(ticket_id)
except(ResourceNotFoundError):
    print('Ticket ID %s not found' % ticket_id)

チケット情報のまとめ

python-redmineに詳細記載されている内容をまとめる。
https://python-redmine.com/resources/issue.html
なお、チケットに該当の情報が登録されていない場合、ISSUEのプロパティ自体が存在していない。
そのため、情報取得に関して該当のプロパティを所持しているか判定を行う必要がある。

info = issue.property if hasattr(issue, 'property') else None

|Redmine情報|ISSUE内情報|
|---|---|---|
| チケットID | issue.id |
| チケットURL | issue.url|
| トラッカーID | issue.tracker.id |
| トラッカー | issue.tracker.name |
| 題名| issue.subject |
| 説明 | issue.description |
| ステータスID | issue.status.id |
| ステータス | issue.status.name |
| 優先度ID | issue.priority.id |
| 優先度 | issue.priority.name |
| 担当者ID | issue.assigned_to.id |
| 担当者名 | issue.assigned_to.name |
| 親チケットID | issue.parent |
| 開始日 | issue.start_date |
| 期日 | issue.due_date |
| 予定工数| issue.estimated_hours |
| プロジェクトID | issue.project.id |
| プロジェクト | issue.project.name |
| 作成者ID | issue.author.id |
| 作成者名 | issue.author.name |
| 進捗率 | issue.done_ratio |
| 作成日 | issue.created_on |
| 更新日 | issue.updated_on |
| 作業時間 | issue.spent_hours |

なお、複数の情報があるものはそれぞれのオブジェクトに各情報が入っている。

ウォッチャー issue.watchers
ウォッチャーID .id
ウォッチャー名 .name
カスタム領域 issue.custom_fields
カスタムID .id
カスタム名 .name
カスタム値 .value
送付ファイル issue.attachments
ファイルID .id
ファイル名 .filename
ファイル説明 .description
ファイルサイズ .filesize
ファイル著者 .author
ファイルURL .content_url
ファイル作成日 .created_on
コミットログ issue.changesets
子チケット issue.children
子チケットID .id
子チケットタイトル .subject
関連するチケット issue.relations
関連ID .id
関連する自分のID .issue_id
関連する相手のID .issue_to_id
関連のタイプ .relation_type

上記情報を以下で表示する。

from redminelib import Redmine
from redminelib.exceptions import ResourceNotFoundError
REDMINE_URL = r'http://user/redmine' # Redmineのパス
REDMINE_KEY = 'xxxxxx' # APIアクセスキー
redmine = Redmine(REDMINE_URL, key = REDMINE_KEY)

ticket_id = 4 # チケットのID
try:
    issue = redmine.issue.get(ticket_id)

    # チケット情報
    print('チケットID: %s' % issue.id if hasattr(issue, 'id') else None)
    print('チケットURL: %s' % issue.url if hasattr(issue, 'url') else None)
    print('トラッカーID: %s' % issue.tracker.id if hasattr(issue, 'tracker') else None)
    print('トラッカー: %s' % issue.tracker.name if hasattr(issue, 'tracker') else None)
    print('題名: %s' % issue.subject if hasattr(issue, 'subject') else None)
    print('説明: %s' % issue.description if hasattr(issue, 'description') else None)
    print('ステータスID: %s' % issue.status.id if hasattr(issue, 'status') else None)
    print('ステータス: %s' % issue.status.name if hasattr(issue, 'status') else None)
    print('優先度ID: %s' % issue.priority.id if hasattr(issue, 'priority') else None)
    print('優先度: %s' % issue.priority.name if hasattr(issue, 'priority') else None)
    print('担当者ID: %s' % issue.assigned_to.id if hasattr(issue, 'assigned_to') else None)
    print('担当者名: %s' % issue.assigned_to.name if hasattr(issue, 'assigned_to') else None)
    print('親チケットID: %s' % issue.parent if hasattr(issue, 'parent') else None)
    print('開始日: %s' % issue.start_date if hasattr(issue, 'start_date') else None)
    print('期日: %s' % issue.due_date if hasattr(issue, 'due_date') else None)
    print('予定工数: %s' % issue.estimated_hours if hasattr(issue, 'estimated_hours') else None)
    print('プロジェクトID: %s' % issue.project.id if hasattr(issue, 'project') else None)
    print('プロジェクト: %s' % issue.project.name if hasattr(issue, 'project') else None)
    print('作成者ID: %s' % issue.author.id if hasattr(issue, 'author') else None)
    print('作成者名: %s' % issue.author.name if hasattr(issue, 'author') else None)
    print('進捗率: %s' % issue.done_ratio if hasattr(issue, 'done_ratio') else None)
    print('作成日: %s' % issue.created_on if hasattr(issue, 'created_on') else None)
    print('更新日: %s' % issue.updated_on if hasattr(issue, 'updated_on') else None)
    print('作業時間: %s' % issue.spent_hours if hasattr(issue, 'spent_hours') else None)

    # 情報個別詳細
    print('ウォッチャー') # ウォッチャー
    for detail in issue.watchers:
        print('    ウォッチャーID: %s' % detail.id)
        print('    ウォッチャー名: %s' % detail.name)
    print('カスタム領域') # カスタム領域
    for detail in issue.custom_fields:
        print('    カスタムID: %s' % detail.id)
        print('    カスタム名: %s' % detail.name)
        print('    カスタム値: %s' % detail.value)
    print('送付ファイル') # 送付ファイル
    for detail in issue.attachments:
        print('    ファイルID: %s' % detail.id)
        print('    ファイル名: %s' % detail.filename)
        print('    ファイル説明: %s' % detail.description)
        print('    ファイルサイズ: %s' % detail.filesize)
        print('    ファイル著者: %s' % detail.author)
        print('    ファイルURL: %s' % detail.content_url)
        print('    ファイル作成日: %s' % detail.created_on)
    print('コミットログ') # コミットログ
    for detail in issue.changesets:
        print('    %s' % detail)
    print('子チケット') # 子チケット
    for detail in issue.children:
        print('    子チケットID: %s' % detail.id)
        print('    子チケットタイトル: %s' % detail.subject)
    print('関連するチケット') # 関連するチケット
    for detail in issue.relations:
        print('    関連ID: %s' % detail.id)
        print('    関連する自分のID: %s' % detail.issue_id)
        print('    関連する相手のID: %s' % detail.issue_to_id)
        print('    関連のタイプ: %s' % detail.relation_type)
except(ResourceNotFoundError):
    print('Ticket ID %s not found' % ticket_id)

参考

https://qiita.com/mima_ita/items/1a939db423d8ee295c85
https://python-redmine.com/resources/issue.html

6
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?