2011年12月18日日曜日

HTA(HTML Application)で使われるJavaScriptエンジン

JavaScript エンジン Chakra を無理矢理使う。という記事を見て、IE9環境においてHTAで使われるJavaScript engineのバージョンが何か気になったので調べてみました。


HTAはWindows環境であれば特別な実行環境が不要なため、Windows環境で簡単な処理をやりたい、でもコマンドプロンプトは嫌だという人に使ってもらうアプリの環境として重宝しています。


調べた結果ですが、Chakraが使われるようです。ただ、何も言わないと5.7互換モードのようなので、X-UA-CompatibleでIE8/IE9モードを指示します。これでJSON.parseとかも使えるようになります。


ソース


結果

2011年12月7日水曜日

Python2からPython3へ

この記事は2011 Pythonアドベントカレンダー(Python3)8日目のエントリーです。@shimizukawaさんから指名されました、@hideaki_t/高橋です。

はじめに

igo-pythonやwhooshのPython3対応を行ったときに実際に問題となった、Python2とPython3の違いとその対応方法を書きたいと思います。なお、私の経験を元にしているため、2と3の差異の一部しかカバーしていません。
私はどちらもPython2/3両対応としたため、既存のPython2対応モジュールを3にも対応させるときに参考になればと思います。

2から3の変更点についてはすでに数回触れられている上、前日の@shimizukawaさんの記事とのかぶりが多くなっています。実際の作業においては、清水川さんの記事が参考になると思います。

と書いていたのですが、順序比較について調べていたら時間が無くなってしまいました…。

問題の分類

まず、発生した問題を分類してみました。
  • そのままでは実行できない・すぐエラーがわかるタイプ
    • SyntaxError系
      • 文字列のUnicode文字化
      • printの関数化
    • NameError系
      • 型・関数名の削除
  • 実行できるけど結果が変わる・エラーに気付かないかも知れないタイプ
    • 引数が受け付ける方が変わっている
    • 順序比較のルールが変わった

そのままでは実行できないタイプ

1. デフォルトの文字列がUnicode文字列になった

Python3では文字列がデフォルトでUnicode文字列となるため、StringPrefixが不要になりました。そのためPython2でのUnicode文字列リテラル(u"文字列")がSyntaxErrorになります。
この問題は、uを除去するだけで解決できますが、Python2.xとの互換を取るときには関数化するなどの工夫が必要になります。

2. printが文から関数になった

printが関数になったので、関数呼び出しの書式にする必要があります。とりあえず動けばいい場合、最も簡単な2/3両対応の方法は括弧'()'で囲むことです。3の場合は関数呼び出しに、2の場合はprintの対象がタプルになります。 非ASCII文字を含む出力などで期待通りの出力を得るには、関数化が必要になると思います。私はsys.stdout.writeで出力する関数を作りました。

3. 型・関数・モジュール・クラスなどの、削除・改名

  • unicode/unichr関数が無くなりました
  • 組み込みのfile型/file関数が無くなりました。ファイルはopenで開く必要があります(2.4までは2.2でfile関数が追加され、openは互換のためにfileのaliasであると書かれていました。2.5でopenが望ましいとされました)

実行できるけど、結果が変わる・実行時エラーが出るタイプ

NameError系もここに分類されますが…

1. 整数同士の割り算('/' 演算子)の結果が、整数ではなく浮動小数点数になった(PEP238)

Python2と同じように、整数同士の割り算で剰余を切り捨てた商が欲しい場合は、'//' 演算子を使う必要があります。Python2でも from __future__ import division すれば '//'演算子は使えるので、これを使いました。
これは、配列の添え字に使うなど整数が必須な場面があるとエラーが起きます。

2. 文字列ではなくbytesを受け取るようになったもの/文字しか受け付けないもの

  • ord - 文字しか受け付けません。bytesの場合は各要素が整数値なので先頭要素を取ればいいだけです
  • struct.unpack - bytesしか受け付けません(正確ではありません。後で補足します…)

3. 順序比較の変更

ここだけかぶってなかったので調べました。

Ordering Comparisonsに変更点があります。関係ないオブジェクト同士の比較などはエラーが起きるようになりました。この変更により、1<"1" や 1<Noneのような比較をするとTypeErrorが発生します。

Python 2.7.2 (default, Nov 21 2011, 17:25:27)
[GCC 4.6.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 1<None
False
>>>

Python 3.2.2 (default, Nov 21 2011, 16:50:59)
[GCC 4.6.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 1<None
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: int() < NoneType()

この影響で初期値にNoneを設定しておいて、比較するような処理が書けなくなりました。なので、None以外でその条件を満たす取り得ない値がない場合は、少し面倒です。

また、自作クラスでもそのままでは比較できません。そのクラスのオブジェクトの順序比較をしたい場合には、__lt__(self, other)メソッドの定義が必要になりました。また、sorted, list.sortに比較関数(cmp)が渡せなくなっているため、sortをしたいときにも__lt__(self, other)の定義が必要です。

どこでTypeErrorが出るのかを追ってみました。まずdisモジュールで単純な比較処理を見ると、Python2とPython3で違いはありませんでした。

>>> import dis
>>> dis.dis(lambda: 1<None)
  1           0 LOAD_CONST               1 (1)
              3 LOAD_CONST               0 (None)
              6 COMPARE_OP               0 (<)
              9 RETURN_VALUE      


ソースを追う必要がありそうなので、object.c:do_richcompareを読んでみました。
オブジェクトの型の関連をチェックしていて、比較の右辺が左辺のサブクラスになっている場合は順序比較が出来そうです。また、左辺(逆順の場合は右辺)が比較可能の場合も比較は可能のようです。

__lt__なし
>>> class C: pass
... 
>>> C()<C()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: C() < C()


__lt__あり
>>> class C:
...  def __lt__(self, x): return False
... 
>>> C()<C()
False

別クラスのオブジェクトの比較
>>> class D: pass
... 
>>> C()<D()
False
>>> D()<C()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: D() < C()
最初の方は左辺側が順序比較可能になっているためエラーになりません。

サブクラスのオブジェクトとの比較
>>> class D(C): pass
... 
>>> C()<D()
False
>>> D()<C()
False

どちらも成功します。

ただ、比較可能なものでもエラーになることがあるのは追い切れませんでした。
例 1は比較可能だがNoneとは比較できない
>>> 1<2
True
>>> 1<None
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: int() < NoneType()


実際にはNone以外で問題になることは殆ど無いと思います。

まとまりもないですが、私の分はここまでにしたいと思います。
つぎは、@lirisさんよろしくお願いします。

2011年12月3日土曜日

Arch Linuxでvmwgfxを使う

いまは簡単になっていますので、最近のvmwgfx(Arch Linux)にメモを書きました。


Arch Linux on VMware Player4.0.1でvmwgfxを使うまでのメモ。
1. VMWARE gfx kernel driverをもってくる(masterがvmwgfx 2.xになっているのでvmwgfx_2_0_branchではなくなった)

ソース取得後、makeして出来たkoを置く。
$git clone git://anongit.freedesktop.org/mesa/vmwgfx
$ make && gzip vmwgfx.ko && sudo mv vmwgfx.ko.gz /lib/modules/$(uname -r)/kernel/drivers/gpu/drm/vmwgfx/
2. 新しいSVGAドライバとXAが必要なので、aur/mesa-fullをインストール。
$yaourt -S mesa-full
不要なドライバを外すためPKGBUILDを編集(Gallium版SVGAドライバとXAを有効にする)
編集
 --with-dri-drivers=i915,i965,nouveau,radeon,r200 \
 --with-gallium-drivers=r300,r600,nouveau,svga,swrast \
を次のようにする。
 --with-dri-drivers= \
 --with-gallium-drivers=svga,swrast \
次のオプションをconfigureに追加
 --enable-xa \
あとはビルドしてインストールすればよい。
3. xf86-video-vmwareのvmwgfx_branchを準備
git clone git://anongit.freedesktop.org/xorg/driver/xf86-video-vmware
cd xf86-video-vmware
git checkout vmwgfx_branch
$ ./autogen.sh --prefix=/usr
$ make
$ make install
4. /etc/X11/xorg.conf.dに20-vmwgfx.confなんて名前でファイルを作成する
Section "Device"
 Identifier "SVGA Grapics Device"
 Driver "vmwgfx"
EndSection
5. glxheads, glxinfoなどで確認する
$ glxinfo | grep renderer
OpenGL renderer string: Gallium 0.4 on SVGA3D; build: RELEASE;