Python

SQLAlchemy

久しぶりに使った。http://www.sqlalchemy.org/download.html0.6.6になってるのね。手元にあるEssential SQLAlchemyは0.4ベースだったので、細かいところで変更が加えられている。relationを張る部分はrelationではなくrelationshipに移行してね、という注意…

Unit Test vs Functional TestそしてClean Code

Agile2008でもらったゴムバンドを未だに手首につけている。確かBob Martinだったと思うが、テスト駆動開発と「Clean Code」の関係について熱く語っていた年だ。 メソッドは短く。 メソッドが実現することは一つ。 あるメソッドのテストに色々と条件を設定し…

cron

ちょっとハマったのでメモしておく。Google App Engine(Python)でcronを動かすには、cron.yamlを記述すればよい。こちらのGoogle説明書にあるとおり。ただし...Django使って組み上げる場合はcron.yamlでの記述に注意が必要。例えばGoogle説明書にある cron: …

@patchを使ったコントローラのテスト

Python用Mockはいろいろあるけど、これは便利だと思った→Mock - Mocking and Testing LibraryDjangoでこんなコントローラがあったとしよう。 def index(request): try: token = _get_cookie(request, 'token') except KeyError: return render_to_response('…

Windowsでbotoを使う

Windows XP上でVirtualenvを設定し、botoを導入してAmazon Web Serviceの開発をする時のメモ: Virtualenv設置の注意点 環境変数TEMPはC:\Tempあたりにしておく。 Virtualenv設置先はC:\MyPython\Python26とか。 →ディレクトリ名に空白が含まれると、easy_ins…

Amazon SimpleDBをPythonからちゃんと使う

なんかいつの間にかbotoが1.9bになっていてGentooのパッケージにもしっかり格納されている。そして1.9bではquery()メソッドは消されており、2007年時点での説明書は全く役にたたない。amazonaws.comというサイトには、API一覧っぽいのが掲載されているが、や…

Gap Upを見つけるPython Script

ystockquote.pyを持ってくる。 適当なディレクトリを作る $ tree . . |-- __init__.py |-- gap.py `-- ystockquote.py gap.py import sys from ystockquote import get_historical_prices def main(argv): result = get_historical_prices(argv[0], argv[1],…

SimpleDBの一貫性読み出し性能評価

一貫性読み出し(consistency read)の性能評価をしてみた。 下記、やる気の無いコードを利用。 import boto import datetime sdb = boto.connect_sdb() domain = sdb.get_domain('test_simpledb') for item in domain: item.delete() write_sec = 0 write_mic…

RPXを使って認証を賢く簡単に

OpenIDだとかFacebook認証だとか、おじさんにはどういう仕組になっているのだか全然わからないのだが、世の中どんどん進化している。 この手の認証サービスを活用することで、利用者もサービス提供側も幸せになれる。 利用者は新たなID/Passwordの組合せを覚…

Amazon SimpleDBのConsistency Readをbotoから使うには

botoはSVN版から持ってくる。 $ svn checkout http://boto.googlecode.com/svn/trunk/ boto-read-only $ cd boto-read-only $ sudo python setup.py install select()にはconsistent_readを指定する引数がある。domain.pyより: def select(self, query='', n…

やり残し・バグ

Test書いてない。 OpenID認証を通すには、extra_environ = {'REMOTE_USER': 'test'}をRequestに渡せばよいはず。 Bug OpenID認証画面で存在しないOpenIDや空白を投入すると、エラーでこける。 /verifyが呼ばれる際に、app_globalを与えられていない模様。結…

利用者属性の登録

次に、OpenIDで認証した人がニックネームと時差を登録できるようにする。 モデル model/__init__.py import boto import jsonpickle class UserProperty(object): def __init__(self, openid = None, nickname = None, time_diff = 0): self.openid = openid…

Signout

今度はOpenIDからのSignoutを実装する。 Helper lib/helpers.py from routes import url_for clock.py helper取り込み from myclock.lib import helpers as h テンプレート修正 now.html <%inherit file="/base/index.html"/> ${c.content} <br/> <a href="${h.url_for(action = 'signout')}">Signout</a> develop</br/>…

OpenIDログイン画面の設定

OpenID認証画面だが、以下の問題が残っている。 OpenID入力欄が狭い。 時刻表示できない。 そもそも、この認証画面は誰が表示しているのだろう? もちろん、AuthKitなわけだが、具体的にはAuthKitのauthkit/authenticate/openid.pyの中のtemplate()で定義さ…

OpenID認証を取り入れる

次にOpenID認証を取り込む。 AuthKitを使うのが手っ取り早い。 だけど、説明書が整備されていなくて結構苦労した。 以下の手順でたぶんOK。 AuthKitの設定(config/middleware.py) from myclock.config.environment import load_environment from authkit.aut…

サーバの時刻を表示する

まずは認証なしでサーバの時刻を表示する。 コントローラ名はclock、アクション名はnowでいいでしょ。 $ paster controller clock clock.py import logging from pylons import request, response, session, tmpl_context as c from pylons.controllers.util…

プロジェクト設置

pasterコマンドで一発。 $ paster create -t pylons MyClock Enter template_engine (mako/genshi/jinja2/etc: Template language) ['mako']: Enter sqlalchemy (True/False: Include SQLAlchemy 0.5 configuration) [False]: 自分はVM配下のLinuxで動かして…

前提

Pylonsが設置されていること。 注: SimpleDBを使うが、別にAmazon EC2を使う必要はない。手元のLinuxやMacでいけるはず。 formbuilder - AWSのアカウントを持っていること。 これがないとSimpleDB使えません。 botoが設置されていること。 Tips: /etc/boto.c…

Pylons+SimpleDB+OpenIDチュートリアル風味

Amazon Web Serviceには、SimpleDBがついてくる。 そのSimpleDBをPylonsから使ってみようという試み。 こうしたほうがいいんでないの? という指摘歓迎。 作るもの 以下のような簡単なWebアプリケーションを考える。 ブラウザで当該アプリケーションにアクセ…

Google App Engine Oil (GAEO)

GAE上のPylonsはイケてないので、GAEOを使ってみる。 今のところよさげ。 自分へのメモ App EngineのSDKは、DataStoreの代わりにsqlite使っているので、GentooでPythonをビルドする際にUSE変数を正しく設定すること。

Pylonsは管理者権限がなくても開発環境設置可能

知らんかった... Installingより go-pylons.pyをダウンロード 適当な開発環境用ディレクトリを指定して、go-pylons.pyを実行 $ python go-pylons.py MyPylons→MyPylons配下にPylons環境が設置される。 $ ls -l total 0 drwxr-xr-x 13 masayang masayang 442 …

一覧表示

phone.py def list(self): u = jsonpickle.Unpickler() c.phones = [] indexes = meta.Session.query(model.Name).all() for i in indexes: ser = self.mc.get(i.phone_id.encode('ascii')) c.phones.append(u.restore(ser)) return render('/derived/phone/…

deleteの改造

phone.py def delete(self, id = None): if id is None: abort(404) ser = self.mc.get(id.encode('ascii')) if ser is None: abort(404) u = jsonpickle.Unpickler() phone = u.restore(ser) if not isinstance(phone, model.Phone): abort(404) query = me…

saveの改造

次に編集時の変更をインデックスに反映させる。 phone.py @restrict('POST') @validate(schema = NewPhoneForm(), form = 'edit') def save(self, id = None): if id is None: abort(404) ser = self.mc.get(id.encode('ascii')) if ser is None: abort(404)…

createのテスト追加

テストコードも直しておく。 from phonebook.model import meta, Name #..... def test_create(self): """Tests that valid data is saved to the database, that the response redirects to the view() action that a flash message is set in the session"…

番組の途中ですが...

Part-Iのテスト記述でtest_createが抜けていたので追加修正。 def test_create(self): """Tests that valid data is saved to the database, that the response redirects to the view() action that a flash message is set in the session""" response = s…

createの改造

まずはcreateが呼ばれたときに、SQLAlchemyも呼び出すようにする。 phone.py from phonebook.model import meta @restrict('POST') @validate(schema = NewPhoneForm(), form = 'new') def create(self): phone = model.Phone() for k, v in self.form_resul…

SQLAlchemyの設定

Pylonsはデータ永続層の仕組みを提供しない。が、OR Mapperの一種であるSQLAlchemyとの相性は良い。(pasterでプロジェクト設置した際に、SQLAlchemyを使うかどうか指定したでしょ→http://d.hatena.ne.jp/masayang/20100219/1266606799)今回は開発環境なので…

Pylons+memcacheDBでのデータ永続化チュートリアル風味 Part-II

Part Iでは、MemcacheDBへのCRUD(Create, Read, Update, Delete)を実装したが、「一覧表示できない」という致命的な欠陥があった。そこで今回は、検索用索引をsqliteに格納してやろう、というお話。例えばname属性で検索したり並べかえたりしたいのであれば…

Pylons+memcacheDB...削除とそのテスト

そして削除およびそのテストを記述。コントローラphone.py def delete(self, id = None): if id is None: abort(404) ser = self.mc.get(id.encode('ascii')) if ser is None: abort(404) u = jsonpickle.Unpickler() phone = u.restore(ser) if not isinsta…