pip の bundle 機能

Pylons および依存パッケージを1つの pybundle ファイルにまとめる。

$ pip bundle pylons.pybundle Pylons

以下のようなパッケージ一覧ファイルを用意して、 requirement オプションで渡すとベター

$ cat requirements.txt
Beaker==1.2.2
FormEncode==1.2.1
Mako==0.2.4
Paste==1.7.2
PasteDeploy==1.3.3
PasteScript==1.7.3
Pygments==1.0
Pylons==0.9.7rc6
Routes==1.10.3
Tempita==0.3
WebError==0.10.1
WebHelpers==0.6.4
WebOb==0.9.6.1
WebTest==1.1
decorator==3.0.1
nose==0.10.4
simplejson==2.0.9
wsgiref==0.1.2
$ pip bundle -r requirements.txt pylons.pybundle 

pybundle ファイルから Pylons をインストール(ネットワーク接続不要)

$ pip install pylons.pybundle

インストール済みパッケージのスナップショットを取ることもできる。

$ pip freeze 
Beaker==1.2.2
FormEncode==1.2.1
Mako==0.2.4
Paste==1.7.2
PasteDeploy==1.3.3
PasteScript==1.7.3
Pygments==1.0
Pylons==0.9.7rc6
Routes==1.10.3
Tempita==0.3
WebError==0.10.1
WebHelpers==0.6.4
WebOb==0.9.6.1
WebTest==1.1
decorator==3.0.1
nose==0.10.4
simplejson==2.0.9
wsgiref==0.1.2

また、 site-packages ディレクトリの下には egg-info とパッケージが個別にインストールされるので、パッケージのみを zip で固めることも可能。

$ pip zip weberror
Zip weberror (in ./lib/python2.5/site-packages/weberror)

これは pkg_resources の機能を Google App Engine と合わせて使う時に役立ちそう。
egg-info ごとアーカイブされていると、現在の appengine 1.1.9 では pkg_resources の一部機能が使えないから。

posted by id:junya_hayashi

テスト駆動デバッグ

社内でテックランチ(お昼を食べながら技術的な話題について議論する会)を行ったときの資料です。

========================================
テスト駆動デバッグ
========================================

----------
特徴
----------

- デバッグを始める前にまずテストを書く
- テストが通ったらそこでデバッグは終了。いちいちブラウザで確認したりしない

----------
メリット
----------

- エラーの再現手順が明確化される
- テストケースが自然に増える
- デグレードが防げる
- エラー処理をまじめに考えるようになる

----------
デメリット
----------

- 少し余計に時間がかかる
- テストの書きにくいタイプの処理をデバッグするのには不向き

テスト駆動デバッグでは、デバッグの流れはこんな感じになります:

  1. バグ発見!
  2. バグを再現するテストを書く
  3. できたテストを実行してみて失敗することを確認する
  4. 〜ここでようやくデバッグ
  5. テストが通ればその時点でデバッグ完了

Pyxis では buildbot による自動テストも行っているのですが、テストケースを書く場合は buildbot と組み合わせることでさらに高い効果が得られます。特に、テスト結果が視覚化される→テストを書くモチベーションが上がる→テストケースが増える→自動テストの段階で新たなバグが即座に発見されるようになる→テストを書くモチベーションが上がる、という好循環が生まれることは大きな利点だと思います。

buildbot については、いずれ改めて書きます。

Enjoy testing!

by id:knzm

Porting to Python 3: Do’s and Don’ts

http://lucumr.pocoo.org/cogitations/2008/12/07/porting-to-python-3-dos-and-donts/ の翻訳です。原文のライセンスに従い、この翻訳は Creative Commons ライセンス (http://creativecommons.org/licenses/by-nc-sa/2.0/at/deed.ja) に従います。翻訳の誤りや改善案があればコメント欄で指摘してください。

Porting to Python 3: Do’s and Don’ts
==================================================

Python 3 への移植: すべきこととすべきでないこと

So. Python 3 is here and everybody is happy. Now the community expects everyone who wrote a library to port it over to Python 3. So here my experiences so far:

Python 3 が公開されてみんな喜んでいる。今、コミュニティはライブラリの作者が Python 3 へ移植することを期待している。そこで、これまでの私の経験によると:

Don’ts

                  • -

すべきでないこと

Let’s start with the things you should not do.

すべきでないことから始めよう。

  • Use py.test for your testsuite. The developers told me that they do not plan to adapt it to Python 3 in the near future. That however is a gib no-go for such a library because it automatically breaks all the libraries that use it for unittesting. So switch over to unittest or nose as soon as possible. I’m not exactly sure how compatible nose is with Python 3, but I will post a followup about that issue in the following days because nearly all the testsuites of my libraries are currently written in py.test and nose is the testsuite that comes the closest.

py.test をテストスイートに使うこと。(py.test の)開発者達は、近い将来に py.test を python 3 へ適応させるつもりがないことを教えてくれた。しかし、それはユニットテストに py.test を使用するすべてのライブラリを自動的に壊すので、そのような(=テストスイート)ライブラリにとっての gib (big?) 失策だ。したがって、できるだけ早く unittest か nose に移行したほうがいい。 nose が Python 3 とどのくらい互換性があるのか正確には知らないが、この件について数日中に followup をポストするつもりだ。なぜなら私のライブラリのほとんど全てが現在 py.test を使って書かれていて、 nose が最も近いテストスイートだからだ。

  • Forking your library for Python 3. Don’t do that. If you can’t create a version that comes out of 2to3 and passes your testsuite do not try to hand correct the code generated. Keep in mind that you will have to support both 2.x and 3.x for at least the next two years so hand correcting the 3.x version is nothing you want to do. If you have problems with 2to3 (because it does something wrong) write it to the python-porting mailinglist.

ライブラリを Python 3 用にフォークすること。そんなことするな。もし 2to3 でテストスイートを通るバージョンを作成できないなら、生成されたコードを手で修正してはいけない。あなたは 2.x と 3.x を少なくともあと 2 年はサポートしなければならず、手作業による 3.x バージョンの修正はあなたの望むことではないということを思い出そう。もし 2to3 を使って問題があれば (because it does something wrong) python-porting メーリングリストにそのことを伝えよう。

  • Drop 2.5 support. I know converting libraries is easier if you can just support 2.6 and 3.0 but until Linux distributions / OS X ship up to date Python versions it will take some time. You will only hurt your users with such a decision.

2.5 サポートを打ち切ること。2.6 と 3.0 だけをサポートするならライブラリを変換するのは簡単だということは分かっているが、多くの Linux ディストリビューションOS X が最新の Python を搭載するようになるまでしばらくかかるだろう。そんな決断をすればユーザを傷つけるだけだ。

Dos

                  • -

すべきこと

Now to what you should do

次はあなたがすべきことだ。

  • Report problems with 2to3 as soon as possible and suggest improvements. From what I saw so far 2to3 is a nice tool but it needs a lot of post-converting fixes which are unacceptable. Try to port your library and think of how you could give 2to3 hints what it should do. I guess we can expect more command line switches, custom fixes or even comments that give 2to3 an idea of what to do (similar to how pylint ignores warnings). Write that to the porting mailinglist as soon as possible or inform “gutworth” on irc.freenode.net/#python-dev who is maintaining the 2to3 tool.

2to3 の問題をできるだけ早く連絡して、改良を提案すること。私のこれまでに見たところ 2to3 は良いツールだが、容認できない多くの変換後の修正を必要としている。私は、何をすべきかに関する考えを 2to3 に与えるための、より多くのコマンドラインスイッチや、カスタム修正またはコメントさえ期待できると思う(pylint が警告を無視するのと同様)。それを、なるべく早く porting メーリングリストに書くか、あるいは 2to3 ツールを維持している "gutworth" に irc.freenode.net/#python-dev 上で知らせる。

That’s it for the moment. Concrete tips for porting specific idoms over will come once that is possible :)

さしあたりこのくらいだ。特定のイディオムを移植するための具体的な tips は、それが可能になれば、出てくるだろう。

posted by id:knzm

レコードの前後のデータを取得する

「pubdate」「modified_at」「id」の3つのフィールドをキーにソートして、特定のレコードの前後を取得する。

    def get_neighbors(entry):
        query = Session.query(DiaryModel)

        # get neighbors
        peers = query.filter_by(pubdate=entry.pubdate)\
                     .order_by(DiaryModel.modified_at,
                               DiaryModel.id).all()
        entry_idx = [ i for i, p in enumerate(peers) if p.id==entry.id ][0]

        if entry_idx==0:
            older = query.filter(DiaryModel.pubdate<entry.pubdate)\
                         .order_by(desc(DiaryModel.pubdate),
                                   desc(DiaryModel.modified_at),
                                   desc(DiaryModel.id)).first()
        else:
            older = peers[entry_idx-1]

        if entry_idx==len(peers)-1:
            newer = query.filter(DiaryModel.pubdate>entry.pubdate)\
                         .order_by(DiaryModel.pubdate,
                                   DiaryModel.modified_at,
                                   DiaryModel.id).first()
        else:
            newer = peers[entry_idx+1]

        return [older, newer]

もっと良い方法があるだろうか?

posted by id:junya_hayashi

VietNam 出張 2

2ヶ月間も更新していないですね、ごめんなさい。
開発が進んでいないわけではなくて、むしろかなり進みました。社内的に、Pyxis を用いたBasic, Lite などの製品を開発しています。

8月は丸々VietNam出張でした。数は少ないですが、VietNam 支社でも Pythonista が着実に成長しつつあります。

id:junya_hayashi