ぬまやんブログ

Pythonエンジニアになるべく修行中

BacklogAPIライブラリを作ってみた

Pythonエンジニア見習いのぬまやんです。

今回はBacklogAPIのクライアントライブラリを作ってみました。
Backlogの課題やプロジェクトをオブジェクトとして扱えるようにしています。

目次

動機

今まで作りかけだった自作のライブラリにエキスパートPythonプログラミングの内容を実践してみたいと思ったことがきっかけです。
エキスパートPythonプログラミングは言語の基本文法だけでなく、パッケージの作り方やテスト、プロジェクトの管理 についてPythonのベストプラクティスをまとめていただいている本になります。

エキスパートPythonプログラミング改訂2版

エキスパートPythonプログラミング改訂2版

作ったもの

作成したライブラリはGitHubにて管理していて、PyPIに公開しています。

pypi.org

使い方

実現したかったことはBacklogのプロジェクトや課題をオブジェクトとして扱うことです。
そのため以下のような操作感にしています。

from backlogapi import BacklogClient

client = BacklogClient(api_key='apiKey', space_name='spaceName'
# Space内の全プロジェクトを取得する
projects = client.project.all()
project1 = projects[0]

# プロジェクト内の課題を取得する
issues = project1.get_issues()

# 取得した課題を削除する
for issue in issues:
    issue.delete()

エキスパートPythonプログラミングを参考にしたところ

PyPIのへのアップロード

今回のライブラリの目標はPyPIにアップロードして、公開することでした。 公開するにはsetup.py, MANIFEST.in, requirements.txtなど準備するものが多いです。
本書にはこの設定方法について詳細や一般的な手段が記されています。

本書内で何箇所か説明されている新しいPyPIはすでに公開されています。 pypi.org
さらに Project DescriptionについてMarkdownの対応も完了しています。 対応方法はsetup.pyのsetup関数に以下を追加するだけです。

long_description_content_type='text/markdown',

コード管理手法

コードの管理として、継続的デプロイが紹介されています。
私はGitHubにてホスティングしていたため、TravisCIを用いて自動テストを行いました。 TravisCIを用いた所感は以下になります。

  • 新規の仮想環境にてテストを行うことができる
  • GitHubとの連携が簡単
  • 設定方法のドキュメントが読みやすい

他にも紹介されているJenkinsやBuildbotについても試していきたいと思います。

テスト駆動開発

テストについては基礎から応用まで幅広く記されています。 具体的にはunittestを用いた基本的なテスト方法から拡張モジュールであるnose, pytestの使い方が説明されています。 今回はBacklogという外部APIを用いたライブラリなので、Mockを作成する方法やtoxを使ったマトリックステストも使ってみました。

本書から引用したツール・ライブラリは以下になります。

作ってみた感想

ベースとなる書籍があったためPyPIでの公開はスムーズにできました。
しかし、ライブラリ自体を使用する側の目線に立って作ることが難しかったです。
現状はまだまだ使いにくいものなので、改善していきたいと思います。 また、使用感を教えていただけると大変嬉しいです。

line-bot-sdk-pythonを使ってみた

はじめに

line-bot-sdk-pythonPythonを用いてLINE botを作りました。 ライブラリの操作で何箇所か詰まってしまったので、備忘録として記載します。

開発環境

ライブラリ

概要

line-bot-sdk-pythonはLINEのMessaging APIのクライアントライブラリであり、Bot開発を簡単に始めることがきます。 デコレータを用いて、イベントごとの処理を分けて記述したり、Signatureから署名を検証する操作を簡単にかけます。

事前準備

初めてLINE Botを作成するときは以下の公式ドキュメントからチャネルの作成まで完了する必要があります。 登録が終わったら、自分のBotの各種設定をコンソール画面から取得することができます。

URL設定

LINEのWebhookを用いるとBotへのメッセージや友達追加などのイベント時にHTTP POSTリクエストを発行できます。 コンソール画面のWebhook URLの項目にPOST先のURLを定義することで設定が完了します。

Djangoではルーティングを用いてURLを設定します。

urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('callback', views.callback)
]

認証

LINE Messaging APIを用いいる場合は以下の二つの定義が必要になります。

  • LINE_ACCESS_SECRET: 署名の検証で使用
  • CHANNEL_ACCESS_TOKEN: 各API通信を行うときに使用

コンソール画面のChannel基本設定から、Channel Secretとアクセストークン を発行します。これらがそれぞれLINE_ACCESS_SECRETとCHANNEL_ACCESS_TOKENに当たります。

Djangoのviews.py上では以下になります。

views.py

from linebot import LineBotApi, WebhookHandler

# 各クライアントライブラリのインスタンス作成
line_bot_api = LineBotApi(channel_access_token=CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(channel_secret=LINE_ACCESS_SECRET)

handlerの使い方

レスポンスの関数呼び出しとリクエストの署名検証

リクエストごとの関数を呼び出すためにはWebhookHandlerのhandleメソッドを用います。 handleメソッドは署名検証も同時に行います。 引数にはレスポンスのbodyと署名検証のためのsignatureを使います。

views.py

from django.http import HttpResponseForbidden, HttpResponse
from linebot.exceptions import InvalidSignatureError

def callback(request):
    # リクエストヘッダーから署名検証のための値を取得
    signature = request.META['HTTP_X_LINE_SIGNATURE']
    # リクエストボディを取得
    body = request.body.decode('utf-8')
    try:
        # 署名を検証し、問題なければhandleに定義されている関数を呼び出す
        handler.handle(body, signature)
    except InvalidSignatureError:
        # 署名検証で失敗したときは例外をあげる
        HttpResponseForbidden()
    # handleの処理を終えればOK
    return HttpResponse('OK', status=200)

イベントごとに関数を定義

handlerのaddメソッドを用いて、リクエストのイベントごとに実行する関数を記述できます。 例えば、友達追加されたときに「初めまして」というメッセージを送信する処理は以下のようになります。

views.py

# linebot.modelsから処理したいイベントをimport
from linebot.models import (
    FollowEvent, TextSendMessage
)

# addメソッドの引数にはイベントのモデルを入れる
# 関数名は自由
@handler.add(FollowEvent)
def handle_follow(event):
    line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text='初めまして')
    )

handler.addメソッドには引数にリクエストのイベントを指定します。 イベントはlinebot.modelsに定義されていて、メッセージやグループ参加などがあります。 関数の引数であるeventはLINE Messaging APIで定義されているリクエストボディになります。

リプライはLineBotApiのメソッドを用いています。 第一引数のevent.reply_tokenはイベントの応答に用いるトークンです。 第二引数にはlinebot.modelsに定義されている返信用のTextSendMessageオブジェクトを渡しています。

handler.addメソッドはメッセージイベントの場合にテキストや画像のようなメッセージの 内容でも処理を分けることができます。

from linebot.models import (
    MessageEvent,
    TextMessage ,ImageMessage, AudioMessage
)

# メッセージイベントの場合の処理
# かつテキストメッセージの場合
@handler.add(MessageEvent, message=TextMessage)
def handle_text_message(event):
    # メッセージでもテキストの場合はオウム返しする
    line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text=event.message.text)
    )


# 画像、音声メッセージの場合
@handler.add(MessageEvent, message=(ImageMessage, AudioMessage))
def handle_image_audio_message(event):
    content = line_bot_api.get_message_content(event.message.id)
    with open('file', 'w') as f:
        for c in content.iter_content():
            f.write(c)

まとめ

line-bot-sdk-pythonを使ってイベントごとにレスポンスを変える処理を作りました。 処理部分を関数で簡単に分けることができるためとてもシンプルに書くことができます。 この処理を使って複数のAPIを連携したbotを作ったので、後日まとめたいです。

コード例

views.py

from django.http import HttpResponseForbidden, HttpResponse

from linebot.exceptions import InvalidSignatureError
from linebot.models import (
    MessageEvent, TextMessage, FollowEvent, UnfollowEvent,
    TextSendMessage, ImageMessage, AudioMessage
)

from linebot import LineBotApi, WebhookHandler


# 各クライアントライブラリのインスタンス作成
line_bot_api = LineBotApi(channel_access_token=CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(channel_secret=LINE_ACCESS_SECRET)


def callback(request):
    # signatureの取得
    signature = request.META['HTTP_X_LINE_SIGNATURE']
    body = request.body.decode('utf-8')
    try:
        # 署名の検証を行い、成功した場合にhandleされたメソッドを呼び出す
        handler.handle(body, signature)
    except InvalidSignatureError:
        return HttpResponseForbidden()
    return HttpResponse('OK')



# フォローイベントの場合の処理
@handler.add(FollowEvent)
def handle_follow(event):
    line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text='初めまして')
    )


# メッセージイベントの場合の処理
@handler.add(MessageEvent, message=TextMessage)
def handle_text_message(event):
    # メッセージでもテキストの場合はオウム返しする
    line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text=event.message.text)
    )

@handler.add(MessageEvent, message=(ImageMessage, AudioMessage))
def handle_image_audio_message(event):
    # 画像と音源の場合は保存する
    content = line_bot_api.get_message_content(event.message.id)
    with open('file', 'w') as f:
        for c in content.iter_content():
            f.write(c)

参考

Django備忘録: 複数チェックボックス

複数のチェックボックスから値を受け取る方法

複数のチェックボックスやテキストから値を得る方法がわからなかったので調べてみました。 request.POSTからkey-valueで取得しようとすると一つのinputタグしか取得できないため、POSTのメソッドを使用しなければなりません。

HTML

サンプルのHTMLは以下になります。nameが同一で、valueが異なるときを想定しています。

<input type="checkbox" name="test" value="value1" />
<input type="checkbox" name="test" value="value2" />

viewでの受け取り方

今回は関数ベースのviewが前提です。

>>> values = request.POST.getlist('test')  # testはcheckboxのinputタグのname
>>> print(values)
['value1', 'value2']

getlistメソッドについて

request.POSTおよびrequest.GETオブジェクトはdjango.http.QueryDictクラスのインスタンスでした。 そのQueryDictは 辞書型のサブクラスであり、通常の辞書のメソッドに加えてgetlist, lists, urlencodeなどのメソッドも追加されていることがわかりました。 このQueryDictのメソッドを用いてリストを得ることができます。

参考にした公式ドキュメントを貼付します。 https://docs.djangoproject.com/ja/2.0/ref/request-response/#querydict-objects

独学プログラマーを読んでみた

この本を買ったきっかけ

きっかけは第一章を本屋で読んだことでした。私は現在未経験からプログラマーを目指している一員です。プログラミングの勉強を初めて一年くらいがたち、本格的にプログラマーへの転職を考えていました。

そんな中で目にした本書のイントロダクションは印象的でした。特に著者がモチベーションを維持するためのテクニックは衝撃的で、全く思いつかない上に真似できません。未経験からプロになるために必要なことがわかると思い、購入しました。

概要

本書は六部構成になっており、プログラミングの基本から、各ツールの使い方など広く浅い内容であると思います。

本書の対象者

本書はプログラミング経験のない方をメインターゲットとしています。そのため、普段からガリガリ書いているプログラマーの方には少し物足りないかもしれないです。

良かったところ

各章にチャレンジ問題がある

読んだあとにどのくらい身についてるかをチェックできるので助かります。

日本語版の注釈

実際にコードを書くときに日本語を扱う上でのギャップはなく、原著のように読むことができました。 また、各詳細サイトも日本語版のリンクが添付してあり、参考になりました。

データ構造・アルゴリズム

プログラミングの入門本ではあまり触れられない内容に見えますが、本書では紹介されています。 この本で学ぶというようりも、課題の一つとして認識するためという印象です。

Part5

いざ言語の文法や使い方を覚えた状態から"仕事"にするまでに何が必要か書いてあります。 紹介されているのは欧米流ですが、参考になることはとても多いです。

総評

もっと早く手に取れたら良かったです。Pythonの入門本というよりもプログラマーの入門本だと思っています。 これからプログラマーへの道を考えている人にはおすすめの一冊です。

独学プログラマー Python言語の基本から仕事のやり方まで

独学プログラマー Python言語の基本から仕事のやり方まで

HTTP入門

こんにちは、ぬまやんです。最近Goプログラミング実践入門を購入しました。この本を元にWebアプリやHTTPについて勉強した内容をまとめてみます。多数見当違いな記述もあると思いますが、ご指摘お願いいたします。

1. HTTPの定義

  • クライアント(ユーザー側)とサーバー(サービス提供側)をリクエスト/レスポンスの1回のやりとりで完結させる通信

例: twiiter
ユーザーがツイート検索することでリクエストがサーバーに送信され、サーバーがレスポンスを返して、検索結果をブラウザに表示

  • HTTP1.Xではリクエスト/レスポンスはテキストベースにて行われていたが、HTTP2.0になるとバイナリ

1.1 HTTPリクエス

  • リクエストは以下の構成からなる
  • リクエストヘッダの後にはメッセージがなくても空行を必ず挟むこと
GET /example.com/hatena.html HTTP/1.3
User-Agent: Mozilla/5.0

(メッセージ本体)
  1. リクエスト行(メソッド URI バージョン)
  2. リクエストヘッダ (0行以上)
  3. 空行
  4. メッセージ本体(省略可能)

リクエストメソッド

  • リクエストメソッドはWebアプリに対して、処理してほしい要求内容を表す
  • 主要なメソッドと要求内容を記載する
    • GET: 指定するリソースの返却
    • POST: メッセージ本体のデータをリソースに送信(送信後の処理内容はサーバーが決定)
    • PUT: メッセージ本体のデータをリソースに置き換え
    • DELETE: リソースの削除
  • POSTとPUTは2回同様のメソッドを送信した時にサーバの状態が変更されるか否かが異なる
    • POSTは2回サーバに送信した時にサーバ状態が変更される場合がある
    • PUTは2回サーバに送信した時、2回目はサーバの状態を変更しない

リクエストヘッダ

  • リクエストに付随する情報が表示される
  • 主要なヘッダを記載する
    • Content-Length: メッセージ本体のバイト数
    • Host: サーバ名とポート番号
    • User-Agent: クライアント情報

1.2 HTTPレスポンス

  • レスポンスの構成をリクエスト同様表示する
  • リクエスト同様にヘッダの後には必ず空行を含める
200 OK
Date: 05 Nov 2017 10:02:59 GMT
Content-Length: 712300

<!DOCTYPE html> (リクエストHTML)
  1. ステータス
  2. レスポンスへッダ (0行以上)
  3. 空行
  4. HTML

レスポンスステータス

  • レスポンスはステータスによって結果を要約している
  • 以下に主要レスポンスを記す
    • 1XX: サーバがリクエストを受信し、処理中である状態
    • 2XX: クライアントのリクエストを元に処理が成功した状態
    • 3XX: サーバがリクエストを処理したが、クライアントからの追加情報を待っている状態
    • 4XX: クライアントエラーであり、リクエストを見直す必要がある(404 Not Foundなど)
    • 5XX: サーバエラーであり、サーバ側の不具合のためリトライすると成功する可能性がある

レスポンスヘッダ

  • リクエストヘッダと同様な記法でリクエスト結果の情報が記載されている
  • 以下に主要なヘッダを記載する
    • Allow: サーバのサポートしているリクエストメソッドを記載
    • Server: ドメイン
    • Date: 日時

2. Webアプリケーション

  • WebアプリケーションはHTTPを用いて以下の動作を行うシステム

    1. HTTPを介してリクエストメッセージを受信
    2. リクエストから処理を行う
    3. 結果を元にHTMLとレスポンスを生成してクライアントに送信
  • これらの処理を行うために、Webアプリケーション内にはハンドラとテンプレートエンジンの二つの構成がある

2.1 ハンドラ

  • クライアントからのリクエストを受信し、処理を行うもの
  • 一般的にハンドラをHTTPメッセージ処理を行うコントローラとアプリケーション処理を行うモデルに分割する

2.2 テンプレートエンジン

  • クライアントに返却するHTMLを作成するもの
  • 静的テンプレートとアクティブテンプレートに分かれる
    • 静的テンプレート: HTMLにあらかじめ入力項目を設けて、リクエストを元に埋め込んでいくもの
    • アクティブテンプレート: 条件式や繰り返しを用いてHTMLを動的に生成するもの(PHPはアクティブテンプレートから始まった)

感想

  • HTTPの仕組みのシンプルさが直感的でとてもわかりやすかったです
  • 常に広く普及する仕組みにわかりやすさは欠かせないものであると実感しました

僕のワンダフル・ライフ

はじめに

最近気になっていたナミヤ雑貨店の奇蹟と僕のワンダフル・ライフのどちらを見ようか悩み、 ホームドラマでさっぱりしたい気分だったのでわんこを観てきました。

あらすじ

ある一匹(?)の犬が何度も生まれ変わり、命の恩人との再会を目指すお話です。

感想

細かいところが気にならなくなるようなファンタジーですね。 何回か泣いてしまいました。

もしかしたら賢い犬は過去何回か転生してきているんじゃないかと思ってしまいます。 はじめベイリーだった頃は無邪気で遊ぶのが大好きな犬だったのに、警察犬になり人を救っていく姿はめちゃめちゃかっこいいです。 イーサン(アダルト)の元に帰って来てハンナ(アダルト)を引き合わせたのはグッジョブでしたね。 イーサンの幸せを慮った行動でした。

お気に入りはマヤの元にいた頃でお互いに心を理解し合えるほどの関係が眩しかった分、転生の時は切なかったですね。 初めての恋も切なく、相手の犬の気持ちも聞きたかったです。

犬がどれだけ人を思い愛してくれるかがわかるお話でした。 犬や猫を飼う時はできるだけ一緒にいて遊んでたくさん思い出を作りたいです。

3度目の殺人

是枝さん

3度目の殺人を観に行きました。
是枝監督の作品はかなり好みで、前回の「海よりもまだ深く」は映画館に2回足を運びました。
阿部ちゃんが好きということもありますが、登場人物が今までの自分を乗り越えていく姿は胸熱です。
そして父になる」も良いですね。
リリーフランキー福山雅治という最高に父にしたい二人です。

 

以下ネタバレ注意

人物について

役所広司演じる三隅が殺人犯、福山雅治演じる重盛が弁護士で、被害者遺族である咲江ちゃんを広瀬すずが演じています。
重盛は法廷で勝つために真実は必要ないし、分かり得ないという弁護士です。
しかし、三隅の弁護をしていくうちに今回の事件については真実を知りたいという気持ちに駆られていきます。

対する三隅は重盛と面会を重ねるたびに証言を変え、三隅含めた弁護士達を困らせてしまいます。
過去に殺人の前科があり、死刑確実と言われていた状態から当時の裁判長だった重盛父に守られた経緯があります。
そのためか重盛父に感謝し、尊敬している描写がいくつかありました。

咲江ちゃんは被害者遺族ですが三隅と交流があり、仲の良さが見え隠れします。

感想

真実とはなんであろうかと葛藤させられました。
最後に重盛が三隅をただの器としたことから、誰かの意思が三隅を動かしていたのでしょう。
三隅は咲江ちゃんを守ろうとしたのか、咲江ちゃんや社員の方々の理不尽さを裁きたかったのか。
なぜ重盛父に咲江ちゃんと遊んだことを娘として伝えたのか。
三隅はどこで重盛の娘のことを知ったのか。
なぜ重盛父はなぜ三隅を生かしたことを後悔しているのでしょうか。
私には見えないことだらけですね。

ただ、三隅は咲江ちゃんの真実を露見させないために無実を主張し、重盛はそのことに気づいていたのかなとは考えます。

裁判長が評価やスケジュールから裁判を続行させ、最後には死刑を下したことは死刑制度について考えさせられますね。
端から見ると評価を下げたくないから殺したように見えます。
その環境に入ると疑問を持てなくなってしまうんですかね。

暗示が多く難しいですがとても面白かったです。
誰かと話たくなる映画でした。