def func(self): """ Adds the line without any formatting changes. If the editor handles code, it might add automatic indentation. """ caller = self.caller editor = caller.ndb._eveditor buf = editor.get_buffer() # add a line of text to buffer line = self.raw_string.strip("\r\n") if editor._codefunc and editor._indent >= 0: # if automatic indentation is active, add spaces line = editor.deduce_indent(line, buf) buf = line if not buf else buf + "\n%s" % line self.editor.update_buffer(buf) if self.editor._echo_mode: # need to do it here or we will be off one line cline = len(self.editor.get_buffer().split('\n')) if editor._codefunc: # display the current level of identation indent = editor._indent if indent < 0: indent = "off" self.caller.msg("|b%02i|||n (|g%s|n) %s" % ( cline, indent, raw(line))) else: self.caller.msg("|b%02i|||n %s" % (cline, raw(self.args)))
def display_buffer(self, buf=None, offset=0, linenums=True, options={"raw": False}): """ This displays the line editor buffer, or selected parts of it. Args: buf (str, optional): The buffer or part of buffer to display. offset (int, optional): If `buf` is set and is not the full buffer, `offset` should define the actual starting line number, to get the linenum display right. linenums (bool, optional): Show line numbers in buffer. options: raw (bool, optional): Tell protocol to not parse formatting information. """ if buf is None: buf = self._buffer if is_iter(buf): buf = "\n".join(buf) lines = buf.split('\n') nlines = len(lines) nwords = len(buf.split()) nchars = len(buf) sep = self._sep header = "|n" + sep * 10 + "Line Editor [%s]" % self._key + sep * (_DEFAULT_WIDTH - 24 - len(self._key)) footer = "|n" + sep * 10 +\ "[l:%02i w:%03i c:%04i]" % (nlines, nwords, nchars) + sep * 12 + "(:h for help)" + sep * (_DEFAULT_WIDTH - 54) if linenums: main = "\n".join("|b%02i|||n %s" % (iline + 1 + offset, raw(line)) for iline, line in enumerate(lines)) else: main = "\n".join([raw(line) for line in lines]) string = "%s\n%s\n%s" % (header, main, footer) self._caller.msg(string, options=options)
def func(self): """ Adds the line without any formatting changes. If the editor handles code, it might add automatic indentation. """ caller = self.caller editor = caller.ndb._eveditor buf = editor.get_buffer() # add a line of text to buffer line = self.raw_string.strip("\r\n") if editor._codefunc and editor._indent >= 0: # if automatic indentation is active, add spaces line = editor.deduce_indent(line, buf) buf = line if not buf else buf + "\n%s" % line self.editor.update_buffer(buf) if self.editor._echo_mode: # need to do it here or we will be off one line cline = len(self.editor.get_buffer().split('\n')) if editor._codefunc: # display the current level of identation indent = editor._indent if indent < 0: indent = "off" self.caller.msg("|b%02i|||n (|g%s|n) %s" % (cline, indent, raw(line))) else: self.caller.msg("|b%02i|||n %s" % (cline, raw(self.args)))
def handle_error(self, callback, trace): """ Handle an error in a callback. Args: callback (dict): the callback representation. trace (list): the traceback containing the exception. Notes: This method can be useful to override to change the default handling of errors. By default, the error message is sent to the character who last updated the callback, if connected. If not, display to the everror channel. """ callback_name = callback["name"] number = callback["number"] obj = callback["obj"] oid = obj.id logger.log_err("An error occurred during the callback {} of " "{} (#{}), number {}\n{}".format( callback_name, obj, oid, number + 1, "\n".join(trace))) # Create the error message line = "|runknown|n" lineno = "|runknown|n" for error in trace: if error.startswith(' File "<string>", line '): res = RE_LINE_ERROR.search(error) if res: lineno = int(res.group(1)) # Try to extract the line try: line = raw(callback["code"].splitlines()[lineno - 1]) except IndexError: continue else: break exc = raw(trace[-1].strip("\n").splitlines()[-1]) err_msg = "Error in {} of {} (#{})[{}], line {}:" \ " {}\n{}".format(callback_name, obj, oid, number + 1, lineno, line, exc) # Inform the last updater if connected updater = callback.get("updated_by") if updater is None: updater = callback["created_by"] if updater and updater.sessions.all(): updater.msg(err_msg) else: err_msg = "Error in {} of {} (#{})[{}], line {}:" \ " {}\n {}".format(callback_name, obj, oid, number + 1, lineno, line, exc) self.ndb.channel.msg(err_msg)
def handle_error(self, callback, trace): """ Handle an error in a callback. Args: callback (dict): the callback representation. trace (list): the traceback containing the exception. Notes: This method can be useful to override to change the default handling of errors. By default, the error message is sent to the character who last updated the callback, if connected. If not, display to the everror channel. """ callback_name = callback["name"] number = callback["number"] obj = callback["obj"] oid = obj.id logger.log_err("An error occurred during the callback {} of " \ "{} (#{}), number {}\n{}".format(callback_name, obj, oid, number + 1, "\n".join(trace))) # Create the error message line = "|runknown|n" lineno = "|runknown|n" for error in trace: if error.startswith(' File "<string>", line '): res = RE_LINE_ERROR.search(error) if res: lineno = int(res.group(1)) # Try to extract the line try: line = raw(callback["code"].splitlines()[lineno - 1]) except IndexError: continue else: break exc = raw(trace[-1].strip("\n").splitlines()[-1]) err_msg = "Error in {} of {} (#{})[{}], line {}:" \ " {}\n{}".format(callback_name, obj, oid, number + 1, lineno, line, exc) # Inform the last updater if connected updater = callback.get("updated_by") if updater is None: updater = callback["created_by"] if updater and updater.sessions.all(): updater.msg(err_msg) else: err_msg = "Error in {} of {} (#{})[{}], line {}:" \ " {}\n {}".format(callback_name, obj, oid, number + 1, lineno, line, exc) self.ndb.channel.msg(err_msg)
def display_buffer(self, buf=None, offset=0, linenums=True, options={"raw": False}): """ This displays the line editor buffer, or selected parts of it. Args: buf (str, optional): The buffer or part of buffer to display. offset (int, optional): If `buf` is set and is not the full buffer, `offset` should define the actual starting line number, to get the linenum display right. linenums (bool, optional): Show line numbers in buffer. options: raw (bool, optional): Tell protocol to not parse formatting information. """ if buf is None: buf = self._buffer if is_iter(buf): buf = "\n".join(buf) lines = buf.split("\n") nlines = len(lines) nwords = len(buf.split()) nchars = len(buf) sep = self._sep header = ( "|n" + sep * 10 + "Line Editor [%s]" % self._key + sep * (_DEFAULT_WIDTH - 24 - len(self._key)) ) footer = ( "|n" + sep * 10 + "[l:%02i w:%03i c:%04i]" % (nlines, nwords, nchars) + sep * 12 + "(:h for help)" + sep * (_DEFAULT_WIDTH - 54) ) if linenums: main = "\n".join( "|b%02i|||n %s" % (iline + 1 + offset, raw(line)) for iline, line in enumerate(lines) ) else: main = "\n".join([raw(line) for line in lines]) string = "%s\n%s\n%s" % (header, main, footer) self._caller.msg(string, options=options)
def add_callback(self): """Add a callback.""" obj = self.obj callback_name = self.callback_name types = self.handler.get_events(obj) # Check that the callback exists if not callback_name.startswith("chain_") and callback_name not in types: self.msg("The callback name {} can't be found in {} of " "typeclass {}.".format(callback_name, obj, type(obj))) return definition = types.get(callback_name, (None, "Chained event.")) description = definition[1] self.msg(raw(description.strip("\n"))) # Open the editor callback = self.handler.add_callback(obj, callback_name, "", self.caller, False, parameters=self.parameters) # Lock this callback right away self.handler.db.locked.append((obj, callback_name, callback["number"])) # Open the editor for this callback self.caller.db._callback = callback EvEditor(self.caller, loadfunc=_ev_load, savefunc=_ev_save, quitfunc=_ev_quit, key="Callback {} of {}".format( callback_name, obj), persistent=True, codefunc=_ev_save)
def format_usage(self): """Return the usage line. Note: This method is present to return the raw-escaped usage line, in order to avoid unintentional color codes. """ return raw(super(UnixCommandParser, self).format_usage())
def format_usage(self): """Return the usage line. Note: This method is present to return the raw-escaped usage line, in order to avoid unintentional color codes. """ return raw(super(UnixCommandParser, self).format_usage())
def format_help(self): """Return the parser help, including its epilog. Note: This method is present to return the raw-escaped help, in order to avoid unintentional color codes. Color codes in the epilog (the command docstring) are supported. """ autohelp = raw(super(UnixCommandParser, self).format_help()) return "\n" + autohelp + "\n" + self.post_help
def format_help(self): """Return the parser help, including its epilog. Note: This method is present to return the raw-escaped help, in order to avoid unintentional color codes. Color codes in the epilog (the command docstring) are supported. """ autohelp = raw(super(UnixCommandParser, self).format_help()) return "\n" + autohelp + "\n" + self.post_help
def privmsg(self, user, channel, msg): """ Called when the connected channel receives a message. Args: user (str): User name sending the message. channel (str): Channel name seeing the message. msg (str): The message arriving from channel. """ if not msg.startswith('***'): user = user.split('!', 1)[0] user = ansi.raw(user) self.data_in("bot_data_in %s@%s: %s" % (user, channel, msg))
def privmsg(self, user, channel, msg): """ Called when the connected channel receives a message. Args: user (str): User name sending the message. channel (str): Channel name seeing the message. msg (str): The message arriving from channel. """ if not msg.startswith('***'): user = user.split('!', 1)[0] user = ansi.raw(user) self.data_in("%s@%s: %s" % (user, channel, msg))
def privmsg(self, user, channel, msg): """ Called when the connected channel receives a message. Args: user (str): User name sending the message. channel (str): Channel name seeing the message. msg (str): The message arriving from channel. """ if channel == self.nickname: # private message user = user.split('!', 1)[0] self.data_in(text=msg, type="privmsg", user=user, channel=channel) elif not msg.startswith('***'): # channel message user = user.split('!', 1)[0] user = ansi.raw(user) self.data_in(text=msg, type="msg", user=user, channel=channel)
def privmsg(self, user, channel, msg): """ Called when the connected channel receives a message. Args: user (str): User name sending the message. channel (str): Channel name seeing the message. msg (str): The message arriving from channel. """ if channel == self.nickname: # private message user = user.split("!", 1)[0] self.data_in(text=msg, type="privmsg", user=user, channel=channel) elif not msg.startswith("***"): # channel message user = user.split("!", 1)[0] user = ansi.raw(user) self.data_in(text=msg, type="msg", user=user, channel=channel)
def privmsg(self, user, channel, msg): """ Called when the connected channel receives a message. Also called when this Bot recieves a personal message. Args: user (str): User name sending the message. channel (str): Channel name seeing the message. Or this Bots name if recieving a personal message. msg (str): The message arriving from channel. """ # Respond to private messages with a little bit of information. if channel == self.nickname: user = user.split('!', 1)[0] pm_response = ("This is an Evennia IRC bot connecting from " "'%s'." % settings.SERVERNAME) self.send_privmsg(pm_response, user=user) # We pass regular channel messages to our Account Bot. elif not msg.startswith('***'): user = user.split('!', 1)[0] user = ansi.raw(user) self.data_in(text=msg, type="msg", user=user, channel=channel)
def add_callback(self): """Add a callback.""" obj = self.obj callback_name = self.callback_name types = self.handler.get_events(obj) # Check that the callback exists if not callback_name.startswith( "chain_") and not callback_name in types: self.msg("The callback name {} can't be found in {} of " \ "typeclass {}.".format(callback_name, obj, type(obj))) return definition = types.get(callback_name, (None, "Chained event.")) description = definition[1] self.msg(raw(description.strip("\n"))) # Open the editor callback = self.handler.add_callback(obj, callback_name, "", self.caller, False, parameters=self.parameters) # Lock this callback right away self.handler.db.locked.append((obj, callback_name, callback["number"])) # Open the editor for this callback self.caller.db._callback = callback EvEditor(self.caller, loadfunc=_ev_load, savefunc=_ev_save, quitfunc=_ev_quit, key="Callback {} of {}".format(callback_name, obj), persistent=True, codefunc=_ev_save)
def list_callbacks(self): """Display the list of callbacks connected to the object.""" obj = self.obj callback_name = self.callback_name parameters = self.parameters callbacks = self.handler.get_callbacks(obj) types = self.handler.get_events(obj) if callback_name: # Check that the callback name can be found in this object created = callbacks.get(callback_name) if created is None: self.msg("No callback {} has been set on {}.".format( callback_name, obj)) return if parameters: # Check that the parameter points to an existing callback try: number = int(parameters) - 1 assert number >= 0 callback = callbacks[callback_name][number] except (ValueError, AssertionError, IndexError): self.msg( "The callback {} {} cannot be found in {}.".format( callback_name, parameters, obj)) return # Display the callback's details author = callback.get("author") author = author.key if author else "|gUnknown|n" updated_by = callback.get("updated_by") updated_by = updated_by.key if updated_by else "|gUnknown|n" created_on = callback.get("created_on") created_on = created_on.strftime( "%Y-%m-%d %H:%M:%S") if created_on else "|gUnknown|n" updated_on = callback.get("updated_on") updated_on = updated_on.strftime( "%Y-%m-%d %H:%M:%S") if updated_on else "|gUnknown|n" msg = "Callback {} {} of {}:".format(callback_name, parameters, obj) msg += "\nCreated by {} on {}.".format(author, created_on) msg += "\nUpdated by {} on {}".format(updated_by, updated_on) if self.is_validator: if callback.get("valid"): msg += "\nThis callback is |rconnected|n and active." else: msg += "\nThis callback |rhasn't been|n accepted yet." msg += "\nCallback code:\n" msg += raw(callback["code"]) self.msg(msg) return # No parameter has been specified, display the table of callbacks cols = ["Number", "Author", "Updated", "Param"] if self.is_validator: cols.append("Valid") table = EvTable(*cols, width=78) table.reformat_column(0, align="r") now = datetime.now() for i, callback in enumerate(created): author = callback.get("author") author = author.key if author else "|gUnknown|n" updated_on = callback.get("updated_on") if updated_on is None: updated_on = callback.get("created_on") if updated_on: updated_on = "{} ago".format( time_format((now - updated_on).total_seconds(), 4).capitalize()) else: updated_on = "|gUnknown|n" parameters = callback.get("parameters", "") row = [str(i + 1), author, updated_on, parameters] if self.is_validator: row.append("Yes" if callback.get("valid") else "No") table.add_row(*row) self.msg(unicode(table)) else: names = list(set(list(types.keys()) + list(callbacks.keys()))) table = EvTable("Callback name", "Number", "Description", valign="t", width=78) table.reformat_column(0, width=20) table.reformat_column(1, width=10, align="r") table.reformat_column(2, width=48) for name in sorted(names): number = len(callbacks.get(name, [])) lines = sum( len(e["code"].splitlines()) for e in callbacks.get(name, [])) no = "{} ({})".format(number, lines) description = types.get(name, (None, "Chained event."))[1] description = description.strip("\n").splitlines()[0] table.add_row(name, no, description) self.msg(unicode(table))
def list_callbacks(self): """Display the list of callbacks connected to the object.""" obj = self.obj callback_name = self.callback_name parameters = self.parameters callbacks = self.handler.get_callbacks(obj) types = self.handler.get_events(obj) if callback_name: # Check that the callback name can be found in this object created = callbacks.get(callback_name) if created is None: self.msg("No callback {} has been set on {}.".format(callback_name, obj)) return if parameters: # Check that the parameter points to an existing callback try: number = int(parameters) - 1 assert number >= 0 callback = callbacks[callback_name][number] except (ValueError, AssertionError, IndexError): self.msg("The callback {} {} cannot be found in {}.".format( callback_name, parameters, obj)) return # Display the callback's details author = callback.get("author") author = author.key if author else "|gUnknown|n" updated_by = callback.get("updated_by") updated_by = updated_by.key if updated_by else "|gUnknown|n" created_on = callback.get("created_on") created_on = created_on.strftime("%Y-%m-%d %H:%M:%S") if created_on else "|gUnknown|n" updated_on = callback.get("updated_on") updated_on = updated_on.strftime("%Y-%m-%d %H:%M:%S") if updated_on else "|gUnknown|n" msg = "Callback {} {} of {}:".format(callback_name, parameters, obj) msg += "\nCreated by {} on {}.".format(author, created_on) msg += "\nUpdated by {} on {}".format(updated_by, updated_on) if self.is_validator: if callback.get("valid"): msg += "\nThis callback is |rconnected|n and active." else: msg += "\nThis callback |rhasn't been|n accepted yet." msg += "\nCallback code:\n" msg += raw(callback["code"]) self.msg(msg) return # No parameter has been specified, display the table of callbacks cols = ["Number", "Author", "Updated", "Param"] if self.is_validator: cols.append("Valid") table = EvTable(*cols, width=78) table.reformat_column(0, align="r") now = datetime.now() for i, callback in enumerate(created): author = callback.get("author") author = author.key if author else "|gUnknown|n" updated_on = callback.get("updated_on") if updated_on is None: updated_on = callback.get("created_on") if updated_on: updated_on = "{} ago".format(time_format( (now - updated_on).total_seconds(), 4).capitalize()) else: updated_on = "|gUnknown|n" parameters = callback.get("parameters", "") row = [str(i + 1), author, updated_on, parameters] if self.is_validator: row.append("Yes" if callback.get("valid") else "No") table.add_row(*row) self.msg(unicode(table)) else: names = list(set(list(types.keys()) + list(callbacks.keys()))) table = EvTable("Callback name", "Number", "Description", valign="t", width=78) table.reformat_column(0, width=20) table.reformat_column(1, width=10, align="r") table.reformat_column(2, width=48) for name in sorted(names): number = len(callbacks.get(name, [])) lines = sum(len(e["code"].splitlines()) for e in callbacks.get(name, [])) no = "{} ({})".format(number, lines) description = types.get(name, (None, "Chained event."))[1] description = description.strip("\n").splitlines()[0] table.add_row(name, no, description) self.msg(unicode(table))
def edit_callback(self): """Edit a callback.""" obj = self.obj callback_name = self.callback_name parameters = self.parameters callbacks = self.handler.get_callbacks(obj) types = self.handler.get_events(obj) # If no callback name is specified, display the list of callbacks if not callback_name: self.list_callbacks() return # Check that the callback exists if callback_name not in callbacks: self.msg("The callback name {} can't be found in {}.".format( callback_name, obj)) return # If there's only one callback, just edit it if len(callbacks[callback_name]) == 1: number = 0 callback = callbacks[callback_name][0] else: if not parameters: self.msg("Which callback do you wish to edit? Specify a number.") self.list_callbacks() return # Check that the parameter points to an existing callback try: number = int(parameters) - 1 assert number >= 0 callback = callbacks[callback_name][number] except (ValueError, AssertionError, IndexError): self.msg("The callback {} {} cannot be found in {}.".format( callback_name, parameters, obj)) return # If caller can't edit without validation, forbid editing # others' works if not self.autovalid and callback["author"] is not self.caller: self.msg("You cannot edit this callback created by someone else.") return # If the callback is locked (edited by someone else) if (obj, callback_name, number) in self.handler.db.locked: self.msg("This callback is locked, you cannot edit it.") return self.handler.db.locked.append((obj, callback_name, number)) # Check the definition of the callback definition = types.get(callback_name, (None, "Chained event.")) description = definition[1] self.msg(raw(description.strip("\n"))) # Open the editor callback = dict(callback) self.caller.db._callback = callback EvEditor(self.caller, loadfunc=_ev_load, savefunc=_ev_save, quitfunc=_ev_quit, key="Callback {} of {}".format( callback_name, obj), persistent=True, codefunc=_ev_save)
def edit_callback(self): """Edit a callback.""" obj = self.obj callback_name = self.callback_name parameters = self.parameters callbacks = self.handler.get_callbacks(obj) types = self.handler.get_events(obj) # If no callback name is specified, display the list of callbacks if not callback_name: self.list_callbacks() return # Check that the callback exists if not callback_name in callbacks: self.msg("The callback name {} can't be found in {}.".format( callback_name, obj)) return # If there's only one callback, just edit it if len(callbacks[callback_name]) == 1: number = 0 callback = callbacks[callback_name][0] else: if not parameters: self.msg( "Which callback do you wish to edit? Specify a number.") self.list_callbacks() return # Check that the parameter points to an existing callback try: number = int(parameters) - 1 assert number >= 0 callback = callbacks[callback_name][number] except (ValueError, AssertionError, IndexError): self.msg("The callback {} {} cannot be found in {}.".format( callback_name, parameters, obj)) return # If caller can't edit without validation, forbid editing # others' works if not self.autovalid and callback["author"] is not self.caller: self.msg("You cannot edit this callback created by someone else.") return # If the callback is locked (edited by someone else) if (obj, callback_name, number) in self.handler.db.locked: self.msg("This callback is locked, you cannot edit it.") return self.handler.db.locked.append((obj, callback_name, number)) # Check the definition of the callback definition = types.get(callback_name, (None, "Chained event.")) description = definition[1] self.msg(raw(description.strip("\n"))) # Open the editor callback = dict(callback) self.caller.db._callback = callback EvEditor(self.caller, loadfunc=_ev_load, savefunc=_ev_save, quitfunc=_ev_quit, key="Callback {} of {}".format(callback_name, obj), persistent=True, codefunc=_ev_save)