python

2010年9月 2日 (木)

subversionのコミットログを検索して置換

subversionのコミットログにメーラのメッセージを
ちょっと加工してのせていたのですが、送信日時が
「xx年xx月xx日xx曜日 xx:xx…」となってました。
これの「xx曜日 」が前から気になっていて、
ついに削ることにしました。

それで以前作ったpythonのプログラムをモディファイし、
コミットログを取り出して文字列を見つけたら置換して書き込むのを
繰り返すものを作りました。

以下がそれです。無理やりなところや無意味な宣言もありますが。

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

import os
import time
import sys, string
from svn import core, fs, delta, repos
import codecs

#argvs[1]:repository path
argvs = sys.argv  #コマンドライン引数リスト
argc = len(argvs) #引数の個数
if (argc != 2):   #2でなければ出る
    exit(1)

path = argvs[1]
path = core.svn_path_canonicalize(path)
repos_ptr = repos.open(path)
fs_ptr = repos.fs(repos_ptr)

rev = fs.youngest_rev(fs_ptr)
start_rev = 1
end_rev = rev

for current_rev in range(start_rev,end_rev+1):
    #get comment log
    log = fs.revision_prop(fs_ptr, current_rev, core.SVN_PROP_REVISION_LOG) or ''
    if log.count('曜日 '):
        print "rev:%d log change" % current_rev
        log = log.replace('月曜日 ', '')
        log = log.replace('火曜日 ', '')
        log = log.replace('水曜日 ', '')
        log = log.replace('木曜日 ', '')
        log = log.replace('金曜日 ', '')
        log = log.replace('土曜日 ', '')
        log = log.replace('日曜日 ', '')
       
        #set comment log
        fs.change_rev_prop(fs_ptr, current_rev, core.SVN_PROP_REVISION_LOG ,log)

UTF-8で保存して、editlog.pyのように名前をつけたとすると

python editlog.py C:\TracLight\projects\svn\aaa

でaaaというリポジトリのコメント置換を行います。
(C:\TracLight\projects\svn\aaaがリポジトリのパス)

| | コメント (0) | トラックバック (0)

2009年10月21日 (水)

pySerial/pyWin32でシリアル通信、でも受信が…

TracLightningに入っているpython(2.5)を使ってシリアル通信のプログラムを
試してみました。
その際、pySerial(pyserial-2.5-rc1.win32.exe)やpyWin32(pywin32-214.win32-py2.5.exe)を
インストールして使いました。
以下がそのプログラム。

# -*- coding: shift_jis -*-

from serial import Serial
from struct import unpack,pack
import time
from array import array

cmd1 = pack('8B',0x08,0x11,0x01,0x00,0x00,0x00,0x02,0xE4)
cmd2 = pack('8B',0x08,0x11,0x01,0x00,0x00,0x00,0x1B,0xCB)
cmd_done = pack('4B',0x04,0x12,0x02,0xE8)

b_array = array('B')

"""
送信のフォーマット
1.コマンド
    (パケット最後までの個数) 0x04または0x08 data0 … checksum
    2番目のデータが0x08なら設定値書き換えコマンド、
    0x04なら設定値にあわせた設定を実行するコマンド

受信のフォーマット
1.メッセージ
    (パケット最後までの個数) 0x0d data0 … checksum
    最小パケットは(n,0x0d,0x00,checksum)で4byte
2.コマンドに対するack
    0x03 0x0c 0xf1
"""
def checksum(num):
    global b_array
    csum = 0
    for i in range(num):
        csum += b_array[i]
    csum = csum % 256
    if csum==0:
        return True
    else:
        return False

def mParser():
    global b_array
    #len(b_array)>=numが前提
    num=b_array[0]
    if num > 4 and b_array[1]==0x0d and b_array[2]!=0 and checksum(num)==True: #メッセージの時だけ取り出し
        print b_array[:num]
    elif num == 4 and b_array[1]==0x0d and b_array[2]==0 and b_array[3]==0xef: #
        #なにもしない
        num =num #dummy
    elif b_array[0]==3 and b_array[1]==0x0c and b_array[2]==0xf1:#ack
        num = num #dummy
        #とりあえず何もやらない
    else:
        if num == 0 or checksum(num)==False:
            #print b_array
            #ここにくるものはほとんどごみ(なぜごみが出るか不明)…
            b_array=b_array[1:] #1個削る
            return
    b_array=b_array[num:] #1パケット分を削る

def bParser():
    global b_array
    while True:
        if len(b_array):
            num = b_array[0]
            if num == 0:
                num = 1
            if len(b_array)>=num:
                num = b_array[0]
                mParser()
            else:
                break
        else:
            break

com = Serial(
  port=0,
  baudrate=115200,
  bytesize=8,
  parity='N',
  stopbits=1,
  timeout=0, #0ならread()はすぐ読み出し
  xonxoff=0,
  rtscts=0,
  writeTimeout=None,
  dsrdtr=None)

com.flushInput()
com.flushOutput()

print com.portstr

interval = 8 #[sec]
v=0
b_array = array('B') #arrayとして初期化

print 'start'
nexttime = time.time()
while True:
    if time.time() >= nexttime:
        nexttime = nexttime + interval
        #送信
        if v==0:
          #print 'CMD1' % n
          com.write(cmd1)
          v = 1
        else:
          #print 'CMD2' % n
          com.write(cmd2)
          v = 0
        time.sleep(0.05)
        com.write(cmd_done) #実際に実行させる
    else:
        #受信
        dlen = com.inWaiting() #受信バッファにたまってる数を確認
        if dlen > 0:
            d = com.read(dlen)
            b_array.extend(array('B',d)) #b_arrayの後ろから追加
            bParser()
        else:
            b_array = array('B') #arrayをクリア#いるかな?これがないとしてもごみでるけど
        time.sleep(0.05)
com.close() #結局ctrl+Cとかで止めるから意味がなくなってる

しかし、送信はいいのですが、受信に変なデータ(ごみ)が入ってきます。
必ずというわけでもないのですが。
とりあえず長さとチェックサムをチェックすることで
いまのところ何とかなってる(と思う)のですが、すっきりしません。
これがなければ、ackを確認してから次のコマンドが出るようにしたいのですけど。
コンソールだけでなく、修正してtkinterを使ったものにしてもごみが出てしまいます。

---
TracLightningのpythonでは
win用python関連(pySerialやpyWin32)のインストーラがpythonの場所を見つけられなくてインストールできないのを
TracLightningでpsycoを使うでの、1,2の内容、もしくは手作業でレジストリ書き替えが必要だと思います(私は以前やっていたので)。

| | コメント (0) | トラックバック (0)

2009年4月 2日 (木)

pythonでUTF8→S-JIS変換?結局UTF8のまま。

HyperEstraierのindex(その3)でチェンジセットのログをファイルにするpythonスクリプトを
作ったのですが、途中でこけることがありました。
調べたら、Subversionのログ(UTF8)をS-JISに変換している部分で
ERRORになってました。つまり、

log=unicode(log,'utf-8').encode('Shift_JIS')

のようにしてました。しかしUnicodeEncodeErrorと。なんだかS-JISにない文字に
変換しようとしてるとか言ってるみたいです。例えば、「繋」ぎ込みが該当。本当は、

UTF8→S-JIS

としたいけど、pythonでは、

UTF8→unicode→S-JIS

のようにするしかない(のかな)。ファイルはS-JISにしないといけないと思うんだけど。
unicodeをはさむからだめなんでしょうか。S-JISには絶対あるはずの文字なんですけど。
S-JISをcp932に変えてみましたがだめ。
調べてみたら、

    log=unicode(log,'utf-8')
    s = ""
    for c in log:
        try:
            c.encode("cp932")
        except UnicodeEncodeError:
            s += "?"
        else:
            s += c
    log=s

のようにしたらerrorがでないとのこと。つまり、1文字ずつ変換するということ。
試すとerrorはでないけど、変換できないところは「?」に置き換わる。

さらに調べるとmbcs(Multiple Byte Character Set、
1文字が複数バイトで表現される文字とのこと)についての記述を見つけました。でも、

log=unicode(log,'utf-8').encode("mbcs")

ではやっぱりERROR。ためしに、

    log=unicode(log,'utf-8')
    s = ""
    for c in log:
        try:
            c.encode("mbcs")
        except UnicodeEncodeError:
            s += "?"
        else:
            s += c
    log=s

しかしこの方法ならちゃんと変換できました…?

秀丸エディタで開いてみると…、「UTF-8」じゃん。

でもestcmd gatherしてtracから検索してみると…、検索できます!
xdoc2txtあたりでS-JISにしてるのかな?
というわけで、何もせず、UTF8のまま使うことに。
SearchHyperEstraierに機能追加してみました。を修正しました。

| | コメント (2) | トラックバック (0)

2009年2月19日 (木)

SQLite DBの変更作業をしてみました

大して何も考えずに作ったpatch(マルチリポジトリの件)のわりに
普通に動いてる(と思う)ので本格的に移行。

1.trac.iniの修正
2.dbの修正

のような感じでできるかなと思いましたが、
dbの修正を行うのにSQLite Database browserだけで作業すると
ちょっと大変なので、
テーブルをexport、テキストエディタで置換作業、
テーブルにimportのような作業にならないか
試行錯誤。

guiでSQLiteのdbを操作できるものの中で
export/importで文字コードの指定ができ、操作性もよいもの
ということでtksqliteを探し出す。
http://reddog.s35.xrea.com/wiki/TkSQLite.html#download
ちゃんと日本語のguiです。

これで、tksqliteで編集したいテーブルを「列名を出力」にして
text(csv)に出力(UTF-8))し、編集、
tksqliteで「1行目を列として扱う」にしてtext(csv)(UTF-8))でとりこみ。
(DBは必ずバックアップを取ってから編集。)

取り込みの際は、
編集したいテーブルを表示、全て選んで削除にし、
そこに読み込む。
(スキームの定義などやるのは大変だからこれが一番楽。
これが簡単にやれるのはtksqliteくらいじゃないかと。)

あとはtext化したものをUTF-8でどう編集するか。
私の場合、作業のひとつに

//trac/aaa/changeset/xxx
    ↓
changeset:xxx/aaa

のような置換(xxxは数字の文字列)が100個以上必要でした。

テキストエディタや他のテキスト変換フリーウェアを探し、
もともとそういう操作ができないか
試すと結果に誤りが出ることがあるなどでどれも使えず。

結局pythonでやってみることに。

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

import sys, string
import re

argvs = sys.argv  #コマンドライン引数リスト
argc = len(argvs) #引数の個数

if (argc != 3):   #3でなければ出る
    quit()
fin = open(argvs[1], "r")
fout = open(argvs[2], "w")

s="//trac/aaa/changeset/"
s0="changeset:"
s1="/aaa"
for x in fin.readlines():
    n=x.find(s) #-1ならなし
    if n!=-1:
        #sがあれば次は必ず数字が来ると想定
        #数字がどこまであるか検索する
        start = (n+len(s))
        for m in range(1,len(x)-len(s)):
            if not x[start:(start+m)].isdigit():
                break
        s2 = x[start:(start+m-1)] #s2は数字の文字列
        x = re.sub(s+s2,s0+s2+s1 , x) #置換
    fout.write(x)
fin.close()
fout.close()

これをrepl.pyという名前とすると、

python repl.py wiki.csv wiki_out.csv

でとりあえずできました。

残りの編集はテキストエディタで行い、tksqliteを使ってimport。
やっと文字化けなしで変更作業を終えました。

| | コメント (0) | トラックバック (0)

2008年9月10日 (水)

TracLightningでpsycoを使う

win版pythonをインストーラで入れた場合はwin版psycoのインストーラで
簡単にインストールできるけど、traclightningにはいってるpythonだと
psycoのインストーラがpythonの場所を見つけられなくてインストールできません。

こうやればできた(と思う)のでとりあえずメモ。

1.以下のような内容のファイルを作成する。(ここではInstallPath.regとする。)

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Python\PythonCore\2.5\InstallPath]
@="C:\\TracLight\\python\\"

[HKEY_CURRENT_USER\Software\Python\PythonCore\2.5\InstallPath\InstallGroup]
@="Python 2.5"

2.InstallPath.regをクリックしてpythonインストール先をレジストリに入れる。

3.psycoのwindows版をダウンロード、インストール。

4.「C:\TracLight\python-lib\trac\trac\web\modpython_frontend.py」に

import psyco
psyco.profile()

を追加する(ファイルの先頭にあたりでよいとのことだった)。

5.「C:\TracLight\python-lib\trac」で

python setup.py install

を実行する。

6.あとは通常通りサービスのインストールをして開始する。

実際のインストール先に合わせて試してください。
1,2は手作業でレジストリに書き込んでもいいです。

| | コメント (0) | トラックバック (0)