123
 123

Fri 22 February, 2008

Click here to bookmark this link.Channel Image06:09 風邪引き» Matzにっき
朝から雪で、教会から帰ったら家の前の坂道が雪で滑って登れない。 先に帰った妻は子供たちと一緒に雪かきをしていた。 子供たちはどちらかというと雪遊びをしていたんだけど。 しかし、今年高校受験の長女は、勉強もせずに雪まみれになって 「滑ったり」、「転んだり」、「(溝に)落ちたり」していたのだが、 それはそれでいいんだろうか。 ところが、夕方になって妻が「寒気がする」とか言い出した。 どうやら先週の半ばに引いていた風邪が治りきっておらず 再発したらしい。 微熱と関節痛など典型的な風邪症状。 インフルエンザではなさ..
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image06:09 渡米» Matzにっき
6時前に起床。成田でネットアクセスするためにワイヤレスゲート ヨドバシカメラオリジナルプランを購入。 朝、7時すぎに出発。 途中でデジカメを忘れたことに気がついて引き返す。 わりとぎりぎりの時間に米子空港に到着。 米子空港出発組と合流。 米子から羽田へ。羽田からリムジンバスで成田へ。 成田ではワイヤレスゲートのおかげで快適にネット。 夕方からUAでサンフランシスコへ。 サンフランシスコについたらまだ午前中である。 バスで梅田望夫さんのところへ。 祝日(Presitent's Day)なのに親切に対応していただく。 ありがたい。..
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image06:09 レノボX300 封筒に入る超薄型ThinkPad - Engadget 日本語版» Matzにっき
Macbook Airと同じくらい薄いThinkpadについて。 かっこいい。魅力的。 タッチパッドは要らないけど。 この間X61を買ったばかりなので、出たらすぐに、というわけにはいかないとは思うけど。 弾さんみたいに年に1台とかいうペースでは買わないし。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image06:09 Matzに聞いてみた:効率の良い開発についてどうお考えでしょう? - page3 - builder by ZDNet Japan» Matzにっき
以前にインタビューを受けたものが公開された。 なんとなくRubyの宣伝っぽく聞こえるような書き方がしてあるが、 例によって本人にはそんなつもりは毛頭ない。 生産性とスピードがより重視される、というのが基本的な内容なんだけど、 「Web系に限定されるんじゃないか」と読む人も多いんじゃないかと思う。 少なくとも、「今」に限定して考えるとその通りだろう。 基幹系はWebのようには行かない。 また、現時点でRubyを基幹系に適用すべきとは考えない。 「できない」とは思わないし、実際に適用している人もいるんだけど、 Web系よりは..
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl

Thu 21 February, 2008

Click here to bookmark this link.Channel Image17:51 Twitter Updates for 2008-02-20» halostatue
lazytwitter: iTunes.app/Leopard Firewall problems? http://skitch.com/austin/g1uk/usernotificationcenter # xcode-lazytwitter: convert Makefiles to projects? Is there a concept of a "solution" like in Visual Studio? (A project of projects.) # honestly confused why anyone gives a shit if Obama learned from a Communist mentor: http://boortz.com/nuze/200802/02202008.html # And who the hell is Neal Boortz anyway? What makes him better than Coulter and [...]
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image06:07 Want to work on languages at Microsoft?» John Lam on Software
First a public service announcement followed by a message from our sponsors ... The videos from our Lang.net 2008 symposium are now online. For a recap of the conference, see my earlier blog post. If you like what you see...
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image03:27 gambrel: 1.The hock of a ho...» Projectionist
gam•brel
[gam-bruhl]noun
1.The hock of a horse or other animal.
2. A frame used by butchers for hanging carcasses by the legs.

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl

Wed 20 February, 2008

Click here to bookmark this link.Channel Image15:02 werkzeug指南(4)» 动态感觉 静观其变
上次我们说道了jinja模板引擎,设定了模板引擎的配置,包括加载器,
加载的文件系统的路径。现在就来说说jinja的模板本身的语法,jinja原先用过一次,
和django template极其相似,而且有意思的是它能在{% if %}使用运算符,
可以在模板中调用函数,a(),注意是带括号的。这些方面的改进让它与
django template相比,更具灵活和简便。来看看Shorty的模板吧。
既然和django template类似,那么就有模板继承的概念了。看看它的布局模板,templates/layout.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Shorty</title>
</head>
<body>
<h1><a href="{{ url_for('new') }}">Shorty</a></h1>
<div class="body">{% block body %}{% endblock %}</div>
<div class="footer">
<a href="{{ url_for('new') }}">new</a> |
<a href="{{ url_for('list') }}">list</a> |
use shorty for good, not for evil
</div>
</body>
</html>
这其中有{% block body %}{% endblock %}这就是子模板需要填充的内容。
url_for()这个函数的调用出自哪里呢?就是前面utils.py中定义的url_for函数。
这个函数由jinja的环境设置中配置,jinja_env.globals['url_for']=url_for,通过
这样设定之后,就能在模板的上下文中使用了。

有了这个layout.html后,就可以继承{% extends %}它了,并填充
{% block body %}{% endblock %}的内容了。看看new.html
{% extends 'layout.html' %}
{% block body %}
<h2>Create a Shorty-URL!</h2>
{% if error %}<div class="error">{{ error }}</div>{% endif -%}
<form action="" method="post">
<p>Enter the URL you want to shorten</p>
<p><input type="text" name="url" id="url" value="{{ url|e(true) }}"></p>
<p>Optionally you can give the URL a memorable name</p>
<p><input type="text" id="alias" name="alias">{#
#}<input type="submit" id="submit" value="Do!"></p>
<p><input type="checkbox" name="private" id="private">
<label for="private">make this URL private, so don't list it</label></p>
</form>
{% endblock
%}

e(true)是jinja的一个filter,{# #}是注释块,这里是为了不留下空白符。

templates/display.html
{% extends 'layout.html' %}
{% block body %}
<h2>Shortened URL</h2>
<p>
The URL {{ url.target|urlize(40, true) }}
was shortened to {{ url.short_url|urlize }}.
</p>
{% endblock
%}

url.target, url.short_url是URL的属性,参看models.py。
urlize也是filter

看了templates之后,还缺少一个东西,就是那些静态文件css/javascript怎么弄呢?
django中是把这些静态文件分离出来交给web server处理,开发时是用一个过渡的方式来处理。

还记得在最开头的目录结构中有一个static. werkzeug是在application.py中
加入下列代码:
from os import path
from werkzeug import SharedDataMiddleware


把STATIC_PATH加入到utils.py中

STATIC_PATH = path.join(path.dirname(__file__), 'static')
既然application.py是一个dispatch的话,那就继续扮演这个角色,包装一下原先定义的
__call__(),但是self.__call__ = wrap(self.__call__)这样的用法是不对,换个用法
把原先的__call__更名为dispatch,再用新的__call__来包装dispatch.
def __call__(self, environ, start_response):
return self.dispatch(environ, start_response
)

这样处理后,就到__init__函数中,安排一个包装dispatch的包装器。
self.dispatch = SharedDataMiddleware(self.dispatch, {
'/static': STATIC_PATH
})
这就是充分利用了wsgi的middleware的作用,不断来增强wsgi的功能。

在utils.py用下面的url_map替换原先的url_map = Map()
url_map = Map([Rule('/static/<file>', endpoint='static', build_only=True)])

有了这个,就可以在html中加入css的引入。

<link rel="stylesheet" type="text/css" href="{{ url_for('static', file='style.css') }}">

从上面的介绍,基本上就介绍完Shorty的主干线了。models/views/templates/dispatch,
这4个环节,让werkzeug做的wsgi application的结构
渐渐清晰起来。但是感觉上还是有些乱,
这是因为它还不是一个完整的framework,如果是一个完整的framework,比如django/pylons,
它就会隐藏哪些呢?

1.dispatch,这个不必由开发人员来处理,应该由框架处理。
2.模板的衔接上,不必由开发人员以编程的方式来配置模板,
应采取更简单的作法。
3.在utils.py中可以看到很多东西,什么东西都往那一撂,像个仓库,
应该能有更清楚的作法。

但是这样的开发方式有什么好处呢?
一个就是灵活,模板是自己的,orm是用自己的,有什么wsgi middleware可用,
都能加入,而且是以一种直观的方式加入。
二是对一些小的项目,可能就是一个或两个py文件就打发,整个项目的打包简单
了,不需要用不到的功能。
三就是对开发人员来说,扩展性由自己来定,这是wsgi middleware的特点决定
的,可以不断加入wsgi middleware,增加功能。
...
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image13:30 Twitter Updates for 2008-02-19» halostatue
finishing the review of the technical book I’m looking over # hate bugs that can’t be reproduced on development machines. # huh. hadn’t noticed that spacebar in twitterriffic does the right thing. # @mattgemmell aren’t all the Kool Kids using Git these days? # @objo *snort* someone actually did that somewhere? # @iacas yeah. that is annoying. wonder why the [...]
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image11:02 werkzeug指南(3)» 动态感觉 静观其变
开始进入views.py,这里和django一样,是真正接触project业务逻辑处理的地方。
由它来连接models和templates

看代码吧
from werkzeug import redirect
from werkzeug.exceptions import NotFound
from shorty.utils import session, render_template, expose, validate_url, \
url_for
from shorty.models import URL

@expose('/')
def new(request):
error = url = ''
if request.method == 'POST':
url = request.form.get('url')
alias = request.form.get('alias')
if not validate_url(url):
error = "I'm sorry but you cannot shorten this URL."
elif alias:
if len(alias) > 140:
error = 'Your alias is too long'
elif '/' in alias:
error = 'Your alias might not include a slash'
elif URL.query.get(alias):
error = 'The alias you have requested exists already'
if not error:
uid = URL(url, 'private' not in request.form, alias).uid
session.commit()
return redirect(url_for('display', uid=uid))
return render_template('new.html', error=error, url=url)

@expose('/display/<uid>')
def display(request, uid):
url = URL.query.get(uid)
if not url:
raise NotFound()
return render_template('display.html', url=url)

@expose('/u/<uid>')
def link(request, uid):
url = URL.query.get(uid)
if not url:
raise NotFound()
return redirect(url.target, 301)

@expose('/list/', defaults={'page': 1})
@expose('/list/<int:page>')
def list(request, page):
pass
这里有几个地方要注意:
1.就是@expose,这里是在utils.py中定义的decorate,也就是说在执行views.py时
碰到@expose之类的,就会调用utils.py中的expose,然后就自动加入url map,
再由wsgi application的Shorty来处理,url_map.bind_to_environ(environ)。
2.激活模板的处理是render_template,这个werkzeug并没有含有,而是通过
选定的template引擎来处理的。这个例子是用Jinja的模板引擎。那么来看看
render_template是如何编写的。
3.在new()中处理表格form的内容,使用的是request.form.get来捕获用户输入的信息。
for os import path
from urlparse import urlparse
from werkzeug import Response
from jinja import Environment, FileSystemLoader

ALLOWED_SCHEMES = frozenset(['http', 'https', 'ftp', 'ftps'])
TEMPLATE_PATH = path.join(path.dirname(__file__), 'templates')
jinja_env = Environment(loader=FileSystemLoader(TEMPLATE_PATH))
jinja_env.globals['url_for'] = url_for

def render_template(template, **context):
return Response(jinja_env.get_template(template).render(**context),
mimetype='text/html')

def validate_url(url):
return urlparse(url)[0] in
ALLOWED_SCHEMES


从这段代码中,可以看到要设置jinja的配置信息Environment
,以及要加载
模板的路径TEMPLATE_PATH,我们在开头介绍项目的目录结构就有一个子目录
是templates,使用的加载器是FileSystemLoader。有了这个之后,
看render_template定义, template是模板本身,context是出入模板的上
下文相关的变量信息,然后打包生成html。这段代码也是放在utils.py文件中。
...
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image09:02 werkzeug指南(2)» 动态感觉 静观其变
在上篇中,主要说的是Shorty这个wsgi application的class,是整个web的dispatch,
承担了数据进出,分派url的映射处理,也就是

request=>url map=>views=>response
                              /     \
                     models    templates

Shorty算是一个中枢,控制着整个数据的走向。在这个例子中url map的处理
有些特别,先按照它的处理走,有时间我们再按照django的urls.py方式独立出来。


下面就要对models/views/templates相对应的代码作些介绍了。

在utils.py中,配置了sqlalchemy的session,metadata,在application.py中
配置了create_engine,引入数据库引擎。下面来看看models.py中到底如何
来定义models的。

from datetime import datetime
from sqlalchemy import Table, Column, String, Boolean, DateTime
from shorty.utils import session, metadata, url_for, get_random_uid

url_table = Table('urls', metadata,
Column('uid', String(140), primary_key=True),
Column('target', String(500)),
Column('added', DateTime),
Column('public', Boolean)
)

class URL(object):

def __init__(self, target, public=True, uid=None, added=None):
self.target = target
self.public = public
self.added = added or datetime.utcnow()
if not uid:
while True:
uid = get_random_uid()
if not URL.query.get(uid):
break
self.uid = uid

@property
def short_url(self):
return url_for('link', uid=self.uid, _external=True)

def __repr__(self):
return '<URL %r>' % self.uid

session.mapper(URL, url_table
)


这个是sqlalchemy的定义models的方式,先建Table,然后声明class,
最后用mapper来映射之。这与django定义models的方式不同。
get_random_uid是需要在utils.py进行补充的。是随机生成id号。

from random import sample, randrange

URL_CHARS = 'abcdefghijkmpqrstuvwxyzABCDEFGHIJKLMNPQRST23456789'

def get_random_uid():
return ''.join(sample(URL_CHARS, randrange(3, 9
)))

定义好models之后,就可以用开始介绍的manage.py initdb来生成数据库的
表结构了。application.py和models.py中通过utils.py中定义的session,
metadata来关联在一起。

运行manage.py shell进入交互式shell来看看models的处理吧。

Interactive Werkzeug Shell

>>> from shorty.models import session, URL
>>> urls = [URL('http://example.org/'), URL('http://localhost:5000/')]
>>> URL.query.all()
[]
>>> session.commit()
>>> URL.query.all()
[<URL '5cFbsk'>, <URL 'mpugsT'>]
>>> URL('http://werkzeug.pocoo.org/', False, 'werkzeug-webpage')
>>> session.commit()

>>>
URL.query.filter_by(public=False).all()
[<URL 'werkzeug-webpage'>]
>>> URL.query.filter_by(public=True).all()
[<URL '5cFbsk'>, <URL 'mpugsT'>]
>>> URL.query.get('werkzeug-webpage')
<URL 'werkzeug-webpage'>
...
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image08:38 Blue Collar TV Parody of AFV» Joey Gibson's Blog

This video is a couple of years old now, but I haven't seen it posted on Youtube before, so I did. You know how on America's Funniest Home Videos about 80% of the videos are of some poor schmuck getting whacked in the nuts? This video takes it to a whole new level. I laugh so hard every time I watch this.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image02:11 The Octopus Project –...» Projectionist

The Octopus Project – Truck


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image02:09 I don’t mind if people don’...» Projectionist
I don’t mind if people don’t like me as long as it’s for things I am.

Steve Wozniak


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl

Tue 19 February, 2008

Click here to bookmark this link.Channel Image20:09 io - Objective-C Syntax» Matzにっき
IoでObjective-Cの文法を導入する試み。 こういう「クレージー」なことができる言語は素晴らしい。 が、日常的に使いたいかどうかはまた別問題である。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:09 InfoQ: John McCarthy on Elephant 2000, Lisp, Ruby and the Computer Industry» Matzにっき
John McCarthyがRubyに言及したのかっ、と思ってインタビューのログを読んだが、 インタビュアーがふっただけなのね。そりゃそうか。 で、返答は当然(?)ながら I don't know enough for example about Ruby to know in what way it's related to Lisp. Does it use, for example, list structures as data. So if you want to compute with sums and products, you have to parse every time? So, in that respect Ruby still isn't up to where Lisp was in 1960. というもの。ある意味、予想通り。 未来の言語であるところの「Elephant..
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image17:04 Twitter Updates for 2008-02-18» halostatue
@timbray when *isn’t* LF pissy? # @timbray I’m happier with our product’s Solaris support than our Linux support, mostly because Sun is sane on library versioning. # rented Wii Super Paper Mario for the holiday weekend. Enjoying the day off. # @uliwitness I’m not celebrating Dead Prez day. I’m celebrating Family Day. ;) # reviewing an early draft of [...]
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image17:02 werkzeug tutorial(1)» 动态感觉 静观其变
Werkzeug指南

在看werkzeug tutorial,感觉它的编排上有点和自己的思路相悖,所以我调整一下前后结构,按自己的理解来介绍这篇werkzeug tutorial的内容。这篇指南中的例子,采用的套路基本和django类似,就是用models/views/templates。
(一)目录结构
Werkzeug算是半个框架,创建一个project还没有自动化。那就手动开始做一个project的目录结构,按这个方式走一遍,就知道前后的关系了。这个应用是shorty,随便在一个目录下,比如在werktest目录下,创建如下的目录结构:

manage.py
shorty/
    __init__.py
    templates/
static/

manage.py和__init__.py还都是空文件。有__init__.py存在说明shorty是个包,manage.py是这个project的管理器,类似django project的manage.py。前面说过它用的是mtv的方式,那后面还有models.py, views.py一步步加入。

(二)manage.py
manage.py用来激活一个开发用的web server,以及其他的一些功能,比如调试器,初始化数据,交互式的shell之类。先来写一些代码到manage.py

#!/usr/bin/env python
from werkzeug import script

def make_app():
    from shorty.application import Shorty
    return Shorty('sqlite:////tmp/shorty.db')

def make_shell():
    from shorty import models, utils
    application = make_app()
    return locals()
 
action_runserver = script.make_runserver(make_app, use_reloader=True)
action_shell = script.make_shell(make_shell)
action_initdb = lambda: make_app().init_database()

script.run()

werkzeug中的包script就是专门处理这些的。注意看其中的action_xxx之类的,针对这些命名,可以用manage.py xxx来调用,
比如说
manage.py shell,就是进入交互式shell,
manage.py initdb,就是初始化数据库,
manage.py runserver,就是启动开发用的web server,
而且user_reloader=True,还是针对代码变化随时重启的。

(三)wsgi application
在manage.py中,有个action_runserver,调用的是make_app,这个就是用来调用wsgi application的

def make_app():
    from shorty.application import Shorty
    return Shorty('sqlite:////tmp/shorty.db')
 
在shorty目录下,创建application.py,wsgi application有两种方式来创建的,一个是以函数xxx_wsgi_application(environ, start_response)的方式,另一个是以带有__call__(self, environ, start_response)的对象方式来创建,面向对象的方式更好些,因为通过封装,可以传入一些配置信息,还能处理一些wsgi middleware。所以看看shorty/application.py的代码:

from sqlalchemy import create_engine
from werkzeug import Request, ClosingIterator
from werkzeug.exceptions import HTTPException

from shorty.utils import session, metadata, local, local_manager, url_map
from shorty import views

import shorty.models

class Shorty(object):

    def __init__(self, db_uri):
        local.application = self
        self.database_engine = create_engine(db_uri, convert_unicode=True)
 
    def init_database(self):
        metadata.create_all(self.database_engine)

    def __call__(self, environ, start_response):
        local.application = self
        request = Request(environ)
        local.url_adapter = adapter = url_map.bind_to_environ(environ)

        try:
            endpoint, values = adapter.match()
            handler = getattr(views, endpoint)
            response = handler(request, **values)
        except HTTPException, e:
            response = e
        return ClosingIterator(response(environ, start_response),
                               [session.remove, local_manager.cleanup])

application.py中还导入了shorty.utils,这里导入了很多附加的处理,比如orm的初始化,url mapping的处理,看看shorty/utils.py吧:

from sqlalchemy import MetaData
from sqlalchemy.orm import create_session, scoped_session
from werkzeug import Local, LocalManager
from werkzeug.routing import Map, Rule

local = Local()
local_manager = LocalManager([local])
application = local('application')

metadata = MetaData()
session = scoped_session(lambda: create_session(application.database_engine,
                         transactional=True), local_manager.get_ident)

url_map = Map()
def expose(rule, **kw):
    def decorate(f):
        kw['endpoint'] = f.__name__
        url_map.add(Rule(rule, **kw))
        return f
    return decorate

def url_for(endpoint, _external=False, **values):
    return local.url_adapter.build(endpoint, values, force_external=_external)

通过上面两个py文件,你可以看到application.py中wsgi application,在__init__()中引入数据库引擎,这点在manage.py中有反映。

def make_app():
    from shorty.application import Shorty
    return Shorty('sqlite:////tmp/shorty.db')

返回的是Shorty对象,这样调用后,实际执行的有两个,一个就是Shorty.__init__(),另一个就是__call__(self, environ, start_response),
Shorty中定义的另一个函数init_database,是用来创建数据库的,在manage.py中由action_initdb来处理。

下面来看看__call__中的内容,既然这个是wsgi application的核心,这里应该就是负责uri dispatch的中转站,由它来分配相关的一些调用,这样的话,当然先要获取request的相关信息

request = Request(environ)

然后就是要分析request的信息,

local.url_adapter = adapter = url_map.bind_to_environ(environ)

这个看的有些晕了吧。
Try/except块中,对adapter对url进行分离


endpoint, values = adapter.match()

分离出相关的function,也就是具体的views,views沿用了django的用法,怎么找呢,它运用了python的getattr函数,这是对模块动态查询的

handler = getattr(views, endpoint)

就是先找到views.py中有无endpoint的函数,然后就去调用之

response = handler(request, **values)

如没有找到,则发生异常。

return ClosingIterator(response(environ, start_response),
                               [session.remove, local_manager.cleanup])

最后是个收尾,返回response(environ, start_response),这就是真正处理wsgi的地方。它是可以用middleware的方式进行连续的调用的。后面的函数,是回调函数,session.remove, local_manager.cleanup,

(四)   utils.py到底有些什么
我们前面列出了utils.py的代码,它这里头杂七杂八的,什么都有,我也晕。

from werkzeug import Local, LocalManager
from werkzeug.routing import Map, Rule

local = Local()
local_manager = LocalManager([local])
application = local('application')

local对象是一个线程对象,它的属性都和当前的request绑定在一起,就能隐含的以线程安全的方式传递local对象,local_manager是用来跟踪所有的local对象,在request处理的最后结尾,能把local对象正确的删除之。

application = local('application')

这个是用字符串的local对象,返回的是一个proxy对象,指向的是local对象的名字,比如上面这句就是application指向的就是local.application,在Shorty中__init__()和__call__()中都有一句代码

local.application = self

而__init__()引入local.application = self实际没有什么用处,可是要在shell中使用,它就有用了,就能在交互状态下使用了。

from sqlalchemy import MetaData
from sqlalchemy.orm import create_session, scoped_session

metadata = MetaData()
session = scoped_session(lambda: create_session(application.database_engine,
                         transactional=True), local_manager.get_ident)

这里其实我也没有用过,scoped_session看介绍是一个factory函数,我也是云里雾里,不懂其中的内涵。local_manager.get_ident返回的是local对象内部使用的上下文的信息(context identifier)。似乎就是多个程序联用,可以使用同一个session来处理,这好像可以解决我原先碰到的那个问题,就是多个request来处理sqlalchemy的session,而这些session是处理同一个数据,如果session是不同的话,数据同步的问题就会出现,如果在这个scope_session统一来处理的话,就不会发生数据不一致的问题了。我只是猜测。上次我碰到问题的时候,最后是使用即刻写数据库,更新掉缓存。(待续)...
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl

Mon 18 February, 2008

Click here to bookmark this link.Channel Image16:06 Twitter Updates for 2008-02-17» halostatue
lovely dinner party at a friend’s. # @jsnell that (haiku political debates) would not be a bad thing. ;) # Powered by Twitter Tools.
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image16:06 米澤先生講義» Matzにっき
楽天で米澤先生による講義が開催される。 米澤先生といえば、私が幼いころ(高校生くらい?)、 オブジェクト指向に関する情報が欲しかったけど 当時入手できる日本語の情報が、岩波の『算法表現論』くらいしかなくて、 苦労して借りてきて読んだのが私の原点になっている。 その先生とこんなに親しくお話しできるというのは なんとありがたいことなのだろうなあ。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image16:06 京都 - jkondoの日記» Matzにっき
はてなが京都に帰る、というお話。 いや、デブサミの講師控室で「なおやさんが京都へ引っ越し」とかいう話を 耳にしていたのだが、このニュースとつながるまでちょっと時間がかかった。 にぶい。 「東京じゃないところ」がどれだけのアドバンテージになるのか、 あるいはディスアドバンテージになるのか、注意深く見守りたい。 はてなにはすでにそこそこの人材がいるので、うまくやれば、 「毎日開発合宿」のように開発が進むかもしれない。 「普通の会社(NaClも含めて)」では、なかなかそれは難しいのだけど、 はてなはそういうのができ..
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image16:06 「島根県CMS」のオープンソースとしての公開について» Matzにっき
とうとう公開された。 OSS化に伴ういろいろと面倒なことをクリアした関係者の方に 純粋に敬意を表したい。 とりあえず島根県では使い物になっているが、汎用性などについては 改善の余地があると思う。できるものならばこのCMSを中心にしたコミュニティが 形成されて、発展するサイクルが成立すれば、と思う。 それはそれで難しい課題は山積みなんだけど、それでも、なお。 ITProによる記事「島根県のホームページ管理システムがOSSとして無償公開,地元企業がRubyで開発:ITpro」
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image16:02 说说werkzeug» 动态感觉 静观其变

近日看到werkzeug出了0.2版本,它是colubrid的后续项目,因原先弄过colubrid的一个小应用,所以好奇地想看看werkzeug是什么样子。看完werkzeug的文档后,感觉还是要写点介绍的东西。

Werkzeug并不能算是一个web framework,它和colubrid一样,只是完成了web framework所需很少的一部分,基本可以把它作为完成了responserequest的处理功能,而且是以wsgi的方式来完成的。那么以wsgi自居的出名的软件有几个:pastepylons这两个是其中的代表。尤其pylons还是以paste为基础实现的一个比较完整的web framework。那werkzeug为何还要出现呢?从werkzeug的一些背景来看,一是原先有colubrid为蓝本,做了一些重新设计,二是paste作为一个wsgi超强的tool,过于复杂,附带的pastescriptpastedeploywsgi本身没有关系,只是作为wsgi的部署和运行需要,使得很多人对paste有种畏惧。而paste目前又将requestresponse独立出来以webobject的方式来处理,包之间的依赖关系又平添了一层。Werkzeug的简单,小巧,仅仅处理的就是wsgi的一系列小功能,使得它能填补paste阻碍造成的空间。

werkzeug不能算一个web framework,是因为它不强制使用特定的模板引擎,也不强制使用orm,没有想django那样的admin,没有pylons那样的ajax的集成。werkzeug就是为wsgi应用编写的一组简单的工具,包括的功能有requestresponse对象的处理,http实体标签(entity tags),缓存控制的头信息(cache control headers)cookie处理,文件上传,以及url routing的处理(可以和djangourl routing媲美)。

Werkzeug的出现对那些想组合适合自身需求的人来说,是个有趣的选择。它提供的tutorial文档充分展示了mvc,准确的说应该是mtvd(model/template/view/dispatch),就是django极力宣传的哲学套餐。可能werkzeug目前来说与django/pylons相比,开发效率上可能没有那么自动,不过它所展现的框架的脉络对开发人员来说是极具吸引力的。要加一个自动化工具来连接所需web framework的各组件,应该会促进更多人使用werkzeug

如果想了解wsgi的详情,可以参看我以前blog的文章,还有一点,特别是以前还有一篇译文是讲why not many python web framework的,werkzeug恰恰是为其中的最薄弱的一环(如何处理wsgi)注入了新的活力和源泉。

有空我将继续werkzeug的介绍。

...
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image12:45 Ruby Metaclass详解» Ruby on Rails: LetRails
来自whytheluckystiff.net。 —————————————– 如果你是Ruby Metaprogramming的新手,那么下面的代码或许会帮你找到一点感觉: class Object  ...
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image07:14 办公软件:社会网络浏览器Flock» 天天红玉世界
正在赶超Firefox的社会网络浏览器Flock
  • 说明
    • 浏览器Flock是虽然是基于Mozillas Firefox,但是它速度更快并且提供更多的功能:在浏览器中直接阅读RSS,写博客和共享照片等等。这是我现在天天使用的浏览器。

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image03:11 デブサミ2日目» Matzにっき
昨日が最終セッションで日帰りできず、 明日は別件で前泊が必要だったので、 今日は東京で過ごさざるをえない。 午前中、広尾で教会の用事をすませて昼食を両親と取り、 午後はデブサミへ。 特に見たいと思っているセッションがあるわけではないので 展示を中心に。 Pythonのブースでは、 柴田さんから「『たのしいみんなのPython』にサインしてください」と依頼される。 Guidoのサインの下というのもどうなんだろう。 一部で価値が出るのかもしれない。 ついでに(?)、PHPブースではPHP本にサインする。 フレンドリー。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image03:11 PythonをDISる。» Matzにっき
デブサミ会場で、雑談していると「PythonはDISらないんですか」と柴田さんから。 なんか自虐的じゃない? とは言うものの、Pythonは基本的に良い言語で、 不満な点はかなり微妙だ。一般人にはどーでもいいような点だと思う。 一応リストを。 式と文の区別が明確。 インデントベースだとeRubyのようなテンプレートが難しい ブロックを含む式を持てない。Haskellみたいにブレースを使えば式にできるといいのに reduceがなくなる generator難しい。yieldを書くと戻り値が変化するってのはどうよ list comprehensionが難しい。英語人には人気..
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image03:11 Pre New Generation Chronicle:上野康平−−3次元空間を統べる若き天才プログラマー - ITmedia エンタープライズ» Matzにっき
−− 大物ハッカーといえば? Rubyのまつもとゆきひろさん。ハッカー理想像を実践されているところにあこがれます。技術力だけをみれば、まつもとさんより優れた方も多く存在されるかもしれませんが、日本人であそこまで自分の信念を持って行動されるハッカーってなかなかいないんじゃないかなと思いますし、自分でしっかりとしたコミュニティーを運営されていることなどもリスペクトしています。Ruby 1.9で過去の遺産をバシバシ捨てているのは素晴らしいなぁ。ああいう覚悟がC++にあれば、もう少し違っていたでしょうが。 いやあ、ほめら..
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image03:11 New Generation Chronicle:べにぢょ−−ギークプロトコルの解読を試みるサイバーヤンキー - ITmedia エンタープライズ» Matzにっき
えーと...、女性から見てギークに魅力があるって話は 残念ながら他で聞いたことないなあ。 例外中の例外の話、なのかな。 あえて魅力に感じられそうな点といえば 頭良さそう 物知りそう 収入良さそう くらいかなあ。一方、 自分を大切にしてくれなそう 人間味が薄そう とかのネガティブ要因もあるし。 まあ、どっちにしても個人に帰属する要因が大きいので、 ギークだからどうこうということは必ずしもないだろう。 根っからのオタクの私だって、結婚して子供までいるわけだし。 弾さんもそうだ。 もっとも、女房子供以外からモテたためし..
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl

Sun 17 February, 2008

Click here to bookmark this link.Channel Image13:39 Twitter Updates for 2008-02-16» halostatue
@wilshipley wouldn’t that be more of a guild? # going to make pain perdu this morning # tired. made rice bread pain perdu; spelt tortillas; waiting for spelt and honey bread dough to finish the first rise. + cashew/almond butter # @ntalbott that reminds me. must insist that the parental units bring some grits when they come up [...]
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image05:14 デブサミ2008 1日め (ディープな1日)» Matzにっき
東京へ。 雪で飛行機の出発が1時間ほど遅れる。 出雲空港はわりと雪に慣れているので、1時間も遅れるのは珍しい。 おかげで約束に遅れちゃったけど。 目黒の雅叙園に移動。 まずは、『BeautifulCode』日本語訳を記念して、 販促のために翻訳者の久野先生と奥様と対談。 最近は知らない人の方が多いかもしれないけど、 久野先生は日本を代表する言語屋で、 私の師匠筋の人である。 以前にも書いたけど、 Rubyの言語設計にも多少影響を与える記事を書いた人だ。 なもんだから、対談はいきなりディープな世界に突入。 みんなついてこれるのか?..
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image04:37 Custom Firmware on the PSP» Pablotron: News

Last night I installed a custom firmware (CFW) on my PSP. The custom firmwares allow you to run unsigned homebrew (e.g. non-Sony sanctioned) applications.

Applications

The PSP homebrew community has been pretty active; there are several useful applications and emulators for lots of older systems. There are even emulators for obscure systems like the ColecoVision and Neo Geo.

Here's what works for me so far, in no particular order:

I also tried the Genesis, NES, and N64 emulators, but they aren't working yet. Here's a picture of the SNES emulator at work:

Playing SNES on a PSP
Playing SNES on a PSP

The custom firmware also allows you to dump UMDs and run them from a memory stick. Since it's pretty much impossible to fit a PSP and 8 UMDs in the your pockets without looking like a complete tool, I'm going to offload as many UMDs as I can into the 3GB remaining on my memory stick.

The next section explains the firmware installation process. If you don't have a PSP, you may still find my creatively ominous safety warnings entertaining.

Installation

Installing the custom firmware varies in complexity depending on the model of PSP model and version of the original firmware. If you're fortunate enough to have an older "phat" PSP (e.g. the larger black model) that's running firmware 1.00 or 1.50, then installing the custom firmware is fairly straightforward.

If you know someone with a PSP who already has the custom firmware installed, then the installation process is still easy enough, because they can use their PSP to help you with yours.

If you've got a newer PSP Slim (the smaller white model, like the one in the picture above) and/or are running a newer firmware, then there are no easy options left, so get ready for the comically unpleasant experience below.

In order to install the custom firmware, you'll need a spare battery and a spare memory stick. For the love of Douglas Adams, please do not use this post as a guide! There are several web sites (here and here) that cover the entire installation process in far more detail and with the appropriate safety precautions. If you mess this up you will turn your PSP into a lifeless and possibly explosive plastic brick.

The basic, high-level steps are as follows:

  1. Create a Pandora's battery. This is a battery that has been modified to make the PSP into boot from the memory stick.
  2. Create a Magic Memory Stick. This is a memory stick that has been specially formatted to boot and perform a firmware upgrade. Note that there are some limits on the capacity and brand of memory stick that can be used; see the guides above for more details.
  3. With the PSP powered off and the battery removed, insert the magic memory stick into the PSP.
  4. Insert the Pandora's battery. The PSP will power on automatically boot from the magic memory stick.
  5. Use the software on the magic memory stick to install the custom firmware. On the PSP Slim the display is blank, so you just have to hit X and wait. The lights on the front of the PSP will blink for several minutes. The PSP will automatically power off when the installation is finished.
  6. Remove the Pandora's battery and the magic memory stick. The memory stick can be reformatted and used as usual. The Pandora's battery can not, because some of the battery's safety features are disabled as part of the conversion process. In other words, do not attempt to use the Pandora's battery as a regular battery unless you want your PSP to melt into a smoldering puddle of goo.
  7. Power on the PSP using a regular battery or the power cable. Congratulations, you are now running the custom firmware.

The hardest part of this process is creating the Pandora's battery. If you know someone with a PSP that already has the custom firmware installed, then they can run an application on their PSP to temporarily "soft-mod" a regular battery into Pandora's battery.

If you don't know anyone with a PSP that already has the custom firmware installed, then the only way to convert a regular battery into a Pandora's battery is to "hard-mod" it; that means cutting open the battery casing and disconnecting one of the leads on the internal circuitry.

The guides I read (see above) have plenty of pictures, but I was still surprised by how small the pieces actually were. Here's a picture I just took of my Pandora's battery, including a ruler and quarter as size references:

Inside a Pandora's Battery
Inside a Pandora's Battery

Creating a Magic Memory Stick is much simpler. Basically you:

  • format the memory stick in a special way (using mspformat)
  • copy the necessary firmware installation and upgrade files into place
  • generates an Initial Program Load (IPL) file,
  • copy the generated IPL file to the first sector of the memory stick (using mspinst)

If you're using Windows, the "TotalNewbi Installer" and "Pandora Easy GUI" tools can automate this process. In theory, anyway. When I tried to use them in my Windows XP VMWare instance, they both had problems. The TotalNewbi Installer simply refused to work, and the Pandora Easy GUI blue-screened XP each time I ran it.

Here's what finally worked:

  • used Pandora Easy GUI to copy the firmware files into place and generate the installer definition file (mspinst.idl)
  • used dd in Linux to copy mspinst.ibl into the first sector of the Memory Stick

The good news is that creating the Pandora's Battery and Magic Memory Stick are the hardest steps in the process. Once you get past them, everything else is relatively straightforward. Even better, the process can be used to install custom firmware on any PSP, regardless of hardware model or firmware version.

That's it for me. If you're interested in the history and technical details of PSP homebrew, check out this extremely detailed PSP homebrew Wikipedia entry.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image01:29 デブサミ» 青木日記
http://codezine.jp/devsumi/2008/ 水曜はデブサミでした。今回は (っていうか初めてだけど) スピーカー参加。 「ふつうの Ruby プログラマに贈る Ruby プログラミング講座」 というテーマでしゃべってきました。 前半 30 分は、るびまの添削連載でやったネタのうち、 他の言語から Ruby へ乗り換えた人に効果的と思われる話。 内容はこんなもん。 protected いらねー pと pp unless と until、使ってる? クラスと名前空間 (クラス・モジュールのネストについて) ファイル名の付けかた (メインクラス名をdowncase して付ける、ネストを反..
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image01:29 取材» Matzにっき
先日に引き続き、某雑誌のためにライターさんから取材を受ける。 「クリスチャンとしての私」と「プログラマ(言語デザイナ)の私」の関係に 関心を持たれたようで、かなりの時間を教会とかの生活について 話す。そういえば、こんなに教会関係の話を(教会員でない人に)話すのは久しぶりな感じ。 宣教師時代の経験とか。 宗教って微妙な題材だと思うんだけど、いいのか? 私としては、これも私の重要な一部なので、ありがたいと思ってるけど。 妻にも電話で取材をしていた。 内容は聞かなかったのだが、後で聞いたところ、 「彼は『ダーリン..
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl

Sat 16 February, 2008

Click here to bookmark this link.Channel Image17:46 网站推荐:集Google和百度于一体» 天天红玉世界
Click here to bookmark this link.Channel Image14:11 Twitter Updates for 2008-02-15» halostatue
tired. sick. bedtime. # @bynkii that is, by and large, how I do my charity. Unless @bmf is saving the lemurs. I don’t need fear of hell to be charitable. # @ShawnKing so what you’re saying is that the D300 fails you, not the other way around? ;) # @marick why QTP and not, say, iMovie? # lazytwitter: why [...]
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl

Fri 15 February, 2008

Click here to bookmark this link.Channel Image22:12 for循环与each的区别» Ruby on Rails: LetRails
for和each的区别主要在于: for是通过调用each实现,因此for更慢一些 for会在each的scope之外创建一个局部变量,这在某些情况下会引发问题 关于第二点,下面的代码可以很好的说明这个问题: ir...
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image13:32 Twitter Updates for 2008-02-14» halostatue
strike one on linkspank.com: they want me to spam ten friends to join them. # aside from the facebook app, what differentiates linkspank from digg or something like that? really? # stuffed up in a major way today. not happy. :( # @objo we’ve got a pot luck today. I brought "hakuna frittata" ;) # Dah duh nuh nah! [...]
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image07:53 Rails框架:组件理念是否重返Rails框架» 天天红玉世界
组件理念是否重返Rails框架
  • 说明
    • 看看什么时候Rails应用程序的根目录下面的目录components开始被使用?还是一直让它空着?

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Sources