6 pyending
= os
.extsep
+ 'py'
8 class error(Exception):
11 class EventStopError(error
):
14 class CommandError(error
):
21 def __init__(self
, **kwargs
):
22 for attr
in kwargs
.items():
25 trigger_sequence
= ("pre", "setup", "on", "setdown", "post")
30 # An event has occurred, the e_name event!
31 def trigger(e_name
, e_data
=None, **kwargs
):
33 e_data
= data(**kwargs
)
35 #print 'Event:', e_name, e_data
40 for e_stage
in trigger_sequence
:
41 if e_stage
in events
[e_name
]:
42 for f_ref
, s_name
in events
[e_name
][e_stage
]:
45 except EventStopError
:
47 except CommandError
, e
:
56 # Stop all processing of the current event now!
60 # Registers a specific function with an event at the given sequence stage.
61 def register(e_name
, e_stage
, f_ref
, s_name
=""):
62 if e_name
not in events
:
65 if e_stage
not in events
[e_name
]:
66 events
[e_name
][e_stage
] = []
68 events
[e_name
][e_stage
] += [(f_ref
, s_name
)]
70 # turn a filename (or module name) and trim it to the name of the module
71 def get_scriptname(name
):
72 s_name
= os
.path
.basename(name
)
73 if s_name
.endswith(pyending
):
74 s_name
= s_name
[:-len(pyending
)]
77 #take a given script name and turn it into a filename
78 def get_filename(name
):
79 # split the directory and filename
80 dirname
= os
.path
.dirname(name
)
81 s_name
= get_scriptname(name
)
83 for path
in dirname
and (dirname
,) or sys
.path
:
84 filename
= os
.path
.join(path
, s_name
+ pyending
)
85 if os
.access(filename
, os
.R_OK
):
88 raise ImportError("No urk script %s found" % name
)
90 # register the events defined by obj
91 def register_all(name
, obj
):
92 # we look through everything defined in the file
94 # for each bit of the event sequence
95 for e_stage
in trigger_sequence
:
97 # if the function is for this bit
98 if f
.startswith(e_stage
):
100 # get a reference to a function
101 f_ref
= getattr(obj
, f
)
103 # normalise to the event name
104 e_name
= f
.replace(e_stage
, "", 1)
106 # add our function to the right event section
107 register(e_name
, e_stage
, f_ref
, name
)
111 #load a .py file into a new module object without affecting sys.modules
112 def load_pyfile(filename
):
113 s_name
= get_scriptname(filename
)
115 module
= imp
.new_module(s_name
)
116 module
.__file
__ = filename
118 # When a module gets collected, everything in its __dict__ gets set to None
119 # We can't let that happen until all the objects that need it are gone
120 # This should protect the module from being collected without __dict__
121 module
.__module
__ = module
123 f
= file(filename
,"U")
127 exec compile(source
, filename
, "exec") in module
.__dict
__
130 # Load a python script and register
131 # the functions defined in it for events.
132 # Return True if we loaded the script, False if it was already loaded
134 s_name
= get_scriptname(name
)
135 filename
= get_filename(name
)
140 loaded
[s_name
] = None
143 loaded
[s_name
] = load_pyfile(filename
)
148 register_all(s_name
, loaded
[s_name
])
152 # Is the script with the given name loaded?
154 return get_scriptname(name
) in loaded
156 # Remove any function which was defined in the given script
158 s_name
= get_scriptname(name
)
162 for e_name
in list(events
):
163 for e_stage
in list(events
[e_name
]):
164 to_check
= events
[e_name
][e_stage
]
166 events
[e_name
][e_stage
] = [(f
, m
) for f
, m
in to_check
if m
!= s_name
]
168 if not events
[e_name
][e_stage
]:
169 del events
[e_name
][e_stage
]
171 if not events
[e_name
]:
175 s_name
= get_scriptname(name
)
177 if s_name
not in loaded
:
180 temp
= loaded
[s_name
]
188 loaded
[s_name
] = temp
189 register_all(s_name
, temp
)
192 def run(text
, window
, network
):
193 split
= text
.split(' ')
195 c_data
= data(name
=split
.pop(0), text
=text
, window
=window
, network
=network
)
197 if split
and split
[0].startswith('-'):
198 c_data
.switches
= set(split
.pop(0)[1:])
200 c_data
.switches
= set()
204 event_name
= "Command" + c_data
.name
.capitalize()
205 if event_name
in events
:
206 result
= trigger(event_name
, c_data
)
209 c_data
.window
.write("* /%s: %s" % (c_data
.name
, result
[0]))
211 trigger("Command", c_data
)
214 c_data
.window
.write("* /%s: No such command exists" % (c_data
.name
))
216 # Script stuff starts here
218 def onCommandPyeval(e
):
219 loc
= sys
.modules
.copy()
220 loc
.update(e
.__dict
__)
221 import pydoc
#fix nonresponsive help() command
222 old_pager
, pydoc
.pager
= pydoc
.pager
, pydoc
.plainpager
224 result
= repr(eval(' '.join(e
.args
), loc
))
225 if 's' in e
.switches
:
227 'say - %s => %s' % (' '.join(e
.args
),result
),
232 e
.window
.write(result
)
234 for line
in traceback
.format_exc().split('\n'):
236 pydoc
.pager
= old_pager
238 def onCommandPyexec(e
):
239 loc
= sys
.modules
.copy()
240 loc
.update(e
.__dict
__)
241 import pydoc
#fix nonresponsive help() command
242 old_pager
, pydoc
.pager
= pydoc
.pager
, pydoc
.plainpager
244 exec ' '.join(e
.args
) in loc
246 for line
in traceback
.format_exc().split('\n'):
248 pydoc
.pager
= old_pager
250 def onCommandLoad(e
):
254 e
.window
.write('Usage: /load scriptname')
258 e
.window
.write("* The script '%s' has been loaded." % name
)
260 raise CommandError("The script is already loaded; use /reload instead")
262 e
.window
.write(traceback
.format_exc(), line_ending
='')
263 raise CommandError("Error loading the script")
265 def onCommandUnload(e
):
269 e
.window
.write('Usage: /unload scriptname')
273 e
.window
.write("* The script '%s' has been unloaded." % name
)
275 raise CommandError("No such script is loaded")
277 def onCommandReload(e
):
281 e
.window
.write('Usage: /reload scriptname')
285 e
.window
.write("* The script '%s' has been reloaded." % name
)
287 raise CommandError("The script isn't loaded yet; use /load instead")
289 e
.window
.write(traceback
.format_exc(), line_ending
='')
291 def onCommandScripts(e
):
292 e
.window
.write("Loaded scripts:")
294 e
.window
.write("* %s" % name
)
296 def onCommandEcho(e
):
297 e
.window
.write(' '.join(e
.args
))
300 for name
in globals():
301 if name
.startswith('onCommand'):
302 register(name
[2:], "on", globals()[name
], '_events')