2013年4月22日

Tumblr API v2 を利用する

概要

TumblrのAPIを突然利用したくなったので、利用方法をメモする。

OAuth Key の取得

API を利用するには Twitter 等と同様 アプリケーションを登録して OAuth Keyを取得する必要がある。
プリの登録は、「http://www.tumblr.com/oauth/apps」で行なう。

Tumblr Register application

「Register application」ボタンで登録。

Tumblr reg app name

「Application name」、「Administrative contact email」、「Default callback URL」が必須なので入力する。
登録内容は後でも変更できる。callback URL はとりあえず自分のサイト等にしておけば良い。

登録が完了すると、「OAuth Consumer Key」、「Secret Key」が取れる。

クライアントアプリケーション作成

クライアントアプリケーショを作成する。
Python で rauth を利用して認証と表示までしたサンプルが以下。実際に利用する場合は「OAuth Consumer Key」、「Secret Key」を自分の物に変更する。
rauth は OAuth を簡単に処理する外部ライブラリでかなり便利。「pip install rauth」などであらかじめインストールしておくこと。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import unittest

import os
import re
import webbrowser
from ConfigParser import SafeConfigParser

from rauth import OAuth1Service


class TumblrClientTest(unittest.TestCase):
    """
    Tumblr クライアントサンプルテスト
    """

    def test_sample(self):
        """
        テスト
        """
        client = TumblrClient()

        # sessin の取得
        session = client.get_session()

        # user/info 取得
        response = session.get('user/info').json()
        self.assertEqual(response['meta']['status'], 200)
        self.assertEqual(response['meta']['msg'], 'OK')

        # blog/info 取得
        path = 'blog/scipsy.tumblr.com/info?api_key={api_key}'
        response = session.get(path.format(
            api_key=client.get_api_key())).json()
        self.assertEqual(response['meta']['status'], 200)
        self.assertEqual(response['meta']['msg'], 'OK')
        self.assertEqual(response['response']['blog']['name'], 'scipsy')


class TumblrClient(object):
    """
    Tumblr クライアントサンプル
    """
    def get_api_key(self):
        """
        API key = OAuth Consumer Key
        """
        return 'OAuth Consumer Key'

    def get_consumer_secret(self):
        """
        Secret Key
        """
        return 'Secret Key'

    def get_session(self):
        """
        session の取得
        """
        # 設定ファイルのパス
        config_file = os.path.abspath(os.path.join(
            os.path.dirname(__file__), 'tumblr.cfg'))

        tumblr = OAuth1Service(
            name='tumblr',
            consumer_key=self.get_api_key(),
            consumer_secret=self.get_consumer_secret(),
            request_token_url='https://www.tumblr.com/oauth/request_token',
            access_token_url='https://www.tumblr.com/oauth/access_token',
            authorize_url='https://www.tumblr.com/oauth/authorize',
            base_url='https://api.tumblr.com/v2/')

        if os.path.exists(config_file):
            # 設定ファイルが存在する場合、設定ファイル読み込み
            config = SafeConfigParser()
            config.read(config_file)

            access_token = config.get('account', 'access_token')
            access_token_secret = config.get('account', 'access_token_secret')

            session = tumblr.get_session((access_token, access_token_secret))
        else:
            # 設定ファイルが存在しない場合、初回認証
            session = self.auth(tumblr)

            # 設定ファイル出力
            config = SafeConfigParser()
            sec_name = 'account'
            config.add_section(sec_name)
            config.set(sec_name, 'access_token', session.access_token)
            config.set(sec_name, 'access_token_secret',
                       session.access_token_secret)
            with open(config_file, 'wb') as configfile:
                config.write(configfile)

        return session

    def auth(self, tumblr):
        """
        ブラウザでの初回認証
        """
        request_token, request_token_secret = tumblr.get_request_token()
        authorize_url = tumblr.get_authorize_url(request_token)
        print '表示されたURLをブラウザで開きます: ' + authorize_url
        webbrowser.open(authorize_url)

        authed_url = raw_input('ブラウザアドレスバーのURLをペースとしてください: ')
        verifier = re.search(r'\oauth_verifier=([^#]*)', authed_url).group(1)

        # session 取得
        session = tumblr.get_auth_session(
            request_token,
            request_token_secret,
            method='POST',
            data={'oauth_verifier': verifier})

        return session

if __name__ == '__main__':
    unittest.main()

正しく認証されていると、設定画面の「Apps」に登録したアプリが表示される。

Tumblr apps

API のドキュメント

公式 APIドキュメントが「http://www.tumblr.com/docs/en/api/v2」に存在するので、あとは必要な物を利用するだけ。

2013年4月2日

matplotlib 1.2.1 コンパイル時に Tk 8.5 must be compiled with tcl.h from Tcl 8.5 のエラー

現象

「Tk 8.5 must be compiled with tcl.h from Tcl 8.5」のエラーは Tcl 8.4 と 8.5 が同居している場合に発生する。
Mac OS X の場合、MacPorts や Homebrew、ActiveTck なんかをインストールしている環境で発生しやすい。
Linux 系の場合、パスの設定が変になっている可能性がある。

対処

Mac OS X の場合は、tkagg を利用しないのが一番簡単だと思う。
setup.cfg に以下のように設定してコンパイルすれば良い。

[gui_support]
tkagg = False

本来は根源的に解決すべきだが、とりあえずはこれでも大体の場合は困らない。
ただ tkagg を必要とする場合は、別途考える必要があるかも。

2012年12月5日

Riak コンパイルメモ

概要

Erlang で実装されたNoSQL系のデータベース「Riak」の先端をコンパイルする手順メモ。

手順

コンパイルする場合 Erlang と Git コマンドが必須なのでパスに存在するか確認しておく。

Riak はビルドに「rebar」を利用している。最新である必要は特にないが、これもコンパイルしておく。

git cline git://github.com/basho/rebar.git
cd rebar
./bootstrap

Mac OS Xでコンパイルしているが、環境変数に UNICODE が含まれていると認識されコンパイルエラーになった。
Support environment vars with unicode characters · 61c353d · l4u/rebar-1 · GitHub」のパッチをあてたら通過した。

Riak 本体をコンパイルする。rebar のコピーを忘れないようにする。

git clone git://github.com/basho/riak.git
cd riak
cp /path/to/rebar .
make rel

関連ライブラリが Git で clone されてコンパイルされるので、環境によっては時間かかる。
途中でコンパイルエラーにたまになったので、rebarのバイナリコピーしてから再度 make するとちゃんと継続してコンパイルしてくれた。
「rel」ディレクトリの下にコンパイルされた。

使い方は確認中なので、また後で書く。

2012年12月4日

XML ファイルから PO ファイル を作成する

概要

XML ファイルを翻訳することがそれなりの頻度である。翻訳するなら PO ファイルを生成するのが便利。
XML から PO ファイルを生成するには「xml2po」か、「ITS Tool」を使う。両方ともGnomeのドキュメント国際化でも使われている Python で作成されたツール。
両方とも XML から PO を生成したり、PO から XML に戻したりできる。
ITS Tool の方が新しい。

xml2po

sudo port install gnome-doc-utils
xml2po --version

POファイルの作成と、XMLへの戻しは以下のようにする。

xml2po -o sample.pot sample.xml
cp sample.pot ja.po
mkdir ja
xml2po -p ja.po sample.xml > ja/sample.xml

ITS Tool

# 依存ライブラリインストール
pip install ftp://xmlsoft.org/libxml2/python/libxml2-python-2.6.21.tar.gz
# ダウンロード
curl -O http://files.itstool.org/itstool/itstool-1.2.0.tar.bz2
tar xvfz itstool-1.2.0.tar.bz2
cd itstool-1.2.0
./configure
sudo make install
# バージョン確認
itstool --version

POファイルの作成と、XMLへの戻しは以下のようにする。

itstool sample.xml -o sample.pot
cp sample.pot ja.po
msgfmt -o ja.mo ja.po
mkdir ja
itstool -m ja.mo -o ja/ sample.xml

まとめ

翻訳対象の XML にもよるだろうが、自分は xml2po の方を普段は利用している。

2012年12月3日

Erlang を Emacs でコーディングするための設定

概要

プログラミング言語Erlangを Emacs でコーディングするための設定。

Erlangインストール

Mac の場合は dmg、MacPorts、Homebrew でインストールする方法がある。

dmgの場合

あまり知られていないみたいだが、ちゃんと dmg によるバイナリが配布されている。
以下からダウンロード可能。
https://www.erlang-solutions.com/downloads/download-erlang-otp
アクセスするとブラウザの設定で自動でOperating Systemが選択されるはずだが、Operating Systemが適切でない場合は選択しなおせば dmg がダウンロードできる。
バイナリは通常は 64bit を選択すれば良い。

MacPortsの場合

sudo port install erlang

Homebrewの場合

brew install erlang

動作確認

ターミナルから動作するか確認する。「erl」コマンドで Erlang Shell が起動する。

% erl
1 > 2 + 4.
6
2 > halt().

「.」を忘れないように。「halt()」で終了する。

Emacsの設定

erlang-modeとdistelを設定する。
erlang-mode は Erlang と同時にインストールされる。

MacPorts だと「/opt/local/lib/erlang/lib/tools-*/emacs/」に存在する。

distelは補完とか、その他いろいろ便利なので設定している。

git clone git://github.com/jixiuf/distel.git
cd distel
make

init.el の設定は以下。path 関連の設定が必要だけど、略。

(setq erlang-root-dir "/opt/local/lib/erlang")
(require 'erlang-start)
(require 'erlang-flymake)

(require 'distel)
(distel-setup)

Erlang でのプログラム経験がかなり少ないので、ほとんど設定してない。

2012年11月19日

Cassandra 1.1 簡易メモ

概要

Apache Cassandra」の 1.1.6 をとりあえず試すためのメモ。
ネット上の記事が結構古い物しかない印象なので、公開しておく。
触りだけで、深い所までは書いてない。

設置から起動

curl -O http://ftp.riken.jp/net/apache/cassandra/1.1.6/apache-cassandra-1.1.6-bin.tar.gz
tar xvf apache-cassandra-1.1.6-bin.tar.gz
cd apache-cassandra-1.1.6

# conf の中で利用しているディレクトリを作成
sudo mkdir -p /var/log/cassandra
sudo chown -R `whoami` /var/log/cassandra
sudo mkdir -p /var/lib/cassandra
sudo chown -R `whoami` /var/lib/cassandra

# 起動
bin/cassandra -f

デフォルトでは Messaging Service が 7000 ポート、thrift server が 9160 ポートを利用する。

アクセス

標準クライアントは依然から存在する「bin/cassandra-cli」か、新しい「bin/cqlsh」を利用する。
ネットや README だと cassandra-cli を利用しているが、cqlsh の方が使いやすいのでそちらを利用する。

bin/cqlsh localhost

keyspaceの作成

最初に RDB のデータベース相当 である keyspace を作成する。

CREATE KEYSPACE Keyspace1
  WITH strategy_class = 'SimpleStrategy' 
   AND strategy_options:replication_factor = 1;

keyspace に移動

cqlsh> use Keyspace1;
cqlsh:Keyspace1>

column family の作成

RDB のテーブル相当である column family を作成する。cqlshを利用すると、「CREATE COLUMNFAMILY」、「CREATE TABLE」のいずれでも作成できる。
「CREATE TABLE」を利用すると 従来の RDB 的に column も同時に作成できる。とりあえずこちらを利用したサンプル。
Snappy による圧縮を指定して作成する場合は以下のようにする。

CREATE TABLE Users (
  user_id int PRIMARY KEY,
  user_name varchar,
  age int
  )
  WITH comparator=LongType
   AND compression_parameters:sstable_compression='SnappyCompressor'
   AND compression_parameters:chunk_length_kb=128;

確認は「DESCRIBE」コマンド。

DESCRIBE KEYSPACE Keyspace1
DESCRIBE COLUMNFAMILIE 
DESCRIBE COLUMNFAMILY Users

データ挿入

データを挿入してみる。

SELECT * FROM Users;
INSERT INTO Users (user_id, user_name, age) VALUES (1, 'John Smith', 42);
INSERT INTO Users (user_id, user_name, age) VALUES (2, '日本語 挿入', 33);
SELECT * FROM Users;

INSERT は UPDATE と同じ動作をするので、prymary key が重複するデータを挿入すると上書きする。

データ参照

SELECT文を発行する。
まず count で行数を取得してみる。古いバージョンでは count は Row 中の column 数を表示している時もあったが、現在は Row の数を返すようになっている。

select count(*) from Users;

普通に SELECT文が発行できる。暗黙に「limit = 10000」が付与される。

select user_name, age from Users where user_id = 1 ;

データ削除

DELETE文を発行する。

delete from Users where user_id = 1;

「PRIMARY KEY」を設定していると、「PRIMARY KEY」以外の値が消えるだけで「PRIMARY KEY」の値が残るので、論理削除とかにした方が良い場合もある。

ソート

ORDER BY したい場合は、PRIMARY KEY を複合キーで作る必要があるので、PRIMARY KEY を複合キーで作成できる場合にしか使えない。

参考サイト

2012年11月13日

Emacs で Python の補完を強化する jedi を設定してみた

概要

Emacs の Python 補完はいろいろあるが、どれもいまいち遅い。「emacs-jedi」は結構高速に補完してくれるみたいなので、設定してみた。

設定

Python のライブラリをインストール

pip install epc
pip install jedi

Emacs のライブラリを取得。

git clone git://github.com/kiwanami/emacs-deferred.git
git clone git://github.com/kiwanami/emacs-ctable.git
git clone git://github.com/kiwanami/emacs-epc.git
git clone git://github.com/tkf/emacs-jedi.git

init.el の設定

(require 'jedi)
(add-hook 'python-mode-hook 'jedi:ac-setup)

これで auto-complete を利用して補完が可能。eldoc が有効になっていると、関数の引数説明も表示される。
結構高速に動作してくれるのでしばらく利用してみる。