やましろ先生がアヘ顔ダブルピースで溶鉱炉に沈んでから 2 ヶ月が経った #ymsr
はい
死にました
詳細は割愛します。死んだので送別会をしました。
渋谷の北海道ではなく、なんか水の上の良いところでやりました。
これでもし、やましろ先生が
正直、「妹です。」って女装したymsrが出てくる可能性が少しはあり得ると思ってる。
— 太一 (@ryushi) 2014, 2月 13
こんな感じで出てきても川に落として殺すことで送別会が成り立って便利、みたいな話をしてました。
思い出
一緒に仕事したこととかないんですけど、それ以外のところにはだいたい彼がいました。
特に java-ja との出会いはエンジニアコミュニティとの出会いであり、転職のきっかけであり、つまりは年収 2 倍です。まあ会場には ymsr 先生のおかげで 3 倍になった人もいた。
心情
向こうにやましろ先生いると思えば死ぬのも怖くないという感じがした #ymsr
— ねじめ (@drillbits) 2014, 2月 15
人見知りなぼくが勉強会とかで壁役をしてると、たいてい彼がやってきて「Twitter にあるまじきイケメンです」とか「java-ja にあるまじきイケメンです」とか言って誰かに紹介してくれました。
ぼくがそっちに行ったときにも、その勢いで紹介していただいてあの世での地位を築いていきたい。
やっぱりやましろ先生だけだと不安なのであと 2, 3 人死ぬか殺すかしないといけないですね #ymsr
— ねじめ (@drillbits) 2014, 2月 15
まだ行かないけど。
ありがとう、やましろ先生。これからもよろしく。
こちらからは以上です。
NHK 番組表 API を触る為の Python クライアント作った
はい
え!?有給休暇取ってないの!?翌日が祝日なのに!?なにすんの!?前日が日曜日で?次の日が建国記念日で?有給取らない?なにすんの!?なにすんのそれ!?え!?有給取らないの!?4連休に出来るのに!?なにすんの!?どこ勤務?どこ勤務?どこ勤務?どこ勤務?どこ勤務?どこ勤務?どこ勤務?ど
— すぎやまたいち (@sgymtic) 2014, 2月 9
有給とったはいいけど自宅の空調から異音がして全取っ替えを頼んだら 5 時間近く立ち会いでどこにも行けず暇になったので作った。
使い方は README を、API の詳細は公式ドキュメントを読めばいいと思う。例によって Python 3.3 じゃないと動きません。
先行者たち
- PHP: NHK番組表API for PHP を書いたよ - localdisk
- Scala: NHK 番組表 API の Scala クライアント - seratch's weblog in Japanese
- Perl: NHK番組表APIを触る為のPerlクライアント作った - その手の平は尻もつかめるさ
- Go: mattn/go-nhk · GitHub
- Ruby: NHK 番組表 API を触る為の Ruby クライアント作った - life.stub(:happy?).and_return(true)
- Emacs: NHK 番組表 API を触る為の Emacs クライアント作った - Thanks Driven Life
その他
実装的にはたいしたことやらないので雑多なこと色々やった。
バージョン番号の埋め込み
setup.py の setup 関数に指定するやつ、普通はそのまま書くけど、 SQLAlchemy のこれパクって nhk.__version__ で参照できる番号と同じになるようにした。便利かどうかはよくわからない。
egg じゃなくて wheel で配布するようにした
2014 年なんで。
$ pip install wheel $ python setup.py bdist_wheel upload
drone.io 使った
テストするのに API KEY 必要なので、テストコードで環境変数をみるようにして drone.io 使うようにした。
drone.io のスクリプトはこんなの。
pip install -e .[testing] python setup.py test pip install wheel python setup.py sdist bdist_wheel
環境変数 NHK_API_KEY は drone.io の設定の Environment Variables ってとこに入れる。
でもこれ普通に API 利用回数消費するので実行しすぎるとテスト全部失敗することになる。。。
ResourceWarning 出てるけど放置した
Build #3 | nhk-api
なんか出てるけど直してない。
ResourceWarning in python 3.2+ · Issue #1882 · kennethreitz/requests · GitHub
これかなー。
実用性
自作の録画サーバーに組み込んで使うかというと、
- 民法には同様の API がない
- API の仕様上 2 日分 しか取得できない(従来の epg 取得方法なら 1 週間ぐらい)
- NHK だけ特別扱いして実装するのがだるい
- オフラインでも動作するようにしたい
使わないと思います。
追記
epgdump は epgdump でチューナー使うことになるし、そこ効率化しようとすると録画してない時間を割り出して epg 取得するとか考えないといけなくてだるいけど、多分そんなこと考えるよりチューナー増やして金で解決したほうがはやい
— ねじめ (@drillbits) 2014, 2月 10
金で解決できるの便利
— ねじめ (@drillbits) 2014, 2月 10
というわけで一番下のチョコください http://t.co/cIAMiq2zb6
— ねじめ (@drillbits) 2014, 2月 10
Python and Alchemy - Python Advent Calendar 2013
この記事は Python Advent Calendar 2013 のアレです。
Python には SQLAlchemy をはじめ、錬金術由来の名を持つパッケージがたくさんある。適当に列挙する。
Elixir
エリクサー、エリクシール、霊薬であり万能薬。賢者の石と同一あるいはそこから作成される液体。
最近は言語のほうが有名だけど、こっちは ORM というか SQLAlchemy のラッパー。開発はたぶん止まってる。
なんでそんなに錬金術用語が多いのか
たぶん Python が蛇だから。蛇というのは錬金術では重要なシンボルで、よくみるのはウロボロスっていう自分の尾を噛んで環になってる蛇(有翼の竜とされることもある)。
鋼の錬金術師とかにもでてくる。ていうか PyPy のロゴがまさにそれ。
他にも、十字架にかけられた蛇が賢者の石を表していたりする。
そもそも錬金術とは
化学以前に存在した、卑金属を貴金属(黄金)に変えて一攫千金メイクマネー秒速1億センチメートルなやつ、とかじゃない。
黄金とは完全な物質、完全な精神のことであり、非金属を変成させて黄金を得るというのは、不完全な人間を完全な存在に変えるプロセスが婉曲的に表現されたもので、こっちのほうが夢がある*1。
錬金術では「一なるもの(第一質量)」が変化して様々な存在になるとされていて、その変化に携わるのが「乾 ・ 湿 ・ 熱 ・ 冷」という属性。
その第一質量と属性を結びつけるのが「エーテル」とか「第五元素」「プネウマ」で、それを操ることができれば物質を自由に錬成することができる。で、それをうまいこと抽出して集めたものが賢者の石とか呼ばれる。
錬金術とシンボル
錬金術の文献には数多くのシンボルが使われてる。
錬金術の実験とか知識は非キリスト的なやつだったので、弾圧をのがれたりするために、そういうシンボルとか暗号で技術を伝承していった。オープンソースだけど歴史的経緯を知らないと誰も読めないみたいな感じになってる。
そのうちのひとつが蛇。有翼のやつは水銀、無翼なやつは硫黄を表してて、争っている絵は化学反応を象徴してる。だから Python のロゴにも蛇が二匹いるのかもしれない。
錬金術の変成過程には必ず「黒化(死・腐敗)」「白化(復活・浄化)」「赤化(完成)」がある。ウロボロスはこの死と再生のイメージをもってる。あとその円環構造が全一思想という「全が一を作り、一は全に影響を与える」というのも表してる。
まとめ
Pelican のドキュメントにはこう書かれてる。
「ペリカン」という名前の由来
フランス語で「notebook」という意味の「calepin」のアナグラムだよ。
Why the name “Pelican”?
錬金術まったく関係ない。
他のパッケージについても、錬金術に言及してるテキストとかないっぽいし、単にプログラマが錬金術とか魔術とか好きなだけという感じがする。
真相はぼくよりもっと長く Python 使ってるおじさんたちのが知ってそう。
Next Advent は Hi_king 氏です。
*1:ただ、黄金の錬成は副産物だけど、でも無意味というわけではなくて、それはそれで大切な作業だった。大いなる作業。物質的かつ霊的作業。
ミラクルライト作った - プリキュア Advent Calendar 2013 #cure_advent
この記事はプリキュア Advent Calendar 2013のやつです。
大きなお友達は基本的にミラクルライトもらえないみたいなので Python で作った。プリキュアに力を与えてテストを実行する。
pypi: https://pypi.python.org/pypi/miraclelight
github: https://github.com/drillbits/miraclelight
$ pip install miraclelight
これで miraclelight コマンドができるけど、今回はテスト用意するのめんどくさいのでリポジトリに入ってるサンプルのテストを実行する。
$ git clone git@github.com:drillbits/miraclelight.git $ cd miraclelight $ python setup.py install $ tree . ├── README.rst ├── setup.py ├── src │ └── miraclelight │ └── __init__.py └── tests ├── __init__.py └── test_sample.py 3 directories, 5 files
カレントディレクトリに Python の unittest が discover してくれそうなやつがあるので、そのまま実行すればいい。*1
$ miraclelight
実行すると、このように表示されて止まる。
ライトをふって プリキュアを おうえんしてね!(Press enter, enter, enter) ( ^q^)ノシ
このままだとテストは永久に実行されず、プロジェクトは崩壊し、世界が砂漠になってもうダメです。
エンターキーを連打してプリキュアを応援しましょう。
10 エンターで 1 テストケース倒せる。
このテストランナーを使うと Jenkins で自動的に定期テストとかいっさいできなくなるけど、そんな人任せじゃダメだと思う。年末あたりに滅びかける世界は救えないと思う。「みんなで力を合わせれば不可能はない」とプリキュア 5 つの誓いの 6 つ目にもある。
がんばってすべてのテストを倒そう。
技術的な話
基本的には標準の unittest 拡張しただけだけど、普通にエンター入力すると改行されてしまうので、こんな感じで防いでる。
import fcntl import os import sys import termios fd = sys.stdin.fileno() oldterm = termios.tcgetattr(fd) newattr = termios.tcgetattr(fd) newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO termios.tcsetattr(fd, termios.TCSANOW, newattr) oldflags = fcntl.fcntl(fd, fcntl.F_GETFL) fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK) try: c = sys.stdin.read(1) finally: termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm) fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)
*1:ちなみに開始ディレクトリを指定したい場合は unittest と同じで miraclelight discover -s
Django + MySQL 5.5 でモデルオブジェクトの datetime の値が生成時と生成後で変わる
class Diavolo(models.Model): ctime = models.DateTimeField(auto_now_add=True)
っていう生成時に現在日時を自動的に保存してくれるやつを作るじゃないですか。
>>> d1 = Diavolo.objects.create() >>> d2 = Diavolo.objects.get(pk=d1.pk) >>> d1.ctime == d2.ctime False
はい。
>>> d1.ctime datetime.datetime(2013, 10, 25, 13, 32, 25, 244575) >>> d2.ctime datetime.datetime(2013, 10, 25, 13, 32, 25)
つらい。
MySQL を使っている場合、Django の ORM は models.DateTimeField を MySQL の TIMESTAMP 型として扱うけど、MySQL 5.5 はマイクロ秒をサポートしてない。
でも Model.objects.create() の戻り値のオブジェクトは INSERT するために生成されたやつなので、この時点ではマイクロ秒がそのまま残ってる。
対して、改めてデータベースから取得したやつは truncate されてる。なので
class DiavoloMapper(ModelMapper): class Meta: model = Diavolo def get_diavolo_as_dict(id): obj = Diavolo.objects.get(pk=id) return DiavoloMapper(obj).as_dict()
みんな大好き bpmappers を使ったこんな Mapper があったとして、こういうテスト書くと落ちる。
from testfixtures import compare class TestGetDiavoloAsDict(TestCase): def _getTarget(self): from mappers import get_diavolo_as_dict return get_diavolo_as_dict def _callFUT(self, id): func = self._getTarget() return func(id) def test_one(self): obj = Diavolo.objects.create(pk=1) dct = self._callFUT(id=1) compare(dct, dict(id=1, ctime=obj.ctime))
なので obj じゃなくて改めてモデルオブジェクトを取得してくるか、マイクロ秒を切り取るかしないといけない。まあ ctime みたいな auto_now_add されるやつはいっそテストしなくてもいいけど。
ちなみにローカルで sqlite 使ってたりするとこのテスト通る。こわいですね。
flake8 で Python のコードをチェックするときにオプションを渡すやつ
いつの間にか pep8 の 79 文字制限のところがゆるくなってたのを教えてもらった。
pep8 そろそろ 120 文字くらいにならんのかな
— ねじめちゃん (@drillbits) 2013, 10月 9
@drillbits 変わったよね、この間。
— V (@voluntas) 2013, 10月 9
@drillbits 99文字になってるよ
— Hajime Nakagami (@hajime_nakagami) 2013, 10月 9
@drillbits "いくつかのチームはより長い行を強く好みます。 あるチームによって、排他的あるいは主導的にメンテナンスされているコードは、 そのチームで合意が取れるのであれば、ウィンドウ幅の制限を80から100に 増やしてもいいでしょう。"
— V (@voluntas) 2013, 10月 9
@drillbits https://t.co/Pw3QpvkmuB
— V (@voluntas) 2013, 10月 9
チーム内で合意がとれるならまあいいんじゃね、的な感じ。
@drillbits 勉強不足 m9
— V (@voluntas) 2013, 10月 9
はい
flake8 という便利なやつがこれをチェックしてくれるけど、デフォルトは 79 文字なので引数とか設定ファイルで文字数を変えてやる必要がある。
Jenkins とかのビルドサーバーなら、コマンドに引数でいいんだけど、ローカルでチェックしたいときちょっとだるい。
http://flake8.readthedocs.org/en/latest/config.html#global
[flake8] max-line-length = 99
こういうのを ~/.config/flake8 に置けばいいけど、これだとチームごとに max-line-length とか違う場合に対応できない。
~/.config/flake8 というパスは flake8 の --config オプションで変えられるけど、vimrc で保存時に自動チェックするようにしてるので、動的に今いるプロジェクトの config のパスを与えるのがよくわからない。
autocmd FileType python autocmd BufWritePost <buffer> :!flake8 %
と思ってたら
setup.cfg でできた。~/.config/flake8 と同じ記法でプロジェクトのルートに置けばいい。setup.py も tox.ini もないプロジェクトあるのでどうかと思ってたんだけど、setup.py なくても setup.cfg で問題なかった。
http://flake8.readthedocs.org/en/latest/config.html#per-project
あと
flake8 はチェックをスルー死体業したい行に # NOQA って書くと無視してくれて便利。あまり使わないけど、Django の settings を階層化するのはよくやるので、そのときにはないと死ぬ。
おまけ
setup.cfg どこでどうやって読んでるのかと思ったら flake8 じゃなくて pep8 で読み込んでたし、単純にディレクトリさかのぼって探してた https://t.co/XvjIzUinCh
— ねじめちゃん (@drillbits) 2013, 10月 9
プリキュアハッカソンで pycure 作った
プリキュアハッカソンは普通に映画館に参戦すると事案が発生してしまう大友たちがDVDでプリキュア映画を鑑賞しつつプログラミングするやつです。
ほとんどの人が映画に夢中でコードを書かない中、めずらしくまじめにハッカソンしてたらできた。映画もちゃんと見ました。
pypi: https://pypi.python.org/pypi/pycure
github: https://github.com/drillbits/pycure
Acme::PrettyCure インスパイアードです。
$ pip install pycure
コマンド化してないので任意の対話シェルを起動するなどして動かす。
from pycure import Precure p = Precure.now p.title # -> 'ドキドキ!プリキュア' p.girls[0].name # -> '相田マナ' p.girls[0].transform() # みなぎる愛! キュアハート! # 愛を無くした悲しいジコチューさん、このキュアハートがあなたのドキドキ取り戻してみせる! # 問答無用で以上が標準出力される p.girls[0].name # -> 'キュアハート' # 名前が変更されてる
ちなみに変身から元に戻る関数は未実装です。
任意のプリキュアシリーズを取得したい場合は以下のような感じ。
from pycure import Precure Precure.slugs # -> ['', 'maxheart', 'splashstar', 'yes', 'gogo', 'fresh', 'heartcatch', 'suite', 'smile', 'dokidoki'] p = Precure["smile"] # Precure は OrderedDict の拡張なのでキーを指定して取得 p.girls[2].name # -> '黄瀬やよい' p.girls[2].transform() # ピカピカピカリンジャンケンポン! キュアピース!
ちなみにジャンケンができる機能は未実装です。
あと Acme 版と同じ仕様で、初代が変身する場合は相手の名前が引数に必要。
from pycure import Precure p = Precure[""] # 無印なので空文字がキー p.title # -> 'ふたりはプリキュア' p.girls[0].name # -> '美墨なぎさ' p.girls[1].name # -> '雪城ほのか' p.girls[0].transform() # pycure.girl.PartnerInvalidError になる p.girls[0].transform("雪城ほのか") # 光の使者、キュアブラック! # 光の使者、キュアホワイト! # ふたりはプリキュア! # 闇の力のしもべ達よ! # とっととお家に帰りなさい! p.girls[0].name # -> 'キュアブラック' p.girls[1].name # -> 'キュアホワイト' # こちらも変身状態になってる
MaxHeart の強化フォームとかキュアエコーとか色々追加してないのある。
こちらからは以上です。