北大侠客行MUD论坛

 找回密码
 注册
搜索
热搜: 新手 wiki 升级
查看: 12037|回复: 9

MushPy: a Python framework on top of Mushclient's API

[复制链接]
发表于 2010-5-15 11:00:31 | 显示全部楼层 |阅读模式
大家好,我最近写了一个Python框架用于开发Mushclient机器人。这个基于mushclient的api,和mushclient api的区别是,这个是一个更“pythonic”的方法,并且更方便使用。例如,用decorator创建一个trigger:
  1. @Trigger.make("一个regexp", ...):
  2. def callback_function(name,line,wc):
  3.   # ...
  4.   pass
复制代码
再例如,直接用print语句打印到mushclient notepad:
  1. notepad = McTerminal("Title")
  2. print >> notepad, "hello world!"
复制代码
如果替换sys.stdout:
  1. import sys
  2. sys.stdout = McTerminal("standard output")
复制代码
所有的程序,只要print到stdout的,都会被redirect到这个notepad!方便吧!

还有最得意的,python的coroutine,也就是Lua的wait:
  1. @coroutine
  2. def a_coroutine():
  3.   yield
  4.   do_something()
  5.   args, kwargs = yeild ('timer', 0,0,10) # 等待10秒

  6.   args, kwargs = yield ('regexp', '一个触发器')  #触发后继续执行下面的语句!
  7.   # ...
复制代码
原帖看这里: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:
  1. * terminal.py:
  2.     Construct a Python file-like object for the Mushclient's notepads

  3. * objects.py:
  4.     * Trigger
  5.     * Alias
  6.     * Timer

  7. * coroutine.py:
  8.     * 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
=============
  1. Help on class McTerminal in module mushpy.terminals:

  2. class McTerminal
  3. |  Construct a Python file-like object for the Mushclient's notepads.
  4. |  
  5. |  This is an abstraction of Mushclient's notepads for the ease of use in
  6. |  Python. An example is better than thousand words:
  7. |  
  8. |      >>> import sys
  9. |      >>> sys.stdout = McTerminal("Standard Output")
  10. |  
  11. |      >>> print "Hello world"
  12. |  
  13. |  Once sys.stdout is been replace by an McTerminal instance, all codes that
  14. |  write to stdout (print, etc.) will be directed to a Mushclient's notepad
  15. |  titled "Standard Output". Fancy, heh?
  16. |  
  17. |  When instantiating, several keyword options can be used:
  18. |  
  19. |      * time_stamp: (boolean) prefix a time stamp to each line, default to False
  20. |      * prompt_to_save: (boolean) prompt to save on exit, default to False
  21. |      * read_only: (boolean) if the notepad is readonly. default to True
  22. |  
  23. |  An example:
  24. |      
  25. |      >>> notepad = McTerminal( "An McTerminal Example", time_stamp=True, read_only=True )
  26. |      >>> print >> notepad, "Hello world!"
  27. |      >>> print >> notepad, "Yeah! It's so easy to use Mushclient!"
  28. |  
  29. |  The output:
  30. |  
  31. |      05/14/10 22:01:26: Initializing...
  32. |      05/14/10 22:03:41: Hello world!
  33. |      05/14/10 22:03:57: Yeah! It's so easy to use Mushclient!
复制代码
============
Trigger
============
  1. Help on class Trigger in module mushpy.objects:

  2. class Trigger(McObject)
  3. |  The Python wrapper of a trigger representation.
  4. |  
  5. |  This is a thin layer on top of Mushclient's trigger API.
  6. |  
  7. |  The Trigger class only can be instantiate by a name (optional):
  8. |  
  9. |      >> trig = Trigger("trigger_name")
  10. |  
  11. |  or without a name:
  12. |  
  13. |      >> trig = Trigger()
  14. |  
  15. |  One can test if a trigger object has a trigger object exists in Mushclient:
  16. |  
  17. |      >> trig.exists()
  18. |  
  19. |  A trigger w/o name will return False. If a trigger does not exists, one can
  20. |  create one with:
  21. |  
  22. |      >> trig.create( "pattern", group="group_name", one_shot=1, ... )
  23. |  
  24. |  The options are listed in Mushclient's document under SetTriggerOption().
  25. |  
  26. |  If the trigger is instantiated without a name specified, a unique one will
  27. |  be assigned to be when created in Mushclient.
  28. |  
  29. |  If the trigger with the specified name exists, many details about it can be
  30. |  retreived or set, like a Python dict:
  31. |  
  32. |      >> print trig['group']
  33. |      >> print trig['match']
  34. |      >> print trig['enabled']
  35. |      >> print trig['one_shot']
  36. |      >> # ...
  37. |  
  38. |      >> trig['group'] = 'new_group_name'
  39. |      >> trig['enabled'] = 0 # disable
  40. |  
  41. |  Some methods can be used:
  42. |  
  43. |      >>> trig.disable()
  44. |      >>> trig.enable()
  45. |      >>> trig.delete()   # this will delete the underlying mushclient trigger
  46. |  
  47. |  One powerfull feature built beyond Mushclient is the callback function:
  48. |  
  49. |      >>> def func(name, line, wc):
  50. |      ...     pass
  51. |  
  52. |      >>> trig.callback = func
  53. |  
  54. |  Once the trigger is matched, func will be called. Callback can be accessed like an attribute:
  55. |  
  56. |      >>> print trig.callback
  57. |  
  58. |  It can also be deleted:
  59. |  
  60. |      >>> del trig.callback
  61. |  
  62. |  Note that the callback, once set, will overwrite the existing "script"
  63. |  option. Even it is deleted, the original "script" option will not be
  64. |  restored. However, it is more convenient to use callback so that "script"
  65. |  option need not to be set explicitly any more.
  66. |  
  67. |  WARNING: Do not try to modify a trigger's "script" option once a callback
  68. |  is used. Because MushPy uses a global dispatcher to dispatch (invoke)
  69. |  callbacks for all triggers that has a callback registered. In other words,
  70. |  when a callback is set for a trigger, the trigger's "script" option is set
  71. |  to the global dispatcher. Once changed, when the trigger fires, dispatcher
  72. |  will not be invoked, as a result, the desired call back will not be invoked
  73. |  either.
  74. |  
  75. |  On top of the powerfull callback, the decorator is proudly presented:
  76. |  
  77. |      >>> @Trigger.make( "some pattern", group="group_name", one_shot=1, ... )
  78. |      ... def callback( name, line, wc ):
  79. |      ...     pass
  80. |  
  81. |  Therefore, a trigger will be created. The function "callback" will be
  82. |  registered as the trigger's callback.
  83. |  
  84. |  The trigger object is accessible as the callback's attribute. Since a
  85. |  callback function may be used by multiple triggers, multiple aliases, and
  86. |  multiple timers, it has a set, "mc_objects", to store all its connected
  87. |  triggers/aliases/timers.
  88. |  
  89. |      >>> for obj in trig.mc_objects:
  90. |      ...     print obj['name']
复制代码
==============
Alias
==============
  1. Help on class Alias in module mushpy.objects:

  2. class Alias(McObject)
  3. |  The Python wrapper of Mushclient's Alias
  4. |  
  5. |  Usage is the same as Trigger.
复制代码
=============
Timer
=============
  1. Help on class Timer in module mushpy.objects:

  2. class Timer(McObject)
  3. |  Python wrapper of Mushclient's Timer.
  4. |  
  5. |  Usage is similar to Trigger/Alias, with a few exceptions.
  6. |  
  7. |  To instantiate:
  8. |      
  9. |      >>> timer = Timer( hour, minute, second, option1=value1, option2=value2, ... )
  10. |  
  11. |  To use as a decorator
  12. |  
  13. |      >>> @Timer.make( hour, minute, second, [keyword options...] )
  14. |      >>> def callback( name ):
  15. |      ...     pass
复制代码
==============
Coroutine
==============
  1. Help on class coroutine in module mushpy.coroutine:

  2. class coroutine(__builtin__.object)
  3. |  Decorate a callable to use it as a coroutine.
  4. |  
  5. |  Usage:
  6. |      @coroutine()
  7. |      def bla():
  8. |          pass
  9. |  
  10. |  or
  11. |      def bla(): pass
  12. |      bla = coroutine()(bla)
  13. |  
  14. |  To write a coroutine, there is a protocol to follow:
  15. |      
  16. |      1. The decorated callable takes the arguments to generate the
  17. |      generator. If you don't know what it is, just ignore it and use no
  18. |      arguments.
  19. |  
  20. |      2. On the first line of the coroutine, you must use the following yield
  21. |      statement to receive the arguments from the caller.
  22. |  
  23. |          args, kwargs = yield
  24. |  
  25. |      3. Likewise, each time you yield, the return value of the yield
  26. |      statement will be (args, kwargs) from the caller.
  27. |  
  28. |      4. (Feature) You can use the following yields to specify when to resume
  29. |      running the code below the yields:
  30. |  
  31. |          # resume after 5 seconds
  32. |          args, kwargs = yield ('timer', 0,0,5)
  33. |  
  34. |          # resume when the pattern matched
  35. |          args, kwargs = yield ('match', r'some regular expression pattern')
  36. |  
  37. |      5. When the coroutine returns, the caller will receive the return value
  38. |      StopIteration. Otherwise, the caller will always receive the return
  39. |      value None. Since it's not the attemp of a coroutine to return
  40. |      something to the caller, but resume doing something at times, I
  41. |      currently do not plan to provide a protocol for returning a meaningfull
  42. |      value to the caller.
  43. |  
  44. |  An example of using coroutines:
  45. |  
  46. |  @coroutine(arg_to_aCoroutine)
  47. |  def aCoroutine(arg_to_aCoroutine):
  48. |      args, kwargs = yield    # Must have this at the first line
  49. |      print 'arguments of the first call', args, kwargs
  50. |  
  51. |      args, kwargs = yield ('timer', 0,0,3)
  52. |      print '3 seconds have passed. Arguments:', args, kwargs
  53. |  
  54. |      args, kwargs = yield ('match', r'hello world')
  55. |      print 'I see "hello world" from the MUD output. Arguments:', args, kwargs
  56. |  
  57. |      # Coroutine returns here. Caller will receive StopIteration
  58. |      return
复制代码
北大侠客行Mud(pkuxkx.com),最好的中文Mud游戏!
发表于 2010-5-15 11:08:18 | 显示全部楼层
北大侠客行Mud(pkuxkx.com),最好的中文Mud游戏!
发表于 2010-5-15 11:09:48 | 显示全部楼层
支持,顶一个.
高手好多.
可惜,我不会Python
北大侠客行Mud(pkuxkx.com),最好的中文Mud游戏!
发表于 2010-5-15 11:10:17 | 显示全部楼层
膜拜一下大牛
北大侠客行Mud(pkuxkx.com),最好的中文Mud游戏!
发表于 2010-5-15 11:39:02 | 显示全部楼层
北大侠客行Mud(pkuxkx.com),最好的中文Mud游戏!
发表于 2010-5-15 12:11:55 | 显示全部楼层
最好放些简单的demo。
北大侠客行Mud(pkuxkx.com),最好的中文Mud游戏!
发表于 2010-5-15 18:49:18 | 显示全部楼层
后排学习来的
北大侠客行Mud(pkuxkx.com),最好的中文Mud游戏!
 楼主| 发表于 2010-5-15 21:41:08 | 显示全部楼层
原帖由 zgbl 于 2010-5-15 11:39 AM 发表
已转至http://pkuxkx.com/wiki/robot/other


谢谢加精
北大侠客行Mud(pkuxkx.com),最好的中文Mud游戏!
 楼主| 发表于 2010-5-15 21:48:37 | 显示全部楼层

回复 1楼 的帖子

对了。这个package还带有一个测试模块:mushpy.tests

由于时间有限,目前只有测试Trigger的测试程序,希望大家帮我添加更多的测试,完善这个framework。

希望大家能够一起参与进来。
北大侠客行Mud(pkuxkx.com),最好的中文Mud游戏!
发表于 2013-1-12 21:25:42 | 显示全部楼层
我去,chrome继续坑爹中,召唤@nol @seagate 来加精
北大侠客行Mud(pkuxkx.com),最好的中文Mud游戏!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|北大侠客行MUD ( 京ICP备16065414号-1 )

GMT+8, 2024-11-25 02:41 AM , Processed in 0.013594 second(s), 14 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表