Sphinx のビルドをファイル監視して自動で行う

Sphinx でドキュメントを書く必要があったので、せっかくなので make html をいちいち手打ちしないで自動でビルドするようにした。

先人はいる

ファイル監視してスクリプトってのはまあある話で、Python なら watchdog というのが使えるようだ。
参考
watchdogモジュールのwatchmedoコマンドが便利 - 偏った言語信者の垂れ流し
omakeもmakeも使わずに、Sphinxドキュメントの継続的ビルド - Study08.net 対シンバシ殲滅用人型機動兵器

pip install watchdog
watchmedo shell-command --patterns="*.rst" --recursive --command='make html'
# あるいは
watchmedo shell-command -p="*.rst" -R -c="make html"

なんてことはない話ですね。

で、できると思った?

残念さやかちゃんでした!

Vim だとファイル更新が検知されない

VimFiler で新規作成したときは検知されて更新がはしるけど、ファイル保存時には検知されない。で、ちょっと聞いてみると Vim 特有の問題で他のエディターだと問題がなかった。たとえば、CotEditor だと特に問題なく検知され更新が走った。

これの問題は gorakhargosh/watchdog · GitHub にあった。

About using watchdog with editors like Vim

Vim does not modify files unless directed to do so. It creates backup files and then swaps them in to replace the files you are editing on the disk. This means that if you use Vim to edit your files, the on-modified events for those files will not be triggered by watchdog. You may need to configure Vim to appropriately to disable this feature.

Vim だとバックアップファイルの関係でファイル編集イベントが拾えないよ。だからなんか Vim の設定を無効にしてね」とある。でも set nobackup set noswapfile はしている。つまり、スワップファイルもバックアップファイルもつくらないようにしている。なぜだろう。さがした。あった。

python - Writing a file with vim doesn't fire a file change event on OS X - Stack Overflow

ということで、以下のようになった

set noswapfile
set nobackup
set nowritebackup

まあ

勝手にビルドしてくれるのはすごい楽ですね

hg log の出力をもうちょっといい感じに整形する

Feb とか Fri とかわかんない

いまのところこんなかんじの .hgrc をつかっていて、あまり不自由はなかった。

[ui]
username = atasatamatara
editor = vim

[extensions]
color =
graphlog =
pager =

[color]
status.modified = magenta bold
status.added = green bold
status.removed = red bold
status.deleted = cyan bold
status.unknown = blue bold
status.ignored = black bold
diff.diffline = bold
diff.extended = cyan bold
diff.file_a = red bold
diff.file_b = green bold
diff.hunk = magenta
diff.deleted = red
diff.inserted = green
diff.changed = white
diff.trailingwhitespace = bold red_background

[pager]
pager = LESS='FSRX' less

%include ~/.hgrc.local

だいたいいいんだけど、hg log とか hg glog したときに日付のフォーマットが Fri, 2013, みたいなそういう形式なのがちょっと嫌でどうにか整形できないかと思った。考えてみれば mercurial なんだし python で、 datetime を strftime すればいいんじゃね?と思って調べた。GUI ツール使えってのもいいが、おれは CUI で完結させるほうが好きなんです。

style と template についての資料

hg log --template {string} か、そのテンプレートになったファイル hg log --style {PATH} でできる。具体的な参考資料は以下。
style について Chapter 11. Customizing the output of Mercurial
template の設定サンプル mercurialのstyleを使用してlog出力をカスタマイズする - yuitowest's blog
具体的な設定の公式資料は hg help templating で確認できる。
また、具体的な設定項目についての日本語訳してくれているものがある。 11 Customising the output of Mercurial

.hgrc で読み込ませる設定について

Mercurial: where to put the "style file" so it can (easily) be used on all my projects - Stack Overflow を参考にした。

[ui]
style = path/to/mystyle

自分がやった具体的な設定

最終的にこんな感じになった

changeset = '\033[0;33mchengeset : {rev}:{node|short} {tags}\033[0m\nsummary   : {desc|firstline|strip}\nuser      : {author}\nbranch    : {branch}\ndate      : {date|isodate} : {date|age}\n{file_adds}\n{file_dels}\n{file_mods}\n\n'

start_file_adds = '\n'
file_add = '\033[0;31mA {file_add}\033[0m\n'
# end_file_adds = ''

# start_file_dels = ''
file_del = '\033[0;31mR {file_del}\033[0m\n'
# end_file_dels = ''

# start_file_mods = ''
file_mod = '\033[0;35mM {file_mod}\033[0m\n'
# end_file_mods = ''

とりあえず日時フォーマットを {date|isodate}して {date|age}そのコミットが何時間前かの表示を追加、branch も常に表示するようにした。ついでにファイルの add, remove, modified したのも表示されるようにした。どのファイルが更新されるかみれるというのは、誰がどのブランチでどのファイルを触ったかがわかりやすくて動きが見えやすくていい。そのかわり気持ちちょっと重くなった。hg log --limit 10 とかしてもかわらない。まあ、気持ちの問題としていまはまあいいやという。

まあ

GUI ツールつかえば簡単かもだけど、自分としてはかねがね満足。もうすこしいえば diff まわりでもっと簡単に楽にみれるようにしたいけど、まあ、いまはいいや。

ここまでかいたけど

hgview って git の tig みたいなものもあるんですね……

AWS の EC2 と S3 をちょっとさわった

目的はある特定の数日間だけサーバーが欲しいということだったんだけど、いろいろ流れて使わないことになった。でもまあ AWS のさわりくらいやっておこう。というメモ。

ざっくりとした理解

とりあえず公式やそれに準じるドキュメントを読めばだいたいわかる。あとはググれば導入くらいの話はわりとある。
アマゾン ウェブ サービス | クラウド プラットフォーム活用を支援する Amazon の Iaas, Paas 型クラウド (AWS 日本語)
Amazon EC2 (仮想サーバー Amazon Elastic Compute Cloud) | アマゾン ウェブ サービス(AWS 日本語)
AWSのはじめかた | アマゾン ウェブ サービス(AWS 日本語)
あとは自分のざっくりとした理解

  • 導入には amazon のアカウント、AWS 用のアカウント、決済としてクレカかそれに準ずるなにか、あとは本人確認のために電話番号が必要
    • 企業でやるならメルアドはそりゃそうだけど、決済のクレカあたりまわりは少し気をつけたほうが利用料金の請求時にどうとかあるらしい
  • EC2 が基本と考えていい。EBS はES2 のためのハードディスクのようなもので、S3 はあくまでそれとは独立したストレージ。RDS は DB だけど、細かい設定をしなかったりある程度手軽にパラメータなどを管理画面から行えるというあたりが楽らしい。
  • public DNS が AWS 環境下での接続するための名前(というか DNS)。だけど、IP や DNS は変わるようなので静的な IP をつけることができる。それが EIP。
  • EC2 において STOP は EC2 の料金がかからないけれど、EBS を保持する料金はかかる。terminate は AMI ごと終了する。警告もでる。
  • AMI は AWS で使うイメージファイルのようなもの。ディストリビューションごとにセットで配布されてたりもするし、自分で設定した AMI を保存してそれを適合することもできる

かるくためした

さわっただけ。だいたいは資料と触った感じでわかったけど、以下の記事が導入としてわかりやすかった。いろいろ忘れてた。
新規に作成した鍵でEC2インスタンスにSSH接続する - 虎塚

  • リージョンは Tokyo にした。なんとなく。EC2 は micro の一番小さいやつ。AMI は Amazon Linux AMI(64bit) を使用
  • 秘密鍵はリージョン単位らしい
  • 初期設定でのユーザーは ec2-user なので、そこから作業を開始しないといけない。root ではない。でもsudo 権限はついているので sudo su できる(なんかUbuntu っぽい)
    • 具体的には ssh ec2-user@ec2-xx-xxx-xxx-xx.ap-northeast-1.compute.amazonaws.com -i hoge.pem という感じ。
  • EIP については適当に作成してくれるアドレスを associate Address で EC2 インスタンスに紐づけてやればいい。release で開放。その IP 自体を消すのはなんかそれっぽいものがある。

あとは普通に物理マシン、仮想マシンレンタルサーバーでもVPNでも同じように ssh の鍵を配置してつなぐだけ。管理画面からも公開鍵の管理ができて、キーペアの作成もできるっぽい。コンソールに接続するのもブラウザに Java のプラグインがはいっていれば使えるっぽい(さくらのVPNでもそうだった)

S3 に関してはとりあえずファイルを置く、消す、WWW に公開するというところまでやった。触るだけなら特に難しいことはない。

まあ

触るのは簡単。あとは適切に使えるか。適切にスケールアウトさせたり止めたりとか。

蛇足

AWS を本格的に業務で使うときにどのインスタンスをどのくらいどんな構成でどんな AMI でやるほうがいいのかはわからない。でも、AWS を触るだけなら簡単だったというのは、今まで自宅サーバーしてたりさくらのVPNを使っていたということ、Linux を触る時に基礎的なユーザーの追加やパーミッションとオーナーの設定をとりあえず触れる程度に知っていたからだ。もうすこしいえば公開鍵認証というものがあって、公開鍵を ~/.ssh/authorized_keys に登録するという手順まで知っていたからだ*1

差分を吸収するとはそういうことで、それすらわからない状況がプログラミングや仕事において大量にある。そういうことを少しずつメモしてあるのを公開したい。そして Sphinx あたりにドキュメントとしてまとめて公開したい。かつての自分のために。プログラミングやエンジニアの「これくらいできて当然だよね」という水準は際限なく上がる*2。なまじそういう界隈をみているというのもある。でも、彼らの「当然」の話は、おれには全然当然じゃなかったことはものすごくたくさんある。

それを本家にパッチを送ったりパッケージを公開する人もいるだろう。YAPC や PyCon みたいな運営、あるいは勉強会をする人もいるだろう。ほんとうにすごいとおもう。自分は勉強会とかオフ会経由でこの業界にはいった。その恩恵は受けている。でも、そうじゃなくて、おれはあくまでインターネットに、 WWW に公開された場所に、そういうなにかをおいておきたい気持ちがある。このブログは基本的にただの備忘録だけど、そういう側面はわりとある。

まあ、やるかはわからない。明日には忘れてるかもしれない。

*1:まあここの名前はたしか sshd の設定で変えられたはずだけど、慣習的には変えないと思う

*2:まあ別にプログラミング/エンジニアだけじゃなくて音楽やイラストの界隈でもあるけど

シェルスクリプトについてすこし学んだ

「今年はインフラやデプロイやシェルスクリプトはできなくていい」とはいったものの、ある人のスクリプトがたしかに便利でいい感じだった。ので、ちょっと触発されて少しだけかいて学んだ。以下、簡単なメモ。

[改訂新版] シェルスクリプト基本リファレンス  ??#!/bin/shで、ここまでできる (WEB+DB PRESS plus)

[改訂新版] シェルスクリプト基本リファレンス  ??#!/bin/shで、ここまでできる (WEB+DB PRESS plus)

最速文法的な

まあググるといいけど。以下、コメントにかく

# 宣言時はなにもつけない
a='hoge'
# 使用するときは $a と $ をつける
# 変数を展開するときはダブルクォーテーション
echo "$a"
# 変数を展開しないときはシングルクォート
echo '$a'

ここまではまあいいとして、if の [ の実態や () や $ のつかわれかたがまちまちでかなり混乱してた。メモ。

# if のあとの [ ] の実態は test コマンド
# test のエイリアスが [
# [ コマンドの最終引数が ] だと test コマンドの終了を意味する
if [ -f ~/path/to/file ]; then
  echo 'hoge'
fi
# なので以下と同等
if [ -f ~/path/to/file ]
  then
  echo 'hoge'
fi
# [[ ... ]] も test コマンドとして似たような挙動をするけど、判定や終了コードの扱いが若干違う
# {} は関数定義などのブロック
# 関数定義
func (){...}
# (()) は算術式。そのなかで定義された変数はローカル変数として扱える
# () はサブシェル。コマンドをまとめるときにつかう
# 関数定義の () とは違う
# 絶対パスを求める。 dirname $0 は相対パスになってしまうため
BASE_DIR=$(cd $(dirname $0); pwd)
# 関数定義で引数を使うときは $@ で可変長引数、 $1, $2 などで参照する
# ${hoge:~/path/to/file}ってのはなんかこうラベルを貼った参照?あまりよくわからない

[[]] について if 文と test コマンド - UNIX & Linux コマンド・シェルスクリプト リファレンス

まあ

あんまりまだちゃんとできなくていいけど、ちょっとしたときに使える武器はほしい。実際簡単なスクリプトをつくったけど、なかなか便利だった。

パーフェクトPythonを読んだ

パーフェクトPython (PERFECT SERIES 5)

パーフェクトPython (PERFECT SERIES 5)

1冊で言語仕様から最新の技術までを網羅した内容。網羅的に解説されているだけでなく、各技術に関しては基本からしっかり解説し、必要な箇所では、技術の進歩によってブラックボックス化が進んだ、内部処理が裏で何をしているのかを掘り下げて解説してあるため、体系的に知りたい初心者はもちろん中級者にもお勧めの一冊です.最新のPython3.3に対応

Python 3系を意識しているとか、言語仕様や周辺ライブラリの紹介ってのもあるけど、なにより Pythonic な文化であるとか習慣であるとか、それこそ「Zen of Python」が日本語でここまで語られていることが貴重な書籍だと感じた。

以下は細々としたメモ。書き起こしてみたらだいぶ頭が弱い感じがする文章になってるけど、まあ、はい。

with と context manager について

with open() as f っていうのはもはやイディオムになってるんだけど、たとえば fabric での cd コマンドでも context manager を使ってたりする。内部的には __open__ __exit__ などを呼ぶことで状態を管理できるというのはなんとなく調べたときに知ってたけど、少し整理がついた。

mro と superclass

これはどの言語でもある話だろうけど、最近 Django の class base view が mixin しまくっててよくわからなかったので調べていた。そのときに「誰が親クラスなのか」「その関数は誰のものなのか」というのを探すとき、mro が役に立つ。

文字列とバイト列

たぶん Python を触るといやでも出くわすのがこれで、文字列だとおもったらバイト列で UTF-8 になってなくて UnicodeDecodeError とかはよくある。最近だと mesasge pack の話があったけど、マルチバイトなことを意識されてないコードとかわりとある。まあ実際 ascii(というか laten-1 ?) な文字列を扱う分にはたしかに不自由がない。文字の扱いについてやりだすとだいぶ面倒なので*1避けてたところあるけど、すこし整理がついた。

C拡張

たとえば PIL あたりとか cPickle とかだと C の拡張を使うことになるというのはいいけど、それが具体的にどうやってるのかを知れて「へー」と思った。

nonlocal とクロージャ

JS だとよくあるクロージャを Python でやるとき、nonlocal で一番近い変数を探しにいくところでつかえるというのはちょっとおもしろかった。ただ、それが Python としてどう使えるのかはよくわからないけれど。

proprety アクセス

@property や @property.setter みたいな話。前 Python/Django の property をどう扱えばいいかモヒカンさんに相談した話 - AtAsAtAmAtArA というのをかいたとき「とりあえず関数に倒しておくのが無難。でも状態が変わってないのならプロパティと明示してもいいんじゃないの」とあった。たぶん JavaScript においてのプロパティって話と、そもそも C みたいにプロパティアクセスがないという考え方を知らなかったので*2これもすこし整理がついた。

以上

たぶん最速文法的なところだったらウェブのチュートリアルをやればいいと思う。本当に公式のチュートリアルは充実していて、あれでだいたい使えるようになるとは思う。でもそうじゃなくて、これから Python を本格的につかいたい、より Python らしいコードをかきたい人にいいと感じた。個人的には文化や慣習、Zen of Python なところをこうした形で伝えてくれるのはわりとうれしい。自分の場合たまたま Python な会社でそういう環境だったからある程度知れたけど、きっとそういう環境であるところは少ない*3

*1:UTF-16UTF-7であるとか、ではEUC-JPであるとかの違いがあることを知ってても、じゃあ Python 的に内部的にどこまでやってるかを知るのはいまはだるい

*2:そこらへんは C を軽くさわったときや Obj-C についてすこしかじったとき少し脳内で整理がついた

*3:とはいえ、自分もPEP8には完全には従ってなかったりはする。具体的には80文字折り返し。PyPiになにかをあげたこともないし