IronPython」タグアーカイブ

.NET Framework required BOM

デフォルトの search.ini や lng 読み込みで文字化けする理由が判明。
BOM が付いていない UTF-8 文書は UTF-16 文字列に変換読み込みしてくれないということ…

何を今更 BOM での判別といい UNICODE と cp932 の混在といい…
もうイヤだこの変態 OS は、全てが UTF-8 である最近の Linux を見習ってくれ!

Python 組み込みの open() では読み込んだ後に変換しかできないわけだから、方法ある?
System.IO.StreamReader と System.Text.Encoding.UTF8 を普通に使うのが一番だよな。
StreamReader オブジェクトは for ループに…やっぱり無理か。

import os

# 略

class Inifile(InifileBase):
    def __init__(self, filename):
        InifileBase.__init__(self, filename)
        self.header = ""
        self.ini = []
        if os.path.exists(filename):
            f = open(filename)
            x = f.read()
            f.close()
            lines = x.split("\n")
            section = ""
            for line in lines:
                if line == "":
                    continue
                if len(line) > 2 and line[0] =="[" and line[-1] == "]":
                    section = line[1:-1]
                elif section == "":
                    pass # 何もしない
                elif "=" in line:
                    pos = line.index("=")
                    self._add(section, line[:pos], line[pos+1:])

from System.IO import *
from System.Text import *

# 略

class Inifile(InifileBase):
    def __init__(self, filename):
        # ベースクラスでアトリビュートを利用する場合は IronPython でも必要
        InifileBase.__init__(self, filename)
        self.header = ""
        self.ini = []
        #if os.path.exists(filename):
        if File.Exists(self.filename):
            f = StreamReader(self.filename, Encoding.UTF8)
            try:
                section = ""
                while 1:
                    line = f.ReadLine()
                    if line == None:
                        break
                    if line == "":
                        continue
                    if len(line) > 2 and line[0] =="[" and line[-1] == "]":
                        section = line[1:-1]
                    elif section == "":
                        pass # 何もしない
                    elif "=" in line:
                        pos = line.index("=")
                        self._add(section, line[:pos], line[pos+1:])
            finally:
                f.Close()

utf8read

大体同じに仕上げたけど Linux 版とコード共有はもうあきらめるしかない。
組み込みの open とは違い StreamReader は Close 必須なので忘れないでね。
しかし私は無限ループを作って null で抜けるコードばかりだ、一番単純に書けるのよね。
if not line: だと空文字も拾ってしまうのは Python という言語の常識かな。

ついでに継承ベースクラスの __init__() が不要の IronPython も必要な場合があると解った。
ここではベースクラスで self.filename を定義しているだけなんだが、そういう場合に。
だから無意味に呼び出しても結果が同じなのか、ふむふむ。

これならコンストラクタ化されているというのに自由に __init__() を定義できる。
C++ の継承で頭を抱えた経験がある人にしか解らないだろうけど嬉しい仕様だ。

seeme_a405.zip

次はメニューの文字化けか、一部だけ化けるというのが理解に苦しむ。

こんなノロノロ作っている間に Opera 10 が RC になっているわ。
SeeMe for Windows v4 はもうしばらく C# つまり exe 形式のままね。
そのほうがいいという人のほうが多いと知っているけどシラネ!

GtkNoteBook and TabControl

SeeMe for Linux では GtkNoteBook の各ページは Python の List でアクセス。

note = gtk.Notebook()
page = []
for i in range(4):
    tab = gtk.Label(tab_label[i])
    page.append(gtk.VBox())
    self.note.append_page(page[i], tab)
page[0].pack_start(self.sw1)
page[1].pack_start(self.sw2)

という方法を見つけたけど IronPython でも同じようにできるのかな?
.NET Framework では TabControl と TabItem なんていうものを使う。
まあこんなのは実際にやってみるのが早い。

note = TabControl()
self.page = []
for i in range(3):
    page = TabItem()
    page.Header = tab_label[i]
    note.AddChild(page)
    self.page.append(page)
self.page[0].Content = self.custome_listview
self.page[1].Content = self.default_listview

tab1

おぉ同じように使えるじゃないの!
XAML で作っているとこんな添え字でのアクセスは考え付きもしないだろう。
リストの添え字アクセスにメリットを感じるかどうかで人それぞれだと思うけど。

だけど…

tab2

又しても文字化けだよ。
lng ファイルは for Linux で使っている InifileReader クラスで読んでいるののだが…
もしかして一度全部読み込まないと UTF-8 を UTF-16 に自動変換できないのかな?
メニューの文字化けも解決していないしまいった、以下今日のバックアップ。

seeme_a404.zip

GetFullPath

ぱぇぽぃ2 ? Blog Archive ? Opera WMV

の最後でカレントディレクトリからでは端末で絶対パス名を取れない場合があると書いた。
待てよ? os.path が無い IronPython ではどうやるのだろう?

Path メンバ (System.IO)

System.IO.Path で普通に GetFullPath メソッドがあった。
そういえば IronPython では __file__ は使えるのだろうか?
ということで試してみる。

#-*- coding:utf-8 -*-

import sys
import System

print sys.argv[0]
print __file__
print System.IO.Path.GetFullPath(__file__)

abspath

あぁやはりカレントディレクトリではこうなるのか。
見落とししやすい所なので注意したほうがいいね、cmd.exe から起動しない!と言わない。

それと。

ShowDialog() メソッドで開いた Window で Value を参照しようとすると例外になる。
調べると ShowDialog() の戻り値自体が Boolean になっている、C# と違うじゃん。
何故?よく解らないけどコンパイルしないとこういう結果になるのかな。

それと。

バックアップを試せば解るけど Welcome クラスは Application インスタンスを作成していない。
それなのに Window が普通に動くんだが、メッセージループはどうなっているの?
試しに Show() メソッドで表示してみたら即終了、なるほどそういうことなのか。
Window は ShowDialog() メソッドを使うなら Application インスタンスから動かす必要は無いのね。
何のことか解らない人は Windows アプリは何故動くのかを勉強しておこう、→の本で。

ついでに Welcome のインスタンスを作ったらその中で sys.exit() できなかった。
その前に Close() しなきゃいけないのか、ふむふむ。

それと。

GtkEntry は Nautilus からファイルをドロップするとファイルのフルパスが流し込まれる。
Linux 版と動作を合わせたいので「ようこそ」のフルパス入力部で同じようにしたい。
つか「ファイルの参照ダイアログ」は使いたくないだけだが、多分使う人はいないと思うし。
「minipoli を使え」にしてもイイけどそれはやはりあんまりかと。

[WPF]ドラッグアンドドロップ

検索したら簡単に方法が見つかった、IronPython 言語への書き換えも普通どおり。
あぁ Windows の開発は楽チンだなぁ…日本語でアッサリ見つかるんだもの。
PyGtk になると日本語では実用的コードなんかまったく見つからないからね。

今日は結構勉強になった。
Ubuntu 上の VirtualBox で動かしている Windows 7 RC でやったほうが開発が楽しいなんて…
困ったら即 Ubuntu に戻れるからだろうけどさ、ということで今日のバックアップ。

welcomedlg

seeme_a403.zip

とりあえず「ようこそ」だけ移植完了、先はまだ長い。

SeeMe is to IronPython

C# で SeeMe for Windows を作るのはヤメにしたい。
Python ばかりやっているとやはり巷の噂どおり行末セミコロンを忘れるんだなぁこれが。
既定の型がバカみたく多い .NET Framework で型指定なんてもうやってられない。
何よりコンパイルしなきゃいけない、今では何故コンパイルする必要があるのかも疑問。

それより Visual Studio に嫌気が。
一昨日 Visual Studio の自動アップデートが掛かって一時間以上マシンが使えなかった。
サイズがデカ過ぎるんだよ!だから仮想の OS には入れたくないし又待たされるのはゴメンだ。
結果 Ubuntu と Vista の HDD を入れ替える回数が多くなる、いいかげんにコネクタが不安。
Ubuntu 上の仮想な Windows 7 上で気楽にサクッと小物アプリを作れるのが理想…
そうなるとやはり IronPython が一番の選択肢になる。

ところで IronPython で検索するとコンパイル方法とかよく見つかるんだが…
動的言語を何故コンパイルなんてしたい人がいるのか私にはまったく理解できない…
メリットをわざわざ自分で潰すなんて、コンパイルするなら C# で作ればいいんだし…
それよりなにより Windows 7 では exe にするとインストーラが必要に…
更にオープンソースにするもなにも配布は一つのアーカイブのみでオケになるのに…
Linux の /usr/bin 以下を見てそれでもコンパイルしたいのか?という感じ。

ということで SeeMe はとっとと IronPython で作り替える。

面倒くさいので XAML は C# のをそのまま使…えなかった、ハンドラ指定の部分で。
それと Python らしく Name 属性に大文字を入れたくないし Linux 版との整合性も整えたい。
エディタ部の腐った配置も書き換えたい、使う人には解らないだろうけど我ながらコードが酷い。
System.Windows.Window の継承クラスをトップレベルウインドウにしたいというのもあるけど。
のでやはり書き換えることに。

細かいパーツは XAML を三重クォートでまとめたのをいくつかコピペですませる。
XAML でやったほうが良いものは XAML で、コードのほうが都合がよいものはコードで。
inifile8.py は os モジュールが無いから Linux 版をそのままは使えなかった。
とりあえずツールバーまでは再現した。
とやっていたのでありますが。

seeme_ipy2

何故文字化けするの?
どうでもいいが IronPython は pyc キャッシュを作成しないことに今頃気がついた、遅!

原因が解らないけど、とりあえずココまでのバックアップ。
明日明後日はとある事情で田舎に帰りますのでまた来週。

seeme_a402.zip

MIME Type is disjoint

そういえば Windows の MIME Type はどうなっているのだろう?

MIMEタイプの取得・判定 – Programming/Tips – 総武ソフトウェア推進所

ふむふむ、そうやるのか。
Windows の場合は拡張子が全てなので Python の mimetypes モジュールでよさげだが。
せっかくなので試してみよう。

# -*- coding: UTF-8 -*-

import clr

clr.AddReferenceByPartialName("PresentationCore")
clr.AddReferenceByPartialName("PresentationFramework")
clr.AddReferenceByPartialName("WindowsBase")

from System import *
from System.IO import *
from System.Windows import *
from System.Windows.Controls import *
from Microsoft.Win32 import *

class MimeTypeWindow(Window):
    """
        Get MIME Type for Windows
    """
    def __init__(self):
        self.Width = 320
        self.Height = 240
        self.Title = "MimeTypeWindow"
        self.AllowDrop = True
        self.Drop += self.on_drop
        self.textblock = TextBlock()
        self.textblock.Text = "Drop"
        self.Content = self.textblock

    def on_drop(self, sender, e):
        files = e.Data.GetData(DataFormats.FileDrop)
        ext = Path.GetExtension(str(files[0]))
        if ext:
            key = Registry.ClassesRoot.OpenSubKey(ext)
            if key:
                s = key.GetValue("Content Type")
                if s:
                    self.textblock.Text = s
                else:
                    self.textblock.Text = "No MimeType"
            else:
                self.textblock.Text = "No Registry Key"
        else:
            self.textblock.Text = "No Extension Value"

if __name__ == "__main__":
    a = Application()
    a.Run(MimeTypeWindow())

今頃知ったけど .NET Framework の null は None でイイんだね。
これと Python の mimetypes モジュールとでどうなるか試す。
ぱぇぽぃ2 ? Blog Archive ? Get MIME Type and Description
で GNOME と違うのかもついでに、zip アーカイブを試す。

mime_all

あら…
ついでに Opera は Linux 版なのに

opera_mime

なんというか、やっぱりアプリケーションによってバラバラだよ。