« 2006年8月 | メイン | 2007年12月 »

2007年11月25日

mixi-photo.rb

さきほどからなんだかとまらなくなって、rubyでmixi用写真アップロードのライブラリ作ってみました。ドキュメンテーションもエラー処理もテストも皆無ですが一応置いておきます。

激しく添削希望です。

mixi-photo.rb

MixiPhoto.newすると既存のアルバム情報をとってきて、albumsに入れます。MixiPhoto#createAlbumで新規アルバムが作成できます。このとき、MixiPhoto#albumsは更新されません(ってよくないですね)。MixiPhotoAlbum#uploadPhotoするとアルバムの写真が更新されます。

超簡単な使い方例。

#!/usr/bin/ruby
$KCONV='u'
require 'mixi-photo'

user='foo@bar.com'  # mixi登録メールアドレス
pass='foobar'             # mixiパスワード

mixi = MixiPhoto.new(user, pass)

# 既存のアルバムに写真追加
mixi.albums.each { |x|
  x.uploadPhoto("./test.jpg")
}

# 新規アルバム作成、写真を追加
mixi.createAlbum("テストアルバム", "説明文").uploadPhoto("./someimage.jpg")

2007/11/26 0:59 version 0.0.2 createAlbumで説明文を必須にしました

2007/11/27 21:00 version 0.0.3 ちょっと手直し

2007/12/08 02:30 version 0.0.4 nonce生成方法のバグを、指摘に従い修正(ありがとうございます)

mixi 写真アップロードAPI

このあたりを参考に、mixiのatom ppでの写真アップロードをちまちまRubyで検証してました。

ちょっとだけ自分用にメモ。

  • 今日現在では、リクエストのURLがhttp://photo.mixi.jp/atom/r=4になってるみたい。
  • アルバムのアクセス制御は
    • 公開: <permit:access>public</permit:access>
    • 友達まで: <permit:access>friends</permit:access>
    • 非公開: <permit:access>protected</permit:access>、このときは<permit:token>に閲覧キーを入れる

まだアルバム生成のとこまでしかできてない上になんだか恥ずかしいコードですが一応貼ってみます。検証用につくったんで、写真アップロードまで入れるかどうかはわかりませんが、もし変更したらここに反映させてきます。

追記: 一応ひととおり作りましたので、新しいほうをご参照ください。古いほうはひっこめました

Module#===

RubyリファレンスマニュアルのNet::HTTPまわりをみていたら、こんな例がありました。

  response = Net::HTTP.get_response(URI.parse(uri_str))
  case response
  when Net::HTTPSuccess     then response
  when Net::HTTPRedirection then fetch(response['location'], limit - 1)
  else
    response.error!
  end
型チェックでcaseが使えるのか...? と不審に思い。caseの比較は===演算子だよな。
String === "foo" # ==> true
"foo" === String # ==> false
Object == "foo" # ==> true
Integer === "foo" # ==> false
Numeric === 1 # ==> true

クラスオブジェクトの===ってこういうふうに使えるようですが、どこで定義されてるんだ...?

と思ったら、Module#===が働いているようです。メカニズムまだ理解できません。

追記: あ、ClassがModuleのサブクラスだったのか! なるほど。っていうか、この疑問はそもそも恥ずかしい疑問だったんだな...。

Lightroom SDKでは(いまのところ)SHA1が使えない...

ちょっと寄り道してWSSEってどうやって使うんだ? とか調べていて気付きました。

いまのPreview版Lightroom SDKではLrMD5ってのがあるけど、そこではSHA1は使えません。では自前でSHA1の実装を...と思うと、Luaで書くのはちょっと現実的じゃありません。Luaにはビット演算子がないんです(元データから0,1の数字列を生成すればできなくはないですが...)。では外部コマンドを、と思うと、Lightroom SDKではシェルからの実行は削除されてます。

実行速度はともかくとして、Lua単体でSHA1作ってみるかな(笑)

追記: あ、LrTasks.execute()ってのがos.execute()とほぼ同じだ。これでできるな

Luaの勉強: 5

Luaリファレンスマニュアルの日本語訳でお勉強第5回です。

コルーチン

言葉だけ知ってるけど意味を知らないコルーチン。協調型マルチスレッドといわれたりします。継続の一種だともいわれたりします。

Luaのコルーチンは、

  • coroutine.createに、引数としてコルーチンのメイン関数を渡して作成
  • corutine.resumeで開始。
  • コルーチン内部では、coroutine.yieldで抜ける。このとき、よんだ側のresumeが帰ってくる。戻り値はtrueと、yieldの引数(あれば)。コルーチン内部でエラーがあればfalse。
  • 再度corutine.resumeを呼ぶと、yieldの後から再開される。
  • resumeの引数は、最初の時はメイン関数への引数。yieldからの復帰のときは、yieldの戻り値になります。
  • coroutine.wrapってのがあります。resumeに似ているが、
    • 戻り値はコルーチンじゃなくてresumeを呼び出す関数
    • 関数の戻り値は、resumeの戻り値から最初のブール値を除いたもの
    • コルーチン内部のエラーをキャッチすることはなく、そのまま呼び出しもとに伝搬

メカニズムは簡単ですね。使いどころを理解するのがちょっと難しそう。

でも、Lightroom SDKでは標準ライブラリcoroutineが使えないので、Lightroomのプラグイン使ってる限りはコルーチン使うことはないのです。ちょっとつまらん

2007年11月24日

Luaの勉強: 4

Luaリファレンスマニュアルの日本語訳でお勉強第4回です。

環境

グローバル変数を解決する「環境」。これもやっぱりテーブル。実はそれほどグローバルじゃなくて、関数の環境や実行中スレッドの環境はsetfenv関数で置き換えられるのでした。ユーザデータ、C関数、他のスレッドの環境は、C APIを使わないと変更できません。

って、ユーザデータの環境って使うことあるのかな...?

弱参照テーブル

弱参照テーブルから参照されているオブジェクト(キーまたは値)は、ガベージコレクト対象になります。

テーブルのメタテーブルで__modeに"k"が含まれているとキーが弱参照, "v"が含まれていれば値が弱参照、だそうです。

何に使うんだろう、弱参照...。

次はコルーチン。なので別記事をおこします。ところで「べつき」を変換すると「戸次」になるんですね。これはなんだ、地名か、人名か?

2007年11月22日

Luaの勉強: 3

Luaリファレンスマニュアルの日本語訳でお勉強第三回です。もともとの目的だったLightroom SDKも並行して調べてますが、そっちはあとでまとめて書きます。

メタテーブル

大雑把にいえばメタテーブルは演算子オーバーロードを実現する仕組み、ですね(といい加減なことを書くとえらいひとに怒られるかもしれませんが)。

値は「メタテーブル」を持つことができます。メタテーブルは、連結とか長さとか加算とかの演算子の振る舞い定義に使われます。+が呼ばれたときに、メタテーブルのaddメタメソッドが呼ばれる、という風に動きます。

テーブルやユーザデータ(ってのはC言語側データでバイト列として扱われる)のメタテーブルは、setmetatable関数で変更できます。ほかの基本型のメタテーブルは変更できません(C APIでは変更できる、そうですが)。

加算とか減算とかだけじゃなくて、「値を関数呼び出ししたときに呼ばれる」メタメソッドなんてのもあります。

う、時間切れです。今回はここまで。

2007年11月21日

Luaの勉強: 2

引き続き、Luaリファレンスマニュアルの日本語訳でお勉強です。

長さ演算子

演算子はおおむね普通。とおもっていたら、テーブルに対する長さ演算子の振る舞いにちょっとびっくりしました。

長さ演算子は単項の#です。 文字列に適用した場合はバイト数。

テーブルに適用した場合は、テーブルをtとすると: t[n] ~= nilでt[n + 1] = nilになるようなnと定義されているそうで、そうするとどうなるのか、以下実例をあげてみましょう。

t1 = {"a", "b", "c"}
#t1 -- 値は3

t2 = {value1 = "a", value2 = "b", value3 = "c" }
#t2 -- 値は0

t3 = {value1 = "a", "b", value3 = "c" }
#t3 -- 値は1

t4 = {value1= "a", [22]="b", value3="c" }
#t4 -- 値は0

t5 = {value1 = "a", "b", [2]="c"}
#t5 -- 値は2
なんでこうなるかは、リファレンスマニュアルちゃんと読むとわかります。でもこれじゃ、連想配列に対する長さ演算子としては使い物になりませんね。テーブルに対するイテレータが作れればまあ実用上問題ない、んだろうけど、イテレータってどうやって作るんだろう。

関数呼び出し構文

v:name(...)の意味は、v.name(v, ...)とほぼ同じ。ただし、v:nameの場合はvの評価は一度しか行われない。v:nameの書式を「メソッド」と呼ぶ。関数定義で:構文使っている場合はやはり「メソッド定義」と呼ばれて、暗黙の第一引数はselfという名前で参照できる。

引数の形式は、()でも、テーブルコンストラクタでも、文字列でもよい。

return 関数呼び出し ってやると、末尾再帰最適化するそうな。あとで実験してみましょう。

Luaの勉強:1

ありがたいことにLuaリファレンスマニュアルの日本語訳がありましたので、Lightroom SDKからはなれてLua自体をざっと勉強してみます。

ものすごい基本的な要素から。

テーブル

{}ってなんだ? と、Lightroom SDKのガイドをみていておもったのですが、これはテーブルというデータ構造でした。

テーブルというのは連想配列です。関数もファーストクラスオブジェクトなので、テーブルには値として関数も格納できる。この場合、この関数は「メソッド」と呼ぶ、のかな?

table.nameって記法は、table["name"]と同じ意味のシンタックス・シュガー。

変数

変数は型をもたない。グローバルかローカル。ローカル変数はレキシカルスコープを持つ。明示的にlocalと宣言しなければ変数はグローバル。

グローバル変数は、「環境」テーブルに定義されている。グローバル変数xへの参照は、_envを環境テーブルとするならば、_env.xと同じ。

実行の単位はチャンクとよび、文のあつまり。チャンクは、可変長引数の無名関数の本体と同じ。文の集まりは、ブロックでもある(構文的には同じだが、意味が違う)。do - endで囲むと単一の文もブロックになる。

多重代入

ができます。x,y = y, xで値の交換ができたり。

制御構造

けっこう普通だけど、breakやreturnはブロックの最後で使わなくてはならない、ってのが面白い。どうしても途中でbreakしたかったら、do break endとかでブロックをつくるのだ。

2007年11月20日

Adobe Photoshop Lightroom plugin SDKはじめました

超ひさびさの更新です。

Adobe Photoshop Lightroom 1.3発表と同時に、plugin SDKのpreview版が発表されました。

プラグインは、Luaというスクリプト言語で書きます。Luaって初耳でしたが、ブラジル製の組み込み向けスクリプト言語だそうで、わたしが知らないところでけっこうつかわれているらしいです。CarbonEmacsパッケージにはlua-mode.el入ってたしな。そしてLightroomはそもそも、Luaでかなりの部分が書かれているそうな。

まずはSDK Guideのチュートリアルをちまちまやってみました。Luaの文法すら知らずにやってるので、いろいろわからんのですが、雰囲気はつかめました。今日の所のメモ:

  • Luaスクリプト内で日本語はUTF8で書けばよいみたい。要仕様確認
  • Luaで{}でかこわれたモノはなんだ? propertyの列のようでもある。namespaceをあらわすこともある。tableと呼ぶらしい。
  • Luaでのピリオドとコロンの意味を調べること。namespace.functionぽいのだけど、コロンがよくわからない。factory:itemみたいな使い方。
  • import, requireの意味を調べること
  • LrFunctionContext.callWithContext...の意味を調べること