python-CFG-0.0.9/000075500000000000000000000000001072760770200134445ustar00rootroot00000000000000python-CFG-0.0.9/CFG/000075500000000000000000000000001072760770200140435ustar00rootroot00000000000000python-CFG-0.0.9/CFG/Application.py000064400000000000000000000162021072760770200166610ustar00rootroot00000000000000""" ====================================================== Проект: Универсальный конфигуратор Модуль: Приложение-прототип Автор: Андрей Орлов Версия: ${Id: } ------------------------------------------------------ Дата: Mon Nov 19 21:09:12 MSK 2001 ====================================================== """ import sys import os import string import Parser import CFG from Exceptions import * class Application : """ Универсальный конфигуратор / Приложение-прототип : Простое приложение -- загружаем конфигурацию из файла в домашнем каталоге и перекрываем ее командной строкой. Резервируются следующие ключи : --verbose - увеличивает счетчик болтливости; --verbose-stderr- болтовня херачится на stderr, не stdout --debug - запуск в отладочном режиме; --help - выводит помощь; --dump - выводит дамп конфига; --dump_level - тип дампа конфига; --exit - выход сразу после загрузки конфигов; В конфигурации определяется ключик "verbose" & "debug", управляющие отображением. """ def __init__(self,prefix=None,cfg={},cfg_names = ('/etc/','~/.','.')) : if not prefix : self.prefix = os.path.splitext(os.path.basename(sys.argv[0]))[0] else : self.prefix = prefix self.cfg = cfg self.cfg.application = self self.cfg_names = cfg_names def verbose(self,fmt,level=1,*argv) : if len(argv)==1 and type(argv[0]) == type({}) : argv = argv[0] if level<=self.cfg['verbose-level'] : std = sys.stdout if self.cfg['verbose-stderr'] : std = sys.stderr std.write( '?V - %s - ' % self.prefix + fmt % argv + "\n") std.flush() def warning(self,fmt,level=0,*argv) : if len(argv)==1 and type(argv[0]) == type({}) : argv = argv[0] if level<=self.cfg['verbose-level'] : std = sys.stderr std.write( '?W - %s - ' % self.prefix + fmt % argv + "\n") std.flush() def fatal(self,fmt,level=0,exit=1,*argv) : if len(argv)==1 and type(argv[0]) == type({}) : argv = argv[0] if level<=self.cfg['verbose-level'] : std = sys.stderr std.write( '?F - %s - ' % self.prefix + fmt % argv + "\n") std.flush() sys.exit(1) def configure(self) : try : if 0 == len(filter(lambda x : '--cfg_load'==x[0:len('--cfg_load')],sys.argv[1:])) : for prefix in self.cfg_names : try : fn = os.path.expanduser(string.join((prefix,self.prefix,'rc'),"")) f = open(fn) except IOError : continue self.cfg = self.cfg.duplicate(realm=fn) Parser.ParseFile(self.cfg,f) f.close() self.cfg = self.cfg.duplicate(realm='Environment') Parser.ParseEnv(self.cfg,self.prefix + '_') self.cfg = self.cfg.duplicate(realm='Options') Parser.ParseOpt(self.cfg) except ConfigError,msg : self.fatal("%s",0,0,msg) return 1 def init(self) : return 1 def main(self,args=None) : return self.exec_seq(args) def exec_seq(self,args=None) : if not args : args = self.cfg.arguments for item in args : s = 'arg_'+item if hasattr(self,s) : apply(getattr(self,s),(),{}) else : self.fatal('Неизвестная команда %s',0,1,item) return 1 def exec_cmd(self,args=None) : if not args : args = self.cfg.arguments try : cmd = 'arg_%s' % args[0] except IndexError : self.fatal('Не указано ни одной команды') if hasattr(self,cmd) : d = {} as = [] for item in args[1:] : try : a,v = string.split(item,'=',1) d[a] = v except : as.append(item) try : return apply(getattr(self,cmd),as,d) except TypeError,msg : if self.cfg['debug'] : raise self.fatal('Неверный ситаксис команды %s : %s',0,1,args[0],msg) else : self.fatal('Неизвестная команда "%s"' % args[0]) def finit(self) : self.verbose('END Of Application named %s',1,self.prefix) return 1 def run(self) : if self.configure() : if self.cfg.has_key('debug') and self.cfg['debug'] : self.verbose('Запуск с отладкой') res = self.init() and self.main() and self.finit() else : try : res = self.init() except SystemExit : raise except KeyboardInterrupt : self.fatal('Инициализация прервана') except : self.fatal('Ошибка во время инициализации') if res is not None : try : try : res = self.main() except SystemExit : raise except KeyboardInterrupt : self.fatal('Выполнение прервано') except : self.fatal('Ошибка во время выполнения') finally : try : self.finit() except SystemExit : raise except KeyboardInterrupt : self.fatal('Завершение прервано') except : self.fatal('Ошибка во время завершения') return res def prnt(self) : if type(self.cfg) is type({}) : print '=' * 72 k = self.cfg.keys() k.sort() for item in k : if type(self.cfg[item]) is type('') : s = '"%s"' % self.cfg[item] else : s = str(self.cfg[item]) print "%-40s%-40s" % ("%s = " % item,str(s)) print '=' * 72 else : self.cfg.prnt() python-CFG-0.0.9/CFG/CFG.py000064400000000000000000000335041072760770200150210ustar00rootroot00000000000000""" ====================================================== Проект: Универсальный конфигуратор Модуль: Хранение конфигурации Автор: Андрей Орлов Версия: ${Id: } ------------------------------------------------------ Дата: Mon Nov 19 21:09:12 MSK 2001 ====================================================== """ import UserDict import sys from cPickle import dump,load from Exceptions import * import Parser class BaseConfig (UserDict.UserDict) : """ Универсальный конфигуратор / хранение конфигурации : Базовый класс -- конфигурация сохраняется посредством последовательности словарей, в которых каждый последующий наследует атрибуты предыдущего. """ def __init__(self,dict=None, parent={},realm='',arguments=[]) : self.parent = parent # Родительский объект self.realm = realm # Название данной секции self.arguments = arguments # Ссылка на массив аргументов командной строки self.sections = [] # Секции UserDict.UserDict.__init__(self,dict) def __len__(self): return len(self.data) + self.parent.__len__() def __getattr__(self,attr) : if attr == 'application' : try : return UserDict.UserDict.__getattr__(self,attr) except AttributeError : self.application = getattr(self.parent,attr) return self.application else : return UserDict.UserDict.__getattr__(self,attr) def __getitem__(self,key) : try : return self.data[key] except KeyError : return self.parent[key] def __setitem__(self,key,value) : s = 'switch_' + key if hasattr(self,s) and callable(getattr(self,s)) : apply(getattr(self,s),(key,value),{}) else : self.data[key] = value def use(self,key) : s = 'switch_' + key if hasattr(self,s) and callable(getattr(self,s)) : try : apply(getattr(self,s),(key,),{}) except TypeError : raise ConfigError,'Ключ %s требует аргумент' % key else : self[key] = self.default(key) def setparent(self,cfg) : parent = self.cfg def keys(self) : return self.data.keys() + self.parent.keys() def items(self) : return self.data.items() + self.parent.items() def values(self) : return self.data.values() + self.parent.values() def has_key(self, key) : return self.data.has_key(key) or self.parent.has_key(key) def duplicate(self,dict=None,realm='') : return self.__class__(parent=self,realm=realm,dict=dict,arguments=self.arguments) def default(self,attr) : return 1 def section(self,dict=None,realm='') : try : if dict : self.data[realm].update(dict) return self.data[realm] except KeyError : self.sections.append(realm) return self.__class__(parent=self,realm=realm,dict=dict,arguments=self.arguments) def parents(self) : ps = [] cr = self while type(cr) is not type({}) : ps.append(cr) cr = cr.parent ps.append(cr) return ps def prnt(self,min=0,max=-1) : for item in self.parents()[min:max] : print '===> %-20s =' % item.realm + '=' * 45 self.save(cfg=item.data,plain=1) print '=' * 72 def getdict(self) : dict = self.parent.getdict() dict.update(self.dict) return dict def dictionary(self,min=0,max=-1) : ps = self.parents() cfg = {} for d in ps[min:max] : cfg.update(d.data) return cfg def filtered(self,*items) : cfg = {} for item in items : try : cfg[item] = self[item] except KeyError : pass # print cfg return cfg def save(self,ouf=sys.stdout,cfg=None,plain=1) : if cfg is None : cfg = self.data ks = cfg.keys() ks.sort() for item in filter(lambda x,cfg=cfg : not isinstance(cfg[x],BaseConfig), ks ) : if type(cfg[item]) is type('') : s = '"%s"' % cfg[item] else : s = str(cfg[item]) ouf.write( "%-40s%s\n" % ("%s = " % item,str(s)) ) for item in filter(lambda x,cfg=cfg : isinstance(cfg[x],BaseConfig), ks ) : print "\n[%s]\n" % item if plain : cfg[item].save(cfg=cfg[item].data,plain=plain) else : cfg[item].save(plain=plain) class Switch : """\ Описание: Универсальный конфигуратор / хранение конфигурации : Предопределенные ключи. Обработка ключей, требуемая для конфигурации Application. Автор: Андрей Орлов Дата: Wed Nov 21 13:09:53 MSK 2001 Ключи: verbose - увеличить (задать) уровень трассировки, verbose-stderr - выводить трассировку на stderr, debug - запуск в отладочном режиме, dump = type - вывести дамп конфигурации, тип может быть: detail - детальная схема конфигурации, content - список секций конфигурации, plain - конфигурационный файл dump-min - минимальный уровень дампа конфигурации, dump-max - максимальный уровень дампа конфигурации, help = [chapter]- вывести хелп, exit - прекратить исполнение программы и выйти, cfg_dump - сохранить конфигурацию в виде бинарного дампа, cfg_load - загрузить конфигурацию из бинарного дамп, cfg_read - прочитать конфигурационный файл, cfg_clean - восстановить умолчания в конфигурации. """ default_cfg = { 'verbose-level' : 1, 'verbose-stderr': 0, 'debug' : 0, 'dump-level' : 0, 'dump-min' : 2, 'dump-max' : -2, } def __init__(self) : if type(self.parent) is type({}): for attr,value in self.default_cfg.items() : if not self.data.has_key(attr) : self.data[attr] = value def switch_verbose(self,attr,value=1) : if value is not None : self['verbose-level'] = int(value) else : self['verbose-level'] = self['verbose-level'] + 1 def switch_dump(self,attr,value='detail') : if value == 'detail' : print '# Детальный дамп конфигурации [%i:%i]' % (self['dump-min'],self['dump-max']) self.prnt(self['dump-min'],self['dump-max']) elif value == 'plain' : print '# Плоский дамп конфигурации [%i:%i]' % (self['dump-min'],self['dump-max']) self.save(cfg=self.dictionary(self['dump-min'],self['dump-max'])) elif value == 'content' : print '# Очередь конфигураций [%i:%i]' % (self['dump-min'],self['dump-max']) n = self['dump-min'] for item in self.parents()[self['dump-min']:self['dump-max']] : print n,":",item.realm n = n+1 else : print '# Возможный тип дампа - detail,plain,content' def switch_help(self,attr,value=None) : if value == 'cfg' : print self.__doc__ else : cfg = {'application':sys.argv[0], 'prefix':sys.prefix} cfg.update(self.dictionary(0,-1)) print self.application.__doc__ % cfg def switch_exit(self,attr,value=None) : sys.exit(0) def switch_cfg_dump(self,attr,value) : try : f = open(value,'w') dump(self,f) f.close() except IOError,msg : raise ConfigError,'Не удается сохранить дамп конфигурации в (%s): %s' % (value,msg) def switch_cfg_load(self,attr,value) : """ Загрузка конфигурации из ранее сохраненного дампа """ try : value = str(value) if not hasattr(self,'hasbeenloaded') : f = open(value,'r') self.parent = load(f) f.close() self.hasbeenloaded = 1 except IOError,msg : raise ConfigError,'Не удается загрузить дамп конфигурации (%s): %s' % (value,msg) except EOFError,msg : raise ConfigError,'Не удается загрузить дамп конфигурации (%s): внезапный конец файла' % (value,) def switch_cfg_read(self,attr,value) : self.parent = self.__class__(realm=value,parent=self.parent) Parser.ParseFile(self.parent,open(value,'r')) def switch_cfg_clean(self,attr,value=None) : if value : try : self[value] = self.parents()[-2][value] except KeyError : raise ConfigError,'Неизвестный параметр "%s"' % value else : self.parent = self.parents()[-2] class Strict : """ Универсальный конфигуратор / хранение конфигурации : Строгая загрузка конфига - допускает загрузку переменных только из числа уже определенных, причем грузятся переменные того же типа.""" def __setitem__(self,key,value) : s = 'switch_' + key if hasattr(self,s) and callable(getattr(self,s)) : apply(getattr(self,s),(key,value),{}) else : if not isinstance(value,BaseConfig) : if not self.has_key(key) : raise ConfigError,'Неизвестный ключ "%s"' % key elif type(self[key]) != type(value) : raise ConfigError,'Неверный тип данных ключа "%s" (%s -> %s)' % (key,type(value),type(self[key])) self.data[key] = value class Config (Switch, BaseConfig) : __doc__ = """\ Описание: Универсальный конфигуратор / хранение конфигурации : Простая конфигурация. """ + Switch.__doc__ def __init__(self,dict=None, parent={},realm='',arguments=[],cfg_load=None) : if cfg_load : self.cfg_load('cfg_load',cfg_load) else : BaseConfig.__init__(self,dict,parent,realm,arguments) Switch.__init__(self) class ConfigS (Strict, Config) : __doc__ = """\ Описание: Универсальный конфигуратор / хранение конфигурации : Простая конфигурация с проверкой. """ + Switch.__doc__ python-CFG-0.0.9/CFG/Exceptions.py000064400000000000000000000006271072760770200165430ustar00rootroot00000000000000""" ====================================================== Проект: Универсальный конфигуратор Модуль: Исключения Автор: Андрей Орлов Версия: ${Id: } ------------------------------------------------------ Дата: Mon Nov 19 21:09:12 MSK 2001 ====================================================== """ ConfigError = 'ConfigError' python-CFG-0.0.9/CFG/Parser.py000064400000000000000000000123151072760770200156530ustar00rootroot00000000000000""" ====================================================== Проект: Универсальный конфигуратор Модуль: Разбор конфигурации Автор: Андрей Орлов Версия: ${Id: } ------------------------------------------------------ Дата: Mon Nov 19 21:09:12 MSK 2001 ====================================================== """ import sys import string import os import re from Exceptions import * class Parser : """ Универсальный конфигуратор / разбор конфигурации : Базовые операции -- разбор пары атрибут/значение, значение означивается eval """ def __init__(self,cfg) : self.cfg = cfg self.read() def read(*a) : pass def load_value(self,value) : try : return eval(value) except : return value def setconfig(self,attr,value) : self.cfg[attr] = value return None def parse(self,line) : try : attr,value = string.split(line,'=',1) except ValueError : return self.cfg.use(line) # return self.setconfig(line,self.cfg.default(line)) attr = string.strip(attr) value = self.load_value(string.strip(value)) return self.setconfig(attr,value) class ParseFile (Parser) : """ Универсальный конфигуратор / чтение конфигурации : Чтение конфигурации из файла -- парсинг строки на пару атрибут/значение, значение означивается eval """ cfg_ignore = re.compile('(^[ \t\n]*#.*)|(^[ \t\n]*$)').match cfg_sect = re.compile('^[ \t\n]*\[.*\][ \t\n]*$').match cfg_value = re.compile('^.*[^ \t\n]+.*=.*[^ \t\n]+.*$').match def __init__(self, cfg, f=sys.stdin) : """ Инициализация. В качестве f должен быть указан файл, доступный на чтение """ self.f = f self.pcfg = cfg Parser.__init__(self,cfg) def read(self) : num = 0 try : while 1 : num = num + 1 line = self.f.readline() if not line : break elif self.cfg_ignore(line) : continue elif self.cfg_sect(line) : realm = string.strip(string.strip(line)[1:-1]) self.cfg = self.pcfg[realm] = self.pcfg.section(realm=realm) elif self.cfg_value(line) : self.parse(line) else : raise ConfigError,'Неверная строка конфигурации' except ConfigError,msg : raise ConfigError,"%s : %u -- %s" % (self.f.name,num,msg) return class ParseOpt (Parser) : """ Универсальный конфигуратор / чтение конфигурации : Чтение конфигурации из опций -- получаем список атрибутов с использованием getopt, полученные значения означиваются eval """ def __init__(self,cfg) : Parser.__init__(self,cfg) def read(self) : for line in sys.argv[1:] : if line[0:2] == '--' : line = line[2:] if self.parse_flag(line,('without','not_use','not','disable'),0) : pass elif self.parse_flag(line,('with','have','is','use','do','enable'),1) : pass else : self.parse(line) elif line[0:1] == '-' : pass else : self.cfg.arguments.append(line) def parse_flag(self,line,prefix,flag) : attr = parse_prefix(line,prefix) if attr : self.setconfig(attr,flag) return 1 return None def parse_prefix(line,prefix=()) : for item in prefix : l = len(item) if line[0:l] == item : if line[l] in ('-','=','_') : return "use_" + line[l+1:] else : raise ValueError,line return None class ParseEnv (Parser) : """ Универсальный конфигуратор / разбор конфигурации : Чтение конфигурации из среды -- получаем переменные среды, префикс которых равен префиксу приложения (передается). Все переменные среды означиваем и вклюаем в конфигурацию """ def __init__(self, cfg, prefix='') : self.prefix = prefix Parser.__init__(self,cfg) def read(self) : for line in filter(lambda s, prefix=self.prefix : prefix == s[0:len(prefix)] ,os.environ.keys()) : self.parse(line) def parse(self,line) : return self.setconfig(line[len(self.prefix):],self.load_value(os.environ[line])) python-CFG-0.0.9/CFG/__init__.py000064400000000000000000000007421072760770200161570ustar00rootroot00000000000000""" ====================================================== Проект: Универсальный конфигуратор Автор: Андрей Орлов Версия: ${Id: } ------------------------------------------------------ Дата: Mon Nov 19 21:09:12 MSK 2001 ====================================================== """ import CFG import Parser import Application from Exceptions import * Application = Application.Application ConfigS = CFG.ConfigS python-CFG-0.0.9/doc/000075500000000000000000000000001072760770200142115ustar00rootroot00000000000000python-CFG-0.0.9/doc/Application.txt000064400000000000000000000037641072760770200172270ustar00rootroot00000000000000# Про класс Application я кой-чего напишу. У него существуют специаьные # слоты, из которых сегодня нас интересуют: # main - основная вызываемая функция # arg_<ИМЯ_КОМАНДЫ> - обработчик команды. Обработчик команды может # принимать аргументы. # # Остальное неважно ;) # # Есть специальные функции, которые должны быть испольозваны: # verbose(<ФОРМАТ>[,<УРОВЕНЬ>[,<АРГУМЕНТЫ>]]) трассировка # warning(<ФОРМАТ>[,<УРОВЕНЬ>[,<АРГУМЕНТЫ>]]) предупреждение # fatal(<ФОРМАТ>[,<УРОВЕНЬ>[,<ОШИБКА>][,<АРГУМЕНТЫ>]]) фатальное завершение # # Все это - сообщения об ошибках. У них у всех есть уровень - # т.е. тот уровень при котором сообщение будет выведено. # # Какие должны быть уровни: # # 0 - Безмолвие. # 1 - Основные стадии, старт, завершение, инициализация коннекторов, и т.п. # 2 - Обнаружение необычных условий # 3 - Начало иттераций внутри стадий # 4 - Каждая иттерация (начало конец или середина, на усмотрение) # 5 - Начало библиотечногой вызова # 10+ - отладка. # # Уровни 0-1-2-3 должны быть заполнены. # # Уровень четыре - для длительных иттеративных процедур. # # Уровень пять - для критчиных вызовов с негарантированным успехом # (например system или popen). python-CFG-0.0.9/doc/README.txt000064400000000000000000000005141072760770200157070ustar00rootroot00000000000000====================================================== Проект: Универсальный конфигуратор Автор: Андрей Орлов Версия: ${Id: } ------------------------------------------------------ Дата: Mon Nov 19 21:09:12 MSK 2001 ====================================================== python-CFG-0.0.9/doc/all.txt000064400000000000000000000053031072760770200155230ustar00rootroot00000000000000====================================================== Проект: Универсальный конфигуратор Модуль: Дока Автор: Андрей Орлов Версия: ${Id: } ------------------------------------------------------ Дата: Sat Dec 8 12:36:09 MSK 2001 ====================================================== Универсальный конфигуратор - это набор прототипов, ориентированный на создание приложений единой архитектуры. Универсальный конфигуратор включает в себя три независимые компоненты, каждая из которых может быть применена независимо. Вот список этих компонент: - Собственно приложение, реализуемое базовым классом Application. Обеспечивает выполнение стандартной последовательности инициализирующих и финитных операций. Предоставляет стандартную библиотеку служебных вызовов. - Конфигурация, реализуемая классом Config. Обеспечивает поддержку структуры конфигурации, и логику доступа к ней. Предоставляет набор стандартных опций, актуальных для всех приложений, в т.ч. для приложений, реализованных поверх класса Application. На концептуальном уровне, конфигурация может рассматриваться как ассоциативный массив ключей и их значений, причем значениями могут быть другие конфигурации. - Парсер конфигурационных файлов. Обеспечивает абстракцию от формата и способа хранения конфигурации. В текущей версии парсер реализован как стандартный модуль, не подлежащий какой-либо замене или изменению и загружается непосредственно классом Application. Минимальный пример приложения, реализованного на этой основе приведен в scripts/sample.py. ====================================================== python-CFG-0.0.9/doc/application.txt000064400000000000000000000124501072760770200172570ustar00rootroot00000000000000====================================================== Проект: Универсальный конфигуратор Модуль: Application/Дока Автор: Андрей Орлов Версия: ${Id: } ------------------------------------------------------ Дата: Mon Nov 19 21:09:12 MSK 2001 ====================================================== Про класс Application я кой-чего напишу. Это прототип обобщенного приложения, выполняющий следющие операции: 1. Загрузка конфига 2. Инициализация приложения 3. Выполнение команд 4. Откат инициализации 5. Завершение. Любое приложение должно содержать класс, порождаемый от Application. Вызов приложения осуществляется методом run(), т.е. sys.exit(Application(cfg={}).run()) - это стандартная конструкция. Application может работать в двух режимах: обычном и отладочном. Отладочный режим включается ключом --debug=1. Основное отличие отладочного и основного режима - в основном режиме все исключения перехватываются и маскируются. В отладочном - нет. Программирование Application заключается в порождении от него объекта и перекрытия специальных слотов. Каждый слот должен возвращать ненулевое значение, иначе будет считаться что слот завершился неудачно и из программы будет произведен безопасный выход. Основной интерес на сегодня представляют следующие слоты: init -- Инициализация. Выполяется поверх уже разобранного конфига. main -- Основная вызываемая функция. Существует несколько стандартных прототипов, в т.ч. execute_cmd & execute_seq. execute_seq -- Пытается выполнить параметры командной строки как команды, вызывая функции вида arg_<ИМЯ_КОМАНДЫ> без аргументов execute_cmd -- Пытается выполнить первый параметр командной строки как команду, вызывая функцию вида arg_<ИМЯ_КОМАНДЫ> передавая ей в качестве аргментов остальные параметры командной строки. finit -- Завершение. Предназначен для выполнения завершающих действий, в т.ч. закрытия файлов, сохранение промежуточных данных и т.п. Вызывается даже при аварийном завершении метода main Класс Application предоставляет ряд функций, в том числе специальные функции, для вывода сообщений:: verbose(<ФОРМАТ>[,<УРОВЕНЬ>[,<АРГУМЕНТЫ>]]) - трассировка warning(<ФОРМАТ>[,<УРОВЕНЬ>[,<АРГУМЕНТЫ>]]) - предупреждение fatal(<ФОРМАТ>[,<УРОВЕНЬ>[,<ОШИБКА>][,<АРГУМЕНТЫ>]]) фатальное завершение Все это - сообщения об ошибках. У них у всех есть уровень - т.е. тот уровень при котором сообщение будет выведено. Для построения стандартного приложения они обязательно должны использоваться. Рекомендуемая степень детализации и смысл каждого уровня следующий: 0 - Безмолвие. 1 - Основные стадии, старт, завершение, инициализация коннекторов, и т.п. 2 - Обнаружение необычных условий 3 - Начало иттераций внутри стадий 4 - Каждая иттерация (начало конец или середина, на усмотрение) 5 - Начало библиотечногой вызова 10+ - отладка. Уровни 0-1-2-3 должны быть заполнены всегда. Уровень четыре должен заполнятся для длительных иттеративных процедур. Уровень пять должен запонятся для критчиных вызовов с негарантированным успехом (например system или popen). Уровнеи больше 10ти в релизе по возможности должны оставаться пустыми. python-CFG-0.0.9/doc/config.txt000064400000000000000000000135331072760770200162240ustar00rootroot00000000000000====================================================== Проект: Универсальный конфигуратор Модуль: Config/Дока Автор: Андрей Орлов Версия: ${Id: } ------------------------------------------------------ Дата: Mon Nov 19 21:09:12 MSK 2001 ====================================================== Про класс Config я тоже кой-чего напишу. Это прототип конфигурации, предоставляющий стандартную логику и набор стандартных ключей. Существует два класса Config: Config & ConfigS. Отличие класса ConfigS в том, что в нем могут быть созданы только те ключи, которые есть в базовой конфигурации, передаваемой в качестве параметра при инициализации, причем значения этих ключей должны быть того же самого типа. Класс ConfigS является основным на сегодняшний день, поэтому использовать следует именно его. Есть два способа настройки класса: 1. Передача при инициализации хэша с умолчаниями Если это не сделать, то нельзя будет создать ни одного ключа в конфигурации. Передачи хеша с умолчаниями достаточно для подавляющего большинства приложений. 2. Порождение своего класса Позволяет добавить ключи с более сложной обработкой, чем просто добавление в конфигурацию. Использование такого метода в текущей версии крайне не желательно: если необходима дополнительная инициализация, то ее лучше проводить в методе init() класса Application. При порождении класса новые обработчики ключей задаются как функции вида:: switch_<ИМЯ_КЛЮЧА>(self,key[,arg[=<УМОЛЧАНИЕ>]]), где key - ключ, arg - значение ключюча. Обязательность, отсутствие или умолчание аргумента arg означет обязательность, отсутстствие или умолчание значения ключа. Обработчик должен сохранять разобранный ключ в хеше self.data таким образом, что бы печать этого значения допускала повторную загрузку в том же самом формате (т.е. если в конфиге задается список, то и ключу должно быть присвоено значение списка), если это невозможно, то и хрен с ним - в следущей версии попробуем решить это иначе. Конфигурация, загружаемая в класс Config*, представляет собой список деревьев, примерно следующего вида: [ {:, : {:} } , { ..... }] При разрешении любого ключа из любой ветви дерева просматриваются все родительчкие узлы, а затем все корневые узлы деревьев, идущих в списке перед данным. Каждый элемент списка деревъев соотстветствует своему вызову парсера конфигурации. Прасеры вызываются в следующем порядке: <Конфиг> ... <Конфиг> <Среда> <Командая строка>. Конфигурация поддерживает следующие стандартные ключи: verbose -- увеличить (задать) уровень трассировки, verbose-stderr -- выводить трассировку на stderr, debug -- запуск в отладочном режиме, не маскируются исключения, dump = type -- вывести дамп конфигурации, тип может быть: detail -- детальная схема конфигурации, content -- список секций конфигурации, plain -- конфигурационный файл dump-min -- минимальный уровень дампа конфигурации, dump-max -- максимальный уровень дампа конфигурации, help = [chapter]-- вывести хелп, help=cfg - хелп на конфгурациюб exit -- прекратить исполнение программы и выйти, cfg_dump -- сохранить конфигурацию в виде бинарного дампа, cfg_load -- загрузить конфигурацию из бинарного дамп, cfg_read -- прочитать конфигурационный файл, сfg_clean -- восстановить умолчания в конфигурации. В общем, just click & enjoy ;) ====================================================== python-CFG-0.0.9/scripts/000075500000000000000000000000001072760770200151335ustar00rootroot00000000000000python-CFG-0.0.9/scripts/sample.py000075500000000000000000000024541072760770200167760ustar00rootroot00000000000000#! /usr/bin/python """\ ================================================================================ Описание: Пример программы Автор: Андрей Орлов Дата: Wed Nov 21 11:57:27 MSK 2001 Вызов : %(application)s [ключи] [команда]*" Команды: hello [<приветствие>] Выводит строку приветствия или Hello world Ключи: ================================================================================ """ import CFG import string import sys class App (CFG.Application) : __doc__ = __doc__ main = CFG.Application.exec_cmd def arg_hello(self,*arg,**kw) : if not self.cfg['count'] : self.fatal('Счетчик повторов равен 0') self.verbose('Начало вывода приветствий') for item in range(0,self.cfg['count']) : if len(arg) == 0 : print "Hello,World!" else : print string.join(arg," ") return 1 app=App(cfg=CFG.ConfigS(dict={ 'verbose-level':1, 'count':1, },realm='Inner Defaults'),cfg_names=('/etc/','./.'),prefix='hello') sys.exit(app.run())