Use "group" instead of "category"
authorJeremy Stanley <fungi@yuggoth.org>
Thu, 16 Nov 2017 02:36:34 +0000 (02:36 +0000)
committerJeremy Stanley <fungi@yuggoth.org>
Thu, 16 Nov 2017 02:36:34 +0000 (02:36 +0000)
Update all uses of category/categories to group/groups. Also add
selftests for the "show groups" and "show group <group>" commands.

etc/mudpy.yaml
mudpy/data.py
mudpy/misc.py
mudpy/tests/fixtures/test_daemon.yaml
mudpy/tests/selftest.py
share/command.yaml

index ed43c59..6259200 100644 (file)
@@ -8,7 +8,7 @@ _load: [ archetype.yaml, command.yaml, menu.yaml, sample ]
 
 _lock: true
 
 
 _lock: true
 
-.mudpy.filing.categories: { account: { flags: [ private ] } }
+.mudpy.filing.groups: { account: { flags: [ private ] } }
 .mudpy.filing.prefix: "."
 .mudpy.filing.search: [ "", "etc", "share", "data" ]
 .mudpy.filing.stash: "data"
 .mudpy.filing.prefix: "."
 .mudpy.filing.search: [ "", "etc", "share", "data" ]
 .mudpy.filing.stash: "data"
index 3dc71d0..5233da2 100644 (file)
@@ -161,7 +161,7 @@ class Data:
 
 def find_file(
     file_name=None,
 
 def find_file(
     file_name=None,
-    category=None,
+    group=None,
     prefix=None,
     relative=None,
     search=None,
     prefix=None,
     relative=None,
     search=None,
index a596eb5..2da1b40 100644 (file)
@@ -42,25 +42,25 @@ class Element:
         self.contents = {}
 
         if self.key.find(".") > 0:
         self.contents = {}
 
         if self.key.find(".") > 0:
-            self.category, self.subkey = self.key.split(".")[-2:]
+            self.group, self.subkey = self.key.split(".")[-2:]
         else:
         else:
-            self.category = "other"
+            self.group = "other"
             self.subkey = self.key
             self.subkey = self.key
-        if self.category not in self.universe.categories:
-            self.universe.categories[self.category] = {}
+        if self.group not in self.universe.groups:
+            self.universe.groups[self.group] = {}
 
         # get an appropriate origin
         if not origin:
 
         # get an appropriate origin
         if not origin:
-            self.universe.add_category(self.category)
+            self.universe.add_group(self.group)
             origin = self.universe.files[
             origin = self.universe.files[
-                    self.universe.origins[self.category]["fallback"]]
+                    self.universe.origins[self.group]["fallback"]]
 
         # record or reset a pointer to the origin file
         self.origin = self.universe.files[origin.source]
 
         # add or replace this element in the universe
         self.universe.contents[self.key] = self
 
         # record or reset a pointer to the origin file
         self.origin = self.universe.files[origin.source]
 
         # add or replace this element in the universe
         self.universe.contents[self.key] = self
-        self.universe.categories[self.category][self.subkey] = self
+        self.universe.groups[self.group][self.subkey] = self
 
     def reload(self):
         """Create a new element and replace this one."""
 
     def reload(self):
         """Create a new element and replace this one."""
@@ -71,7 +71,7 @@ class Element:
         """Remove an element from the universe and destroy it."""
         for facet in dict(self.facethash):
             self.remove_facet(facet)
         """Remove an element from the universe and destroy it."""
         for facet in dict(self.facethash):
             self.remove_facet(facet)
-        del self.universe.categories[self.category][self.subkey]
+        del self.universe.groups[self.group][self.subkey]
         del self.universe.contents[self.key]
         del self
 
         del self.universe.contents[self.key]
         del self
 
@@ -176,8 +176,8 @@ class Element:
     def can_run(self, command):
         """Check if the user can run this command object."""
 
     def can_run(self, command):
         """Check if the user can run this command object."""
 
-        # has to be in the commands category
-        if command not in self.universe.categories["command"].values():
+        # has to be in the commands group
+        if command not in self.universe.groups["command"].values():
             result = False
 
         # avatars of administrators can run any command
             result = False
 
         # avatars of administrators can run any command
@@ -315,7 +315,7 @@ class Universe:
 
     def __init__(self, filename="", load=False):
         """Initialize the universe."""
 
     def __init__(self, filename="", load=False):
         """Initialize the universe."""
-        self.categories = {}
+        self.groups = {}
         self.contents = {}
         self.directions = set()
         self.loading = False
         self.contents = {}
         self.directions = set()
         self.loading = False
@@ -371,18 +371,18 @@ class Universe:
             # start loading from the initial file
             mudpy.data.Data(self.filename, self)
 
             # start loading from the initial file
             mudpy.data.Data(self.filename, self)
 
-        # load default storage locations for categories
+        # load default storage locations for groups
         if hasattr(self, "contents") and "mudpy.filing" in self.contents:
             self.origins.update(self.contents["mudpy.filing"].get(
         if hasattr(self, "contents") and "mudpy.filing" in self.contents:
             self.origins.update(self.contents["mudpy.filing"].get(
-                "categories", {}))
+                "groups", {}))
 
 
-        # add some builtin categories we know we'll need
-        for category in ("account", "actor", "internal"):
-            self.add_category(category)
+        # add some builtin groups we know we'll need
+        for group in ("account", "actor", "internal"):
+            self.add_group(group)
 
         # make a list of inactive avatars
         inactive_avatars = []
 
         # make a list of inactive avatars
         inactive_avatars = []
-        for account in self.categories.get("account", {}).values():
+        for account in self.groups.get("account", {}).values():
             for avatar in account.get("avatars"):
                 try:
                     inactive_avatars.append(self.contents[avatar])
             for avatar in account.get("avatars"):
                 try:
                     inactive_avatars.append(self.contents[avatar])
@@ -477,18 +477,18 @@ class Universe:
 
     def get_time(self):
         """Convenience method to get the elapsed time counter."""
 
     def get_time(self):
         """Convenience method to get the elapsed time counter."""
-        return self.categories["internal"]["counters"].get("elapsed")
+        return self.groups["internal"]["counters"].get("elapsed")
 
 
-    def add_category(self, category, fallback=None):
-        """Set up category tracking/metadata."""
-        if category not in self.origins:
-            self.origins[category] = {}
+    def add_group(self, group, fallback=None):
+        """Set up group tracking/metadata."""
+        if group not in self.origins:
+            self.origins[group] = {}
         if not fallback:
             fallback = mudpy.data.find_file(
         if not fallback:
             fallback = mudpy.data.find_file(
-                    ".".join((category, "yaml")), universe=self)
-        if "fallback" not in self.origins[category]:
-            self.origins[category]["fallback"] = fallback
-        flags = self.origins[category].get("flags", None)
+                    ".".join((group, "yaml")), universe=self)
+        if "fallback" not in self.origins[group]:
+            self.origins[group]["fallback"] = fallback
+        flags = self.origins[group].get("flags", None)
         if fallback not in self.files:
             mudpy.data.Data(fallback, self, flags=flags)
 
         if fallback not in self.files:
             mudpy.data.Data(fallback, self, flags=flags)
 
@@ -907,7 +907,7 @@ class User:
         """Instantiate a new, unconfigured avatar for this user."""
         counter = 0
         while ("avatar_%s_%s" % (self.account.get("name"), counter)
         """Instantiate a new, unconfigured avatar for this user."""
         counter = 0
         while ("avatar_%s_%s" % (self.account.get("name"), counter)
-                in universe.categories.get("actor", {}).keys()):
+                in universe.groups.get("actor", {}).keys()):
             counter += 1
         self.avatar = Element(
             "actor.avatar_%s_%s" % (self.account.get("name"), counter),
             counter += 1
         self.avatar = Element(
             "actor.avatar_%s_%s" % (self.account.get("name"), counter),
@@ -1362,31 +1362,31 @@ def on_pulse():
         user.pulse()
 
     # add an element for counters if it doesn't exist
         user.pulse()
 
     # add an element for counters if it doesn't exist
-    if "counters" not in universe.categories.get("internal", {}):
+    if "counters" not in universe.groups.get("internal", {}):
         Element("internal.counters", universe)
 
     # update the log every now and then
         Element("internal.counters", universe)
 
     # update the log every now and then
-    if not universe.categories["internal"]["counters"].get("mark"):
+    if not universe.groups["internal"]["counters"].get("mark"):
         log(str(len(universe.userlist)) + " connection(s)")
         log(str(len(universe.userlist)) + " connection(s)")
-        universe.categories["internal"]["counters"].set(
+        universe.groups["internal"]["counters"].set(
             "mark", universe.contents["mudpy.timing"].get("status")
         )
     else:
             "mark", universe.contents["mudpy.timing"].get("status")
         )
     else:
-        universe.categories["internal"]["counters"].set(
-            "mark", universe.categories["internal"]["counters"].get(
+        universe.groups["internal"]["counters"].set(
+            "mark", universe.groups["internal"]["counters"].get(
                 "mark"
             ) - 1
         )
 
     # periodically save everything
                 "mark"
             ) - 1
         )
 
     # periodically save everything
-    if not universe.categories["internal"]["counters"].get("save"):
+    if not universe.groups["internal"]["counters"].get("save"):
         universe.save()
         universe.save()
-        universe.categories["internal"]["counters"].set(
+        universe.groups["internal"]["counters"].set(
             "save", universe.contents["mudpy.timing"].get("save")
         )
     else:
             "save", universe.contents["mudpy.timing"].get("save")
         )
     else:
-        universe.categories["internal"]["counters"].set(
-            "save", universe.categories["internal"]["counters"].get(
+        universe.groups["internal"]["counters"].set(
+            "save", universe.groups["internal"]["counters"].get(
                 "save"
             ) - 1
         )
                 "save"
             ) - 1
         )
@@ -1395,8 +1395,8 @@ def on_pulse():
     time.sleep(universe.contents["mudpy.timing"].get("increment"))
 
     # increase the elapsed increment counter
     time.sleep(universe.contents["mudpy.timing"].get("increment"))
 
     # increase the elapsed increment counter
-    universe.categories["internal"]["counters"].set(
-        "elapsed", universe.categories["internal"]["counters"].get(
+    universe.groups["internal"]["counters"].set(
+        "elapsed", universe.groups["internal"]["counters"].get(
             "elapsed", 0
         ) + 1
     )
             "elapsed", 0
         ) + 1
     )
@@ -1472,7 +1472,7 @@ def get_menu(state, error=None, choices=None):
 
 def menu_echo_on(state):
     """True if echo is on, false if it is off."""
 
 def menu_echo_on(state):
     """True if echo is on, false if it is off."""
-    return universe.categories["menu"][state].get("echo", True)
+    return universe.groups["menu"][state].get("echo", True)
 
 
 def get_echo_message(state):
 
 
 def get_echo_message(state):
@@ -1485,7 +1485,7 @@ def get_echo_message(state):
 
 def get_default_menu_choice(state):
     """Return the default choice for a menu."""
 
 def get_default_menu_choice(state):
     """Return the default choice for a menu."""
-    return universe.categories["menu"][state].get("default")
+    return universe.groups["menu"][state].get("default")
 
 
 def get_formatted_default_menu_choice(state):
 
 
 def get_formatted_default_menu_choice(state):
@@ -1505,7 +1505,7 @@ def get_menu_description(state, error):
 
         # try to get an error message matching the condition
         # and current state
 
         # try to get an error message matching the condition
         # and current state
-        description = universe.categories[
+        description = universe.groups[
             "menu"][state].get("error_" + error)
         if not description:
             description = "That is not a valid choice..."
             "menu"][state].get("error_" + error)
         if not description:
             description = "That is not a valid choice..."
@@ -1515,7 +1515,7 @@ def get_menu_description(state, error):
     else:
 
         # try to get a menu description for the current state
     else:
 
         # try to get a menu description for the current state
-        description = universe.categories["menu"][state].get("description")
+        description = universe.groups["menu"][state].get("description")
 
     # return the description or error message
     if description:
 
     # return the description or error message
     if description:
@@ -1525,7 +1525,7 @@ def get_menu_description(state, error):
 
 def get_menu_prompt(state):
     """Try to get a prompt, if it was defined."""
 
 def get_menu_prompt(state):
     """Try to get a prompt, if it was defined."""
-    prompt = universe.categories["menu"][state].get("prompt")
+    prompt = universe.groups["menu"][state].get("prompt")
     if prompt:
         prompt += " "
     return prompt
     if prompt:
         prompt += " "
     return prompt
@@ -1533,7 +1533,7 @@ def get_menu_prompt(state):
 
 def get_menu_choices(user):
     """Return a dict of choice:meaning."""
 
 def get_menu_choices(user):
     """Return a dict of choice:meaning."""
-    menu = universe.categories["menu"][user.state]
+    menu = universe.groups["menu"][user.state]
     create_choices = menu.get("create")
     if create_choices:
         choices = eval(create_choices)
     create_choices = menu.get("create")
     if create_choices:
         choices = eval(create_choices)
@@ -1544,7 +1544,7 @@ def get_menu_choices(user):
     creates = {}
     for facet in menu.facets():
         if facet.startswith("demand_") and not eval(
     creates = {}
     for facet in menu.facets():
         if facet.startswith("demand_") and not eval(
-           universe.categories["menu"][user.state].get(facet)
+           universe.groups["menu"][user.state].get(facet)
            ):
             ignores.append(facet.split("_", 2)[1])
         elif facet.startswith("create_"):
            ):
             ignores.append(facet.split("_", 2)[1])
         elif facet.startswith("create_"):
@@ -1577,17 +1577,17 @@ def get_formatted_menu_choices(state, choices):
 def get_menu_branches(state):
     """Return a dict of choice:branch."""
     branches = {}
 def get_menu_branches(state):
     """Return a dict of choice:branch."""
     branches = {}
-    for facet in universe.categories["menu"][state].facets():
+    for facet in universe.groups["menu"][state].facets():
         if facet.startswith("branch_"):
             branches[
                 facet.split("_", 2)[1]
         if facet.startswith("branch_"):
             branches[
                 facet.split("_", 2)[1]
-            ] = universe.categories["menu"][state].get(facet)
+            ] = universe.groups["menu"][state].get(facet)
     return branches
 
 
 def get_default_branch(state):
     """Return the default branch."""
     return branches
 
 
 def get_default_branch(state):
     """Return the default branch."""
-    return universe.categories["menu"][state].get("branch")
+    return universe.groups["menu"][state].get("branch")
 
 
 def get_choice_branch(user, choice):
 
 
 def get_choice_branch(user, choice):
@@ -1604,17 +1604,17 @@ def get_choice_branch(user, choice):
 def get_menu_actions(state):
     """Return a dict of choice:branch."""
     actions = {}
 def get_menu_actions(state):
     """Return a dict of choice:branch."""
     actions = {}
-    for facet in universe.categories["menu"][state].facets():
+    for facet in universe.groups["menu"][state].facets():
         if facet.startswith("action_"):
             actions[
                 facet.split("_", 2)[1]
         if facet.startswith("action_"):
             actions[
                 facet.split("_", 2)[1]
-            ] = universe.categories["menu"][state].get(facet)
+            ] = universe.groups["menu"][state].get(facet)
     return actions
 
 
 def get_default_action(state):
     """Return the default action."""
     return actions
 
 
 def get_default_action(state):
     """Return the default action."""
-    return universe.categories["menu"][state].get("action")
+    return universe.groups["menu"][state].get("action")
 
 
 def get_choice_action(user, choice):
 
 
 def get_choice_action(user, choice):
@@ -1689,8 +1689,8 @@ def handler_entering_account_name(user):
             user.error = "bad_name"
 
         # if that account exists, time to request a password
             user.error = "bad_name"
 
         # if that account exists, time to request a password
-        elif name in universe.categories.get("account", {}):
-            user.account = universe.categories["account"][name]
+        elif name in universe.groups.get("account", {}):
+            user.account = universe.groups["account"][name]
             user.state = "checking_password"
 
         # otherwise, this could be a brand new user
             user.state = "checking_password"
 
         # otherwise, this could be a brand new user
@@ -1838,8 +1838,8 @@ def handler_active(user):
         command_name = command_name.lower()
 
         # the command matches a command word for which we have data
         command_name = command_name.lower()
 
         # the command matches a command word for which we have data
-        if command_name in universe.categories["command"]:
-            command = universe.categories["command"][command_name]
+        if command_name in universe.groups["command"]:
+            command = universe.groups["command"][command_name]
         else:
             command = None
 
         else:
             command = None
 
@@ -1906,8 +1906,8 @@ def command_help(actor, parameters):
     if parameters and actor.owner:
 
         # is the command word one for which we have data?
     if parameters and actor.owner:
 
         # is the command word one for which we have data?
-        if parameters in universe.categories["command"]:
-            command = universe.categories["command"][parameters]
+        if parameters in universe.groups["command"]:
+            command = universe.groups["command"][parameters]
         else:
             command = None
 
         else:
             command = None
 
@@ -1935,8 +1935,8 @@ def command_help(actor, parameters):
             if see_also:
                 really_see_also = ""
                 for item in see_also:
             if see_also:
                 really_see_also = ""
                 for item in see_also:
-                    if item in universe.categories["command"]:
-                        command = universe.categories["command"][item]
+                    if item in universe.groups["command"]:
+                        command = universe.groups["command"][item]
                         if actor.can_run(command):
                             if really_see_also:
                                 really_see_also += ", "
                         if actor.can_run(command):
                             if really_see_also:
                                 really_see_also += ", "
@@ -1957,10 +1957,10 @@ def command_help(actor, parameters):
 
         # give a sorted list of commands with descriptions if provided
         output = "These are the commands available to you:$(eol)$(eol)"
 
         # give a sorted list of commands with descriptions if provided
         output = "These are the commands available to you:$(eol)$(eol)"
-        sorted_commands = list(universe.categories["command"].keys())
+        sorted_commands = list(universe.groups["command"].keys())
         sorted_commands.sort()
         for item in sorted_commands:
         sorted_commands.sort()
         for item in sorted_commands:
-            command = universe.categories["command"][item]
+            command = universe.groups["command"][item]
             if actor.can_run(command):
                 description = command.get("description")
                 if not description:
             if actor.can_run(command):
                 description = command.get("description")
                 if not description:
@@ -2094,15 +2094,15 @@ def command_show(actor, parameters):
     if not parameters:
         message = "What do you want to show?"
     elif arguments[0] == "time":
     if not parameters:
         message = "What do you want to show?"
     elif arguments[0] == "time":
-        message = universe.categories["internal"]["counters"].get(
+        message = universe.groups["internal"]["counters"].get(
             "elapsed"
         ) + " increments elapsed since the world was created."
             "elapsed"
         ) + " increments elapsed since the world was created."
-    elif arguments[0] == "categories":
-        message = "These are the element categories:$(eol)"
-        categories = list(universe.categories.keys())
-        categories.sort()
-        for category in categories:
-            message += "$(eol)   $(grn)" + category + "$(nrm)"
+    elif arguments[0] == "groups":
+        message = "These are the element groups:$(eol)"
+        groups = list(universe.groups.keys())
+        groups.sort()
+        for group in groups:
+            message += "$(eol)   $(grn)" + group + "$(nrm)"
     elif arguments[0] == "files":
         message = "These are the current files containing the universe:$(eol)"
         filenames = sorted(universe.files)
     elif arguments[0] == "files":
         message = "These are the current files containing the universe:$(eol)"
         filenames = sorted(universe.files)
@@ -2116,22 +2116,22 @@ def command_show(actor, parameters):
             if universe.files[filename].flags:
                 message += (" $(yel)[%s]$(nrm)" %
                             ",".join(universe.files[filename].flags))
             if universe.files[filename].flags:
                 message += (" $(yel)[%s]$(nrm)" %
                             ",".join(universe.files[filename].flags))
-    elif arguments[0] == "category":
+    elif arguments[0] == "group":
         if len(arguments) != 2:
         if len(arguments) != 2:
-            message = "You must specify one category."
-        elif arguments[1] in universe.categories:
+            message = "You must specify one group."
+        elif arguments[1] in universe.groups:
             message = ('These are the elements in the "' + arguments[1]
             message = ('These are the elements in the "' + arguments[1]
-                       + '" category:$(eol)')
+                       + '" group:$(eol)')
             elements = [
                 (
             elements = [
                 (
-                    universe.categories[arguments[1]][x].key
-                ) for x in universe.categories[arguments[1]].keys()
+                    universe.groups[arguments[1]][x].key
+                ) for x in universe.groups[arguments[1]].keys()
             ]
             elements.sort()
             for element in elements:
                 message += "$(eol)   $(grn)" + element + "$(nrm)"
         else:
             ]
             elements.sort()
             for element in elements:
                 message += "$(eol)   $(grn)" + element + "$(nrm)"
         else:
-            message = 'Category "' + arguments[1] + '" does not exist.'
+            message = 'Group "' + arguments[1] + '" does not exist.'
     elif arguments[0] == "file":
         if len(arguments) != 2:
             message = "You must specify one file."
     elif arguments[0] == "file":
         if len(arguments) != 2:
             message = "You must specify one file."
index 7c39b1d..2a35aac 100644 (file)
@@ -9,7 +9,7 @@ _load: [ archetype.yaml, command.yaml, menu.yaml, sample ]
 
 _lock: true
 
 
 _lock: true
 
-.mudpy.filing.categories: { account: { flags: [ private ] } }
+.mudpy.filing.groups: { account: { flags: [ private ] } }
 .mudpy.filing.prefix: "."
 .mudpy.filing.search: [ "", "etc", "share", "data" ]
 .mudpy.filing.stash: "data"
 .mudpy.filing.prefix: "."
 .mudpy.filing.search: [ "", "etc", "share", "data" ]
 .mudpy.filing.stash: "data"
index 1b9c81b..cba69c6 100644 (file)
@@ -184,6 +184,18 @@ test_show_file = (
     (2, r'These are the nodes in the.*file:.*internal\.counters.*> ', ""),
 )
 
     (2, r'These are the nodes in the.*file:.*internal\.counters.*> ', ""),
 )
 
+test_show_groups = (
+    (2, "> ", "show groups"),
+    (2, r'These are the element groups:.*'
+        r'  \x1b\[32maccount\x1b\[0m.*> ', ""),
+)
+
+test_show_group = (
+    (2, "> ", "show group account"),
+    (2, r'These are the elements in the "account" group:.*'
+        r'  \x1b\[32maccount\.admin\x1b\[0m.*> ', ""),
+)
+
 test_show_element = (
     (2, "> ", "show element mudpy.limit"),
     (2, r'These are the properties of the "mudpy\.limit" element.*'
 test_show_element = (
     (2, "> ", "show element mudpy.limit"),
     (2, r'These are the properties of the "mudpy\.limit" element.*'
@@ -236,6 +248,8 @@ dialogue = (
     (test_set_refused, "refuse altering read-only element"),
     (test_show_files, "show a list of loaded files"),
     (test_show_file, "show nodes from a specific file"),
     (test_set_refused, "refuse altering read-only element"),
     (test_show_files, "show a list of loaded files"),
     (test_show_file, "show nodes from a specific file"),
+    (test_show_groups, "show groups"),
+    (test_show_group, "show group"),
     (test_show_element, "show element"),
     (test_show_log, "show log"),
     (test_custom_loglevel, "custom loglevel"),
     (test_show_element, "show element"),
     (test_show_log, "show log"),
     (test_custom_loglevel, "custom loglevel"),
index ade3907..67bfb7d 100644 (file)
@@ -65,4 +65,4 @@ command.set.help: Invoke it like this:$(eol)$(eol)   set actor:dominique descrip
 command.show.action: command_show(actor, parameters)
 command.show.administrative: true
 command.show.description: Show various data.
 command.show.action: command_show(actor, parameters)
 command.show.administrative: true
 command.show.description: Show various data.
-command.show.help: Here are the possible incantations (<parameter> is required, [option] is optional, (note) is a note):$(eol)$(eol)   show categories (list all element category names)$(eol)   show category <category> (list the elements in a category)$(eol)   show element <element> (list facet definitions for an element)$(eol)   show file <filename> (list elements in a file)$(eol)   show files (list all element data files)$(eol)   show log [level [start [stop]]] (list logs above level from start to stop)$(eol)   show result <expression> (evaluates a python expression)$(eol)   show time (returns several current timer values)
+command.show.help: Here are the possible incantations (<parameter> is required, [option] is optional, (note) is a note):$(eol)$(eol)   show groups (list all element group names)$(eol)   show group <group> (list the elements in a group)$(eol)   show element <element> (list facet definitions for an element)$(eol)   show file <filename> (list elements in a file)$(eol)   show files (list all element data files)$(eol)   show log [level [start [stop]]] (list logs above level from start to stop)$(eol)   show result <expression> (evaluates a python expression)$(eol)   show time (returns several current timer values)