From be70007ae999da3d3f64b12a6ec13080977be99b Mon Sep 17 00:00:00 2001 From: Jeremy Stanley Date: Sat, 26 Nov 2005 22:55:44 +0000 Subject: [PATCH] Imported from archive. * command (command:show), mudpy.py (command_show): Improved parameter descriptions in the help text for the administrative show command, and added a file parameter to allow listing of elements included within a known data file. * command (command:show), mudpy.py (command_show, get_loglines): Modified the administrative show log command to take parameters for filtering and start/stop entry ranges. * mudpy.py (DataFile.load, Universe.load, command_reload) (reload_data): The administrative reload command now re-reads data from read-only data files and updates the corresponding elements. (command_show): Refactored if/then spaghetti logic to be easier to follow. --- command | 4 +- mudpy.py | 219 +++++++++++++++++++++++++++++++++++++-------------------------- 2 files changed, 132 insertions(+), 91 deletions(-) diff --git a/command b/command index 907335a..c983ed3 100644 --- a/command +++ b/command @@ -65,6 +65,6 @@ help = Invoke it like this:$(eol)$(eol) set actor:dominique description You se [command:show] action = command_show(actor, parameters) administrative = yes -description = Show element data. -help = Here are the possible incantations:$(eol)$(eol) show categories$(eol) show category actor$(eol) show element location:1:2:3:4$(eol) show files$(eol) show log 20$(eol) show result avatar.get("name")$(eol) show time +description = Show various data. +help = Here are the possible incantations ( is required, [parameter] is optional, (note) is a note):$(eol)$(eol) show categories (list all element category names)$(eol) show category (list the elements in a category)$(eol) show element (list facet definitions for an element)$(eol) show files (list all element data files)$(eol) show file (list elements in a file)$(eol) show log [level [start [stop]]] (list logs above level from start to stop)$(eol) show result (evaluates a python expression)$(eol) show time (returns the current universal elapsed time counter) diff --git a/mudpy.py b/mudpy.py index d1c434f..f5a8826 100644 --- a/mudpy.py +++ b/mudpy.py @@ -59,7 +59,9 @@ class Element: else: self.category = "other" self.subkey = self.key - if not self.category in universe.categories: self.category = "other" + if not self.category in universe.categories: + self.category = "other" + self.subkey = self.key universe.categories[self.category][self.subkey] = self # get an appropriate filename for the origin @@ -271,11 +273,15 @@ class Element: class DataFile: """A file containing universe elements.""" def __init__(self, filename, universe): + self.filename = filename + self.universe = universe + self.load() + def load(self): + """Read a file and create elements accordingly.""" self.modified = False self.data = RawConfigParser() - if access(filename, R_OK): self.data.read(filename) - self.filename = filename - universe.files[filename] = self + if access(self.filename, R_OK): self.data.read(self.filename) + self.universe.files[self.filename] = self if self.data.has_option("__control__", "include_files"): includes = makelist(self.data.get("__control__", "include_files")) else: includes = [] @@ -283,26 +289,24 @@ class DataFile: origins = makedict(self.data.get("__control__", "default_files")) for key in origins.keys(): if not key in includes: includes.append(key) - universe.default_origins[key] = origins[key] - if not key in universe.categories: - universe.categories[key] = {} + self.universe.default_origins[key] = origins[key] + if not key in self.universe.categories: + self.universe.categories[key] = {} if self.data.has_option("__control__", "private_files"): for item in makelist(self.data.get("__control__", "private_files")): if not item in includes: includes.append(item) - if not item in universe.private_files: + if not item in self.universe.private_files: if not isabs(item): - item = path_join(dirname(filename), item) - universe.private_files.append(item) + item = path_join(dirname(self.filename), item) + self.universe.private_files.append(item) for section in self.data.sections(): if section != "__control__": - Element(section, universe, filename) + Element(section, self.universe, self.filename) for include_file in includes: if not isabs(include_file): - include_file = path_join(dirname(filename), include_file) - DataFile(include_file, universe) - def is_writeable(self): - """Returns True if the __control__ read_only is False.""" - return not self.data.has_option("__control__", "read_only") or not self.data.getboolean("__control__", "read_only") + include_file = path_join(dirname(self.filename), include_file) + if include_file not in self.universe.files or not self.universe.files[include_file].is_writeable(): + DataFile(include_file, self.universe) def save(self): """Write the data, if necessary.""" @@ -337,6 +341,9 @@ class DataFile: # unset the modified flag self.modified = False + def is_writeable(self): + """Returns True if the __control__ read_only is False.""" + return not self.data.has_option("__control__", "read_only") or not self.data.getboolean("__control__", "read_only") class Universe: """The universe.""" @@ -345,9 +352,8 @@ class Universe: self.categories = {} self.contents = {} self.default_origins = {} - self.files = {} self.private_files = [] - self.loglines = {} + self.loglines = [] self.pending_events_long = {} self.pending_events_short = {} self.userlist = [] @@ -369,11 +375,15 @@ class Universe: if access(filename, R_OK): break if not isabs(filename): filename = abspath(filename) - DataFile(filename, self) + self.filename = filename + self.load() + def load(self): + """Load universe data from persistent storage.""" + self.files = {} + DataFile(self.filename, self) def save(self): """Save the universe to persistent storage.""" for key in self.files: self.files[key].save() - def initialize_server_socket(self): """Create and open the listening socket.""" @@ -843,38 +853,44 @@ def log(message, level=0): while 0 < len(universe.loglines) >= max_log_lines: del universe.loglines[0] universe.loglines.append((level, timestamp + " " + line)) -def get_loglines(level, start, stop=0): +def get_loglines(level, start, stop): """Return a specific range of loglines filtered by level.""" - # begin with a blank message - message = "" - # filter the log lines - loglines = filter(lambda x,y: x>=level, universe.loglines) + loglines = filter(lambda x: x[0]>=level, universe.loglines) - # we need this in several places - count = len(loglines) + # we need these in several places + total_count = str(len(universe.loglines)) + filtered_count = len(loglines) # don't proceed if there are no lines - if count: + if filtered_count: # can't start before the begining or at the end - if start > count: start = count + if start > filtered_count: start = filtered_count if start < 1: start = 1 # can't stop before we start - if stop >= start: stop = start - 1 + if stop > start: stop = start + elif stop < 1: stop = 1 # some preamble - message += "There are " + str(len(universe.loglist)) - message += " log lines in memory and " + str(count) + message = "There are " + str(total_count) + message += " log lines in memory and " + str(filtered_count) message += " at or above level " + str(level) + "." - message += " The lines from " + str(stop) - message += " to " + str(start) + " are:$(eol)$(eol)" + message += " The lines from " + str(stop) + " to " + str(start) + message += " are:$(eol)$(eol)" # add the text from the selected lines - for line in loglines[-start:-stop]: - message += " " + line[1] + "$(eol)" + if stop > 1: range_lines = loglines[-start:-(stop-1)] + else: range_lines = loglines[-start:] + for line in range_lines: + message += " (" + str(line[0]) + ") " + line[1] + "$(eol)" + + # there were no lines + else: + message = "None of the " + str(total_count) + message += " lines in memory matches your request." # pass it back return message @@ -1088,6 +1104,7 @@ def on_pulse(): def reload_data(): """Reload data into new persistent objects.""" for user in universe.userlist[:]: user.reload() + universe.load() def check_for_connection(listening_socket): """Check for a waiting connection and return a new user object.""" @@ -1445,13 +1462,14 @@ def handler_active(user): else: command = None # if it's allowed, do it - if user.avatar.can_run(command): exec(command.get("action")) + actor = user.avatar + if actor.can_run(command): exec(command.get("action")) # otherwise, give an error - elif command_name: command_error(user.avatar, input_data) + elif command_name: command_error(actor, input_data) # if no input, just idle back with a prompt - else: user.send("", just_prompt=True) + else: actor("", just_prompt=True) def command_halt(actor, parameters): """Halt the world.""" @@ -1482,8 +1500,8 @@ def command_reload(actor): def command_quit(actor): """Leave the world and go back to the main menu.""" if actor.owner: - actor.owner.deactivate_avatar() actor.owner.state = "main_utility" + actor.owner.deactivate_avatar() def command_help(actor, parameters): """List available commands and provide help for commands.""" @@ -1599,55 +1617,78 @@ def command_say(actor, parameters): def command_show(actor, parameters): """Show program data.""" message = "" - if parameters.find(" ") < 1: - if parameters == "time": - message = universe.categories["internal"]["counters"].get("elapsed") + " increments elapsed since the world was created." - elif parameters == "categories": - message = "These are the element categories:$(eol)" - categories = universe.categories.keys() - categories.sort() - for category in categories: message += "$(eol) $(grn)" + category + "$(nrm)" - elif parameters == "files": - message = "These are the current files containing the universe:$(eol)" - filenames = universe.files.keys() - filenames.sort() - for filename in filenames: message += "$(eol) $(grn)" + filename + "$(nrm)" - else: message = "" - else: - arguments = parameters.split() - if arguments[0] == "category": - if arguments[1] in universe.categories: - message = "These are the elements in the \"" + arguments[1] + "\" category:$(eol)" - elements = universe.categories[arguments[1]].keys() - elements.sort() - for element in elements: - message += "$(eol) $(grn)" + universe.categories[arguments[1]][element].key + "$(nrm)" - elif arguments[0] == "element": - if arguments[1] in universe.contents: - message = "These are the properties of the \"" + arguments[1] + "\" element:$(eol)" - element = universe.contents[arguments[1]] - facets = element.facets() - facets.sort() - for facet in facets: - message += "$(eol) $(grn)" + facet + ": $(red)" + escape_macros(element.get(facet)) + "$(nrm)" - elif arguments[0] == "result": - if len(arguments) > 1: - try: - message = repr(eval(" ".join(arguments[1:]))) - except: - message = "Your expression raised an exception!" - elif arguments[0] == "log": - if match("^\d+$", arguments[1]) and int(arguments[1]) > 0: - linecount = int(arguments[1]) - if linecount > len(universe.loglines): linecount = len(universe.loglist) - message = "There are " + str(len(universe.loglist)) + " log lines in memory." - message += " The most recent " + str(linecount) + " lines are:$(eol)$(eol)" - for line in universe.loglist[-linecount:]: - message += " " + line + "$(eol)" - else: message = "\"" + arguments[1] + "\" is not a positive integer greater than 0." - if not message: - if parameters: message = "I don't know what \"" + parameters + "\" is." - else: message = "What do you want to show?" + arguments = parameters.split() + if not parameters: message = "What do you want to show?" + elif arguments[0] == "time": + message = universe.categories["internal"]["counters"].get("elapsed") + " increments elapsed since the world was created." + elif arguments[0] == "categories": + message = "These are the element categories:$(eol)" + categories = universe.categories.keys() + categories.sort() + for category in categories: message += "$(eol) $(grn)" + category + "$(nrm)" + elif arguments[0] == "files": + message = "These are the current files containing the universe:$(eol)" + filenames = universe.files.keys() + filenames.sort() + for filename in filenames: + if universe.files[filename].is_writeable(): status = "rw" + else: status = "ro" + message += "$(eol) $(red)(" + status + ") $(grn)" + filename + "$(nrm)" + elif arguments[0] == "category": + if len(arguments) != 2: message = "You must specify one category." + elif arguments[1] in universe.categories: + message = "These are the elements in the \"" + arguments[1] + "\" category:$(eol)" + elements = [(universe.categories[arguments[1]][x].key) for x in universe.categories[arguments[1]].keys()] + elements.sort() + for element in elements: + message += "$(eol) $(grn)" + element + "$(nrm)" + else: message = "Category \"" + arguments[1] + "\" does not exist." + elif arguments[0] == "file": + if len(arguments) != 2: message = "You must specify one file." + elif arguments[1] in universe.files: + message = "These are the elements in the \"" + arguments[1] + "\" file:$(eol)" + elements = universe.files[arguments[1]].data.sections() + elements.sort() + for element in elements: + message += "$(eol) $(grn)" + element + "$(nrm)" + else: message = "Category \"" + arguments[1] + "\" does not exist." + elif arguments[0] == "element": + if len(arguments) != 2: message = "You must specify one element." + elif arguments[1] in universe.contents: + element = universe.contents[arguments[1]] + message = "These are the properties of the \"" + arguments[1] + "\" element (in \"" + element.origin.filename + "\"):$(eol)" + facets = element.facets() + facets.sort() + for facet in facets: + message += "$(eol) $(grn)" + facet + ": $(red)" + escape_macros(element.get(facet)) + "$(nrm)" + else: message = "Element \"" + arguments[1] + "\" does not exist." + elif arguments[0] == "result": + if len(arguments) < 2: message = "You need to specify an expression." + else: + try: + message = repr(eval(" ".join(arguments[1:]))) + except: + message = "Your expression raised an exception!" + elif arguments[0] == "log": + if len(arguments) == 4: + if match("^\d+$", arguments[3]) and int(arguments[3]) >= 0: + stop = int(arguments[3]) + else: stop = -1 + else: stop = 0 + if len(arguments) >= 3: + if match("^\d+$", arguments[2]) and int(arguments[2]) > 0: + start = int(arguments[2]) + else: start = -1 + else: start = 10 + if len(arguments) >= 2: + if match("^\d+$", arguments[1]) and 0 <= int(arguments[1]) <= 9: + level = int(arguments[1]) + else: level = -1 + else: level = 1 + if level > -1 and start > -1 and stop > -1: + message = get_loglines(level, start, stop) + else: message = "When specified, level must be 0-9 (default 1), start and stop must be >=1 (default 10 and 1)." + else: message = "I don't know what \"" + parameters + "\" is." actor.send(message) def command_create(actor, parameters): -- 2.11.0