Fork me on GitHub

2009/06/12

はてな
追記
パッチがいるのを忘れていました。
一番下にあります。

バッチファイル。実行すると直接バイナリ配置するので気をつけて。バッチの先頭にあるパスを環境に合わせ修正して下さい。
pythonのソースはオフィシャルから「Python-2.6.2.tar.bz2」を、pdcursesもオフィシャルから「pdcurs34.zip」をダウンロードし"C:¥TEMP¥"に展開しておきます。
@echo off
setlocal

set PYTHON26=c:\Python26

set PYSOURCE=c:\temp\Python-2.6.2
set PDSOURCE=c:\temp\pdcurses

if "%1" == "msvc" goto msvc
if "%1" == "gcc" goto gcc
goto usage

:msvc
set FLAGS=/nologo /LD -DHAVE_CURSES_RESIZE_TERM -DNCURSES_MOUSE_VERSION=2
echo building _curses.pyd
cl %FLAGS% -I%PYTHON26%\include -I%PDSOURCE% %PYSOURCE%\Modules\_cursesmodule.c /link %PYTHON26%\libs\python26.lib %PDSOURCE%\win32\pdcurses.lib %PDSOURCE%\win32\panel.lib /out:%PYTHON26%\lib\_curses.pyd
echo building _curses_panel.pyd
cl %FLAGS% -I%PYTHON26%\include -I%PDSOURCE% %PYSOURCE%\Modules\_curses_panel.c /link %PYTHON26%\libs\python26.lib %PDSOURCE%\win32\pdcurses.lib %PDSOURCE%\win32\panel.lib /out:%PYTHON26%\lib\curses\_curses_panel.pyd
goto end

:gcc
set FLAGS=-DHAVE_CURSES_RESIZE_TERM -DNCURSES_MOUSE_VERSION=2 -Wl,--enable-auto-import -Wl,--export-all -s -shared
echo building _curses.pyd
gcc %FLAGS% -I%PYTHON26%\include -I%PDSOURCE% %PYSOURCE%\Modules\_cursesmodule.c %PYTHON26%\libs\libpython26.a %PDSOURCE%\win32\pdcurses.a %PDSOURCE%\win32\panel.a -o %PYTHON26%\lib\curses\_curses.pyd
echo building _curses_panel.pyd
gcc %FLAGS% -I%PYTHON26%\include -I%PDSOURCE% %PYSOURCE%\Modules\_curses_panel.c %PYTHON26%\libs\libpython26.a %PDSOURCE%\win32\pdcurses.a %PDSOURCE%\win32\panel.a -o %PYTHON26%\lib\curses\_curses_panel.pyd
goto end

:usage
echo pycurses_build.bat [msvc or gcc]

:end
endlocal
以下ソースにあてるパッチです。Windows上のsetuptermは必ずエラーで返すコードになっているので呼ばないようにしています。
--- Modules/_cursesmodule.c.orig    2009-06-13 01:30:02.000000000 +0900
+++ Modules/_cursesmodule.c 2009-06-13 01:30:23.000000000 +0900
@@ -2036,6 +2036,7 @@
        }
    }
 
+#ifndef _WIN32
    if (setupterm(termstr,fd,&err) == ERR) {
        char* s = "setupterm: unknown error";
        
@@ -2048,6 +2049,7 @@
        PyErr_SetString(PyCursesError,s);
        return NULL;
    }
+#endif
 
    initialised_setupterm = TRUE;
 

2009/06/10

はてな
これは良いね。
MOONGIFT: » GoogleリーダーのCUIフロントエンド「Peep」:オープンソースを毎日紹介

Googleリーダーは出始めた頃はAjaxを使った高速な操作性が可能で、とても便利なRSSリーダーだった。だが今ではソーシャル的な機能も増えており「読む」という機能に特化していない。速度だってlivedoorリーダーの方が速いだろう。そんなGoogleリーダーを再度便利にしてくれる、それがPeepだ。

http://www.moongift.jp/2009/06/peep/
ryuji's peep at master - GitHub

This software is a TUI front-end for Google Reader

http://github.com/ryuji/peep/tree/master
待ってたよ。こんなの。
peep
peep-view
ブラウザを起動するとfirefoxになっちゃうので環境変数BROWSERにw3mを設定すれば端末内で暮らせてウマー!

2009/02/18

はてな
先ほど試していたtw2ですが、少しやる気になってoutputzの設定もすませて動かしてみました。
ただ、中で使っているreadlineはimportした瞬間にbuilt-inのraw_input()を乗っ取ってしまい、かつ完全にマルチバイトに対応しきれていない様で、入力後の文字が化け化けになってしまいました。
おそらく、入力をutf-8で想定した作りになっているんだと思いますが、これはおそらく解決までに時間が掛かりそうな気がしています。
なのでpatchを書いてa2cさんにpull requestしました。
まれにutf-8しかない文字をtwitter/wassrに書き込んでくれる人がいるので、良いテストになりました。
raw_input()の変わりに、sys.stdin.readline()を使うようにしてあります。
diff --git a/tw2.py b/tw2.py
index fb04179..98fe90a 100755
--- a/tw2.py
+++ b/tw2.py
@@ -73,6 +73,9 @@ if __name__ == "__main__":
   friends = set()
   friendsTimeLine = []
 
+  def _T(text):
+    return text.encode('mbcs', 'ignore')
+
   def complete(text, status):
     results = [x for x in friends if x.startswith(text)] + [None]
     return results[status]
@@ -90,13 +93,13 @@ if __name__ == "__main__":
     # get twitter friends Replies
     print '\twassr replies\t'
     for data in reversed(wassr.getReplies()):
-      print '%-12s : %s' % (data['user_login_id'] ,data['text'])
+      print _T('%-12s : %s' % (data['user_login_id'] ,data['text']))
       friends.add(data['user_login_id'])
  
     # get twitter friends Replies        
     print '\n\twassr replies\t'
     for data in reversed(twitter.GetReplies()):
-      print '%-12s : %s' % (data.GetUser().GetScreenName() ,data.GetText())
+      print _T('%-12s : %s' % (data.GetUser().GetScreenName() ,data.GetText()))
       friends.add(data.GetUser().GetScreenName())
     return 0
 
@@ -105,7 +108,7 @@ if __name__ == "__main__":
     # Get FriendsTimeLine
     print ' -----  wassr Friends Time Line  -----'
     for data in reversed(wassr. getTimeline()):
-      print "%-12s: %s" % (data['user_login_id'] ,data['text'])
+      print _T("%-12s: %s" % (data['user_login_id'] ,data['text']))
       twit = "wr[]%-12s: %s" % (data['user_login_id'] ,data['text'])
       if twit in friendsTimeLine:
         pass
@@ -114,7 +117,7 @@ if __name__ == "__main__":
         friendsTimeLine.append(twit)
     print '\n  -----  twitter Friends Time Line  -----'
     for data in reversed(twitter.GetFriendsTimeline()):
-      print '%-12s : %s' % (data.GetUser().GetScreenName() ,data.GetText())
+      print _T('%-12s : %s' % (data.GetUser().GetScreenName() ,data.GetText()))
       # append log
       twit  = "tw[%s]%-12s: %s" % (data.GetCreatedAt(), data.GetUser().GetScreenName(), data.GetText())
       if twit in friendsTimeLine:
@@ -127,7 +130,8 @@ if __name__ == "__main__":
 
   prompt = '\n cmd: Friendstimeline[f] eXit[xx] \n> '
   while True:
-    input = raw_input(prompt).split(" ")
+    print prompt,
+    input = sys.stdin.readline().decode('mbcs').encode('utf-8').strip().split(" ")
     if input[0] != '':
       if len(input) == 1:
         if len(input[0]) > 2:
Macで動かなかったら御免なさい。

はてな
a2cさんが作ったtwitter client「tw2」を動かして見ようと思ったのですが、エラーも出るしpitが起動するエディタに何もテンプレートが出力されないのでコードを追ってみた。
調べた結果tw2ではなくpit側に原因がある事が分かった。
Bug #325139 in web.py: “web.profiler does not work on Windows”

tempfile.NamedTemporaryFile() to generate a temp file. On Windows the file cannot be opened a second time. Using tempfile.mkstemp() instead works but you lose the guaranteed cleanup of the temp file.

https://bugs.edge.launchpad.net/webpy/+bug/325139
どうやらNamedTemporaryFile()を使っていて、かつNamedTemporaryFile()はclose()時にファイルを削除してくれるのだけれど、内部でmkstempを使いfdを貰っているのにそのfdをclose()してくれていないものだからWindowsのハンドルが残りっぱなしになりwrite()もflush()もremove()出来ないと言う物だった。
Windowsでpit.pyを使ったプログラムを起動された事がある方は、一度テンポラリディレクトリの中を綺麗にした方が良いかもしれません。
    (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
    file = _os.fdopen(fd, mode, bufsize)
    return _TemporaryFileWrapper(file, name)
つまり
import os, yaml, tempfile

t = tempfile.NamedTemporaryFile()
t.write("foo")
t.flush()
path = os.path.abspath(t.name)
result = open(path).read()
t.close()
print result
の様にclose()前だと、fdが開放されていないので"Permission Denited"、また
import os, yaml, tempfile

t = tempfile.NamedTemporaryFile()
t.write("foo")
t.flush()
path = os.path.abspath(t.name)
t.close()
result = open(path).read()
print result
の様にclose()後だと、ファイルは消えてしまっているのでopen()出来ない...という事。なにそれ苦笑

上記リンクにある通り、NamedTemporaryFile()の変わりにmkstempを使い、かつremove()前にclose()してやれば動いた。
--- pit.py.orig 2008-06-28 16:58:42.000000000 +0900
+++ pit.py  2009-02-18 17:22:30.734375000 +0900
@@ -18,13 +18,21 @@
         else:
             if not os.environ.has_key('EDITOR'):
                 return {}
-            t = tempfile.NamedTemporaryFile()
             c = yaml.dump(opts['config'] if opts.has_key('config') else Pit.get(name) ,default_flow_style=False)
+
+            fd, path = tempfile.mkstemp()
+            os.close(fd)
+            t = open(path, "w+b")
             t.write(c)
             t.flush()
-            path = os.path.abspath(t.name)
+
             Popen([os.environ['EDITOR'],path]).communicate()
-            result = open(path).read()
+
+            t = open(path)
+            result = t.read()
+            t.close()
+            os.remove(path)
+
             if result == c:
                 print 'No Changes'
                 return profile[name]
@@ -44,7 +52,7 @@
         if opts.has_key('require'):
             flg = False
             keys = set(opts['require'].keys()) - set(ret.keys())
-            if keys:
+            if len(keys):
                 for key in keys:
                     ret[key] = opts['require'][key]
                 ret = Pit.set(name,{'config' : ret})
で、tw2については、outputzのIDがいるらしく面倒臭くなったのでヤメ。また今度試します。

ところでこのパッチ、NamedTemporaryFile()を修正するパッチにすべきか、はたまたpit.pyを修正してyoshioriさんに送ればよいのか...どうしましょうねぇ

2009/02/10

はてな
これは朗報。
Google App Engine Blog: SDK version 1.1.9 Released
  • You can now use the Python standard libraries urllib, urllib2 or httplib to make HTTP requests. This has been a frequent request on our issue tracker.
  • We've been working on a set of tools that will make the process of uploading and downloading data from App Engine applications easier. Today we're excited to announce an early release of our new bulk uploading client. You can try it out here. Let us know what you think in our Google Group!
  • Several updates to our datastore, including the automatic generation of single property indexes and the addition of IN and != operators to db.Query. See the Datastore API docs for more details.
  • A bunch of additional bugfixes and enhancements, listed in our Release Notes.
http://googleappengine.blogspot.com/2009/02/sdk-version-119-released.html
試しに以下の様なコードを書いて
import urllib2

f = urllib2.urlopen('http://www.google.com/')
print "Content-Type: text/plain;"
print
print f.read()

実行させてみた。

おー動いてる。これで今までGoogle App Engineのurlfetch API様にパッチを当ててきた物が要らなくなる。