MushPy: a Python framework on top of Mushclient's API
大家好,我最近写了一个Python框架用于开发Mushclient机器人。这个基于mushclient的api,和mushclient api的区别是,这个是一个更“pythonic”的方法,并且更方便使用。例如,用decorator创建一个trigger:@Trigger.make("一个regexp", ...):def callback_function(name,line,wc):
# ...
pass再例如,直接用print语句打印到mushclient notepad:notepad = McTerminal("Title")
print >> notepad, "hello world!"如果替换sys.stdout:import sys
sys.stdout = McTerminal("standard output")所有的程序,只要print到stdout的,都会被redirect到这个notepad!方便吧!
还有最得意的,python的coroutine,也就是Lua的wait:@coroutine
def a_coroutine():
yield
do_something()
args, kwargs = yeild ('timer', 0,0,10) # 等待10秒
args, kwargs = yield ('regexp', '一个触发器')#触发后继续执行下面的语句!
# ...原帖看这里:http://mushclient.com/forum/?id=10283
下载在这里:http://code.google.com/p/mushpy/downloads/list
This is to announce a Python framework for Mushclient's API. It is a
more "Pythonic" way to develop MUD automations. Currently, there are
several modules available:* terminal.py:
Construct a Python file-like object for the Mushclient's notepads
* objects.py:
* Trigger
* Alias
* Timer
* coroutine.py:
* Decorate a callable to use it as a coroutine.The package can be downloaded from here: http://code.google.com/p/mushpy/downloads/list
Package details:
=============
Terminal
=============Help on class McTerminal in module mushpy.terminals:
class McTerminal
|Construct a Python file-like object for the Mushclient's notepads.
|
|This is an abstraction of Mushclient's notepads for the ease of use in
|Python. An example is better than thousand words:
|
| >>> import sys
| >>> sys.stdout = McTerminal("Standard Output")
|
| >>> print "Hello world"
|
|Once sys.stdout is been replace by an McTerminal instance, all codes that
|write to stdout (print, etc.) will be directed to a Mushclient's notepad
|titled "Standard Output". Fancy, heh?
|
|When instantiating, several keyword options can be used:
|
| * time_stamp: (boolean) prefix a time stamp to each line, default to False
| * prompt_to_save: (boolean) prompt to save on exit, default to False
| * read_only: (boolean) if the notepad is readonly. default to True
|
|An example:
|
| >>> notepad = McTerminal( "An McTerminal Example", time_stamp=True, read_only=True )
| >>> print >> notepad, "Hello world!"
| >>> print >> notepad, "Yeah! It's so easy to use Mushclient!"
|
|The output:
|
| 05/14/10 22:01:26: Initializing...
| 05/14/10 22:03:41: Hello world!
| 05/14/10 22:03:57: Yeah! It's so easy to use Mushclient!============
Trigger
============Help on class Trigger in module mushpy.objects:
class Trigger(McObject)
|The Python wrapper of a trigger representation.
|
|This is a thin layer on top of Mushclient's trigger API.
|
|The Trigger class only can be instantiate by a name (optional):
|
| >> trig = Trigger("trigger_name")
|
|or without a name:
|
| >> trig = Trigger()
|
|One can test if a trigger object has a trigger object exists in Mushclient:
|
| >> trig.exists()
|
|A trigger w/o name will return False. If a trigger does not exists, one can
|create one with:
|
| >> trig.create( "pattern", group="group_name", one_shot=1, ... )
|
|The options are listed in Mushclient's document under SetTriggerOption().
|
|If the trigger is instantiated without a name specified, a unique one will
|be assigned to be when created in Mushclient.
|
|If the trigger with the specified name exists, many details about it can be
|retreived or set, like a Python dict:
|
| >> print trig['group']
| >> print trig['match']
| >> print trig['enabled']
| >> print trig['one_shot']
| >> # ...
|
| >> trig['group'] = 'new_group_name'
| >> trig['enabled'] = 0 # disable
|
|Some methods can be used:
|
| >>> trig.disable()
| >>> trig.enable()
| >>> trig.delete() # this will delete the underlying mushclient trigger
|
|One powerfull feature built beyond Mushclient is the callback function:
|
| >>> def func(name, line, wc):
| ... pass
|
| >>> trig.callback = func
|
|Once the trigger is matched, func will be called. Callback can be accessed like an attribute:
|
| >>> print trig.callback
|
|It can also be deleted:
|
| >>> del trig.callback
|
|Note that the callback, once set, will overwrite the existing "script"
|option. Even it is deleted, the original "script" option will not be
|restored. However, it is more convenient to use callback so that "script"
|option need not to be set explicitly any more.
|
|WARNING: Do not try to modify a trigger's "script" option once a callback
|is used. Because MushPy uses a global dispatcher to dispatch (invoke)
|callbacks for all triggers that has a callback registered. In other words,
|when a callback is set for a trigger, the trigger's "script" option is set
|to the global dispatcher. Once changed, when the trigger fires, dispatcher
|will not be invoked, as a result, the desired call back will not be invoked
|either.
|
|On top of the powerfull callback, the decorator is proudly presented:
|
| >>> @Trigger.make( "some pattern", group="group_name", one_shot=1, ... )
| ... def callback( name, line, wc ):
| ... pass
|
|Therefore, a trigger will be created. The function "callback" will be
|registered as the trigger's callback.
|
|The trigger object is accessible as the callback's attribute. Since a
|callback function may be used by multiple triggers, multiple aliases, and
|multiple timers, it has a set, "mc_objects", to store all its connected
|triggers/aliases/timers.
|
| >>> for obj in trig.mc_objects:
| ... print obj['name']==============
Alias
==============Help on class Alias in module mushpy.objects:
class Alias(McObject)
|The Python wrapper of Mushclient's Alias
|
|Usage is the same as Trigger.=============
Timer
=============Help on class Timer in module mushpy.objects:
class Timer(McObject)
|Python wrapper of Mushclient's Timer.
|
|Usage is similar to Trigger/Alias, with a few exceptions.
|
|To instantiate:
|
| >>> timer = Timer( hour, minute, second, option1=value1, option2=value2, ... )
|
|To use as a decorator
|
| >>> @Timer.make( hour, minute, second, )
| >>> def callback( name ):
| ... pass==============
Coroutine
==============Help on class coroutine in module mushpy.coroutine:
class coroutine(__builtin__.object)
|Decorate a callable to use it as a coroutine.
|
|Usage:
| @coroutine()
| def bla():
| pass
|
|or
| def bla(): pass
| bla = coroutine()(bla)
|
|To write a coroutine, there is a protocol to follow:
|
| 1. The decorated callable takes the arguments to generate the
| generator. If you don't know what it is, just ignore it and use no
| arguments.
|
| 2. On the first line of the coroutine, you must use the following yield
| statement to receive the arguments from the caller.
|
| args, kwargs = yield
|
| 3. Likewise, each time you yield, the return value of the yield
| statement will be (args, kwargs) from the caller.
|
| 4. (Feature) You can use the following yields to specify when to resume
| running the code below the yields:
|
| # resume after 5 seconds
| args, kwargs = yield ('timer', 0,0,5)
|
| # resume when the pattern matched
| args, kwargs = yield ('match', r'some regular expression pattern')
|
| 5. When the coroutine returns, the caller will receive the return value
| StopIteration. Otherwise, the caller will always receive the return
| value None. Since it's not the attemp of a coroutine to return
| something to the caller, but resume doing something at times, I
| currently do not plan to provide a protocol for returning a meaningfull
| value to the caller.
|
|An example of using coroutines:
|
|@coroutine(arg_to_aCoroutine)
|def aCoroutine(arg_to_aCoroutine):
| args, kwargs = yield # Must have this at the first line
| print 'arguments of the first call', args, kwargs
|
| args, kwargs = yield ('timer', 0,0,3)
| print '3 seconds have passed. Arguments:', args, kwargs
|
| args, kwargs = yield ('match', r'hello world')
| print 'I see "hello world" from the MUD output. Arguments:', args, kwargs
|
| # Coroutine returns here. Caller will receive StopIteration
| return ttk_00 ttk_00 ttk_00 支持,顶一个.
高手好多.
可惜,我不会Python 膜拜一下大牛 已转至http://pkuxkx.com/wiki/robot/other 最好放些简单的demo。 后排学习来的 原帖由 zgbl 于 2010-5-15 11:39 AM 发表 http://pkuxkx.com/forum/images/common/back.gif
已转至http://pkuxkx.com/wiki/robot/other
谢谢加精
回复 1楼 的帖子
对了。这个package还带有一个测试模块:mushpy.tests由于时间有限,目前只有测试Trigger的测试程序,希望大家帮我添加更多的测试,完善这个framework。
希望大家能够一起参与进来。 我去,chrome继续坑爹中,召唤@nol @seagate 来加精
页:
[1]