nose でテスト事前、事後処理する
ナウでヤングな Pythonista はテストは nose を使うみたいなのです。
良くわかりませんがそういうものです。
事前処理と事後処理
DB の初期化とかテストの事前処理や事後処理はないと困っちゃいますが、
nose ではこんな風に書きます。
def setup_func(): # ... def teardown_func(): # ... @with_setup(setup_func, teardown_func) def test(): # ...
デコレータ以外にも色々やり方はあります。
http://somethingaboutorange.com/mrl/projects/nose/0.9.3/
pit と併用して使う
外部の API と連携してるテストなどをやりたい時に
いつも使ってる pit の環境汚したく無いなぁなんて時は
プロファイルを切り変えられるので
それを呼ぶと幸せになります
from nose.tools import with_setup from hatenad import HatenaDiary from pit import Pit __profile__ ='' def setup_func(): global __profile__ __profile__ = Pit.config()['profile'] Pit.switch('test') def teardown_func(): Pit.switch(__profile__) @with_setup(setup_func, teardown_func) def test_Post(): test_conf = Pit.get('hatena.ne.jp',{'require' : {'userid':'Your hatena.ne.jp userid','password':'Your hatena.ne.jp password'}}) # ...
これだけでテストの時だけプロファイルを切りかえられますので
少しだけテストが楽になるかなぁと思います。
注意点としては pit の設定ファイルは共有してるので
テストの途中で違うプログラムが pit を使ってしまうとテスト用のプロファイル見ちゃうので
そこだけ気をつけてくだしあ><
Python ではてなダイアリーに投稿
Python の atompub で使いやすいライブラリがみつからなかったので
自前でゴリゴリ
#!/usr/bin/env python # -*- coding: utf-8 -*- # http://d.hatena.ne.jp/keyword/%a4%cf%a4%c6%a4%ca%a5%c0%a5%a4%a5%a2%a5%ea%a1%bcAtomPub import base64 import random import sha import urllib2 import urllib from datetime import date,datetime import sys # 2.5 までは 201 がエラー扱いになっちゃうので if sys.version_info[0] < 3 and sys.version_info[1] < 6: def __http_response(self, request, response): code, msg, hdrs = response.code, response.msg, response.info() if not (200 <= code < 300): response = self.parent.error( 'http', request, response, code, msg, hdrs) return response urllib2.HTTPErrorProcessor.http_response = __http_response class WSSEHeader(urllib2.BaseHandler) : def __init__(self, userid, passwd): self.userid = userid self.passwd = passwd def get_nonce(self): private = str(random.random()) now = datetime.now() timestamp = now.strftime('%Y-%m-%dT%H:%M:%SZ') return '%s %s' % (timestamp, sha.new('%s:%s' % (timestamp, private)).hexdigest()) def get_wsse(self): nonce = self.get_nonce() base64_encoded_nonce = base64.encodestring(nonce).replace('\n', '') now = datetime.now() post_creation_time = now.strftime('%Y-%m-%dT%H:%M:%SZ') password_digest = base64.encodestring(sha.new(nonce + post_creation_time + self.passwd).digest()).replace('\n', '') return 'UsernameToken Username="%s", PasswordDigest="%s", Created="%s", Nonce="%s"' \ % (self.userid, password_digest, post_creation_time, base64_encoded_nonce) def http_request(self,req): req.add_header('X-WSSE', self.get_wsse()) req.add_header('User-agent', 'yoshiori\'s test(yoshiori@gmail.com)') return req class HatenaDiary: def __init__(self, userid, passwd): self.userid = userid self.passwd = passwd self.url = 'http://d.hatena.ne.jp/%s/atom/' % userid def postEntry(self, title, text, isDraft=False): entry = '''<?xml version="1.0" encoding="utf-8"?> <entry xmlns="http://purl.org/atom/ns#"> <title><![CDATA[%s]]></title> <content type="text/plain"><![CDATA[%s]]></content> </entry> ''' % (title,text) print entry url = self.url + 'draft' if isDraft else self.url + 'blog' return self._open(url,entry) def getEntrys(self): return self._open(self.url + 'blog') def get(self): return self._open(self.url) def _open(self,url,param=None): opener = urllib2.build_opener( WSSEHeader(self.userid, self.passwd)) return opener.open(url,param) if param else opener.open(url) if __name__ == '__main__': from pit import Pit hatena_conf = Pit.get('hatena.ne.jp',{'require' : {'userid':'Your hatena.ne.jp userid','password':'Your hatena.ne.jp password'}}) diary = HatenaDiary(hatena_conf['userid'],hatena_conf['password']) print diary.postEntry('日本語','**日本語\n-ほげ\n-ふぉお\n>|python|\nimport sys\n||<',True)
pip って何(・ω・ )
http://d.hatena.ne.jp/mopemope/20090220/p4
で、pip って何!?
pip
pip is a replacement for easy_install. It uses mostly the same techniques for finding packages, so packages that were made easy_installable should be pip-installable as well.
easy_install っていうか package の管理をもっと便利にするぜっていう認識でOK?
とりあえずインストール
$ sudo easy_install pip
自分の環境にインストールしてる package の一覧取得
$ pip freeze
で出来る
http://d.hatena.ne.jp/tokuhirom/20090219/1235034086
こういう事を Python でやりたいので
最近、環境をまっさらにした Ubuntu で
とりあえず雛形的な物を作る
$ pip freeze Beaker==0.9.5 Brlapi==0.5.2 Conch==8.1.0 GnuPGInterface==0.3.2 Numeric==24.2 PAM==0.4.2 PIL==1.1.6 PyYAML==3.06 SQLAlchemy==0.4.6 Twisted==8.1.0 Twisted-Core==8.1.0 Twisted-Lore==8.1.0 Twisted-Mail==8.1.0 Twisted-Names==8.1.0 Twisted-News==8.1.0 Twisted-Runner==8.0.0 Twisted-Web==8.1.0 Twisted-Words==8.1.0 apturl==0.2.7ubuntu1 ccsm==0.7.8 command-not-found==0.1 cups==1.0 docutils==0.4 gdata.py==1.0.9 gnome-app-install==0.5.12-0ubuntu1 human-theme==0.5 ipython==0.8.4 jockey==0.5beta3 mercurial==1.0.1 nvidia-common==0.0.0 onboard==0.0.0 pexpect==2.1 pit==0.2 pyOpenSSL==0.7 pycrypto==2.0.1 pyserial==2.3 python-apt==0.6.17 python-debian==0.1.11 python-irclib==0.4.6 python-launchpad-bugs==0.3.1 python-twitter==0.5 pyusb==0.4.1 pyxdg==0.15 rdflib==2.4.0 roman==0.2- screen-resolution-extra==0.0.0 simple-ccsm==0.7.8 simplejson==2.0.6 system-service==0.1.6 ubuntu-gdm-themes==0.30 ubuntu-wallpapers==0.28.1 ufw==0.23.3 unattended-upgrades==0.1 usb-creator==0.1.8 virtkey==0.01 wsgiref==0.1.2 xkit==0.0.0 zope.interface==3.3.1
けっこう色々な物入ってるなぁ
pip freeze > mypackages.txt
して、自分が使ってそうなのだけ残す
$ cat mypackages.txt PyYAML==3.06 SQLAlchemy==0.4.6 ipython==0.8.4 pit==0.2 python-irclib==0.4.6 python-twitter==0.5 simplejson==2.0.6
自分用の bundle 作成
$ pip bundle -r mypackages.txt yoshioris.pybundle
完成!!
これで完成した「yoshioris.pybundle」を持っていけばスグに環境が作れる!!
TODO mypackages.txt yoshioris.pybundle を バージョン管理
これ自体をどんな名前で管理しよう??
とか思いつつ mercurial 使ってみようかなぁ
誰か良い名前教えてくだしあ><
(Task::BeLike::Tokuhirom みたいなの)
pit 用の yasnippet
なんか毎回書くのメンドイので snippet 書いた。
便利♪
# -*- coding: utf-8 -*- # name: pit # contributor: Yoshiori SHOJI <yoshiori@gmail.com> # -- ${1:name} = Pit.get('${2:domain}',{'require' : {'${3:require1}':'Your $2 $3}','${4:require2}':'Your $2 $4'}})
2 つの Python-mode
なんか色々な歴史的経緯があって emacs には 2 つの Python-mode があるっぽい
- emacs22 に標準で付いてる Python-mode
- (上と区別して)python-mode.el と呼ばれてるもの http://launchpad.net/python-mode
今まで全然しらなかったので標準で入ってるのを使ってたんだけど、
タマにインデントまわりでおかしな挙動をする事があった。
と、いうかインデントまわりでおかしな挙動をされると Python は致命的なので
調べてたら上記の 2 つの Pyhton-mode を知ったんですけどねw
というわけで、気分を変えて使ってみたんだけど……
何が違うのか判らないwwww
C-c C-c で実行時にコンソールが開くか開かないかくらいの違いしかわからなかった><
とりあえず使ってみます><
http://w.koshigoe.jp/study/?%5Bpython%5Dpython-mode.el%A4%CE%A5%AD%A1%BC%A5%D0%A5%A4%A5%F3%A5%C9
ipython-el 入れてみた!!
http://ipython.scipy.org/dist/ipython.el
(require 'ipython) (setq py-python-command-args '("-cl"))
少し幸せになった!!
ファイルの更新があったら Firefox で今開いてるページをリロード
なんか色々方法はあるのですが、準備がめんどくさかったので
MozRepl 使って自分でさくっと
#!/usr/bin/env python # -*- coding: utf-8 -*- import sys,os,telnetlib,time class MozRepl: def __init__(self, host='localhost',port=4242): self.tn = telnetlib.Telnet(host,port) self.tn.read_until("repl>") def reload(self): self.tn.write('content.location.reload(true)') def close(self): self.tn.write('repl.quit()') self.tn.close() def getMtime(filename): return os.stat(filename).st_mtime if __name__ == '__main__': filename = sys.argv[1] print 'start - ' + filename mtime = getMtime(filename) mozrepl = MozRepl() while True: new_mtime = getMtime(filename); if mtime != new_mtime: mozrepl.reload() mtime = new_mtime print 'reload' time.sleep(1) mozrepl.close() print 'end'
なーんも考えずに動けばいいやで作ったので突っ込み大歓迎です><
Python でブロックスコープ的な for 文
Re: http://subtech.g.hatena.ne.jp/cho45/20090115/1232016840
import sys a = ['a','b','c',] for i in range(len(a)): (lambda item,index : sys.stdout.write(str([item,index]) + '\n') )(a[i],i)
式しか書けないけどw