Mac使いでは無いので詳しくは知らないのですが・・・
import locale
locale.getpreferredencoding()
によって得られるエンコーディングは、環境毎に適した方法で一般的に利用されている
エンコーディング・・・なのですが、Python 2.6 ではこの部分のMac対応部分が
UNIXのlocaleを使ったマナーに対応しておらず、Mac OS 9 から利用できる方法を
使っているようです。
Python 3.1 と 2.7 から、localeを使った方法に対応する予定です。
# コミットログは追いかけていませんが、該当バグのstatusでは2.7/3.1のみが指定されていて、
# Python 2.6.3 でのfixは期待できないかと思います。
Mercurial以外にも locale.getpreferredencoding() を利用しているアプリはあると
思うので、以下のようにしてこの関数を乗っ取ると良いかもしれません。
1) site.py を見つけ同じディレクトリに sitecustomize.py が無ければ作る
2) sitecustomize.py の中に以下の行を追加する
import locale
def _mypreferredencoding(*args):
return 'UTF-8' # がんばって環境変数から取り出すとなお良い。
_orig_getpreferredencoding = locale.getpreferredencoding
locale.getpreferredencoding = _mypreferredencoding
3) python -c "import locale; print locale.getpreferredencoding()" を実行して
UTF-8 と表示されることを確かめる。
それにしても、元のエラーメッセージで "'utf8' codec can't decode bytes in ..." と
utf8が使われているように見えるのに失敗していて、HGENCODING=utf-8すると
成功するのはやはり謎です。
--
Naoki INADA <songof...@gmail.com>
先ほどのメールに書いたように、エラーメッセージに utf8 と書かれているのが気になります。
Macでは同じUTF-8でも正規化方法が違うとか聞いたことがあるのですが、
よろしければ問題が出る環境で以下を試して頂けないでしょうか?
$ echo 機能追加 > foo.txt
$ python
Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41)
[GCC 4.3.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> foo = open('foo.txt').readline()
>>> foo
'\xe6\xa9\x9f\xe8\x83\xbd\xe8\xbf\xbd\xe5\x8a\xa0\n'
>>> foo.decode('utf8')
u'\u6a5f\u80fd\u8ffd\u52a0\n'
>>> foo.decode('utf-8')
u'\u6a5f\u80fd\u8ffd\u52a0\n'
>>>
#インタラクティブシェルを起動してコマンドを入力しています。
#シェルを抜けるにはCtrl-Dを押してください。
--
Naoki INADA <songof...@gmail.com>
> 稲田さんも仰っているように、これを解決する魔法の方法が
> sitecustomize.py のデフォルトエンコーディングを
> ASCII から UTF-8 に変更してしまうことのようです。
私が書いたのは defaultencoding ではなくてpreferredencoding の方です。
setdefaultencoding() を使うのは、Pythonistaとして負けた気分になるので(笑)、
エラーが出たらその部分を直すことにしています
> しかし、これは本質的な解決方法ではなくて、
> どこか見知らぬ場所で自動変換されているのを UTF-8 にすると、
> 見た目上、エラーが出なくなる(適切に処理される)だけで、
> 本来は適切な型を指定するのが在るべき姿(?)だと聞きました。
Mercurialはきちんとデコード/エンコードしていないからエラーになるのではなくて、
デコード/エンコードする時に指定するエンコーディングを間違っているからエラーに
なるので、デフォルトエンコーディングは関係ないですね。
ありがとうございます。
見たところ、utf-8とutf8で違いがあるわけでもないし、echoの結果も普通の
UTF-8になっていますね。
うーん、なんであのエラーメッセージが "utf8" でデコードに失敗していると
言っていたのか、なぜHGENCODINGを設定したら直るのか、まったく判らない・・・
--
Naoki INADA <songof...@gmail.com>
2009年9月15日21:21 INADA Naoki <songof...@gmail.com>:
> ありがとうございます。
> 見たところ、utf-8とutf8で違いがあるわけでもないし、echoの結果も普通の
> UTF-8になっていますね。
> うーん、なんであのエラーメッセージが "utf8" でデコードに失敗していると
> 言っていたのか、なぜHGENCODINGを設定したら直るのか、まったく判らない・・・
ちなみに "加" で終わる文字列でのトラブルは他でも見かけました。
http://idlysphere.blog66.fc2.com/blog-entry-11.html
藤原さんや稲田さんの言うとおり、ちょっと不可解で気持ちがおさまらない
ので気になっちゃってます。encoding面で思い当たることっていったら、
Macの場合 unicode の正規化処理でNFDくらいなのですが、濁点などの合字の
問題問題の話なので、今回は多分関係ないですよね。
思いつくほかの(薄い)可能性としては。。。
mercurial.encoding をみると HGENCODINGを指定しない場合、
Mac OSのlocale問題を回避するために setlocale()していますが、
これがなにかしらの影響を与える、とか。。。
で、徳冨さん、もう少しご協力願えるならば。。。
試しに HGENCODING をセットしない状態で pythonを起動し、
真っ先に
import mercurial.encoding
print mercurial.encoding.encoding
を行ってから稲田さん提示のことをもう一度行ったとしても
同じ結果でしょうか?
あと、HGENCODING をセットしない状態(エラーの出るはず)で
hg commit を実行する際に --traceback オプションを付けてみた結果を
見せてもらえば、どこでエラーが起きてるのかがわかって、
もしかしたらヒントになる *かも* しれません。
--
Shun-ichi GOTO
ありがとうございます。
> ■ 1. 前回と同様のオペレーションの記録
> tokutomi$ unset HGENCODING
> tokutomi$ env | grep HG
> tokutomi$ python
> Python 2.6.1 (r261:67515, Jul 7 2009, 23:51:51)
> [GCC 4.2.1 (Apple Inc. build 5646)] on darwin
> Type "help", "copyright", "credits" or "license" for more information.
>>>> import mercurial.encoding
>>>> print mercurial.encoding.encoding
> UTF8
>>>> foo = open('foo.txt').readline()
>>>> foo
> '\xe6\xa9\x9f\xe8\x83\xbd\xe8\xbf\xbd\xe5\x8a\xa0\n'
>>>> foo.decode('utf8')
> u'\u6a5f\u80fd\u8ffd\u52a0\n'
>>>> foo.decode('utf-8')
> u'\u6a5f\u80fd\u8ffd\u52a0\n'
>>>>
問題ないですねぇ。
ところで foo.txt を作るのに使用したエディタは、失敗したコミットの際の
コミットログを作るのに使用したエディタと同じでしょうか?
> ■ 2. --traceback のログ
> tokutomi$ hg commit --traceback -m '機能追加'
> トランザクションを中断します!
> ロールバックを完了しました
> Traceback (most recent call last):
(中略)
> File
> "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/mercurial/encoding.py",
> line 64, in fromlocal
> raise error.Abort("decoding near '%s': %s!" % (sub, inst))
> Abort: decoding near '機能追?': 'utf8' codec can't decode bytes in position
> 9-10: unexpected end of data!
> 中止: decoding near '機能追?': 'utf8' codec can't decode bytes in position 9-10:
> unexpected end of data!
> tokutomi$
tracebackでの呼び出し履歴自体も問題なさそうなのですが、
最後のエラーが期待と違ってものすごく気になります。
Abort: decoding near '機能追?': 'utf8' codec can't decode bytes in
position 9-10: unexpected end of data!
上のエラーは最後の "加"(0xe5 0x8a 0xa0) の部分がUTF-8シーケンスとして3
バイト構成であるはずなのに2バイトしか得られないため起きています。ターミ
ナルへの漢字入力から内部のcommit()に至るまでのどこかで1バイト欠けてしまっ
てるということになります。理由は不明ですが、ターミナル周りで何かあるの
かも?(憶測)
で、さらにリクエストです。
できる範囲で構いませんので以下のことをしていただけますか。
1. ターミナル上で python を起動し import sys および
sys.stdin.readline() を実行し、"機能追加"の漢字4文字を(コピペではな
く)いつものように入力し、改行を入力すると正しく
'\xe6\xa9\x9f\xe8\x83\xbd\xe8\xbf\xbd\xe5\x8a\xa0\n' が得られますか?
2. hg に --debugger でデバッガ内で引数を表示するとどうかみてみて欲しい
です。Windows でやるとこんな感じになり、『機能追加』文字列のバイト並
びが見えますが、そちらの環境だと期待する12バイトのutf-8文字列になっ
てますかね。
$ hg commit --traceback -m '機能追加' --debugger
(Pdb) import sys
(Pdb) sys.argv
['c:\\mercurial\\hg.exe', 'ci', '-m', '\x91\xc5\x82\xc2', '--debugger']
(Pdb) len(sys.argv[3])
4
(Pdb) quit
この段階で正しいかどうかで python 内部か外部かを切り分けできると思う。
3. 最初のメールでのエラーの際に使用したコミットログのテキストのバイト列
が知りたいです。というのもエラーには '?機能追? のように "?" が3個ほ
ど見えていています。これはターミナル表示の際に utf-8 としてencode で
きないバイトを置き換えたものかと思いますので、奇妙なバイトが紛れ込ん
でる可能性があります。
できれば、hg ci の際に開いたテキストエディタで文面を入力した後そのま
ま保存して終るのではなくて、いつものようにファイルに保存後直ちに終了
せず、その内容を別ファイルにも保存してみてくれませんか? そしてその
コミットが失敗したならば、その別ファイルの内容(バイト列)が参考になり
ますので、そういうファイルが得られたならばzip してバイナリファイル添
付するか、od -x コマンドなどでHEXダンプしたテキストを見せて欲しい。
4. hg の extension の類を設定しているならば一旦全てなしにしてコミットを
試してみて欲しい。現在有効なextension は hg showconfig extensions
で得られます。
> そういえば、Snow Leopard (Mac OS X 10.6.1) を使用しており、
> Mercurial のインストールは MacPorts (パッケージマネジャー) を使いました。
> 上のログを見ると Python も MacPorts で入ったみたいですが、Python 自体
> は /usr/bin のモノ (Apple 版) が使われています。影響してるかどうかは分か
> りませんが…。
> ---
> $ which python
> /usr/bin/python
> $ python --version
> Python 2.6.1
> $ /opt/local/bin/python2.6 --version
> Python 2.6.2
5. まさかとはおもうけど python のバージョンの違いによる影響があるかも
知れないので hg ci と実行する変わりに
/opt/local/bin/python2.6 `which hg` ci として
コミットしてみると成功したり、ということはありませんかね。
--
Shun-ichi Goto
機能追加の前後にある???の意味がわかりました。
mercurial.encoding.fromlocal の中で、エラーメッセージをこのように出力しています。
try:
return s.decode(encoding, encodingmode).encode("utf-8")
except UnicodeDecodeError, inst:
sub = s[max(0, inst.start-10):inst.start+10]
raise error.Abort("decoding near '%s': %s!" % (sub, inst))
デコード時にエラーが起こった前後10バイトずつ切ってるんですね。
utf-8の境界を無視してぶった切ったバイト列がコンソールに表示されているので、
???と表示されても仕方ありません。
??のなぞが解けたんですが、エラーの意味がまだわかっていないので、
encoding.py に添付のパッチをあててバグを再現してもらえませんか?
fromlocal() の引数に渡る時点で欠けているもしくはゴミがついているのであれば、
このパッチで判断できると思います。
--
Naoki INADA <songof...@gmail.com>
ですね。ただ最初のメールのエラーでは、この "?" は前後のほかに
"加" の字ののころにもあります。これが hg ci -m "機能追加"での
1文字欠如と同じことが起きてるのだろうと思ってます。
'?機能追?
- CSS ?'
コミットログで"機能追加"の行と"- CSS..."の行の間に空行が
あったかどうかは分かりませんですが、あったとして、
"加" の3バイト目が欠けてLFが喰いこんで変換エラー(invalid data)と
なって、上のような表示に至ったのではないか、というシナリオを
思い浮かべてます。
そして hg ci -m "機能追加" のほうは喰いこむ後続バイトがないため
別のエラー(unexpected end of data)になる、と。
おそらくはfromlocal()の時点ではすでに欠けているので、
どこで欠けたがわからないと根治できませんねぇ。
--
Shun-ichi GOTO
なるほど
ただし、やはりHGENCODINGで直るというのがまだ意味がわからないので、
足場固めの意味で先ほどのパッチは当ててもらえればと。
後藤さんの意見を踏まえて、もう一つ仕込んでほしいのが、changelog.py の
changelog.add メソッドで、
user, desc = encoding.fromlocal(user), encoding.fromlocal(desc)
という行を見つけて、
+
+ import sys
+ print >>sys.stderr, "desc(A):", repr(desc)
+
+ # strip trailing whitespace and leading and trailing empty lines
+ desc = '\n'.join([l.rstrip() for l in desc.splitlines()]).strip('\n')
+
+ print >>sys.stderr, "desc(B):", repr(desc)
+
user, desc = encoding.fromlocal(user), encoding.fromlocal(desc)
のようにしていただけますか?
# バックアップ取らずに修正してしまってdiff取れない(汗
--
Naoki INADA <songof...@gmail.com>
あれ・・・出力が変わってないですね・・・
locate コマンド(ってMacにあるのかな?)等を使って、 mercurial/encoding.py という
ファイルがパッチを当てていただいたもの以外に存在しないか、もし存在しているので
あれば hg コマンドがそちらを実行していないか確認していただけますか?
--
Naoki INADA <songof...@gmail.com>
ないすふぉろーです
そのとおりです。うまく伝えられなかった。
とはいえ 引数 -m で python には正しく伝わっていることが確認できた
(外部からpythonへの引き渡し時点では化けて/欠けてない)以上、
それほど重要ではないですので、気が向いたらで結構です。
--
Shun-ichi GOTO
内部で文字列を弄っている部分を疑ったのですが、それに入る前にすでに最後の
1バイトが欠けていますね・・・
もっと手前の部分を調べるパッチを作りました。先のパッチに追加で添付のパッチを当てて、
HGENCODINGを設定するパターン、設定しないパターンで試してみて下さい。
お手数をおかけしますが、よろしくお願いします。
--
Naoki INADA <songof...@gmail.com>
> ちなみに、対応が入っていると思われる「最新の Python」って、
> どの版を指すんですかね? > パイソニスタの皆様
http://svn.python.org/view/python/trunk/Include/pyport.h?r1=36519&r2=36793&pathrev=36793
Wed Aug 4 06:33:51 2004 UTC
えーっと、少なくともPython2.4には入ってますね。
#ifdef __FreeBSD__
#include <osreldate.h>
#if __FreeBSD_version > 500039
となっているのですが、このマクロが Mac OS X では効かないんでしょうか。
--
Naoki INADA <songof...@gmail.com>
効いていなかったようです。
Pythonのissue trackerに登録しておいたので、 Python 2.6.4 が出るころには
Python側で対策されるかもしれません。
・・・というか、こんな古いバグ持ち出すなよ・・・ >apple
--
Naoki INADA <songof...@gmail.com>