mamefugouメモボード

ついにfixutf8のTest()が動いた!だけど…

osutilインポートエラーの修正

osutilのインポートエラーが出ているので、まずはどのモジュールをインポートしようとしているのか突き止めようと思います。
from mercurial import osutil なので、mercurialの下にいるはず。
ignoreの時と同じようにC:\Python27\Lib\site-packages\mercurialの中を探してみたところ、C:\Python27\Lib\site-packages\mercurial\cextの下にosutil.pyが存在していました。
from mercurial import util, osutil, dispatch, extensions, i18n
mercurialではなくmercurial.cextからimportするように変更します。
from mercurial import util, dispatch, extensions, i18n
from mercurial.cext import osutil
この状態で実行してみたところ、インポートエラーが発生しなくなりましたが、別の個所でエラーになります。

win32helper.pyでmapcpがNoneでエラーになる

エラーが発生しているのは、fixutf8.pyではなく同じフォルダ内にあるwin32helper.pyのようです。
fixutf8.pyのtest()関数で呼び出しているwin32helper.rawprint()関数の内部で起きています。
u = s.decode('utf-8')
try:
    if oldcp != 65001:
        s = u.encode('cp%d' % oldcp)
except UnicodeError:
    if usecpmap:
        cpname, newcp = mapcp(u)
mapcp(u)で発生していて、uはtry節の直前で定義されていて、ブレイクポイントで中身を確認しても文字列が入っており、Noneではないので、mapcpがNoneということになります。
mapcpで検索をしてみたところ、先頭でmapcp = Noneと定義されていました。
さらに別の関数の内部で
def uisetup(ui):
    global usecpmap, mapcp
    usecpmap = ui.config('fixutf8', 'usecpmap', usecpmap)
    if usecpmap:
        import cpmap
        mapcp = cpmap.reduce
global変数としてmapcpにcpmap.reduceというものが代入されていました。
cpmap.reduceは同フォルダの別ファイルcpmap.pyの最後に定義されている関数でした。
def reduce(s):
    l = list(cps)
    for c in s:
        l = [cp for cp in charmap[ord(c)] if cp in l]
    return (l[0], cpmap[l[0]])
どうやらmapcp変数は関数ポインタとして利用されているようです。
ここでwin32helper.pyに戻って処理を良く見ると、関数ポインタがセットされるuisetup()関数は直接スクリプトを起動したときにどこからも呼ばれないことが分かります。
そこでrawprint()関数の内部で、Noneだったら関数ポインタを設定するように変更します。
if usecpmap:
    global mapcp
    if mapcp is None:
        import cpmap
        mapcp = cpmap.reduce
    cpname, newcp = mapcp(u)
この状態で実行したところ無事エラーが出なくなりました。

ついにfixutf8.pyのTest()実行  しかし

fixutf8Test()実行結果
実行結果はこのようになりました。
this is a test と表示されました。
さっそく日本語ファイルがコミットできるか試してみます。

日本語ファイルは文字化けしたままでした。
テストが通ったから大丈夫だと思ったのですが、甘かったようです。
何やら警告のようなものが文字化けた状態で出ています。
fixutf8.pyを有効にしたままコミットしようとしたところ、別のエラーが発生しています。
File "mercurial\vfs.pyo", line 403, in __call__
TypeError: __init__() got an unexpected keyword argument 'checkambig'
存在しないcheckambig引数を渡してるようです。
エラーが出てるのがmercurial側のソースのようです。
次はこのエラーを調べてみることにします。

いよいよfixutf8.pyの修正作業開始

いよいよfixutf8.pyの修正作業を開始していきたいと思います。

一応の確認として、fixutf8.pyはGNU General Public Licenseのようなので、いじくりまわしてOKのようです。個人であれこれしてる分にはバレないかと思いますが、ブログに載せるので一応確認しておきました。(ソースコードの先頭のコメントに書いてありました)


fixutf8.pyの全体構成

まずfixutf8.py全体がどういう構造になっているか把握しておきたいと思います。
  • import関連
  • def test():
  • def mapconvert(convert, canconvert, doc):
  • def utf8wrapper(orig, *args, **kargs):
  • def uisetup(ui):
  • def extsetup():
  • スクリプト処理
だいたいこういう構成になっているようです。
関数の中を軽く見てみましたが、いつ呼ばれるかはこのpythonだけだと分からないですね。
extensions.wrapfunction()やwin32helperの処理を実行しているようなので、TortoiseHGやWindowsからのコールバックなりで、関数が呼ばれる仕組みなのでしょう。多分。

ここで気になるのは、スクリプト処理の部分。
if __name__ == "__main__":
    test()
インデントが先頭から始まっているので、ここは普通に実行される部分のようです。
参考サイト様:
このif文のおかげで、importしてきた時に、test()が実行されないようです。
逆の言い方をすれば、fixutf8.pyを直接実行した場合はtest()関数が実行されるので、単体でテストができるということのようです。
まずはこのテスト関数が問題なく動くようにしていこうと思います。

demandimport.ignoreが見つからないエラー

実行をすると、まず最初のimportの部分で
'module' object has no attribute 'ignore'
というエラーが発生します。
from mercurial import demandimport
demandimport.ignore.extend(["win32helper", "osutil"])
このignoreが見つからないようです。
修正するためにdemandimportについて調べます。

demandimportとは?

参考サイト様:
どうやらモジュールが実際に実行されるときにimportされるように遅延する処理のようです。
ignoreに無視するモジュールを指定できるということなのですが、ignoreが見つからないと出ているのでソースを見てみようと思います。
from mercurialとなっていたので、mercurialパッケージの中に存在するのではないかとローカルにインストールしたmercurialの中身(C:\Python27\Lib\site-packages\mercurial)を探してみましたが見つかりませんでした。
そこで、demandimportでGrep検索をかけてみたところ、C:\Python27\Lib\site-packages\mercurial\__init__.pyが引っかかりました。
import hgdemandimport
demandimport = hgdemandimport
と記述されており、どうやらdemandimportは正しくはhgdemandimportが正式名称だったようです。
そこで今度はhgdemandimportを探したところ、C:\Python27\Lib\site-packages\hgdemandimportが見つかりました。
早速hgdemandimportの__init__.pyの中身を確認します。
IGNORES = {
    '__future__',
    '_hashlib',
無視するモジュールを格納している集合型が定義されていました。
どうやらmercurial用に更新されていくうちに、変数名が変わったようです。
本家demandimportのgithub
を確認すると、本家のdemandimportの方では、_ignoreという変数に無視モジュールを追加していました。

ignore見つからないエラーの修正

原因が分かったので修正してみようと思います。
IGNORE変数はset型のようです。
参考サイト様
修正前
from mercurial import demandimport
demandimport.ignore.extend(["win32helper", "osutil"])
修正後
from mercurial import demandimport
demandimport.IGNORES.add("win32helper")
demandimport.IGNORES.add("osutil")
これでエラーが発生しなくなりました。
demandimport.IGNORES = demandimport.IGNORES | {"win32helper", "osutil"}
という書き方もできますが、見た時の分かりやすさを重視してadd()で追加するようにしました。

次はcannot import name osutilというエラーが出ています。
osutilがimportできないようです。
test()を実行するまでが長そうな気がしてきましたね…。

VisualStudioでpythonを実行する

VisualStudioのソリューションを用意する

VisualStudio2019で新しいプロジェクトを作成して、Pythonのソリューションを用意します。
Pythonアプリケーション>既存のPythonコードから作成します。
プロジェクト名は、前回クローンしたMameFixUtf8を指定、作成するPATHはD:\project\MameFixUtf8を指定。
ソリューションとプロジェクトを同じディレクトリに作成にチェックも入れておきましょう。

ソリューションを作成すると、既存のコードを指定するウィザードウィンドウが表示されるので、D:\project\MameFixUtf8を指定し次へを押します。
使用するPythonのバージョンをプルダウンメニューから選びます。Python2.7を指定。
スタートアップのコードを指定します。fixutf8.pyを指定しておきます。
※ここで指定したはずなのになぜかbuildcpmap.pyがスタートアップに指定されていたので、手動でfixutf8.pyを右クリックして、スタートアップファイルに指定しなおしました。

普通に実行してみたところ、エラーが発生しました。

mercurialをインストールする

from mercurial import demandimport
mercurialが見つからないという内容のようです。
mercurialをインストールしていないので、当然怒られます。

余談ですが、TortoiseHGに含まれているmercurialからimportすれば、良いのではないか?
と思いましたが、ダメでした。
C:\Program Files\TortoiseHg\lib\mercurial.cext.base85.pyd
というそれっぽいものがありましたが、VisualStudioの検索パスに含めましたが、mercurialモジュールとしては使えない模様。
諦めて、普通にPythonにmercurialをインストールすることにしました。

手動でインストールしたPython2.7にのみインストールしたいと思います。
pipと呼ばれるインストールの補助ツールを使用します。
基本的には既にインストールされているはずです。
py -2 -m pip install mercurial
これでPython2.7にmercurialがインストールされます。
コマンド的には以下のようになります。
pythonにercurialインストール
打ち間違いも含まれていますが、ご愛敬ということで目を瞑ってください。
pipがインストール済みか確認も兼ねてバージョンを確かめたあと、mercurialのインストールをしています。
その際にpipのバージョンが古いようだったので、pipのアップグレードもしています。

再度VisualStduioで実行してみる

mercurialのインストールが終わったようなので、再度VisualStudioで実行してみます。
VisualStudioのソリューションエクスプローラー、Python環境にmercurialが追加されていました。
mercurialが追加されている
この状態で実行してみたところ、'module' object has no attribute 'ignore'というエラーが出ました。
TortoiseHGで出力されていたエラーと同じものなので、同じ状態になったと言えそうです。
今後はVisualStudio上でエラーが起きないように修正をしていきたいと思います。

自己流fixutf8.pyのリポジトリを用意

Pythonのインストール

すでに自分の環境にはPythonがインストール済みなので、インストールは割愛。
参考サイト様:
このあたりを参考にインストールをすると良いかもしれません。

なぜPython3系と2系を共存させているかというと、TortoiseHGはPython2.7で動作しているからです。TortoiseHGのヘルプから確認したところ「Mercurial-5.0.2, Python-2.7.13」とのことでした。
ところがPython2系は、2020年でのサービスの終了が予定されています。
公式のお知らせ:
その為、将来的にはTortoiseHGもPython3系に対応することになるのではないかと思います。
Mercurialの方はすでにPython3系に対応しているようなので、そろそろPython3系TortoiseHGも来るのではないかと思います。多分。

リポジトリの用意

https://bitbucket.org/tinyfish/hg-fixutf8/src/default/
からfixutf8のリポジトリをクローンしてきます。次にそのままこのリポジトリを元に、プロジェクトのリポジトリを作りたいと思います。
クローンする時に、クローン先のフォルダ名を好きなプロジェクト名に変更しましょう。
MameFixUtf8とでもしておきます。
次にTortoiseHGの同期タブを開いて、エイリアスとPATHをローカルのプロジェクトPATHに変更します。これで元のURLにコミットしたりせずに済むはずです。
mamefixutf8_alias.jpg

上記画像で「work」という新しいブランチが作成されていますが、ブランチの作成だけをコミットしました。この状態でプッシュを行いましたが、同期でプッシュ先をローカルのPATHにしているので、ソースのURLのリポジトリにはプッシュされていませんでした。
今後はこのまま修正内容をプッシュしていこうかと思います。

これで、作業を開始する土台ができたと言いたいですが、何を使って開発をしていくかという問題が残っています。
テキストエディタでコーディングしても良いのですが、VisualStudioでPythonのコーディングと実行ができるので、VisualStudioでコーディングをしていこうかなと思います。

バージョン管理どれにしよう

自宅でプログラムを打つ時に、今まではフォルダ名+日時など付けて管理していた。
仕事でバージョン管理をしていると、ソースの一部を元に戻したり、文字置換ミスって戻す時に楽で、自宅でも使いたいと思うようになったので、導入しようと思った。

mercurialとgitのどちらにしようか悩んだ。
会社でmercurialを使用していて使い慣れているが、
gitの方が人気のイメージがあったので、gitに挑戦するのもありかもしれない。
色々と調べたが、やりたいことはバージョン管理ソフトの比較やレビューではなく、プログラムを使ってゲームやらソフトを作ることなので、ツール選びに時間をかけすぎてもしょうがないので、使い慣れてるmercurialを使うことにした。

TortoiseHG

https://tortoisehg.bitbucket.io/ja/

会社と同じくMercurialのGUIクライアントのTortoiseHGを使う。

ただそのまま使うには問題があり、その対応をどうするか…。


日本語ファイルがそのままだとバージョン管理できない。


LinuxやOsXはUnicodeでファイル名を管理していて、WindowsはShift-JISで管理している。mercurialはShift-JISファイル名に対応していない。というのが原因のようです。
参考サイト様


Windowsだけで使用する場合は、win32mbcs拡張機能を有効するだけで問題無いようです。

会社ではMacなどからもTortoiseHGを使用するので、fixutf8.pyを使用しているのですが、上記サイト様でもあるように、すでにメンテが止まってしまっています。


そこで対策として以下の事をやってみました。
・Windows SubSystem for Linuxを使って、Linuxから管理をする。
・Python勉強ついでにfixutf8.pyを最新のTortoiseHGで動くように修正してみる。


・Windows SubSystem for Linuxを使って、Linuxから管理をする。
参考サイト様
参考サイト様を見ながら、WSLをインストールしようとしたのですが、アプリと機能からWSLを有効化して、インストールして再起動しても、UbuntuもDebianもWSLが有効化されていない。とエラーになってしまいました。
再起動をしてもチェックは入ったままなのですが、Windows側の不具合なので、インストールしなおしが必要な模様。正直面倒なので、この方法諦め。

・Python勉強ついでにfixutf8.pyを最新のTortoiseHGで動くように修正してみる。
こっちの方針でやってみることにしてみる。
ひとまず現状出てるのは、ignoreが見つからないというエラーのようなので、これを直してみよう。
プロフィール

mamefugou

Author:mamefugou
ゲーム業界でプログラマしてます。
クライアントとサーバーやったり。
UI画像作成と組み込みやったり。
(クオリティは…まぁ)
あっちこっち中途半端に担当。

古臭い書き方するプログラマ。
イベント駆動型あんまり好きじゃない。

主にC++とpythonがメイン。

最新記事
月別アーカイブ
カテゴリ
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QR