doctestの誕生についてを翻訳してみた
動機
1ヶ月ほど前にネットを徘徊していたらTim PetersがdoctestについてコメントをGoogleGroupsに書いていたので、興味半分で読んでいたらなんとそれがdoctestのプロトタイプコードだった。
Pythonの中で好きなモジュールを挙げよって言われたらおそらく真っ先にdoctestと答えるだろうってぐらい好きだし、このモジュールの強力なところはテストとしてもドキュメント中のサンプルコードとしても振舞いが可能であると言う点が非常にエレガント。
さらにこれが後にDDD(Docstring Driven Development, 巷でよく言われてるDomain Driven Developmentじゃないよ)となったという歴史的瞬間でもあったと考えたらモチベーション右肩上がりですw
翻訳文
翻訳は自分のbitbucketに公開してあるのでそちらを参照してください。
現状ではドラフト段階ですがそのうち正式版にします。
フィードバック
フィードバックについては大歓迎です。
コメントに残していってもらって結構です。
参考
今回翻訳にあたって参考にした記事(といってもだいぶ前から翻訳はしてるけど
ドキュメントの翻訳にSphinxを使う (i18n非利用) — Python製ドキュメンテーションビルダー、Sphinxの日本ユーザ会
FlashBuilder4でのデータとサービスでハイフンが入ったタグ名を回避する方法
きっかけ
自宅サーバーにSubsonicというミュージックサーバーを動かしていて、こいつはAPIを使っていろいろクライアントを作れたりする。
実際にいくつかクライアントが公式ページで紹介されている。
そこでAIRを使って自分で遊んでみようと思いたって作る事にした。
FlashBuilder4から新しく使えるようになった「データとサービス」を使うとWebサービスなどのデータがものすごく簡単にアクセスできるようになった。
ところがいざSubsonicのAPIを使って「戻り値の型を設定」のウィザードにある自動検出で操作を呼び出して設定しようすると下のようなエラーが出て先に進めず...
ActionScript命名規則の壁
SubsonicのAPIはXMLかMP3などのバイナリを返してきくるが、XMLのタグにハイフンが含まれているせいであるようだ。
実際にハイフンを除いてウィザードの「サンプルXML/JSON応答を入力」を選び、図の様に入力すると問題無く次に進む。
ググってみたらどうやらXMLパーサーが解析したタグの名前をプロパティ名に充てようとするために起こるらしい。
具体的に言うとXMLに"foo-tag"というタグ名があるとオブジェクトは次の様にマッピングしようとする(多分
HogeObj.foo-tag
ハイフンはマイナス演算子として扱われるためにエラーになるらしい。
回避方法としては[]を使ってインデックスに文字列を指定してアクセスすればいけるらしい。
でも今回はデータとサービスの機能を使いたいしということで却下w
Flaskでproxy的な使い方をする
まずFlaskを簡単に説明するとRubyでいうSinatraにあたるマイクロWebフレームワーク。
詳しく知りたい方はググってください。
で、具体的な方法はFlaskがSubsonicサーバーのフロントエンドになりFlaskのハンドラがurllib2でアクセスしにいってその中のXMLを書き換えるという強引な方法。
こうした理由はHTML5でも使う予定をしてるけどサーバーが返すレスポンスが少しマズいのでaudioタグで再生できないというのが有ったし、いろいろ書き換えて遊ぶためにFlaskを採用した。
まあ最もお前の趣味だろと言われれば否定しないけどw
コード
今回できたコードが以下。
とりあえうず動く確証が欲しかったのでベタ書き&ping.viewのAPIのみしか動きませんが...
#! python # -*- coding:utf-8 -*- from flask import Flask import urllib2 BASEURL = 'http://<subsonic-url>/rest/' app = Flask(__name__) @app.route("/ping.view") def do_ping(): target_action = "ping.view?u=USERNAME&p=PASSWORD&v=VERSION&c=CLIENTNAME" result = urllib2.urlopen(BASEURL + target_action) result_body = result.read() return result_body.replace("subsonic-response", "subsonicResponse") if __name__ == '__main__': app.run(debug=True)
ちなみにユーザー名とかパスワードとか(GETパラメータのu,pの部分)べた書きすればパスワード無しでAPI使えるだだ漏れミュージックサーバーができる。
iPadでPDFをiBooksに保存する方法
iBooksで開く
普段はiPhone使ってるのでPDFダウンロードするとiBooksで開くというボタンが開く事が出来るけどiPadのSafariには無く、どうやらiOS4のSafariの機能らしい。
ということでこの方法は秋まで待つしかない。
Goodreader経由で開く
幸い上司の持っているiPadにはGoodreaderが入っていて、最初はURLコピーしてGoodreaderでペーストしてダウンロードしてそれをiBooksで開いてくださいという提案をしたら、そんなめんどくせー事いちいちやってられるかとあっさり却下された。
で、今日しばらく調べたらhttpの前にgをつけて、ghttp:// 〜にすればGoodreaderで開けるらしい。
さすがにアドレスバーにコピペしてgつけてくださいって言っても二の舞になりかねないのでブックマークレットを作る事にした。
ブッマークレットのソース
スペースはURLエンコードしてやるのが正しいんだろうけど、しなくてもうまくいったのでとりあえず貼っとく。
javascript:var a=document.getElementsByTagName('a');for(var i=0;i<a.length;i++){if(a[i].href.search(/^http:\/\/.*\.pdf$/i)==0){a[i].href='g'+a[i].href;}}
解説するとhttp:// 〜.pdfのリンクのURLの先頭にgをつけて書き換えるということをしているだけです。
解説終わり。
バグや改善などあったら指摘いただければ幸いです。
SimpleHTTPServerのMIMEタイプ追加
今HTML5でGPSロガー作ろうと言う事でコーディング中。
んで山の中の僻地言った場合どうすんのよとかいちいちつなぐとお金掛かるし的な事を考えてOffline Web Applicationsを使おうとなり、習得の為に写経することにした。
とりあえずテスト用にHTTPサーバーが欲しいときにはPythonistaな人なら迷わず
python -m SimpleHTTPServer
とやってると思います。
Offline Web Applicationsを実現するにはキャッシュマニフェストというものを書かないといけないんだけど、それのMIMEタイプが"text/cache-manifest"にする必要がある。
そこでMIMEタイプを追加する方法を調べたらSimpleHTTPHandlerのextensions_mapにマッピングを追加すればいいらしい。
ちなみにextensions_mapはdict型です。
出来たコードは以下。
コード自体は9割公式マニュアルのパクリです。
#! python # -*- coding:utf-8 -*- import SimpleHTTPServer import SocketServer PORT = 8000 Handler = SimpleHTTPServer.SimpleHTTPRequestHandler Handler.extensions_map['.manifest'] = 'text/cache-manifest' httpd = SocketServer.TCPServer(("",PORT), Handler) print "serving at port", PORT httpd.serve_forever()
取得結果もばっちり。
TDDBC名古屋に参加してきた
rst2pdfの日本語周り設定
日本語でrstファイルを書いてそのままrst2pdfに突っ込むと大変残念なPDFが生成される。
ググったところフォントとスタイルシートを設定すればいいらしい。
具体的な設定は以下を参照してください。
rst2pdfをWindowsで使ってみた - 偏った言語信者の垂れ流し
本題
で、このスタイルシートとフォントの指定をいちいちするのは非常に面倒。
たまにしか使わないからいいかと思ったけど、たまにしか使わないので毎回「オプションどうやって書いたっけ?」な状態。
調べたら公式マニュアルに設定ファイルを書けと載っていたので設定してみたところ無事できた。
設定ファイル
以下自分が使っている設定ファイル。
フォントやスタイルシートは先述の日本語の設定の記事を書いたid:nurupobugさんのものを基に自分の環境に合わせたもの使ってます。
# This is an example config file. Modify and place in ~/.rst2pdf/config [general] # A comma-separated list of custom stylesheets. Example: # stylesheets="fruity.json,a4paper.json,verasans.json" stylesheets="~/.rst2pdf/ja.json" # Create a compressed PDF # Use true/false (lower case) or 1/0 # Example: compressed=true compressed=false # A colon-separated list of folders to search for fonts. Example: # font_path="/usr/share/fonts:/usr/share/texmf-dist/fonts/" font_path="C:/Fonts" # Language to be used for hyphenation support language="ja_JP" # Default page header and footer header="" footer="" # What to do if a literal block is too large. Can be # shrink/truncate/overflow fit_mode="shrink" # What is the maximum level of heading that starts in a new page. # 0 means no level starts in a new page. break_level=0
header, footerはNoneにしておくと何故かそのまま"None"と入ってしまうので空文字を設定した。
rst2pdf公式マニュアル和訳
3章の設定ファイルを抜粋で翻訳。
かなり適当なので、翻訳ミス等がありましたらご指摘ください。
自分で訳しておきながら自分の設定ファイルは英語というw
3 設定ファイル
バージョン0.8からrst2pdfは/etc/rst2pdf.confと~/.rst2pdf/configにある設定ファイルを読み込みます(設定ファイルがある場合)。
~/.rst2pdf/configの設定ファイルは/etc/rst2pdf.confにある設定ファイルより優先されます。
以下に現在使用できる設定とファイル内容の例を示します。# これは設定ファイル例です。修正して~/rst2pdf/configに置いてください。 [general] # カンマ区切りのカスタムスタイルシートのリスト。 # 例:"fruity.json,a4paper.json,verasans.json" stylesheets="" # 圧縮されたPDFを生成 # 使用する true/false (全て小文字) もしくは 1/0 # 例: compressed=true compressed=false # コロン区切りのフォントサーチパスのリスト # 例: font_path="/usr/share/fonts:/usr/share/texmf-dist/fonts/" font_path="" # 言語のハイフネーションサポート language="en_US" # デフォルトのページヘッダとページフッタ header=None footer=None # リテラルブロックが大きすぎる場合の処理 # shrink/truncate/overflow fit_mode="shrink" # 改ページ処理のヘッディング最大レベルを指定します。 # 0は改ページ処理のレベルを設定しないことを意味します。 break_level=0rst2pdfにある設定例にはすべてのオプションが含まれています。
小数点の表し方とメソッド呼び出し
第2回Python-FITで
dir(3)で調べると、3はrealというメソッドを持っている。しかし3.realはできない。なぜ?
という質問が出た。
確認してみると
>>> 3.real File "<stdin>", line 1 3.real ^ SyntaxError: invalid syntax
確かにエラーだ。
その時自分も咄嗟には答えられなかったけど、書籍版Pyチュー第1版かなんかに
整数に.をつけると小数点として扱われる。
的なものを思い出した。そこで確認したら、
>>> type(3) <type 'int'> >>> type(3.) <type 'float'>
となった。んで、float型がraalメソッドは持っているかということを確認したら、
>>> dir(3.) ['__abs__', '__add__', '__class__', '__coerce__', '__delattr__', '__div__', '__divmod__', '__doc__', '__eq__', '__float__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getformat__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__int__', '__le__', '__long__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__nonzero__', '__pos__', '__pow__', '__radd__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rmod__', '__rmul__', '__rpow__', '__rsub__', '__rtruediv__', '__setattr__', '__setformat__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', 'as_integer_ratio', 'conjugate', 'fromhex', 'hex', 'imag', 'is_integer', 'real']
問題なくある様子。ということで上記の結果から導き出される事実は、
浮動小数点の表記間違ってるぞゴルァ
ということで怒られているんだろう。正しくは、
>>> int(3).real 3 >>> (3).real 3
2つ目は何をしているかと言うと、ただし()内の演算は行おうとして、何もせず整数の3を返し、realメソッドを呼び出す。という動作(多分