def test_retrieve_none(self): with locks.authority_of(locks.SYSTEM): foo = db.Object("foo") self.assertRaises(KeyError, db.find, lambda obj: obj.name == "bar") found = db.find_all(lambda obj: obj.name == "bar") self.assertEqual(len(found), 0)
def execute(self, player, args): players = db.find_all( lambda x: isinstance(x, db.Player) and x.connected) player.send("{number} {playersare} connected: {players}.".format( number=len(players), playersare="player is" if len(players) == 1 else "players are", players=utils.comma_and(map(str, list(players)))))
def execute(self, player, args): players = db.find_all(lambda x: isinstance(x, db.Player) and x.connected) player.send("{number} {playersare} connected: {players}.".format( number=len(players), playersare="player is" if len(players) == 1 else "players are", players=utils.comma_and(map(str, list(players)))))
def location_options(location): """ Return a list of (name, object) pairs for everything in a location, suitable for OneOf's options arg. """ if not isinstance(location, db.Object): raise TypeError("Invalid location: {}".format(location)) return [(obj.name, obj) for obj in db.find_all(lambda obj: obj.location == location)]
def test_dig_noexits(self): uid = db._nextUid self.assert_response("dig Room", "Enter the name of the exit into the " "room, if any (. to cancel):") self.assert_response("", "Enter the name of the exit back, if " "any (. to cancel):") self.assert_response("", "Dug room #{}, Room.".format(uid)) room = db.get(uid) self.assertEqual(room.type, "room") self.assertEqual(room.name, "Room") exits = db.find_all(lambda x: x.type == "exit" and (x.location is room or x.destination is room)) self.assertEqual(exits, set())
def test_retrieve_one(self): with locks.authority_of(locks.SYSTEM): obj_created = db.Object("foo") db.store(obj_created) obj_found = db.get(obj_created.uid) self.assertEqual(obj_created, obj_found) self.assertTrue(obj_created is obj_found) self.assertEqual(obj_found.name, "foo") self.assertEqual(obj_found.type, "thing") found = db.find_all(lambda x: x.uid == obj_created.uid) self.assertEqual(len(found), 1) self.assertEqual(obj_created, found.pop()) self.assertEqual(obj_created, db.get(obj_created.uid))
def test_dig_noexits(self): uid = db._nextUid self.assert_response( "dig Room", "Enter the name of the exit into the " "room, if any (. to cancel):") self.assert_response( "", "Enter the name of the exit back, if " "any (. to cancel):") self.assert_response("", "Dug room #{}, Room.".format(uid)) room = db.get(uid) self.assertEqual(room.type, "room") self.assertEqual(room.name, "Room") exits = db.find_all(lambda x: x.type == "exit" and (x.location is room or x.destination is room)) self.assertEqual(exits, set())
def test_retrieve_many(self): with locks.authority_of(locks.SYSTEM): foo = db.Object("foo") bar = db.Object("bar") baz = db.Object("baz") db.store(foo) db.store(bar) db.store(baz) def starts_with_ba(obj): return obj.name.startswith("ba") self.assertRaises(KeyError, db.find, starts_with_ba) found = db.find_all(starts_with_ba) self.assertNotIn(foo, found) self.assertIn(bar, found) self.assertIn(baz, found) self.assertEqual(len(found), 2)
def test_destroy(self): with locks.authority_of(locks.SYSTEM): owner = db.Object("owner") not_owner = db.Object("not_owner") db.store(owner) db.store(not_owner) with locks.authority_of(owner): item = db.Object("item") db.store(item) item_uid = item.uid with locks.authority_of(not_owner): self.assertRaises(locks.LockFailedError, item.destroy) with locks.authority_of(owner): item.destroy() matches = db.find_all(lambda x: x.uid == item_uid) self.assertEqual(len(matches), 0) self.assertRaises(KeyError, db.get, item_uid)
def handle(self, player, line): """ Parse the input line for a command and arguments, reporting any errors or unresolvable ambiguity. """ line = line.strip() if not line: return split_line = line.split(None, 1) if len(split_line) == 1: split_line.append("") first, rest_of_line = split_line name = "" command = None # Check for nospace commands nospace_matches = [] for command in all_commands(): for name in command().nospace_names: # We can't use find_by_name because we don't know where the # nospace command ends. if line.startswith(name): # No partial matching, for the same reason. nospace_matches.append((name, command)) if len(nospace_matches) == 1: name, command = nospace_matches[0] if len(line) > len(name): arguments = line[len(name):] else: arguments = "" try: try: if len(nospace_matches) > 1: raise parser.AmbiguityError(line, 0, parser.Command.errmsg, parser.Command, nospace_matches) # Check for normal command matches pattern = parser.CommandName(fullOnly=True)("command") parse_result = pattern.parseString(first, parseAll=True) matched = parse_result["command"] arguments = rest_of_line if nospace_matches: # We found a regular command, but already had a nospace # command. raise parser.AmbiguityError(line, 0, parser.Command.errmsg, parser.Command, nospace_matches + [matched]) else: name, command = parse_result["command"] except parser.NotFoundError as e: # No commands match, what about exits? exits = [(exit.name, exit) for exit in db.find_all(lambda x: x.type == 'exit' and x.location == player.location)] try: pattern = parser.OneOf(exits)("exit").setName("exit") parse_result = pattern.parseString(first, parseAll=True) # OneOf(exits) parsed, so exactly one exit matches. if not nospace_matches: command = commands.world.Go arguments = first except parser.AmbiguityError as f: # Multiple exits match and no full commands do. if not nospace_matches: player.send(f.verbose()) return # At this point there can only be one nospace command. # Let it fall all the way through to execution. except parser.NotFoundError as _: raise e except parser.NotFoundError as e: if not nospace_matches: message = e.verbose() # Check whether a require_full command would have matched rf_commands = [c for c in all_commands() if c.require_full] # (ignoring perfect matches because we would have already seen # them) rf_matches = utils.find_by_name(e.pstr, rf_commands, attributes=["names"])[1] if len(rf_matches) == 1: rf_name, rf_command = rf_matches[0] message += (" (If you mean \"{},\" you'll need to use the " "whole command name.)".format(rf_name)) elif rf_matches: rf_names = [c[0] for c in rf_matches] message += (" (If you meant one of these, you'll need to " "use the whole command name: {}.)" .format(", ".join(rf_names))) player.send(message) return except parser.AmbiguityError as e: # it's not clear from the name which command the user intended, # so see if any of their argument specs match what we got parsable_matches = [] for possible_name, possible_command in e.matches + nospace_matches: try: if nospace_matches and ((possible_name, possible_command) == nospace_matches[0]): test_arguments = line.split(possible_name, 1)[1] else: test_arguments = rest_of_line pattern = possible_command.args(player) args = pattern.parseString(test_arguments, parseAll=True) parsable_matches.append((possible_name, possible_command)) except pyparsing.ParseException: # user probably didn't intend this command; skip it. pass except utils.UserError: parsable_matches.append((possible_name, possible_command)) if len(parsable_matches) == 1: name, command = parsable_matches[0] if len(line) > len(name): if parsable_matches[0] in nospace_matches: arguments = line[len(name):] else: arguments = rest_of_line else: arguments = "" else: if parsable_matches: # we can at least narrow the field a little e.matches = parsable_matches player.send(e.verbose()) return # okay! we have a command! let's parse it. try: args = command.args(player).parseString(arguments, parseAll=True) command().execute(player, args) except utils.UserError as e: if hasattr(e, "verbose"): player.send(e.verbose()) else: player.send(str(e)) except pyparsing.ParseException as e: usages = command().usages if len(usages) > 1: from commands.help import Usage player.send("Usage:") Usage().execute(player, {"command": (name, command)}, tabs=True) else: player.send("Usage: " + usages[0]) player.send("(Try \"help {}\" for more help.)".format(name))
def __init__(self): super(PlayerName, self).__init__( [(p.name, p) for p in db.find_all(lambda p: p.type == 'player')], pyp.Word(pyp.alphas)) self.setName('player')
def handle(self, player, line): """ Parse the input line for a command and arguments, reporting any errors or unresolvable ambiguity. """ line = line.strip() if not line: return split_line = line.split(None, 1) if len(split_line) == 1: split_line.append("") first, rest_of_line = split_line name = "" command = None # Check for nospace commands nospace_matches = [] for command in all_commands(): for name in command().nospace_names: # We can't use find_by_name because we don't know where the # nospace command ends. if line.startswith(name): # No partial matching, for the same reason. nospace_matches.append((name, command)) if len(nospace_matches) == 1: name, command = nospace_matches[0] if len(line) > len(name): arguments = line[len(name):] else: arguments = "" try: try: if len(nospace_matches) > 1: raise parser.AmbiguityError(line, 0, parser.Command.errmsg, parser.Command, nospace_matches) # Check for normal command matches pattern = parser.CommandName(fullOnly=True)("command") parse_result = pattern.parseString(first, parseAll=True) matched = parse_result["command"] arguments = rest_of_line if nospace_matches: # We found a regular command, but already had a nospace # command. raise parser.AmbiguityError(line, 0, parser.Command.errmsg, parser.Command, nospace_matches + [matched]) else: name, command = parse_result["command"] except parser.NotFoundError as e: # No commands match, what about exits? exits = [(exit.name, exit) for exit in db.find_all(lambda x: x.type == 'exit' and x.location == player.location) ] try: pattern = parser.OneOf(exits)("exit").setName("exit") parse_result = pattern.parseString(first, parseAll=True) # OneOf(exits) parsed, so exactly one exit matches. if not nospace_matches: command = commands.world.Go arguments = first except parser.AmbiguityError as f: # Multiple exits match and no full commands do. if not nospace_matches: player.send(f.verbose()) return # At this point there can only be one nospace command. # Let it fall all the way through to execution. except parser.NotFoundError as _: raise e except parser.NotFoundError as e: if not nospace_matches: message = e.verbose() # Check whether a require_full command would have matched rf_commands = [c for c in all_commands() if c.require_full] # (ignoring perfect matches because we would have already seen # them) rf_matches = utils.find_by_name(e.pstr, rf_commands, attributes=["names"])[1] if len(rf_matches) == 1: rf_name, rf_command = rf_matches[0] message += (" (If you mean \"{},\" you'll need to use the " "whole command name.)".format(rf_name)) elif rf_matches: rf_names = [c[0] for c in rf_matches] message += (" (If you meant one of these, you'll need to " "use the whole command name: {}.)".format( ", ".join(rf_names))) player.send(message) return except parser.AmbiguityError as e: # it's not clear from the name which command the user intended, # so see if any of their argument specs match what we got parsable_matches = [] for possible_name, possible_command in e.matches + nospace_matches: try: if nospace_matches and ((possible_name, possible_command) == nospace_matches[0]): test_arguments = line.split(possible_name, 1)[1] else: test_arguments = rest_of_line pattern = possible_command.args(player) args = pattern.parseString(test_arguments, parseAll=True) parsable_matches.append((possible_name, possible_command)) except pyparsing.ParseException: # user probably didn't intend this command; skip it. pass except utils.UserError: parsable_matches.append((possible_name, possible_command)) if len(parsable_matches) == 1: name, command = parsable_matches[0] if len(line) > len(name): if parsable_matches[0] in nospace_matches: arguments = line[len(name):] else: arguments = rest_of_line else: arguments = "" else: if parsable_matches: # we can at least narrow the field a little e.matches = parsable_matches player.send(e.verbose()) return # okay! we have a command! let's parse it. try: args = command.args(player).parseString(arguments, parseAll=True) command().execute(player, args) except utils.UserError as e: if hasattr(e, "verbose"): player.send(e.verbose()) else: player.send(str(e)) except pyparsing.ParseException as e: usages = command().usages if len(usages) > 1: from commands.help import Usage player.send("Usage:") Usage().execute(player, {"command": (name, command)}, tabs=True) else: player.send("Usage: " + usages[0]) player.send("(Try \"help {}\" for more help.)".format(name))