2008年05月15日

这是我新挖的一个坑,不过已经填了些土了。它是什么呢?它是我写的一个web framework。怎么连我也造轮呢?记得我以前是更注重向现有框架做贡献的呀。

首先这个框架是一个试验品,或者说是主要是个人使用,因此我将有完全的控制权,这一点很重要。我可以用它学到许多框架的知识。以前只是使用,学习,象学过:cherrypy, Karrigell, snakelets等,不过没有做过什么开发;zope则是我学得最早了,不过也早就放弃了;django投入的精力最多,也开发了不少东西;再后来就是web2py了,不过重用搞得我很不爽,而且有些想法不被认同。但这些更多的还是集中在开发方面,对于框架本身了解有限,这次造轮是一个好机会。

其次用过的框架都有不让人满意的,而且许多观点也不被认同,因此我想信只有自已的才是最好的。就象我当初离开drPython自已创建了UliPad一样,想怎么做怎么么,很爽,这下子变成别人的观点将不被我认同了(是不是有些小人得志的感觉)?不过现实如此,我也很清楚地早就认识到这一点。因此要么你的努力被社区认同,要么另起炉灶,这种例子太多了,不然也不会有这么多的选择。那么django不让我满意的象模板,虽然对设计者友好,但是对程序员不友好,不想细说了。开发还不够简洁,在我写完Django Step by Step教程之后我已经意识到,用它作为入门的还不如使用Karrigell。太多需要知道的。不过这个也不好解决,功能随着复杂,自然会越来越难。而且这种不简洁是与web2py相比的结果。在学了web2py才知道web也可以这样开发,集成在浏览器几乎可以做一切事,自动的ticket,适合程序员的模板系统,自动维护的数据库模块,最少配置开发,约定url规则,这一些与django相比显得很轻巧和方便。如果你看过代码,的确要比django简单,但是说句实话,因为只是个人项目难免代码的风格和技术要逊于django。不过由于设计上不方便重用,url的固定方式,虽然支持routing的修改,但是还是不够方便,因此仍然让我感到遗憾。而web2py的设计上的修改很有可能是对web2py的某种否定,所以在我看来它无法按我满意的方向发展。不过web2py的作者massimo是一个非常让人敬佩的人,非常有创造力和激情。

所以作为尝试,我打算自已做一个框架,也许用在自已的项目中,也许是放在GAE上用。现在已经有一个雏开型了。目前项目地址在 http://mymisc.googlecode.com/svn/trunk/kuaiboo 你可以使用svn将代码取下来。可以说它是一个大杂烩,我目前集中了:

  • Werkzeug 用它来完成框架的搭建,因为它本来就是用来做框架的
  • webob 用来生成Request和Response对象,因为GAE和pylons就使用它。本来我是使用Werkzeug自带的,不过ygao建议我使用webob,好就先用它,不行再换。
  • 模板使用web2py的,不过进行了改造。我还是挺喜欢它可以支持python代码的方式,虽然块结束时要输入pass,不过没关系,可以用来解决使用缩近造成的排版问题。
  • 数据库还没有加,目前打算使用web2py的模块
  • Form处理我将使用我自已写的,不过更接近django的方式
  • URL mapping还没有想太好,目前我是采用Werkzeug的教程的方式,使用了一个@expose在每个输出的view方法前进行修饰。不过这样的做法需要将所有的view模块先导入才可以,不知道会不会影响效率。
  • 处理模式为MVT
  • View目前采用函数方式,正在考虑是否要使用class方式,不过这样一来decorator的方式就用不了了。
  • 组织方式采用django的app方式,你可以在多个app中组织代码,最终形成完整应用。
  • 与webserver交互一方面是支持wsgi标准,另一方面借用了web2py中的cherrypy模块,可以独立部署为服务器,不过只是测了一下,还没有加进去。

还有些没有想到或没有实现的东西,比如:i18n的问题。可能你已经看出,一个框架要关心的事情真是很多。不过我会一点点完善它。有兴趣你可以关注。那么我会在我的Blog上记录对它的修改,因为是个人项目,所以可能修改得随心所欲。当然欢迎你参与和讨论。

这是一篇massimo张贴在raddit上的文章链接,引来许多的评论。不过许多评论是执不赞同意见。有些是对无导入有质疑,有些是对与django比较所使用的例子有质疑,有些则是认为web2py言过其实,有些还认为massimo不愿接受批评。我想不说存在不存在问题(至少我个人认为不导入对于单APP可能是方便的,但是正是由于这一点造成APP间不能互相调用,存在硬伤),但文章的题目就容易引人争论。

每个人都有自已的习惯,习惯接近的则形成部落,但仍然会有自已的想法。所以人群就是分分合合,框架也是一样,有些人喜欢这种,有些人喜欢那种,有些人是喜欢其中一部分。因此当进行比较时,自然要对自已喜欢的进行维护。

这种争论在语言的比较中最为常见。

不过习惯不同,很难说哪个是绝对的好。也许你认为不好,但是别人就能用它做出Cool的东西来,你说到底好不好。关键还是看使用者的水平。只不过不同的框架提供的思路和方便程序不同,可能找一个更符合个人性格的框架会让你学起来和用起来更舒服罢了。

2008年05月12日
  1. I made blue theme as default theme, so you don’t need to set yourself now. And if you want to use it as default color theme, you should remove all the files in conf/stx, including Python.stx.

  2. With this new implemention, there is still a [default_style] session can be configured in config.ini, and here is the options which you can configure now:

    [default_style]
    STC_STYLE_TEXT = u"fore:#8DB0D3"
    STC_STYLE_NUMBER = u"fore:#FF00FF"
    STC_STYLE_STRING = u"fore:#00FF80"
    STC_STYLE_COMMENT = u"italic,fore:#008040"
    STC_STYLE_KEYWORD1 = u"fore:#FFFF00"
    STC_STYLE_KEYWORD2 = u"fore:#AFFFEE"
    STC_STYLE_IDENTIFIER = u"fore:#8DB0D3"
    STC_STYLE_OPERATOR = u"fore:#F0804F"
    STC_STYLE_CHARACTER = u"fore:#E19618"
    STC_STYLE_REGEX = u"fore:#FFFF80"
    STC_STYLE_DEFAULT = u"fore:#FFFFFF,back:#112435,face:%(mono)s,size:%(size)d"
    STC_STYLE_LINENUMBER = u"fore:#FFFFFF,back:#1F4661,face:%(mono)s,size:%(lnsize)d"
    STC_STYLE_CONTROLCHAR = u"fore:#FFFFFF"
    STC_STYLE_BRACELIGHT = u"bold,fore:#FF0000"
    STC_STYLE_BRACEBAD = u"bold,fore:#0000FF"
    STC_STYLE_CARET_FORE = u"fore:#FF0000"
    STC_STYLE_CARETLINE_BACK = u"back:#5F0054"
    STC_STYLE_SELECTION_BACK = u"back:#000080"
    STC_STYLE_FOLDER = u"back:#3476A3"
    STC_STYLE_MARKER = u"fore:#F0804F,back:#FFFFFF"
    STC_STYLE_TAG = u"fore:#15852B"
    STC_STYLE_TAG1 = u"fore:#2CEF50"
    STC_STYLE_TAGKEY = u"fore:#FFFF00"
    STC_STYLE_ATTRNAME = u"fore:#F0804F"
    STC_STYLE_ATTRVALUE = u"fore:#156EB2"
    STC_STYLE_CLASSNAME = u"fore:#BBFF4F"
    STC_STYLE_DEFNAME = u"fore:#4179C5"
    STC_STYLE_LINK = u"fore:#FEFF8F,underline"
    STC_STYLE_STRINGEOL = u"fore:#FF6F82,back:#E0C0E0,eol"

  3. For STC_STYLE_DEFAULT and STC_STYLE_LINENUMBER, you should notice there are string place holderes, and you can set fontname and fontsize in [default] session, just like:

    [default]
    editor_font = "fontname"
    editor_fontsize = 12
    editor_linesize = 10

And of cause you can directly set the fontname and fontsize in STC_STYLE_DEFAULT and STC_STYLE_LINENUMBER. If you don’t directly set fontname and fontsize in style string, then UliPad will use default Mono font and the font size will be 12, linesize will be 10.

So if you want to custom a new theme, but not limit a single language, you should define [default_style] in config.ini, just like above example. And the old white theme you will be:

[default_style]
STC_STYLE_TEXT = "fore:#000000"
STC_STYLE_NUMBER = "fore:#6B238E"
STC_STYLE_STRING = "fore:#2A2AA5"
STC_STYLE_COMMENT = "italic,fore:#238E23,back:#E8FFE8"
STC_STYLE_KEYWORD1 = "bold,fore:#0000FF"
STC_STYLE_KEYWORD2 = "bold,fore:#2F032A"
STC_STYLE_IDENTIFIER = "fore:#000000"
STC_STYLE_OPERATOR = "fore:#000000"
STC_STYLE_CHARACTER = "fore:#9F9F9F"
STC_STYLE_REGEX = "fore:#DB70DB"
STC_STYLE_DEFAULT = "face:%(mono)s,size:%(size)d"
STC_STYLE_LINENUMBER = "back:#AAFFAA,size:%(lnsize)d" #back:#C0C0C0
STC_STYLE_CONTROLCHAR = "fore:#000000" #xxxxxxx
STC_STYLE_BRACELIGHT = "fore:#FF0000,bold" #fore:#0000FF,back:#AAFFAA,bold
STC_STYLE_BRACEBAD = "fore:#0000FF,bold" #fore:#FF0000,back:#FFFF00,bold
STC_STYLE_CARET_FORE = "fore:#FF0000"
STC_STYLE_CARETLINE_BACK = "back:#EEEEEE"
STC_STYLE_SELECTION_BACK = "back:#000080"
STC_STYLE_FOLDER = "back:#FFFFFF"
STC_STYLE_MARKER = "fore:#FFFFFF,back:#000000"
STC_STYLE_TAG = ‘fore:#15852B’
STC_STYLE_TAG1 = ‘fore:#2CEF50′
STC_STYLE_TAGKEY = ‘bold,fore:#0000FF’
STC_STYLE_ATTRNAME = ‘bold,fore:#F0804F’
STC_STYLE_ATTRVALUE = ‘fore:#156EB2′
STC_STYLE_CLASSNAME = "bold,fore:#FF0000"
STC_STYLE_DEFNAME = "bold,fore:#007F7F"
STC_STYLE_LINK = "fore:#0000FF,underline"
STC_STYLE_STRINGEOL = "fore:#000000,back:#E0C0E0,eol" #"fore:#2A2AA5,eol"

Remeber, this setting will only effect default configuration, but not existed *.stx file .

2008年05月11日

具体的代码在: http://code.google.com/p/ulipad/wiki/BlueThemeForPython

而且在UliPad中的最新代码中,你还可以设置Folder Margin的背景色。还可以设置Marker的前景和背景色。关键字分别为: -folercolor 和 -markercolor。

如果你想修改缺省字体,可以设置default的字体。

2008年05月08日

前阵子我已经在GAE上申请成功的一个帐号,因此创建了一个 http://ulipad.appspot.com,不过它是我直接使用GAE的SDK开发的,其中改造了web2py的模板。现在Massimo已经声明web2py的最新版本已经可以支持GAE了,并且给出了一个视频。从视频上看,首先是在本地进行开发,然后部署到GAE上去。下面是我的一个实践的记录。

1. 先从svn中同步成最新的版本。如果你仔细观察,你会看到有app.yaml和cgihandler.py,它们将用来处理wsgi的请求。如果你打开app.yaml,可以看到:

application: web2py
version: 1
api_version: 1
runtime: Python

handlers:
- url: .*
  script: cgihandler.py

很明显,所以有处理都交给cgihandler.py了。因为web2py可以处理静态文件,因此也不需要对静态文件单独配置。

2. 在本地的GAE环境下创建一个开发目录,我起名为web2try。这个开发目录要看你的安装路径的,我是在windows下进行的,路径为C:\Program Files\Google\google_appengine。

3. 将web2py目录下的所有东西导出。我是使用svn的export命令。这样,只保留有用的源码,象.svn之类的东西就没有了。然后再将导出的内容拷贝到web2try目录下。这样看上去基本上就是:

applications/
    __init__.py
gluon/
app.yaml
cgihandler.py
web2py.py

是不是与你的有些不同,没关系,是因为我把认为无用的东西删除了。使用全部的内容,你是可以在本地GAE环境下进行开发的,但是上传时会发现文件非常多。因此我的做法是在另外的目录下进行开发,GAE中只保留上传的内容。在applications下,现在是空的,在我开发好app之后会拷贝过来。web2py在这一点还是好的,每个app是独立的。admin我没有保留,因为在GAE上不能进行写文件操作,所以你无法直接在GAE中使用admin进行开发,所以不要了。examples也不要了,太大了。经过精简后,文件数控制在80左右。

4. 本地开发。这块就不多做介绍了。只强调几点:

a)注意controller中:

response.session_id=None # comment if you want to store sessions

这句话很重要。因为GAE不能写文件,所以这样的话就可以暂时不使用session了。但如果你要写,可能目前还存在问题。

b)如果你需要使用数据库,可以:

from gluon.contrib import gql
db=gql.SQLDB()

其它的基本上就没有什么区别的。不过我还没有试过,所以也不清楚是否存在问题。而且GAE的数据库不是真正的关系数据库,所以有些功能没有,比如查询时没有不等于,like等。而且它还有一些其它的扩展,如Expando模型,可以动态设置属性,还有一些非关系数据的字段类型,如ListProperty等。所以数据库这块要仔细一些。

5. 在本地开发完毕后,将app拷贝到applications目录下。

6. 上传。上传之前请注意检查你的app.yaml中的application名字与你在GAE中创建的app的名字要相同。

不过因为我是在windows下开发,所以遇到了一个问题是关于回车符的。这个问题在邮件列表中得到了解决。

上面就是我的记录,测试的功能还很不完整,可能需要随着使用再慢慢发现。

http://web2try.appspot.com/Form/default/index 是我使用web2py搭建的一个例子,只是一个表格模块的测试,可以看一下。

2008年04月25日

New Features and Changes:

  1. Add php.acp thanks for 魏振 <etggy@163.com>
  2. Replace old snippet with new snippet, more details please see <Snippet Howto>
  3. Binding F5 to editor but not MainFrame, and add F5(Refresh) support in Directory Browser.
  4. Improve Python class browser, threading update, change some icons
  5. Add indent cursor move functionality see <Indent Moving Howto>
  6. Improve threading document modification process, so you can get better efficiency
  7. Introduce meide(http://code.google.com/p/meide) project to simplify the interface creation
  8. Add FNB.FNB_DROPDOWN_TABS_LIST style to EditorCtrl
  9. Change auto file check in Editor on_set_focus event handler
  10. Change DDE to asyncore and asynchat framework
  11. Change preference dialog from notebook to treebook
  12. Add icon set theme support
  13. Add strip line ending when saving functionality option in Preferences
  14. Strip leading space when doing "Run in Shell"
  15. Add auto detect python interpreter in windows platform
  16. Improve ReST document render, and fix the setfocus lost bug when auto modified the html output, thanks a lot to ygao
  17. Change setmenutext to use fix width to set the menu text, replace with ‘t’
  18. Chanage notebook left double click to right double click(enlarge notebook size)
  19. Add search text count in Find & Replace pane
  20. Add line ending mixture check when saving file feature
  21. Improve preference dialog input assistant checkbox process. When you check the first checkbox(Enable input assistant) it’ll automatically toggle other 5 checkboxes.
  22. Change new toolbutton to dropdown toolbutton, and it can remember the last new file type(select new type menu first), then when you select new menu, it’ll create a new file with the last new file type
  23. Improve command search and pairprog plugin caret display process
  24. Add auto new version of UliPad check
  25. Add slice language syntax support
  26. Add auto pop up project setting dialog when adding directory to directoy browser window
  27. Add Open Explorer Window Here menu to editoctrl tab context menu
  28. Add open snippet tool button, change open dirbrowser and open snippet toolbutton to check toolbutton
  29. Change explorer.exe %s as explorer.exe /e, %s in windows platform
  30. Add copy filename to clipboard menu on document area tab context menu
  31. Add wrap text feature, via [Edit]->[Format]->[Wrap Text...]

New Plugins:

  1. canvas_test_plugin, you can directly test DC api
  2. web2py_plugin, supply web2py shell

Bug fix:

  1. Fix webopen twice open bug
  2. Fix editor shortcuts key caption error
  3. Fix if set DROP_DOWN_TABS_LIST style, right arrow will disappear bug
  4. Fix utf-16 convertion bug
  5. Fix mako tag auto complete bug #issue 14
  6. Fix if lines are folded, when goto hiding lines will no effect bug
  7. Fix DDE bug, thanks to LP <liupengf12@gmail.com>
  8. Fix webopen bug, can’t correctly deal with ‘mailto:’
  9. Fix smart tabs bug
  10. Fix copy and paste lineending is not correct bug
  11. Fix tab invisible bug after changing size or changing the page title
  12. Fix template line-ending not match the default line-ending setting
  13. Fix password widget is not Password type widget bug
  14. Fix script filename cannot be unicode(chinese) bug
  15. Fix syntax check exception process bug
  16. Fix ruler bug

 UliPad has ported to code.google.com, so you can visit the new project site at:
http://code.google.com/p/ulipad, and also visit the new svn address. Recommends
using source version.

source version download: http://ulipad.googlecode.com/files/ulipad.3.9.zip
window exe version: http://ulipad.googlecode.com/files/ulipad.3.9.exe

maillist: http://groups.google.com/group/ulipad
ulipad snippets site: http://ulipad.appspot.com (hosted by GAE)

Hope you enjoy it.

2008年04月22日

1. 发送邮件的问题

sender不能为空,必须是创建应用的管理员的邮箱。

2. 如何在有代理的环境下使用appcfg.py来更新项目

先在命令行上设置代理,如:

set http_proxy=username:password@proxy_host:proxy_port

上面是带用户和口令的,如果没有,则形式为:

set http_proxy=proxy_host:proxy_port

3. 使用数据库时,不支持!=操作,没有like, match之类的

4. 打印调试信息,可以使用:

import logging
logging.error(xxx)

sys.stderr.write(str(xxx))
2008年04月21日

可以访问 http://ulipad.appspot.com
可以为ulipad写一些使用技巧之类的,当然也可以写其它的。这是我使用GAE(Google Application Engine)开发的一个小网站。

要求:

1. 必须是gmail用户,且要登录
2. 内容是使用rst格式,支持语法高亮,具体格式见: http://www.djangosnippets.org/snippets/42/
3. 写完后别人不会马上看到,需要由管理员(我)的审核,但自已还可以看到和修改

功能:

1. 一般用户可以添加,可以修改自已写的
2. 管理员可以添加,修改其它用户的,删除,修改发布,允许评论选项

Todo:

1. 完成分类,标签(虽然已经可以输入,但是没有显示,需要增加)

有兴趣可以将你平台积累的ulipad相关的技术,心得放上去让大家分享。

2008年04月18日

今天开发了一个wraptext模块,它可以对文本进行折行处理。详情:

 说明
    本程序用来进行文本的折行处理,支持中文和英文,可以处理Unicode和普通字符串

 参数说明
    text       待处理的文本,可以是unicode或str
    width      处理宽度
    encoding   字符串编码,只当text不是unicode时有效
    cr         换行符,如果为None则自动从文本中判断,自动设定为找到的第一个换
               行符,如果找不到缺省为’\n’,如果不为None,则使用设定的换行符
    indent     非首行缩近量
    firstindent首行缩近量
    skipchar   行首忽略字符,如果存在则在处理前会清除每前开始前有skipchar的文本

 功能描述
  1.支持unicode和非unicode文本,如果为非unicode文本,则会使用encoding指定的编
    码对文本转换为unicode,在返回时,会根据原文本是unicode还是非unicode进行转
    换并输出。
  2.支持段落概念。两个以上连续的回车为段落分隔,其中如果一行只包括空白(空格或
    制表符的行)将视为空行。最终的结果段落间只保存一个空行。如果只存在单个换行
    则相邻的行视为同一段落。支持’\n’, ‘\r\n’, ‘\r’三种形式的换行符。可以自动
    使用文本中的回车符或指定转换后的回车符。
  3.自动处理亚洲文字和半角字符,自动处理空白,多个空白(包括制表符)将自动合并
    成一个。亚洲文字和英文之间以空格分隔。对于亚洲文字中间的空白自动删除。
  4.支持缩近设置,首行缩近和非首行缩近。缩近量可以是数值,则为空格*数值,可以
    是字符串。如果firstindent没有设置将缺省为indent的值。
  5.可以设置每行行首要忽略的字符,如注释行的’#',在处理时将先删除匹配的行首字
    符。

 示例
  msg = ”’中文 中文hello, world”’
  wraptext(msg, 10)

现在代码放在 http://code.google.com/p/pyzh 中。原来它已经有一个模块,不过不满足我的要求,于是自已重新写了一个。

2008年04月11日

这里把我在google app engine中如何实现xml-rpc的处理描述一下:

import cgi
import wsgiref.handlers

from google.appengine.api import users
from google.appengine.ext import webapp

def version():
    return ‘3.9′

class XMLRPC(webapp.RequestHandler):
    def post(self):
        import xmlrpclib
        p, m = xmlrpclib.loads(self.request.body)
        try:
            f = globals().get(m)
            if f and callable(f):
                result = f(*p)
                xml = xmlrpclib.dumps((result,), methodresponse=1)
            else:
                xml = xmlrpclib.dumps(xmlrpclib.Fault(-32400, ’system error: Cannot find or call %s’ % m), methodresponse=1)
        except Exception, e:
            xml = xmlrpclib.dumps(xmlrpclib.Fault(-32400, ’system error: %s’ % e), methodresponse=1)
        self.response.headers['Content-Type'] = ‘text/xml; charset=utf-8′
        self.response.out.write(xml)

def main():
    application = webapp.WSGIApplication(
                                       [('/XMLRPC', XMLRPC)],
                                       debug=True)
    wsgiref.handlers.CGIHandler().run(application)

if __name__ == "__main__":
    main()

类XMLRPC对应/XMLRPC这个url。我的app的地址是: http://ulipad.appspot.com 因此你可以使用 http://ulipad.appspot.com/XMLRPC 来访问XMLRPC类。在XMLRPC类中定义了post方法,xml-rpc要求所有的请求都使用POST方法来传输。这个函数的处理还是挺简单的,首先要得到上传的xml报文,通过self.request.body_file.read()来得到。然后使用xmlrpclib的loads()方法得到对应的参数和方法名。然后在当前的作用域globals()中查找是否存在指定的函数(这块你可以按照需要自行修改),找到后进行执行。然后将结果再以xmlrpc的格式返回,通过使用xmlrpclib.dumps()来转换结果。

app.yaml中配置为:

- url: /XMLRPC
  script: handler_xmlrpc.py

这里文件名为handler_xmlrpc.py.

update: 2008/04/18

修改 self.request.body_file.read() 为 self.request.body