Completely rewrote the dispatcher in the command system
This commit is contained in:
		
							parent
							
								
									162dd1eb6f
								
							
						
					
					
						commit
						4635a08f94
					
				
					 7 changed files with 178 additions and 101 deletions
				
			
		
							
								
								
									
										117
									
								
								src/command_system/dispatcher.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								src/command_system/dispatcher.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,117 @@
 | 
				
			||||||
 | 
					# Copyright (c) 2010, Alexander Cherniuk (ts33kr@gmail.com)
 | 
				
			||||||
 | 
					# All rights reserved.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					# modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					# are met:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					#   notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# * Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					#   notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					#   documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Backbone of the command system. Provides smart and controllable
 | 
				
			||||||
 | 
					dispatching mechanism with an auto-discovery functionality. In addition
 | 
				
			||||||
 | 
					to automatic discovery and dispatching, also features manual control
 | 
				
			||||||
 | 
					over the process.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from types import NoneType
 | 
				
			||||||
 | 
					from tools import remove
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					COMMANDS = {}
 | 
				
			||||||
 | 
					CONTAINERS = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def add_host(host):
 | 
				
			||||||
 | 
					    CONTAINERS[host] = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def remove_host(host):
 | 
				
			||||||
 | 
					    remove(CONTAINERS, host)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def add_container(container):
 | 
				
			||||||
 | 
					    for host in container.HOSTS:
 | 
				
			||||||
 | 
					        CONTAINERS[host].append(container)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def remove_container(container):
 | 
				
			||||||
 | 
					    for host in container.HOSTS:
 | 
				
			||||||
 | 
					        remove(CONTAINERS[host], container)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def add_commands(container):
 | 
				
			||||||
 | 
					    commands = COMMANDS.setdefault(container, {})
 | 
				
			||||||
 | 
					    for command in traverse_commands(container):
 | 
				
			||||||
 | 
					        for name in command.names:
 | 
				
			||||||
 | 
					            commands[name] = command
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def remove_commands(container):
 | 
				
			||||||
 | 
					    remove(COMMANDS, container)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def traverse_commands(container):
 | 
				
			||||||
 | 
					    for name in dir(container):
 | 
				
			||||||
 | 
					        attribute = getattr(container, name)
 | 
				
			||||||
 | 
					        if is_command(attribute):
 | 
				
			||||||
 | 
					            yield attribute
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def is_command(attribute):
 | 
				
			||||||
 | 
					    from framework import Command
 | 
				
			||||||
 | 
					    return isinstance(attribute, Command)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def is_root(namespace):
 | 
				
			||||||
 | 
					    metaclass = namespace.get("__metaclass__", NoneType)
 | 
				
			||||||
 | 
					    return issubclass(metaclass, Dispatchable)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_command(host, name):
 | 
				
			||||||
 | 
					    for container in CONTAINERS[host]:
 | 
				
			||||||
 | 
					        command = COMMANDS[container].get(name)
 | 
				
			||||||
 | 
					        if command:
 | 
				
			||||||
 | 
					            return command
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def list_commands(host):
 | 
				
			||||||
 | 
					    for container in CONTAINERS[host]:
 | 
				
			||||||
 | 
					        commands = COMMANDS[container]
 | 
				
			||||||
 | 
					        for name, command in commands.iteritems():
 | 
				
			||||||
 | 
					            yield name, command
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Dispatchable(type):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, name, bases, namespace):
 | 
				
			||||||
 | 
					        parents = super(Dispatchable, self)
 | 
				
			||||||
 | 
					        parents.__init__(name, bases, namespace)
 | 
				
			||||||
 | 
					        if not is_root(namespace):
 | 
				
			||||||
 | 
					            self.dispatch()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def dispatch(self):
 | 
				
			||||||
 | 
					        if self.AUTOMATIC:
 | 
				
			||||||
 | 
					            self.enable()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Host(Dispatchable):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def enable(self):
 | 
				
			||||||
 | 
					        add_host(self)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def disable(self):
 | 
				
			||||||
 | 
					        remove_host(self)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Container(Dispatchable):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def enable(self):
 | 
				
			||||||
 | 
					        add_container(self)
 | 
				
			||||||
 | 
					        add_commands(self)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def disable(self):
 | 
				
			||||||
 | 
					        remove_commands(self)
 | 
				
			||||||
 | 
					        remove_container(self)
 | 
				
			||||||
| 
						 | 
					@ -1,90 +0,0 @@
 | 
				
			||||||
# Copyright (C) 2009-2010  Alexander Cherniuk <ts33kr@gmail.com>
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
# This program is free software: you can redistribute it and/or modify
 | 
					 | 
				
			||||||
# it under the terms of the GNU General Public License as published by
 | 
					 | 
				
			||||||
# the Free Software Foundation, either version 3 of the License, or
 | 
					 | 
				
			||||||
# (at your option) any later version.
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
# This program is distributed in the hope that it will be useful,
 | 
					 | 
				
			||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					 | 
				
			||||||
# GNU General Public License for more details.
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
# You should have received a copy of the GNU General Public License
 | 
					 | 
				
			||||||
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
"""
 | 
					 | 
				
			||||||
The backbone of the command system. Provides automatic dispatching which
 | 
					 | 
				
			||||||
does not require explicit registering commands or containers and remains
 | 
					 | 
				
			||||||
active even after everything is done, so new commands can be added
 | 
					 | 
				
			||||||
during the runtime.
 | 
					 | 
				
			||||||
"""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from types import NoneType
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Dispatcher(type):
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    containers = {}
 | 
					 | 
				
			||||||
    commands = {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @classmethod
 | 
					 | 
				
			||||||
    def register_host(cls, host):
 | 
					 | 
				
			||||||
        cls.containers[host] = []
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @classmethod
 | 
					 | 
				
			||||||
    def register_container(cls, container):
 | 
					 | 
				
			||||||
        for host in container.HOSTS:
 | 
					 | 
				
			||||||
            cls.containers[host].append(container)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @classmethod
 | 
					 | 
				
			||||||
    def register_commands(cls, container):
 | 
					 | 
				
			||||||
        cls.commands[container] = {}
 | 
					 | 
				
			||||||
        for command in cls.traverse_commands(container):
 | 
					 | 
				
			||||||
            for name in command.names:
 | 
					 | 
				
			||||||
                cls.commands[container][name] = command
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @classmethod
 | 
					 | 
				
			||||||
    def get_command(cls, host, name):
 | 
					 | 
				
			||||||
        for container in cls.containers[host]:
 | 
					 | 
				
			||||||
            command = cls.commands[container].get(name)
 | 
					 | 
				
			||||||
            if command:
 | 
					 | 
				
			||||||
                return command
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @classmethod
 | 
					 | 
				
			||||||
    def list_commands(cls, host):
 | 
					 | 
				
			||||||
        for container in cls.containers[host]:
 | 
					 | 
				
			||||||
            commands = cls.commands[container]
 | 
					 | 
				
			||||||
            for name, command in commands.iteritems():
 | 
					 | 
				
			||||||
                yield name, command
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @classmethod
 | 
					 | 
				
			||||||
    def traverse_commands(cls, container):
 | 
					 | 
				
			||||||
        for name in dir(container):
 | 
					 | 
				
			||||||
            attribute = getattr(container, name)
 | 
					 | 
				
			||||||
            if cls.is_command(attribute):
 | 
					 | 
				
			||||||
                yield attribute
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @staticmethod
 | 
					 | 
				
			||||||
    def is_root(ns):
 | 
					 | 
				
			||||||
        metaclass = ns.get('__metaclass__', NoneType)
 | 
					 | 
				
			||||||
        return issubclass(metaclass, Dispatcher)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @staticmethod
 | 
					 | 
				
			||||||
    def is_command(attribute):
 | 
					 | 
				
			||||||
        from framework import Command
 | 
					 | 
				
			||||||
        return isinstance(attribute, Command)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class HostDispatcher(Dispatcher):
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __init__(self, name, bases, ns):
 | 
					 | 
				
			||||||
        if not Dispatcher.is_root(ns):
 | 
					 | 
				
			||||||
            HostDispatcher.register_host(self)
 | 
					 | 
				
			||||||
        super(HostDispatcher, self).__init__(name, bases, ns)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class ContainerDispatcher(Dispatcher):
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __init__(self, name, bases, ns):
 | 
					 | 
				
			||||||
        if not Dispatcher.is_root(ns):
 | 
					 | 
				
			||||||
            ContainerDispatcher.register_container(self)
 | 
					 | 
				
			||||||
            ContainerDispatcher.register_commands(self)
 | 
					 | 
				
			||||||
        super(ContainerDispatcher, self).__init__(name, bases, ns)
 | 
					 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,8 @@ import re
 | 
				
			||||||
from types import FunctionType
 | 
					from types import FunctionType
 | 
				
			||||||
from inspect import getargspec, getdoc
 | 
					from inspect import getargspec, getdoc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from dispatching import Dispatcher, HostDispatcher, ContainerDispatcher
 | 
					from dispatcher import Host, Container
 | 
				
			||||||
 | 
					from dispatcher import get_command, list_commands
 | 
				
			||||||
from mapping import parse_arguments, adapt_arguments
 | 
					from mapping import parse_arguments, adapt_arguments
 | 
				
			||||||
from errors import DefinitionError, CommandError, NoCommandError
 | 
					from errors import DefinitionError, CommandError, NoCommandError
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,8 +33,12 @@ class CommandHost(object):
 | 
				
			||||||
    Command host is a hub between numerous command processors and
 | 
					    Command host is a hub between numerous command processors and
 | 
				
			||||||
    command containers. Aimed to participate in a dispatching process in
 | 
					    command containers. Aimed to participate in a dispatching process in
 | 
				
			||||||
    order to provide clean and transparent architecture.
 | 
					    order to provide clean and transparent architecture.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    The AUTOMATIC class variable, which must be defined by a command
 | 
				
			||||||
 | 
					    host, specifies whether the command host should be automatically
 | 
				
			||||||
 | 
					    dispatched and enabled by the dispatcher or not.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    __metaclass__ = HostDispatcher
 | 
					    __metaclass__ = Host
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CommandContainer(object):
 | 
					class CommandContainer(object):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
| 
						 | 
					@ -41,11 +46,15 @@ class CommandContainer(object):
 | 
				
			||||||
    allowing them to be dispatched and proccessed correctly. Each
 | 
					    allowing them to be dispatched and proccessed correctly. Each
 | 
				
			||||||
    command container may be bound to a one or more command hosts.
 | 
					    command container may be bound to a one or more command hosts.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Bounding is controlled by the HOSTS variable, which must be defined
 | 
					    The AUTOMATIC class variable, which must be defined by a command
 | 
				
			||||||
    in the body of the command container. This variable should contain a
 | 
					    processor, specifies whether the command processor should be
 | 
				
			||||||
    list of hosts to bound to, as a tuple or list.
 | 
					    automatically dispatched and enabled by the dispatcher or not.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Bounding is controlled by the HOSTS class variable, which must be
 | 
				
			||||||
 | 
					    defined by the command container. This variable should contain a
 | 
				
			||||||
 | 
					    sequence of hosts to bound to, as a tuple or list.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    __metaclass__ = ContainerDispatcher
 | 
					    __metaclass__ = Container
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CommandProcessor(object):
 | 
					class CommandProcessor(object):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
| 
						 | 
					@ -126,13 +135,13 @@ class CommandProcessor(object):
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_command(self, name):
 | 
					    def get_command(self, name):
 | 
				
			||||||
        command = Dispatcher.get_command(self.COMMAND_HOST, name)
 | 
					        command = get_command(self.COMMAND_HOST, name)
 | 
				
			||||||
        if not command:
 | 
					        if not command:
 | 
				
			||||||
            raise NoCommandError("Command does not exist", name=name)
 | 
					            raise NoCommandError("Command does not exist", name=name)
 | 
				
			||||||
        return command
 | 
					        return command
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def list_commands(self):
 | 
					    def list_commands(self):
 | 
				
			||||||
        commands = Dispatcher.list_commands(self.COMMAND_HOST)
 | 
					        commands = list_commands(self.COMMAND_HOST)
 | 
				
			||||||
        commands = dict(commands)
 | 
					        commands = dict(commands)
 | 
				
			||||||
        return sorted(set(commands.itervalues()))
 | 
					        return sorted(set(commands.itervalues()))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,6 +41,7 @@ from ..framework import CommandContainer, command, doc
 | 
				
			||||||
from hosts import *
 | 
					from hosts import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Execute(CommandContainer):
 | 
					class Execute(CommandContainer):
 | 
				
			||||||
 | 
					    AUTOMATIC = True
 | 
				
			||||||
    HOSTS = ChatCommands, PrivateChatCommands, GroupChatCommands
 | 
					    HOSTS = ChatCommands, PrivateChatCommands, GroupChatCommands
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DIRECTORY = "~"
 | 
					    DIRECTORY = "~"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,18 +25,18 @@ class ChatCommands(CommandHost):
 | 
				
			||||||
    This command host is bound to the command processor which processes
 | 
					    This command host is bound to the command processor which processes
 | 
				
			||||||
    commands from a chat.
 | 
					    commands from a chat.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    pass
 | 
					    AUTOMATIC = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PrivateChatCommands(CommandHost):
 | 
					class PrivateChatCommands(CommandHost):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    This command host is bound to the command processor which processes
 | 
					    This command host is bound to the command processor which processes
 | 
				
			||||||
    commands from a private chat.
 | 
					    commands from a private chat.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    pass
 | 
					    AUTOMATIC = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class GroupChatCommands(CommandHost):
 | 
					class GroupChatCommands(CommandHost):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    This command host is bound to the command processor which processes
 | 
					    This command host is bound to the command processor which processes
 | 
				
			||||||
    commands from a group chat.
 | 
					    commands from a group chat.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    pass
 | 
					    AUTOMATIC = True
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,6 +43,7 @@ class StandardCommonCommands(CommandContainer):
 | 
				
			||||||
    to all - chat, private chat, group chat.
 | 
					    to all - chat, private chat, group chat.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    AUTOMATIC = True
 | 
				
			||||||
    HOSTS = ChatCommands, PrivateChatCommands, GroupChatCommands
 | 
					    HOSTS = ChatCommands, PrivateChatCommands, GroupChatCommands
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @command
 | 
					    @command
 | 
				
			||||||
| 
						 | 
					@ -164,6 +165,7 @@ class StandardCommonChatCommands(CommandContainer):
 | 
				
			||||||
    to a chat and a private chat only.
 | 
					    to a chat and a private chat only.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    AUTOMATIC = True
 | 
				
			||||||
    HOSTS = ChatCommands, PrivateChatCommands
 | 
					    HOSTS = ChatCommands, PrivateChatCommands
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @command
 | 
					    @command
 | 
				
			||||||
| 
						 | 
					@ -221,6 +223,7 @@ class StandardChatCommands(CommandContainer):
 | 
				
			||||||
    to a chat.
 | 
					    to a chat.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    AUTOMATIC = True
 | 
				
			||||||
    HOSTS = (ChatCommands,)
 | 
					    HOSTS = (ChatCommands,)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class StandardPrivateChatCommands(CommandContainer):
 | 
					class StandardPrivateChatCommands(CommandContainer):
 | 
				
			||||||
| 
						 | 
					@ -229,6 +232,7 @@ class StandardPrivateChatCommands(CommandContainer):
 | 
				
			||||||
    to a private chat.
 | 
					    to a private chat.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    AUTOMATIC = True
 | 
				
			||||||
    HOSTS = (PrivateChatCommands,)
 | 
					    HOSTS = (PrivateChatCommands,)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class StandardGroupChatCommands(CommandContainer):
 | 
					class StandardGroupChatCommands(CommandContainer):
 | 
				
			||||||
| 
						 | 
					@ -237,6 +241,7 @@ class StandardGroupChatCommands(CommandContainer):
 | 
				
			||||||
    to a group chat.
 | 
					    to a group chat.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    AUTOMATIC = True
 | 
				
			||||||
    HOSTS = (GroupChatCommands,)
 | 
					    HOSTS = (GroupChatCommands,)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @command(raw=True)
 | 
					    @command(raw=True)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										35
									
								
								src/command_system/tools.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/command_system/tools.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,35 @@
 | 
				
			||||||
 | 
					# Copyright (c) 2010, Alexander Cherniuk (ts33kr@gmail.com)
 | 
				
			||||||
 | 
					# All rights reserved.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					# modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					# are met:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					#   notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# * Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					#   notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					#   documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from types import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def remove(sequence, target):
 | 
				
			||||||
 | 
					    if isinstance(sequence, ListType):
 | 
				
			||||||
 | 
					        if target in sequence:
 | 
				
			||||||
 | 
					            sequence.remove(target)
 | 
				
			||||||
 | 
					    elif isinstance(sequence, DictType):
 | 
				
			||||||
 | 
					        if target in sequence:
 | 
				
			||||||
 | 
					            del sequence[target]
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue