tmux の起動時セッションを自動化する tmuxinator いれた

開発用 Ubuntu VM はスリープっぽい保存はするけど、ローカルの Mac は落とさないといけない。で、毎回 ssh でウィンドウやペインごとに ssh つないだりするのはだるい。ということで tmuxinator いれた。

導入

いろいろある。特に ruby の開発してないし、適当にシステムグローバルにいれた*1
tmuxinatorで一瞬で開発環境を起動する #Ruby #AdventCalendar #tmux #開発環境 - Qiita

# インストール
gem install tmuxinator
# .zshrc に設定
[[ -s ~/.tmuxinator/scripts/tmuxinator ]] && source ~/.tmuxinator/scripts/tmuxinator

で、つくる。ひな形やサンプルがあるのでだいたい簡単にできる。

# デフォルトの alias
mux new my_project

設定はこんなかんじにした。コマンドの連結がシェルの文法なのか独特の yml なのか、それともできないのかはよくわからない。実際動いてない。けどまあ、とりあえず複数 ssh でつなぐだけできるからいい。

# ~/.tmuxinator/my_proj.yml
# you can make as many tabs as you wish...

project_name: my_proj
project_root: ~/
socket_name:
tabs:
  - VMvim: ssh dev
  - VMterm:
      layout: main-vertical
      panes:
        - ssh dev
        - ssh dev
        - ssh dev
  - my: cd ~/work

これだけなら簡単

256 色対応

vim で 256 color 対応しようとすると「ターミナルソフト」「シェル」「screen/tmux」「vim」のすべてが対応していないと色が反映されない。で、いつもは tmux -2 で起動してたけど、mux を通すとできない。alias tmux = 'tmux -2' したりとかしたけど、結局以下に至った

  • iTerm2 のターミナル設定を xterm-256color
  • vim は t_co=256 してある
  • .tmux.conf で set-option -g default-terminal screen-256color

ちょっとつまづたいのは、xterm-256color ってターミナルの設定してるのに tmux 側では screen-256color なんだね。とか。そういうあたり。あとは github の issue あたりをみて cli_args で -2 とか設定するとかしてたけど、いらなかった。

まあ

自動化はよい

*1:まあ ruby で開発することがあったら rbenv を使うだろう。tmuxinator は rvm を想定しているっぽいのがあるけど

Django アプリのダミーデータを大量投入するスクリプトをかく

モデルのフィールドが変わったり名前変わったりしそうだし、開発初期だと sqlite でサクっとつくって壊したりする。というときでも、とりあえずサイトを動かしたりするためになんらかのダミーデータを大量投入する必要はある。で、つくってたりした。

データ量としては10モデル x 10 とかつくれればよかったから多くはないけど、外部キーの組み合わせでよしなにやる必要があるので結果的にはとりあえず50個とか200個とかの単位でつくった。

人に聞いた

いろいろ

  • python manage.py shell で for でぶんまわす
  • Emacs あたりで生 SQL かいてコピペする
  • むしろ Emacs からそのまま流す
  • mysql workbench なるものがつかいやすいらしい

とかなんかまあなんかいろいろあったけど、とりあえずまだ sqlite だしまあ for でぶんまわした。生SQLをかくのはだるそうだし、ORM であわせたほうが楽っぽい気がしたし。

from django.utils.timezone import now
from myproj.models import MyModel
for i in xrange(1, 50):
    MyModel.object.create(name="name{0}".format(i), create_time=now())

まあこんな感じでゴリゴリ連番でつくっていった

のはいいけど

最初の一回はどうにか1時間くらいでつくったのはいいけど、モデルかわったり、外部キーでいろいろつくらないといけなかったからやっぱりスクリプトにした。やってることはだいたい上記なんだけど、どうしたらラクにできるかと。

python のスクリプトにすればいいだけだった

そりゃそうだったんだが、要は make_sql とか作って python manage.py shell の中で import make_sql make_sql.main() とかすればよかっただけだった。以下はサンプル。

# coding: utf-8

if __name__ == '__main__':
    main()


def main():
    make_user()
    make_author()
    make_book()


def make_user():
    for i in xrange(1, 30):
        User.objects.create(
            name="name{0}".format(i),
            email="email{0}@email.com".format(i),
            is_delete=False)

# あとは外部キーとかたくさんコピペしながら条件付けしてつくっていく
...
# django でのシェルにはいって
python manage.py shell
# インポートして
import make_sql
# 流す
make_sql.main()

まあ

こういう作業はわりと嫌いじゃない。もっと言えばシェルスクリプトにしてからこの python のスクリプト流しらもっとらくだけど、まあそこまではしなくていいかなってところにいる。

Django でページング

よくある話、ページングしたかった。で、実際そういう機能がある。前は djang-pagination っていうのをつかったことがあったけど 1.3 くらいから使えなくなったとか、また、まあ別にそんなに難しい話でもなさそうだったので普通にフレームワークの機能で実装した。

日本語 1.0::ペジネータ (paginator) — Django v1.0 documentation
公式 1.5::Pagination | Django documentation | Django

最初から英語でみてたけど、英語のほうがサンプルコードが充実していてよい。

概要

  • Paginator クラスにクエリセットとページ指定をしてインスタンスにして
  • paginator.page(page)で実際のページを表示させる

基本はこれだけ。

ちなみに

以下にかくことをそれっぽくいい感じにお手軽に提供してくれるのが django.views.generic.ListView (class base view) ですね

サンプル

公式にあるサンプルに自分の理解でコメントをつける。

# 必用なものをとりこむ
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

def listing(request):
    # ページング対象にしたいオブジェクトをすべて取得しておく
    contact_list = Contacts.objects.all()
    # Paginator でインスタンスにする。この場合 25 件づつページングする
    paginator = Paginator(contact_list, 25)

    # クエリストリングで page の値を受け取る
    page = request.GET.get('page')
    try:
        contacts = paginator.page(page)
    except PageNotAnInteger:
        # int じゃなかったらとりあえず 1 ページ目に返す
        contacts = paginator.page(1)
    except EmptyPage:
        # 範囲外ならこの場合最後に飛ばす
        contacts = paginator.page(paginator.num_pages)
    # 辞書で渡してやる
    return render_to_response('list.html', {"contacts": contacts})

素の render_to_response だと RequestContext をつつんでくれないかもだからそこらへんは自分でよしなにする。今回は Class Base View で DetailView とかの中で get_context_data で context に上書きするような形にしていたので特に意識しなかった。

で、テンプレート

<!-- 普通に for で回して表示させる -->
{% for contact in contacts %}
    {# Each "contact" is a Contact model object. #}
    {{ contact.full_name|upper }}<br />
    ...
{% endfor %}

<!-- ページングの処理 -->
<div class="pagination">
    <span class="step-links">
        {% if contacts.has_previous %}
            <!-- ここでクエリストリングにページをわたしてやる。 -->
            <a href="?page={{ contacts.previous_page_number }}">previous</a>
        {% endif %}

        <span class="current">
            Page {{ contacts.number }} of {{ contacts.paginator.num_pages }}.
        </span>

        {% if contacts.has_next %}
            <a href="?page={{ contacts.next_page_number }}">next</a>
        {% endif %}
    </span>
</div>

難しいことはやってないんだけどもう一度いうと

  • paginator オブジェクトがページング全体の情報を持っている
  • pages = paginator.page(page) みたいにして pages オブジェクトにオブジェクトの配列にして返してやってつかったりする
  • そのために ?page= というように request.GET の辞書につめこんでいる

という流れになっている。なので、 urls.py とかでうけとってよしなにしようとか paginator オブジェクトの中とは別で pages でオブジェクトを生成する必要があるっていうあたりがハマりどろだった。

まあ

思えばはじめて Django というか Web アプリケーションフレームワークさわったちょうど2年前くらいはページングの実装とか自分でがんばってたなーとかうまくいかないなーとか*1、思い出した。素直にドキュメント読んで使えるレベルになっただけ、2年前とは変わったのかなぁ、なんて。

*1:それで django-pagination をつかった

vim で python 開発するとき pyflakes + PEP8 = flake8 が便利

補完とかは Python 開発で便利な jedi-vim いれてみたらたしかにライフチェンジングだった - AtAsAtAmAtArA とかみよう。

PEP8 する必要があった

今まではシンタックスだけの pyflakes だけしてた。PEP8 はある程度守ってるけど80行折り返しと行間については多少自分のやり方でまあいいかなって思ってからだ。でも今回は PEP8 準拠でやろうってことになった。ということで vim-pep8 いれようとしたらなくなってて、 flake8 ってのに統一されてた。

flake8 ってなに

pyflakes + PEP8 つまりシンタックスチェックと python 的なコーディングルールの両方をパッケージにしたもの。
flake8 2.0 : Python Package Index

flake8 導入

まんまです

pip install flake8

virtualenv 環境だし virtualenv.vim もいれてます。

vim でつかう

vim-flake8/ftplugin/python_flake8.vim at master · nvie/vim-flake8 · GitHub
Using syntastic with vim (and a vim bug on OSX) - Statisfactory
自分の場合 syntactic + pyflakes でやってるのでいろいろ試行錯誤した結果 pyflakes-pathogen + vim-flake8 に落ち着いた。なんか公式だと「vim-pathogen でやってね」ってあるけど、自分は NeoBundle だし、じゃあ vim-pathogen いれて pyflakes-pathogen やめたりしたら syntactic でシンタックスが自動化されなくて微妙だったからこうした。

まあ

flake8 めっちゃべんり

あと、PEP8って

けっこうメジャーなライブラリでも完全には順守されてないっぽい感じではあった。Django とか(Django は Pyhton じゃないよねとかそういうあれではなくて)。こうして自動チェックいれてしまうとそれ準拠じゃないとかえって気持ち悪いくらいになっちゃうけど、じゃあそれを言語仕様までにいれたらキツすぎるのはまあある。パーフェクトPython の感想で「Zen of Python いいね」みたいなことかいたけど、「Python のインデントだるい」という感覚少し思い出した。感じた。

sed + awk をすこしさわった

dotinstall で sedawk の講座が出たから*1せっかくなのでやってみた。思えば grep | sed しか知らないくらいだし、awk なにそれこわいという状態だし。
sed入門 (全10回) - プログラミングならドットインストール
AWK入門 (全13回) - プログラミングならドットインストール

sed(gsed)

GNU sed を使うため、Mac の場合は gnu-sed をインストールする必要がある。

引数

  • f file
  • e exec
    • これは省略可能
  • i repalce
  • n
    • あんまりわかってないけど sed -n 'p' file みたいに p するときに他のを出力しない的な

パターンスペース

アドレスに対してコマンドを実行する。記号はだいたい vi 準拠っぽい感じ

# not
3!d
# それぞれ指定
1d;4d
# 範囲
1,3d
# 末尾
$d
# 正規表現っぽいけどちょっと正規表現じゃない操作
/hoge$/d
  • p = 表示
  • a = apppend
  • i = insert
  • y = copy

まあ vi 準拠なので馴染みやすい

正規表現

s/hoge/moge/gi みたいに正規表現が使える。

  • Regexp でとったら & で参照
  • (match) (match) で \1 \2 で参照

ホールドスペース

パターンスペースの裏でよしなにする。正直難しかったし使わなさそうでだるかった。

  • パターンスペースのバックグランドで動作する
  • hでhold
  • gでget
  • x で excahge(交換)

まあ

正規表現でしかつかわないかとおもったら d,p,a,i と vi like にできるおどろき。まあでもホールドスペースはつらい。ただ sed -i.bak でバックアップはいいね。

awk(gawk)

これも Mac だと gnu-awk をいれる必要がある。

引数と実行

  • f file
  • コマンドラインでは '{}' で実行(""はだめ)。文字列リテラルは "hoge" で文字列連結は space で

概要

行指向スクリプト。レコードに対してフィールドを操作する。行志向スクリプト, Cっぽいらしい。

特殊引数

  • $0,1,2で参照 $0 は全体
  • NR は行番号
  • NF はフィールドの数

文法

大きく分けて処理としては3つになる

  • BEGIN {...}
  • something(条件など) {...}
  • something(条件など) {...}
  • something(条件など) {...}
  • END {...}

BEGIN でよしなに初期設定とかできる。デリミタ(FS(Field Separator))とか、RS でフィールドの区切りとかなんとか。
あと比較演算子と論理演算子とかもある。 (pattern) || (pattern) {command} 比較演算子には正規表現もある(~)。if 的条件もある NR < 5 とか。

関数

文字列、数値、システムコール、配列、辞書とかそれっぽいものがひととおりある。

  • printf あるよ、printf("name:%10s %-5d", $1, $3)
  • 変数と代入演算子もあるよ, 文字列は space で連結だよ
  • 組み込み関数いろいろあるから使えるよ。
    • number は int, log, sin, cos, sqrtとか
    • Stirng は sbustring, length, index, match, splitとか
    • システムコールとかある, timeとか
    • bit演算とか
    • if, for(for in), while ある
    • 配列は 1 から
    • 辞書もあるよ
    • function name(arg){} で定義できるよ

まあ

シェルスクリプトだるいですね。そりゃシェルスクリプトだるくて Perl つくったのうれしいね。がんばってパースするのやだ。でも zsh とかで使えるかも、しれない。たぶんつらぽよくてきっとやらない。

*1:ちょうどこの記事をかいたとき