静岡プログラミング言語勢力図2013春版

13.03.23追記

皆さんのおかげでShizuoka.pyを開催することになりましたので楽しくやりましょう。

ProductName キングダム 1 (ヤングジャンプコミックス)
原 泰久
集英社 / 530円 ( 2006-05-19 )



静岡県は東西に長いので文化が結構違うのだが、実はプログラミングのカルチャーも違うのだ。 二年くらい前は西のRuby東のPythonと言われていたような気がするんだが最近は静岡県東部でHaskellerが勢力を伸ばし始めているのが認知されているらしく素晴らしいですね。

shizuoka_lang

西部にはHamamatsu.rbがあり、東部には三島Haskell無名関数の会があるのに、静岡でPythonの集まりがないのはアレなので、一度くらいはShizuoka.pyをやりませんか?

snake

巳年だしね。

Shizuoka.pyをやります

shizuoka.py

4/13 13:00-17:30@静岡b-nestです。発表者絶賛大募集中です。

Pythonの魅力は別にここに書かなくてもわかると思うので、Hokkaido.pm Casualに倣い静岡にくるとどんな美味しい食べ物があるかを書いておきます。

由比で春の桜えび漁が始まっている

静岡と三島の中間にある由比漁港で、ちょうど春漁の真っ最中なので新鮮な桜えびが食べられます。というわけで、漁港に立ち寄るのもいいでしょう。

三島のうなぎは美味い

うなぎの泥臭さをとるために綺麗な水に二三日さらす必要があるために、湧水量の多い三島ではうなぎ屋が多いそうです。

桜屋かうなよしだったら桜屋のほうが好きなんだけど昼は超混みます。

ほかにもいろいろあるよ。

沼津漁港は観光地としても面白い

沼津駅からタクシーで5分くらいの場所に沼津港があります。ちょっと観光地化しているので食べるところは色々あります。イワシ専門店の磯はるなんかはオススメです。

他には沼津港深海水族館なんかもそれなりに面白いです。

あとは沼津の誇る地ビールの店であるタップルームが昼からやっているので、昼飲みするにはオススメです。海を眺めながらビールをグビグビやりながらまったりするのは至福。

というわけで、観光も兼ねて遊びに来てもいいかと思います。

Mac OSX 10.8にmatplotlibをインストールする

昔からmatplotlibのインストールはめんどくさかったんだが、OSX 10.8には全然入らない、入る気配すらみせない。

インストールできたと思ってもipython --pylabするとAbort trap: 6する。python対話環境からimportしてみると

Symbol not found: _png_set_longjmp_fn

がでる。sofみたらln -sでいけるでっていうのを見つけたんだけど、「えーこれで解決すんの?」と思いつつやってみたけどやっぱダメだった。

さらに色々調べていたら、Mac OSX 10.7 LionにNumpy,Scipy,Matplotlibなどをインストールするというエントリをみつけて、Scipy Superpackを入れてみたらあっさりインストールできた。

仮想環境じゃないけどまぁいいかなぁと。

  • Numpy
  • Scipy
  • Matplotlib
  • iPython
  • Pandas

がインストールされるのでPython for Data Analysisを読む準備が整った。

ProductName Python for Data Analysis
Wes Mckinney
Oreilly & Associates Inc / 3634円 ( 2012-10-29 )


ScipyをLionにインストール

なんかエラーが出たのでちょっとはまった。

....ARPACK/FWRAPPERS/veclib_cabi_c.o" failed with exit status 1

みたいなやつ。

Installing SciPy / Mac OS Xにあるように環境変数を設定してから再度pipしたらインストールできた。

$ export CC=clang
$ export CXX=clang
$ export FFLAGS=-ff2c

できたのでよし。

gntpを使ってgrowl通知をしてみた

gntpを使ってみた。Growlモジュールと違ってurlを渡せばアイコンが表示されるので便利。

gntp

Shizudev作る会は、手を動かす系(ハンズオンとかワークショップ)が多めの不定期の集まりです。最近はHaskellに重点をおいています。興味があれば参加してください。

import requests
import json
import gntp.notifier

r = requests.get("https://api.github.com/orgs/shizuru/members")
members = json.loads(r.content)

growl = gntp.notifier.GrowlNotifier(
    applicationName="Shizuru",
    notifications=["New Updates", "New Messages"],
    defaultNotifications=["Shizuru Members"],
)
growl.register()

for member in members:
    growl.notify(
        noteType="New Messages",
        title=member['login'],
        description=member['html_url'],
        icon=member['avatar_url'],
        sticky=False,
        priority=1,
    )

LiveReload(Python)で更新検知させてCompassでコンパイル、ついでにブラウザもリロードする

compass watchでコンパイルするたびにブラウザリロードするのが面倒になったので、Sass+Compass, Guard, LiveReloadのRubyな組み合わせかなぁと思ったら、PYthon LiveReloadを見つけたので早速使ってみた。

Emacsでscssファイルを編集してセーブすると、更新を完治してcompassでコンパイルした後、ブラウザを自動リロードするので、かなり楽ちん。ブラウザ用にモニターが欲しくなる。

livereload

インストールはドキュメントの通りに。chromeの拡張は入れておく。

GruntfileはPythonスクリプトなのでかなり自由度が高く、なんでもできそう(growl通知とか)。

Sphinx と LiveReload を組み合わせるを参考にCompassの設定をしてみた。ソースコード見てたらCommandCompilerを使ったcompassっていう関数でも作っておけばいいんだろうなぁと思いつつあとでやるかも、やらないかも。

#!/usr/bin/env python

from livereload.task import Task
import logging

def compass():
    from subprocess import Popen, PIPE
    argv = ["compass", "compile"]
    p = Popen(argv, stdin=PIPE, stdout=PIPE, stderr=PIPE)
    stdout, stderr = p.communicate()
    if stderr:
        logging.error(stderr)

Task.add('sass/screen.scss', compass)

Sphinxもブラウザが自動更新したら快適だろうなぁと思ったのでこっちも対応しておく。

Pythonで今週がいつからいつまでかを調べる

例えば SQLAlchemyである週(今週とか先週)で検索をかけたいとか結構ある(calendar daysじゃなくてworking daysとか)。

そういう時に今日が何曜日か調べて月曜日から金曜日までのたし引きをするのがすぐに思いつくんだけどスマートじゃないのでちょっと調べたらdatetime.isocalendarっていうメソッドで今日が今年の第何週かが返ってくる。

というわけなので、週の1日目(月曜)と5日目(金曜)を探せばいい。

>>> from datetime import datetime
>>> today = datetime.now()
>>> today
datetime.datetime(2013, 3, 8, 18, 48, 12, 860947)>>> today.isocalendar()
(2013, 10, 5)
>>> ti = today.isocalendar()
>>> datetime.strptime("{} {} {}".format(ti[0], ti[1], 1), "%Y %W %w")
datetime.datetime(2013, 3, 11, 0, 0)

ん、次の週の月曜日を指している?

というところがハマったポイントでisocalendarは1からはじまるけど%Wは0からはじまるみたい。

なので第何週目かから1を引いておく

>>> datetime.strptime("{} {} {}".format(ti[0], ti[1]-1, 1), "%Y %W %w")
datetime.datetime(2013, 3, 4, 0, 0)
>>> datetime.strptime("{} {} {}".format(ti[0], ti[1]-1, 5), "%Y %W %w")
datetime.datetime(2013, 3, 8, 0, 0)

あとはデータベースに問い合わせをすればよい。

autopep8: PythonのソースコードをPEP8に従って綺麗にしてくれるコマンド

perlでいうところのPerl::Tidyみたいなものかな。

自分の開発環境ではflymakeはしらせているので、autopep8は必要ないけど、他のヒトのpythonスクリプトを取り込む時には一回かけておくとflymakeに警告されないようになるのでなかなかいいかもしれない。

FlaskとSQLAlchemyでつくるreStructuredTextなWiki (5)

reStructuredTextをHTMLにコンバートする

まずはreStructuredTextをHTMLにコンバートするためにdocutilsをインストールします。

pip install docutils

modelを修正してreStructuredTextをHTMLにコンバートするメソッドを追加します。

from sqlalchemy import Column, Integer, String, Text, DateTime
from flaski.database import Base
from datetime import datetime
from docutils.core import publish_parts
overrides = {'doctitle_xform': 0,
             'initial_header_level': 2}

class WikiContent(Base):
    __tablename__ = 'wikicontents'
    id = Column(Integer, primary_key=True)
    title = Column(String(128), unique=True)
    body = Column(Text)
    date = Column(DateTime, default=datetime.now())

    def __init__(self, title=None, body=None, date=None):
        self.title = title
        self.body = body
        self.date = date

    def __repr__(self):
        return '<Title %r>' % (self.title)

    @property
    def html(self):
        parts = publish_parts(source=self.body,
                              writer_name="html",
                              settings_overrides=overrides
                              )
        return parts['html_body']

@propertyデコレータを使うことでcontent.html()とメソッド呼び出しではなくcontent.htmlとプロバティとしてアクセスできるようになります。setting_overridesしているのはタイトルをh1要素にしているので、トップレベルのヘッダーをh2から始めたいからです。

それからpostした時の戻り値もhtmlにコンバートしたものにします。

@app.route("/<title>", methods=["POST"])
def post_content(title=None):
    ......
    return content.html

httpieでちょっとテストしてみます

$ http --form POST http://localhost:5000/rsttest body="rst **strong** and *italic*"
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 85
Server: Werkzeug/0.8.3 Python/2.7.3
Date: Sun, 03 Mar 2013 06:29:59 GMT

<div class="document">
<p>rst <strong>strong</strong> and <em>italic</em></p>
</div>

正しく変換されています。

テンプレートを修正する

ブラウザでアクセスした場合にもきちんとHTMLが表示されるようにJinja2テンプレートを修正します。

show_content.html

{% extends "layout.html" %}
{% block body %}
<h1>{{content.title}}</h1>
<div>{{content.html|safe}}</div>
<p>{{content.date}}</p>
{% endblock %}

content.bodyをhtmlに変更するだけですが、そのままだとHTMLタグがエスケープされてしまうのでsafeフィルターを付ける必要があります。

flaski4

クリックで書き換えられるようにする

wikiのコンテンツエリアをクリックした時にformの編集画面に切り替わるようにします。そのためにjeditableプラグインを利用するのでminifyバージョンをstaticディレクトリにダウンロードしておいてください。

これはajaxで通信するので編集画面に切り替わった際に元データをGETするためのAPIを用意しておきます。

app.pyに次の関数を追加します。

@app.route("/rst/<title>")
def show_rst(title):
    content = WikiContent.query.filter_by(title=title).first()
    if content is None:
        abort(404)
    return content.body

単にrstなデータを返しているだけです。

続いてテンプレートも修正します。

show_content.html

{% extends "layout.html" %}
{% block body %}
<h1>{{content.title}}</h1>
<div class="editable_textarea">{{content.html|safe}}</div>
<p>{{content.date}}</p>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="{{url_for('static', filename='jquery.jeditable.mini.js')}}"></script>
<script>
  $(".editable_textarea").editable("{{content.title}}", { 
      type   : 'textarea',
      submitdata: { _method: "post" },
      name     : 'body',
      loadurl  : '/rst/' + '{{content.title}}',
      rows     : 10,
      submit : 'OK',
      cancel : 'cancel',
      cssclass : "editable"
  });
</script>
{% endblock %}

jeditableで操作するためにdiv要素にクラスを追加しています。

bodyの最後にjQueryとjeditableを呼び出しています。先ほどapp.pyに追加した関数はloadurlで呼び出すようになっています。

コンテンツをクリックすると編集画面になるので

flaski5

日本酒に対する熱い思いをぶつけます。

flaski6

ここまでのGitHub

まとめ

reStructuredTextなWikiのための機能はひと通り揃いました。あとは見栄えを良くするためにStylus+Nib+Nibbleあたりでデザインをちょこまかいじればいいでしょう。

1362294513