📄 optionsclass.py
字号:
return False raise TypeError, self.name + " must be True or False" if self.multiple_values_allowed(): # This will fall apart if the allowed_value is a tuple, # but not a homogenous one... if isinstance(self.allowed_values, types.StringTypes): vals = list(self._split_values(value)) else: if isinstance(value, types.TupleType): vals = list(value) else: vals = value.split() if len(self.default_value) > 0: to_type = type(self.default_value[0]) else: to_type = types.StringType for i in range(0, len(vals)): vals[i] = self._convert(vals[i], to_type) return tuple(vals) else: return self._convert(value, svt) raise TypeError, self.name + " has an invalid type." def _convert(self, value, to_type): '''Convert an int, float or string to the specified type.''' if to_type == type(value): # already the correct type return value if to_type == types.IntType: return locale.atoi(value) if to_type == types.FloatType: return locale.atof(value) if to_type in types.StringTypes: return str(value) raise TypeError, "Invalid type." def unconvert(self): '''Convert value from the appropriate type to a string.''' if type(self.value) in types.StringTypes: # nothing to do return self.value if self.is_boolean(): # A wee bit extra for Python 2.2 if self.value == True: return "True" else: return "False" if type(self.value) == types.TupleType: if len(self.value) == 0: return "" if len(self.value) == 1: v = self.value[0] if type(v) == types.FloatType: return locale.str(self.value[0]) return str(v) # We need to separate out the items strval = "" # We use a character that is invalid as the separator # so that it will reparse correctly. We could try all # characters, but we make do with this set of commonly # used ones - note that the first one that works will # be used. Perhaps a nicer solution than this would be # to specifiy a valid delimiter for all options that # can have multiple values. Note that we have None at # the end so that this will crash and die if none of # the separators works <wink>. if self.delimiter is None: if type(self.allowed_values) == types.TupleType: self.delimiter = ' ' else: v0 = self.value[0] v1 = self.value[1] for sep in [' ', ',', ':', ';', '/', '\\', None]: # we know at this point that len(self.value) is at # least two, because len==0 and len==1 were dealt # with as special cases test_str = str(v0) + sep + str(v1) test_tuple = self._split_values(test_str) if test_tuple[0] == str(v0) and \ test_tuple[1] == str(v1) and \ len(test_tuple) == 2: break # cache this so we don't always need to do the above self.delimiter = sep for v in self.value: if type(v) == types.FloatType: v = locale.str(v) else: v = str(v) strval += v + self.delimiter strval = strval[:-len(self.delimiter)] # trailing seperator else: # Otherwise, we just hope str() will do the job strval = str(self.value) return strval def is_boolean(self): '''Return True iff the option is a boolean value.''' # This is necessary because of the Python 2.2 True=1, False=0 # cheat. The valid values are returned as 0 and 1, even if # they are actually False and True - but 0 and 1 are not # considered valid input (and 0 and 1 don't look as nice) # So, just for the 2.2 people, we have this helper function try: if type(self.allowed_values) == types.TupleType and \ len(self.allowed_values) > 0 and \ type(self.allowed_values[0]) == types.BooleanType: return True return False except AttributeError: # If the user has Python 2.2 and an option has valid values # of (0, 1) - i.e. integers, then this function will return # the wrong value. I don't know what to do about that without # explicitly stating which options are boolean if self.allowed_values == (False, True): return True return Falseclass OptionsClass(object): def __init__(self): self.verbose = None self._options = {} self.restore_point = {} self.conversion_table = {} # set by creator if they need it. # # Regular expressions for parsing section headers and options. # Lifted straight from ConfigParser # SECTCRE = re.compile( r'\[' # [ r'(?P<header>[^]]+)' # very permissive! r'\]' # ] ) OPTCRE = re.compile( r'(?P<option>[^:=\s][^:=]*)' # very permissive! r'\s*(?P<vi>[:=])\s*' # any number of space/tab, # followed by separator # (either : or =), followed # by any # space/tab r'(?P<value>.*)$' # everything up to EOL ) def update_file(self, filename): '''Update the specified configuration file.''' sectname = None optname = None out = TemporaryFile() if os.path.exists(filename): f = file(filename, "r") else: # doesn't exist, so create it - all the changed options will # be added to it if self.verbose: print >> sys.stderr, "Creating new configuration file", print >> sys.stderr, filename f = file(filename, "w") f.close() f = file(filename, "r") written = [] vi = ": " # default; uses the one from the file where possible while True: line = f.readline() if not line: break # comment or blank line? if line.strip() == '' or line[0] in '#;': out.write(line) continue if line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR": # no leading whitespace out.write(line) continue # continuation line? if line[0].isspace() and sectname is not None and optname: continue # a section header or option header? else: # is it a section header? mo = self.SECTCRE.match(line) if mo: # Add any missing from the previous section if sectname is not None: self._add_missing(out, written, sectname, vi, False) sectname = mo.group('header') # So sections can't start with a continuation line optname = None if sectname in self.sections(): out.write(line) # an option line? else: mo = self.OPTCRE.match(line) if mo: optname, vi, optval = mo.group('option', 'vi', 'value') if vi in ('=', ':') and ';' in optval: # ';' is a comment delimiter only if it follows # a spacing character pos = optval.find(';') if pos != -1 and optval[pos-1].isspace(): optval = optval[:pos] optval = optval.strip() # allow empty values if optval == '""': optval = '' optname = optname.rstrip().lower() if self._options.has_key((sectname, optname)): out.write(optname) out.write(vi) newval = self.unconvert(sectname, optname) out.write(newval.replace("\n", "\n\t")) out.write('\n') written.append((sectname, optname)) for sect in self.sections(): self._add_missing(out, written, sect, vi) f.close() out.flush() if self.verbose: # save a backup of the old file shutil.copyfile(filename, filename + ".bak") # copy the new file across f = file(filename, "w") out.seek(0) shutil.copyfileobj(out, f) out.close() f.close() def _add_missing(self, out, written, sect, vi, label=True): # add any missing ones, where the value does not equal the default for opt in self.options_in_section(sect): if not (sect, opt) in written and \ self.get(sect, opt) != self.default(sect, opt): if label: out.write('[') out.write(sect) out.write("]\n") label = False out.write(opt) out.write(vi) newval = self.unconvert(sect, opt) out.write(newval.replace("\n", "\n\t")) out.write('\n') written.append((sect, opt)) def load_defaults(self, defaults): '''Load default values (stored in Options.py).''' for section, opts in defaults.items(): for opt in opts: # If first item of the tuple is a sub-class of Option, then # instantiate that (with the rest as args). Otherwise, # assume standard Options class. klass = Option args = opt try: if issubclass(opt[0], Option): klass = opt[0] args = opt[1:] except TypeError: # opt[0] not a class pass o = klass(*args) self._options[section, o.name] = o def set_restore_point(self): '''Remember what the option values are right now, to be able to go back to them, via revert_to_restore_point(). Any existing restore point is wiped. Restore points do not persist over sessions. ''' self.restore_point = {} for key, opt_obj in self._options.iteritems(): self.restore_point[key] = opt_obj.get() def revert_to_restore_point(self): '''Restore option values to their values when set_restore_point() was last called. If set_restore_point() has not been called, then this has no effect. If new options have been added since set_restore_point, their values are not effected. ''' for key, value in self.restore_point.iteritems(): self._options[key].set(value) def merge_files(self, file_list): for f in file_list: self.merge_file(f) def convert_and_set(self, section, option, value): value = self.convert(section, option, value) self.set(section, option, value)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -