Mockのpatchの勘違い

良くわからないけど唐突に意識高くなったので俺ブログ書くわ!!!ブログ書くわ!!! けど後2分くらいしかきっと持たない!!!早く書くんだ俺!!!2分後にはまた死んだ魚ような目になってしまうぞ!

という訳でPythonのMockで小一時間ハマったネタを書く。

前提

まずこんな感じで fuga.pyをimportして利用したhoge.pyをテストするhogetests.pyがあるとする。

# fuga.py
# -*- coding: utf-8 -*-

def piyo():
    return 'piyopiyo'
# hoge.py
# -*- coding: utf-8 -*-

from fuga import piyo

def hogecall():
    return piyo()

if __name__ == "__main__":
    print hogecall() # => piyopiyo
# hogetests.py
# -*- coding: utf-8 -*-

import random
import unittest
from mock import patch

class HogeTests(unittest.TestCase):

    def _getTargetFunc(self):
        from hoge import hogecall
        return hogecall

    def test_hogecall(self):
        hogecall = self._getTargetFunc()
        self.assertEqual(hogecall(), "piyopiyo")

if __name__ == '__main__':
    unittest.main()

やりたい事

ここで hogecallの中で読んでるpiyo()て関数をモック化したい。

def hogecall():
    return piyo() # <= コイツをモック化したい

間違った

最初はmock.patchを利用してこのように書いた

@patch('fuga.piyo', return_value="hogehoge")
def test_hogecall2(self, piyo):
     hogecall = self._getTargetFunc()
     self.assertEqual(hogecall(), "hogehoge")

だがこれはうまく行かず hogehogeが欲しいのにpiyopiyoばっかり帰ってきやがる。無茶しやがって。

正解

正解は patchに噛ます対象が、fuga.piyoではなく、hoge.piyoだった。patchで指定する時は、実際の処理で使われてる関数を置き換えるというものらしい。

@patch('hoge.piyo', return_value="hogehoge") #<=  × fuga.piyo   ○ hoge.piyo
def test_hogecall2(self, piyo):
     hogecall = self._getTargetFunc()
     self.assertEqual(hogecall(), "hogehoge")

余談

  • hogeとかpiyoとかhogehogeとかpiyopiyoとかもう書いてる本人も良くわからない。多分大体あってる

Marked で reST(reStructuredText) を リアルタイムプレビューする

reST書いてる時に、いい感じでプレビューしてくれるのないかな。って思って見つけたヤツをメモる

やってみたら割と便利だった。

rst2html.py のパスをMarkedのCustomProcessorに設定するだけでいいらしい。

f:id:tell-k:20130324185420p:plain

あと毎回Marked 起動するのめんどいので、こんな感じで、.bashrcにaliasとして設定しておいた。

alias rstpreview='open -a Marked'

これでいつでも好きなファイルをMarkedで開ける

$ rstpreview hoge.rst

Markedは保存した内容を即座にプレビュー画面に反映してくれるので嬉しい。あとは僕のreST書きたい欲を待つだけ。

hc コマンドで、HTTP のステータスコードをすばやくしらべる!

一般的な Web Programmer ならば、HTTP Status code はすべて暗記していると聞きました。

しかし、僕は初心者なので、なかなか覚えきれていないので、HTTPのステータスコードをさがすのに便利なツールをPythonで用意しようと思いましたが。。。もう。。あった。。。らしく。。。用意しま。。せん。。

pip でインストールすれば。。。いいんじゃないですかね。。。(ヤケ)

$ pip install httpcode

f:id:tell-k:20130215102555p:plain

Django と localflavor の 都道府県コード の話 (ドラクエコピペ風)

注意喚起(2013/02/27)

localflavorは、Django1.5までにしか含まれていません。1.5では非推奨になっています。1.6では削除される予定です。Django1.5以上を利用している、しようと検討されている方は、利用しない方が良いでしょう。

また、他にもdjango.contribの中から

  • django.contrib.databrowse
  • django.contrib.markup

などが1.6で削除される予定です。

大声:Djangoで開発プロジェクトやりますプログラマ以外× @2 今プログラマ2人
プログラミング経験は最低でも10年ある方のみでサクサク行きます。

‐最初のスプリント終了‐

刹那:なんで、てるけーさん都道府県コードをいちいち書いてたの?
killer:ふん…
カオス:wwwwwww
てるけー:え?
刹那:何調べる労力けちってんの?
刹那:普通に「django.contrib.localflavor.jp.jp_prefectures」で一発だから
刹那:都道府県コード一個一個定義してたら47回書くけどlocalflavorなら0回。常識でしょ
killer:常識だな…
カオス:ケチるなよww
てるけー:すいません、知らなかったんです
刹那:しかも最初は全員Django開発経験アリで、理解者のみって言ったのに
killer:無知は…万死に値する……
カオス:どんまい てるけー www
てるけー:すいません次からやります
刹那:実装者はsettingsで諸々設定して、対象のフォームのフィールドの
刹那:Widget として「JPPrefectureSelect」を設定した後
刹那:Redbull(200円)飲んで、諸々動き確かめて、テストを書く。基本だから
刹那:まぁ知ってたんだろうけど
刹那:調べる労力ケチってんじゃねーよカス

‐てるけーさんが開発プロジェクトから追放されました‐

すいません。知りませんでした。

f:id:tell-k:20130215102555p:plain

注意

localflavorにある都道府県コードを何が何でも採用する必要はない。既存、別システムで既に採用しているコード体系と整合性を保ちたい場合や、独自で「海外」などの項目を追加したい場合などには、特に採用する強い理由は無いだろう。参考リンクにある記事の中では、「ISO 3166-2:JP」に併せてほしかったなどの意見もあったりする。

ただコピペだとしても毎回自分で定義するの面倒だからあると嬉しいですね。

本記事は単純に「あるの!?」ていう驚きと僕の情弱っぷりを表現してみたかっただけです。なので知らなかったり、使わなかったとしても、万死には値しない……

またlocalflavor.jpの中には、日本の 郵便番号 用のフォームフィールドも用意されていたりします。

sphinxjp.themes.basicstrap 0.2.0 リリースしました

というわけで久しぶりのブログ更新。

あれですね2012年いつのまに終わってたんですかね。2012年12月に世界が終わるとかなんとか言ってた人たちは今どんな気持ちで生活してるんですかね。ちょっと話てみたいですね。

そんなわけでSphinxというドキュメンテーションツールのデザインテーマをこさえてみました。Twiter Bootstrapという、今や猫も杓子も使い始めるほどの人気のアレをベースにしてみたテーマです。(実際、猫も杓子も使えるわけではない)

制作に当たっては、面識はございませんが@shkumagaiさんや、@shimizukawaさんがPyPiにあげてるテーマが大分参考になりました。ありがとうございます。参考にしましたっていうか、setup.pyやらなんやらの書き方はもうほぼパクリ超インスパイアされました。

@shkumagaiさんのこの資料にも大変お世話になりますた。

BootstrapをベースにしたSphinxテーマは既に幾つかありますが、ヘッダーメニューに色々入ってたりして、個人的にはもうちょっとシンプルなのないかなー的に探していたのが事の発端です。

結局求めるものは見つからなかったので、Sphinxのdefaultテーマを単純にBootstrap対応しました的なもの作り始めた次第です。

今回は利用者の方が、オプションを変えるだけで、ある程度自分の気に入ったデザインにできるように頑張ってみました。デザインの変更の仕方については、イメージが付きやすいように簡単にまとめみましたのでこれを見ながらhtml_theme_optionsの設定をしてみてください。

デザインをいじいじする例

デフォルトでは凄く簡素な感じになっています。

f:id:tell-k:20130213002501p:plain

conf.pyのhtml_theme_option下記のように変えてみます。

html_theme_options = {
    'rightsidebar': True,     
    'sidebar_span': 4,
    'nav_fixed': True,
    'nav_width': '900px',
    'content_fixed': True,
    'content_width': '900px',
    'googlewebfont': True,
    'googlewebfont_url': 'http://fonts.googleapis.com/css?family=Text+Me+One',
    'googlewebfont_style': "font-family: 'Text Me One', sans-serif",
    'inner_theme': True,
    'inner_theme_name': 'bootswatch-united',
}

するとこんな風になります。

f:id:tell-k:20130213002759p:plain

あーサイドバーウゼーって人は、下記のように設定して1カラムにすることもできたりします。

html_theme_options = {
    'nosidebar': True,    
    'googlewebfont': True,
    'googlewebfont_url': 'http://fonts.googleapis.com/css?family=Jacques+Francois+Shadow',
    'googlewebfont_style': "font-family: 'Jacques Francois Shadow', sans-serif",
    'inner_theme': True,
    'inner_theme_name': 'bootswatch-amelia',
}

f:id:tell-k:20130213004239p:plain

是非お試しください。

以下なんか雑多メモ

  • カスタムテーマを作るための簡単なチュートリアル的なものを、どっかに纏めておきたい(備忘録的な意味で)
  • DOCTYPE宣言はHTML5したった。
  • カスタムロールの作り方は以下の記事が参考になった。
  • ディレクティブとロールは別ものだという事に気づいた。
  • FontAwesome用のアイコンタグは iタグを使いたかったけど、docutilsをチラ見する限り、任意のタグを吐き出すの面倒くさそうだったのでspanタグ我慢した。(簡単なやり方があるのかもしれんけど。)
  • apache 2.0 ライセンスのもの使って配布する時は、元のライセンスの場所を明記する必要がある。
  • sphinxjp.themes.coreをベースに作ったけど、sphinxjpのどこかに連絡した方がいいんだろうか(遅い)
  • theme.confのオプションはテンプレートでは theme_xxxxという変数で参照できる。
    • booleanの判定は (theme_googlewebfont|tobool) みたいな感じでtoboolをかますと良い。
  • 検索窓が無かったのはバグです
  • スマホ対応? それ https://readthedocs.org/ で出来るしww とか言わんといて。
  • スマホ用にもうちょっと最適化したい
  • Twitter Bootstrap 2.3.0 リリースされたのは見なかった事にした。Bootswatch, Font Awesomeの対応状況をみながら対応する。
  • 0.1.x はヘッダーカラーが黒になってるけど、0.2.0は白になってるので気をつけて。黒がお好みの方はheader_inverse_colorをTrueにしてくだしあ。
  • 実はちょいちょいデザインが崩れてるぽい所があるので、ちゃんと直さな。
  • Google Web Fontとかでデカいフォントを選ぶとけっこうくずれるケースがあるのを今みつけた。。
  • 多分最低限の事しか対応できてないので、なんかデザインが崩れるとかあったらご連絡ください。

以上おわり

connpass の イベント検索を作る

数日前に「自転車 x エンジニア」のkey3の こんなツイートを見かけた。

connpass は確かに検索は出来ないが、APIを提供してくれている。

これを使ってお手軽にイベント検索を作ってみた。

f:id:tell-k:20121008142933p:plain

検索オプションとか、ページングとか対応してないので、何か要望・ご意見があればいってください。

collections.pyのnamedtupleが凄いの話

こんなツイートを数日前に見つけた。脊髄反射的にcollections.pyを見に行ったら、確かに凄くて色んな意味で感動した。見てもらえれば、分かると思うけど、端的に言うと下記のような事をしてた。 そういえば標準モジュールとか中身全然見た事なかったので、ちょこちょこ見てみようと思った。

# -*- coding: utf-8 -*-

classname = "Saiyan"
saiyan_name = "Kakarot"

template = """
# -*- coding: utf-8 -*-

class %(classname)s(object):

    def __init__(self, name):
        self.name = name

    def say_hello(self):
        return 'Hello! My Name is ' + self.name

kakarot = %(classname)s("%(saiyan_name)s")
""" % locals()

try:
    exec template
except SyntaxError as e:
    raise SyntaxError(e)

print kakarot.say_hello() #=> Hello! My Name is Kakarot

raditz = Saiyan("Raditz")
print raditz.say_hello() #=> Hello! My Name is Raditz