Created
January 10, 2010 20:09
-
-
Save bebraw/273735 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import inspect | |
class Context: | |
owner = None | |
def claim_for(self, owner): | |
self.owner = owner | |
def release(self): | |
self.owner = None | |
class Commands(list): | |
def __init__(self, commands=None): | |
commands = commands if commands else [] | |
if not hasattr(commands, '__iter__'): | |
commands = [commands] | |
super(Commands, self).__init__(commands) | |
def match(self, expression): | |
priorities = ('high', 'normal', 'low') | |
for priority in priorities: | |
commands = self.find(priority=priority) | |
for command in commands: | |
if command.matches(expression): | |
return command | |
def find(self, name=None, priority=None): | |
if name: | |
for command in self: | |
class_name = command.__class__.__name__ | |
if class_name.lower() == name: | |
return command | |
if priority: | |
return filter(lambda command: command.priority == priority, self) | |
class Interpreter: | |
def __init__(self, commands=None): | |
self.context = Context() | |
self.commands = Commands(commands) | |
self.variables = {} | |
def interpret(self, expression): | |
possible_parameters = {'context': self.context, | |
'commands': self.commands, 'expression': expression, | |
'variables': self.variables} | |
try: | |
if self.context.owner: | |
command = self.context.owner | |
else: | |
command = self.commands.match(expression) | |
args = self._get_args(command.execute) | |
params = self._find_parameters(possible_parameters, args) | |
return command.execute(**params) | |
except: | |
return 'null' | |
def _get_args(self, method): | |
return inspect.getargspec(method).args | |
def _find_parameters(self, possible_parameters, args): | |
ret = {} | |
for name, value in possible_parameters.items(): | |
if name in args: | |
ret[name] = value | |
return ret |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from mock import Mock | |
from placidity.interpreter import Context, Commands, Interpreter | |
# TODO: convert execute asserts to assert_called_with and handle | |
# return with return_value. Note that it's possible to mock the | |
# signatures in Mock 0.7 (fix after release or include svn version in | |
# /lib) | |
class TestContext: | |
def setup_method(self, method): | |
self.context = Context() | |
def test_claim_for(self): | |
assert self.context.owner == None | |
self.context.claim_for('foobar') | |
assert self.context.owner == 'foobar' | |
def test_release(self): | |
self.context.claim_for('barfoo') | |
assert self.context.owner == 'barfoo' | |
self.context.release() | |
assert self.context.owner == None | |
class TestCommands: | |
def test_find_single(self): | |
class Foo: | |
pass | |
command = Foo() | |
commands = Commands(command) | |
assert commands.find(name='foo') == command | |
def test_find_nothing(self): | |
commands = Commands() | |
assert commands.find(name='foo') == None | |
def test_find_based_on_priority(self): | |
class Bar: | |
priority = 'low' | |
class Foo: | |
priority = 'normal' | |
class Help: | |
priority = 'normal' | |
command1 = Bar() | |
command2 = Foo() | |
command3 = Help() | |
commands = Commands((command1, command2, command3)) | |
assert commands.find(priority='low') == [command1, ] | |
multiple = commands.find(priority='normal') | |
assert command2 in multiple | |
assert command3 in multiple | |
class TestInterpreter: | |
def test_exception(self): | |
interpreter = Interpreter() | |
assert interpreter.interpret('foobar') == 'null' | |
def test_context_owner_set(self): | |
def execute_1(): | |
return 'foo' | |
command1 = self.create_command('foobar', execute_method=execute_1) | |
def execute_2(expression): | |
if expression == 'foobar': | |
return None | |
return 'bar' | |
command2 = self.create_command('bar', execute_method=execute_2) | |
interpreter = Interpreter([command1, command2]) | |
interpreter.context.claim_for(command2) | |
assert interpreter.interpret('foobar') == None | |
assert interpreter.interpret('bar') == 'bar' | |
def test_no_return(self): | |
def execute(): | |
pass | |
command = self.create_command('foo', execute_method=execute) | |
interpreter = Interpreter(command) | |
assert interpreter.interpret('foo') == None | |
def test_priority(self): | |
def execute_1(): | |
return 'foo' | |
command1 = self.create_command('bar', 'high', execute_1) | |
def execute_2(): | |
return 'BYE' | |
command2 = self.create_command('bar', 'normal', execute_2) | |
def execute_3(): | |
return 'BYEBYE' | |
command3 = self.create_command('bar', 'low', execute_3) | |
interpreter = Interpreter([command1, command2, command3]) | |
assert interpreter.interpret('bar') == 'foo' | |
def test_execute_parameters(self): | |
def no_parameters(): | |
return 'executed command' | |
def with_context(context): | |
assert context.owner == None | |
return 'executed command' | |
def with_commands(commands): | |
assert commands == [command, ] | |
return 'executed command' | |
def with_expression(expression): | |
assert expression == 'command' | |
return 'executed command' | |
def with_variables(variables): | |
assert variables == {} | |
return 'executed command' | |
def with_multiple_parameters(expression, commands, | |
variables, context): | |
assert context.owner == None | |
assert commands == [command, ] | |
assert expression == 'command' | |
assert variables == {} | |
return 'executed command' | |
execute_methods = (no_parameters, with_context, with_commands, | |
with_expression, with_variables, with_multiple_parameters, ) | |
command = self.create_command('command') | |
interpreter = Interpreter(command) | |
for execute_method in execute_methods: | |
command.execute = execute_method | |
assert interpreter.interpret('command') == 'executed command', \ | |
execute_method.__name__ + ' failed!' | |
command.matches.assert_called_with('command') | |
def test_execute_command(self): | |
def execute(): | |
return 'executed command' | |
command1 = self.create_command('foo', execute_method=execute) | |
command2 = self.create_command('bar', execute_method=execute) | |
interpreter = Interpreter([command1, command2, ]) | |
assert interpreter.interpret('foo') == 'executed command' | |
def create_command(self, name, priority='normal', execute_method=None): | |
command = Mock() | |
command.aliases = name | |
command.matches = Mock() | |
command.matches.return_value = True | |
if execute_method: | |
command.execute = execute_method | |
command.priority = priority | |
return command |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment