def clean_callable(func, config): """Compiles the regexes, moves commands into func.rule, fixes up docs and puts them in func._docs, and sets defaults""" nick = config.core.nick prefix = config.core.prefix help_prefix = config.core.prefix func._docs = {} doc = trim_docstring(func.__doc__) example = None func.unblockable = getattr(func, 'unblockable', True) func.priority = getattr(func, 'priority', 'medium') func.thread = getattr(func, 'thread', True) func.rate = getattr(func, 'rate', 0) if not hasattr(func, 'event'): func.event = ['PRIVMSG'] else: if isinstance(func.event, basestring): func.event = [func.event.upper()] else: func.event = [event.upper() for event in func.event] if hasattr(func, 'rule'): if isinstance(func.rule, basestring): func.rule = [func.rule] func.rule = [compile_rule(nick, rule) for rule in func.rule] if hasattr(func, 'commands'): func.rule = getattr(func, 'rule', []) for command in func.commands: regexp = get_command_regexp(prefix, command) func.rule.append(regexp) if hasattr(func, 'example'): example = func.example[0]["example"] example = example.replace('$nickname', nick) if example[0] != help_prefix: example = help_prefix + example[len(help_prefix):] if doc or example: for command in func.commands: func._docs[command] = (doc, example)
def bind_commands(self): self.commands = {'high': {}, 'medium': {}, 'low': {}} self.scheduler.clear_jobs() def bind(priority, regexp, func): # Function name is no longer used for anything, as far as I know, # but we're going to keep it around anyway. if not hasattr(func, 'name'): func.name = func.__name__ def trim_docstring(doc): """Clean up a docstring""" if not doc: return '' lines = doc.expandtabs().splitlines() indent = sys.maxsize for line in lines[1:]: stripped = line.lstrip() if stripped: indent = min(indent, len(line) - len(stripped)) trimmed = [lines[0].strip()] if indent < sys.maxsize: for line in lines[1:]: trimmed.append(line[indent:].rstrip()) while trimmed and not trimmed[-1]: trimmed.pop() while trimmed and not trimmed[0]: trimmed.pop(0) return '\n'.join(trimmed) doc = trim_docstring(func.__doc__) # At least for now, only account for the first command listed. if hasattr(func, 'commands') and func.commands[0]: example = None if hasattr(func, 'example'): if isinstance(func.example, basestring): # Support old modules that add the attribute directly. example = func.example else: # The new format is a list of dicts. example = func.example[0]["example"] example = example.replace('$nickname', str(self.nick)) if doc or example: self.doc[func.commands[0]] = (doc, example) self.commands[priority].setdefault(regexp, []).append(func) for func in self.callables: if not hasattr(func, 'unblockable'): func.unblockable = False if not hasattr(func, 'priority'): func.priority = 'medium' if not hasattr(func, 'thread'): func.thread = True if not hasattr(func, 'event'): func.event = 'PRIVMSG' else: func.event = func.event.upper() if not hasattr(func, 'rate'): if hasattr(func, 'commands'): func.rate = 0 else: func.rate = 0 if hasattr(func, 'rule'): rules = func.rule if isinstance(rules, basestring): rules = [func.rule] if isinstance(rules, list): for rule in rules: pattern = self.sub(rule) flags = re.IGNORECASE if rule.find("\n") != -1: flags |= re.VERBOSE regexp = re.compile(pattern, flags) bind(func.priority, regexp, func) elif isinstance(func.rule, tuple): # 1) e.g. ('$nick', '(.*)') if len(func.rule) == 2 and isinstance(func.rule[0], str): prefix, pattern = func.rule prefix = self.sub(prefix) regexp = re.compile(prefix + pattern, re.I) bind(func.priority, regexp, func) # 2) e.g. (['p', 'q'], '(.*)') elif len(func.rule) == 2 and \ isinstance(func.rule[0], list): prefix = self.config.core.prefix commands, pattern = func.rule for command in commands: command = r'(%s)\b(?: +(?:%s))?' % ( command, pattern ) regexp = re.compile(prefix + command, re.I) bind(func.priority, regexp, func) # 3) e.g. ('$nick', ['p', 'q'], '(.*)') elif len(func.rule) == 3: prefix, commands, pattern = func.rule prefix = self.sub(prefix) for command in commands: command = r'(%s) +' % command regexp = re.compile( prefix + command + pattern, re.I ) bind(func.priority, regexp, func) if hasattr(func, 'commands'): for command in func.commands: prefix = self.config.core.prefix regexp = get_command_regexp(prefix, command) bind(func.priority, regexp, func) if hasattr(func, 'interval'): for interval in func.interval: job = Willie.Job(interval, func) self.scheduler.add_job(job)
def bind_commands(self): self.commands = {'high': {}, 'medium': {}, 'low': {}} self.scheduler.clear_jobs() def bind(priority, regexp, func): # Function name is no longer used for anything, as far as I know, # but we're going to keep it around anyway. if not hasattr(func, 'name'): func.name = func.__name__ def trim_docstring(doc): """Clean up a docstring""" if not doc: return [] lines = doc.expandtabs().splitlines() indent = sys.maxsize for line in lines[1:]: stripped = line.lstrip() if stripped: indent = min(indent, len(line) - len(stripped)) trimmed = [lines[0].strip()] if indent < sys.maxsize: for line in lines[1:]: trimmed.append(line[indent:].rstrip()) while trimmed and not trimmed[-1]: trimmed.pop() while trimmed and not trimmed[0]: trimmed.pop(0) return trimmed doc = trim_docstring(func.__doc__) if hasattr(func, 'commands') and func.commands[0]: example = None if hasattr(func, 'example'): if isinstance(func.example, basestring): # Support old modules that add the attribute directly. example = func.example else: # The new format is a list of dicts. example = func.example[0]["example"] example = example.replace('$nickname', str(self.nick)) help_prefix = (self.config.core.help_prefix or self.config.core.prefix.strip('\\')) if example[0] != help_prefix: example = help_prefix + example[len(help_prefix):] if doc or example: for command in func.commands: self.doc[command] = (doc, example) self.commands[priority].setdefault(regexp, []).append(func) for func in self.callables: if not hasattr(func, 'unblockable'): func.unblockable = False if not hasattr(func, 'priority'): func.priority = 'medium' if not hasattr(func, 'thread'): func.thread = True if not hasattr(func, 'event'): func.event = ['PRIVMSG'] else: if type(func.event) is not list: func.event = [func.event.upper()] else: func.event = [event.upper() for event in func.event] if not hasattr(func, 'rate'): func.rate = 0 if hasattr(func, 'rule'): rules = func.rule if isinstance(rules, basestring): rules = [func.rule] if isinstance(rules, list): for rule in rules: pattern = self.sub(rule) flags = re.IGNORECASE if rule.find("\n") != -1: flags |= re.VERBOSE regexp = re.compile(pattern, flags) bind(func.priority, regexp, func) elif isinstance(func.rule, tuple): # 1) e.g. ('$nick', '(.*)') if len(func.rule) == 2 and isinstance(func.rule[0], str): prefix, pattern = func.rule prefix = self.sub(prefix) regexp = re.compile(prefix + pattern, re.I) bind(func.priority, regexp, func) # 2) e.g. (['p', 'q'], '(.*)') elif len(func.rule) == 2 and \ isinstance(func.rule[0], list): prefix = self.config.core.prefix commands, pattern = func.rule for command in commands: command = r'(%s)\b(?: +(?:%s))?' % (command, pattern) regexp = re.compile(prefix + command, re.I) bind(func.priority, regexp, func) # 3) e.g. ('$nick', ['p', 'q'], '(.*)') elif len(func.rule) == 3: prefix, commands, pattern = func.rule prefix = self.sub(prefix) for command in commands: command = r'(%s) +' % command regexp = re.compile(prefix + command + pattern, re.I) bind(func.priority, regexp, func) if hasattr(func, 'commands'): for command in func.commands: prefix = self.config.core.prefix regexp = get_command_regexp(prefix, command) bind(func.priority, regexp, func) if hasattr(func, 'interval'): for interval in func.interval: job = Willie.Job(interval, func) self.scheduler.add_job(job)