SEP = "." TYPESEP = ":" SPECIAL_CHARS = ( SEP, TYPESEP ) ESC_CHAR = "\\" DEAD_CHAR = chr(0) def escape(pathname): pathname = pathname.replace(ESC_CHAR, 2*ESC_CHAR) for character in SPECIAL_CHARS: pathname = pathname.replace(character, ESC_CHAR+character) return pathname def unescape(pathname): for character in SPECIAL_CHARS: pathname = pathname.replace(ESC_CHAR+character, character) pathname = pathname.replace(2*ESC_CHAR, ESC_CHAR) return pathname def litsplit(original, sep=SEP, count=-1): original = original.replace(ESC_CHAR+sep, DEAD_CHAR) return [x.replace(DEAD_CHAR,ESC_CHAR+sep) for x in original.split(sep,count)] def chomp(original, sep=SEP, count=1): if count > 0: return sep.join(litsplit(original, sep)[:-count]) elif count < 0: templist=litsplit(original, sep) return sep.join(templist[len(templist)+count:]) else: return original def isabs(facet, sep=SEP): if facet and facet.startswith(sep): return True else: return False def load(universe={}, filename=None, sep=SEP): import os, os.path, re if not filename: possible_filenames = [ ".mudpyrc", ".mudpy/mudpyrc", ".mudpy/mudpy.conf", "mudpy.conf", "etc/mudpy.conf", "/usr/local/mudpy/mudpy.conf", "/usr/local/mudpy/etc/mudpy.conf", "/etc/mudpy/mudpy.conf", "/etc/mudpy.conf" ] for filename in possible_filenames: if os.access(filename, os.R_OK): break if not os.path.isabs(filename): filename = os.path.join(os.getcwd(), filename) todo = [ ( "", filename ) ] while todo: anchor, datafile = todo.pop() datadir = os.path.dirname(datafile) if os.access(datafile, os.R_OK): data = file(datafile) for line in data: subanchor = "" if not ( re.match("^\w*#", line) or re.match("^\w*$", line) ): key, value = [ x.strip() for x in litsplit(line, "=", 1) ] value = eval( value, { "__builtins__": { "False": False, "True": True } } ) if key.startswith("!"): addkey = ".mudpy.file."+escape(datafile)+sep+key[1:] universe[addkey] = value if key.startswith("!load:"): subanchor = anchor+sep+key[6:] elif key == "!load": subanchor = anchor if subanchor: for item in value: if item.startswith("file:"): addfile = item[5:] if not addfile.startswith(os.path.sep): addfile = os.path.join( datadir, addfile ) if not ( subanchor, addfile ) in todo: todo = [ ( subanchor, addfile ) ] + todo else: if not key.startswith(sep): key = sep.join( [ anchor, key ] ) universe[key] = value if key.startswith(".mudpy.data"): if key.startswith(".mudpy.data:"): subanchor = key.replace(".mudpy.data:", sep, 1) elif key == ".mudpy.data": subanchor = sep if subanchor and value.startswith("file:"): addfile = unescape(value.replace("file:", "", 1)) if not os.path.isabs(addfile): addfile = os.path.join( datadir, addfile ) if not ( subanchor, addfile ) in todo: todo = [ ( subanchor, addfile ) ] + todo data.close() else: print("WARNING: Cannot open " + datafile + " for reading.") def save(universe): keylist = filter(lambda x: x.startswith('.mudpy.file.'), universe.keys()) keylist.sort() print("meta = {") for key in keylist: print(" " + key + " = " + repr(universe[key]) + ",") print(" }\n") keylist = universe.keys() keylist.sort() print("universe = {") for key in keylist: print(" " + key + " = " + repr(universe[key]) + ",") print(" }\n") def validate(universe, sep=SEP, typesep=TYPESEP): for key, value in universe.items(): facet_name = litsplit(litsplit(key)[-1], typesep)[0] if facet_name == "facet": facet_def = ".mudpy.facet" else: facet_def = ".mudpy.facet:" + facet_name facet_type = str( type(value) ) if facet_def not in universe: print("WARNING: No strict typing for "+facet_name+" data, assuming "+facet_type+sep) else: facet_check = "" if facet_type != facet_check: print("WARNING: Facet "+facet_name+" is "+facet_type+" but should be "+facet_check+sep) def groups(universe): groups = [] for facet in universe.keys(): group = chomp(facet, count=2) if group not in groups: groups.append(group) return groups def elements(universe, group, sep=SEP): elements = [] for facet in universe.keys(): if facet.startswith(group+sep): if len(litsplit(facet.replace(group+sep, "", 1))) < 3: element = chomp(facet) if element not in elements: elements.append(element) return elements def facets(universe, element, sep=SEP): facets = [] for facet in universe.keys(): if facet.startswith(element+sep): if len(litsplit(facet.replace(element+sep, "", 1))) < 2 and facet not in facets: facets.append(facet) return facets def adjacent(reference, peer, sep=SEP): if peer.startswith(sep): return peer else: return chomp(reference) + sep + peer def ancestors(universe, element, deep=10): ancestors = [] depth = 0 while True: if ancestors: cursor = ancestors[depth] depth += 1 else: cursor = element next = get(universe, "inherit", cursor, deep=0) if next: for parent in get(universe, "inherit", cursor, deep=0): parent = adjacent(cursor, parent) if parent not in ancestors and parent != element: ancestors.append(parent) if depth >= len(ancestors) or depth >= deep: break return ancestors def innate(universe, element): innate = [] for facet in facets(universe, element): relative = chomp(facet, count=-1) if relative != "inherit": innate.append(relative) return innate def inherited(universe, element, deep=10): inherited = [] for ancestor in ancestors(universe, element, deep): for facet in facets(universe, ancestor): if facet not in inherited: relative = chomp(facet, count=-1) if relative != "inherit": inherited.append(relative) return inherited def get(universe, facet, element="", group="", reference="", deep=10, sep=SEP): if isabs(element): facet = sep.join((element, facet)) elif isabs(group): facet = sep.join((group, element, facet)) if isabs(reference): facet = adjacent(reference, chomp(facet, count=-1)) element = chomp(facet) ancestors = [] depth = 0 while True: if ancestors: cursor = ancestors[depth] depth += 1 else: cursor = chomp(facet) possible = adjacent(cursor+sep, chomp(facet, count=-1)) if possible in universe: return universe[possible] next = sep.join((cursor, "inherit")) if next in universe: for parent in universe[next]: parent = adjacent(cursor, parent) if parent not in ancestors and parent != element: ancestors.append(parent) if depth >= len(ancestors) or depth >= deep: return None