コード例 #1
0
ファイル: test_data.py プロジェクト: mongolsamurai/MUSS
    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)
コード例 #2
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)))))
コード例 #3
0
    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)
コード例 #4
0
ファイル: social.py プロジェクト: mongolsamurai/MUSS
 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)))))
コード例 #5
0
ファイル: parser.py プロジェクト: mongolsamurai/MUSS
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)]
コード例 #6
0
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)]
コード例 #7
0
ファイル: test_building.py プロジェクト: mongolsamurai/MUSS
 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())
コード例 #8
0
ファイル: test_data.py プロジェクト: mongolsamurai/MUSS
    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))
コード例 #9
0
ファイル: test_building.py プロジェクト: rlazarus/MUSS
 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())
コード例 #10
0
    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))
コード例 #11
0
ファイル: test_data.py プロジェクト: mongolsamurai/MUSS
    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)
コード例 #12
0
    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)
コード例 #13
0
ファイル: test_data.py プロジェクト: mongolsamurai/MUSS
    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)
コード例 #14
0
    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)
コード例 #15
0
ファイル: handler.py プロジェクト: mongolsamurai/MUSS
    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))
コード例 #16
0
 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')
コード例 #17
0
ファイル: parser.py プロジェクト: mongolsamurai/MUSS
 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')
コード例 #18
0
ファイル: handler.py プロジェクト: rlazarus/MUSS
    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))