Thursday, November 15, 2007

how to override google default font-family in firefox

At your /path/to/your/firefox/config/path/chrome/userContent.css file to add this:

@-moz-document domain(google.com)
{
body, td, input, textarea, select {
font-family: sans-serif;
}
}

Sunday, August 19, 2007

Better linux use

$ info coreutils

see, how many command you have known?

Friday, August 10, 2007

Use a Django project in a standalone script

simple in project directory~~
from django.core.management import setup_environ
import settings
setup_environ(settings)

but this didn't work with python console or ipython with error ": Empty module name"

Wednesday, July 18, 2007

Howto: Install and configure LDAP Server (slapd) with TLS in Gentoo

1.1. Install openldap on gentoo

# emerge openldap pam_ldap nss_ldap
# chown ldap:ldap /var/lib/openldap-ldbm /var/lib/openldap-data /var/lib/openldap-slurp

1.2. /etc/openldap/slapd.conf

include /etc/ldap/schema/core.schema
include /etc/ldap/schema/cosine.schema
include /etc/ldap/schema/nis.schema
include /etc/ldap/schema/inetorgperson.schema

### "#echo rootpw `slappasswd -h {SSHA}` >> /etc/openldap/slapd.conf" to generate a password with SSHA crypt

password-hash {SSHA}

# Define SSL and TLS properties
TLSCertificateFile /etc/ssl/ldap.pem
TLSCertificateKeyFile /etc/openldap/ssl/ldap-key.pem
TLSCACertificateFile /etc/ssl/ldap.pem

database bdb # use bdb as backend database
suffix "dc=example, dc=com"
directory /var/lib/openldap-data
rootdn "cn=Manager, dc=example, dc=com"
rootpw {SSHA}ksjdlfjsdlfjslfkjsdlfjl
checkpoint 1024 5

# index
index cn,sn,uid pres,eq,approx,sub
index objectClass eq

# then setup access rules...:
access to attrs=userPassword
by self write
by anonymous auth
by dn.base="cn=Manager,dc=example, dc=com" write
by * none
access to *
by self write
by dn.base="cn=Manager,dc=example,dc=com" write
by * read

1.3. /etc/openldap/ldap.conf

BASE         dc=example, dc=com
URI ldaps://server_host[change it to server]:636/
TLS_REQCERT allow

1.4. Genertate SSL certificate

# cd /etc/ssl
# openssl req -config /etc/ssl/openssl.cnf -new -x509 -nodes -out ldap.pem -keyout /etc/openldap/ssl/ldap-key.pem -days 999999
# chown ldap:ldap /etc/openldap/ssl/ldap.pem

1.5. Modify /etc/conf.d/slapd

OPTS="-h 'ldaps:// ldapi://%2fvar%2frun%2fopenldap%2fslapd.sock'"

1.6. Start slapd

/etc/init.d/slapd start

If success, with this command to test connection, "-d 5" is for debug:

ldapsearch -D "cn=Manager,dc=example,dc=com" -W -d 5

1.7. Autostart slapd service at Systemstart

rc-update slapd default add

1.8. Some issues

  • command "slaptest" for verify slapd.conf
  • if id3entry.bdb not found, try "slapadd"
  • recover DB: db4.3_recover -h .
  • useful log: /var/log/messages

Monday, July 16, 2007

wmctrl

The wmctrl program is a UNIX/Linux command line tool to interact with an EWMH/NetWM compatible X Window Manager.

http://sweb.cz/tripie/utils/wmctrl/

zenity - display GTK+ dialogs

zenity is a program that will display GTK+ dialogs, and return (either in the return code, or on standard output) the users input. This allows you to present information, and ask for information from the user, from all manner of shell scripts.

For example, zenity --question will return either 0 or 1, depending on whether the user pressed OK or Cancel. zenity --entry will output on standard output what the user typed into the text entry field.

Comprehensive documentation is available in the GNOME Help Browser, under GNOME/Utilities.

EXAMPLES

Display a file selector with the title Select a file to remove. The file selected is returned on standard output.


zenity --title="Select a file to remove" --file-selection

Display a text entry dialog with the title Select Host and the text Select the host you would like to flood-ping. The entered text is returned on standard output.


zenity --title "Select Host" --entry --text "Select the host you would like to flood-ping"

Display a dialog, asking Microsoft Windows has been found! Would you like to remove it?. The return code will be 0 (true in shell) if OK is selected, and 1 (false) if Cancel is selected.


zenity --question --title "Alert" --text "Microsoft Windows has been found! Would you like to remove it?"

Show the search results in a list dialog with the title Search Results and the text Finding all header files....


find . -name '*.h' | zenity --title "Search Results" --text "Finding all header files.." --column "Files"

Display a weekly shopping list in a check list dialog with Apples and Oranges pre selected


zenity --list --checklist --column "Buy" --column "Item" TRUE Apples TRUE Oranges FALSE Pears FALSE Toothpaste

Display a progress dialog while searching for all the postscript files in your home directory find `echo $HOME` '*.ps' | zenity --progress --pulsate

http://www.linuxmanpages.com/man1/zenity.1.php

devilspie

Devil’s Pie can be configured to detect windows as they are created, and match the window to a set of rules. If the window matches the rules, it can perform a series of actions on that window.

configuration files are in .devilspie folder, like firefox.ds. Code example:
(if
(is (application_name) "Firefox")
(set_workspace 2)
)
Detail description and syntax here: http://wiki.foosel.net/linux/devilspie


Tabbed rxvt

URxvt.perl-ext-common: default,tabbed
URxvt.tabbed.tab-fg: 12
URxvt.tabbed.tab-bg: 0
URxvt.tabbed.tabbar-fg: 4

Saturday, July 14, 2007

Bash tricks

bash vi keybind:
set -o vi in .bashrc

chinese locale but english console:
LANG="en_US.UTF-8"
LC_CTYPE="zh_CN.UTF-8"
in /etc/environment

custom bash prompt with color:

export TERM=xterm-color

PS1='${debian_chroot:+($debian_chroot)}\[\033[0;35m\]\d - \u@\h:\w\[\033[0;33m\] :: '

in .bashrc

Wednesday, July 11, 2007

Wednesday, July 4, 2007

Determining Current Function Name

# use sys._getframe() -- it returns a frame object, whose attribute
# f_code is a code object, whose attribute co_name is the name:
import sys
this_function_name = sys._getframe().f_code.co_name

# the frame and code objects also offer other useful information:
this_line_number = sys._getframe().f_lineno
this_filename = sys._getframe().f_code.co_filename

# also, by calling sys._getframe(1), you can get this information
# for the *caller* of the current function. So you can package
# this functionality up into your own handy functions:
def whoami():
import sys
return sys._getframe(1).f_code.co_name

me = whoami()

# this uses argument 1, because the call to whoami is now frame 0.
# and similarly:
def callersname():
import sys
return sys._getframe(2).f_code.co_name

him = callersname()

Tuesday, July 3, 2007

RequestContext in Template

def some_view(request):
# ...
return render_to_response('my_template.html',
my_data_dictionary,
context_instance=RequestContext(request))

Here’s what each of the default processors does:

django.core.context_processors.auth

If TEMPLATE_CONTEXT_PROCESSORS contains this processor, every RequestContext will contain these three variables:

  • user — An auth.User instance representing the currently logged-in user (or an AnonymousUser instance, if the client isn’t logged in). See the user authentication docs.

  • messages — A list of messages (as strings) for the currently logged-in user. Behind the scenes, this calls request.user.get_and_delete_messages() for every request. That method collects the user’s messages and deletes them from the database.

    Note that messages are set with user.message_set.create. See the message docs for more.

  • perms — An instance of django.core.context_processors.PermWrapper, representing the permissions that the currently logged-in user has. See the permissions docs.

django.core.context_processors.debug

If TEMPLATE_CONTEXT_PROCESSORS contains this processor, every RequestContext will contain these two variables — but only if your DEBUG setting is set to True and the request’s IP address (request.META['REMOTE_ADDR']) is in the INTERNAL_IPS setting:

  • debugTrue. You can use this in templates to test whether you’re in DEBUG mode.
  • sql_queries — A list of {'sql': ..., 'time': ...} dictionaries, representing every SQL query that has happened so far during the request and how long it took. The list is in order by query.

django.core.context_processors.i18n

If TEMPLATE_CONTEXT_PROCESSORS contains this processor, every RequestContext will contain these two variables:

See the internationalization docs for more.

django.core.context_processors.media

If TEMPLATE_CONTEXT_PROCESSORS contains this processor, every RequestContext will contain a variable MEDIA_URL, providing the value of the MEDIA_URL setting.

django.core.context_processors.request

If TEMPLATE_CONTEXT_PROCESSORS contains this processor, every RequestContext will contain a variable request, which is the current HttpRequest object. Note that this processor is not enabled by default; you’ll have to activate it.

Writing your own context processors

A context processor has a very simple interface: It’s just a Python function that takes one argument, an HttpRequest object, and returns a dictionary that gets added to the template context. Each context processor must return a dictionary.

Custom context processors can live anywhere in your code base. All Django cares about is that your custom context processors are pointed-to by your TEMPLATE_CONTEXT_PROCESSORS setting.


Mixin 和 Plugin

mixin 是统称,我又区分为Mixin和Plugin两种。

Mixin 是增加新东西或与原有的东西合并。比如向一个类增加属性或方法。
Plugin 相当于一个回调函数的扩展,它的调用入口一定是存在于某个方法中。举例来说:

class A(Mixin):
__mixinname__ = 'a'

def __init__(self):
self.initmixin()
#code
self.callplugin('plugin1', args1, args2)
#code
obj = self.execplugin('plugin2', args1, args2, args3)

上面的代码是一个slot class的例子,其中self.callplugin()和self.execplugin()是对于两种不同的Plugin的调用点。

为什么有这个东西的想法就是,我可以使用Mixin的方式将__init__方法替换掉,但可能我的处理代码为了不影响以前的东西仍然要保存许多的原始代码,这样程序看上去很乱。比如,不使用Plugin的方式,类可能为:

class A:
def __init__(self):
code1
code2

这时我发现A需要修改,那么可能需要在code1和code2之间加入一些代码,不使用mixin技术,你一定是要么直接修改A的代码,要么从A派生,不管怎能么样,__init__的代码都会为:

def __init__(self):
code1
newcode
code2

这样code1和code2就需要保留。如果再需要在code1和code2之间加入代码,你又要做这样的工作,要么修改A,要么从A派生,然后保留以前的代码。而采用mixin技术,你只需要在code1与code2之间加入一个插入点,那么A类就基本上不需要修改了。新的代码就使用一个新的Plugin来实现,再增加新的代码就再写一个Plugin就行了。能过Mixin模块将其合成一个Plugin的链。

因为Plugin是处于代码中间的,因此叫这个名字,这与插件的工作方式是一样的。而callplugin和execplugin的调用就是Plugin的接口定义。第一个参数是这个plugin接口的名字,后面是它的参数。而定义Plugin方法时需要按调用接口来定义参数,如上面的plugin1有两个参数,它的某个Plugin定义为:

def myplugin1(a, b):
print a, b
Mixin.setPlugin('a', 'plugin1', myyplugin1)

这样就通过Mixin模块的setPlugin方法将myplugin1与__mixinname__为'a'的plugin调用点为'plugin1'的接口关联起来了。

在执行callplugin和execplugin时不需要传入slot class
的__mixinname__,因为自已知道在调用Plugin时使用哪个slot class的Plugins。

Sunday, July 1, 2007

How to download a whole website?

wget -r http://address

Wednesday, June 27, 2007

setting.py & urls.py for /media/

ADMIN_MEDIA_PREFIX = '/admin_media/'

(r'^media/(?P.*)$', 'django.views.static.serve', {'document_root': '/Users/username/django/django_projects/project_name/media'}),

MEDIA_ROOT = '/Users/username/django/django_projects/project_name/media/'
MEDIA_URL = '/media/'


Monday, June 25, 2007

常用开源协议详细解析

开源在今天的软件业已经很普遍,但开源是否意味着使用者可以对开源后的代码为所欲为呢?答案是否定的.开源运动同样有自己的游戏规则和道德准则.不遵行这些规则不但损害开源运动的健康发展,也会对违规者造成名誉和市场上的损失,更可能陷入法律纠纷和赔偿.
  首先,要对几个概念有所了解:

  1. Contributors 和 Recipients

   Contributors 指的是对某个开源软件或项目提供了代码(包括最初的或者修改过的)发布的人或者实体(团队、公司、组织等),Contributors 按照参与某个软件开源的时间先后,可以分为 an initial Contributor 和 subsequent Contributors .

  Recipients指的是开源软件或项目的获取者,显然,subsequent Contributors 也属于 Recipients之列.

  2. Source Code 和 Object Code

  Source Code 指的是各种语言写成的源代码,通过Source Code,结合文档, 可以了解到整个软件的体系结构及具体到某个功能函数的实现方法等.

  Object Code 指的是Source Code 经过编译之后,生成的类似于“类库”一样的,提供各种接口供他人使用的目标码,按我的理解,它就是像常见的DLL、ActiveX、OCX控件性质的东西.(不知道这样理解对不对)

  分清楚这两个概念的目的在于,有些开源,只发布Object Code ,当然,大多数发布的是Source Code.很多协议也对 “你发布的是哪种Code的时候应该怎样”,有着明确的约束.

  3. Derivative Module 和 Separate Module

  Derivative Module 指的是,依托或包含“最初的”或者“从别人处获取的”开源代码而产生的代码,是原“源代码”的增强(不等于增加)、改善和延续的模块,意为“衍生模块”.

  Separate Module 指的是,参考或借助原“源代码”,开发出的独立的,不包含、不依赖于原“源代码模块”,意为“独立的模块”.理解这两个概念的目的在于,很多协议对涉及到商业发布的时候,会有哪些是衍生的,哪些是独立的,有着明确的商业发布规定.

  现今存在的开源协议很多,而经过Open Source Initiative组织通过批准的开源协议目前有58种.我们在常见的开源协议如BSD, GPL, LGPL,MIT等都是OSI批准的协议.如果要开源自己的代码,最好也是选择这些被批准的开源协议.
  这里我们来看四种最常用的开源协议及它们的适用范围,供那些准备开源或者使用开源产品的开发人员/厂家参考.

  BSD开源协议(Berkeley Software Distribution )

   BSD开源协议是一个给予使用者很大自由的协议.基本上使用者可以“为所欲为”可以自由的使用,修改源代码,也可以将修改后的代码作为开源或者专有软件 再发布.但“为所欲为”的前提当你发布使用了BSD协议的代码,或则以BSD协议代码为基础做二次开发自己的产品时,需要满足三个条件:

  1. 如果再发布的产品中包含源代码,则在源代码中必须带有原来代码中的BSD协议.

  2. 如果再发布的只是二进制类库/软件,则需要在类库/软件的文档和版权声明中包含原来代码中的BSD协议.

  3. 不可以用开源代码的作者/机构名字和原来产品的名字做市场推广.

  其实这几个规则约定的目的也只是达到一个目的:是他人的东西,别人以BSD开源了,你就不能不做任何声明而占为己有,更不能用他人的名义来做商业推广.你只对你自己的东西拥有绝对控制权.

   举个例子,你用开源代码(A)修改或做其他增添之后,产生了产品B,这时候,你对B的控制由你自己决定,你可以用任何协议再开源,也可以闭源商业发布. 但,因为如果B中包含了A或A的一部分(一点都不包含就不叫修改了),那你在B产品的版权声明中,必须有提到你有使用到 A ,并且附带上 A 的开源协议.而且不能做商业推广的时候将B 冠以原开源作者的名义以促进商业推广.

  BSD代码鼓励代码共享,但需要尊重代码作者的著作权.BSD由于允许使用者修改和重新发布代码,也允许使用或在BSD代码上
开发商业软件发布和销售,因此是对商业集成很友好的协议.而很多的公司企业在选用开源产品的时候都首选BSD协议,因为可以完全控制这些第三方的代码,在必要的时候可以修改或者二次开发.

  Apache Licence 2.0

  Apache Licence是著名的非盈利开源组织Apache采用的协议.该协议和BSD类似,同样鼓励代码共享和尊重原作者的著作权,同样允许代码修改,再发布(作为开源或商业软件).需要满足的条件也和BSD类似:

  1. 需要给代码的用户一份Apache Licence

  2. 如果你修改了代码,需要再被修改的文件中说明.

  3. 在延伸的代码中(修改和有源代码衍生的代码中)需要带有原来代码中的协议,商标,专利声明和其他原来作者规定需要包含的说明.

  4. 如果再发布的产品中包含一个Notice文件,则在Notice文件中需要带有Apache Licence.你可以在Notice中增加自己的许可,但不可以表现为对Apache Licence构成更改.

  Apache Licence也是对商业应用友好的许可.使用者也可以在需要的时候修改代码来满足需要并作为开源或商业产品发布/销售.

  GPL (Gun General Public License)vesion 2.0 1991

   我们很熟悉的Linux就是采用了GPL.GPL协议和BSD, Apache Licence等鼓励代码重用的许可很不一样.GPL的出发点是代码的开源/免费使用和引用/修改/衍生代码的开源/免费使用,但不允许修改后和衍生的代 码做为闭源的商业软件发布和销售.这也就是为什么我们能用免费的各种linux,包括商业公司的linux和linux上各种各样的由个人,组织,以及商 业软件公司开发的免费软件了.

  GPL协议的主要内容是只要在一个软件中使用(“使用”指类库引用,修改后的代码或者衍生代码)GPL 协议的产品,则该软件产品必须也采用 GPL协议,既必须也是开源和免费.这就是所谓的“传染性”.GPL协议的产品作为一个单独的产品使用没有任何问题,还可以享受免费的优势.

  由于GPL严格要求使用了GPL类库的软件产品必须使用GPL协议,对于使用GPL协议的开源代码,商业软件或者对代码有保密要求的部门就不适合集成/采用作为类库和二次开发的基础.

  最常见的开源协议,使用它作为授权协议的有大名鼎鼎的 Linux .GPL最显著的两个特点就是网上称为的“病毒性传播”和“不允许闭源的商业发布”.

   所谓的“病毒性传播”,指的是,GPL规定,所有从GPL协议授权的源码衍生出来的(即上面提到的Derivative Module),或者要跟GPL授权的源码混着用的Project,都要遵循GPL协议,就像病毒一样,粘上了关系,就“中毒”了.GPL这样规定的目的 是,保证在GPL协议保护下的产品,不会再受到其他协议或者授权的约束.即让跟GPL有关系的源码都能免费获取.举个例子,如果你的改进的Linux中使 用了GPL授权下的开源模块(也必须使用,你不可能自己重新去做个内核吧,如果做出来了,你也没必要叫Linux了.),那么你整个Linux产品也必须 遵循GPL协议去开源,不能以其他方式去开源发布,更不允许闭源发布.这样一来,就不会出现这样一个Linux--这个功能是GPL协议授权的,可以免费 获取源码,而另外一个功能是其他协议下的,拿不到源码.这点规定对使用或者研究该产品的人来说,是一个极大的便利.

  而“不允许闭源商 业发布”指的是,在GPL授权下,你的软件产品可以商业发布,拿去卖钱,但是在这同时,你也必须将该产品的源码以GPL协议方式开源发布出去,供他人免费 获取.也许有人会迷惑,拿去卖,又同时开源,那谁来买阿?这个产品怎么赚钱呢??这就涉及到开源产品的商业模式的问题了,想了解相关一些信息的话,可以看 看以上我给出链接的一些文章.至于后面,可能会写一篇关于开源项目的商业模式的随笔.

  GPL协议下的商业发布的一个关键点就像 Java 视线论坛的 Robbin所说的,GPL是针对软件源代码的版权,而不是针对软件编译后二进制版本的版权.你有权免费获得软件的源代码,但是你没有权力免费获得软件的 二进制发行版本.GP对软件发行版本唯一的限制就是:你的发行版本必须把完整的源代码一同提供.

  它细节如再发布的时候需要伴随GPL协议等和BSD/Apache等类似.

  LGPL

   LGPL是GPL的一个为主要为类库使用设计的开源协议.和GPL要求任何使用/修改/衍生之GPL类库的的软件必须采用GPL协议不同. LGPL允许商业软件通过类库引用(link)方式使用LGPL类库而不需要开源商业软件的代码.这使得采用LGPL协议的开源代码可以被商业软件作为类 库引用并发布和销售.

  但是如果修改LGPL协议的代码或者衍生,则所有修改的代码,涉及修改部分的额外代码和衍生的代码都必须采用 LGPL协议.因此LGPL协议的开源代码很适合作为第三方类库被商业软件引用,但不适合希望以LGPL协议代码为基础,通过修改和衍生的方式做二次开发 的商业软件采用.

  GPL/LGPL都保障原作者的知识产权,避免有人利用开源代码复制并开发类似的产品.

  CPL(Common Public Liecense) vesion 1.0

  CPL是IBM 提出的并通过了OSI(Open Source Initiative)批准的开源协议.主要用于一些IBM或跟IBM相关的开源软件/项目中.如很著名的Java开发环境 Eclipse 、RIA开发平台Open Laszlo等.

  CPL也是一项对商业应用友好的协议.它允许 Recipients 对源码进行任意的使用、复制、分发、传播、展示、修改以及改后做闭源的二次商业发布,这点跟 BSD 很类似,也属于自由度比较高的开源协议.但是,需要遵循:

  1. 当一个Contributors将源码的整体或部分再次开源发布的时候,必须继续遵循 CPL开源协议来发布,而不能改用其他协议发布.除非你得到了原“源码”Owner 的授权.

  2. CPL协议下,你可以将源码不做任何修改来商业发布.但如果你要将修改后的源码其开源,而且当你再发布的是Object Code的时候,你必须声明它的Source Code 是可以获取的,而且要告知获取方法.

  3. 当你需要将CPL下的源码作为一部分跟其他私有的源码混和着成为一个 Project 发布的时候,你可以将整个Project/Product 以私人的协议发布,但要声明哪一部分代码是CPL下的,而且声明那部分代码继续遵循CPL.

  4. 独立的模块(Separate Module),不需要开源.

Yesky编译

Sunday, June 24, 2007

Disable System Beep

Just add this to /etc/modprobe.d/blacklist

Code:
# turn off the PC speaker
blacklist pcspkr


Or

Add the following to /etc/rc.local:
Code:
for i in 1 2 3 4 5 6
do
setterm -blength 0 > /dev/tty$i
done
Or

vi /etc/rc.local
add this line to the end of your script
just before the exit 0
restart service or computer.

modprobe -r pcspkr
exit 0

Or

Put this command in /etc/profile:
setterm -bfreq 0

svn propset

svn propset svn:keywords "Id" V2EXCore.php


Subversion 中可以使用的 Keyword 包括下面这些。
  • Id
    这是一种综合的格式,例如“$Id: V2EXCore.php 4 2005-10-29 23:08:09Z livid $”。
  • LastChangedDate
    最后被修改的时间,这个属性也可以缩写为 Date。
  • LastChangedBy
    最后修改该源代码文件的用户名,这个属性也可以被缩写为 Author。
  • LastChangedRevision
    最后修订的版本号,这个属性也可以被缩写为 Revision 或者 Rev。
  • HeadURL
    该源代码文件所位于的 Repository 上的绝对 URL 地址,这个属性也可以被缩写为 URL。

Subversion 只会对你明确设置了 Keyword 进行更新,比如如果你对某个源代码文件执行了下面这条指令。
svn propset svn:keywords "Id Date" V2EXCore.php

则在 V2EXCore.php 中所有的 $Id$ 和 $Date$ 都会被替换,而 $Author$ 之类的没有被设置的属性则不会发生替换。

Wednesday, June 20, 2007

Testing Django applications

Doctest

For example:

from django.db import model

class Animal(models.Model):
"""
An animal that knows how to make noise

# Create some animals
>>> lion = Animal.objects.create(name="lion", sound="roar")
>>> cat = Animal.objects.create(name="cat", sound="meow")

# Make 'em speak
>>> lion.speak()
'The lion says "roar"'
>>> cat.speak()
'The cat says "meow"'
"""

name = models.CharField(maxlength=20)
sound = models.CharField(maxlength=20)

def speak(self):
return 'The %s says "%s"' % (self.name, self.sound)

When you run your tests, the test utility will find this docstring, notice that portions of it look like an interactive Python session, and execute those lines while checking that the results match.

For more details about how doctest works, see the standard library documentation for doctest


unittests

Like doctests, Django’s unit tests use a standard library module: unittest. As with doctests, Django’s test runner looks for any unit test cases defined in models.py, or in a tests.py file stored in the application directory.

An equivalent unittest test case for the above example would look like:

import unittest
from myapp.models import Animal

class AnimalTestCase(unittest.TestCase):

def setUp(self):
self.lion = Animal.objects.create(name="lion", sound="roar")
self.cat = Animal.objects.create(name="cat", sound="meow")

def testSpeaking(self):
self.assertEquals(self.lion.speak(), 'The lion says "roar"')
self.assertEquals(self.cat.speak(), 'The cat says "meow"')

When you run your tests, the test utility will find all the test cases (that is, subclasses of unittest.TestCase) in models.py and tests.py, automatically build a test suite out of those test cases, and run that suite.

For more details about unittest, see the standard library unittest documentation.


Testing Tools

To assist in testing various features of your application, Django provides tools that can be used to establish tests and test conditions.


Running tests

Run your tests using your project’s manage.py utility:

$ ./manage.py test

If you only want to run tests for a particular application, add the application name to the command line. For example, if your INSTALLED_APPS contains myproject.polls and myproject.animals, but you only want to run the animals unit tests, run:

$ ./manage.py test animals

When you run your tests, you’ll see a bunch of text flow by as the test database is created and models are initialized. This test database is created from scratch every time you run your tests.

Tuesday, June 19, 2007

Python Inner Classes

Why Python has inner classes at all?
class Outer:
def __init__(self):
self.x = 5

class Inner:
def __init__(self):
self.y = 10

if __name__ == '__main__':
outer = Outer()
inner = outer.Inner()
print outer.x
print inner.y
print inner.x

I've been seeing a pattern where I'd like to be able to create nested class hiearchies like this. Usually it's due to containment. For example, let's say I have a Tools class that can hold a bunch of tool classes like Hammer or Sawsall. Now, I'd like my tool classes to be able to get back at their containing Tools instance. I generally model these classes like this:

class Tools:
def __init__(self):
self.tools = []

def add(tool):
self.tools.append(tool)

class Hammer:
def __init__(self, tools):
self.tools = tools

class Sawsall:
def __init__(self, tools):
self.tools = tools

Okay, so you can see the pattern, right? Each tool class is going to have this tools argument that tells them who their container is. But this doesn't seem right to me. That the tool classes need reference to their container shouldn't have to bother the person using these classes. It seems a bit weird that I would create an Sawsall instance passing a reference to the container I plan to add it to.

tools = Tools()
sawsall = Sawsall(tools)
tools.add(sawsall)

It just looks redundant. Here's how I would like that to read:

tools = Tools
sawsall = tools.Hammer()
tools.add(sawsall)

Now, that's still a little redundant and doesn't seem entirely correct for some reason but I think the container.Class() convention is more clear than the other way. Even without inner classes, we can still get this functionality by adding a Hammer() method to the Tools class:

class Tools:
def Hammer(self):
return Hammer(self)

如何根据已有数据自动产生Model

使用方法非常简单:
在项目目录下的命令行中输入:
python manage.py inspectdb

python manage.py inspectdb > models.py

自动产生models.py文件:

python 代码
  1. class DjangoAdminLog(models.Model):
  2. id = models.IntegerField(primary_key=True)
  3. action_time = models.DateTimeField()
  4. user_id = models.IntegerField()
  5. content_type_id = models.IntegerField(null=True, blank=True)
  6. object_id = models.TextField(blank=True)
  7. object_repr = models.CharField(maxlength=200)
  8. action_flag = models.TextField() # This field type is a guess.
  9. change_message = models.TextField()
  10. class Meta:
  11. db_table = 'django_admin_log'

Focus on creating the public interface — “views”

Philosophy

A view is a “type” of Web page in your Django application that generally serves a specific function and has a specific template. For example, in a weblog application, you might have the following views:

  • Blog homepage — displays the latest few entries.
  • Entry “detail” page — permalink page for a single entry.
  • Year-based archive page — displays all months with entries in the given year.
  • Month-based archive page — displays all days with entries in the given month.
  • Day-based archive page — displays all entries in the given day.
  • Comment action — handles posting comments to a given entry.

In our poll application, we’ll have the following four views:

  • Poll “archive” page — displays the latest few polls.
  • Poll “detail” page — displays a poll question, with no results but with a form to vote.
  • Poll “results” page — displays results for a particular poll.
  • Vote action — handles voting for a particular choice in a particular poll.

In Django, each view is represented by a simple Python function.

Design your URLs

format:
(regular expression, Python callback function [, optional dictionary])

Default URLconf in mysite/urls.py. It also automatically set your ROOT_URLCONF setting (in settings.py) to point at that file:

ROOT_URLCONF = 'mysite.urls'

Time for an example. Edit mysite/urls.py so it looks like this:

from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^polls/$', 'mysite.polls.views.index'),
(r'^polls/(?P\d+)/$', 'mysite.polls.views.detail'), (r'^polls/(?P\d+)/results/$', 'mysite.polls.views.results'), (r'^polls/(?P\d+)/vote/$', 'mysite.polls.views.vote'),
)
The poll_id='23' part comes from (?P\d+). Using parenthesis around a
pattern “captures” the text matched by that pattern and sends it as an argument
to the view function; the ?P defines the name that will be used to
identify the matched pattern; and \d+ is a regular expression to match a sequence of
digits (i.e., a number).

function call with parameter like this: detail(request=, poll_id='23')


Write view

Open the file mysite/app_dir/views.py and put the following Python code in it:

from django.http import HttpResponse

def index(request):
return HttpResponse("Hello, world. You're at the poll index.")

def detail(request, poll_id):
return HttpResponse("You're looking at poll %s." % poll_id)


Each view is responsible for doing one of two things: Returning an HttpResponse
object containing the content for the requested page, or raising an exception
such as Http404. The rest is up to you.

Your view can read records from a database, or not. It can use a template system
such as Django’s — or a third-party Python template system — or not.

It can generate a PDF file, output XML, create a ZIP file on the fly, anything
you want, using whatever Python libraries you want.

All Django wants is that HttpResponse. Or an exception.

from mysite.polls.models import Poll
from django.http import HttpResponse

def index(request):
latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5]
output = ', '.join([p.question for p in latest_poll_list])
return HttpResponse(output)

from django.template import Context, loader
from mysite.polls.models import Poll
from django.http import HttpResponse

def index(request):
latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5]
t = loader.get_template('polls/index.html')
c = Context({
'latest_poll_list': latest_poll_list,
})
return HttpResponse(t.render(c))

Raising 404

Now, let’s tackle the poll detail view — the page that displays the question

for a given poll. Here’s the view:

from django.http import Http404
# ...
def detail(request, poll_id):
try:
p = Poll.objects.get(pk=poll_id)
except Poll.DoesNotExist:
raise Http404
return render_to_response('polls/detail.html', {'poll': p})

A shortcut: get_object_or_404()

It’s a very common idiom to use get() and raise Http404 if the object doesn’t exist. Django provides a shortcut. Here’s the detail() view, rewritten:

from django.shortcuts import render_to_response, get_object_or_404
# ...
def detail(request, poll_id):
p = get_object_or_404(Poll, pk=poll_id)
return render_to_response('polls/detail.html', {'poll': p})

The get_object_or_404() function takes a Django model module as its first argument and an arbitrary number of keyword arguments, which it passes to the module’s get() function. It raises Http404 if the object doesn’t exist.

There’s also a get_list_or_404() function, which works just as get_object_or_404() — except using filter() instead of get(). It raises Http404 if the list is empty.

Simplifying the URLconfs

Take some time to play around with the views and template system. As you edit the URLconf, you may notice there’s a fair bit of redundancy in it:

urlpatterns = patterns('',
(r'^polls/$', 'mysite.polls.views.index'),
(r'^polls/(?P\d+)/$', 'mysite.polls.views.detail'),
(r'^polls/(?P\d+)/results/$', 'mysite.polls.views.results'),
(r'^polls/(?P\d+)/vote/$', 'mysite.polls.views.vote'),
)

Namely, mysite.polls.views is in every callback.

Because this is a common case, the URLconf framework provides a shortcut for common prefixes. You can factor out the common prefixes and add them as the first argument to patterns(), like so:

urlpatterns = patterns('mysite.polls.views',
(r'^polls/$', 'index'),
(r'^polls/(?P\d+)/$', 'detail'),
(r'^polls/(?P\d+)/results/$', 'results'),
(r'^polls/(?P\d+)/vote/$', 'vote'),
)

This is functionally identical to the previous formatting. It’s just a bit tidier.

Decoupling the URLconfs

While we’re at it, we should take the time to decouple our poll-app URLs from our Django project configuration. Django apps are meant to be pluggable — that is, each particular app should be transferrable to another Django installation with minimal fuss.

Our poll app is pretty decoupled at this point, thanks to the strict directory structure that python manage.py startapp created, but one part of it is coupled to the Django settings: The URLconf.

We’ve been editing the URLs in mysite/urls.py, but the URL design of an app is specific to the app, not to the Django installation — so let’s move the URLs within the app directory.

Copy the file mysite/urls.py to mysite/polls/urls.py. Then, change mysite/urls.py to remove the poll-specific URLs and insert an include():

(r'^polls/', include('mysite.polls.urls')),

include(), simply, references another URLconf. Note that the regular expression doesn’t have a $ (end-of-string match character) but has the trailing slash. Whenever Django encounters include(), it chops off whatever part of the URL matched up to that point and sends the remaining string to the included URLconf for further processing.

Here’s what happens if a user goes to “/polls/34/” in this system:

  • Django will find the match at '^polls/'
  • It will strip off the matching text ("polls/") and send the remaining text — "34/" — to the ‘mysite.polls.urls’ urlconf for further processing.

Now that we’ve decoupled that, we need to decouple the ‘mysite.polls.urls’ urlconf by removing the leading “polls/” from each line:

urlpatterns = patterns('mysite.polls.views',
(r'^$', 'index'),
(r'^(?P\d+)/$', 'detail'),
(r'^(?P\d+)/results/$', 'results'),
(r'^(?P\d+)/vote/$', 'vote'),
)

The idea behind include() and URLconf decoupling is to make it easy to plug-and-play URLs. Now that polls are in their own URLconf, they can be placed under “/polls/”, or under “/fun_polls/”, or under “/content/polls/”, or any other URL root, and the app will still work.

All the poll app cares about is its relative URLs, not its absolute URLs.

Activate the admin site

The Django admin site is not activated by default — it’s an opt-in thing. To activate the admin site for your installation, do these three things:

  • Add "django.contrib.admin" to your INSTALLED_APPS setting.
  • Run python manage.py syncdb. Since you have added a new application to INSTALLED_APPS, the database tables need to be updated.
  • Edit your mysite/urls.py file and uncomment the line below “Uncomment this for admin:”. This file is a URLconf; we’ll dig into URLconfs in the next tutorial. For now, all you need to know is that it maps URL roots to applications.
go to “/admin/” on your local domain — e.g., http://127.0.0.1:8000/admin/. You should see the admin’s login screen

class Poll(models.Model):
# ...
class Admin:
pass
class Admin:
fields = (
(None, {'fields': ('question',)}),
('Date information', {'fields': ('pub_date',), 'classes': 'collapse'}),
)


poll = models.ForeignKey(Poll, edit_inline=models.STACKED, num_in_admin=3)

choice = models.CharField(maxlength=200, core=True)
votes = models.IntegerField(core=True)

poll = models.ForeignKey(Poll, edit_inline=models.TABULAR, num_in_admin=3)

Customize the admin change list


class Poll(models.Model):
# ...
class Admin:
# ...
list_display = ('question', 'pub_date')


list_display = ('question', 'pub_date', 'was_published_today')
#was_published_today custom method

def was_published_today(self):
return self.pub_date.date() == datetime.date.today()
was_published_today.short_description = 'Published today?'

list_filter = ['pub_date']
search_fields = ['question']
date_hierarchy = 'pub_date'

detail see: http://www.djangoproject.com/documentation/model-api/

Customize the admin look and feel

Clearly, having “Django administration” and “example.com” at the top of each admin page is ridiculous. It’s just placeholder text.

That’s easy to change, though, using Django’s template system. The Django admin is powered by Django itself, and its interfaces use Django’s own template system. (How meta!)

Open your settings file (mysite/settings.py, remember) and look at the TEMPLATE_DIRS setting. TEMPLATE_DIRS is a tuple of filesystem directories to check when loading Django templates. It’s a search path.

By default, TEMPLATE_DIRS is empty. So, let’s add a line to it, to tell Django where our templates live:

TEMPLATE_DIRS = (
"/home/my_username/mytemplates", # Change this to your own directory.
)

Now copy the template admin/base_site.html from within the default Django admin template directory (django/contrib/admin/templates) into an admin subdirectory of whichever directory you’re using in TEMPLATE_DIRS. For example, if your TEMPLATE_DIRS includes "/home/my_username/mytemplates", as above, then copy django/contrib/admin/templates/admin/base_site.html to /home/my_username/mytemplates/admin/base_site.html. Don’t forget that admin subdirectory.

Then, just edit the file and replace the generic Django text with your own site’s name and URL as you see fit.

Note that any of Django’s default admin templates can be overridden. To override a template, just do the same thing you did with base_site.html — copy it from the default directory into your custom directory, and make changes.

Astute readers will ask: But if TEMPLATE_DIRS was empty by default, how was Django finding the default admin templates? The answer is that, by default, Django automatically looks for a templates/ subdirectory within each app package, for use as a fallback. See the loader types documentation for full information.

Customize the admin index page

On a similar note, you might want to customize the look and feel of the Django admin index page.

By default, it displays all available apps, according to your INSTALLED_APPS setting. But the order in which it displays things is random, and you may want to make significant changes to the layout. After all, the index is probably the most important page of the admin, and it should be easy to use.

The template to customize is admin/index.html. (Do the same as with admin/base_site.html in the previous section — copy it from the default directory to your custom template directory.) Edit the file, and you’ll see it uses a template tag called {% get_admin_app_list as app_list %}. That’s the magic that retrieves every installed Django app. Instead of using that, you can hard-code links to object-specific admin pages in whatever way you think is best.

Django offers another shortcut in this department. Run the command python manage.py adminindex polls to get a chunk of template code for inclusion in the admin index template. It’s a useful starting point.

For full details on customizing the look and feel of the Django admin site in general, see the Django admin CSS guide.

Saturday, June 16, 2007

Begin Django.

Creating a project

run the command django-admin.py startproject mysite. This will create a mysite directory in your current directory.

The development server

Let’s verify this worked. Change into the mysite directory, if you haven’t already, and run the command python manage.py runserver.


Changing the port

By default, the runserver command starts the development server on port 8000. If you want to change the server’s port, pass it as a command-line argument. For instance, this command starts the server on port 8080:

python manage.py runserver 8080

Full docs for the development server are at django-admin documentation.

Now that the server’s running, visit http://127.0.0.1:8000/ with your Web browser. You’ll see a “Welcome to Django” page, in pleasant, light-blue pastel. It worked!


Database setup

Now, edit settings.py. It’s a normal Python module with module-level variables representing Django settings. Change these settings to match your database’s connection parameters:

  • DATABASE_ENGINE — Either ‘postgresql_psycopg2’, ‘mysql’ or ‘sqlite3’. Other backends are also available.
  • DATABASE_NAME — The name of your database, or the full (absolute) path to the database file if you’re using SQLite.
  • DATABASE_USER — Your database username (not used for SQLite).
  • DATABASE_PASSWORD — Your database password (not used for SQLite).
  • DATABASE_HOST — The host your database is on. Leave this as an empty string if your database server is on the same physical machine (not used for SQLite).

sudo aptitude install python-psycopg2


By default, INSTALLED_APPS contains the following apps, all of which come with Django:

  • django.contrib.auth — An authentication system.
  • django.contrib.contenttypes — A framework for content types.
  • django.contrib.sessions — A session framework.
  • django.contrib.sites — A framework for managing multiple sites with one Django installation.

These applications are included by default as a convenience for the common case.

Each of these applications makes use of at least one database table, though, so we need to create the tables in the database before we can use them. To do that, run the following command:

python manage.py syncdb

For the minimalists

Like we said above, the default applications are included for the common case, but not everybody needs them. If you don’t need any or all of them, feel free to comment-out or delete the appropriate line(s) from INSTALLED_APPS before running syncdb. The syncdb command will only create tables for apps in INSTALLED_APPS.

Creating models


Projects vs. apps

What’s the difference between a project and an app? An app is a Web application that does something — e.g., a weblog system, a database of public records or a simple poll app. A project is a collection of configuration and apps for a particular Web site. A project can contain multiple apps. An app can be in multiple projects.


python manage.py startapp polls

Edit the polls/models.py file so it looks like this:

from django.db import models

class Poll(models.Model):
question = models.CharField(maxlength=200)
pub_date = models.DateTimeField('date published')

class Choice(models.Model):
poll = models.ForeignKey(Poll)
choice = models.CharField(maxlength=200)
votes = models.IntegerField()

  • python manage.py sql polls
  • python manage.py validate polls — Checks for any errors in the construction of your models.
  • python manage.py sqlcustom polls — Outputs any custom SQL statements (such as table modifications or constraints) that are defined for the application.
  • python manage.py sqlclear polls — Outputs the necessary DROP TABLE statements for this app, according to which tables already exist in your database (if any).
  • python manage.py sqlindexes polls — Outputs the CREATE INDEX statements for this app.
  • python manage.py sqlall polls — A combination of all the SQL from the ‘sql’, ‘sqlcustom’, and ‘sqlindexes’ commands.

Now, run syncdb again to create those model tables in your database:

python manage.py syncdb
http://www.djangoproject.com/documentation/db-api/


PostgreSQL

一直习惯于Redhat FreeBSD下postgresql的安装,这次用了一台Ubuntu的server,让经典的sudo命令给忽悠了一下,走了几个弯路,特此记下。同时该步骤也可供debian用户参考。

  1. 安装:
    sudo apt-get install postgresql-8.1 #安装8.1版本的pgsql
    sudo /etc/init.d/postgresql-8.1 restart
  2. 添加数据库用户,正是这一条指令让我郁闷——Ubuntu中默认的pgsql安装,postgres用户不能su的,但创建数据库用户必须使用postgres帐户操作,于是就成了:
    sudo -u postgres createuser -P YOURNAME
    强烈建议配置密码,一来为了安全,二来也是为了以后方便配置
  3. 创建用户名对应的数据库
    sudo -u postgres createdb YOURNAME
  4. 登录测试
    psql -U YOURNAME

最后,关于pgsql无法远程访问的问题:修改/etc/postgresql/8.1/main中的“#listen_addresses = 'localhost'”为“listen_addresses = '*‘”重新启动即可

Tuesday, June 5, 2007

split String into Chinese Symbol and English Word.

From Huang, Jiahua

# _zhstr , _asstr 存储 中文,非中文 数组
_zhstr = []
_asstr = []
def _fenzhas(stri):
''' 分开中文和非中文,
存入全局数组 _zhstr , _asstr
'''
global _asstr
global _zhstr
ln = len(stri)
_zhstr = []
_asstr = []
n = 0
m = 0
try:
stri[n] >= u'\u4e00'
except:
return 0
while n < ln:
if stri[n] >= u'\u4e00':
if m==0:_zhstr.append(' ')
_zhstr.append(stri[n])
## print 'z:',stri[n]
m=1
else:
if m==1:_asstr.append(' ')
_asstr.append(stri[n])
## print 'a:',stri[n]
m=2
n+=1

Converter CJK Encoding to Unicode

encc = ""
def zh2unicode(stri):
"""Auto converter encodings to unicode

It will test utf8,gbk,big5,jp,kr to converter"""
global encc
for c in ('utf-8', 'gbk', 'big5', 'jp', 'euc_kr','utf16','utf32'):
encc = c
try:
return stri.decode(c)
except:
pass
encc = 'unk'
return stri

Logitech Mouse 4 Way Scrollbutton.

For Logitech RX300:

Section "InputDevice"
Identifier "Configured Mouse"
Driver "evdev"
Option "Dev Name" "Logitech USB Optical Mouse"
Option "CorePointer"
Option "Device" "/dev/input/event2"
Option "Buttons" "7"
Option "ZAxisMapping" "4 5 6 7"
EndSection

ps: Information of Option "Device" comes from /proc/bus/input/devices

For Logitech RX1000:


Section "InputDevice"
Identifier "Configured Mouse"
Driver "evdev"
Option "Dev Name" "Logitech USB Optical Mouse"
Option "CorePointer"
Option "Buttons" "8"
Option "ZAxisMapping" "4 5 6 7"
Option "Resolution" "1000"
EndSection

Yahei

Use Yahei to default font of Ubuntu.

Ubuntu Guide Feisty Fawn (chinese)

http://wiki.ubuntu.org.cn/index.php?title=Ubuntu:Feisty&variant=zh-cn

http://wiki.ubuntu.org.cn/index.php?title=%E5%BF%AB%E9%80%9F%E8%AE%BE%E7%BD%AE%E6%8C%87%E5%8D%97/FeistyFawn&variant=zh-cn

third party source for libdvdcss2 and w32codecs

sourcelist add:

deb http://medibuntu.sos-sts.com/repo/ feisty free non-free
deb-src http://medibuntu.sos-sts.com/repo/ feisty free non-free
key:
wget -q http://packages.medibuntu.org/medibuntu-key.gpg -O- | sudo apt-key add -
then:
sudo apt-get update
sudo apt-get install w32codecs libdvdcss2

Saturday, June 2, 2007

NvidiaLaptopBinaryDriverSuspend

https://help.ubuntu.com/community/NvidiaLaptopBinaryDriverSuspend

Section "Device"
...
Option "NvAGP" "1"
EndSection

/etc/default/acpi-support
...

# Should we attempt to warm-boot the video hardware on resume?
POST_VIDEO=false

...

Swap and Hibernation problem

Ubunutu uses unique IDs (UUIDs) to identify partitions. The advantage of this is you do not have to differentiate between sda and hda devices. So if upgrading to modern libata drivers will work without having to rewrite hda devices to sda ones.

However feisty seems to have a problem with this naming method and swap partitions on some installations. Do $ sudo free to check if your swap partition is used. If the line with swap it it just returns three times "0", your swap partition is not being used and you are most probably affected by bug 66637. The problem is that your system generates a new UUID for your swap partition on every reboot. Your old settings in the fstab then cannot be used anymore and your system does not use any swap. Without swap hibernate (suspend to disk) does not work either (standby/suspend to RAM still does).

Follow these instructions to fix this

  1. determine your swap with $ sudo fdisk -l. In my case it was /dev/sda2
  2. do mkswap on your swap partition and record the uuid which this command outputs, e.g. $ sudo mkswap /dev/sda2
  3. now use this UUID to put into fstab: Look for the line with the swap partition and replace the old UUID with the new one: $ sudo gedit /etc/fstab
  4. add the same UUID intu your resume file: $ sudo gedit /etc/initramfs-tools/conf.d/resume; the file should only look like this: "RESUME=UUID="
  5. do $ update-initramfs -u
  6. update your grub configuration; edit it with $ sudo gedit /boot/grub/menu.lst and look for the line that says "# defoptions=quiet splash" and change it to "# defoptions=quiet splash resume="
  7. reboot normally. After this test with $ sudo free or with $ swapon -s if your swap is now activated
  8. Now you can test hibernate, too.

Thanks to various people on the bug thread.

Wednesday, May 30, 2007

Bash Shell 快捷键的学习使用

ash Shell 快捷键的学习使用
from DBA notes by Fenng

作者:Fenng 发布在 dbanotes.net

这篇 Bash Shell Shortcuts 的快捷键总结的非常好。值得学习。下面内容大多数是拷贝粘贴与总结.
CTRL 键相关的快捷键:

Ctrl + a - Jump to the start of the line
Ctrl + b - Move back a char
Ctrl + c - Terminate the command //用的最多了吧?
Ctrl + d - Delete from under the cursor
Ctrl + e - Jump to the end of the line
Ctrl + f - Move forward a char
Ctrl + k - Delete to EOL
Ctrl + l - Clear the screen //清屏,类似 clear 命令
Ctrl + r - Search the history backwards //查找历史命令
Ctrl + R - Search the history backwards with multi occurrence
Ctrl + u - Delete backward from cursor // 密码输入错误的时候比较有用
Ctrl + xx - Move between EOL and current cursor position
Ctrl + x @ - Show possible hostname completions
Ctrl + z - Suspend/ Stop the command
补充:
Ctrl + h - 删除当前字符
Ctrl + w - 删除最后输入的单词

ALT 键相关的快捷键:
平时很少用。有些和远程登陆工具冲突。

Alt + < - Move to the first line in the history
Alt + > - Move to the last line in the history
Alt + ? - Show current completion list
Alt + * - Insert all possible completions
Alt + / - Attempt to complete filename
Alt + . - Yank last argument to previous command
Alt + b - Move backward
Alt + c - Capitalize the word
Alt + d - Delete word
Alt + f - Move forward
Alt + l - Make word lowercase
Alt + n - Search the history forwards non-incremental
Alt + p - Search the history backwards non-incremental
Alt + r - Recall command
Alt + t - Move words around
Alt + u - Make word uppercase
Alt + back-space - Delete backward from cursor // SecureCRT 如果没有配置好,这个就很管用了。

其他特定的键绑定:
输入 bind -P 可以查看所有的键盘绑定。这一系列我觉得更为实用。

Here "2T" means Press TAB twice
$ 2T - All available commands(common) //命令行补全,我认为是 Bash 最好用的一点
$ (string)2T - All available commands starting with (string)
$ /2T - Entire directory structure including Hidden one
$ 2T - Only Sub Dirs inside including Hidden one
$ *2T - Only Sub Dirs inside without Hidden one
$ ~2T - All Present Users on system from "/etc/passwd" //第一次见到,很好用
$ $2T - All Sys variables //写Shell脚本的时候很实用
$ @2T - Entries from "/etc/hosts" //第一次见到
$ =2T - Output like ls or dir //好像还不如 ls 快捷
补充:
Esc + T - 交换光标前面的两个单词

很多来自GNU 的 readline 库。另外一份总结也很好

记忆是所有技术人员的敌人。一次要把所有的都记住是不可能的。针对自己的使用习惯,对少数快捷键反复使用,短期内就会有效果。

中文分词模块 from Huang Jiahua

#!/usr/bin/python

# -*- coding: UTF-8 -*-
# Author: Huang Jiahua
# Last modified: 2004-08-25

__revision__ = '0.1'

#切分关键字,要求预先转换为 Unicode 类型
# 分开中文,非中文 -> 按 seps 列表分隔 -> 对中文二元分词 -> 合并 -> 返回数组

import sys
##sys.setappdefaultencoding('utf8')

#分隔关键字列表 seps 设置
seps=[]
seps=[" ","\t","\n","\r",",","<",">","?","!",
";","\#",":",".","'",'"',"(",")","{","}","[","]","|","_","=",
" ",",","?","。","、",""",""","《","》","[","]","!","(",")"]
# Unicode 编码的分隔关键字列表
def _utuni(strr):return unicode(strr,'utf8')
seps=map(_utuni,seps)

##_alkeys={}
_zhkeys={}
_askeys={}
# _zhstr , _asstr 存储 中文,非中文 数组
_zhstr = []
_asstr = []

def _zhsplitkey(stri):
# 对 stri 二元分词法
#存入全局字典 _zhkeys
global _zhkeys
ln = len(stri)
if ln == 1:
return stri
#拆分中文关键字,二元分词法
n = 0
while n < ln-1:
_zhkeys[stri[n]+stri[n+1]] = ''
n = n+1
## return keyy.keys()

def _fenzhas(stri):
# 分开中文和非中文,
# 存入全局数组 _zhstr , _asstr
global _asstr
global _zhstr
ln = len(stri)
_zhstr = []
_asstr = []
n = 0
m = 0
try:
stri[n] >= u'\u4e00'
except:
return 0

while n < ln:
if stri[n] >= u'\u4e00':
if m==0:_zhstr.append(' ')
_zhstr.append(stri[n])
## print 'z:',stri[n]
m=1
else:
if m==1:_asstr.append(' ')
_asstr.append(stri[n])
## print 'a:',stri[n]
m=2
n+=1
## print 'zh:',''.join(_zhstr)
## print 'as:',''.join(_asstr)

def _fenseps(stri):
# 按 seps 列表分隔, 返回分隔后数组
global seps
alkeys={}
n = 0
m = 0
ln=stri.__len__()
while n if stri[n] in seps:
alkeys[stri[m:n]]=''
m=n+1
n+=1
if n>m:alkeys[stri[m:n]]=''
return alkeys.keys()

def splitkey(stri):
"""Split the keys

Split the keys."""
# 接受 str 返回分词后数组
global _zhstr
global _asstr
global _zhkeys
global _askeys
_zhkeys = {}
_askeys = {}
_zhstr = []
_asstr = []
_fenzhas(stri) #分开中文,非中文,存入数组 _zhstr , _asstr
zhstr= _fenseps(''.join(_zhstr))
asstr= _fenseps(''.join(_asstr)) #?
_zhstr = []
_asstr = []
for i in zhstr:
_zhsplitkey(i) #中文分词放入字典 _zhkeys
for i in asstr:
_askeys[i]=''

alkeys = {}
alkeys.update(_zhkeys)
alkeys.update(_askeys)
_zhkeys = {}
_askeys = {}
return alkeys.keys()

if __name__=="__main__":
# 命令行测试
import sys
# sys.setappdefaultencoding('unicode')
enc = sys.stdin.encoding
if len(sys.argv) > 1:
keyy = sys.argv[1]
else:
keyy = sys.stdin.read()
## keyyy = splitkey(keyy.decode(enc))
keyyy = splitkey(keyy.decode('utf8'))
for i in keyyy:
## print i.encode(enc),
print i.encode('utf8'),

Monday, May 28, 2007

FreezePython with QT4

FreezePython -OOc --include-modules=sip --install-dir=dist_linux/dist2 --init-script=ConsoleSetLibPath ingc.py

Sunday, May 27, 2007

How to support input method in KDE/Qt application.

Author: Takumi ASAKI

Sometimes additional code is necessary to support input method in KDE/Qt application. This document will explain what's input method and how to support input method.

What's input method?

Input method is system to help user's keyboard input. Using input method, user can input characters that can not input from keyboard directly, and reduce cost of keyboard input. Input method is necessary for the user wants to input CJK(Chinese, Japanese, and Korean) and other language's characters.

In X Window System, XIM(X Input Method) is standard input method. Qt and KDE support XIM. But XIM is legacy system and lacks some features modern input method should have.

So, the input method systems other than XIM are developing now. IIIMF(Internet Intranet Input Method Framework), UIM(Universal Input Method), and SCIM(Smart Common Input Method platform).

Gtk+ supports these input methods using immodule. Qt supports only XIM. But immodule for Qt project tries to introduce immodule to Qt.

What's immodule?

immodule is plugable module for input method. It supports several input methods and can change input method dynamically.

Original Qt(without immodule patch) supports XIM only. So, user has to use XIM-bridge(ex. htt, uim-xim) when user wants to use the other input method. But with immodule patched Qt, user can use favorite input method directly.

Qt4(next major version of Qt) will take the result of the immodule for Qt project, and support immodule. If developer wants to support input method correct, sometimes some input method related code is necessary.

When do you need writing code to support input method?

case A)

Your application doesn't need input text.

You don't need to do anything.

case B)

Your application need input text. And you use only input widget in KDE or Qt library. (ex. QLineEdit, QTextEdit, and more)

You don't need to do anything. KDE and QT library's input widget supports input method correct. There is no need of additional code.

case C)

Your application need input text. And you want to support keyboard input in your own widget. (ex. kate, konsole, kolourpaint, koffice, and more)

You need writing code to support input method. See next section.

How to support input method in KDE/Qt application.

If you want to support keyboard input in your own widget(case C), you need writing code to support input method.

Step A)

Set inputMethodEnabled property to ture. inputMethodEnabled property can enable/disable input method. And default is false except some input widgets. If your widget accepts input from input method, set it to true using QWidget::setInputMethodEnabled() method.

setInputMethodEnabled( true );

note: Original qt can use input method even when inputMethodEnabled property is false. (original qt ignore this property.) it's bug(maybe) and it confuses user. ( When widget doesn't accept text input(e.g. QLabel, QPushButton), I can open input method's window on that widget. ) So qt with immodule check this property to use input method. If your qt is without immodule, it seems to do not need this step. But this is needed.

Step B)

Set microFocusHint for input method can get position of input place.

When widget shows or moves cursor, you should set microFocusHint using QWidget::setMicroFosucHint().

microFocusHint is a hint that input method get place of input. It's help for input method shows additional information at suitable place when user uses input method.

Step C)

Accpet QKeyEvent's text.

Create your widget's keyPressEvent() event handler. And check QKeyEvent::text() for input method's input.

When QKeyEvent::text() is not empty, widget should accept it as user input.

note: QKeyEvent::text() is used when user uses XIM and OverTheSpot style. If user uses OnTheSpot style or other input method, we can't get input method's input using this way. See Step D).

Step D)

Implement QIMEvent handlers.

Input method's inputs are sent by QIMEvent when user uses input method other than OverTheSpot style XIM.

Please see QIMEvent's document for detail. You should reimplement QWidget::imStartEvent(), QWidget::imComposeEvent(), and QWidget::imEndEvent().

QWidget::imStartEvent()
Remember cursor position to show composing string. (QIMEvent doesn't have it.)
QWidget::imComposeEvent()
Remember composing string(QIMEvent::text()) and cursor position(QIMEvent::cursorPos()) in it and selecting string length(QIMEvent::selectionLength). Then show it as composing(preedit) strings.
QWidget::imEndEvent()
In imEndEvent(), QIMEvent sends final text user commits. Accept QIMEvent::text() as final text.

Maybe that's all of input method support.

Please read and comment it.

Saturday, May 26, 2007

QCoreApplication::setLibraryPaths

void QCoreApplication::setLibraryPaths ( const QStringList & paths ) [static]

Sets the list of directories to search when loading libraries to paths. All existing paths will be deleted and the path list will consist of the paths given in paths.

See also libraryPaths(), addLibraryPath(), removeLibraryPath(), and QLibrary.

Friday, May 25, 2007

GIf support in Windows

(To configure Qt with GIF support, pass -qt-gif to the configure script or check the appropriate option in the graphical installer.)

Tuesday, May 22, 2007

MixIn

MixIn 技术 (感谢 limdou 的介绍)

def MixIn(pyClass, mixInClass):
print "Mix class:",mixInClass, " into: ",pyClass,'\n'
pyClass.__bases__ += (mixInClass,)

class A:
def __init__(self):
self.name = "Class A"
def fun(self):
print self.name

class B:
def __init__(self):
self.name = "Class B"
def add(self, a,b):
print 'function defined in B'
return a + b

obj_a = A()

print obj_a
print dir(obj_a),'\n'

MixIn(A,B)

print obj_a
print dir(obj_a),'\n'

print obj_a.add(3,5)


-----------------------------------------〉
执行结果:

>>>
<__main__.a>
['__doc__', '__init__', '__module__', 'fun', 'name']

Mix class: __main__.B into: __main__.A

<__main__.a>
['__doc__', '__init__', '__module__', 'add', 'fun', 'name']

function defined in B
8

解释一下 MixIn 技术,就是使 一个类成为另一个类的基类, 这样会使 被 MixIn 的那个类具有了新的特性。
在例子程序中, 我们将 B 类 MixIn 进 A 类, 成为 A 的基类,于是, A 类的实例便具有了 B 类的方法(add)


obj_a = A() obj_a 是 类 A 的一个实例

print obj_a <__main__.a>
print dir(obj_a),'\n' ['__doc__', '__init__', '__module__', 'fun', 'name']

MixIn(A,B) 将B MixIn 进 A

print obj_a <__main__.a>

print dir(obj_a),'\n' ['__doc__', '__init__', '__module__', 'add', 'fun', 'name']
注意,这时候,多了一个 add 方法(类B 中定义)

print obj_a.add(3,5) 现在 A 的实例可以使用 B 中的方法了

python中实现Single模式

#!/usr/bin/env python

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

class Singleton:

""" A python singleton """

class __impl:

""" Implementation of the singleton interface """

def spam(self):

""" Test method, return singleton id """

return id(Singleton.__instance)

# storage for the instance reference

__instance = None

def __init__(self):

""" Create singleton instance """

# Check whether we already have an instance

if Singleton.__instance is None:

# Create and remember instance

Singleton.__instance = Singleton.__impl()

# Store instance reference as the only member in the handle

self.__dict__['_Singleton__instance'] = Singleton.__instance

def __getattr__(self, attr):

""" Delegate access to implementation """

return getattr(self.__instance, attr)

def __setattr__(self, attr, value):

""" Delegate access to implementation """

return setattr(self.__instance, attr, value)

class SingletonType(type):

"""Singleton Metaclass"""

def __init__(cls, name, bases, dic):

super(SingletonType, cls).__init__(name, bases, dic)

cls.instance = None

def __call__(cls, *args, **kwargs):

if cls.instance is None:

cls.instance = super(SingletonType, cls).__call__(*args, **kwargs)

return cls.instance

class MyClass:

__metaclass__ = SingletonType

if __name__ == '__main__':

#print dir(MyClass)

ob1 = MyClass()

ob2 = MyClass()

print id(ob1), id(ob2)

#print dir(Singleton)

s1 = Singleton()

s2 = Singleton()

print id(s1), s1.spam()

print id(s2), s2.spam()