From 874c21723820a7a36d13c3dbcf1ec3d02ade5076 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A5=D0=B8=D1=80=D0=B5=D1=86=D0=BA=D0=B8=D0=B9=20=D0=9C?= =?UTF-8?q?=D0=B8=D1=85=D0=B0=D0=B8=D0=BB?= Date: Tue, 20 Apr 2010 15:43:30 +0400 Subject: [PATCH] Remove trash --- build/lib/calculate-lib/pym/__init__.py | 0 build/lib/calculate-lib/pym/cl_base.py | 1156 ---- build/lib/calculate-lib/pym/cl_fill.py | 346 - build/lib/calculate-lib/pym/cl_log.py | 59 - build/lib/calculate-lib/pym/cl_profile.py | 7136 --------------------- build/lib/calculate-lib/pym/cl_utils.py | 510 -- build/lib/calculate-lib/pym/cl_utils2.py | 563 -- build/lib/calculate-lib/pym/cl_vars.py | 91 - 8 files changed, 9861 deletions(-) delete mode 100644 build/lib/calculate-lib/pym/__init__.py delete mode 100644 build/lib/calculate-lib/pym/cl_base.py delete mode 100644 build/lib/calculate-lib/pym/cl_fill.py delete mode 100644 build/lib/calculate-lib/pym/cl_log.py delete mode 100644 build/lib/calculate-lib/pym/cl_profile.py delete mode 100644 build/lib/calculate-lib/pym/cl_utils.py delete mode 100644 build/lib/calculate-lib/pym/cl_utils2.py delete mode 100644 build/lib/calculate-lib/pym/cl_vars.py diff --git a/build/lib/calculate-lib/pym/__init__.py b/build/lib/calculate-lib/pym/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/build/lib/calculate-lib/pym/cl_base.py b/build/lib/calculate-lib/pym/cl_base.py deleted file mode 100644 index 4a8626e..0000000 --- a/build/lib/calculate-lib/pym/cl_base.py +++ /dev/null @@ -1,1156 +0,0 @@ -#-*- coding: utf-8 -*- - -# Copyright 2008-2010 Mir Calculate Ltd. http://www.calculate-linux.org -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import gettext -import os -import getopt -import sys -############################################################################## -import re -import copy -import types -import string -#import os -import filecmp -import ConfigParser -import time -import socket -#import sys -import random -import string -import cl_utils -############################################################################## - -_expand_lang = gettext._expand_lang - -def exit(codeExit): - """Метод выхода из программы""" - sys.exit(codeExit) - -def __findFileMO(domain, localedir=None, languages=None, all=0): - # Модифицинрованный метод модуля gettext ищет файл перевода - if localedir is None: - localedir = _default_localedir - if languages is None: - languages = [] - for envar in ('LANGUAGE', 'LC_ALL', 'LC_MESSAGES', 'LANG'): - val = os.environ.get(envar) - if val: - languages = val.split(':') - break - if 'C' not in languages: - languages.append('C') - # now normalize and expand the languages - nelangs = [] - for lang in languages: - for nelang in _expand_lang(lang): - if nelang not in nelangs: - nelangs.append(nelang) - # select a language - if all: - result = [] - else: - result = None - for lang in nelangs: - if lang == 'C': - break - mofile = os.path.join(localedir, '%s_%s.mo' % (domain,lang)) - if os.path.exists(mofile): - if all: - result.append(mofile) - else: - return mofile - return result - -gettext.find = __findFileMO - -class GlobalParam(type): - """ Метакласс для глобальных параметров - """ - def __init__(cls, *args): - cls.GP = [] - cls.GP.append("") - -class lang: - """Класс многоязыковой поддержки lang для перевода сообщений программ на -другие языки. - -Типичное использование: - import sys - import lang - - # язык сообщений английский - tr = lang.lang(en) - # язык определяется системой - #tr = lang.lang() - - #Установка домена переводаldap - # в последующем можно не использовать - задается глобально - tr.setGlobalDomain('calc') - # задается локально для одного файла - #tr.setLocalDomain('calc') - - # Установка метода перевода для текущего модуля - tr.setLanguage(sys.modules[__name__]) - -Где: - tr -- объект перевода - 'en' -- язык выводимых сообщений - sys.modules[__name__] -- модуль сообщения которого переводятся - calc - домен перевода - имя файла перевода без расширения - -Если файл перевода не найден то сообщения не переводятся -Если в модуле сообщения которого переводим, экспортируются другие модули то -они тоже переводятся. - -По умолчанию директория в которой находятся переводы: 'lang/i18h' относительно -исполняемого файла названия файлов перевода совпадают с названиями модулей -если не определен методом setDomainTranslate() - домен перевода. - """ - __metaclass__ = GlobalParam - def __init__(self,l=''): - self.nameDomain = self.GP[0] - #self.nameDomain = '' - """ Название файла перевода (Домен) если используется 1 файл перевода - """ - self.__catalog = os.path.abspath('/usr/share/calculate/i18n') - """ Путь к каталогу переводов (в этом каталоге - ru_RU/LC_MESSAGES в котором файл перевода) - """ - env = os.environ - if l == "" and env.has_key('LANG'): - l = env['LANG'].split('.')[0].split("_")[0] - """ Определение языка """ - self.__modnames = {} - """ Словарь переведенных модулей - ключ --- имя модуля - значение --- был ли модуль переведен (1 или 0) - """ - self.__l = l - """Язык перевода для всех модулей""" - - def __translate(self,message): - """Метод translate возвращает полученное значение без -изменений""" - return message - - def setLanguage(self,module): - """ Установка языка перевода для модуля module. - - параметр --- экспортируемый модуль python - если в этом модуле экспортируются другие модули - то язык устанавливается и для них - Метод запускается после экспорта модуля который будем переводить - """ - t = vars(module) - for i in dir(module): - q = str(t[i]) - if 'module' in q and not '__' in i and not '/usr/lib' in q\ - and not 'built-in' in q : - mod = vars(module)[i] - self.__setLang(mod) - return self.__setLang(module) - - def __setLang(self,module): - """ Установка языка перевода для модуля module. - - В случае нахождения файла перевода возвращает истину. - Во всех случаях устанавливает метод перевода для модуля. - Если нет файла перевода метод перевода возвращает то же - значение что получает - """ - if module.__name__ in self.__modnames.keys(): - return True - - if self.nameDomain == '': - if module.__name__ == "__main__": - nameDomain = module.__file__.split('.')[0] - else: - nameDomain = module.__name__ - else: - nameDomain = self.nameDomain - - if self.__l == 'en': - module._ = self.__translate - ret = 1 - else: - la = [] - la.append(self.__l) - if gettext.find(nameDomain,self.__catalog,la): - """Если найден словарь то инициализируем переводчик""" - transl = gettext.translation(nameDomain\ - ,self.__catalog,la) - - #module._ = transl.ugettext - module._ = transl.gettext - ret = 1 - else: - module._ = self.__translate - ret = 0 - self.__modnames[module.__name__] = ret - return ret - - def getTranslatorByName(self,namemodule): - """ Метод который по имени модуля определяет, был ли модуль с этим - именем переведен - """ - if self.__modnames.has_key(namemodule): - return self.__modnames[namemodule] - return 0 - - def setGlobalDomain(self, nameDomain): - """ Метод для установки домена перевода (глобально для всех файлов) - """ - self.GP[0] = nameDomain - self.nameDomain = self.GP[0] - return True - - def setLocalDomain(self, nameDomain): - """ Метод для установки домена перевода (локально для одного файла) - """ - self.nameDomain = nameDomain - return True - -############################################################################## -# Перевод модуля на другой язык -tr = lang() -tr.setLocalDomain('cl_lib') -tr.setLanguage(sys.modules[__name__]) - -############################################################################## -class opt: - def __init__(self,shortOpt,longOpt = []): - """ Длинные и короткие опции командной строки допустимые в программе - a - короткая опция - >program -a - - a: - короткая опциия со значением - >program -a 10 - - a:: - короткая опциия у которой может быть или не быть значение - >program -a - >program -a 15 - - "ha:" - значение параметра shortOpt - две опции h - без значения, a - со значением - - help - длинная опция без значения - test= - длинная опция со значением - - ["help","test="] - значение парамера longOpt - >program -a - две опции help - без значения, test - со значением - """ - self.shortOpt = shortOpt - self.longOpt = longOpt - self.sysArgv = sys.argv[1:] - - def getopt(self): - try: - opts, args = getopt.getopt(self.sysArgv,self.shortOpt,self.longOpt) - except getopt.GetoptError: - self.handlerErrOpt() - sys.exit(1) - for option, value in opts: - if len(option) == 2: - option = option[1:] - else: - option = option[2:] - self.handlerOpt(option,value) - for param in args: - self.handlerParam(param) - - def handlerErrOpt(self): - # Обработчик в случае неправильных параметров - pass - - def handlerOpt(self,option,value): - # Обработчик (параметр значение) - pass - - def handlerParam(self,param): - # Обработчик хвостов (значение) - pass - -############################################################################### -import cl_profile -class iniParser(cl_profile._error): - """Класс для работы с ini файлами - - """ - def __init__(self, iniFile): - # название ini файла - self.iniFile = iniFile - # права создаваемого ini-файла - self.mode = 0640 - # Cоответствует ли формат файла нужному - self.checkIni = None - - def setMode(self, mode): - """установка прав создаваемого ini-файла""" - self.mode = mode - - def openIniFile(self): - if not os.access(self.iniFile, os.R_OK): - return "" - FD = open(self.iniFile, "r") - textIni = FD.read() - FD.close() - return textIni - - def writeIniFile(self, txtConfig): - if not os.path.exists(self.iniFile): - fd = os.open(self.iniFile, os.O_CREAT) - os.close(fd) - os.chmod(self.iniFile, self.mode) - if not os.path.exists(self.iniFile): - self.setError(_("Unable to create file") + ": " + self.iniFile) - return False - FD = open(self.iniFile, "r+") - FD.truncate(0) - FD.seek(0) - FD.write(txtConfig) - FD.close() - - def setVar(self, strHeader, dictVar): - """Заменяет или добавляет область и переменные - - Добавляет область в ini-файл или объединяет с существующей - strHeader - имя области - dictVar - словарь переменных - """ - textIni = self.openIniFile() - nameFomat = self.checkIniFile(textIni) - if not nameFomat: - return False - if type(strHeader) in (tuple, list): - # формат plasma - classObj = cl_profile.plasma - else: - if nameFomat == "plasma": - self.setError(_("In the file %s (format - 'plasma'), \ - write the variable in the format 'samba'")\ - %self.iniFile) - return False - # формат samba - classObj = cl_profile.samba - # создаем объект - # и записываем в него содержимое ini-файла - objIni = classObj(textIni) - # создаем текст из строки заголовка и - # словаря переменных области - txtConfig = objIni.createTxtConfig(strHeader, dictVar) - # создаем объект и записываем в него текст - objIniAdd = classObj(txtConfig) - # объединяем объекты для получения результирующего текста - objIni.join(objIniAdd) - # получаем текст - txtConfig = objIni.getConfig().encode("UTF-8") - # записываем его в ini файл - self.writeIniFile(txtConfig) - return True - - def isEmptyFile(self, textIni): - """Является ли файл пустым""" - if not textIni.strip(): - return True - else: - return False - - def checkIniFile(self, textIni): - """Проверка на правильность формата файла""" - if self.checkIni == None: - # Ошибка - if textIni == False: - self.checkIni = False - return False - self.checkIni = "samba" - # В файле есть данные - if not self.isEmptyFile(textIni): - try: - objIni = cl_profile.plasma(textIni) - except: - self.setError(_("Incorrect format file") + ": " + \ - self.iniFile) - self.checkIni = False - return self.checkIni - allAreas = objIni.docObj.getAllAreas() - for xmlArea in allAreas: - parentNode = xmlArea.parentNode - if parentNode and parentNode.tagName == "area": - self.checkIni = "plasma" - break - if self.checkIni == "samba": - objIni = cl_profile.samba(textIni) - xmlBody = objIni.docObj.getNodeBody() - if not xmlBody.firstChild: - self.checkIni = False - return self.checkIni - - def delVar(self, strHeader, nameVar): - """Удаляем переменную из ini файла""" - delNameVar = "!%s" %(nameVar) - dictVar = {delNameVar:"del"} - res = self.setVar(strHeader, dictVar) - return res - - def delArea(self, strHeader): - """Удаляем область из ini файла""" - if type(strHeader) in (tuple, list): - # Формат plasma - delStrHeader = strHeader[:] - delStrHeader[-1] = "!%s"%delStrHeader[-1] - else: - # Формат samba - delStrHeader = "!%s" %(strHeader) - dictVar = {"del":"del"} - res = self.setVar(delStrHeader, dictVar) - return res - - def getVar(self, strHeader, nameVar): - """Получаем значение переменной из ini-файла""" - textIni = self.openIniFile() - nameFomat = self.checkIniFile(textIni) - if not nameFomat: - return False - formatPlasma = False - if type(strHeader) in (tuple, list): - # формат plasma - classObj = cl_profile.plasma - formatPlasma = True - else: - if nameFomat == "plasma": - self.setError(_("In the file %s (format - 'plasma'), \ - get the variable in the format 'samba'")\ - %self.iniFile) - return False - # формат samba - classObj = cl_profile.samba - # создаем объект и записываем в него содержимое ini-файла - objIni = classObj(textIni) - # получаем ноду body - xmlBody = objIni.docObj.getNodeBody() - flagFound, xmlBody = self.getLastNode(objIni, xmlBody, strHeader, - formatPlasma) - if flagFound and xmlBody: - if formatPlasma: - strHeader = strHeader[-1] - # находим в области переменную - res = objIni.docObj.getAreaFieldValues(strHeader, nameVar, xmlBody) - else: - res = False - if res is False: - return "" - else: - return res - - - def getLastNode(self, objIni, xmlBody, strHeader, formatPlasma): - """Ищет область в XML в которой область с переменными""" - flagFound = True - lenStrHeader = len(strHeader) - if formatPlasma and lenStrHeader>0: - xmlAreas = [xmlBody] - for i in xrange(lenStrHeader-1): - flagFound = False - for xmlArea in xmlAreas: - xmlAreas = objIni.docObj.getArea(strHeader[i], xmlArea) - if xmlAreas: - flagFound = True - break - if xmlAreas: - xmlBody = xmlAreas[0] - return flagFound,xmlBody - - def getAreaVars(self, strHeader): - """Получаем все переменнные области из ini-файла""" - textIni = self.openIniFile() - nameFomat = self.checkIniFile(textIni) - if not nameFomat: - return False - formatPlasma = False - if type(strHeader) in (tuple, list): - # формат plasma - classObj = cl_profile.plasma - formatPlasma = True - else: - if nameFomat == "plasma": - self.setError(_("In the file %s (format - 'plasma'), \ - get all variables in the format 'samba'")\ - %self.iniFile) - return False - # формат samba - classObj = cl_profile.samba - # создаем объект типа samba и записываем в него содержимое ini-файла - objIni = classObj(textIni) - # получаем ноду body - xmlBody = objIni.docObj.getNodeBody() - flagFound, xmlBody = self.getLastNode(objIni, xmlBody, strHeader, - formatPlasma) - if flagFound and xmlBody: - if formatPlasma: - strHeader = strHeader[-1] - # если находим область то выдаем словарем все переменные иначе False - res = objIni.docObj.getAreaFields(strHeader, xmlBody) - else: - res = False - if res is False: - return {} - else: - return res - - def getAllSectionNames(self): - """Получаем все имена секций определенных в ini файле - - Если формат ini файла plasma то имя секции - - имена нескольких секций через запятую - """ - textIni = self.openIniFile() - nameFomat = self.checkIniFile(textIni) - if not nameFomat: - return False - if nameFomat == "samba": - # создаем объект типа samba и записываем в него содержимое ini-файла - objIni = cl_profile.samba(textIni) - elif nameFomat == "plasma": - # создаем объект типа plasma и записываем в него содержимое - # ini-файла - objIni = cl_profile.plasma(textIni) - else: - return [] - xmlNodes = objIni.docObj.getAllAreas() - # Имена секций ini файла - namesSection = [] - if nameFomat == "plasma": - for xmlNode in xmlNodes: - nSect = objIni.docObj.getNameArea(xmlNode) - if nSect: - namesSect = [nSect] - parentNode = xmlNode.parentNode - while parentNode != objIni.docObj.body: - nameSect = objIni.docObj.getNameArea(parentNode) - if nameSect: - namesSect.append(nameSect) - parentNode = parentNode.parentNode - else: - return [] - namesSection.append(",".join(reversed(namesSect))) - elif nameFomat == "samba": - # получаем ноду body - for xmlNode in xmlNodes: - nSect = objIni.docObj.getNameArea(xmlNode) - if nSect: - namesSection.append(nSect) - return namesSection - -############################################################################## - -class var: - '''Объект "Переменная окружения"''' - # название сервиса которому принадлежит переменная - #(Global, Builder, Client, Server итд) - service = None - # значение переменной - value = "" - # режим записи (атрибут mode) - mode = "r" - # переменная для внутреннего использования (official) - official = False - # количество вызовов метода заполнения - countFill = 0 - # объект в котором создан этот объект - parentObj = None - # запускать или нет метод заполнения - fillStart = True - # dynamic = True то переменная динамическая при повтороном запуске - # запускается метод заполнения - # метод заполнения не запускается только если fillStart = False - # (осторожно возможно зацикливание программы если методы заполнения - # переменных используют методы друг друга) - dynamic = False - - def __init__(self, parentObj): - # словарь зависимых переменных {имя:значение} - self.dependValues = {} - # тип переменной (атрибут type) - self.type = ('default') - # список допустимых значений переменных (select) - self.select = () - # объект который создал этот объект - self.parentObj = parentObj - - def is_update(self): - #Нужно ли перезапускать метод заполнения (если зависимые переменные - #обновились то нужно) - upd = False - for depVarName in self.dependValues.keys(): - value = self.parentObj.__getattribute__(depVarName).Get() - if self.dependValues[depVarName] != value: - self.dependValues[depVarName] =\ - self.parentObj.__getattribute__(depVarName).value - upd = True - break - return upd - - def Get(self): - """Получение значения переменной""" - if not self.fillStart: - return self.value - if self.dynamic: - self.value = self.Fill() - return self.value - if not self.value: - if self.countFill>0: - return self.value - self.countFill += 1 - self.value = self.Fill() - if self.dependValues and self.is_update(): - self.countFill += 1 - self.value = self.Fill() - return self.value - - def Set(self, value): - """Запись значения переменной""" - self.value = value - return self.value - - def Fill(self): - """Заполнение переменной в далнейшем заменяем методом заполнения""" - return self.value - - -class DataVars(object): - class DataVarsError(Exception): - """Класс ошибок""" - pass - # добавляем пути к модулям если они не добавлены - if not os.path.abspath(\ - '/usr/lib/calculate/calculate-server/pym') in sys.path: - sys.path.insert(0,os.path.abspath(\ - '/usr/lib/calculate/calculate-server/pym')) - if not os.path.abspath(\ - '/usr/lib/calculate/calculate-lib/pym') in sys.path: - sys.path.insert(0,os.path.abspath(\ - '/usr/lib/calculate/calculate-lib/pym')) - if not os.path.abspath(\ - '/usr/lib/calculate/calculate-builder/pym') in sys.path: - sys.path.insert(0,os.path.abspath(\ - '/usr/lib/calculate/calculate-builder/pym')) - # Импортируемые модули - (раздел: модуль переменных, модуль заполнения - #переменных) - __modlist={'Global':('cl_vars','cl_fill'), - 'Server':('cl_vars_server','cl_fill_server'), - 'Builder':('cl_vars_builder','cl_fill_builder'), - 'Client':('cl_vars_client','cl_fill_client'), - } - def __init__(self): - #self.t1 = fillVars() - #self.t1.Get = self.Get - #self.t1.Set = self.Set - # Для нахождения зависимостей переменных - self.__levelNumber = 0 - self.__LevelsVar = [] - # Для хранения импортированных модулей и объектов - #[(cекция,импортированный модуль переменных, объект заполнения),] - self._importList = [] - self._importData("Global") - - def _importData(self, section): - """Импортирует модули с переменными и модули с функциями заполнения - - section секция раздела (Global, Server, Client итд) - создает необходимые структуры данных - """ - if not section in self.__modlist.keys(): - raise self.DataVarsError(_("Unsupported section %s")%section) - modVar = self.__modlist[section][0] - modFill = self.__modlist[section][1] - # Импортируем класс описания переменных и класс заполнения - try: - exec ("import %s" % (modVar)) - except ImportError, e: - err1 = _("Error in import module %s")%modVar - err2 = _("error") + ": " +str(e) - raise self.DataVarsError("%s\n%s"%(err1,err2)) - flagFindFillModule = True - try: - exec ("import %s" % (modFill)) - except ImportError, e: - if "No module named" in str(e): - flagFindFillModule = False - else: - err1 = _("Error in import module %s")%modFill - err2 = _("error") + ": " +str(e) - raise self.DataVarsError("%s\n%s"%(err1,err2)) - if flagFindFillModule: - # Создаем объект с методами заполнения переменных - exec("fillObj = %s.fillVars()" %modFill) - # Подключаем методы получения и записи переменных - fillObj.Get = self.Get - fillObj.Set = self.Set - else: - fillObj = False - # Заполняем self._importList - exec("self._importList.insert(0,(section,%s,fillObj))"%(modVar)) - - def __findVarData(self, nameVar): - """Находит данные для создания объекта переменная в модулях и - - объектах - """ - # Ищем переменную в модуле - dataVar = False - e = False - for section, moduleVar, fillobj in self._importList: - try: - exec("dataVar=moduleVar.Data.%s"%nameVar) - except AttributeError, e: - pass - if dataVar: - break - if dataVar == False: - err1 = _("Not found variable %s")%nameVar - err2 = "" - if e: - err2 = _("error") + ": " +str(e) - raise self.DataVarsError("%s\n%s"%(err1,err2)) - dataVar['service'] = section - # Ищем метод в объекте методов заполнения - nameMethod = "get_" + nameVar - flagFindMetod = False - for section, moduleVar, fillobj in self._importList: - if fillobj: - if nameMethod in dir(fillobj): - flagFindMetod = True - method = fillobj.__getattribute__(nameMethod) - break - if flagFindMetod: - return (dataVar,method) - else: - return (dataVar,False) - - def __setAttributesVar(self, var ,nameVar, dict): - """Установка аттрибутов для созданного объекта var - - название аттрибута и его значение берется из словаря dict - """ - dict['type'] = nameVar.split('_') - if not set(dict.keys()) <= set(dir(var)): - raise self.DataVarsError(\ - _("error initalize variable %s, incorrect data")%nameVar) - for nameAttr in dict.keys(): - setattr(var,nameAttr, dict[nameAttr]) - return True - - def __Get(self, nameVar): - ret = "" - self.__LevelsVar.append((self.__levelNumber, nameVar)) - self.__levelNumber += 1 - #nameMethod = "get_" + nameVar - if hasattr(self, nameVar): - ret = self.__getattribute__(nameVar).Get() - elif self.__findVarData(nameVar): - dictVar, methodFill =self.__findVarData(nameVar) - varobj = var(self) - # Устанавливаем аттрибуты - self.__setAttributesVar(varobj, nameVar, dictVar) - if methodFill: - varobj.Fill = methodFill - self.__setattr__(nameVar, varobj) - ret = self.__getattribute__(nameVar).Get() - self.__levelNumber -= 1 - if self.__levelNumber == 0 and\ - self.__getattribute__(nameVar).fillStart and\ - len(self.__LevelsVar)>1: - links = self.__getLinks(self.__LevelsVar) - for name in links.keys(): - for nameLink in links[name].keys(): - val = self.__getattribute__(nameLink).Get() - self.__getattribute__(name).dependValues[nameLink] = val - if self.__levelNumber == 0: - self.__LevelsVar = [] - return ret - - def Get(self, nameVar): - return self.__Get(nameVar) - - - def __Set(self, nameVar, value, force=False): - nameMethod = "get_" +nameVar - if not hasattr(self, nameVar) and self.__findVarData(nameVar): - dictVar, methodFill =self.__findVarData(nameVar) - varobj = var(self) - # Устанавливаем аттрибуты - self.__setAttributesVar(varobj, nameVar, dictVar) - if methodFill: - varobj.Fill = methodFill - self.__setattr__(nameVar, varobj) - if hasattr(self, nameVar): - if not force and "r" in getattr(self, nameVar).mode: - print _("Attempt to rewrite a variable for reading:%s")\ - %nameVar - return False - self.__getattribute__(nameVar).fillStart = False - return self.__getattribute__(nameVar).Set(value) - - def Set(self, nameVar, value, force=False): - return self.__Set(nameVar, value, force) - - def __frame(self, lVar): - """получить список областей зависимости переменных""" - data = [] - if not lVar: - return data - firstLevel = lVar[0][0] - for level, name in lVar[1:]: - if level> firstLevel: - data.append((level, name)) - else: - break - return data - - def __getLinks(self, lVar): - """Получить список переменных и от каких переменных они зависят - - на вход список [(уровень рекурсии, название переменной),] - """ - links = {} - frames = {} - levelLinks = {} - lVarFr = lVar - for level, name in lVar: - fr = self.__frame(lVarFr) - if not frames.has_key(name): - frames[name] = fr - levelLinks[name] = level+1 - lVarFr = lVarFr[1:] - for name in frames.keys(): - level = levelLinks[name] - fr = frames[name] - links[name] = {} - for lv, nm in fr: - if level == lv: - links[name][nm] = "" - return links - - def __getPathCalculateIni(self): - """Получить пути до ini файлов""" - return self.Get('cl_env_path') - - def __getSection(self, vname): - """секция для записи в ini файл переменной - - vname - имя переменной - """ - if hasattr(self, vname): - if getattr(self, vname).service == 'Global': - return 'calculate' - else: - return getattr(self, vname).service.lower() - - def __writeVarValue(self, vname, val, location, header): - '''Записать значение в calculate.ini - - Параметры: - vname имя переменной - val значение переменной - location расположение ini файла ('default', 'local', 'remote') - header раздел ini файла ('client', 'server', 'calculate') - - Возвращаемые значение: - True запись успешна - False запись не удалсь - ''' - # получаем все пути до ini файлов - calculate_ini = self.__getPathCalculateIni() - # получаем полный путь до файла ini - if location == 'default': - name_calculate_ini = calculate_ini[2] - elif location == 'local': - name_calculate_ini = calculate_ini[1] - elif location == 'remote': - name_calculate_ini = calculate_ini[0] - else: - return False - # извлекаем из полного имени файла путь - onlydir = os.path.split(name_calculate_ini)[0] - try: - # проверяем чтобы путь до ини файла существовал - if not os.path.exists(onlydir): - # создаем его если отсутствует - os.makedirs(onlydir) - except OSError (nerr,msg): - print nerr, msg - return False - config = iniParser(name_calculate_ini) - # Получаем секцию конфигурационного файла - if not header: - header = self.__getSection(vname) - return config.setVar(header,{vname: cl_utils.convertStrListDict(val)}) - - def __deleteVarValue(self, vname, location, header): - '''Удалить переменную в calculate.ini - - Параметры: - vname имя переменной - location расположение ini файла ('default', 'local', 'remote') - header раздел ini файла ('client', 'server', 'calculate') - - Возвращаемые значение: - True удалено успешно - False удаление не удалсь - ''' - # получаем все пути до ini файлов - calculate_ini = self.__getPathCalculateIni() - # получаем полный путь до файла ini - if location == 'default': - name_calculate_ini = calculate_ini[2] - elif location == 'local': - name_calculate_ini = calculate_ini[1] - elif location == 'remote': - name_calculate_ini = calculate_ini[0] - else: - return False - # извлекаем из полного имени файла путь - onlydir = os.path.split(name_calculate_ini)[0] - # проверяем чтобы путь до ини файла существовал - if not os.path.exists(onlydir): - return False - config = iniParser(name_calculate_ini) - # Получаем секцию конфигурационного файла - if not header: - header = self.__getSection(vname) - if not header: - self.Get(vname) - header = self.__getSection(vname) - # Удаляем переменную - retDelVar = config.delVar(header, vname) - retDelArea = True - if not config.getAreaVars(header): - retDelArea = config.delArea(header) - if retDelArea and retDelVar: - return True - else: - return False - - def Write(self, vname, val, force=False, location='default',header=False): - '''Установить и записать значение переменной в ini файл - - Параметры: - vname имя переменной - val значение переменной - force "принудительный режим" - location расположение ini файла ('default', 'local', 'remote') - header раздел ini файла ('client', 'server', 'calculate') - ''' - if self.__Set(vname, val, force)!= False: - if not val.strip(): - self.__deleteVarValue(vname, location, header) - self.__writeVarValue(vname, val, location, header) - return True - return False - - def Delete(self, vname, location='default', header=False): - '''Удалить переменную в calculate.ini - - Параметры: - vname имя переменной - location расположение ini файла ('default', 'local', 'remote') - - Возвращаемые значение: - True удалено успешна - False удаление не удалсь - ''' - return self.__deleteVarValue(vname, location, header) - - def __getActiveSections(self): - """активные секции в ini файле""" - act_section = [] - for service,t,t in self._importList: - if service == "Global": - act_section.append('calculate') - else: - act_section.append(service.lower()) - return act_section - - def flIniFile(self): - '''Заместить значение переменных значениями из ини файлов - - Возвращаемые значения: - cловарь импортированных переменных - переменные считаны - False - файл не был обнаружен - ''' - #Cловарь переменных из ini файлов - importVars = {} - calculate_ini = self.__getPathCalculateIni() - # активные секции (секции из которых будут использованы переменные) - act_section = self.__getActiveSections() - set_act_section = set(act_section) - i = 0 - locations = ['remote','local','default'] - for name_calculate_ini in calculate_ini: - # проверить сущестование ini файла - if os.path.exists(name_calculate_ini): - # получить объект настроенный на ini - config = iniParser(name_calculate_ini) - # получаем все секции из конфигурационного файла - allsect = config.getAllSectionNames() - if not allsect: - continue - # находим встречающиеся у обоих секции - act_sect = tuple(set(allsect)& set_act_section) - # словарь переменных для ini - файла - importFileVars = {} - # получаем все переменные из всех секций - for section in act_sect: - allvars = config.getAreaVars(section) - if allvars == False: - return False - # словарь переменных для ini - файла - importFileVars = {} - # принудительно переписать все переменные окружения - # полученные из ini - for (k,v) in allvars.items(): - k = k.encode("UTF-8") - value = cl_utils.convertStrListDict(v.encode("UTF-8")) - self.Set(k, value, True) - importFileVars[k] = value - if i < 3: - importVars[locations[i]] = importFileVars - i += 1 - return importVars - - def flServer(self, **args): - '''Заполнить конфигурацию переменных, для ldap''' - # заполнить переменные окружения алгоритмом по умолнанию - self._importData("Server") - - def flClient(self, **args): - '''Заполнить конфигурацию переменных, для клиента''' - # заполнить переменные окружения алгоритмом по умолнанию - self._importData("Client") - - def flBuilder(self, **args): - '''Заполнить конфигурацию переменных, для билдера''' - self.Set('setup_pass','builder',True) - # заполнить переменные окружения алгоритмом по умолнанию - self._importData("Builder") - - def flInstall(self, **args): - '''Заполнить конфигурацию переменных для инсталятора''' - self.Set('setup_pass','install',True) - - - def defined(self, vname): - return True - - - - def exists(self, nameVar): - """ Определяет существует ли переменная с таким имененм - """ - if hasattr(self, nameVar): - return True - foundVar = False - # Ищем переменную в импортируемых модулях - for section, moduleVar, fillobj in self._importList: - if moduleVar.Data.__dict__.has_key(nameVar): - foundVar = True - break - return foundVar - - def getVars(self, type_names=None): - ret = {} - for section, moduleVar, fillobj in self._importList: - dataVar=moduleVar.Data - dictVars = dir(dataVar) - for nameVar in dictVars: - if not "__" in nameVar: - if not (getattr(dataVar,nameVar).has_key("official") and\ - getattr(dataVar,nameVar)['official']): - self.Get(nameVar) - if type_names: - #type_names.sort() - varType =list(getattr(dataVar,nameVar)['type']) - #varType.sort() - #print type_names - #print varType - #print - if not set(type_names)<=set(varType): - continue - ret[nameVar] = getattr(self,nameVar) - return ret - - #распечатать список переменных с значениями - def printVars(self,type_names=None): - var=None - var=self.getVars(type_names) - mlen_name=0; - mlen_type=0; - mlen_mode=0; - for i,j in var.items(): - if len(i)>mlen_name: - mlen_name=len(i) - #if len(str(j.type))>mlen_type: - #mlen_type=len(str(j.type)) - vtype=str(type(var[i].value)).split(" ")[1][1] - if not '[' in var[i].mode: - if vtype in ['d','l']: - mode="[%s%s]"%(var[i].mode.lower(),vtype) - else: - mode="[%s]"%(var[i].mode.lower()) - var[i].mode=mode - if len(mode)>mlen_mode: - mlen_mode=len(mode) - plist=var.keys() - plist.sort() - br = cl_utils.fillstr("-",mlen_name) + " " +\ - cl_utils.fillstr("-",mlen_mode) + " " + cl_utils.fillstr("-",10) - #cl_utils.fillstr("-",mlen_type) + " " +\ - - print "The list of variables:" - print "var name".center(mlen_name),\ - "Mode","Value" - #"Type".center(mlen_type),\ - - - print br - for i in plist: - #if var[i].value is None: - #continue - p_val=var[i].value - if var[i].official: - continue - cl_utils.columnWrite( i, mlen_name, var[i].mode.lower(), - mlen_mode, - #str(var[i].type), - #mlen_type, - p_val) - print br -############################################################################## -class glob_attr: - """Глобальные аттрибуты для методов заполнения переменных""" - - def _runos(self,cmd, ret_first=None, env={}): - """Вернуть результат выполнения команды ОС""" - if not env: - envDict = {} - env.update(os.environ.items() + [("PATH",cl_utils.getpathenv())] +\ - env.items()) - retCode, programOut = cl_utils.runOsCommand(cmd, None, ret_first, env) - if not retCode: - return programOut - return False diff --git a/build/lib/calculate-lib/pym/cl_fill.py b/build/lib/calculate-lib/pym/cl_fill.py deleted file mode 100644 index c5dea91..0000000 --- a/build/lib/calculate-lib/pym/cl_fill.py +++ /dev/null @@ -1,346 +0,0 @@ -#-*- coding: utf-8 -*- - -# Copyright 2008-2010 Mir Calculate Ltd. http://www.calculate-linux.org -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import re -import os -import types -import cl_utils -import cl_base - -class fillVars(object, cl_base.glob_attr): - - def get_os_net_domain(self): - ''' Определим домен''' - domain=self._runos("hostname -d 2>&1") - if not domain: - print _("Error:") + " " +_("Not found domain name") - print _("Command 'hostname -d' returns an empty value") - cl_base.exit(1) - elif re.search("^hostname: ",domain): - return "local" - else: - return domain - - def get_os_linux_shortname(self): - '''Получить переменную короткого названия системы''' - path = '/etc/calculate/calculate.ini' - if os.path.exists(path): - FD = open(path) - data = FD.readlines() - FD.close() - shortNameList = filter(lambda y:y, - map(lambda x:\ - len(x.split("="))==2 and\ - x.split("=")[0]=="calculate" and\ - x.split("=")[1].strip(), data)) - if shortNameList: - return shortNameList[0] - gentooFile = "/etc/gentoo-release" - shortName = "Linux" - if os.path.exists(gentooFile): - shortName = "Gentoo" - return shortName - - def get_os_linux_name(self): - """полное название системы""" - linuxShortName = self.Get("os_linux_shortname") - if linuxShortName: - dictLinuxName = {"CLD":"Calculate Linux Desktop", - "CLDX":"Calculate Linux Desktop", - "CLDG":"Calculate Linux Desktop", - "CDS":"Calculate Directory Server", - "Gentoo":"Gentoo"} - if linuxShortName in dictLinuxName.keys(): - return dictLinuxName[linuxShortName] - else: - return "Linux" - else: - return "Linux" - - def get_os_linux_subname(self): - """постфикс к названию системы""" - linuxShortName = self.Get("os_linux_shortname") - if linuxShortName: - dictLinuxSubName = {"CLD":"KDE", "CLDX":"XFCE", "CLDG":"GNOME"} - if linuxShortName in dictLinuxSubName.keys(): - return dictLinuxSubName[linuxShortName] - else: - return "" - else: - return "" - - def get_os_linux_ver(self): - '''Получить версию системы''' - path = '/etc/calculate/calculate.ini' - if os.path.exists(path): - FD = open(path) - data = FD.readlines() - FD.close() - shortNameList = filter(lambda y:y, - map(lambda x:\ - len(x.split("="))==2 and\ - x.split("=")[0]=="linuxver" and\ - x.split("=")[1].strip(), data)) - if shortNameList: - return shortNameList[0] - gentooFile = "/etc/gentoo-release" - systemVersion = "" - flagGentoo = False - if os.path.exists(gentooFile): - gentooLink = "/etc/make.profile" - if os.path.islink(gentooLink): - systemVersion = os.readlink(gentooLink).rpartition("/")[2] - flagGentoo = True - if not flagGentoo: - kernelVersion=self._runos("uname -r") - if kernelVersion: - systemVersion = kernelVersion.partition("-")[0] - return systemVersion - - def get_os_net_hostname(self): - '''Считать имя компьютера net_host''' - hostname=self._runos("hostname -s 2>&1") - if not hostname: - return "" - if re.search("^hostname: ",hostname): - hostname=self._runos("hostname 2>&1") - if not hostname: - return "" - if re.search("^hostname: ",hostname): - return self.Get('os_linux_shortname') - else: - if hostname=='livecd': - return self.Get('os_linux_shortname') - return hostname - - # все ip - def get_os_net_ip(self): - """все ip компьютера, разделитель запятая""" - IPs = [] - netInterfaces=cl_utils.getdirlist("/sys/class/net/") - for i in netInterfaces: - res = self._runos("/sbin/ifconfig %s"%i) - if not res: - break - for line in res: - searchIP = re.search('addr:([0-9\.]+).+Bcast:', line) - if searchIP: - # ip адрес - ip = searchIP.groups()[0] - IPs.append(ip) - return ",".join(IPs) - - # Разрешенные сети (в данном случае все сети) - def get_os_net_allow(self): - """Разрешенные сети разделитель запятая""" - - def getNet(ip, mask): - """По ip и маске получаем сеть""" - octetsMult = (0x1, 0x100, 0x10000, 0x1000000) - octetsIp = map(lambda x: int(x), ip.split(".")) - octetsMask = map(lambda x: int(x), mask.split(".")) - ipNumb = 0 - for i in octetsMult: - ipNumb += octetsIp.pop()*i - maskNumb = 0 - for i in octetsMult: - maskNumb += octetsMask.pop()*i - startIpNumber = maskNumb&ipNumb - x = startIpNumber - nMask = lambda y: len(filter(lambda x: y >> x &1 ,range(32))) - return "%s.%s.%s.%s/%s"\ - %(x>>24, x>>16&255, x>>8&255, x&255, nMask(maskNumb)) - - networks=[] - netInterfaces=cl_utils.getdirlist("/sys/class/net/") - flagError = False - for i in netInterfaces: - res = self._runos("/sbin/ifconfig %s"%i) - if not res: - flagError = True - break - for j in res: - s_ip=re.search('addr:([0-9\.]+).+Bcast:.+Mask:([0-9\.]+)' ,j) - if s_ip: - ip, mask = s_ip.groups() - networks.append(getNet(ip, mask)) - if flagError: - return "" - return ",".join(networks) - - def get_os_locale_locale(self): - """локаль (прим: ru_RU.UTF-8)""" - if os.environ.has_key("LANG"): - return os.environ["LANG"] - else: - return "en_US.UTF-8" - - def get_os_locale_lang(self): - """язык (прим: ru_RU)""" - locale = self.Get("os_locale_locale") - if locale: - return locale.split(".")[0] - return "" - - def get_os_locale_language(self): - """язык (прим: ru)""" - lang = self.Get("os_locale_lang") - if lang: - return lang.split("_")[0] - return "" - - def get_os_locale_xkb(self): - """раскладка клавиатуры для X""" - path = '/etc/conf.d/keymaps' - mapDict={"by":"us,by", - "be-latin1":"be,us", - "br-abnt2":"br,us", - "cf":"ca,us", - "dk-latin1":"dk,us", - "fr-latin9":"fr,us", - "de-latin1":"de,us", - "is-latin1":"is,us", - "it":"it,us", - "no-latin1":"no,us", - "pl":"pl,us", - "-u ru4":"us,ru(winkeys)", - "es euro2":"es,us", - "sv-latin1":"se,us", - "ua-utf":"us,ua(winkeys)", - "uk":"gb,us", - "us":"us"} - if os.path.exists(path): - FD = open(path) - data = FD.readlines() - FD.close() - shortNameList = filter(lambda y:y, - map(lambda x:\ - len(x.split("="))==2 and\ - x.split("=")[0]=="KEYMAP" and\ - x.split("=")[1].replace('"',"").strip(),\ - data)) - if shortNameList: - if shortNameList[0] in mapDict.keys(): - return mapDict[shortNameList[0]] - lang = self.Get("os_locale_lang") - # Языки: - # Португальский - pt_BR - # Французский - fr_FR - # Немецкий - de_DE - # Итальянский - it_IT - # Польский - pl_PL - # Русский - ru_RU - # Испанский - es_ES - # Украинский - uk_UA - # Английский - en_US - xkbDict = {'pt_BR':'br,us', - 'fr_FR':'fr,us', - 'de_DE':'de,us', - 'it_IT':'it,us', - 'pl_PL':'pl,us', - 'ru_RU':'us,ru(winkeys)', - 'es_ES':'es,us', - 'uk_UA':'us,ua(winkeys)', - 'en_US':'us'} - if lang: - if xkbDict.has_key(lang): - return xkbDict[lang] - return "" - - def get_os_locale_xkbname(self): - """названия используемых раскладок клавиатуры для X""" - localeXkb = self.Get("os_locale_xkb") - if localeXkb: - return localeXkb.split("(")[0] - return "" - - def get_os_arch_machine(self): - """архитектура процессора""" - march = self._runos("uname -m") - if not march: - return "" - return march - - def get_os_root_dev(self): - """корневой раздел файловой системы""" - for record in open('/proc/cmdline','rb').readlines(): - re_res=re.search('^root=(\/dev\/[a-z]+[0-9]).*',record.strip()) - if re_res: - return re_res.group(1) - else: - mountLunes = self._runos("mount") - if not mountLunes: - return "" - if type(mountLunes) == types.ListType: - root_dev = mountLunes[0].split("on / type")[0].strip() - if root_dev: - return root_dev - return "" - - def get_os_root_type(self): - """тип носителя (ram, hdd, livecd)""" - mountLunes = self._runos("mount") - if not mountLunes: - return "" - rootType = "hdd" - if type(mountLunes) == types.ListType: - flagCD = False - for line in mountLunes: - if "/dev/loop0 on / type" in line: - rootType = "ram" - break - elif "/dev/loop0 on /newroot/mnt/livecd type" in line: - rootType = "ram" - flagCD = True - break - if rootType == "ram": - if os.path.exists("/mnt/livecd") or flagCD: - rootType = "livecd" - return rootType - rootDev = self.Get("os_root_dev") - if rootType != "ram" and rootDev: - slpRootDev = rootDev.split("/dev/") - if len(slpRootDev) == 2: - rDev = slpRootDev[1] - devLines = self._runos("ls -la /dev/disk/by-id/", None, - {"LANG":"C"}) - if not devLines: - return "" - if type(devLines) == types.ListType: - for line in devLines: - if rDev in line and "usb-" in line: - rootType = "usb-hdd" - break - if rootType == "ram": - rootType = "hdd" - return rootType - else: - return "" - - def get_hr_virtual(self): - """Название виртуальной машины (virtualbox, vmware, qemu)""" - pciLines = self._runos("/usr/sbin/lspci") - if not pciLines: - return False - virtSysDict = {'VirtualBox':'virtualbox', - 'VMware':'vmware', - 'Qumranet':'qemu'} - virtName = '' - for vName in virtSysDict.keys(): - if filter(lambda x: vName in x, pciLines): - virtName = virtSysDict[vName] - break - return virtName diff --git a/build/lib/calculate-lib/pym/cl_log.py b/build/lib/calculate-lib/pym/cl_log.py deleted file mode 100644 index 46acdf7..0000000 --- a/build/lib/calculate-lib/pym/cl_log.py +++ /dev/null @@ -1,59 +0,0 @@ -#-*- coding: utf-8 -*- - -# Copyright 2008-2010 Mir Calculate Ltd. http://www.calculate-linux.org -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import os -import time - -class log(): - """Класс для записи в лог""" - # Директория хранения логов - logDir = "/var/log/calculate" - def __init__(self,fileName, addDataTime=True): - self.logFile = os.path.join(self.logDir,fileName) - if not os.path.exists(self.logDir): - os.makedirs(self.logDir) - self.addDataTime = addDataTime - - def addLog(self, textLog): - """Добавляет текст в лог файл""" - if not os.path.exists(self.logFile): - try: - fd = os.open(self.logFile, os.O_CREAT,0600) - os.close(fd) - except: - print "Error creating file %s"%self.logFile - return False - textWrite = textLog - if not textLog[-1:] == "\n" : - textWrite = "%s\n"%textLog - if self.addDataTime: - textWrite = "%s %s"%(time.strftime("%d/%m/%Y %H:%M:%S",\ - time.localtime()),textWrite) - try: - FD = open (self.logFile, "a") - FD.write(textWrite) - FD.close() - except: - print "Error writing to file %s"%self.logFile - return False - return True - - def writeError(self, textLog): - """Добавляет сообщение об ошибке в log""" - return self.addLog("ERROR: %s" %textLog) - - def writeSuccess(self, textLog): - """Добавляет сообщение об успехе в log""" - return self.addLog("SUCCESS: %s" %textLog) diff --git a/build/lib/calculate-lib/pym/cl_profile.py b/build/lib/calculate-lib/pym/cl_profile.py deleted file mode 100644 index 8d8ab64..0000000 --- a/build/lib/calculate-lib/pym/cl_profile.py +++ /dev/null @@ -1,7136 +0,0 @@ -#-*- coding: utf-8 -*- - -# Copyright 2008-2010 Mir Calculate Ltd. http://www.calculate-linux.org -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import os -import cl_base -import stat -import re -import xml.dom.minidom -from xml import xpath -import subprocess -import types -import copy -import random -import string -import time - -tr = cl_base.lang() -tr.setLocalDomain('cl_lib') -tr.setLanguage(sys.modules[__name__]) - - -class _error: - # Здесь ошибки, если они есть - error = [] - def getError(self): - """Выдать ошибки""" - if not self.error: - return False - error = "" - for e in self.error: - error += e + "\n" - return error - - def setError(self, error): - """Установка ошибки""" - self.error.append(error) - return True - - -class _terms(_error): - """Вычисление условий применяемых в профилях - - """ - # регулярное выражение для не версии - _re_not_Version = re.compile("[^0-9\.]|^$") - # регулярное выражение для функции - _reFunction = re.compile(\ - "([a-zA-Z0-9\_\-]+)\([a-zA-Z0-9_\-\+\,\*\/\.\'\"~]+\)") - # Регулярное выражение для названия переменной - _reDenyName = re.compile("[^a-zA-Z0-9\_\-]") - # Регулярное выражение для сравниваемого значения - _reDenyValue = re.compile("[^0-9a-zA-Z_\.-]") - - def _convertVers(self, verA, verB): - """Конвертирование номеров версий для корректного сравнения - """ - elemA = verA.split(".") - elemB = verB.split(".") - if len(elemA) > len(elemB): - maxElemB = len(elemB)-1 - for i in range(len(elemA)): - if i > maxElemB: - elemB.append("0") - else: - maxElemA = len(elemA)-1 - for i in range(len(elemB)): - if i > maxElemA: - elemA.append("0") - for i in range(len(elemB)): - lenA = len(elemA[i]) - lenB = len(elemB[i]) - if lenA == lenB: - pass - elif lenA > lenB: - res = lenA - lenB - for z in range(res): - elemB[i] = "0" + elemB[i] - elif lenB > lenA: - res = lenB - lenA - for z in range(res): - elemA[i] = "0" + elemA[i] - return (".".join(elemA), ".".join(elemB)) - - def _equalTerm(self, term, textError, function=False): - """Вычисление логических выражений для условий - - Для корректной работы в классе который наследует этот класс - должен быть объявлен аттрибут self.objVar - (объект для работы с переменными) - function - функция для для обработки функций в заголовке блока - """ - trm = {"&":" and ","||":" or "} - rule = ["==", "!=", ">=", "<=", ">", "<"] - listEqual = [] - for k in trm.keys(): - if k in term: - term = term.replace(k,trm[k]) - trs = term.split(" ") - for t in trs: - flagRule = False - for sepF in rule: - if sepF in t: - flagRule = True - vals = t.split(sepF) - break - - if not flagRule: - flagLog = False - for k in trm.values(): - if k.strip() == t: - flagLog = True - break - if not flagLog: - self.setError("'%s'"%term + " " + _("incorrect")) - self.setError (textError) - return False - else: - listEqual.append(k) - else: - #проверка на допустимость названия переменной - flagFunction = False - if self._reDenyName.search(vals[0]): - #проверка на допустимость функции - flagError = True - if function: - searchFunct = self._reFunction.search(vals[0]) - if searchFunct: - flagError = False - flagFunction = True - if flagError: - self.setError("'%s'"%term + " " + _("incorrect")) - self.setError(textError) - return False - #проверка на допустимость значения - if self._reDenyValue.search(vals[1]): - self.setError("'%s'"%term + " " + _("incorrect")) - self.setError(textError) - return False - flagIntTypeVar = None - if flagFunction: - valVars = function("#-%s-#"%vals[0]) - if valVars is False: - self.setError("'%s'"%term + " " + _("incorrect")) - self.setError(textError) - return False - if "load" == searchFunct.group(1): - if re.search("\(\s*num\s*,",vals[0]): - if valVars: - try: - valVars = int(valVars) - except: - self.setError("'%s'"%term + " " + \ - _("incorrect")) - self.setError (textError) - return False - flagIntTypeVar = True - else: - flagIntTypeVar = False - else: - if valVars == "" and\ - not self._re_not_Version.search(vals[1]): - valVars = "0" - elif vals[1] == "" and\ - not self._re_not_Version.search(valVars): - vals[1] = "0" - else: - try: - valVars = self.objVar.Get(vals[0]) - except self.objVar.DataVarsError, e: - print textError - print e - cl_base.exit(1) - # Номера версий для ini - flagNotIniFunct = True - # Два значения не пусты - flagNotEmptyVals = not (valVars == "" and vals[1] == "") - if flagFunction and flagNotEmptyVals and\ - searchFunct.group(1) == "ini": - # Проверка значения на версию - if not self._re_not_Version.search(valVars) and\ - not self._re_not_Version.search(vals[1]): - verFile, verVar = self._convertVers(vals[1],valVars) - exec(\ - "res=("+"'"+verVar+"'"+sepF+"'"+verFile+"'"+")") - if res: - listEqual.append("1") - else: - listEqual.append("0") - flagNotIniFunct = False - # Cравниваем номера версий - if flagNotIniFunct: - if flagNotEmptyVals and\ - ("_ver" in vals[0] or\ - (flagFunction and searchFunct.group(1) == "pkg") or\ - (flagFunction and searchFunct.group(1) == "load" and\ - re.search("\(\s*ver\s*,",vals[0]))): - # Проверка значения на версию - if self._re_not_Version.search(vals[1]): - self.setError("'%s'"%term + " " + _("incorrect")) - self.setError (_("Value is not version")) - return False - # Проверка значения функции на версию - if self._re_not_Version.search(valVars): - self.setError("'%s'"%term + " " + _("incorrect")) - self.setError (_("Value function is not version")) - return False - verFile, verVar = self._convertVers(vals[1],valVars) - exec("res=("+"'"+verVar+"'"+sepF+"'"+verFile+"'"+")") - if res: - listEqual.append("1") - else: - listEqual.append("0") - flagNotIniFunct = False - else: - if flagIntTypeVar == None: - flagIntTypeVar = True - try: - valVars = int(valVars) - except: - flagIntTypeVar = False - if flagIntTypeVar: - if not vals[1].strip(): - vals[1] = 0 - try: - valFile = int(vals[1]) - except: - self.setError("'%s'"%term +" " +_("incorrect")) - self.setError (textError) - return False - valVar = valVars - exec("res=(%d%s%d)"%(valVar,sepF,valFile)) - if res: - listEqual.append("1") - else: - listEqual.append("0") - else: - if sepF == "!=" or sepF == "==": - if not vals[1].strip(): - vals[1] = "" - valFile = vals[1] - valVar = valVars - exec(\ - "res=("+'"""'+valVar+'"""'+sepF+"'"+valFile+\ - "'"+")") - if res: - listEqual.append("1") - else: - listEqual.append("0") - else: - if not flagNotEmptyVals: - listEqual.append("0") - else: - self.setError("'%s'"%term + " "\ - + _("incorrect")) - self.setError (textError) - return False - exec("res=(%s)"%("".join(listEqual))) - return res - -class fileHeader(_terms): - """Обработка заголовков профилей и конфигурационных файлов - - """ - # Допустимые параметры заголовка - allowParam = ["format", "format_conf", "comment", "append", "force", - "link", "mirror", "symbolic", "chmod", "chown", "name"] - # Корректность заголовка - headerCorrect = True - - # Тип профиля - fileType = "" - # Тип вставки профиля - typeAppend = "" - # Возможные типы вставки профилей - _fileAppend = "join", "before", "after", "replace", "remove" - # Интерпретатор (#!/bin/bash) (#!/usr/bin/python) - execStr = "" - # Символ комментария - comment = False - # Выражение для поиска строки интерпретатора - reExecStr = re.compile("^#!.+\s*",re.I) - # условные операторы - terms = ('>', '<', '==', '!=', '>=', '<=') - # параметры без значения - listParNotVal = ("symbolic", "force", "mirror") - # Результат вычисления условия в заголовке - headerTerm = True - # Сообщение о ошибке - errorMessage = "" - - def __init__(self, text, comment=False, fileType=False, objVar=False, - function=False): - self.body = text - # Объект с переменными - self.objVar=objVar - # Параметры описанные в заголовке файла профиля - self.params = {} - # некорректные параметры - incorrectParams = set([]) - # Удаление Заголовка Calculate - if comment: - # В случае текста XML - if type(comment) == types.TupleType and len(comment) == 2: - _titleList = (_("Modified"), _("File of a profile")) - reCalcHeader =\ - re.compile(u"\s*%s\s+%s.+Calculate.+\s+%s.+\s+%s\s?"%(\ - comment[0], - _titleList[0].decode("UTF-8"), - _titleList[1].decode("UTF-8"), - comment[1], - ), - re.M|re.I|re.U) - textUnicode = text.decode("UTF-8") - reS = reCalcHeader.search(textUnicode) - if reS: - textBody = textUnicode[:reS.start()]+textUnicode[reS.end():] - if textBody: - self.body = textBody.encode("UTF-8") - else: - reCalcHeader =\ - re.compile("\s*%s\-+\s+%s.+Calculate.+\s+%s.+\s+%s\-+\s?"%(\ - comment, - comment, - comment, - comment, - ), - re.M|re.I) - reS = reCalcHeader.search(text) - if reS: - self.body = text[reS.end():] - - if fileType != False: - if fileType=="bin": - self.params["format"] = fileType - self.fileType = self._getType() - self.typeAppend = self._getAppend() - else: - textLines = text.splitlines() - if textLines: - textLine = textLines[0] - rePar = re.compile("\s*#\s*calculate\s+",re.I) - reP = rePar.search(textLine) - if reP: - reL = False - reLns = re.compile(r"\A([^\\\n]*\\\n)+[^\n]*\n*",re.M) - reLs = reLns.search(text) - if reLs: - reL = reLs - paramLine = text[reP.end():reLs.end()] - paramLine = paramLine.replace("\\"," ") - else: - reLn = re.compile("\n") - reL = reLn.search(text) - paramLine = textLine[reP.end():] - if reL: - self.body = text[reL.end():] - else: - self.body = "" - paramList = re.split("\s+",paramLine) - if paramList: - for i in paramList: - foundTerm = False - for term in self.terms: - if term in i: - foundTerm = True - if function: - rezTerm = self._equalTerm(i,\ - _("header profile not valid: ") + \ - i,function) - else: - rezTerm = self._equalTerm(i,\ - _("header profile not valid: ") + \ - i) - if not rezTerm: - self.headerTerm = False - break - if not foundTerm: - par = i.split("=") - if len(par) == 1: - if i in self.listParNotVal: - self.params[i] = "True" - else: - if i.strip(): - incorrectParams = set([i]) - elif len(par) == 2: - self.params[par[0]] = par[1] - - self.comment = self._getComment() - self.fileType = self._getType() - self.typeAppend = self._getAppend() - reExecRes = self.reExecStr.search(self.body) - if reExecRes: - self.execStr = self.body[reExecRes.start():reExecRes.end()] - self.body = self.body[reExecRes.end():] - if not incorrectParams: - incorrectParams = set(self.params.keys()) - set(self.allowParam) - if incorrectParams: - self.headerTerm = False - self.headerCorrect = False - self.errorMessage = _("incorrect header parameters - '%s'")\ - % " ".join(list(incorrectParams)) - - def _getType(self): - """Выдать тип файла""" - if self.params.has_key("format"): - return self.params["format"] - else: - return "raw" - - def _getAppend(self): - """Выдать тип добавления файла""" - if self.params.has_key("append") and self.params["append"] in\ - self._fileAppend: - return self.params["append"] - else: - if self.fileType != "raw" and self.fileType != "bin" and\ - self.fileType != "": - self.params["append"] = "join" - return "join" - self.params["append"] = "replace" - return "replace" - - def _getComment(self): - """Выдать символ комментария файла""" - if self.params.has_key("comment"): - return self.params["comment"] - else: - return False - - -class dirHeader(_terms): - """Обработка заголовков профилей директорий - - """ - # Допустимые параметры заголовка - allowParam = ["append", "chmod", "chown", "name"] - # Корректность заголовка - headerCorrect = True - - # Тип вставки профиля - typeAppend = "" - # Возможные типы вставки профилей - _fileAppend = "join", "remove" - # условные операторы - terms = ('>', '<', '==', '!=', '>=', '<=') - # параметры без значения - listParNotVal = ("symbolic", "force") - # Результат вычисления условия в заголовке - headerTerm = True - # Сообщение о ошибке - errorMessage = "" - - def __init__(self, text, objVar=False, function=False): - self.body = text - # Объект с переменными - self.objVar=objVar - # Параметры описанные в заголовке файла профиля - self.params = {} - # некорректные параметры - incorrectParams = set([]) - - textLines = text.splitlines() - flagErrorBody = False - if textLines: - textLine = textLines[0] - rePar = re.compile("\s*#\s*calculate\s+",re.I) - reP = rePar.search(textLine) - if reP: - reL = False - reLns = re.compile(r"\A([^\\\n]*\\\n)+[^\n]*\n*",re.M) - reLs = reLns.search(text) - if reLs: - reL = reLs - paramLine = text[reP.end():reLs.end()] - paramLine = paramLine.replace("\\"," ") - else: - reLn = re.compile("\n") - reL = reLn.search(text) - paramLine = textLine[reP.end():] - if reL: - self.body = text[reL.end():] - else: - self.body = "" - if self.body.strip(): - self.headerTerm = False - self.headerCorrect = False - self.errorMessage = _("incorrect text in profile: '%s'")\ - %self.body - flagErrorBody = True - if not flagErrorBody: - paramList = re.split("\s+",paramLine) - if paramList: - for i in paramList: - foundTerm = False - for term in self.terms: - if term in i: - foundTerm = True - if function: - rezTerm = self._equalTerm(i,\ - _("header profile not valid: ") + \ - i,function) - else: - rezTerm = self._equalTerm(i,\ - _("header profile not valid: ") + \ - i) - if not rezTerm: - self.headerTerm = False - break - if not foundTerm: - par = i.split("=") - if len(par) == 1: - if i in self.listParNotVal: - self.params[i] = "True" - else: - if i.strip(): - incorrectParams = set([i]) - elif len(par) == 2: - self.params[par[0]] = par[1] - self.typeAppend = self._getAppend() - if not flagErrorBody: - if not incorrectParams: - incorrectParams = set(self.params.keys()) - set(self.allowParam) - if incorrectParams: - self.headerTerm = False - self.headerCorrect = False - self.errorMessage = _("incorrect header parameters - '%s'")\ - % " ".join(list(incorrectParams)) - - def _getAppend(self): - """Выдать тип добавления директории""" - if self.params.has_key("append") and self.params["append"] in\ - self._fileAppend: - return self.params["append"] - else: - return "join" - -class objShare: - """Общий клас для объектов, наследуем - - """ - - def createFieldTerm(self, name, value, quote, docObj): - """Создание поля переменная - значение - - при создании поля проверяется первый символ названия переменной - и добавляется тег action - "!" - drop удаляет - "+" - join добавляет - "-" - replace заменяет - """ - fieldAction = False - if name: - if name[0] == "!" or name[0] == "-" or name[0] == "+": - qnt = self.removeSymbolTerm(quote) - fieldXML = docObj.createField("var",[qnt], - name[1:], [value], - False, False) - if name[0] == "!": - fieldAction = "drop" - elif name[0] == "+": - fieldXML.setAttribute("type", "seplist") - fieldAction = "join" - else: - fieldXML = docObj.createField("var", - [quote.replace("\n","")], - name, [value], - False, False) - else: - fieldXML = docObj.createField("var", - [quote.replace("\n","")], - name, [value], - False, False) - if fieldAction: - docObj.setActionField(fieldXML, fieldAction) - return fieldXML - - def removeSymbolTerm(self, text): - """Удаляет первый символ названия переменной в строке - - Если первый встречающийся символ с начала строки - '+', '-', '!' то он из этой строки будет удален, - если перед этим символом были пробельные символы, - то они будут сохранены, так-же если в строке есть символ - перевода строки он будет удален. - """ - reTerm = re.compile("^[ \t]*(\!|\+|\-)") - textNS = text.replace("\n","") - res = reTerm.search(textNS) - if res: - textNS = textNS[res.start():res.end()-1] + textNS[res.end():] - return textNS - - def getConfig(self): - """Выдает конфигурационный файл""" - listConfigTxt = [] - childNodes = self.docObj.getNodeBody().childNodes - for node in childNodes: - if node.nodeType == node.ELEMENT_NODE: - if node.tagName == "field": - listConfigTxt.append(self.docObj.getQuoteField(node)) - elif node.tagName == "area": - self.docObj.xmlToText([node], listConfigTxt) - return "".join(listConfigTxt) - - - def splitToFields(self, txtBloc): - """Разбиваем текст на поля (объекты) которые имеют следующие аттрибуты - - self.name - если переменная то имя переменной - self.value - если у переменной есть значение то значение переменной - self.comment - если комментарий то текст комментария - self.br - если перевод строки то текст перед переводом из пробелов - - Результат список объектов полей - """ - finBloc = "\n" - if txtBloc[-1] != "\n": - finBloc = "" - - linesBlocTmp = txtBloc.splitlines() - linesBloc = [] - brBloc = [] - z = 0 - lenLines = len(linesBlocTmp) - for i in linesBlocTmp: - - if self.reComment.split(i)[0]: - findCooment = self.reComment.search(i) - comment = False - par = i - if findCooment: - par = i[:findCooment.start()] - comment = i[findCooment.start():] - fields = self.reSepFields.split(par) - lenFields = len(fields) - - if lenFields>1: - for fi in range(lenFields-1): - linesBloc.append(fields[fi]+ self.sepFields) - if fi == lenFields-2: - if comment: - brBloc.append("") - else: - if (lenLines-1)== z: - brBloc.append(finBloc) - else: - brBloc.append("\n") - else: - brBloc.append("") - if comment: - linesBloc.append(comment) - if (lenLines-1)== z: - brBloc.append(finBloc) - else: - brBloc.append("\n") - else: - linesBloc.append(i) - if (lenLines-1)== z: - brBloc.append(finBloc) - else: - brBloc.append("\n") - else: - linesBloc.append(i) - if (lenLines-1)== z: - brBloc.append(finBloc) - else: - brBloc.append("\n") - z +=1 - fields = self.setDataField(linesBloc, brBloc) - return fields - -class xmlShare: - """Общий класс для объектов XML, наследуем - - """ - def _createElement(self, doc, tagName, text="", attributes={}): - """Создание нового XML элемента""" - element = doc.createElement(tagName) - if text: - txtNode = doc.createTextNode(self._toUNICODE(text)) - element.appendChild(txtNode) - for attr in attributes.keys(): - attribute = doc.createAttribute(attr) - attribute.nodeValue = attributes[attr] - element.setAttributeNode(attribute) - return element - - def _toUNICODE(self,val): - """перевод текста в юникод""" - if 'unicode' in "%s" %(type(val)): - return val - else: - return val.decode('UTF-8') - - -class xmlNode(xmlShare): - """Класс для создания нод без аттрибутов - - """ - def __init__(self): - self.node = False - - - def createNode(self, doc, tagName, text=""): - """Создает XML элемент без аттрибутов""" - self.node=self._createElement(doc, tagName, text) - return self.node - - def getNode(self): - return self.node - - -class xmlCaption: - """Класс XML заголовок - - """ - def __init__(self): - #Заголовок области XML нода - self.caption = False - - - def createCaption(self, doc, name, quotes, action=False): - """Создание заголовка области""" - tmpNode = xmlNode() - self.caption = tmpNode.createNode(doc, "caption") - nameNode = tmpNode.createNode(doc, "name",name) - self.caption.appendChild(nameNode) - if action: - actNode = tmpNode.createNode(doc, "action", action) - self.caption.appendChild(actNode) - for q in quotes: - quoteNode = tmpNode.createNode(doc, "quote", q) - self.caption.appendChild(quoteNode) - return self.caption - - def getCaption(self): - """Выдает XML ноду заголовка области""" - return self.caption - -class xmlField(xmlShare): - """Класс для работы с XML полем - - """ - def __init__(self): - # XML нода поле - self.field = False - - - def createField(self, doc, typeField, quotes, name="", - values=[],action=False): - """Cоздание XML ноды поле""" - self.field = self._createElement(doc, "field", "", {"type":typeField}) - if name: - nameNode = self._createElement(doc, "name", name) - self.field.appendChild(nameNode) - for v in values: - valueNode = self._createElement(doc, "value", v) - self.field.appendChild(valueNode) - if action: - actNode = self._createElement(doc, "action", action) - self.field.appendChild(actNode) - for q in quotes: - quoteNode = self._createElement(doc, "quote", q) - self.field.appendChild(quoteNode) - return self.field - - - -class xmlFields: - """Класс, в котором находится список ХМL нод field - - """ - def __init__(self): - self.fields = [] - - def appendField(self, field): - """Добавить XML ноду field""" - self.fields.append(field) - return self.fields - - def getFields(self): - """Выдать список XML нод""" - return self.fields - - -class xmlArea: - """Класс для работы с XML областью - - """ - def __init__(self): - # Область - self.area = False - - def createArea(self, doc, xmlCaption, xmlFields): - """Создание XML области""" - tmpNode = xmlNode() - self.area = tmpNode.createNode(doc, "area") - if xmlCaption and xmlCaption.getCaption(): - self.area.appendChild(xmlCaption.getCaption()) - if xmlFields: - fields = xmlFields.getFields() - for field in fields: - self.area.appendChild(field) - return self.area - -class xmlDoc: - """Класс для работы с XML документом - - """ - def __init__(self): - # документ - self.doc = False - # главная нода - self.root = False - # тело документа - self.body = False - # Заголовок области - временный (в реальности один объект заголовок) - self.tmpCaption = False - # Поля - временные (в реальности один объект поля) - self.tmpFields = False - # Разделитель областей - по умолчанию перевод строки "\n" - self.sepAreas = False - # Разделитель разделенных списков - по умолчанию перевод строки "\n" - #self.sepSplitFields = False - - - def createDoc(self, typeDoc, version): - """Создание нового документа новый документ""" - docTxt = '' - docTxt += '%s'% version - docTxt += '%s' % typeDoc - docTxt += '' - self.doc = xml.dom.minidom.parseString(docTxt) - self.root = self.doc.documentElement - self.body = xpath.Evaluate('child::body',self.root)[0] - # установка разделителя областей - self.sepAreas = self.createField("br",[],"",[],False,False) - # установка разделителя областей разделенных списков - #self.sepSplitFields = self.createField("br",[],"",[],False,False) - return self.doc - - def addField(self, field): - """Добавляет поле во временный список - - Из этого списка в дальнейшем формируется XML область - """ - if not self.tmpFields: - self.tmpFields = xmlFields() - self.tmpFields.appendField(field) - - def createCaption(self, name, quotes, action=False): - """Cоздает заголовок области - - Помещает заголовок в временный артибут - Используется при создании области - """ - self.tmpCaption = xmlCaption() - return self.tmpCaption.createCaption(self.doc, name, quotes, action) - - def createField(self, typeField, quotes=[], name="", - values=[] ,action=False,addTmpField=True): - """Cоздает поле - - Если установлена переменнная addTmpField - добавляет поле во временный список - """ - fieldObj = xmlField() - field = fieldObj.createField(self.doc, typeField, quotes, name, - values, action) - if addTmpField: - self.addField(field) - return field - - def clearTmpFields(self): - """Очищает временный список""" - self.tmpFields = False - - def createArea(self): - """Cоздает область - - Область создается на основании временного атрибута и временного списка - """ - areaObj = xmlArea() - area = areaObj.createArea(self.doc, self.tmpCaption, self.tmpFields) - self.clearTmpCaptionAndFields() - return area - - def clearTmpCaptionAndFields(self): - """Очищает временный аттрибут и временный список""" - self.tmpCaption = False - self.tmpFields = False - - def getNodeRoot(self): - """Выдает корневую ноду""" - return self.root - - def getNodeBody(self): - """Выдает ноду body""" - return self.body - - def setActionField(self, xmlField, actionTxt): - """Устанавливает свойство action для XML поля""" - xmlActions = xpath.Evaluate('child::action',xmlField) - if xmlActions and xmlActions[0].firstChild: - xmlActions[0].firstChild.nodeValue = actionTxt - else: - nodeObj = xmlNode() - newNode = nodeObj.createNode(self.doc, "action", actionTxt) - xmlField.appendChild(newNode) - - - def setActionArea(self, xmlArea, actionTxt): - """Устанавливает свойство action для XML области""" - xmlActions = xpath.Evaluate('child::caption/action',xmlArea) - xmlCaptions = xpath.Evaluate('child::caption',xmlArea) - if xmlActions and xmlActions[0].firstChild: - xmlActions[0].firstChild.nodeValue = actionTxt - else: - if xmlCaptions: - nodeObj = xmlNode() - newNode = nodeObj.createNode(self.doc, "action", actionTxt) - xmlCaptions[0].appendChild(newNode) - - def joinField(self, xmlArea, xmlNewField): - """Объединяет XML ноду область и XML ноду поле""" - newNameField = self.getNameField(xmlNewField) - if not newNameField or not newNameField.strip(): - return False - fieldsOldComp = xpath.Evaluate("child::field[child::name='%s']"\ - %(newNameField), xmlArea) - # Если поле не найдено добавляем его - typeNewField = self.getTypeField(xmlNewField) - if not fieldsOldComp and typeNewField != "seplist": - if self.getActionField(xmlNewField) != "drop": - self.setActionField(xmlNewField, "append") - xmlArea.appendChild(xmlNewField) - return True - newFieldsAction = self.getActionField(xmlNewField) - newValues = self.getFieldValues(xmlNewField) - flagCompare = True - - for nodeFieldOld in fieldsOldComp: - if newFieldsAction == "drop": - if nodeFieldOld.nextSibling and\ - self.getTypeField(nodeFieldOld.nextSibling) == "br": - xmlArea.removeChild(nodeFieldOld.nextSibling) - elif nodeFieldOld.previousSibling and\ - self.getTypeField(nodeFieldOld.previousSibling) == "br": - xmlArea.removeChild(nodeFieldOld.previousSibling) - xmlArea.removeChild(nodeFieldOld) - continue - oldValues = self.getFieldValues(nodeFieldOld) - # Сравнение значений переменной профиля и файла - if set(newValues) != set(oldValues): - flagCompare = False - if self.getActionField(xmlNewField) == "drop": - return True - appSplLst = [] - insSplLst = [] - if typeNewField == "seplist": - if fieldsOldComp: - xmlOldField = fieldsOldComp[-1] - else: - xmlOldField = False - seplistNewXML = self.getSepListToField(xmlNewField) - if seplistNewXML: - for nodeSeplist in seplistNewXML: - if self.getActionField(nodeSeplist) != "drop": - if newFieldsAction == "join": - flagCompareSeplist = False - newValues = self.getFieldValues(nodeSeplist) - for nodeFieldOld in fieldsOldComp: - oldValues = self.getFieldValues(nodeFieldOld) - for newValue in newValues: - if newValue in oldValues: - flagCompareSeplist = True - break - if not flagCompareSeplist: - nextNode = xmlOldField.nextSibling - newInsNode = nodeSeplist.cloneNode(True) - self.setActionField(newInsNode,"append") - - if nextNode: - appSplLst.append((newInsNode, - nextNode, - "insert")) - else: - appSplLst.append((newInsNode, - False, - "append")) - else: - newInsNode = nodeSeplist.cloneNode(True) - if self.getActionField(newInsNode) == "join": - self.setActionField(newInsNode,"append") - if xmlOldField: - insSplLst.append((newInsNode, - xmlOldField, - "insert")) - else: - insSplLst.append((newInsNode, - False, - "append")) - - #xmlArea.insertBefore(\ - #nodeSeplist.cloneNode(True), - #xmlOldField) - - parentNode = nodeSeplist.parentNode - parentNode.removeChild(nodeSeplist) - - insNodesRepl = [] - for newNode, nxtNode, app in insSplLst: - flagCompareSeplist = False - newValues = self.getFieldValues(newNode) - for nodeRepl, nxtNode, app in insNodesRepl: - oldValues = self.getFieldValues(nodeRepl) - for newValue in newValues: - if newValue in oldValues: - flagCompareSeplist = True - break - if not flagCompareSeplist: - if xmlOldField: - insNodesRepl.append((newNode, nxtNode, app)) - - for newNode, nxtNode, app in insNodesRepl: - if app == "insert": - xmlArea.insertBefore(newNode,nxtNode) - elif app == "append": - xmlArea.appendChild(newNode) - if xmlOldField: - parentNode = xmlOldField.parentNode - if parentNode and newFieldsAction != "join": - parentNode.removeChild(xmlOldField) - - for newNode, nxtNode, app in appSplLst: - if app == "insert": - xmlArea.insertBefore(newNode,nxtNode) - elif app == "append": - xmlArea.appendChild(newNode) - - if not flagCompare and typeNewField != "seplist": - # Устанавливаем action=replace - self.setActionField(xmlNewField, "replace") - # Если параметры поля не сходятся заменяем поле - xmlArea.replaceChild(xmlNewField.cloneNode(True), - fieldsOldComp[-1]) - - if newFieldsAction == "join": - fieldsOldRemove = [] - else: - fieldsOldRemove = fieldsOldComp[:-1] - - for nodeFieldOld in fieldsOldRemove: - actionOldNode = self.getActionField(nodeFieldOld) - if actionOldNode == "insert" or actionOldNode == "append": - pass - else: - if nodeFieldOld.nextSibling and\ - self.getTypeField(nodeFieldOld.nextSibling) == "br": - xmlArea.removeChild(nodeFieldOld.nextSibling) - xmlArea.removeChild(nodeFieldOld) - return True - - - def getSepListToField(self, xmlField): - """Выдает элементы распределенного массива - - Область предок поля, в этой области ищутся - элементы распределенного массива - """ - nameField = self.getNameField(xmlField) - if not nameField: - return [] - parentNode = xmlField.parentNode - #print parentNode.toprettyxml() - if parentNode: - fieldsVal = xpath.Evaluate(\ - "child::field[attribute::type='seplist'][child::name='%s'] "\ - %(nameField), parentNode) - #print nameField - return fieldsVal - else: - return [] - - def removeComment(self, xmlArea): - """Удаляет комментарии в XML области""" - fieldNodes = xpath.Evaluate('descendant::field',xmlArea) - for fieldNode in fieldNodes: - if fieldNode.hasAttribute("type"): - if fieldNode.getAttribute("type") == "comment" or\ - fieldNode.getAttribute("type") == "br": - parentNode = fieldNode.parentNode - parentNode.removeChild(fieldNode) - else: - if self.getActionField(fieldNode) == "drop": - pass - elif self.getActionField(fieldNode) == "join": - pass - else: - self.setActionField(fieldNode,"append") - - - def joinBody(self, baseBody, newBody): - """Объединяет две области Body""" - newFields = xpath.Evaluate('child::field',newBody) - xmlNewAreas = xpath.Evaluate('child::area',newBody) - for xmlNewArea in xmlNewAreas: - self.joinArea(baseBody,xmlNewArea) - joinNewFields = xpath.Evaluate("child::field[child::action='join']" - ,newBody) - self.addNewFielsOldArea(newFields, joinNewFields, baseBody) - - - def getRemoveNodeSepList(self, removeNodesDict, baseNode, xmNewlField): - """Находит элементы разделенного списка - - Параметры: - removeNodesDict - Cловарь удаляемых полей разделенного списка - формируется программой - baseNode - Нода в которой идет поиск - xmNewlField - Нода field которая проверяется на принадлежность - к разделенному списку - """ - flagNewNodeSeplist = False - if self.getTypeField(xmNewlField) == "seplist": - flagNewNodeSeplist = True - nameNewField = self.getNameField(xmNewlField) - if nameNewField: - if removeNodesDict.has_key(nameNewField): - return removeNodesDict[nameNewField] - else: - oldFields = xpath.Evaluate('child::field', baseNode) - removeNodes = [] - lenOldFields = len(oldFields) - for i in range(lenOldFields): - oldNode = oldFields[i] - flagSep = self.getTypeField(oldNode) == "seplist" - if flagNewNodeSeplist: - flagSep = True - if flagSep and\ - nameNewField == self.getNameField(oldNode): - removeNodes.append(oldNode) - if i+1 1: - for node in listNodes: - node.setAttribute("type", "seplist") - - def insertBRtoBody(self, xmlArea): - """Добавляет необходимые переводы строк - """ - # Потомки - childNodes = self.getFieldsArea(xmlArea) - # нода BR - fieldXMLBr = self.createField("br",[],"",[],False, False) - # разделитель поля - fieldSplit = False - # Предыдущая нода - lastNode = False - # Cледующая нода - nextNode = False - lenChildNodes = len(childNodes) - for i in range(lenChildNodes): - node = childNodes[i] - lastTmpNode = node - # Нода area - if node.tagName == "area": - if self.getActionArea(node) == "append" or\ - self.getActionArea(node) == "join": - self.delActionNodeArea(node) - if lastNode and lastNode.hasAttribute("type") and\ - lastNode.getAttribute("type") == "br" or\ - lastNode and lastNode.hasAttribute("type") and\ - lastNode.getAttribute("type") == "comment": - indNext = i + 1 - if indNext == lenChildNodes: - xmlArea.appendChild(fieldXMLBr.cloneNode(True)) - else: - nextNode = childNodes[indNext] - lastTmpNode = xmlArea.insertBefore(\ - fieldXMLBr.cloneNode(True), - nextNode) - else: - xmlArea.insertBefore(fieldXMLBr.cloneNode(True), - node) - self.insertBRtoBody(node) - # Нода field - else: - if self.getActionField(node) == "append" or\ - self.getActionField(node) == "join": - self.delActionNodeField(node) - if lastNode and lastNode.hasAttribute("type") and\ - lastNode.getAttribute("type") == "br" or\ - lastNode and lastNode.hasAttribute("type") and\ - lastNode.getAttribute("type") == "comment": - indNext = i + 1 - if indNext == lenChildNodes: - xmlArea.appendChild(fieldXMLBr.cloneNode(True)) - else: - nextNode = childNodes[indNext] - lastTmpNode = xmlArea.insertBefore(\ - fieldXMLBr.cloneNode(True), - nextNode) - else: - xmlArea.insertBefore(fieldXMLBr.cloneNode(True), - node) - lastNode = lastTmpNode - - - - def postParserList(self): - """Находит подходящие XML области и делаем из них поля-массивы""" - xmlAreas = xpath.Evaluate('descendant::area', self.body) - for xmlArea in xmlAreas: - flagListXml = True - fieldValues = [] - xmlFields = xpath.Evaluate('child::field',xmlArea) - if not xmlFields: - flagListXml = False - lenXmlFields = len(xmlFields) - lenBrArea = 0 - for xmlField in xmlFields: - xmlNames = xpath.Evaluate('child::name',xmlField) - xmlVals = xpath.Evaluate('child::value',xmlField) - if xmlField.hasAttribute("type") and\ - xmlField.getAttribute("type") == "br": - lenBrArea += 1 - continue - if not xmlNames and not xmlVals: - flagListXml = False - break - if xmlNames and xmlNames[0].firstChild and\ - xmlNames[0].firstChild.nodeValue: - flagListXml = False - break - if not (xmlVals and xmlVals[0].firstChild and\ - xmlVals[0].firstChild.nodeValue): - flagListXml = False - break - else: - fieldValues.append(xmlVals[0].firstChild.nodeValue) - - if lenXmlFields == lenBrArea: - flagListXml = False - if flagListXml: - nameNode = xpath.Evaluate('child::caption/name',xmlArea)[0] - fieldName = "" - if nameNode.firstChild: - fieldName = nameNode.firstChild.nodeValue - listArea = [] - self.xmlToText([xmlArea],listArea) - fieldQuote = "".join(listArea) - fieldXMLBr = False - if fieldQuote and fieldQuote[-1] == "\n": - fieldQuote = fieldQuote[:-1] - fieldXMLBr = self.createField("br",[],"",[],False, False) - fieldXML = self.createField("list", - [fieldQuote], - fieldName, fieldValues, - False, False) - areaAction = self.getActionArea(xmlArea) - if areaAction: - self.setActionField(fieldXML, areaAction) - parentNode = xmlArea.parentNode - parentNode.insertBefore(fieldXML,xmlArea) - if fieldXMLBr: - parentNode.insertBefore(fieldXMLBr,xmlArea) - parentNode.removeChild(xmlArea) - - -class blocText: - """Разбиваем текст на блоки""" - - def splitTxtToBloc(self, text ,openTxtBloc,closeTxtBloc, - commentTxtBloc, sepField): - """Делит текст на блоки (без заголовков) - - openTxtBloc - регулярное выражение для начала блока - closeTxtBloc - регулярное выражение для конца блока - commentTxtBloc - регулярное выражение - комментарий - возвращает блоки текста - """ - blocs = [] - level = 0 - # Нахождение нескольких блоков в строке - # разделители линий, разделителями могут быть ("","\n") - sepsLines = [] - # линии - txtLines = [] - # Исходные строки - txtLinesSrc = text.splitlines() - for line in txtLinesSrc: - lineBR = "" - lineTmpA = line - closeBl = False - txtLinesTmp = [] - commentSpl = commentTxtBloc.split(line) - flagCommentLine = False - if commentSpl[0].strip(): - closeBl = True - if len(commentSpl) > 1: - commentBl = commentTxtBloc.search(line) - textLine =commentSpl[0] - commentLine = line[commentBl.start(0):] - lineTmpA = textLine - flagCommentLine = True - - while (closeBl): - closeBl = sepField.search(lineTmpA) - if closeBl: - lineTmpB = lineTmpA[closeBl.end(0):] - txtLinesTmp.append(lineTmpA[:closeBl.end(0)]) - lineTmpA = lineTmpB - if lineTmpA.strip(): - txtLinesTmp.append(lineTmpA) - # Если есть значение и комментарий в строке - if flagCommentLine: - for l in txtLinesTmp: - txtLines.append(l) - sepsLines.append("") - if not txtLinesTmp: - txtLines.append(textLine) - sepsLines.append("") - txtLines.append(commentLine) - sepsLines.append("\n") - # Если есть несколько блоков в строке - elif len(txtLinesTmp)>1 and txtLinesTmp[1].strip(): - lenTmpLines = len(txtLinesTmp) - for l in range(lenTmpLines): - txtLines.append(txtLinesTmp[l]) - if l == lenTmpLines-1: - sepsLines.append("\n") - else: - sepsLines.append("") - # Cтрока не преобразована - else: - txtLines.append(line) - sepsLines.append("\n") - - # разбивание на блоки - z = 0 - bl = "" - for i in txtLines: - if commentTxtBloc.split(i)[0].strip() and openTxtBloc.search(i): - level += len(openTxtBloc.split(i)) - 1 - if commentTxtBloc.split(i)[0].strip() and closeTxtBloc.search(i): - level -= len(closeTxtBloc.split(i)) - 1 - bl += i + sepsLines[z] - if level == 0: - if bl: - blocs.append(bl) - bl = "" - z += 1 - # cоздание блоков с элементами не входящими в блоки - realBlocs = [] - z = 0 - bl = "" - for i in blocs: - txtLines = i.splitlines() - if len(txtLines) > 0: - line = txtLines[0] - else: - line = i - if commentTxtBloc.split(i)[0].strip() and openTxtBloc.search(line): - if bl: - realBlocs.append(bl) - bl = "" - realBlocs.append(i) - else: - bl += i - z += 1 - if bl: - realBlocs.append(bl) - bl = "" - if level == 0: - if text and text[-1] != "\n": - tmpBlocs = realBlocs.pop() - tmpBlocs = tmpBlocs[:-1] - realBlocs.append(tmpBlocs) - return realBlocs - else: - return [] - - def findArea(self, text, reTextHeader, reTextArea, numGroupArea=0): - """ Делит текст на области (с заголовками) - - reTextHeader - регулярное выражение для заголовка области - reTextArea - регулярное выражение для всей области - numGroupArea - номер групы результата поиска по регулярному выражению - по всей области - возвращает два списка: первый - заголовки, второй - тела областей без - заголоков - """ - # Заголовки областей - headersArea = [] - # Тексты областей без заголовков - textBodyArea = [] - r = reTextArea.search(text) - if not r: - headersArea.append("") - textBodyArea.append(text) - return (headersArea, textBodyArea) - - txtWr = text - while r: - textArea = r.group(numGroupArea) - txtSpl = txtWr.split(textArea) - area = txtSpl[0] - txtWr = txtSpl[1] - if area: - headersArea.append("") - textBodyArea.append(area) - res = reTextHeader.search(textArea) - header = textArea[:res.end()] - body = textArea[res.end():] - - headersArea.append(header) - textBodyArea.append(body) - - if txtWr: - r = reTextArea.search(txtWr) - else: - r = False - if txtWr: - headersArea.append("") - textBodyArea.append(txtWr) - return (headersArea, textBodyArea) - - - def findBloc(self, text, captionTxtBloc, bodyTxtBloc): - """ Делит текст на блоки (с заголовками) - - captionTxtBloc - регулярное выражение для заголовка блока - bodyTxtBloc - регулярное выражение для тела блока - возвращает два списка: первый - заголовки, второй - тела блоков - """ - # Заголовки блоков - headersTxt = [] - # Тексты блоков - blocsTxt = [] - r = captionTxtBloc.search(text) - if r: - headersTxt.append(r.group(0)) - txtSpl = text.split(r.group(0)) - blocTxt = txtSpl[0] - txtWr = txtSpl[1] - rb = bodyTxtBloc.search(blocTxt) - if not blocTxt: - blocsTxt.append(blocTxt) - if rb: - blocsTxt.append(rb.group(0)) - while (r): - r = captionTxtBloc.search(txtWr) - if r: - headersTxt.append(r.group(0)) - txtSpl = txtWr.split(r.group(0)) - blocTxt = txtSpl[0] - txtWr = txtSpl[1] - rb = bodyTxtBloc.search(blocTxt) - if rb: - blocsTxt.append(rb.group(0)) - else: - blocsTxt.append(txtWr) - if headersTxt and blocsTxt: - if len(headersTxt)>len(blocsTxt): - blocsTxt.insert(0,"") - elif len(headersTxt)= 4: - l = 4 - elif lenSymb >= 3: - l = 3 - elif lenSymb >= 2: - l = 2 - else: - if symbols[0] == '_ch_': - return (True,1) - else: - return (False,1) - result = False - for i in range(l): - if i == 0 and symbols[i] != '_fb_': - break - elif i > 0 and symbols[i] != '_nb_': - break - if lenTail>1 and lenTail != i: - return (False,1) - if i > 0: - result = True - return (result, i) - - - def _intToChar(self, x): - he = hex(x)[2:] - exec("ret = '\\x%s'" %he) - return ret - - def _hexToChar(self, he): - exec("ret = '\\x%s'" %he) - return ret - - def encode(self, text): - """Кодирует смешанный формат в UTF-8""" - ind = 0 - l = 0 - utf = [] - lenUtf = [] - indErr = [] - i = 0 - for ch in text: - r, l = self._retUTF(ch) - utf.append(r) - lenUtf.append(l) - i+=1 - while 1: - if utf[ind] == '_fb_': - res, l = self._sumbUtf(utf[ind:],lenUtf[ind]) - if res is False: - indErr.append(ind) - if l>0: - ind +=l - if ind >= len(utf): - break - else: - if utf[ind] != '_ch_': - indErr.append(ind) - ind +=1 - if ind >= len(utf): - break - if indErr: - lenIndErr = len(indErr) - block = [] - blocks = [] - if lenIndErr > 1: - i = 1 - while 1: - if i == 1: - block.append(indErr[i-1]) - if indErr[i] - indErr[i-1] == 1: - block.append(indErr[i]) - else: - if block: - blocks.append(block) - block = [] - block.append(indErr[i]) - i +=1 - if i >= lenIndErr: - break - else: - block.append(indErr[0]) - if block: - blocks.append(block) - listErr = [] - for block in blocks: - string = "" - for elem in block: - string += hex(ord(text[elem]))[-2:] - listErr.append((block[0],"__hex__?%s?__hex__" %string,elem)) - textOut = text - deltaInd = 0 - for erEl in listErr: - startInd = erEl[0] + deltaInd - endInd = erEl[2] + 1 + deltaInd - textOut = textOut[:startInd] + erEl[1] + textOut[endInd:] - deltaInd += len(erEl[1])-(erEl[2]-erEl[0]+1) - #if i == 1: - #break - #i += 1 - return textOut - - def decode(self, text): - """Декодирует UTF-8 в смешанный формат""" - varStart = "__hex__\?" - varEnd = "\?__hex__" - # -1 Это экранирование '?' которое тоже считается - deltVarStart = len(varStart)-1 - deltVarEnd = len(varEnd)-1 - reVar = re.compile(("%s[a-f0-9]+%s")%(varStart,varEnd),re.M) - resS = reVar.search(text) - textProfileTmp = text - while resS: - mark = textProfileTmp[resS.start():resS.end()] - hexString = mark[deltVarStart:-deltVarEnd] - i = 0 - stringInsert = "" - hexCode = "" - for ch in hexString: - if i>=1: - hexCode += ch - stringInsert += self._hexToChar(hexCode) - hexCode = "" - i = 0 - else: - hexCode += ch - i += 1 - textProfileTmp = textProfileTmp.replace(mark, stringInsert) - resS = reVar.search(textProfileTmp) - return textProfileTmp - - def getUserDataInLDAP(self, userName): - """Получаем домашнюю директорию пользователя из LDAP""" - if not self.conLdap: - import cl_utils2 - data = self.getLDAPDataInConfig() - if not data: - return "" - serverName, usersDN, bindDN, bindPW = data - # Подключаемся к LDAP - ldapObj = cl_utils2.ldapFun(bindDN, bindPW, serverName) - if self.getError(): - return "" - self.conLdap = ldapObj.conLdap - searchScope = ldap.SCOPE_ONELEVEL - searchFilter = "uid=%s" %(userName) - retrieveAttributes = ["uidNumber", - "gidNumber" - "homeDirectory"] - resSearch = ldapObj.ldapSearch(usersDN, searchScope, - searchFilter, retrieveAttributes) - if resSearch: - if resSearch[0][0][1].has_key('uidNumber') and\ - resSearch[0][0][1].has_key('gidNumber') and\ - resSearch[0][0][1].has_key('homeDirectory'): - uid = searchUser[0][0][1]['uidNumber'][0] - gid = searchUser[0][0][1]['gidNumber'][0] - homeDir = resSearch[0][0][1]['homeDirectory'][0] - return uid, gid, homeDir - return "" - - -class processingTemplates: - """Класс для обработки шаблонов""" - - def processingFile(self, path, prefix): - """Обработка в случае профиля файла""" - return True - - def processingDirectory(self, path, prefix): - """Обработка в случае директории если возвращаем None то пропуск дир.""" - return True - - def scanningTemplates(self, scanDir, skipFile=[], skipDir=[], - prefix=None, flagDir=False): - """Время последней модификации внутри директории scanDir""" - ret = True - if not prefix: - prefix = os.path.join(scanDir,"")[:-1] - if not flagDir: - # проверка корневой директории - retDir = self.processingDirectory(scanDir, scanDir) - if retDir is None: - return None - elif retDir is False: - return False - if flagDir or stat.S_ISDIR(os.lstat(scanDir)[stat.ST_MODE]): - for fileOrDir in sorted(os.listdir(scanDir)): - absPath = os.path.join(scanDir,fileOrDir) - relPath = absPath.split(prefix)[1] - stInfo = os.lstat(absPath) - statInfo = stInfo[stat.ST_MODE] - if stat.S_ISREG(statInfo): - # Обработка файла - if relPath in skipFile: - continue - if not self.processingFile(absPath, prefix): - ret = False - break - elif stat.S_ISDIR(statInfo): - # Обработка директории - if relPath in skipDir: - continue - retDir = self.processingDirectory(absPath, prefix) - if retDir is None: - continue - elif retDir is False: - ret = False - break - ret = self.scanningTemplates(absPath, skipFile, - skipDir, prefix, True) - if ret is False: - break - return ret - - -class profile(_file, _terms, xmlShare, processingTemplates): - """Класс для работы с профилями - - На вход 2 параметра: объект хранения переменных, имя сервиса - не - обязательный параметр - - """ - # Словарь установленных программ {"имя программы":[версии]} - installProg = {} - - # Cписок просканированных категорий установленных программ - installCategory = [] - - # Флаг сканирования всех установленных программ - flagAllPkgScan = False - - # Название файла профиля директории - profDirNameFile = ".calculate_directory" - - # стек глобальных переменных - stackGlobalVars = [] - - # директория установленных программ - basePkgDir = "/var/db/pkg" - - # регулярное выражение для поиска версии - reFindVer = re.compile("(?<=\-)\d+\.?\d*\.?\d*") - - def __init__(self, objVar, servDir=False, dirsFilter=[], filesFilter=[]): - # Необрабатываемые директории - self.dirsFilter = dirsFilter - # Необрабатываемые файлы - self.filesFilter = filesFilter - _file.__init__(self) - # Словарь для создания объектов новых классов по образцу - self.newObjProt = {'proftpd':(apache,),} - # Заголовок title - self.__titleHead = "--------------------------------------\ -----------------------------------------" - self._titleBody = "" - self._titleList = (_("Modified"), _("File of a profile")) - - # Метки - varStart = "#-" - varEnd = "-#" - self._reVar = re.compile(("%s[a-zA-Z0-9_-]+%s")%(varStart,varEnd),re.M) - self._reFunc = re.compile(("%s[a-zA-Z0-9_\-\+\(\)\, \*\/\.\'\"~]+%s")\ - %(varStart,varEnd),re.M) - self._deltVarStart = len(varStart) - self._deltVarEnd = len(varEnd) - # Условия - self._reTermBloc = re.compile("#\?(?P[a-zA-Z0-9\-_]+)\ -(?P\([a-zA-Z0-9_\-\+\,\*\/\.\'\"~]+\))?\ -(?P[\>\<\=\!\&\|]+\ -[a-zA-Z0-9\>\<\=\!\|\&\-\+\*\/_\.\,\(\)\'\"~]*)#\ -\n*(?P.+?)\n*#(?P=rTerm)#(?P[ ,\t]*\n?)",re.M|re.S) - # Объект с переменными - self.objVar = objVar - # Базовая директория переноса профилей "/mnt/calculate" или "/" и.т.д - baseDir = self.objVar.Get("cl_root_path") - #self._baseDir = os.path.split(baseDir)[0] - self._baseDir = baseDir - if self._baseDir == "/": - self._baseDir = "" - # Последняя часть директории профиля (имя сервиса: samba, mail) - self._servDir = servDir - if self._servDir: - if self._servDir[0] != "/": - self._servDir = "/" + self._servDir - if self._servDir[-1] != "/": - self._servDir += "/" - self._servDir = os.path.split(self._servDir)[0] - # Созданные директории - self.createdDirs = [] - # Примененные файлы - self.filesApply = [] - # номер обрабатываемого файла - self.numberProcessProf = 0 - # имя текущей программы - _nameProgram = self.objVar.Get("cl_name").capitalize() - # версия текущей программы - _versionProgram = self.objVar.Get("cl_ver") - # имя и версия текущей программы - self.programVersion = "%s %s"%(_nameProgram, _versionProgram) - # Словарь измененных директорий - self.changeDirs = {} - # Словарь директорий с количесвом файлов шаблонов - self.dictTemplates = {} - # Общее количество шаблонов - self.allTemplates = 0 - # Аттрибуты для функции шаблона ini() - # Первоначальный словарь переменных для ini() - self.prevDictIni = {} - # Текущий словарь переменных для ini() - self.currDictIni = {} - # Время модификации конфигурационного файла для ini() - self.timeIni = -1 - self.uid, self.gid, self.homeDir = self.getDataUser() - # Путь к конфигурационному файлу для ini() - self.pathConfigIni = os.path.join(self.homeDir, ".calculate") - self.fileConfigIni = os.path.join(self.pathConfigIni,"ini.env") - # Словарь времен модификации env файлов - self.timeConfigsIni = {} - - def getDataUser(self): - """Получить информацию о пользователе""" - userName = self.objVar.Get("ur_login") - if not userName: - userName = "root" - import pwd - try: - pwdObj = pwd.getpwnam(userName) - uid = pwdObj.pw_uid - gid = pwdObj.pw_gid - homeDir = pwdObj.pw_dir - except: - print _("Can not found user %s")%str(userName) - cl_base.exit(1) - return uid, gid, homeDir - - - # Преобразование восьмеричного в целое (ввод строка, вывод число) - def __octToInt(self, strOct): - if strOct: - try: - exec("res =" + "0" + strOct) - except: - self.setError (_("Not valid oct value: ") + str(strOct)) - return False - return res - else: - self.setError (_("Empty oct value")) - return False - - def removeDir(self, rmDir): - """Рекурсивное удаление директории - - входной параметр директория - Обязательно должен быть определен метод self.printERROR - """ - if not os.path.exists(rmDir): - self.printERROR(_("Not found remove dir %s") %rmDir) - return False - fileObj = _file() - # Сканируем директорию - scanObjs = fileObj.scanDirs([rmDir]) - for socketRm in scanObjs[0].sockets: - # Удаляем сокеты - if os.path.exists(socketRm): - os.remove(socketRm) - for linkRm in scanObjs[0].links: - # Удаляем ссылки - os.unlink(linkRm[1]) - for fileRm in scanObjs[0].files: - # Удаляем файлы - os.remove(fileRm) - scanObjs[0].dirs.sort(lambda x, y: cmp(len(y), len(x))) - for dirRm in scanObjs[0].dirs: - # Удаляем директории - os.rmdir(dirRm) - if rmDir: - os.rmdir(rmDir) - return True - - - def createDir(self, baseProfDir, profDir, baseDirMv, createDir): - """Создает директорию - - baseDirMv + результат вычитания из profDir baseProfDir - createDir - создаваемая директория - """ - if baseDirMv and not os.access(baseDirMv, os.F_OK): - os.makedirs(baseDirMv) - # Созданные директории - createDirs = [] - baseDir = baseProfDir - if baseProfDir[-1] == "/": - baseDir = baseProfDir[:-1] - # Директория в системе относительно baseDirMv без условий - if baseDirMv: - dirMvNoTerm = createDir.partition(baseDirMv)[2] - else: - dirMvNoTerm = createDir - # директория в системе - dirMv = profDir.partition(baseDir)[2] - if len(dirMv)>1 and dirMv[-1] == "/": - dirMv = dirMv[:-1] - ## директория в системе без условий - #dirMvNoTerm = "/".join(map(lambda x:x.split("?")[0],\ - #dirMv.split("/"))) - listDirMv = dirMv.split("/") - listDirMvNoTerm = dirMvNoTerm.split("/") - if len(listDirMv) != len(listDirMvNoTerm): - self.setError (_("Error in profile") + " :" + profDir) - return False - genIn = listDirMv.__iter__() - genOut = listDirMvNoTerm.__iter__() - inAndOutDirs = map(lambda x: [x,genOut.next()], genIn) - createDirs = [] - createDir = [] - while (len(inAndOutDirs)>1): - tmpDirIn = baseDir+"/".join(map(lambda x:x[0], inAndOutDirs)) - tmpDirOut = baseDirMv + "/".join(map(lambda x:x[1],\ - inAndOutDirs)) - if os.access(tmpDirOut, os.F_OK): - break - else: - createDir.append((tmpDirIn, tmpDirOut)) - inAndOutDirs.pop() - createDir.reverse() - for crDirIn,crDirOut in createDir: - try: - mode,uid,gid = self.getModeFile(crDirIn) - except OSError: - self.setError (_("not access dir:" ) + crDirIn) - return False - createDirs.append(crDirOut) - os.mkdir(crDirOut, mode) - os.chown(crDirOut, uid, gid) - return createDirs - - - def applyVarsProfile(self, textProfile, nameProfile): - """ Заменяет переменные на их значения - """ - resS = self._reVar.search(textProfile) - textProfileTmp = textProfile - while resS: - mark = textProfileTmp[resS.start():resS.end()] - varName = mark[self._deltVarStart:-self._deltVarEnd] - varValue = "" - try: - varValue = str(self.objVar.Get(varName)) - except self.objVar.DataVarsError, e: - print _("error in profile %s")%nameProfile - print e - cl_base.exit(1) - textProfileTmp = textProfileTmp.replace(mark, varValue) - resS = self._reVar.search(textProfileTmp) - return textProfileTmp - - - def applyFuncProfile(self, textProfile, nameProfile, nameSystemFile): - """ Применяет функции к тексту профиля - """ - def equalTerm(term, sNum, sMD, localVars): - """Локальная функция для вычисления выражения""" - terms = sNum.findall(term) - if terms: - strNumers = [] - for n in terms: - strNum = n.strip() - if "*" in strNum or "/" in strNum: - strNum = multAndDiv(strNum,sNum,sMD,localVars) - try: - num = int(strNum) - except: - minus = False - if strNum[:1] == "-": - minus = True - strNum = strNum[1:] - if localVars.has_key(strNum): - try: - num = int(localVars[strNum]) - except: - print _("error in profile %s")%nameProfile - print _("error local var %s not int")\ - %str(strNum) - cl_base.exit(1) - elif self.objVar.exists(strNum): - try: - num = int(self.objVar.Get(strNum)) - except: - print _("error in profile %s")%nameProfile - print _("error var %s not int")%str(strNum) - cl_base.exit(1) - else: - print _("error in profile %s")%nameProfile - print _("error local var %s not defined")\ - %str(strNum) - cl_base.exit(1) - if minus: - num =-num - strNumers.append(num) - return sum(strNumers) - print _("error in profile %s")%nameProfile - print _("error profile term %s, incorrect data")%str(term) - cl_base.exit(1) - - def multAndDiv(term,sNum,sMD,localVars): - """локальная функция для умножения и деления""" - termTmp = term - varsLocal = sMD.findall(term) - for var in varsLocal: - flagVarTxt = True - try: - int(var) - except: - flagVarTxt = False - if flagVarTxt: - continue - varReplace = str(equalTerm(var,sNum,sMD,localVars)) - termTmp = termTmp.replace(var,varReplace) - ret = eval(termTmp) - return ret - - def funcSum(funTxt,resS,localVars,textProfileTmp): - """локальная функция вычисляет первую функцию sum() в профиле""" - terms = funTxt[4:-1].replace(" ","").split(",") - # Название локальной переменной - nameLocVar = terms[0] - if not localVars.has_key(nameLocVar): - localVars[nameLocVar] = 0 - if len(terms) == 2: - if terms[1].strip(): - localVars[nameLocVar] = equalTerm(terms[1],sNum,sMD, - localVars) - replace = str(localVars[nameLocVar]) - else: - replace = "" - textProfileTmp = textProfileTmp[:resS.start()] + replace +\ - textProfileTmp[resS.end():] - elif len(terms) == 3: - if terms[1].strip(): - replaceInt = equalTerm(terms[1],sNum,sMD,localVars) - replace = str(replaceInt) - else: - replace = "" - localVars[nameLocVar] = equalTerm(terms[2], - sNum,sMD,localVars) - textProfileTmp = textProfileTmp[:resS.start()] + replace +\ - textProfileTmp[resS.end():] - else: - print _("error in profile %s")%nameProfile - print _("error profile term %s")%str(funTxt) - cl_base.exit(1) - return textProfileTmp - - - def funcExists(funTxt,resS,textProfileTmp): - """если файл существует читает из файла локальную переменную - - если один параметр - выводит значение локальной переменной - """ - terms = funTxt[7:-1].replace(" ","").split(",") - if len(terms) !=1: - print _("error in profile %s")%nameProfile - print _("error profile term %s")%str(funTxt) - cl_base.exit(1) - fileName = terms[0].strip() - if fileName[0] == "~": - # Получаем директорию пользователя - fileName = os.path.join(self.homeDir, - fileName.partition("/")[2],"")[:-1] - elif fileName[0] != "/": - path = os.path.split(nameSystemFile)[0] - fileName=os.path.join(path,fileName) - replace = "" - if os.path.exists(fileName): - replace = "1" - textProfileTmp = textProfileTmp[:resS.start()] + replace +\ - textProfileTmp[resS.end():] - return textProfileTmp - - def funcLoad(funTxt,resS,textProfileTmp): - """если файл существует читает из файла локальную переменную - - если один параметр - выводит значение локальной переменной - """ - terms = funTxt[5:-1].replace(" ","").split(",") - if not terms[0].strip() or\ - (len(terms)==2 and not terms[1].strip()) or\ - len(terms)>2: - print _("error in profile %s")%nameProfile - print _("error profile term %s")%str(funTxt) - cl_base.exit(1) - if len(terms) == 2: - if not terms[0] in ["ver","num","char","key"]: - print _("error in profile %s")%nameProfile - print _("error profile term %s")%str(funTxt) - print _("first argument function is not 'ver' or 'num' or\ - 'char'") - cl_base.exit(1) - if len(terms) == 1: - fileName = terms[0].strip() - # Если домашняя директория - if fileName[0] == "~": - # Получаем директорию пользователя - fileName = os.path.join(self.homeDir, - fileName.partition("/")[2],"")[:-1] - elif fileName[0] != "/": - path = os.path.split(nameSystemFile)[0] - fileName=os.path.join(path,fileName) - else: - fileName = terms[1].strip() - # Если домашняя директория - if fileName[0] == "~": - # Получаем директорию пользователя - fileName = os.path.join(self.homeDir, - fileName.partition("/")[2],"")[:-1] - elif fileName[1] != "/": - path = os.path.split(nameSystemFile)[0] - fileName=os.path.join(path,fileName) - replace = "" - if os.path.exists(fileName): - FD = open(fileName) - replace = FD.read().strip() - FD.close - if not replace and len(terms) == 2 and terms[0] in ["ver","num"]: - replace = "0" - textProfileTmp = textProfileTmp[:resS.start()] + replace +\ - textProfileTmp[resS.end():] - return textProfileTmp - - def getInstallPkgGentoo(): - """Выдает словарь инсталлированных программ и номеров версий""" - pkgs = [] - def getFilesDir(pkgs, dirname, names): - for nameFile in names: - absNameFile = os.path.join(dirname,nameFile) - if os.path.isdir(absNameFile): - tail = absNameFile.split(self.basePkgDir) - if len(tail)==2: - tail = tail[1].split('/') - if len(tail)==3 and tail[1]!='virtual': - pkgs.append(tail[2]) - return True - os.path.walk(self.basePkgDir,getFilesDir, pkgs) - return sharePkg(pkgs) - - def sharePkg(pkgs): - """Получение имен и номеров версий программ""" - pkgs.sort() - installProg = {} - for pkg in pkgs: - findVer = self.reFindVer.search(pkg) - if findVer: - version = findVer.group() - name = pkg.split(version)[0][:-1] - if name in installProg: - installProg[name].append(version) - else: - installProg[name] = [version] - return installProg - - def pkg(nameProg, installProg): - """Выдает установленные версии по имени программы""" - if nameProg in installProg: - return installProg[nameProg][-1] - else: - return "" - - def funcPkg(funTxt,resS,textProfileTmp): - """локальная функция выдает номер версии программы""" - terms = funTxt[4:-1].replace(" ","") - # Название программы - nameProg = terms - # Замена функции в тексте шаблона - replace = "" - if "/" in nameProg: - if nameProg in self.installProg: - replace = pkg(nameProg, self.installProg) - else: - category, spl, nProg = terms.partition("/") - if not category in self.installCategory: - self.installCategory.append(category) - pathCategory = os.path.join(self.basePkgDir, category) - if os.path.exists(pathCategory): - pkgs = os.listdir(pathCategory) - pkgs = map(lambda x: os.path.join(category,x), - pkgs) - installProg = sharePkg(pkgs) - replace = pkg(nameProg, installProg) - self.installProg.update(installProg) - else: - if not self.flagAllPkgScan: - installProg = getInstallPkgGentoo() - self.installProg.update(installProg) - profile.flagAllPkgScan = True - replace = pkg(nameProg, self.installProg) - textProfileTmp = textProfileTmp[:resS.start()] + replace +\ - textProfileTmp[resS.end():] - return textProfileTmp - - def funcRnd(funTxt,resS,textProfileTmp): - """локальная функция выдает строку случайных символов - - первый аргумент: - 'num' - числа, - 'pas' - цифры и буквы - второй аргумент: - количество символов - """ - terms = funTxt[4:-1].replace(" ","").split(",") - if not terms[0].strip() or\ - (len(terms)==2 and not terms[1].strip()) or\ - len(terms)!=2: - print _("error in profile %s")%nameProfile - print _("error profile term %s")%str(funTxt) - cl_base.exit(1) - fArgvNames = ['num','pas'] - if not terms[0] in fArgvNames: - print _("error in profile %s")%nameProfile - print _("error profile term %s")%str(funTxt) - print _("first argument function is not 'num' or 'pas'") - cl_base.exit(1) - try: - lenStr = int(terms[1]) - except: - print _("error in profile %s")%nameProfile - print _("error profile term %s")%str(funTxt) - print _("two argument function is not number") - cl_base.exit(1) - if terms[0] == fArgvNames[0]: - replace=''.join([random.choice(string.digits)\ - for i in xrange(lenStr)]) - elif terms[0] == fArgvNames[1]: - replace=''.join([random.choice(string.ascii_letters + \ - string.digits) for i in xrange(lenStr)]) - else: - print _("error in profile %s")%nameProfile - print _("error profile term %s")%str(funTxt) - cl_base.exit(1) - textProfileTmp = textProfileTmp[:resS.start()] + replace +\ - textProfileTmp[resS.end():] - return textProfileTmp - - def funcCase(funTxt,resS,textProfileTmp): - """локальная функция выдает переменную в определенном регистре - - первый аргумент: - 'upper' - верхний регистр, - 'lower' - нижний регистр, - 'capitalize' - первая буква в верхнем регистре - второй аргумент: - название переменной - """ - terms = funTxt[5:-1].replace(" ","").split(",") - if not terms[0].strip() or\ - (len(terms)==2 and not terms[1].strip()) or len(terms)!=2: - print _("error in profile %s")%nameProfile - print _("error profile term %s")%str(funTxt) - cl_base.exit(1) - fArgvNames = ['upper','lower','capitalize'] - if not terms[0] in fArgvNames: - print _("error in profile %s")%nameProfile - print _("error profile term %s")%str(funTxt) - print _("first argument function is not 'upper' or 'lower' or\ - 'capitalize'") - cl_base.exit(1) - try: - strValue = str(self.objVar.Get(terms[1])) - except: - print _("error in profile %s")%nameProfile - print _("error var %s not found")%str(terms[1]) - cl_base.exit(1) - replace = "" - strValue = self._toUNICODE(strValue) - if terms[0] == 'upper': - replace = strValue.upper() - elif terms[0] == 'lower': - replace = strValue.lower() - elif terms[0] == 'capitalize': - replace = strValue.capitalize() - if replace: - replace = replace.encode("UTF-8") - textProfileTmp = textProfileTmp[:resS.start()] + replace +\ - textProfileTmp[resS.end():] - return textProfileTmp - - def funcPush(funTxt,resS,localVars,textProfileTmp): - """локальная функция записывает значение переменной - - в стек глобальных переменных - """ - terms = funTxt[5:-1].replace(" ","").split(",") - # Название локальной переменной - nameLocVar = terms[0] - flagFoundVar = False - if nameLocVar in localVars.keys(): - flagFoundVar = True - value = localVars[nameLocVar] - else: - try: - value = self.objVar.Get(nameLocVar) - flagFoundVar = True - except: - pass - if flagFoundVar: - # Если переменная существует - if len(terms) == 1: - self.stackGlobalVars.append(str(value)) - else: - print _("error in profile %s")%nameProfile - print _("error profile term %s")%str(funTxt) - print _("error var %s exists")%str(nameLocVar) - cl_base.exit(1) - else: - # Если переменная не существует - if len(terms) == 1: - print _("error in profile %s")%nameProfile - print _("error profile term %s")%str(funTxt) - print _("error var %s not exists")%str(nameLocVar) - cl_base.exit(1) - elif len(terms) == 2: - value = terms[1].strip() - self.stackGlobalVars.append(str(value)) - localVars[nameLocVar] = value - else: - print _("error in profile %s")%nameProfile - print _("error profile term %s")%str(funTxt) - cl_base.exit(1) - replace = "" - textProfileTmp = textProfileTmp[:resS.start()] + replace +\ - textProfileTmp[resS.end():] - return textProfileTmp - - def funcPop(funTxt,resS,localVars,textProfileTmp): - """локальная функция получает значение - - из стека глобальных переменных и присвает локальной переменной - - """ - terms = funTxt[4:-1].replace(" ","").split(",") - # Название локальной переменной - nameLocVar = terms[0] - if len(terms) == 1: - if self.stackGlobalVars: - localVars[nameLocVar] = self.stackGlobalVars.pop() - else: - print _("error in profile %s")%nameProfile - print _("error profile term %s")%str(funTxt) - print _("error, gloval variables stack is empty") - cl_base.exit(1) - else: - print _("error in profile %s")%nameProfile - print _("error profile term %s")%str(funTxt) - cl_base.exit(1) - replace = "" - textProfileTmp = textProfileTmp[:resS.start()] + replace +\ - textProfileTmp[resS.end():] - return textProfileTmp - - def loadVarsIni(iniFileName): - """ Читает файл fileName - создает и заполняет переменные на основе этого файла - Используеться совместно c funcIni - """ - localVarsIni = {} - # Выходим если есть предыдущие ошибки - if self.getError(): - return False - # получить объект ini файла - config = cl_base.iniParser(iniFileName) - # получаем все секции из конфигурационного файла - allsect = config.getAllSectionNames() - if not allsect: - if self.getError(): - # Очистка ошибки - _error.error = [] - return localVarsIni - # Заполняем переменные для funcIni - for sect in allsect: - sectVars = config.getAreaVars(sect) - for name in sectVars.keys(): - nameVar = "%s.%s"%(sect,name) - valueVar = sectVars[name] - localVarsIni[nameVar] = valueVar - return localVarsIni - - def getTimeFile(fileName): - # Получаем время модификации файла - if fileName in self.timeConfigsIni: - return self.timeConfigsIni[fileName] - return 0 - - def funcIni(funTxt, resS, textProfileTmp): - """локальная функция записывает и считывает значение переменной - - из ini файла ~./calculate/ini.env - """ - # Создаем директорию - if not os.path.exists(self.pathConfigIni): - os.makedirs(self.pathConfigIni) - os.chown(self.pathConfigIni, int(self.uid), int(self.gid)) - termsRaw = funTxt[4:-1].split(",") - flagFirst = True - terms = [] - for term in termsRaw: - if flagFirst: - terms.append(term.replace(" ","")) - flagFirst = False - else: - val = term.strip() - # Флаг (не найдены кавычки) - flagNotFoundQuote = True - for el in ('"',"'"): - if val.startswith(el) and val.endswith(el): - terms.append(val[1:-1]) - flagNotFoundQuote = False - break - if flagNotFoundQuote: - terms.append(val) - # Название локальной переменной - nameLocVar = terms[0] - namesVar = nameLocVar.split(".") - if len(namesVar) == 1: - nameLocVar = "main.%s"%nameLocVar - elif len(namesVar)>2: - print _("error in profile %s")%nameProfile - print _("error profile term %s")%str(funTxt) - cl_base.exit(1) - replace = "" - # Получаем время модификации конфигурационного файла - curTime = getTimeFile(self.fileConfigIni) - if len(terms) == 1: - if self.timeIni != curTime: - # читаем переменные из файла - self.prevDictIni = loadVarsIni(self.fileConfigIni) - self.currDictIni.update(self.prevDictIni) - self.timeIni = getTimeFile(self.fileConfigIni) - if nameLocVar in self.currDictIni.keys(): - replace = self.currDictIni[nameLocVar] - elif len(terms) == 2: - if self.timeIni != curTime: - # читаем переменные из файла - self.prevDictIni = loadVarsIni(self.fileConfigIni) - self.currDictIni.update(self.prevDictIni) - self.timeIni = getTimeFile(self.fileConfigIni) - # Значение локальной переменной - valueLocVar = terms[1] - self.currDictIni[nameLocVar] = valueLocVar - else: - print _("error in profile %s")%nameProfile - print _("error profile term %s")%str(funTxt) - cl_base.exit(1) - textProfileTmp = textProfileTmp[:resS.start()] + replace +\ - textProfileTmp[resS.end():] - return (textProfileTmp) - - # Локальные переменные - localVars = {} - # Регулярное выражние для сложения - sNum = re.compile("\-[^\-\+]+|[^\-\+]+") - # Регулярное выражение для умножениея и деления - sMD = re.compile("[^\-\+\*\/]+") - resS = self._reFunc.search(textProfile) - textProfileTmp = textProfile - flagIniFunc = False - while resS: - mark = textProfileTmp[resS.start():resS.end()] - funTxt = mark[self._deltVarStart:-self._deltVarEnd] - # Функция sum - if funTxt.startswith("sum("): - textProfileTmp = funcSum(funTxt,resS,localVars,textProfileTmp) - resS = self._reFunc.search(textProfileTmp) - # Функция load - elif funTxt.startswith("load("): - textProfileTmp = funcLoad(funTxt,resS,textProfileTmp) - resS = self._reFunc.search(textProfileTmp) - elif funTxt.startswith("pkg("): - textProfileTmp = funcPkg(funTxt,resS,textProfileTmp) - resS = self._reFunc.search(textProfileTmp) - elif funTxt.startswith("rnd("): - textProfileTmp = funcRnd(funTxt,resS,textProfileTmp) - resS = self._reFunc.search(textProfileTmp) - elif funTxt.startswith("case("): - textProfileTmp = funcCase(funTxt,resS,textProfileTmp) - resS = self._reFunc.search(textProfileTmp) - elif funTxt.startswith("pop("): - textProfileTmp = funcPop(funTxt,resS,localVars,textProfileTmp) - resS = self._reFunc.search(textProfileTmp) - elif funTxt.startswith("push("): - textProfileTmp = funcPush(funTxt,resS,localVars,textProfileTmp) - resS = self._reFunc.search(textProfileTmp) - elif funTxt.startswith("ini("): - flagIniFunc = True - textProfileTmp = funcIni(funTxt, resS, textProfileTmp) - resS = self._reFunc.search(textProfileTmp) - elif funTxt.startswith("exists("): - textProfileTmp = funcExists(funTxt, resS, textProfileTmp) - resS = self._reFunc.search(textProfileTmp) - else: - resS = False - if flagIniFunc: - # Очистка файла в случае его ошибочного чтения - if not self.prevDictIni and os.path.exists(self.fileConfigIni): - FD = open(self.fileConfigIni, "r+") - FD.truncate(0) - FD.seek(0) - FD.close() - # Если конф. файл модифицирован шаблоном - curTime = getTimeFile(self.fileConfigIni) - if curTime != self.timeIni: - # Считаем переменные из конф. файла - self.prevDictIni = loadVarsIni(self.fileConfigIni) - self.currDictIni.update(self.prevDictIni) - self.timeIni = curTime - # Если словари переменных не совпадают - if self.prevDictIni != self.currDictIni: - # Запишем переменные в конфигурационный файл - # Создание объекта парсера - config = cl_base.iniParser(self.fileConfigIni) - # секции будущего конфигурационного файла - sects = list(set(map(lambda x: x.split(".")[0],\ - self.currDictIni.keys()))) - # запись переменных в файл - for sect in sects: - dictVar = {} - for varName in self.currDictIni.keys(): - if varName.startswith("%s."%sect): - nameVar = varName.rpartition(".")[2] - valueVar = self.currDictIni[varName] - if valueVar: - dictVar[nameVar] = valueVar - if dictVar: - # Запись переменных в секцию - config.setVar(sect, dictVar) - # читаем переменные из файла - self.prevDictIni = loadVarsIni(self.fileConfigIni) - self.currDictIni.update(self.prevDictIni) - self.timeConfigsIni[self.fileConfigIni] = float(time.time()) - self.timeIni = getTimeFile(self.fileConfigIni) - # Меняем владельца в случае необходимости - if os.path.exists(self.fileConfigIni): - fd = os.open(self.fileConfigIni, os.O_RDONLY) - fst = os.fstat(fd) - uid = fst.st_uid - gid = fst.st_gid - os.close(fd) - if self.uid!=uid or self.gid!=gid: - os.chown(self.fileConfigIni, int(self.uid), int(self.gid)) - return textProfileTmp - - def applyTermsProfile(self, textProfile, nameProfile, nameSystemFile=False): - """ Применяет условия, к условным блокам текста - """ - textTerm = "" - resS = self._reTermBloc.search(textProfile) - textProfileTmp = textProfile - def function(text): - """Функция обработки функций в заголовке""" - return self.applyFuncProfile(text, nameProfile, nameSystemFile) - if nameSystemFile: - while resS: - mark = resS.group(0) - body = resS.group("body") - end = resS.group("end") - parent = resS.group("func") - if not parent: - parent = "" - term = resS.group("rTerm") + parent +\ - resS.group("lTerm") - if self._equalTerm(term, _("content profile not valid: ")+\ - nameProfile, function): - textProfileTmp = textProfileTmp.replace(mark, body+end) - else: - textProfileTmp = textProfileTmp.replace(mark, "") - resS = self._reTermBloc.search(textProfileTmp) - else: - while resS: - mark = resS.group(0) - body = resS.group("body") - end = resS.group("end") - term = resS.group("rTerm") + resS.group("lTerm") - if self._equalTerm(term, _("content profile not valid: ")+\ - nameProfile): - textProfileTmp = textProfileTmp.replace(mark, body+end) - else: - textProfileTmp = textProfileTmp.replace(mark, "") - resS = self._reTermBloc.search(textProfileTmp) - return textProfileTmp - - def getNeedProfile(self, fileProfile): - """Применяем правила к названию файла""" - dirP,fileP = os.path.split(fileProfile) - if fileP: - spFile = fileP.split("?") - realFileName = spFile[0] - if len(spFile)>1: - flagTrue = False - for term in spFile[1:]: - if self._equalTerm(term, _("name profile not valid: ")+\ - fileProfile): - flagTrue = True - break - if flagTrue: - return True - else: - return False - else: - return True - else: - self.setError (_("name profile not valid: ")+ str(fileProfile)) - return False - - def getTitle(self, comment, commentList): - """Выдает заголовок профиля ( версия и.т.д)""" - if comment: - commentFirst = comment - commentInsert = comment - commentLast = comment - flagList = False - # В случае открывающего и закрывающего комментария - if type(comment) == types.TupleType and len(comment) == 2: - commentFirst = comment[0] - commentInsert = "" - commentLast = comment[1] - flagList = True - if flagList: - self._titleBody = commentFirst + "\n" - else: - self._titleBody = commentFirst + self.__titleHead + "\n" - z = 0 - lenCommentList = len(commentList) - 1 - for com in self._titleList: - if lenCommentList < z: - self._titleBody += commentInsert + " " + com + "\n" - else: - self._titleBody += commentInsert + " " + com +\ - " " + commentList[z] + "\n" - z += 1 - if flagList: - self._titleBody += commentLast +"\n" - else: - self._titleBody += commentLast + self.__titleHead + "\n" - return self._titleBody - else: - return "" - - def numberAllProfiles(self, number): - """Количество профилей - - Вызов происходит перед наложением профилей - в момент вызова в number находится количество обрабатываемых файлов - Наследуемая функция - Используется для отображения прогресса при наложениии профилей - """ - return True - - def numberProcessProfiles(self, number): - """Номер текущего обрабатываемого профиля - - Вызов происходит при наложении профиля - в момент вызова в number находится номер обрабатываемого профиля - Наследуемая функция - Используется для отображения прогресса при наложениии профилей - """ - return True - - - def scanDirs(self, profilesDirs, objVar=False): - """Измененный метод сканирования директорий""" - dirs = [] - class dirProf: - def __init__(self): - self.baseDir = False - self.dirs = [] - self.files = [] - self.links = [] - self.sockets = [] - flagError = False - blockDirs = [] - def getFilesDir(dirP, dirname, names): - for nameFile in names: - absNameFile = dirname + "/" + nameFile - findBlock = False - for blDir in blockDirs: - st,mid,end = absNameFile.partition(blDir) - if (not st) and mid and end: - findBlock = True - break - if not findBlock: - if os.path.islink(absNameFile): - dest = absNameFile - src = os.readlink(absNameFile) - dirP.links.append((src,dest)) - elif os.path.isfile(absNameFile): - # Добавляем файлы кроме описаний директорий - if self.profDirNameFile != nameFile: - dirP.files.append(absNameFile) - elif os.path.isdir(absNameFile): - # Обработка условий в названии директории - if self.getNeedProfile(absNameFile): - if self.getError(): - blockDirs.append(absNameFile) - flagError = True - break - dirP.dirs.append(absNameFile) - else: - if self.getError(): - blockDirs.append(absNameFile) - flagError = True - break - blockDirs.append(absNameFile) - elif stat.S_ISSOCK(os.stat(absNameFile)[stat.ST_MODE]): - dirP.sockets.append(absNameFile) - for profileDir in profilesDirs: - if profileDir: - # Обработка условий в названии директории - if self.getNeedProfile(profileDir): - if self.getError(): - flagError = True - break - dirP = dirProf() - dirP.baseDir = profileDir - dirs.append(dirP) - os.path.walk(profileDir, getFilesDir, dirP) - else: - if self.getError(): - flagError = True - break - if flagError: - return [] - return dirs - - - def applyProfiles(self): - """Применяет профили к конфигурационным файлам""" - - def createDictTemplates(path, prefix, dictTemplates): - """Создает словарь {"директория":"кол-во шаблонов" ...} - - и считает общее количество шаблонов - """ - # Количество шаблонов - self.allTemplates += 1 - dirTemplate = os.path.split(path)[0] - while(True): - if dirTemplate in dictTemplates.keys(): - dictTemplates[dirTemplate] += 1 - else: - dictTemplates[dirTemplate] = 1 - if dirTemplate == prefix: - break - dirTemplate = os.path.split(dirTemplate)[0] - return dictTemplates - - if not self.objVar.defined("cl_profile_path"): - self.setError (_("not defined Var: ") + "cl_profile_path") - return False - dirsProfiles = self.objVar.Get("cl_profile_path") - dirsProfiles.sort() - # Словарь измененных директорий - self.changeDirs = {} - # Созданные директории - self.createdDirs = [] - # Примененные файлы - self.filesApply = [] - # Номер применяемого шаблона - self.numberProcessProf = 0 - # Словарь директорий с количеством файлов шаблонов - self.dictTemplates = {} - # Количество шаблонов - self.allTemplates = 0 - # Время доступа к конфигурационному файлу функции шаблона ini() - self.timeIni = -1 - # Первоначальный словарь переменных для ini() - self.prevDictIni = {} - # Текущий словарь переменных для ini() - self.currDictIni = {} - # Словарь времен модификации env файлов - self.timeConfigsIni = {} - if self._servDir: - tmpDirsProfiles = [] - for dirP in dirsProfiles: - dirProf = dirP + self._servDir - if os.access(dirProf, os.F_OK): - # Если директория существует - tmpDirsProfiles.append(dirProf) - dirsProfiles = tmpDirsProfiles - scanObj = processingTemplates() - scanObj.processingFile = lambda x,y: createDictTemplates(x, y,\ - self.dictTemplates) - # Считаем количество шаблонов - for dirTemplate in dirsProfiles: - scanObj.scanningTemplates(dirTemplate, - skipFile=self.filesFilter, - skipDir=self.dirsFilter) - self.numberAllProfiles(self.allTemplates) - for dirTemplate in dirsProfiles: - if self.scanningTemplates(dirTemplate, - skipFile=self.filesFilter, - skipDir=self.dirsFilter) is False: - return False - return (self.createdDirs, self.filesApply) - - - def processingFile(self, path, prefix): - """Обработка в случае профиля файла""" - self.numberProcessProf += 1 - self.numberProcessProfiles(self.numberProcessProf) - # Пропуск шаблонов директорий - if self.profDirNameFile == os.path.split(path)[1]: - return True - if self.getNeedProfile(path): - if self.getError(): - return False - fileProfileChange = path - findChangeDir = False - listD = self.changeDirs.items() - listD.reverse() - for dirChangeIn, dirChangeOut in listD: - st,mid,end = path.partition(dirChangeIn) - if (not st) and mid and end: - findChangeDir = True - break - if findChangeDir: - oldFile = dirChangeOut + end - else: - oldFile = path.partition(prefix)[2] - # файл в системе без условий - oldFile = "/".join(map(lambda x:x.split("?")[0],\ - oldFile.split("/"))) - if not findChangeDir: - oldFile = self._baseDir + oldFile - # Фильтрация профилей по названию файла - if oldFile in self.filesFilter: - return True - listProfTitle = prefix.split("/")[-2:] - profTitle = '"' + "/".join(listProfTitle) + '"' - # Записываем в переменную обрабатываемый файл - self.objVar.Set("cl_pass_file",oldFile) - # Пишем время модификации *.env файлов - if oldFile.endswith(".env"): - self.timeConfigsIni[oldFile] = float(time.time()) - filesApl = self.join(path, oldFile, - (self.programVersion,profTitle)) - if filesApl: - self.filesApply += filesApl - else: - if self.getError(): - #print self.getError() - return False - return True - - def processingDirectory(self, path, prefix): - """Обработка в случае директории если возвращаем None то пропуск дир.""" - # Файл шаблона директории - dirInfoFile = os.path.join(path, self.profDirNameFile) - # Проверяем заголовок - ret = self.__isApplyHeadDir(dirInfoFile) - if not ret: - if self.getError(): - self.setError(_("Incorrect profile: " ) + dirInfoFile) - return False - # Добавление количества файлов в пропущенной директории - if path in self.dictTemplates.keys(): - self.numberProcessProf += self.dictTemplates[path] - return None - newDir = self._baseDir + path.partition(prefix)[2] - newDir = "/".join(map(lambda x:x.split("?")[0],\ - newDir.split("/"))) - # Применяем шаблон - pathDir, objHeadDir = self.__getApplyHeadDir(newDir, - dirInfoFile, - self.changeDirs) - # Фильтрация профилей по названию директории - if pathDir in self.dirsFilter: - # Добавление количества файлов в пропущенной директории - if path in self.dictTemplates.keys(): - self.numberProcessProf += self.dictTemplates[path] - return None - if objHeadDir: - if isinstance(objHeadDir, dirHeader): - if not objHeadDir.headerCorrect: - self.setError(_("Incorrect profile: " ) +\ - dirInfoFile) - self.setError(objHeadDir.errorMessage) - return False - if not objHeadDir.headerTerm: - if objHeadDir.getError(): - self.setError(_("Incorrect profile: " ) +\ - dirInfoFile) - return False - if objHeadDir.params.has_key("name"): - self.changeDirs[path] = pathDir - crDirs = self.createDir(prefix, path, - self._baseDir, pathDir) - if crDirs is False: - return False - self.createdDirs += crDirs - else: - if self.getError(): - self.setError(_("Incorrect profile: " ) +\ - dirInfoFile) - return False - # Добавление количества файлов в пропущенной директории - if path in self.dictTemplates.keys(): - self.numberProcessProf += self.dictTemplates[path] - return None - return True - - def __getGenHeadDir(self, newDir, profileDirFile, changeDirs): - """Определяет название создаваемой директории""" - - def function(text): - """Функция обработки функций в заголовке""" - return self.applyFuncProfile(text, newDir, profileDirFile) - - newDirMv = newDir - findChangeDir = False - #Меняем путь к директории - listD = changeDirs.items() - listD.reverse() - for dirChangeIn, dirChangeOut in listD: - st,mid,end = profileDirFile.partition(dirChangeIn) - if (not st) and mid: - findChangeDir = True - break - if findChangeDir: - pathRel = dirChangeOut - lenPathRel = len(pathRel.split("/")) - lenNewDir = len(newDir.split("/")) - lenEndDir = lenNewDir - lenPathRel - tmpDir = newDir - namesDirs = [] - for i in range(lenEndDir): - namesDirs.append(os.path.split(tmpDir)[1]) - tmpDir = os.path.split(tmpDir)[0] - namesDirs.reverse() - nameDir = "/".join(namesDirs) - newDirMv = os.path.join(pathRel, nameDir) - applyDir = newDirMv - if not os.path.exists(profileDirFile): - return (applyDir, True) - try: - FD = open(profileDirFile) - textProfile = FD.read() - FD.close() - except: - self.setError(_("Error open profile: " ) +\ - profileDirFile) - return (applyDir, False) - objHead = dirHeader(textProfile, self.objVar,function) - if not objHead.headerCorrect: - self.setError(_("Incorrect profile: " ) +\ - profileDirFile) - self.setError(objHead.errorMessage) - return (applyDir, False) - if not objHead.headerTerm: - if objHead.getError(): - self.setError(_("Incorrect profile: " ) +\ - profileDirFile) - return (applyDir, False) - # Изменяем название директории - if objHead.params.has_key("name"): - nameDir = objHead.params['name'] - if "/" in nameDir or nameDir == ".." or nameDir == ".": - self.setError (_("False value 'name' in profile: " ) +\ - profileDirFile) - return (applyDir, False) - if not findChangeDir: - pathRel = os.path.split(os.path.abspath(newDirMv))[0] - # Новый путь к оригинальному файлу - newDirMv = os.path.join(pathRel, nameDir) - applyDir = newDirMv - # При удаленнии директории - if objHead.typeAppend == "remove": - return (applyDir, False) - return (applyDir, objHead) - - def scanProfiles(self, serviceName=False, dirObjs=False): - """Сканирует директории профилей - выводит список файлов""" - if not self.objVar.defined("cl_profile_path"): - self.setError (_("not defined Var: ") + "cl_profile_path") - return False - if not dirObjs: - if serviceName : - self._servDir = serviceName - if self._servDir: - if self._servDir[0] != "/": - self._servDir = "/" + self._servDir - if self._servDir[-1] != "/": - self._servDir += "/" - self._servDir = os.path.split(self._servDir)[0] - dirsProfiles = self.objVar.Get("cl_profile_path") - if self._servDir: - tmpDirsProfiles = [] - for dirP in dirsProfiles: - dirProf = dirP + self._servDir - if os.access(dirProf, os.F_OK): - # Если директория существует - tmpDirsProfiles.append(dirProf) - else: - tmpDirsProfiles.append(False) - dirsProfiles = tmpDirsProfiles - dirObjs = self.scanDirs(dirsProfiles,self.objVar) - #файлы к которым были применены профили - filesApply = [] - # Словарь измененных директорий - changeDirs = {} - dirObjsApply = [] - for dirObj in dirObjs: - dirInfoFile = os.path.join(dirObj.baseDir, self.profDirNameFile) - ret = self.__isApplyHeadDir(dirInfoFile) - if ret: - dirObjsApply.append(dirObj) - else: - if self.getError(): - self.setError(_("Incorrect profile: " ) +\ - dirInfoFile) - return False - for dirObj in dirObjsApply: - # сортируем файлы по названию - if dirObj.files: - dirObj.files.sort() - # сортируем директории по названию - if dirObj.dirs: - dirObj.dirs.sort() - blockDirs = [] - for dirProfile in dirObj.dirs: - newDir = self._baseDir + dirProfile.partition(dirObj.baseDir)[2] - newDir = "/".join(map(lambda x:x.split("?")[0],\ - newDir.split("/"))) - # Проверяем условие на директорию - dirInfoFile = os.path.join(dirProfile, self.profDirNameFile) - pathDir, objHeadDir = self.__getGenHeadDir(newDir, - dirInfoFile, - changeDirs) - # Фильтрация профилей по названию директории - if pathDir in self.dirsFilter: - blockDirs.append(dirProfile) - continue - if objHeadDir: - if isinstance(objHeadDir, dirHeader): - if not objHeadDir.headerCorrect: - self.setError(_("Incorrect profile: " ) +\ - dirInfoFile) - self.setError(objHeadDir.errorMessage) - return False - if not objHeadDir.headerTerm: - if objHeadDir.getError(): - self.setError(_("Incorrect profile: " ) +\ - dirInfoFile) - return False - if objHeadDir.params.has_key("name"): - changeDirs[dirProfile] = pathDir - else: - if self.getError(): - self.setError(_("Incorrect profile: " ) +\ - dirInfoFile) - return False - blockDirs.append(dirProfile) - for fileProfile in dirObj.files: - findBlock = False - for blDir in blockDirs: - st,mid,end = fileProfile.partition(blDir) - if (not st) and mid and end: - findBlock = True - break - if findBlock: - continue - if self.getNeedProfile(fileProfile): - if self.getError(): - #print self.getError() - return False - fileProfileChange = fileProfile - findChangeDir = False - listD = changeDirs.items() - listD.reverse() - for dirChangeIn, dirChangeOut in listD: - st,mid,end = fileProfile.partition(dirChangeIn) - if (not st) and mid and end: - findChangeDir = True - break - if findChangeDir: - oldFile = dirChangeOut + end - else: - oldFile = fileProfile.partition(dirObj.baseDir)[2] - # файл в системе без условий - oldFile = "/".join(map(lambda x:x.split("?")[0],\ - oldFile.split("/"))) - if not findChangeDir: - oldFile = self._baseDir + oldFile - # Фильтрация профилей по названию файла - if oldFile in self.filesFilter: - continue - filesApply.append(oldFile) - else: - if self.getError(): - return False - return filesApply - - def __isApplyHeadDir(self, profileDirFile): - """Будет ли применен профиль корневой директории - - Возвращает True, False - """ - - def function(text): - """Функция обработки функций в заголовке""" - return self.applyFuncProfile(text, "", profileDirFile) - - if not os.path.exists(profileDirFile): - return True - try: - FD = open(profileDirFile) - textProfile = FD.read() - FD.close() - except: - self.setError(_("Error open profile: " ) +\ - profileDirFile) - return False - # Заменяем переменные на их значения - textProfile = self.applyVarsProfile(textProfile, profileDirFile) - # Обработка заголовка - objHead = dirHeader(textProfile, self.objVar,function) - if not objHead.headerCorrect: - self.setError(_("Incorrect profile: " ) +\ - profileDirFile) - self.setError(objHead.errorMessage) - return False - if not objHead.headerTerm: - if objHead.getError(): - self.setError(_("Incorrect profile: " ) +\ - profileDirFile) - return False - - ## Изменяем название директории - #if objHead.params.has_key("name"): - #self.setError (_("Invalid name 'name' in profile: " ) +\ - #profileDirFile) - #return False - - ## Удаляем директорию - #if objHead.typeAppend == "remove": - #self.setError (_("Invalid name 'remove' in profile: " ) +\ - #profileDirFile) - #return False - - ## chmod - изменяем права - #if objHead.params.has_key("chmod"): - #self.setError (_("Invalid name 'chmod' in profile: " ) +\ - #profileDirFile) - #return False - - ## chown - изменяем владельца и группу - #if objHead.params.has_key("chown"): - #self.setError (_("Invalid name 'chown' in profile: " ) +\ - #profileDirFile) - #return False - return True - - def __getApplyHeadDir(self, newDir, profileDirFile, changeDirs): - """Применяет профиль к директории (права, владелец, и.т. д)""" - - def function(text): - """Функция обработки функций в заголовке""" - return self.applyFuncProfile(text, newDir, profileDirFile) - - newDirMv = newDir - findChangeDir = False - #Меняем путь к директории - listD = changeDirs.items() - listD.reverse() - for dirChangeIn, dirChangeOut in listD: - st,mid,end = profileDirFile.partition(dirChangeIn) - if (not st) and mid: - findChangeDir = True - break - if findChangeDir: - pathRel = dirChangeOut - lenPathRel = len(pathRel.split("/")) - lenNewDir = len(newDir.split("/")) - lenEndDir = lenNewDir - lenPathRel - tmpDir = newDir - namesDirs = [] - for i in range(lenEndDir): - namesDirs.append(os.path.split(tmpDir)[1]) - tmpDir = os.path.split(tmpDir)[0] - namesDirs.reverse() - nameDir = "/".join(namesDirs) - newDirMv = os.path.join(pathRel, nameDir) - applyDir = newDirMv - if not os.path.exists(profileDirFile): - return (applyDir, True) - try: - FD = open(profileDirFile) - textProfile = FD.read() - FD.close() - except: - self.setError(_("Error open profile: " ) +\ - profileDirFile) - return (applyDir, False) - # Заменяем переменные на их значения - textProfile = self.applyVarsProfile(textProfile, profileDirFile) - # Обработка заголовка - objHead = dirHeader(textProfile, self.objVar,function) - if not objHead.headerCorrect: - self.setError(_("Incorrect profile: " ) +\ - profileDirFile) - self.setError(objHead.errorMessage) - return (applyDir, False) - if not objHead.headerTerm: - if objHead.getError(): - self.setError(_("Incorrect profile: " ) +\ - profileDirFile) - return (applyDir, False) - - # Изменяем название директории - if objHead.params.has_key("name"): - nameDir = objHead.params['name'] - if "/" in nameDir or nameDir == ".." or nameDir == ".": - self.setError (_("False value 'name' in profile: " ) +\ - profileDirFile) - return (applyDir, False) - if not findChangeDir: - pathRel = os.path.split(os.path.abspath(newDirMv))[0] - # Новый путь к оригинальному файлу - newDirMv = os.path.join(pathRel, nameDir) - applyDir = newDirMv - - # Удаляем директорию - if objHead.typeAppend == "remove": - if os.path.isdir(newDirMv): - # удаляем директорию - try: - self.removeDir(newDirMv) - except: - self.setError(_("Can not delete dir: " ) +\ - newDirMv) - return (applyDir, False) - - # chmod - изменяем права - if objHead.params.has_key("chmod"): - mode = self.__octToInt(objHead.params['chmod']) - if mode: - if not os.path.exists(newDirMv): - os.mkdir(newDirMv, mode) - else: - os.chmod(newDirMv, mode) - else: - self.setError (_("False value 'chmod' in profile: " ) +\ - profileDirFile) - return (applyDir, False) - # chown - изменяем владельца и группу - if objHead.params.has_key("chown"): - owner = objHead.params['chown'] - if owner: - if ":" in owner: - strUid, strGid = owner.split(":") - import pwd - try: - uid = pwd.getpwnam(strUid)[2] - except: - self.setError (_("Not user in this system: ") + strUid) - self.setError (_("False value 'chown' in profile: " )+\ - profileDirFile) - return (applyDir, False) - try: - import grp - gid = grp.getgrnam(strGid)[2] - except: - self.setError (_("Not group in this system: ")+strGid) - self.setError (_("False value 'chown' in profile: " )+\ - profileDirFile) - return (applyDir, False) - - if not os.path.exists(newDirMv): - dirProfile = os.path.split(profileDirFile)[0] - try: - mode,uidTmp,gidTmp = self.getModeFile(dirProfile) - except OSError: - self.setError (_("not access dir:" ) + newDirMv) - return (applyDir, False) - os.mkdir(newDirMv, mode) - os.chown(newDirMv, uid, gid) - else: - self.setError (_("False value 'chown' in profile: " ) +\ - profileDirFile) - return (applyDir, False) - else: - self.setError (_("False value 'chown' in profile: " ) +\ - profileDirFile) - return (applyDir, False) - return (applyDir, objHead) - - def __getApplyHeadProfile(self ,newFile, oldFile, copyFile): - """Применяет заголовок к профилю (права, владелец, и.т. д)""" - - def function(text): - """Функция обработки функций в заголовке""" - return self.applyFuncProfile(text, newFile, oldFile) - - self.closeFiles() - # Файлы в системе к которым были применены профили - applyFiles = [oldFile] - if copyFile: - self.nameFileNew = self.absFileName(newFile) - self.FN = self.openNewFile(self.nameFileNew) - self.newProfile = self.FN.read() - self.closeNewFile() - objHeadNew = fileHeader(self.newProfile, False, - self.getFileType(),objVar=self.objVar, - function=function) - if not objHeadNew.headerCorrect: - self.setError(_("Incorrect profile: " ) +\ - newFile) - self.setError(objHeadNew.errorMessage) - return (applyFiles, False) - if not objHeadNew.headerTerm: - if objHeadNew.getError(): - self.setError(_("Incorrect profile: " ) +\ - newFile) - return (applyFiles, False) - - pathProg = "" - # Путь к оригинальному файлу - pathOldFile = oldFile - # Изменяем путь к оригинальному файлу - if objHeadNew.params.has_key("name"): - nameFile = objHeadNew.params['name'] - if "/" in nameFile or nameFile == ".." or nameFile == ".": - self.setError (_("False value 'name' in profile: " ) + newFile) - return False - pathRel = os.path.split(os.path.abspath(oldFile))[0] - # Новый путь к оригинальному файлу - pathOldFile = os.path.join(pathRel,nameFile) - - # В случае force - if objHeadNew.params.has_key("force"): - if os.path.islink(pathOldFile): - # удаляем ссылку - try: - os.unlink(pathOldFile) - except: - self.setError(_("Can not delete link: " ) +\ - pathOldFile) - return (applyFiles, False) - if os.path.isfile(pathOldFile): - # удаляем файл - try: - os.remove(pathOldFile) - except: - self.setError(_("Can not delete file: " ) +\ - pathOldFile) - return (applyFiles, False) - - # Удаляем оригинальный файл - if objHeadNew.typeAppend == "remove": - if os.path.islink(pathOldFile): - # удаляем ссылку - try: - os.unlink(pathOldFile) - except: - self.setError(_("Can not delete link: " ) +\ - pathOldFile) - if os.path.isfile(pathOldFile): - # удаляем файл - try: - os.remove(pathOldFile) - except: - self.setError(_("Can not delete file: " ) +\ - pathOldFile) - return (applyFiles, False) - - flagSymlink = False - flagForce = False - # Если есть параметр mirror - if objHeadNew.params.has_key("mirror"): - if objHeadNew.params.has_key("link"): - profileFile = objHeadNew.params['link'] - if not os.path.exists(profileFile): - if os.path.exists(pathOldFile): - os.remove(pathOldFile) - return (applyFiles, False) - elif not os.path.exists(pathOldFile): - return (applyFiles, False) - # Если есть указатель на файл профиля (link) - if objHeadNew.params.has_key("link") and\ - not objHeadNew.params.has_key("symbolic"): - profileFile = objHeadNew.params['link'] - foundProfileFile = os.path.exists(profileFile) - if foundProfileFile: - FO = self.openNewFile(profileFile) - buff = FO.read() - FO.close() - if os.path.exists(pathOldFile): - os.remove(pathOldFile) - if foundProfileFile: - fd = os.open(pathOldFile, os.O_CREAT) - os.close(fd) - os.chmod(pathOldFile, self._mode) - os.chown(pathOldFile, self._uid, self._gid) - FON = open (pathOldFile, "r+") - FON.write(buff) - FON.close() - - # Если символическая ссылка - if objHeadNew.params.has_key("symbolic"): - prevOldFile = pathOldFile - pathOldFile = objHeadNew.params['link'] - flagSymlink = True - if not "/" == pathOldFile[0]: - pathLink = os.path.split(os.path.abspath(prevOldFile))[0] - pathProg = os.getcwd() - os.chdir(pathLink) - - # chmod - изменяем права - if objHeadNew.params.has_key("chmod"): - mode = self.__octToInt(objHeadNew.params['chmod']) - if mode: - if not os.path.exists(pathOldFile): - fd = os.open(pathOldFile, os.O_CREAT) - os.close(fd) - os.chmod(pathOldFile, mode) - else: - self.setError (_("False value 'chmod' in profile: " ) +\ - newFile) - return (applyFiles, False) - - # chown - изменяем владельца и группу - if objHeadNew.params.has_key("chown"): - owner = objHeadNew.params['chown'] - if owner: - if ":" in owner: - strUid, strGid = owner.split(":") - import pwd - try: - uid = pwd.getpwnam(strUid)[2] - except: - self.setError (_("Not user in this system: ") + strUid) - self.setError (_("False value 'chown' in profile: " )+\ - newFile) - return (applyFiles, False) - try: - import grp - gid = grp.getgrnam(strGid)[2] - except: - self.setError (_("Not group in this system: ")+strGid) - self.setError (_("False value 'chown' in profile: " )+\ - newFile) - return (applyFiles, False) - - if not os.path.exists(pathOldFile): - FO = self.openNewFile(newFile) - FO.close() - fd = os.open(pathOldFile, os.O_CREAT) - os.close(fd) - os.chmod(pathOldFile, self._mode) - os.chown(pathOldFile, uid, gid) - else: - self.setError (_("False value 'chown' in profile: " ) +\ - newFile) - return (applyFiles, False) - else: - self.setError (_("False value 'chown' in profile: " ) +\ - newFile) - return (applyFiles, False) - - self.openFiles(newFile, pathOldFile) - if flagSymlink: - if os.path.exists(prevOldFile) or os.path.islink(prevOldFile): - if os.path.islink(prevOldFile): - # если ссылка то удаляем её - os.unlink(prevOldFile) - else: - # иначе удаляем файл - os.remove(prevOldFile) - if not "/" == pathOldFile[0]: - os.symlink(pathOldFile, prevOldFile) - applyFiles = [prevOldFile,os.path.join(pathLink,pathOldFile)] - else: - os.symlink(pathOldFile, prevOldFile) - applyFiles = [prevOldFile,pathOldFile] - if not objHeadNew.body.strip(): - return (applyFiles, False) - else: - applyFiles = [pathOldFile] - if pathProg: - os.chdir(pathProg) - # Если файлы заменяются не нужно их обрабатывать дальше - if objHeadNew.typeAppend == "replace" and\ - not objHeadNew.params.has_key("symbolic") and\ - objHeadNew.params.has_key("link"): - return (applyFiles, False) - return (applyFiles, objHeadNew) - - def createNewClass(self, name, bases, attrs={}): - """Создает объект нового класса - - createNewClass(self, name, bases, attrs) - name - имя класса - str, - bases - cписок наследуемых классов - (tuple), - attrs - аттрибуты класса - {dict} - """ - class newMethod: - #Объединяем конфигурации - def join(self, newObj): - if newObj.__class__.__name__ == self.__class__.__name__: - self.docObj.joinDoc(newObj.doc) - # Пост обработка - if 'postXML' in dir(self): - self.postXML() - attrsNew = {} - attrsNew["configName"] = name - if attrs: - for key in attrs.keys(): - attrsNew[key] = attrs[key] - newCl = type(name, bases + (newMethod, object,), attrsNew) - return newCl - - def fileIsUtf(self, fileName): - """Проверяет файл на кодировку UTF-8""" - if os.path.exists(fileName): - FD = open(self.absFileName(fileName)) - newProfile = FD.read() - FD.close() - try: - newProfile.decode("UTF-8") - except: - return False - return True - - def join(self, newFile, oldFile, ListOptTitle): - """Объединения профиля и конф. файла - - join(newFile, oldFile, ListOptTitle) - Объединение профиля newFile и конф. файла oldFile, - ListOptTitle - список строк которые добавятся в заголовок - """ - # Выполняем условия для блока текста а так-же заменяем переменные - self.nameFileNew = self.absFileName(newFile) - self.FN = self.openNewFile(self.nameFileNew) - self.newProfile = self.FN.read() - self.closeNewFile() - copyFile = True - if self.getFileType() != "bin": - # Вычисляем условные блоки - self.newProfile = self.applyTermsProfile(self.newProfile, - newFile, oldFile) - #print "|%s|" %(self.newProfile) - # Заменяем переменные на их значения - self.newProfile = self.applyVarsProfile(self.newProfile, - newFile) - # Вычисляем функции - self.newProfile = self.applyFuncProfile(self.newProfile, - newFile, oldFile) - copyFile = False - filesApply, objHeadNew = self.__getApplyHeadProfile(newFile, oldFile, - copyFile) - if not objHeadNew: - return filesApply - # Флаг - кодировка с бинарными примесями у файла профиля включаем при - # условии текстового файла и кодировки отличной от UTF-8 - flagNotUtf8New = False - # Флаг - кодировка с бинарными примесями у оригинального файла - flagNotUtf8Old = False - if not copyFile: - # проверяем кодировку профиля - if not self.fileIsUtf(newFile): - flagNotUtf8New = True - if not (objHeadNew.params.has_key("link") and\ - objHeadNew.params.has_key("symbolic")): - # проверяем кодировку оригинального файла - if not self.fileIsUtf(oldFile): - flagNotUtf8Old = True - self.newProfile = objHeadNew.body - #if objHeadNew.fileType != "bin": - #self.newProfile = self.applyTermsProfile(self.newProfile, - #newFile) - #self.newProfile = self.applyVarsProfile(self.newProfile) - - # Титл конфигурационного файла - title = "" - if ListOptTitle: - title = self.getTitle(objHeadNew.comment, - ListOptTitle) - title = title.encode("UTF-8") - - objHeadOld = False - if objHeadNew.comment: - objHeadOld = fileHeader(self.oldProfile, objHeadNew.comment) - # Тестирование - #print self.nameFileOld - #print objHeadNew.typeAppend - if objHeadNew.fileType: - # Создаем объект в случае параметра format в заголовке - if (objHeadNew.typeAppend == "replace" or\ - objHeadNew.typeAppend == "before" or\ - objHeadNew.typeAppend == "after") and\ - not (objHeadNew.fileType == "bin" or\ - objHeadNew.fileType == "raw"): - # Преобразовываем бинарные файлы - if flagNotUtf8New: - objTxtCoder = utfBin() - self.newProfile = objTxtCoder.encode(self.newProfile) - try: - exec ("objProfNew=%s(self.newProfile)"%\ - (objHeadNew.fileType)) - except NameError: - #Создаем объект из self.newObjProt с помощью - # метаклассов - if self.newObjProt.has_key(objHeadNew.fileType): - objProfNewCl = self.createNewClass(\ - objHeadNew.fileType, - self.newObjProt[objHeadNew.fileType]) - objProfNew = objProfNewCl(self.newProfile) - else: - self.setError (\ - _("False join profile for type profile: ")\ - + objHeadNew.fileType + " : " +\ - newFile) - return False - - if "xml_" in objHeadNew.fileType: - if objProfNew.getError(): - self.setError (_("False profile: " ) + newFile) - return False - nameRootNode = oldFile.rpartition("/")[2].split(".")[0] - objProfNew.setNameBodyNode(nameRootNode) - # Объект Документ - docObj = objProfNew.docObj - # Удаление комментариев из документа - docObj.removeComment(docObj.getNodeBody()) - # Добавление необходимых переводов строк - docObj.insertBRtoBody(docObj.getNodeBody()) - # Добавление необходимых разделителей между областями - docObj.insertBeforeSepAreas(docObj.getNodeBody()) - # Пост обработка - if 'postXML' in dir(objProfNew): - objProfNew.postXML() - # Получение текстового файла из XML документа - self.newProfile = objProfNew.getConfig().encode("UTF-8") - # Если не UTF-8 производим преобразование - if flagNotUtf8New: - self.newProfile = objTxtCoder.decode(self.newProfile) - # Титл для объединения - if ListOptTitle: - title = self.getTitle(objProfNew._comment, - ListOptTitle) - title = title.encode("UTF-8") - # Замена - if objHeadNew.typeAppend == "replace": - if "xml_" in objHeadNew.fileType: - data = self.newProfile.split("\n") - data.insert(1,title) - self.oldProfile = "\n".join(data) - else: - if objHeadNew.execStr: - self.oldProfile = objHeadNew.execStr+title+\ - self.newProfile - else: - self.oldProfile = title + self.newProfile - self.saveOldFile() - return filesApply - # Впереди - elif objHeadNew.typeAppend == "before": - if "xml_" in objHeadNew.fileType: - self.setError (\ - _("False option append=before in profile %s") %newFile) - return False - if objHeadOld and objHeadOld.body: - self.oldProfile = objHeadOld.body - if self.newProfile[-1] == "\n": - tmpProfile = self.newProfile + self.oldProfile - else: - tmpProfile = self.newProfile + "\n" + self.oldProfile - if objHeadNew.execStr: - self.oldProfile = objHeadNew.execStr + title + tmpProfile - elif objHeadOld.execStr: - self.oldProfile = objHeadOld.execStr + title + tmpProfile - else: - self.oldProfile = title + tmpProfile - - #print self.oldProfile - self.saveOldFile() - return filesApply - # Cзади - elif objHeadNew.typeAppend == "after": - if "xml_" in objHeadNew.fileType: - self.setError (\ - _("False option append=after in profile %s") %newFile) - return False - if objHeadOld and objHeadOld.body: - self.oldProfile = objHeadOld.body - if self.newProfile[-1] == "\n": - tmpProfile = self.oldProfile + self.newProfile - else: - tmpProfile = self.oldProfile + "\n" + self.newProfile - if objHeadNew.execStr: - self.oldProfile = objHeadNew.execStr + title + tmpProfile - elif objHeadOld.execStr: - self.oldProfile = objHeadOld.execStr + title + tmpProfile - else: - self.oldProfile = title + tmpProfile - self.saveOldFile() - return filesApply - # Объединение - elif objHeadNew.typeAppend == "join": - if flagNotUtf8New: - objTxtCoder = utfBin() - self.newProfile = objTxtCoder.encode(self.newProfile) - try: - exec ("objProfNew=%s(self.newProfile)"%\ - (objHeadNew.fileType)) - except NameError: - #Создаем объект из self.newObjProt с помощью - # метаклассов - if self.newObjProt.has_key(objHeadNew.fileType): - objProfNewCl = self.createNewClass(\ - objHeadNew.fileType, - self.newObjProt[objHeadNew.fileType]) - objProfNew = objProfNewCl(self.newProfile) - else: - self.setError (\ - _("False join profile for type profile: ")\ - + objHeadNew.fileType + " : " +\ - newFile) - return False - if "xml_" in objHeadNew.fileType: - if objProfNew.getError(): - self.setError (_("False profile: " ) + newFile) - return False - nameRootNode = oldFile.rpartition("/")[2].split(".")[0] - objProfNew.setNameBodyNode(nameRootNode) - # Титл для объединения - if ListOptTitle: - title = self.getTitle(objProfNew._comment, - ListOptTitle) - title = title.encode("UTF-8") - - # В случае пустого конфигурационного файла - reNoClean = re.compile("[^\s]",re.M) - if not self.oldProfile or\ - not reNoClean.search(self.oldProfile): - self.oldProfile = "" - #if objHeadNew.execStr: - #self.oldProfile = objHeadNew.execStr + \ - #title + objProfNew.getConfig().encode("UTF-8") - #else: - #self.oldProfile = title +\ - #objProfNew.getConfig().encode("UTF-8") - #self.saveOldFile() - #return True - - objHeadOld = fileHeader(self.oldProfile, objProfNew._comment) - if objHeadOld.body: - self.oldProfile = objHeadOld.body - else: - self.oldProfile = "" - if flagNotUtf8Old: - objTxtCoder = utfBin() - self.oldProfile = objTxtCoder.encode(self.oldProfile) - if self.newObjProt.has_key(objHeadNew.fileType): - objProfOldCl = self.createNewClass(\ - objHeadNew.fileType, - self.newObjProt[objHeadNew.fileType]) - objProfOld = objProfOldCl(self.oldProfile) - else: - exec ("objProfOld=%s(self.oldProfile)"%\ - (objHeadNew.fileType)) - if "xml_" in objHeadNew.fileType: - if objProfOld.getError(): - self.setError (_("False profile: " ) + oldFile) - return False - nameRootNode = oldFile.rpartition("/")[2].split(".")[0] - objProfOld.setNameBodyNode(nameRootNode) - - #print "#%s#" %(objProfOld.docObj.body.toprettyxml()) - #print "#%s#" %(objProfNew.docObj.body.toprettyxml()) - objProfOld.join(objProfNew) - #print objProfOld.doc.toprettyxml() - #print objProfNew.doc.toprettyxml() - if "xml_" in objHeadNew.fileType: - if objProfOld.getError(): - self.setError (_("False profile: " ) + newFile) - return False - data = \ - objProfOld.getConfig().encode("UTF-8").split("\n") - data.insert(1,title) - self.oldProfile = "\n".join(data) - else: - if objHeadNew.execStr: - self.oldProfile = objHeadNew.execStr + title +\ - objProfOld.getConfig().encode("UTF-8") - elif objHeadOld.execStr: - self.oldProfile = objHeadOld.execStr + title +\ - objProfOld.getConfig().encode("UTF-8") - else: - self.oldProfile = title +\ - objProfOld.getConfig().encode("UTF-8") - # Декодируем если кодировка не UTF-8 - if flagNotUtf8New or flagNotUtf8Old: - self.newProfile = objTxtCoder.decode(self.newProfile) - self.oldProfile = objTxtCoder.decode(self.oldProfile) - self.saveOldFile() - return filesApply - else: - self.setError (_("False (type append) profile: " ) +\ - objHeadNew.typeAppend) - return False - else: - self.setError (_("Type profile not found: ") + newFile) - return False - return filesApply - -class samba(objShare): - """Класс для обработки конфигурационного файла типа samba - - """ - _comment = "#" - configName = "samba" - configVersion = "0.1" - reHeader = re.compile("^[\t ]*\[[^\[\]]+\].*\n",re.M) - reBody = re.compile(".+",re.M|re.S) - reComment = re.compile("\s*%s.*|\s*;.*"%(_comment)) - reSeparator = re.compile("\s*=\s*") - sepFields = "\n" - reSepFields = re.compile(sepFields) - - def __init__(self,text): - self.text = text - self.blocTextObj = blocText() - self._splitToFields = self.splitToFields - # Объект документ - self.docObj = self._textToXML() - # XML документ - self.doc = self.docObj.doc - - def postXML(self): - """Последующая постобработка XML""" - # Для добавления перевода строки между областями если его нет - #print self.docObj.body.toprettyxml() - xmlAreas = xpath.Evaluate("child::area", self.docObj.body) - for xmlArea in xmlAreas: - if xmlArea.previousSibling and\ - self.docObj.getTypeField(xmlArea.previousSibling) == "br": - continue - firstArea = False - xmlFields = xpath.Evaluate("child::field", xmlArea) - if not (xmlFields and\ - (self.docObj.getTypeField(xmlFields[-1]) == "br" or\ - self.docObj.getTypeField(xmlFields[-1]) == "comment")): - if xmlArea.nextSibling: - parentNode = xmlArea.parentNode - nextNode = xmlArea.nextSibling - parentNode.insertBefore(self.docObj.createField("br", - [],"",[], - False,False), - nextNode) - # Удаление лишних переводов строк - childNodes = self.docObj.getFieldsArea(self.docObj.body) - lenBr = 0 - removeBrNodes = [] - for node in childNodes: - if node.tagName == "field" and\ - self.docObj.getTypeField(node) == "br": - lenBr += 1 - if lenBr > 2: - removeBrNodes.append(node) - else: - lenBr = 0 - # Удаление - for rmNode in removeBrNodes: - self.docObj.body.removeChild(rmNode) - - - def join(self, sambaObj): - """Объединяем конфигурации""" - if isinstance(sambaObj, samba): - self.docObj.joinDoc(sambaObj.doc) - self.postXML() - - def setDataField(self, txtLines, endtxtLines): - """Создаем список объектов с переменными""" - class fieldData: - def __init__(self): - self.name = False - self.value = False - self.comment = False - self.br = False - fields = [] - field = fieldData() - z = 0 - for k in txtLines: - textLine = k + endtxtLines[z] - z += 1 - findComment = self.reComment.search(textLine) - if not textLine.strip(): - field.br = textLine - fields.append(field) - field = fieldData() - elif findComment: - field.comment = textLine - fields.append(field) - field = fieldData() - else: - pars = textLine.strip() - nameValue = self.reSeparator.split(pars) - if len(nameValue) > 2: - valueList = nameValue[1:] - nameValue =[nameValue[0],"=".join(valueList)] - if len(nameValue) == 2: - name = nameValue[0] - value = nameValue[1].replace(self.sepFields,"") - field.name = name.replace(" ","").replace("\t","") - field.value = value - field.br = textLine - fields.append(field) - field = fieldData() - return fields - - - def splitCleanBloc(self, txtBloc): - """Делим блок на две части (переменные, пустые строки в конце)""" - txtLines = txtBloc.split("\n") - firstBloc = [] - nextBloc = [] - txtLines.reverse() - z = 0 - for txtLine in txtLines: - if not txtLine.strip(): - nextBloc.append(txtLine) - else: - break - z += 1 - txtLines.reverse() - firstBloc = txtLines[:-z] - nextBloc.reverse() - if nextBloc: - firstBloc.append("") - if nextBloc and "\n".join(nextBloc): - return ("\n".join(firstBloc), "\n".join(nextBloc)) - else: - return False - - def getFullAreas(self, blocs): - """Делит текст на области, (Заголовок, тело) - - Возвращает два списка: заголовки, тела - """ - headsAreas = [] - bodyAreas = [] - if not blocs: - return [] - lenBlocs = len(blocs[0]) - for i in range(lenBlocs): - txtBloc = blocs[1][i] - clean = self.splitCleanBloc(txtBloc) - if clean: - headsAreas.append(blocs[0][i]) - bodyAreas.append(clean[0]) - headsAreas.append("") - bodyAreas.append(clean[1]) - else: - headsAreas.append(blocs[0][i]) - bodyAreas.append(blocs[1][i]) - return (headsAreas, bodyAreas) - - def createTxtConfig(self, strHeader, dictVar): - """Cоздает область с заголовком - - создает текст конфигурационного файла в формате samba из - заголовка (строка) и словаря переменных - """ - if not strHeader: - return "" - outTxt = "[" + strHeader + "]\n" - for key in dictVar.keys(): - outTxt += "%s = %s\n" %(key,dictVar[key]) - return outTxt - - def _textToXML(self): - """Преобразует текст в XML""" - blTmp = self.blocTextObj.findBloc(self.text,self.reHeader,self.reBody) - blocs = self.getFullAreas(blTmp) - headers = [] - startHeaders = [] - finHeaders = [] - docObj = xmlDoc() - docObj.createDoc(self.configName, self.configVersion) - rootNode = docObj.getNodeBody() - # Если пустой текст то создаем пустой документ - if not blocs: - return docObj - - for h in blocs[0]: - listfinH = h.split("]") - finH = listfinH[0] - if "[" in finH: - startHeaders.append(finH + "]") - else: - startHeaders.append(finH) - if len(listfinH) == 2: - finHeaders.append(listfinH[1]) - else: - finHeaders.append("") - headers.append(finH.replace("[","").replace("]","").strip()) - bodys = blocs[1] - - z = 0 - for h in headers: - if not bodys[z]: - z += 1 - continue - areaAction = False - if h: - if h[0] == "!": - docObj.createCaption(h[1:], [startHeaders[z],""]) - areaAction = "drop" - elif h[0] == "-": - docObj.createCaption(h[1:], [startHeaders[z],""]) - areaAction = "replace" - else: - docObj.createCaption(h, [startHeaders[z],""]) - else: - docObj.createCaption(h, [startHeaders[z],""]) - - if "\n" in blocs[0][z]: - if self.reComment.search(finHeaders[z]): - docObj.createField('comment', [finHeaders[z]]) - elif not finHeaders[z].strip() and\ - finHeaders[z].replace("\n",""): - docObj.createField('br', - [finHeaders[z].replace("\n","")]) - else: - docObj.createField('br') - fields = self._splitToFields(bodys[z]) - for f in fields: - if f.name != False and f.value!=False and f.br!=False: - # Обработка условий для samba - if f.name[0] == "!" or f.name[0] == "-" or\ - f.name[0] == "+": - qns = self.removeSymbolTerm(f.br) - xmlField = docObj.createField("var", - [qns], - f.name[1:], [f.value]) - if f.name[0] == "!": - # Удаляемое в дальнейшем поле - docObj.setActionField(xmlField, "drop") - else: - docObj.createField("var",[f.br.replace("\n","")], - f.name, [f.value]) - docObj.createField('br') - elif f.comment != False: - docObj.createField('comment', [f.comment]) - elif f.br != False: - docObj.createField('br', [f.br.replace("\n","")]) - if h.strip(): - area = docObj.createArea() - if areaAction: - docObj.setActionArea(area, areaAction) - rootNode.appendChild(area) - else: - fieldsNodes = docObj.tmpFields.getFields() - for fieldNode in fieldsNodes: - rootNode.appendChild(fieldNode) - docObj.clearTmpFields() - z += 1 - #print docObj.doc.toprettyxml() - return docObj - -class compiz(samba): - """Класс для обработки конфигурационного файла типа compiz - - """ - _comment = "#" - configName = "compiz" - configVersion = "0.1" - reHeader = re.compile("^[\t ]*\[[^\[\]]+\].*\n",re.M) - reBody = re.compile(".+",re.M|re.S) - reComment = re.compile("\s*%s.*"%(_comment)) - reSeparator = re.compile("\s*=\s*") - sepFields = "\n" - reSepFields = re.compile(sepFields) - - def __init__(self,text): - samba.__init__(self,text) - - def join(self, compizObj): - """Объединяем конфигурации""" - if isinstance(compizObj, compiz): - self.docObj.joinDoc(compizObj.doc) - self.postXML() - -class bind(objShare): - """Класс для обработки конфигурационного файла типа bind - - """ - _comment = "//" - configName = "bind" - configVersion = "0.1" - __openArea = "{" - __closeArea = "[ \t]*\}[ \t]*;[ \t]*" - sepFields = ";" - reOpen = re.compile(__openArea) - reClose = re.compile(__closeArea) - reCloseArea = re.compile(__closeArea + "\s*\Z") - reComment = re.compile("[ \t]+%s|^%s|(?<=;)%s"%(_comment,_comment,_comment)) - reSepFields = re.compile(sepFields) - reSeparator = re.compile("[ \t]+") - - def __init__(self,text): - self.text = text - self.blocTextObj = blocText() - # Объект документ - self.docObj = self.textToXML() - # Создаем поля-массивы - self.docObj.postParserList() - # XML документ - self.doc = self.docObj.doc - - # Делим область на составные части - def findOpenClose(self, text, reOpen, reClose, reComment): - """Делит область на составные части - - начальный текстовый блок, - открывающий блок, - блок-тело, - закрывающий блок - """ - firstBloc = "" - startBloc = "" - bodyBloc = "" - endBloc = "" - textLines = text.splitlines() - findOpen = False - if textLines: - findOpen = reOpen.search(textLines[0]) - openBl = reOpen.search(text) - if findOpen and reComment.split(text)[0].strip(): - blocA = text[openBl.end():] - firstBloc = text[:openBl.start()] - startBloc = text[openBl.start():openBl.end()] - closeBl = reClose.search(blocA) - endBloc = blocA[closeBl.start():closeBl.end()] - bodyBloc = blocA[:closeBl.start()] - return (firstBloc, startBloc, bodyBloc, endBloc) - else: - return (firstBloc, startBloc, text, endBloc) - - - # Делим текст на области включая вложенные (areas массив областей) - def splitToAllArea(self, text, areas, reOpen, reClose, reCloseArea, - reComment, reSepFields): - """Делит текст на области включая вложенные - - возвращает список объектов областей (переменная areas) - """ - class area: - def __init__(self): - self.header = False - self.start = False - self.fields = [] - self.end = False - - blocs = self.blocTextObj.splitTxtToBloc(text,reOpen,reClose, - reComment,reSepFields) - for i in blocs: - areaA = area() - first,start,body,end = self.findOpenClose(i, reOpen, reCloseArea, - reComment) - areaA.header = first.replace(" ","").replace("\t","") - areaA.start = first + start - areaA.end = end - - if areaA.end: - blocsA = self.blocTextObj.splitTxtToBloc(body,reOpen,reClose, - reComment,reSepFields) - if blocsA and blocsA[0] == body: - areaA.fields.append(body) - areas.append(areaA) - else: - for ar in blocsA: - self.splitToAllArea(ar, areaA.fields, reOpen, - reClose, - reCloseArea, reComment, - reSepFields) - areas.append(areaA) - else: - areaA.fields.append(body) - areas.append(areaA) - return areas - - - def setDataField(self, txtLines, endtxtLines): - """Создаем список объектов с переменными""" - class fieldData: - def __init__(self): - self.name = False - self.value = False - self.comment = False - self.br = False - fields = [] - field = fieldData() - z = 0 - for k in txtLines: - textLine = k + endtxtLines[z] - z += 1 - findComment = self.reComment.search(textLine) - if not textLine.strip(): - field.br = textLine - fields.append(field) - field = fieldData() - elif findComment: - field.comment = textLine - fields.append(field) - field = fieldData() - else: - pars = textLine.strip() - nameValue = self.reSeparator.split(pars) - if len (nameValue) == 1: - field.name = "" - field.value = textLine.replace(self.sepFields,"") - field.br = textLine - fields.append(field) - field = fieldData() - - if len(nameValue) > 2: - valueList = nameValue[1:] - nameValue =[nameValue[0]," ".join(valueList).replace(\ - self.sepFields,"")] - if len(nameValue) == 2: - name = nameValue[0] - value = nameValue[1].replace(self.sepFields,"") - field.name = name.replace(" ","").replace("\t","") - field.value = value - field.br = textLine - fields.append(field) - field = fieldData() - return fields - - def createCaptionTerm(self, header, start, end, docObj): - """Создание пустой области с заголовком - - при создании области проверяется первый символ заголовка - и добавляется тег action - "!" - drop - "-" - replace - """ - areaAction = False - if header: - if header[0] == "!": - docObj.createCaption(header[1:], [start, - end.replace("\n","")]) - areaAction = "drop" - elif header[0] == "-": - docObj.createCaption(header[1:], [start, - end.replace("\n","")]) - areaAction = "replace" - else: - docObj.createCaption(header, [start, - end.replace("\n","")]) - else: - docObj.createCaption(header, [start, - end.replace("\n","")]) - - areaXML = docObj.createArea() - if areaAction: - docObj.setActionArea(areaXML, areaAction) - return areaXML - - def createXML(self, areas, rootNode, docObj): - """Создаем из массивов областей XML""" - for i in areas: - if str(i.__class__.__name__) == "area": - if i.header and i.start: - areaXML = self.createCaptionTerm(i.header, i.start, - i.end.replace("\n",""), - docObj) - else: - areaXML = rootNode - for f in i.fields: - if str(f.__class__.__name__) == "area": - if f.header and f.start: - areaXMLChild = self.createCaptionTerm(f.header, - f.start, - f.end.replace("\n",""), - docObj) - - self.createXML(f.fields, areaXMLChild, docObj) - - areaXML.appendChild(areaXMLChild) - else: - self.createXML(f.fields, areaXML, docObj) - if "\n" in f.end: - fieldXMLBr = docObj.createField("br",[], - "",[], - False, False) - areaXML.appendChild(fieldXMLBr) - else: - if not f: - continue - fields = self.splitToFields(f) - for field in fields: - if field.name != False: - fieldXML = self.createFieldTerm(field.name, - field.value, - field.br, docObj) - areaXML.appendChild(fieldXML) - if field.br[-1] == "\n": - fieldXMLBr = docObj.createField("br",[], - "",[], - False, False) - areaXML.appendChild(fieldXMLBr) - elif field.comment != False: - fieldXML = docObj.createField("comment", - [field.comment], - "", [], - False, False) - areaXML.appendChild(fieldXML) - elif field.br != False: - brText = field.br.replace("\n","") - if brText: - fieldXML = docObj.createField('br', - [brText], - "", [], - False, False) - else: - fieldXML = docObj.createField('br', - [], - "", [], - False, False) - areaXML.appendChild(fieldXML) - - if i.header and i.start: - rootNode.appendChild(areaXML) - if "\n" in i.end: - fieldXMLBr = docObj.createField("br",[], - "",[], - False, False) - rootNode.appendChild(fieldXMLBr) - - else: - fields = self.splitToFields(i) - for field in fields: - if field.name != False: - fieldXML = self.createFieldTerm(field.name, - field.value, - field.br, docObj) - rootNode.appendChild(fieldXML) - if field.br[-1] == "\n": - fieldXMLBr = docObj.createField("br",[],"", [], - False, False) - rootNode.appendChild(fieldXMLBr) - elif field.comment != False: - fieldXML = docObj.createField("comment", - [field.comment], - "", [], - False, False) - rootNode.appendChild(fieldXML) - elif field.br != False: - brText = field.br.replace("\n","") - if brText: - fieldXML = docObj.createField('br', [brText],"",[], - False, False) - else: - fieldXML = docObj.createField('br', [], "", [], - False, False) - rootNode.appendChild(fieldXML) - #rootNode.appendChild(areaXML) - - def textToXML(self): - """Преобразуем текст в XML""" - areas = [] - if self.text.strip(): - self.splitToAllArea(self.text, areas, self.reOpen, self.reClose, - self.reCloseArea,self.reComment,self.reSepFields) - docObj = xmlDoc() - # Создание объекта документ c пустым разделителем между полями - docObj.createDoc(self.configName, self.configVersion) - if not areas: - return docObj - self.createXML(areas, docObj.getNodeBody(), docObj) - return docObj - - - def join(self, bindObj): - """Объединяем конфигурации""" - if isinstance(bindObj, bind): - self.docObj.joinDoc(bindObj.doc) - -class apache(bind): - """Класс для обработки конфигурационного файла типа apache - - """ - _comment = "#" - configName = "apache" - configVersion = "0.1" - __headerArea = "[^\<\> \t]+[ \t]+[^\<\> \t]+" - __openArea = "[ \t]*\<%s\>"%(__headerArea) - __closeArea = "[ \t]*\<\/[^\<\>]+\>" - sepFields = "\n" - reOpen = re.compile(__openArea) - reClose = re.compile(__closeArea) - reCloseArea = re.compile(__closeArea + "\s*\Z") - reComment = re.compile("[ \t]*%s"%(_comment)) - reSepFields = re.compile(sepFields) - reSeparator = re.compile("[ \t]+") - reHeader = re.compile(__headerArea) - - def __init__(self,text): - self.text = text - self.blocTextObj = blocText() - # Объект документ - self.docObj = self.textToXML() - # Создаем поля-массивы - self.docObj.postParserList() - # Создаем поля разделенные массивы - self.docObj.postParserListSeplist(self.docObj.body) - # XML документ - self.doc = self.docObj.doc - - def postXML(self): - """Последующая постобработка XML""" - # Для добавления перевода строки перед закрывающим тегом - # конфигурационного файла - xmlFields = xpath.Evaluate("child::fields", self.docObj.body) - if not (xmlFields and\ - self.docObj.getTypeField(xmlFields[-1]) == "br"): - self.docObj.body.appendChild(self.docObj.createField("br", - [],"",[], - False,False)) - xmlAreas = xpath.Evaluate("child::area", self.docObj.body) - for xmlArea in xmlAreas: - xmlFields = xpath.Evaluate("child::field", xmlArea) - if not (xmlFields and\ - self.docObj.getTypeField(xmlFields[-1]) == "br"): - xmlArea.appendChild(self.docObj.createField("br", - [],"",[], - False,False)) - - def join(self, apacheObj): - """Объединяем конфигурации""" - if isinstance(apacheObj, apache): - #print self.docObj.doc.toprettyxml() - self.docObj.joinDoc(apacheObj.doc) - self.postXML() - - # Делим область на составные части - def findOpenClose(self, text, reOpen, reClose, reComment, reHeader): - """Делит область на составные части - - начальный текстовый блок, - открывающий блок, - блок-тело, - закрывающий блок - """ - firstBloc = "" - startBloc = "" - bodyBloc = "" - endBloc = "" - textLines = text.splitlines() - findOpen = False - if textLines: - findOpen = reOpen.search(textLines[0]) - openBl = reOpen.search(text) - if findOpen and reComment.split(text)[0].strip(): - blocA = text[openBl.end():] - firstBloc = "" - startBloc = text[openBl.start():openBl.end()] - headBl = reHeader.search(startBloc) - if headBl: - firstBloc = headBl.group(0) - closeBl = reClose.search(blocA) - endBloc = blocA[closeBl.start():closeBl.end()] - bodyBloc = blocA[:closeBl.start()] - return (firstBloc, startBloc, bodyBloc, endBloc) - else: - return (firstBloc, startBloc, text, endBloc) - - # Делим текст на области включая вложенные (areas массив областей) - def splitToAllArea(self, text, areas, reOpen, reClose, reCloseArea, - reComment, reSepFields, reHeader): - """Делит текст на области включая вложенные - - возвращает список объектов областей (переменная areas) - """ - class area: - def __init__(self): - self.header = False - self.start = False - self.fields = [] - self.end = False - - blocs = self.blocTextObj.splitTxtToBloc(text,reOpen,reClose, - reComment,reSepFields) - for i in blocs: - areaA = area() - first,start,body,end = self.findOpenClose(i, reOpen, reCloseArea, - reComment, reHeader) - areaA.header = first.replace(" ","").replace("\t","") - areaA.start = start - areaA.end = end - - if areaA.end: - blocsA = self.blocTextObj.splitTxtToBloc(body,reOpen,reClose, - reComment,reSepFields) - if blocsA and blocsA[0] == body: - areaA.fields.append(body) - areas.append(areaA) - else: - for ar in blocsA: - self.splitToAllArea(ar, areaA.fields, reOpen, - reClose, - reCloseArea, reComment, - reSepFields, reHeader) - areas.append(areaA) - else: - areaA.fields.append(body) - areas.append(areaA) - - - def setDataField(self, txtLines, endtxtLines): - """Создаем список объектов с переменными""" - class fieldData: - def __init__(self): - self.name = False - self.value = False - self.comment = False - self.br = False - fields = [] - field = fieldData() - z = 0 - for k in txtLines: - textLine = k + endtxtLines[z] - #print "#"+brBloc[z]+"#" - z += 1 - findComment = self.reComment.search(textLine) - if not textLine.strip(): - field.br = textLine - fields.append(field) - field = fieldData() - elif findComment: - field.comment = textLine - fields.append(field) - field = fieldData() - else: - pars = textLine.strip() - nameValue = self.reSeparator.split(pars) - if len (nameValue) == 1: - field.name = "" - field.value = textLine.replace(self.sepFields,"") - field.br = textLine - fields.append(field) - field = fieldData() - - if len(nameValue) == 3: - valueList = nameValue[2:] - nameValue =["".join(nameValue[:2])," ".join(valueList)] - - if len(nameValue) > 3: - valueList = nameValue[1:] - nameValue =[nameValue[0]," ".join(valueList).replace(\ - self.sepFields,"")] - if len(nameValue) == 2: - name = nameValue[0] - value = nameValue[1].replace(self.sepFields,"") - field.name = name.replace(" ","").replace("\t","") - field.value = value - field.br = textLine - fields.append(field) - field = fieldData() - return fields - - - def textToXML(self): - """Преобразуем тект в XML""" - areas = [] - self.splitToAllArea(self.text, areas, self.reOpen, self.reClose, - self.reCloseArea,self.reComment,self.reSepFields, - self.reHeader) - docObj = xmlDoc() - - # Создание объекта документ c пустым разделителем между полями - docObj.createDoc(self.configName, self.configVersion) - if not areas: - return docObj - self.createXML(areas, docObj.getNodeBody(), docObj) - return docObj - -class postfix(apache): - """Класс для обработки конфигурационного файла типа postfix - - """ - _comment = "#" - configName = "postfix" - configVersion = "0.1" - sepFields = "\n" - reComment = re.compile("[ \t]*%s"%(_comment)) - reSepFields = re.compile(sepFields) - # разделитель названия и значения переменной - reSeparator = re.compile("\s*=\s*") - def __init__(self,text): - self.text = text - # Объект документ - self.docObj = self.textToXML() - # Создаем поля разделенные массивы - self.docObj.postParserListSeplist(self.docObj.body) - # XML документ - self.doc = self.docObj.doc - - def join(self, postfixObj): - """Объединяем конфигурации""" - if isinstance(postfixObj, postfix): - self.docObj.joinDoc(postfixObj.doc) - - def textToXML(self): - """Преобразуем текст в XML""" - class area: - def __init__(self): - self.header = False - self.start = False - self.fields = [] - self.end = False - areas = [] - oneArea = area() - oneArea.header = "" - oneArea.start = "" - oneArea.fields = [self.text] - oneArea.end = "" - areas.append(oneArea) - docObj = xmlDoc() - # Создание объекта документ c пустым разделителем между полями - docObj.createDoc(self.configName, self.configVersion) - if not areas: - return docObj - self.createXML(areas, docObj.getNodeBody(), docObj) - return docObj - - - def setDataField(self, txtLines, endtxtLines): - """Cоздаем список объектов с переменными""" - class fieldData: - def __init__(self): - self.name = False - self.value = False - self.comment = False - self.br = False - fields = [] - field = fieldData() - z = 0 - for k in txtLines: - textLine = k + endtxtLines[z] - #print "#"+brBloc[z]+"#" - z += 1 - findComment = self.reComment.search(textLine) - if not textLine.strip(): - field.br = textLine - fields.append(field) - field = fieldData() - elif findComment: - field.comment = textLine - fields.append(field) - field = fieldData() - else: - pars = textLine.strip() - nameValue = self.reSeparator.split(pars) - if len (nameValue) == 1: - field.name = "" - field.value = textLine.replace(self.sepFields,"") - field.br = textLine - fields.append(field) - field = fieldData() - - if len(nameValue) > 2: - valueList = nameValue[1:] - nameValue =[nameValue[0],"=".join(valueList).replace(\ - self.sepFields,"")] - if len(nameValue) == 2: - name = nameValue[0] - value = nameValue[1].replace(self.sepFields,"") - field.name = name.replace(" ","").replace("\t","") - field.value = value - field.br = textLine - fields.append(field) - field = fieldData() - return fields - -class ldap(samba): - """Класс для обработки конфигурационного файла типа ldap - - """ - _comment = "#" - configName = "ldap" - configVersion = "0.1" - # Регулярное выражение для заголовка области - reHeader = re.compile("^[\t ]*(access|syncrepl)[^\n]+\n?") - # Регулярное выражения для области - reArea = re.compile("([\t ]*(access|syncrepl)[^\n]+\ -\n([\t ]+[^\n]+\n?)+)",re.M|re.S) - reComment = re.compile("\s*%s.*"%(_comment)) - # разделитель между переменной и значением переменной - reSeparator = re.compile("\s+|\s*=\s*") - # разделитель полей - sepFields = "\n" - # регулярное выражение для разделителя полей - reSepFields = re.compile(sepFields) - - def __init__(self,text): - self.text = text - self.blocTextObj = blocText() - self._splitToFields = self.splitToFields - # Объект документ - self.docObj = self._textToXML() - # Создаем поля-массивы - self.docObj.postParserList() - # Создаем поля разделенные массивы - self.docObj.postParserListSeplist(self.docObj.body) - # XML документ - self.doc = self.docObj.doc - - def join(self, ldapObj): - """Объединяем конфигурации""" - if isinstance(ldapObj, ldap): - self.docObj.joinDoc(ldapObj.doc) - - def setDataField(self, txtLines, endtxtLines): - """Создаем список объектов с переменными""" - class fieldData: - def __init__(self): - self.name = False - self.value = False - self.comment = False - self.br = False - fields = [] - field = fieldData() - z = 0 - for k in txtLines: - textLine = k + endtxtLines[z] - z += 1 - findComment = self.reComment.search(textLine) - if not textLine.strip(): - field.br = textLine - fields.append(field) - field = fieldData() - elif findComment: - field.comment = textLine - fields.append(field) - field = fieldData() - else: - pars = textLine.strip() - nameValue = self.reSeparator.split(pars) - if len(nameValue) > 2: - valueList = nameValue[2:] - nameValue =[nameValue[0]+nameValue[1]," ".join(valueList)] - if len(nameValue) == 2: - name = nameValue[0] - value = nameValue[1].replace(self.sepFields,"") - field.name = name.replace(" ","").replace("\t","") - field.value = value - field.br = textLine - fields.append(field) - field = fieldData() - return fields - - def _textToXML(self): - """Преобразует текст в XML""" - blTmp = self.blocTextObj.findArea(self.text,self.reHeader,self.reArea) - blocs = self.getFullAreas(blTmp) - headers = [] - startHeaders = [] - finHeaders = [] - docObj = xmlDoc() - docObj.createDoc(self.configName, self.configVersion) - rootNode = docObj.getNodeBody() - # Если пустой текст то создаем пустой документ - if not blocs: - return docObj - - for h in blocs[0]: - headers.append(h.rstrip()) - bodys = blocs[1] - - z = 0 - for h in headers: - if not bodys[z]: - z += 1 - continue - areaAction = False - if h: - if h[0] == "!": - header = self.removeSymbolTerm(h.strip()) - headerQuote = self.removeSymbolTerm(h) - docObj.createCaption(header,[headerQuote,""]) - areaAction = "drop" - elif h[0] == "-": - header = self.removeSymbolTerm(h.strip()) - headerQuote = self.removeSymbolTerm(h) - docObj.createCaption(header,[headerQuote,""]) - areaAction = "replace" - else: - docObj.createCaption(h.strip(), [h.rstrip(),""]) - else: - docObj.createCaption(h.strip(), [h.rstrip(),""]) - - if "\n" in blocs[0][z]: - resHead = self.reComment.search(h) - if resHead: - docObj.createField('comment', - blocs[0][z][resHead.start():]) - else: - docObj.createField('br') - - fields = self._splitToFields(bodys[z]) - for f in fields: - if f.name != False and f.value!=False and f.br!=False: - # Обработка условий для samba - if f.name[0] == "!" or f.name[0] == "-" or\ - f.name[0] == "+": - qns = self.removeSymbolTerm(f.br) - xmlField = docObj.createField("var", - [qns], - f.name[1:], [f.value]) - if f.name[0] == "!": - # Удаляемое в дальнейшем поле - docObj.setActionField(xmlField, "drop") - elif f.name[0] == "+": - # Добавляем уникальное поле - xmlField.setAttribute("type", "seplist") - docObj.setActionField(xmlField, "join") - else: - docObj.createField("var",[f.br.replace("\n","")], - f.name, [f.value]) - docObj.createField('br') - elif f.comment != False: - docObj.createField('comment', [f.comment]) - elif f.br != False: - docObj.createField('br', [f.br.replace("\n","")]) - if h.strip(): - area = docObj.createArea() - if areaAction: - docObj.setActionArea(area, areaAction) - rootNode.appendChild(area) - else: - fieldsNodes = docObj.tmpFields.getFields() - for fieldNode in fieldsNodes: - rootNode.appendChild(fieldNode) - docObj.clearTmpFields() - z += 1 - #print docObj.doc.toprettyxml() - return docObj - -class dovecot(bind): - """Класс для обработки конфигурационного файла типа dovecot - - """ - _comment = "#" - configName = "dovecot" - configVersion = "0.1" - __openArea = "{" - __closeArea = "[ \t]*\}[ \t]*" - sepFields = "\n" - reOpen = re.compile(__openArea) - reClose = re.compile(__closeArea) - reCloseArea = re.compile(__closeArea + "\s*\Z") - reComment = re.compile("[ \t]*%s" %(_comment)) - reSepFields = re.compile(sepFields) - # разделитель названия и значения переменной - reSeparator = re.compile("\s*=\s*") - - def __init__(self, text): - bind.__init__(self,text) - - def postXML(self, xmlArea=False): - """Последующая постобработка XML""" - # Добавляем перевод строки если его нет в конец области - if not xmlArea: - xmlArea = self.docObj.body - xmlFields = xpath.Evaluate("child::field", xmlArea) - if xmlFields and not (\ - self.docObj.getTypeField(xmlFields[-1]) == "br" or\ - self.docObj.getTypeField(xmlFields[-1]) == "comment"): - xmlArea.appendChild(self.docObj.createField("br", - [],"",[], - False,False)) - xmlAreas = xpath.Evaluate("child::area", xmlArea) - for area in xmlAreas: - self.postXML(area) - - def join(self, dovecotObj): - """Объединяем конфигурации""" - if isinstance(dovecotObj, dovecot): - #print self.docObj.doc.toprettyxml() - self.docObj.joinDoc(dovecotObj.doc) - # Для добавления перевода строки перед закрывающим тегом - # конфигурационного файла - self.postXML() - - -class procmail(objShare): - """Класс для обработки конфигурационного файла типа procmail - - """ - _comment = "#" - configName = "procmail" - configVersion = "0.1" - sepFields = "\n" - reComment = re.compile("[ \t]*%s" %(_comment)) - reSepFields = re.compile(sepFields) - # разделитель названия и значения переменной - reSeparator = re.compile("=") - def __init__(self, text): - self.text = text - self.docObj = self.textToXML() - self.doc = self.docObj.doc - - def setDataField(self, txtLines, endtxtLines): - """Создаем список объектов с переменными""" - class fieldData: - def __init__(self): - self.name = False - self.value = False - self.comment = False - self.br = False - fields = [] - field = fieldData() - z = 0 - for k in txtLines: - textLine = k + endtxtLines[z] - z += 1 - findComment = self.reComment.search(textLine) - if not textLine.strip(): - field.br = textLine - fields.append(field) - field = fieldData() - elif findComment: - field.comment = textLine - fields.append(field) - field = fieldData() - else: - pars = textLine.strip() - nameValue = self.reSeparator.split(pars) - if len(nameValue) == 2: - name = nameValue[0] - value = nameValue[1].replace(self.sepFields,"") - field.name = name.replace(" ","").replace("\t","") - field.value = value - field.br = textLine - fields.append(field) - field = fieldData() - return fields - - def textToXML(self): - docObj = xmlDoc() - docObj.createDoc(self.configName, self.configVersion) - if self.text: - nodeBody = docObj.getNodeBody() - fields = self.splitToFields(self.text) - for field in fields: - if field.name != False: - fieldXML = self.createFieldTerm(field.name, - field.value, - field.br, docObj) - nodeBody.appendChild(fieldXML) - if field.br[-1] == "\n": - fieldXMLBr = docObj.createField("br",[], - "",[], - False, False) - nodeBody.appendChild(fieldXMLBr) - elif field.comment != False: - fieldXML = docObj.createField("comment", - [field.comment], - "", [], - False, False) - nodeBody.appendChild(fieldXML) - elif field.br != False: - brText = field.br.replace("\n","") - if brText: - fieldXML = docObj.createField('br', - [brText], - "", [], - False, False) - else: - fieldXML = docObj.createField('br', - [], - "", [], - False, False) - nodeBody.appendChild(fieldXML) - return docObj - - def join(self, procmailObj): - """Объединяем конфигурации""" - if isinstance(procmailObj, procmail): - #print self.docObj.doc.toprettyxml() - self.docObj.joinDoc(procmailObj.doc) - -class kde(samba): - """Класс для обработки конфигурационного файла типа kde - - """ - _comment = "#" - configName = "kde" - configVersion = "0.1" - reHeader = re.compile("^[\t ]*\[[^\[\]]+\].*\n?",re.M) - reBody = re.compile(".+",re.M|re.S) - reComment = re.compile("^\s*%s.*"%(_comment)) - reSeparator = re.compile("=") - sepFields = "\n" - reSepFields = re.compile(sepFields) - - def __init__(self,text): - samba.__init__(self,text) - - - def _textToXML(self): - """Преобразует текст в XML""" - blTmp = self.blocTextObj.findBloc(self.text,self.reHeader,self.reBody) - blocs = self.getFullAreas(blTmp) - headers = [] - startHeaders = [] - finHeaders = [] - docObj = xmlDoc() - docObj.createDoc(self.configName, self.configVersion) - rootNode = docObj.getNodeBody() - # Если пустой текст то создаем пустой документ - if not blocs: - return docObj - - for h in blocs[0]: - reH = re.compile("]\s*$") - #listfinH = h.split("]") - listfinH = reH.split(h) - finH = listfinH[0] - if "[" in finH: - startHeaders.append(finH + "]") - else: - startHeaders.append(finH) - if len(listfinH) == 2: - finHeaders.append(listfinH[1]) - else: - finHeaders.append("") - head=finH.replace("][",".").replace("[","").replace("]","").strip() - headers.append(head) - bodys = blocs[1] - - z = 0 - for h in headers: - if not bodys[z]: - z += 1 - continue - areaAction = False - if h: - if h[0] == "!": - docObj.createCaption(h[1:], [startHeaders[z],""]) - areaAction = "drop" - elif h[0] == "-": - docObj.createCaption(h[1:], [startHeaders[z],""]) - areaAction = "replace" - else: - docObj.createCaption(h, [startHeaders[z],""]) - else: - docObj.createCaption(h, [startHeaders[z],""]) - - if "\n" in blocs[0][z]: - if self.reComment.search(finHeaders[z]): - docObj.createField('comment', [finHeaders[z]]) - elif not finHeaders[z].strip() and\ - finHeaders[z].replace("\n",""): - docObj.createField('br', - [finHeaders[z].replace("\n","")]) - else: - docObj.createField('br') - fields = self._splitToFields(bodys[z]) - for f in fields: - if f.name != False and f.value!=False and f.br!=False: - # Обработка условий для samba - if f.name[0] == "!" or f.name[0] == "-" or\ - f.name[0] == "+": - qns = self.removeSymbolTerm(f.br) - xmlField = docObj.createField("var", - [qns], - f.name[1:], [f.value]) - if f.name[0] == "!": - # Удаляемое в дальнейшем поле - docObj.setActionField(xmlField, "drop") - else: - docObj.createField("var",[f.br.replace("\n","")], - f.name, [f.value]) - docObj.createField('br') - elif f.comment != False: - docObj.createField('comment', [f.comment]) - elif f.br != False: - docObj.createField('br', [f.br.replace("\n","")]) - if h.strip(): - area = docObj.createArea() - if areaAction: - docObj.setActionArea(area, areaAction) - rootNode.appendChild(area) - else: - fieldsNodes = docObj.tmpFields.getFields() - for fieldNode in fieldsNodes: - rootNode.appendChild(fieldNode) - docObj.clearTmpFields() - z += 1 - #print docObj.doc.toprettyxml() - return docObj - - def join(self, kdeObj): - """Объединяем конфигурации""" - if isinstance(kdeObj, kde): - self.docObj.joinDoc(kdeObj.doc) - self.postXML() - - -class xmlDocPlasma: - """Класс для замены метода joinArea в xmlDoc для plasma""" - # заменяемый метод для xmlDoc - def joinArea(self, baseNode, xmlNewArea): - """Объединяет область c областью Body (xmlNewArea c baseNode)""" - def appendArea(baseNode, xmlNewArea): - fieldsRemove = xpath.Evaluate(\ - "descendant::field[child::action='drop']", xmlNewArea) - for rmNode in fieldsRemove: - parentNode = rmNode.parentNode - parentNode.removeChild(rmNode) - captionAreasRemove = xpath.Evaluate(\ - "descendant::area/child::caption[child::action='drop']", - xmlNewArea) - for rmNodeCapt in captionAreasRemove: - rmNode = rmNodeCapt.parentNode - parentNode = rmNode.parentNode - parentNode.removeChild(rmNode) - self.setActionArea(xmlNewArea, "append") - # Добавляем разделитель областей во вложенные области - areaNodes = xpath.Evaluate('descendant::area',xmlNewArea) - for areaNode in areaNodes: - self.setActionArea(areaNode,"append") - parentNode = areaNode.parentNode - parentNode.insertBefore(self.sepAreas.cloneNode(True), - areaNode) - baseNode.appendChild(xmlNewArea) - # Добавляем разделитель областей - baseNode.insertBefore(self.sepAreas.cloneNode(True), xmlNewArea) - - nodesNames = xpath.Evaluate('child::area/caption/name',baseNode) - nodesNewArea = xpath.Evaluate('child::caption/name',xmlNewArea) - if not nodesNames: - # Добавляем область - if nodesNewArea: - newAreaAction = self.getActionArea(xmlNewArea) - if not (newAreaAction == "drop"): - appendArea(baseNode, xmlNewArea) - return True - if not nodesNames or not nodesNewArea: - return False - nameArea = "" - if nodesNewArea[0].firstChild: - nameArea = nodesNewArea[0].firstChild.nodeValue.strip() - flagFindArea = False - baseNodes = [] - for oName in nodesNames: - newAreaAction = self.getActionArea(xmlNewArea) - oArea = oName.parentNode.parentNode - oNameTxt = "" - if oName.firstChild: - oNameTxt = oName.firstChild.nodeValue - if nameArea == oNameTxt: - flagFindArea = True - # При использовании удаления - if newAreaAction == "drop": - prevNode = oName.parentNode.parentNode.previousSibling - removePrevNodes = [] - while (prevNode) and self.getTypeField(prevNode) == "br": - removePrevNodes.append(prevNode) - prevNode = prevNode.previousSibling - for removeNode in removePrevNodes: - baseNode.removeChild(removeNode) - baseNode.removeChild(oName.parentNode.parentNode) - continue - elif newAreaAction == "replace": - oldAreaNode = oName.parentNode.parentNode - newAreaCaption = xpath.Evaluate('child::caption', - xmlNewArea)[0] - oldAreaCaption = xpath.Evaluate('child::caption', - oldAreaNode)[0] - if newAreaCaption and oldAreaCaption: - xmlNewArea.replaceChild(oldAreaCaption,newAreaCaption) - self.setActionArea(xmlNewArea,"replace") - baseNode.replaceChild(xmlNewArea, - oldAreaNode) - continue - baseNodes.append(oName.parentNode.parentNode) - - # Заменяем QUOTE - oldAreaNode = oName.parentNode.parentNode - oldAreaQuote = xpath.Evaluate('child::caption/quote', - oldAreaNode)[0] - if oldAreaQuote and\ - not oldAreaQuote.firstChild: - newAreaQuote = xpath.Evaluate('child::caption/quote', - xmlNewArea)[0] - oldAreaCaption = xpath.Evaluate('child::caption', - oldAreaNode)[0] - if newAreaQuote and oldAreaCaption: - oldAreaCaption.replaceChild(newAreaQuote, oldAreaQuote) - - newFields = xpath.Evaluate('child::field',xmlNewArea) - - joinNewFields = xpath.Evaluate(\ - "child::field[child::action='join']" - ,xmlNewArea) - self.addNewFielsOldArea(newFields, joinNewFields, oArea) - - - if not flagFindArea: - # Добавляем область - if not (newAreaAction == "drop"): - appendArea(baseNode, xmlNewArea) - else: - tmpXmlNewAreas = xpath.Evaluate('child::area',xmlNewArea) - for na in tmpXmlNewAreas: - for bn in baseNodes: - self.joinArea(bn, na) - return True - -class plasma(samba): - """Класс для обработки конфигурационного файла типа kde - - """ - _comment = "#" - configName = "plasma" - configVersion = "0.1" - reHeader = re.compile("^[\t ]*\[[^\[\]]+\].*\n?",re.M) - reBody = re.compile(".+",re.M|re.S) - reComment = re.compile("^\s*%s.*"%(_comment)) - reSeparator = re.compile("=") - sepFields = "\n" - reSepFields = re.compile(sepFields) - - def __init__(self,text): - samba.__init__(self,text) - - # Делим текст на области включая вложенные (areas массив областей) - def splitToAllArea(self, text, areas): - """Делит текст на области включая вложенные - - возвращает список объектов областей (переменная areas) - """ - class area: - def __init__(self): - self.header = False - self.start = False - self.fields = [] - self.end = False - - - def findPathArea(listPath, areaF): - """Ищет путь в области - - areaF - объект area - listPath - cписок названий областей - """ - ret = False - if not listPath: - return ret - flagList = False - if type(areaF) == types.ListType: - fields = areaF - flagList = True - else: - fields = areaF.fields - if areaF.header == listPath[0]: - ret = areaF - else: - return ret - for i in fields: - if str(i.__class__.__name__) == "area": - add = False - if not flagList: - add = listPath.pop(0) - if not listPath: - break - ret = False - if i.header == listPath[0]: - ret = findPathArea(listPath, i) - break - else: - if add: - listPath.insert(0,add) - if ret == areaF and len(listPath)>1: - ret = False - return ret - - - blTmp = self.blocTextObj.findBloc(self.text,self.reHeader,self.reBody) - blocs = self.getFullAreas(blTmp) - reH = re.compile("\[([^\[\]]+)\]") - # Список имен блоков - namesBlockList = [] - # Временные поля - fieldsTmp = [] - # Добавляем заголовки - z = 0 - for h in blocs[0]: - if not h: - if blocs[1][z] == "": - fieldsTmp.append("") - #fieldsTmp.append("\n") - else: - fieldsTmp.append(blocs[1][z]) - #print '"' + blocs[1][z] + '"' - z += 1 - continue - #print '"' + blocs[1][z] + '"' - z += 1 - slpNamesBlock = reH.split(h) - # Отступ слева для заголовка - indentionLeft = slpNamesBlock[0] - namesBlock = filter(lambda x: x.strip(), slpNamesBlock) - #namesBlock = map(lambda x: self.removeSymbolTerm(x), namesBlock) - findArea = findPathArea(copy.copy(namesBlock), areas) - namesBlockList.append(namesBlock) - if findArea: - if len(namesBlock) > 1: - namesBlockView = map(lambda x: self.removeSymbolTerm(x), - namesBlock) - else: - namesBlockView = namesBlock - findArea.start = indentionLeft + "[" + \ - "][".join(namesBlockView) + "]" - else: - i = 0 - lenNamesBlock = len(namesBlock) - namesBlockTmp = [] - for nameB in namesBlock: - namesBlockTmp.append(nameB) - findArea = findPathArea(copy.copy(namesBlockTmp), areas) - i += 1 - if not findArea: - areaNew = area() - areaNew.header = nameB - if lenNamesBlock == i: - if len(namesBlock) > 1: - namesBlockView = map(\ - lambda x: self.removeSymbolTerm(x), - namesBlock) - else: - namesBlockView = namesBlock - areaNew.start = indentionLeft + "[" + \ - "][".join(namesBlockView) + "]" - else: - areaNew.start = "" - areaNew.end = "" - if i == 1: - if lenNamesBlock == i: - areas += fieldsTmp - areas.append(areaNew) - findAreaPrev = areas[-1] - else: - if lenNamesBlock == i: - findAreaPrev.fields += fieldsTmp - findAreaPrev.fields.append(areaNew) - findAreaPrev = findAreaPrev.fields[-1] - else: - findAreaPrev = findArea - fieldsTmp = [] - i = 0 - delt = 0 - # Добавляем тела - for body in blocs[1]: - #print "#" + body + "#" - #print - if not blocs[0][i]: - i += 1 - delt +=1 - continue - ## В случае последнего комментария не добавляем перевод строки - #if self.reComment.search(body.splitlines()[-1]): - body = "\n" + body - - namesBlock = namesBlockList[i-delt] - findArea = findPathArea(copy.copy(namesBlock), areas) - if findArea: - #if findArea.fields: - #if type(findArea.fields[0]) == types.StringType: - #findArea.fields.pop(0) - findArea.fields.insert(0, body) - i += 1 - - #eee = 1 - #def prAreas(ar, eee): - #for a in ar: - #if type(a) == types.StringType: - #print 'field', a - #else: - #print "--------------------" - #print "HEADER =", a.header - #print "START =", a.start - #print "FIELDS =", a.fields - #print "LEVEL", eee - #if type(a) != types.StringType: - #if a.fields: - #eee += 1 - #prAreas(a.fields, eee) - - #prAreas(areas, eee) - return areas - - def createCaptionTerm(self, header, start, end, docObj): - """Создание пустой области с заголовком - - при создании области проверяется первый символ заголовка - и добавляется тег action - "!" - drop - "-" - replace - """ - areaAction = False - if header: - if header[0] == "!": - docObj.createCaption(header[1:], [start, - end.replace("\n","")]) - areaAction = "drop" - elif header[0] == "-": - docObj.createCaption(header[1:], [start, - end.replace("\n","")]) - areaAction = "replace" - else: - docObj.createCaption(header, [start, - end.replace("\n","")]) - else: - docObj.createCaption(header, [start, - end.replace("\n","")]) - - areaXML = docObj.createArea() - if areaAction: - docObj.setActionArea(areaXML, areaAction) - return areaXML - - def createXML(self, areas, rootNode, docObj): - """Создаем из массивов областей XML""" - for i in areas: - if str(i.__class__.__name__) == "area": - if i.header: - areaXML = self.createCaptionTerm(i.header, i.start, - i.end.replace("\n",""), - docObj) - for f in i.fields: - if str(f.__class__.__name__) == "area": - if f.header: - areaXMLChild = self.createCaptionTerm(f.header, - f.start, - f.end.replace("\n",""), - docObj) - - self.createXML(f.fields, areaXMLChild, docObj) - - areaXML.appendChild(areaXMLChild) - else: - self.createXML(f.fields, areaXML, docObj) - if "\n" in f.end: - fieldXMLBr = docObj.createField("br",[], - "",[], - False, False) - areaXML.appendChild(fieldXMLBr) - else: - if not f: - continue - fields = self.splitToFields(f) - for field in fields: - if field.name != False: - fieldXML = self.createFieldTerm(field.name, - field.value, - field.br, docObj) - areaXML.appendChild(fieldXML) - if field.br[-1] == "\n": - fieldXMLBr = docObj.createField("br",[], - "",[], - False, False) - areaXML.appendChild(fieldXMLBr) - elif field.comment != False: - fieldXML = docObj.createField("comment", - [field.comment], - "", [], - False, False) - areaXML.appendChild(fieldXML) - elif field.br != False: - brText = field.br.replace("\n","") - if brText: - fieldXML = docObj.createField('br', - [brText], - "", [], - False, False) - else: - fieldXML = docObj.createField('br', - [], - "", [], - False, False) - if areaXML: - areaXML.appendChild(fieldXML) - - if i.header: - rootNode.appendChild(areaXML) - if "\n" in i.end: - fieldXMLBr = docObj.createField("br",[], - "",[], - False, False) - rootNode.appendChild(fieldXMLBr) - - else: - if not i: - continue - fields = self.splitToFields(i) - for field in fields: - if field.name != False: - fieldXML = self.createFieldTerm(field.name, - field.value, - field.br, docObj) - rootNode.appendChild(fieldXML) - if field.br[-1] == "\n": - fieldXMLBr = docObj.createField("br",[],"", [], - False, False) - rootNode.appendChild(fieldXMLBr) - elif field.comment != False: - fieldXML = docObj.createField("comment", - [field.comment], - "", [], - False, False) - rootNode.appendChild(fieldXML) - elif field.br != False: - brText = field.br.replace("\n","") - if brText: - fieldXML = docObj.createField('br', [brText],"",[], - False, False) - else: - fieldXML = docObj.createField('br', [], "", [], - False, False) - rootNode.appendChild(fieldXML) - #rootNode.appendChild(areaXML) - - - def createTxtConfig(self, strHeader, dictVar): - """Cоздает область с заголовком - - создает текст конфигурационного файла в формате samba из - заголовка (строка) и словаря переменных - """ - if not strHeader: - return "" - if type(strHeader) in (tuple, list): - outTxt = "".join(map(lambda x: "["+x+"]",strHeader)) - if not outTxt: - return "" - outTxt += "\n" - else: - outTxt = "[" + strHeader + "]\n" - for key in dictVar.keys(): - outTxt += "%s=%s\n" %(key,dictVar[key]) - return outTxt - - def _textToXML(self): - """Преобразуем текст в XML""" - areas = [] - if self.text.strip(): - self.splitToAllArea(self.text, areas) - #docObj = xmlDoc() - # Создаем новый класс xmlDoc с измененным методом joinArea - newClass = type("newXmlDocPlalma",(xmlDocPlasma,xmlDoc,object),{}) - # Создаем экземпляр нового класса - docObj = newClass() - # Создание объекта документ c пустым разделителем между полями - docObj.createDoc(self.configName, self.configVersion) - if not areas: - return docObj - self.createXML(areas, docObj.getNodeBody(), docObj) - return docObj - - - def postXML(self): - """Последующая постобработка XML""" - # Для добавления перевода строки между областями если его нет - #print self.docObj.body.toprettyxml() - def getQuotesArea(xmlArea): - quotes = [] - xmlQuotes = xpath.Evaluate('child::caption/quote',xmlArea) - for node in xmlQuotes: - if node.firstChild: - quotes.append(node.firstChild.nodeValue) - if len(quotes) == 0: - quotes.append("") - quotes.append("") - elif len(quotes) == 1: - quotes.append("") - return quotes - - xmlAreas = xpath.Evaluate("descendant::area", self.docObj.body) - #print "-------------------------------------------------------" - #print xmlAreas - #if xmlAreas: - #prXmlArea = xmlAreas[0] - for xmlArea in xmlAreas: - # Перед пустой областью и после нее удаляем переводы строк - if getQuotesArea(xmlArea) == ["",""]: - #areaTXT = xpath.Evaluate("child::caption/name", xmlArea)[0] - #print "CL_AREA", areaTXT.firstChild - if xmlArea.previousSibling and\ - self.docObj.getTypeField(xmlArea.previousSibling) == "br": - parentNode = xmlArea.previousSibling.parentNode - if xmlArea.previousSibling.previousSibling and\ - self.docObj.getTypeField(xmlArea.previousSibling.previousSibling) == "br": - parentNode.removeChild(\ - xmlArea.previousSibling.previousSibling) - parentNode.removeChild(xmlArea.previousSibling) - if xmlArea.nextSibling and\ - self.docObj.getTypeField(xmlArea.nextSibling) == "br": - parentNode = xmlArea.nextSibling.parentNode - if xmlArea.nextSibling.nextSibling and\ - self.docObj.getTypeField(xmlArea.nextSibling.nextSibling) == "br": - parentNode.removeChild(xmlArea.nextSibling.nextSibling) - parentNode.removeChild(xmlArea.nextSibling) - continue - - # Собираем поля в кучку - xmlChildAreas = xpath.Evaluate("child::area", xmlArea) - if xmlChildAreas: - childNodes = self.docObj.getFieldsArea(xmlArea) - firstChildArea = xmlChildAreas[0] - if firstChildArea.previousSibling and\ - self.docObj.getTypeField(firstChildArea.previousSibling)=="br": - if firstChildArea.previousSibling.previousSibling: - if self.docObj.getTypeField(\ - firstChildArea.previousSibling.previousSibling)=="br": - firstChildArea = firstChildArea.previousSibling - flagFoundArea = False - it = 0 - lenChild = len(childNodes) - for node in childNodes: - it += 1 - if node.tagName == "area": - flagFoundArea = True - continue - if flagFoundArea and node.tagName == "field": - if self.docObj.getTypeField(node) == "var": - xmlArea.insertBefore(node, firstChildArea) - if it < lenChild: - if self.docObj.getTypeField(childNodes[it])==\ - "br": - xmlArea.insertBefore(childNodes[it], - firstChildArea) - # Добавление перевода строк в если его нет между полями - if self.docObj.getTypeField(node) == "var" and\ - node.previousSibling and\ - not (self.docObj.getTypeField(node.previousSibling) in\ - ("br","comment")): - xmlArea.insertBefore(self.docObj.createField("br", - [],"",[], - False,False), - node) - - # Добавляем BR если его нет первым полем - xmlFields = xpath.Evaluate("child::field", xmlArea) - if not (xmlFields and\ - (self.docObj.getTypeField(xmlFields[0]) == "br" or\ - self.docObj.getTypeField(xmlFields[0]) == "comment")): - if xmlFields: - xmlArea.insertBefore(self.docObj.createField("br", - [],"",[], - False,False), - xmlFields[0]) - # Если последним полем BR, удаляем его - if xmlFields and self.docObj.getTypeField(xmlFields[-1]) == "br": - #print "DEL_BR", xmlFields[-1].nextSibling - #and\ - if not xmlFields[-1].nextSibling: - xmlArea.removeChild(xmlFields[-1]) - - # Если предыдущим полем не (BR или комментарий) - добавляем BR - if xmlArea.previousSibling and\ - not (self.docObj.getTypeField(xmlArea.previousSibling) == "br" or\ - self.docObj.getTypeField(xmlArea.previousSibling) == "comment"): - parentNode = xmlArea.parentNode - parentNode.insertBefore(self.docObj.createField("br", - [],"",[], - False,False), - xmlArea) - # Если есть предыдущее поле, и поле предыдущеее предыдущему - # не равно BR или комментарий то добавляем BR - if xmlArea.previousSibling: - prPrSibling = xmlArea.previousSibling.previousSibling - if prPrSibling and\ - not (self.docObj.getTypeField(prPrSibling) == "br" or\ - self.docObj.getTypeField(prPrSibling) == "comment"): - parentNode = xmlArea.parentNode - parentNode.insertBefore(self.docObj.createField("br", - [],"",[], - False,False), - xmlArea) - # Если после есть BR а за ним ничего нет, удаляем BR - if xmlArea.nextSibling and\ - self.docObj.getTypeField(xmlArea.nextSibling) == "br": - if not xmlArea.nextSibling.nextSibling: - parentNode = xmlArea.nextSibling.parentNode - parentNode.removeChild(xmlArea.nextSibling) - - - def join(self, kdeObj): - """Объединяем конфигурации""" - if isinstance(kdeObj, plasma): - self.docObj.joinDoc(kdeObj.doc) - self.postXML() - -class xml_xfce(_error): - """Класс для объединения xfce-xml файлов""" - # root нода - rootNode = False - # body нода - bodyNode = False - # Документ - doc = False - # Текст профиля - text = "" - # Комментарий - _comment = ("") - - def __init__(self, text): - self.text = text - # Создаем пустой объект - self.docObj = type("_empty_class", (object,), {})() - # Названия аттрибутов для пустого объекта - emptyMethods = ["getNodeBody","removeComment","insertBRtoBody", - "insertBeforeSepAreas"] - # Добавляем необходимые аттрибуты пустому объекту - for method in emptyMethods: - setattr(self.docObj, method, self.emptyMethod) - # Создаем XML документ - self.doc = self.textToXML() - - def emptyMethod(self, *arg , **argv): - """Пустой метод""" - return True - - def setNameBodyNode(self, name): - """Устанавливает название для корневой ноды документа""" - if not self.bodyNode: - return False - self.bodyNode.setAttribute("name", name) - return True - - def textToXML(self): - """Создание из текста XML документа - Храним xml в своем формате - """ - if not self.text.strip(): - self.text = ''' - -''' - try: - self.doc = xml.dom.minidom.parseString(self.text) - except: - self.setError(_("Can not text profile is XML")) - return False - self.rootNode = self.doc.documentElement - self.bodyNode = self.rootNode - return self.doc - - def join(self, xml_xfceObj): - """Объединяем конфигурации""" - if isinstance(xml_xfceObj, xml_xfce): - try: - self.joinDoc(xml_xfceObj.doc) - except: - self.setError(_("Can not join profile")) - return False - return True - - def _removeDropNodesAndAttrAction(self, xmlNode): - """Удаляет ноды с аттрибутом action='drop' - - Также удаляет аттрибут action у всех нод - """ - flagError = False - childNodes = xmlNode.childNodes - if xmlNode.nodeType ==xmlNode.ELEMENT_NODE: - if xmlNode.hasAttribute("action"): - nAction = xmlNode.getAttribute("action") - if not nAction in ("join","replace","drop"): - textError = _('''In the text, XML profile, look \ -for a reserved attribute 'action' with the incorrect value.\n\ -Valid values attribute 'action': \ -(action="join", action="replace", action="drop")''') - self.setError(textError) - return False - xmlNode.removeAttribute("action") - if nAction == "drop": - parentNode = xmlNode.parentNode - if parentNode: - parentNode.removeChild(xmlNode) - if childNodes: - for node in childNodes: - if not self._removeDropNodesAndAttrAction(node): - flagError = True - break - if flagError: - return False - return True - - def postXML(self): - """Последующая постобработка XML""" - # Удаляем теги action и удаляемые ноды - self._removeDropNodesAndAttrAction(self.bodyNode) - - def _join(self, xmlNewNode, xmlOldNode, flagRootNode=True): - """Объединение корневой ноды профиля и корневой ноды файла""" - xmlNode = xmlNewNode - childNodes = xmlNode.childNodes - nextOldNode = xmlOldNode - flagError = False - if xmlNode.nodeType ==xmlNode.ELEMENT_NODE: - n = xmlNode - path = u'' - nName = u'' - nType = u'' - nValue = u'' - nAction = u'' - attrName = '' - attrType = '' - path = n.tagName - if n.hasAttribute("name"): - nName = n.getAttribute("name") - attrName = u"attribute::name='%s'"%nName - if n.hasAttribute("type"): - nType = n.getAttribute("type") - attrType = u"attribute::type='%s'"%nType - if n.hasAttribute("value"): - nValue = n.getAttribute("value") - if n.hasAttribute("action"): - nAction = n.getAttribute("action") - if not nAction in ("join","replace","drop"): - textError = _('''In the text, XML profile, look \ -for a reserved attribute 'action' with the incorrect value.\n\ -Valid values attribute 'action': \ -(action="join", action="replace", action="drop")''') - self.setError(textError) - return False - if xmlOldNode.parentNode: - strAttr = [attrName, attrType] - findAttr = filter(lambda x: x, strAttr) - findAttrStr = '' - if findAttr: - strAttr = u' and '.join(findAttr) - findAttrStr = "[%s]"%strAttr - findPath = u"child::%s%s"%(path,findAttrStr) - # Рабочая нода - if flagRootNode: - workNode = xmlOldNode.parentNode - else: - workNode = xmlOldNode - oldNodes = xpath.Evaluate(findPath, workNode) - #print findPath - #print workNode - #print "----------------------------" - # Новая нода список - flagArray = False - if nType == "array": - flagArray = True - flagDrop = False - flagJoin = True - flagReplace = False - if nAction == "replace": - flagJoin = False - flagReplace = True - elif nAction == "drop": - flagJoin = False - flagDrop = True - if flagRootNode: - textError = _('Incorrect action="drop" in root node') - self.setError(textError) - return False - if oldNodes: - if len(oldNodes)>1: - textError = _("The uncertainty in this profile are \ -the same nodes at one level") - self.setError(textError) - return False - nextOldNode = oldNodes[0] - # Замещаем ноду в случае массива - if flagArray and not flagDrop: - replaceXmlNode = xmlNode.cloneNode(True) - if nAction: - replaceXmlNode.removeAttribute("action") - workNode.replaceChild(replaceXmlNode, - nextOldNode) - flagJoin = False - flagReplace = False - childNodes = False - # Объединение нод - if flagJoin: - if nextOldNode.hasAttribute("value"): - oValue = nextOldNode.getAttribute("value") - if nValue != oValue: - nextOldNode.setAttribute("value",nValue) - # Замещение ноды - elif flagReplace: - replaceXmlNode = xmlNode.cloneNode(True) - if not\ - self._removeDropNodesAndAttrAction(replaceXmlNode): - return False - workNode.replaceChild(replaceXmlNode, - nextOldNode) - childNodes = False - # Удаление ноды - elif flagDrop: - workNode.removeChild(nextOldNode) - childNodes = False - else: - # Добавление ноды - childNodes = False - if not flagDrop: - appendXmlNode = xmlNode.cloneNode(True) - if not\ - self._removeDropNodesAndAttrAction(appendXmlNode): - return False - workNode.appendChild(appendXmlNode) - if childNodes: - for node in childNodes: - if not self._join(node, nextOldNode, False): - flagError = True - break - if flagError: - return False - return True - - def joinDoc(self, doc): - """Объединение документа профиля и документа файла""" - if not self.doc: - self.setError(_("Can not text file is XML")) - return False - if not doc: - self.setError(_("Can not text profile is XML")) - return False - # Импортируем корневую ноду нового документа в текущий документ - #newImportBodyNode = self.doc.importNode(doc.documentElement, True) - # Объединение корневой ноды профиля и корневой ноды файла - if not self._join(doc.documentElement, self.bodyNode): - return False - return True - - def getConfig(self): - """Получение текстового файла из XML документа""" - data = self.doc.toprettyxml(encoding='UTF-8').split("\n") - data = filter(lambda x: x.strip(), data) - return "\n".join(data).replace("\t"," ").decode("UTF-8") - -class squid(procmail): - """Класс для обработки конфигурационного файла типа squid - - """ - configName = "squid" - configVersion = "0.1" - # разделитель названия и значения переменной - reSeparator = re.compile(" ") - - def __init__(self, text): - procmail.__init__(self, text) - # Создаем поля-массивы - self.docObj.postParserList() - # Создаем поля разделенные массивы - self.docObj.postParserListSeplist(self.docObj.body) - - def setDataField(self, txtLines, endtxtLines): - """Создаем список объектов с переменными""" - class fieldData: - def __init__(self): - self.name = False - self.value = False - self.comment = False - self.br = False - fields = [] - field = fieldData() - z = 0 - for k in txtLines: - textLine = k + endtxtLines[z] - z += 1 - findComment = self.reComment.search(textLine) - flagVariable = True - if not textLine.strip(): - field.br = textLine - fields.append(field) - field = fieldData() - flagVariable = False - elif findComment: - if textLine[:findComment.start()].strip(): - field.comment = textLine[findComment.start():] - textLine = textLine[:findComment.start()] - else: - field.comment = textLine - flagVariable = False - fields.append(field) - field = fieldData() - if flagVariable: - pars = textLine.strip() - nameValue = self.reSeparator.split(pars) - if len(nameValue) > 2: - valueList = nameValue[1:] - nameValue =[nameValue[0]," ".join(valueList)] - if len(nameValue) == 2: - name = nameValue[0] - value = nameValue[1].replace(self.sepFields,"") - field.name = name.replace(" ","").replace("\t","") - field.value = value - field.br = textLine - fields.append(field) - field = fieldData() - return fields - - def join(self, squidObj): - """Объединяем конфигурации""" - if isinstance(squidObj, squid): - #print squidObj.getConfig() - self.docObj.joinDoc(squidObj.doc) - -class xml_xfcepanel(xml_xfce): - """Класс для объединения xfce-panel файлов""" - def __init__(self, text): - xml_xfce.__init__(self, text) - self.panelNumbers = {} - - def textToXML(self): - """Создание из текста XML документа - Храним xml в своем формате - """ - if not self.text.strip(): - self.text = ''' - - -''' - try: - self.doc = xml.dom.minidom.parseString(self.text) - except: - self.setError(_("Can not text profile is XML")) - return False - self.rootNode = self.doc.documentElement - self.bodyNode = self.rootNode - return self.doc - - def setNameBodyNode(self, name): - """Пустой метод""" - return True - - def _join(self, xmlNewNode, xmlOldNode, flagRootNode=True, levelNumber=0): - """Объединение корневой ноды профиля и корневой ноды файла""" - xmlNode = xmlNewNode - childNodes = xmlNode.childNodes - nextOldNode = xmlOldNode - flagError = False - if xmlNode.nodeType ==xmlNode.ELEMENT_NODE: - n = xmlNode - path = u'' - nName = u'' - flagArray = False - nValue = u'' - nAction = u'' - attrName = '' - attrType = '' - path = n.tagName - if path == "items": - flagArray = True - if not flagArray: - if n.hasAttribute("name"): - nName = n.getAttribute("name") - attrName = u"attribute::name='%s'"%nName - if n.hasAttribute("value"): - nValue = n.getAttribute("value") - if n.hasAttribute("action"): - nAction = n.getAttribute("action") - if not nAction in ("join","replace","drop"): - textError = _('''In the text, XML profile, look \ -for a reserved attribute 'action' with the incorrect value.\n\ -Valid values attribute 'action': \ -(action="join", action="replace", action="drop")''') - self.setError(textError) - return False - if xmlOldNode.parentNode: - findAttrStr = "" - if attrName: - findAttrStr = "[%s]"%attrName - findPath = u"child::%s%s"%(path,findAttrStr) - # Рабочая нода - if flagRootNode: - workNode = xmlOldNode.parentNode - else: - workNode = xmlOldNode - oldNodes = xpath.Evaluate(findPath, workNode) - flagDrop = False - flagJoin = True - flagReplace = False - flagAppend = False - if nAction == "replace": - flagJoin = False - flagReplace = True - elif nAction == "drop": - flagJoin = False - flagDrop = True - if flagRootNode: - textError = _('Incorrect action="drop" in root node') - self.setError(textError) - return False - if path == "panel": - flagJoin = False - if levelNumber in self.panelNumbers.keys(): - self.panelNumbers[levelNumber] += 1 - else: - self.panelNumbers[levelNumber] = 0 - if oldNodes: - if len(oldNodes)>1 and path != "panel": - textError = _("The uncertainty in this profile are \ -the same nodes at one level") - self.setError(textError) - return False - if path == "panel": - if len(oldNodes)<=self.panelNumbers[levelNumber]: - nextOldNode = oldNodes[-1] - # Добавляем ноду - if not flagDrop: - flagAppend = True - flagReplace = False - childNodes = False - else: - nextOldNode=oldNodes[self.panelNumbers[levelNumber]] - else: - nextOldNode = oldNodes[0] - # Замещаем ноду в случае массива - if flagArray and not flagDrop: - replaceXmlNode = xmlNode.cloneNode(True) - if nAction: - replaceXmlNode.removeAttribute("action") - workNode.replaceChild(replaceXmlNode, - nextOldNode) - flagJoin = False - flagReplace = False - childNodes = False - # Объединение нод - if flagJoin: - if nextOldNode.hasAttribute("value"): - oValue = nextOldNode.getAttribute("value") - if nValue != oValue: - nextOldNode.setAttribute("value",nValue) - # Замещение ноды - elif flagReplace: - replaceXmlNode = xmlNode.cloneNode(True) - if not\ - self._removeDropNodesAndAttrAction(replaceXmlNode): - return False - workNode.replaceChild(replaceXmlNode, - nextOldNode) - childNodes = False - # Удаление ноды - elif flagDrop: - workNode.removeChild(nextOldNode) - childNodes = False - else: - flagAppend = True - flagDrop = False - if flagAppend and not flagDrop: - # Добавление ноды - childNodes = False - if not flagDrop: - appendXmlNode = xmlNode.cloneNode(True) - if not\ - self._removeDropNodesAndAttrAction(appendXmlNode): - return False - workNode.appendChild(appendXmlNode) - if childNodes: - for node in childNodes: - levelNumber +=1 - if not self._join(node, nextOldNode, False, levelNumber): - flagError = True - break - levelNumber -= 1 - if flagError: - return False - return True - - def join(self, xml_xfceObj): - """Объединяем конфигурации""" - if isinstance(xml_xfceObj, xml_xfcepanel): - try: - self.joinDoc(xml_xfceObj.doc) - except: - self.setError(_("Can not join profile")) - return False - return True - - -class dhcp(bind): - """Класс для обработки конфигурационного файла типа dhcp - - """ - _comment = "#" - configName = "dhcp" - configVersion = "0.1" - __openArea = "{" - __closeArea = "[ \t]*\}[ \t]*" - sepFields = ";" - reOpen = re.compile(__openArea) - reClose = re.compile(__closeArea) - reCloseArea = re.compile(__closeArea + "\s*\Z") - reComment = re.compile("^[ \t]*%s"%(_comment)) - reSepFields = re.compile(sepFields) - reSeparator = re.compile("[ \t]+") - - def __init__(self,text): - bind.__init__(self,text) - - def setDataField(self, txtLines, endtxtLines): - """Создаем список объектов с переменными""" - class fieldData: - def __init__(self): - self.name = False - self.value = False - self.comment = False - self.br = False - fields = [] - field = fieldData() - z = 0 - for k in txtLines: - textLine = k + endtxtLines[z] - z += 1 - findComment = self.reComment.search(textLine) - if not textLine.strip(): - field.br = textLine - fields.append(field) - field = fieldData() - elif findComment: - field.comment = textLine - fields.append(field) - field = fieldData() - else: - pars = textLine.strip() - nameValue = self.reSeparator.split(pars) - if len (nameValue) == 1: - field.name = textLine.replace(self.sepFields,"").strip() - field.value = "" - field.br = textLine - fields.append(field) - field = fieldData() - - if len(nameValue) > 2: - nameCheck = nameValue[0] - if nameValue[0][:1] in ["+","-","!"]: - nameCheck = nameValue[0][1:] - if nameCheck == "option" or nameCheck == "hardware" or\ - nameCheck == "set": - valueList = nameValue[2:] - nameValue =[nameValue[0]+nameValue[1], - " ".join(valueList).replace(\ - self.sepFields,"")] - else: - valueList = nameValue[1:] - nameValue =[nameValue[0]," ".join(valueList).replace(\ - self.sepFields,"")] - if len(nameValue) == 2: - name = nameValue[0] - value = nameValue[1].replace(self.sepFields,"") - field.name = name.replace(" ","").replace("\t","") - field.value = value - field.br = textLine - fields.append(field) - field = fieldData() - return fields - - def join(self, dhcpObj): - """Объединяем конфигурации""" - if isinstance(dhcpObj, dhcp): - self.docObj.joinDoc(dhcpObj.doc) - - -class xml_gconf(xml_xfce): - """Класс для объединения gconf-xml файлов""" - # root нода - rootNode = False - # body нода - bodyNode = False - # Документ - doc = False - # Текст профиля - text = "" - # Текущее время в секундах - currentTime = "" - # Комментарий - _comment = ("") - # поддерживаемые аттрибуты тега entry. Пример - supportEntryTypes = ("int", "bool", "float", "string", "list", "pair") - - def __init__(self, text): - self.text = text - # Создаем пустой объект - self.docObj = type("_empty_class", (object,), {})() - # Названия аттрибутов для пустого объекта - emptyMethods = ["getNodeBody","removeComment","insertBRtoBody", - "insertBeforeSepAreas"] - # Добавляем необходимые аттрибуты пустому объекту - for method in emptyMethods: - setattr(self.docObj, method, self.emptyMethod) - # Пустой метод (не нужно имя файла для корневой ноды) - setattr(self, "setNameBodyNode", self.emptyMethod) - # Создаем XML документ - self.doc = self.textToXML() - - def getCurrentTime(self): - """Получение текущего времени в секундах""" - return str(int(time.time())) - - def textToXML(self): - """Создание из текста XML документа - Храним xml в своем формате - """ - if not self.text.strip(): - self.text = '''''' - try: - self.doc = xml.dom.minidom.parseString(self.text) - except: - self.setError(_("Can not text profile is XML")) - return False - self.rootNode = self.doc.documentElement - self.bodyNode = self.rootNode - return self.doc - - def cmpListsNodesEntry(self, listXmlA, listXmlB): - """Сравнение содержимого двух списков XML нод""" - getTextsNodes = lambda y: map(lambda x:\ - x.toxml().replace(" ","").replace("\t","").replace("\n",""), - map(lambda x: x.hasAttribute("mtime") and\ - x.removeAttribute("mtime") or x, - map(lambda x: x.cloneNode(True), - filter(lambda x: x.nodeType==x.ELEMENT_NODE, y)))) - if set(getTextsNodes(listXmlA))==set(getTextsNodes(listXmlB)): - return True - return False - - def _join(self, xmlNewNode, xmlOldNode, flagRootNode=True, levelNumber=0): - """Объединение корневой ноды профиля и корневой ноды файла""" - if levelNumber>1: - return True - xmlNode = xmlNewNode - childNodes = xmlNode.childNodes - nextOldNode = xmlOldNode - flagError = False - if xmlNode.nodeType == xmlNode.ELEMENT_NODE: - n = xmlNode - tagName = n.tagName - nAction = u'' - nName = u'' - nType = u'' - nValue = u'' - nSchema = u'' - attrName = '' - if flagRootNode: - if not tagName == "gconf": - self.setError(_("The text is not a valid gconf-XML format \ -(not found '...')")) - return False - flagType = False - flagValue = False - flagSchema = False - else: - if not tagName == "entry": - self.setError(_("The text is not a valid gconf-XML format \ -(found '<%s>..'")%(tagName,tagName)) - return False - if not n.hasAttribute("name"): - self.setError(_('Not found arrtibute "name" in tag entry')) - return False - flagType = n.hasAttribute("type") - flagValue = False - flagSchema = n.hasAttribute("schema") - if flagSchema: - nSchema = n.getAttribute("schema") - if not flagType and not flagSchema: - self.setError(_('Not found arrtibute "type" in tag entry')) - return False - nName = n.getAttribute("name") - attrName = u"attribute::name='%s'"%nName - if flagType: - flagValue = n.hasAttribute("value") - nType = n.getAttribute("type") - # Проверка правильности аттрибута type - if not nType in self.supportEntryTypes: - self.setError(\ - _('Incorrect arrtibute "type" - ')\ - %nType) - return False - if flagValue: - nValue = n.getAttribute("value") - if n.hasAttribute("action"): - nAction = n.getAttribute("action") - if not nAction in ("join","replace","drop"): - textError = _('''In the text, XML profile, look \ -for a reserved attribute 'action' with the incorrect value.\n\ -Valid values attribute 'action': \ -(action="join", action="replace", action="drop")''') - self.setError(textError) - return False - if xmlOldNode.parentNode: - findAttrStr = "" - if attrName: - findAttrStr = "[%s]"%attrName - findPath = u"child::%s%s"%(tagName,findAttrStr) - # Рабочая нода - if flagRootNode: - workNode = xmlOldNode.parentNode - else: - workNode = xmlOldNode - oldNodes = xpath.Evaluate(findPath, workNode) - # По умолчанию - объединение - flagJoin = True - flagReplace = False - flagDrop = False - # Замещаем ноду - if nType=="string" or nAction=="replace": - flagJoin = False - flagReplace = True - # Замещаем ноду в случае массива - elif nType == "list" or nType == "pair": - flagJoin = False - flagReplace = True - # Удаляем ноду - elif nAction == "drop": - flagJoin = False - flagDrop = True - if flagRootNode: - textError = _('Incorrect action="drop" in root node') - self.setError(textError) - return False - if oldNodes: - if len(oldNodes)>1: - textError = _("The uncertainty in this profile are \ -the same nodes at one level") - self.setError(textError) - return False - nextOldNode = oldNodes[0] - # Объединение нод - if flagJoin: - if flagType and flagValue: - flagChange = False - foundValue = nextOldNode.hasAttribute("value") - if foundValue: - oValue = nextOldNode.getAttribute("value") - if nValue != oValue: - flagChange = True - else: - flagChange = True - if flagChange: - nextOldNode.setAttribute("mtime", - self.currentTime) - nextOldNode.setAttribute("value",nValue) - elif flagSchema: - flagChange = False - foundValue = nextOldNode.hasAttribute("schema") - if foundValue: - oSchema = nextOldNode.getAttribute("schema") - if nSchema != oSchema: - flagChange = True - else: - flagChange = True - if flagChange: - nextOldNode.setAttribute("mtime", - self.currentTime) - nextOldNode.setAttribute("schema",nSchema) - # Замещение ноды - elif flagReplace: - replaceXmlNode = xmlNode.cloneNode(True) - # Сравнение содержимого нод - if not self.cmpListsNodesEntry([replaceXmlNode], - [nextOldNode]): - replaceXmlNode.setAttribute("mtime", - self.currentTime) - if not\ - self._removeDropNodesAndAttrAction(\ - replaceXmlNode): - return False - workNode.replaceChild(replaceXmlNode, - nextOldNode) - childNodes = False - # Удаление ноды - elif flagDrop: - workNode.removeChild(nextOldNode) - childNodes = False - else: - # Добавление ноды - childNodes = False - if not flagDrop: - appendXmlNode = xmlNode.cloneNode(True) - appendXmlNode.setAttribute("mtime", self.currentTime) - if not\ - self._removeDropNodesAndAttrAction(appendXmlNode): - return False - workNode.appendChild(appendXmlNode) - if childNodes: - for node in childNodes: - levelNumber +=1 - if not self._join(node, nextOldNode, False, levelNumber): - flagError = True - break - levelNumber -= 1 - if flagError: - return False - return True - - def join(self, xml_gconfObj): - """Объединяем конфигурации""" - # Получаем текущее время - self.currentTime = self.getCurrentTime() - if isinstance(xml_gconfObj, xml_gconf): - try: - self.joinDoc(xml_gconfObj.doc) - except: - self.setError(_("Can not join profile")) - return False - return True - - def getConfig(self): - """Получение текстового файла из XML документа""" - def expand_start_tabs(s): - q = re.findall("^(\t+)(.*)$",s) - # if q: - return "".join((q[0][0].expand_start_tabs(),q[0][1])) - #else: - # return s - data = self.doc.toprettyxml().split("\n") - data = map(lambda x: expand_start_tabs(x), - filter(lambda x: x.strip(), data)) - dataOut = [] - z = 0 - lenData = len(data) - lenM2 = lenData - 2 - for i in xrange(lenData): - if z>0: - z -= 1 - continue - if i < lenM2 and data[i].endswith(">") and not "<" in data[i+1]: - dataOut.append(data[i] + data[i+1].strip() + data[i+2].strip()) - z = 2 - continue - dataOut.append(data[i]) - return "\n".join(dataOut) diff --git a/build/lib/calculate-lib/pym/cl_utils.py b/build/lib/calculate-lib/pym/cl_utils.py deleted file mode 100644 index 195d4d5..0000000 --- a/build/lib/calculate-lib/pym/cl_utils.py +++ /dev/null @@ -1,510 +0,0 @@ -#-*- coding: utf-8 -*- - -# Copyright 2008-2010 Mir Calculate Ltd. http://www.calculate-linux.org -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import filecmp -import string -from random import choice -from re import search, compile, S -import os -import types -import subprocess - -def getdirlist(s_path): - #Получить список директорий по указаному пути - fdir=filecmp.dircmp(s_path, s_path) - dir_list=fdir.common_dirs - return dir_list - -def prettyColumnStr(*cols): - '''Функция преобразования строк в текстовые колонки. Если указанный текст - не помещается в колонку, то строка переносится на следующую этой же колонки - перенос текста идет по словам, и текст выравнивается по ширине колонки за - счет дополнительных пробелов между словами. Если в строке используется - перенос строки, то текст переносится не просто на следующую строку, а также - на следующую строку колонки, причем если используется \r текст выравнива- - ется по ширине, а если \n, то просто перевод строки. - - Параметры: - cols множестово пар: текст, ширина колонки, причем, если у последней - колонки не указывать ширину, то она будет выведена вся. - - Возвращаемые параметры: - строка, которую можно использовать для вывода на экран - - Пример: columnWrite( "Some text", 10, "Next column", 20 ) - ''' - # шаблон поиска переводов строк - wherenr = compile( '[\n\r]', S ) - retstr = "" - # перевести кортеж в список, т.к. изменяется - cols = list(cols) - # перевести текст в юникод, заодно перевести числа в строку - noconvert = False - space = u' ' - nospace = u'' - for i in xrange(0,len(cols),2): - cols[i] = _toUNICODE(cols[i]) - # флаг "есть еще текст для вывода" - repeat = True - while repeat: - # сбросить итератор на первый элемент - q = 0 - repeat = False - # пока не закончили перебирать параметры (перебираем по парам) - while q < len(cols): - # если это последний параметр, и для него не указана ширина - if q == len(cols)-1: - # выводим его полностью не смотря на ширину окна - retstr += cols[q] + " " - cols[q] = '' - else: - # вывести часть строки не больше указанной ширины колонки - partstr = cols[q][:cols[q+1]] - # искать перевод строки с полученной части - brfind = wherenr.search(partstr) - # если это не последняя колонка - if q + 2 < len(cols): - # добавить разделитель между колонками - cellspacing = space - else: - # разделитель не нужен - cellspacing = nospace - - # если перевод строки найден, то - if brfind != None: - # для текущего вывода в колонку - # берем часть строки до перевода - partstr = partstr[:brfind.start()] - # остальная часть идет в остаток (без перевода) - cols[q] = cols[q][brfind.start()+1:] -# # если используется перевод каретки -# if brfind.group() == '\r': -# # то выравниваем по ширине колонки -# partstr = partstr.ljust(cols[q+1], ' ') -# else: -# # добавить отступы чтобы закончить колонку - partstr = partstr.ljust(cols[q+1], ' ') - # если взята часть строки - elif len(partstr) == cols[q+1] and partstr != cols[q]: - # если взята часть строки (разрыв в слове) - if cols[q][cols[q+1]] != ' ': - # ищем ближайший пробел справа - spacepos = partstr.rfind(' ') - # если пробел найти не удалось - if spacepos == -1: - # то на вывод идет часть строки равной ширине - cols[q] = cols[q][cols[q+1]:] - # если пробел найден - else: - # обрезаем строку до найденного пробела - partstr = partstr[:spacepos] - cols[q] = cols[q][spacepos+1:] - # если взята часть строки (разрыв на пробеле) - else: - # ислючить переносной пробел - cols[q] = cols[q][cols[q+1]+1:] - # выровнить текст по ширине колонки - partstr = partstr.ljust(cols[q+1], ' ') - #partstr = justify(partstr, cols[q+1]) - # остатки строки - else: - # добавить отступы чтобы закончить колонку - partstr = partstr.ljust(cols[q+1], ' ') - cols[q] = '' - - retstr+= partstr + cellspacing - - # остальную часть строки оставить на следующую итерацию - # если от строки что то осаталось - if len(cols[q]) > 0: - # отметить запуск еще одной итерации по параметрам - repeat = True - # следующая пара - q += 2 - # колонки отображены - retstr += "\n" - return retstr.encode('utf8') - -def columnStr(*cols): - '''Вывод данных по колонкам, причем, если данные не вмещаются в указнаную - колонку, то они переносятся на следующую строку в нужную колонку. В строку. - - Параметры: - cols множестово пар: текст, ширина колонки, причем, если у последней - колонки не указывать ширину, то она будет выведена вся. - - Возвращаемые параметры: - строка, которую можно использовать для вывода на экран - - Пример: columnWrite( "Some text", 10, "Next column", 20 ) - ''' - retstr = "" - # перевести кортеж в список, т.к. изменяется - cols = list(cols) - # перевести текст в юникод, заодно перевести числа в строку - for i in xrange(0,len(cols),2): - cols[i] = (str(cols[i])).decode('utf8') - - # флаг "есть еще текст для вывода" - repeat = True - while repeat: - # сбросить итератор на первый элемент - q = 0 - repeat = False - # пока не закончили перебирать параметры (перебираем по парам) - while q < len(cols): - # если это последний параметр, и для него не указана ширина - if q == len(cols)-1: - # выводим его полностью не смотря на ширину окна - retstr += cols[q] + " " - cols[q] = '' - else: - # вывести часть строки не больше указанной ширины колонки - retstr+=(cols[q][:cols[q+1]].ljust(cols[q+1])).encode('utf8') \ - + " " - # остальную часть строки оставить на следующую итерацию - cols[q] = cols[q][cols[q+1]:] - # если от строки что то осаталось - if len(cols[q]) > 0: - # отметить запуск еще одной итерации по параметрам - repeat = True - # следующая пара - q += 2 - # колонки отображены - retstr += "\n" - return retstr - -def columnWrite(*cols): - '''Вывод данных по колонкам, причем, если данные не вмещаются в указнаную - колонку, то они переносятся на следующую строку в нужную колонку. - - Параметры: - cols множестово пар: текст, ширина колонки, причем, если у последней - колонки не указывать ширину, то она будет выведена вся. - - Пример: columnWrite( "Some text", 10, "Next column", 20 ) - ''' - # перевести кортеж в список, т.к. изменяется - cols = list(cols) - # перевести текст в юникод, заодно перевести числа в строку - for i in xrange(0,len(cols),2): - cols[i] = (str(cols[i])).decode('utf8') - - # флаг "есть еще текст для вывода" - repeat = True - while repeat: - # сбросить итератор на первый элемент - q = 0 - repeat = False - # пока не закончили перебирать параметры (перебираем по парам) - while q < len(cols): - # если это последний параметр, и для него не указана ширина - if q == len(cols)-1: - # выводим его полностью не смотря на ширину окна - print cols[q].encode('utf8'), - cols[q] = '' - else: - # вывести часть строки не больше указанной ширины колонки - print (cols[q][:cols[q+1]].ljust(cols[q+1])).encode('utf8'), - # остальную часть строки оставить на следующую итерацию - cols[q] = cols[q][cols[q+1]:] - # если от строки что то осаталось - if len(cols[q]) > 0: - # отметить запуск еще одной итерации по параметрам - repeat = True - # следующая пара - q += 2 - # колонки отображены - print - -def justify(s,width): - '''Выровнить текст по ширине - - Параметры: - s выводимая строка - width ширина на которую надо выровнить строку - - Возвращаямые параметры: - Выровненная строка - ''' - # если подана строка без пробелов - прекратить обработку - if s.find(' ') == -1: - return s - pos = 0 - # переводим в юникод для правильного вычисления длины - try: - s = s.decode( 'utf-8' ) - # пропуск если это не utf-8 - except UnicodeEncodeError: - pass - # пока длина строки меньше указанной - while len(s) < width: - # находим очередной пробел - pos = s.find( ' ', pos ) - # если не найден искать сначала - if pos == -1: - pos = s.find(' ') - # вставить в позицию еще один пробел - s = s[:pos] +' ' +s[pos:] - # оставить удвоенный пробел - pos += 3 - # вернуть строку в utf8 если она пришла в utf8 - return s.encode('utf-8') - -def runOsCommand(cmd, inStr=None, ret_first=None, env_dict=None): - """Выполняет внешнюю программу - - Параметры: - cmd внешняя программа - inStr данные передаваемые программе на страндартный вход. - ret_first вернуть только первую строку - env_dict словарь переменных окружения - Возвращаемые параметры: - строка/строки которую выведет внешняя программа - Возвращает код возврата, stdout+stderr - """ - pipe = subprocess.Popen(cmd, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - env=env_dict, - close_fds=True, - shell=True) - fout, fin, ferr = (pipe.stdout, pipe.stdin, pipe.stderr) - # если есть данные на вход, передать их - if inStr: - fin.write(inStr) - fin.close() - # Код возврата - retcode = pipe.wait() - res = fout.readlines() - fout.close() - res += ferr.readlines() - ferr.close() - if res: - if len(res) == 1 or ret_first: - return retcode, res[0].strip() - else: - return retcode, res - return retcode, None - - -def genpassword(passlen=9): - '''Вернуть случайный пассворд указанной длины - - Параметры: - passlen длина пароля который нужно сгенерировать - - Возвращаемые параметры: - Сгенерированный пароль указанной длины - ''' - res=''.join([choice(string.ascii_letters+string.digits)\ - for i in xrange(passlen)]) - return res - -def fillstr(char, width): - '''Заполнить строку указанным числом символов. Псеводоним символ*кол-во''' - return str(char) * width - - #вернуть пути для запуска утилит -def getpathenv(): - bindir=['/sbin','/bin','/usr/sbin','/usr/bin'] - env=os.environ - if env and env.has_key('PATH'): - lpath=env['PATH'].split(":") - npath=[] - for dirname in bindir: - if os.path.exists(dirname) and dirname not in lpath: - npath.append(dirname) - lpath=npath+lpath - return ":".join(lpath) - -#класс для работы с установленными пакетами -class pakages: - #путь к директории установленнх пакетов - pkgdir="/var/db/pkg/" - #список установленных пакетов - pkglist={} - #Объект содержащий параметры пакета - class pakage(object): - #имя пакета с версией - fullname="" - #имя пакета - name="" - #версия - ver="" - #тип пакета в портежах - portdir="" - def __init__(self, **args): - for atname,atvalue in args.items(): - setattr(self,atname, atvalue) - - def __init__(self): - self.pkglist=self.__getpkglist() - - #разбить имя пакета на тип и имя - def __getpkgver(self, fname): - res=search('^(.+)\-([0-9]+.*)$',fname) - if res: - return res.groups() - else: - return (None,None) - - #собрать установленные в системе пакеты - def __getpkglist(self): - portageDirs=[] - instaledPkg={} - #проверим на существование директории с установленными пакетами - if os.path.exists(self.pkgdir): - #получим список типов пакетов - portageDirs=getdirlist(self.pkgdir) - if len(portageDirs)>0: - #обрабатываем содержимое каждого из типов - for portageDir in portageDirs: - pkgList=getdirlist(self.pkgdir+portageDir) - for pkg in pkgList: - fullname=pkg - pkgName,pkgVer= self.__getpkgver(pkg) - pobj=self.pakage(fullname=fullname, - name=pkgName, \ - ver=pkgVer,\ - portdir=portageDir) - fpkg=portageDir+"/"+pkgName - if instaledPkg.has_key(fpkg): - instaledPkg[fpkg].append(pobj) - else: - instaledPkg[fpkg]=[pobj] - return instaledPkg - - #разбить pkgname на составляющие имени пакета - def __partname(self, pkgname): - if not pkgname.strip(): - return False - res=search('^(.+\/)?(.+)',pkgname) - tname=None - if res.group(1): - tname=res.group(1) - if res.group(2): - res2=search('^(.+)(\-[0-9]+.+$)',res.group(2)) - if res2: - name=res2.group(1) - ver=res2.group(2) - else: - name=res.group(2) - ver=None - if res: - if name and name[-1:]=='-': - name=name[:-1] - if tname and tname[-1:]=='/': - tname=tname[:-1] - if ver and ver[0]=='-': - ver=ver[1:] - return [tname, name, ver] - - - #проверить установленн ли пакет - #isinstalled('dev-db/postgresql') - def isinstalled(self, pkgname): - res=self.getinstpkg(pkgname) - if len(res)>0: - return True - else: - return False - - #вернуть список объектов pakage() соответствующих pkgname - #getinstpkg('dev-db/postgresql') - #в случае отсутствия пакетов возвращает пустой список - def getinstpkg(self, pkgname): - pinfo=self.__partname(pkgname) - if pinfo: - ret=[] - if pinfo[0] and pinfo[1] and pinfo[2]: - if not self.pkglist.has_key(pinfo[0]+'/'+pinfo[1]): - return [] - fpkg=self.pkglist[pinfo[0]+'/'+pinfo[1]] - ret=[] - for i in fpkg: - if i.ver==pinfo[2]: - ret.append(i) - return ret - elif pinfo[0] and pinfo[1]: - if not self.pkglist.has_key(pinfo[0]+'/'+pinfo[1]): - return [] - return self.pkglist[pinfo[0]+'/'+pinfo[1]] - elif pinfo[1] and pinfo[2]: - for i in self.pkglist.keys(): - if search('^.+\/%s$'%(pinfo[1]),i): - for el in self.pkglist[i]: - if el.ver==pinfo[2]: - ret.append(el) - return ret - elif pinfo[1]: - for i in self.pkglist.keys(): - if search('^.+\/%s$'%(pinfo[1]),i): - ret+=self.pkglist[i] - return ret - return [] - - def getListPkg(self): - return self.pkglist - -def list2str(list): - '''Функция переводит список в строку''' - return '['+','.join(list)+']' - -def str2list(s): - '''Функция переводит строку в список''' - return s[1:-1].split(',') - -def dict2str(dict): - '''Функция перводит словарь в строку''' - return '{'+','.join(["%s:%s" % (str(k),str(v)) \ - for (k,v) in dict.items()])+'}' #: - -def str2dict(s): - '''Функция переводит строку в словарь''' - dict = {} - for i in s[1:-1].split(','): - k,v = i.split(':') - dict[k] = v - return dict - -def convertStrListDict(val): - '''Функция определеяется что на входе (строка, список, словарь) - и переводит их в строку и обратно''' - # если подан список - if type(val) == types.ListType: - return list2str(val) - # если подан словарь - elif type(val) == types.DictType: - return dict2str(val) - # если подана строка - else: - # если поданная строка содержит словарь - if ':' in val and '{' in val: - return str2dict(val) - # если поданная строка содержит список - elif ',' in val and '[' in val: - return str2list(val) - # если это просто строка - else: - return val - -def _toUNICODE(val): - """перевод текста в юникод""" - if type(val) == types.UnicodeType: - return val - else: - return str(val).decode('UTF-8') diff --git a/build/lib/calculate-lib/pym/cl_utils2.py b/build/lib/calculate-lib/pym/cl_utils2.py deleted file mode 100644 index 330e7dd..0000000 --- a/build/lib/calculate-lib/pym/cl_utils2.py +++ /dev/null @@ -1,563 +0,0 @@ -#-*- coding: utf-8 -*- - -# Copyright 2008-2010 Mir Calculate Ltd. http://www.calculate-linux.org -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import struct -import termios -import fcntl -import cl_utils - -import cl_profile -import ldap -class ldapFun(cl_profile._error): - '''Объект для работы с LDAP сервером - - подключение к серверу и поиск данных - ''' - def __init__(self, dnUser, password, host="localhost"): - self.conLdap = False - # Получаем соединение с LDAP - try: - self.conLdap = self.__ldapConnect(dnUser, password, host) - except ldap.LDAPError, e: - self.setError(e[0]['desc']) - - def __ldapConnect(self, dnUser, password, host): - """Соединение с LDAP сервером""" - conLdap = ldap.initialize('ldap://%s'%host) - conLdap.simple_bind_s(dnUser, password) - return conLdap - - def ldapSearch(self,baseDN, searchScope, searchFilter, retrieveAttributes): - try: - ldap_result_id = self.conLdap.search(baseDN, searchScope, - searchFilter, - retrieveAttributes) - result_set = [] - while 1: - result_type, result_data = self.conLdap.result(ldap_result_id, - 0) - if (result_data == []): - break - else: - if result_type == ldap.RES_SEARCH_ENTRY: - result_set.append(result_data) - except ldap.NO_SUCH_OBJECT: - return [] - except: - return False - return result_set - -pcs = cl_utils.prettyColumnStr - -class cl_help: - """Объект для работы со справкой, и обработкой параметров. - - Конструктор __init__ должен определить следующие переменные: - - self.chapter список разделов справки, каждый элементы состоит из - имени раздела, флаг видимый/скрытый, кол-во переводов строк - после названия раздела, количество строк после раздела, - тип раздела - Пример: [("Copyright",False,0,2),"options"] - self.relService словарь связей сервисов и действующих опций - ключ - название сервиса, значение - список отображаемых - разделов отмеченных как "options" - Пример: {"samba":[_("Common options"), - _("Service Samba options")]} - self.relOptions словарь связей длинных опций помощи и выводимых разделов - помощи с опциями - ключ - параметр справки, значение список отображаемых - разделов справки - Пример: {"help-ldap":[_("Common options"), - _("Service LDAP options)]} - self.progName словарь имена используемых программ и их номера для - доступа к переменным - Пример: {'cl-groupadd':0, 'cl-groupdel':1} - self.data список данных для справки, каждый элемент словарь: - progAccess: список номеров программ отображающих - Пример: {'progAccess':(0,), - 'shortOption':"g", - 'longOption':"gid", - 'optVal':"GID", - 'helpChapter':_("Options"), - 'help':_("use GID for the new group") - }, - после заполнения параметров необходимо выполнить - self._cl_help__setParamHelp() для заполнения справки - - """ - def __init__(self, cmdName): - # ширина консоли взята за 80 - # -1 чтобы компенсировать расстрояние между колонками - self.consolewidth = 79 - self.column_width = 32 - self.cmdName = cmdName - #короткие опции командной строки - self.shortOpt = [] - #длинные опции командной строки - self.longOpt = [] - # массив разделов (заполняется в __setParamHelp) - self.chapterBloc = [] - #optEnd = "" - #if "user" in self.cmdName and not "mod" in self.cmdName: - #optEnd = _("user") - #elif "group" in self.cmdName and not "mod" in self.cmdName: - #optEnd = _("group") - #self.__setParamHelp() - - def getChapterNumber(self,NameChapter): - """Получить номер раздела по имени""" - num = 0 - for i in self.chapter: - if i[0] == NameChapter: - return num - num += 1 - return False - - def __setParamHelp(self): - """Внутренняя функция формирования справки по данным - - Перебирает все элементы списка data, проверяет их на доступность - данной программы, разбирает опции на среди data и формирует - для по ним справку. - """ - # сформировать нужное количество блоков раздела - self.chapterBloc = [""]*len(self.chapter) - # - sp = {} - i = 0 - # перебираем все элементы справки собираем элементы опции - # так же формируем разделы не опции - for par in self.data: - # перебираем только те опции, которые принадлежат команде - if self.access(par): - # есть короткая (возможно есть и длинная) - if par.has_key("shortOption"): - sp[par["shortOption"]+":"+par["helpChapter"]] = i - # есть только длинная опция - elif par.has_key("longOption"): - sp[par["longOption"]+":"+par["helpChapter"]] = i - # формирование разделов не опций - else: - helpTxt = par['help'] - numChapter = self.getChapterNumber(par['helpChapter']) - self.addChapterHelp(numChapter,helpTxt) - i += 1 - # перебираем все "собранные" опции - # опции перебираются по порядку в списке date - # для сортировки по ключам следует применить код: - # for index in sorted(sp.keys()): - # par = self.data[sp[index]] - for index in sorted(sp.values()): - par = self.data[index] - numChapter = self.getChapterNumber(par['helpChapter']) - # если есть и короткая и длинная - if "shortOption" in par and "longOption" in par: - paraminfo = "-%s, --%s "%(par["shortOption"],par["longOption"]) - # если есть только короткая - elif "shortOption" in par: - paraminfo = "-%s "%par["shortOption"] - # если только длинная - else: - paraminfo = "--%s "%par["longOption"] - # если указан параметр для опции - if "optVal" in par: - optVal = par["optVal"] - else: - optVal = "" - - # вывод вида: " [-o, ][--option] [PARAM]" "helpstring" - helpTxt = pcs(" "+paraminfo+optVal, self.column_width, \ - par['help'], self.consolewidth-self.column_width) - # добавить строку в нужный раздел - self.addChapterHelp(numChapter,helpTxt) - - def getHelp(self, optionsChapters=False): - """Выдать справку. - - Выдает справку в случае если указан optionsChapters, то фильтрует по - типу разделов. - - Параметры: - optionsChapters Flase или список опциональных разделов для - отображения - - Возвращаемые параметры: - Строка со справкой. - """ - # Выдать справку - help = "" - # перебираем все элементы справочных блоков - iterChapterBloc = iter(self.chapterBloc) - # перебираем все разделы по параметрам - for (nameChapter, visibleChapter, beforeStrChapter, \ - afterStrChapter, typeChapter) in self.chapter: - # получаем следующий блок (т.о. textChapterBloc соответ, chapter) - textChapterBloc = iterChapterBloc.next() - # если тип раздела опциональный - if optionsChapters and typeChapter=="options": - # проверяем нужно ли его отображать - if not (nameChapter in optionsChapters): - continue - bef = "\n"*beforeStrChapter - aft = "\n"*afterStrChapter - # если блок не пустой и раздел отображаемый - if len(textChapterBloc) > 0: - if visibleChapter: - help += nameChapter + ": " + bef - help += textChapterBloc + aft - help = help.rstrip()+"\n" - return help - - def addChapterHelp(self, numChapter, helpTxt): - """Добавить в раздел помощи numChapteк тектстовую строку helpTxt - - Параметры: - numChapter номер раздела в который нужно добавить данные справки - helpTxt строка, содержащая данные - """ - self.chapterBloc[numChapter] += helpTxt - return True - - def addData(self,dataHash): - # На будущее (добавляет опции) - self.data.append(dataHash) - return True - - def handleCheckAccess(self,dataHash): - """Замещаемый дополнительный обработчик проверки - доступности опции. - - Входные параметры: - dataHash элементы списка данных справки (self.data) - """ - return True - - def access(self,dataHash): - """Доступна ли опция вызывающей программе - - Параметры: - dataHash словарь элемент типа self.data - - Возвращаемые параметры: - True/False доступна/недоступна - """ - # доступна ли опция вызывающей программе - # опция без progAccess доступна - numProg = self.progName[self.cmdName] - if 'progAccess' in dataHash: - if numProg in dataHash['progAccess']: - # вызов дополнительной проверки доступа к опции - return self.handleCheckAccess(dataHash) - else: - return False - else: - # вызов дополнительной проверки доступа к опции - return self.handleCheckAccess(dataHash) - - def getTypeChapter(self, nameChapter): - """Получить тип раздела по его имени - - Параметры: - nameChapter название раздела - - Возвращаемые параметры: - строка тип раздела - Flase(Boolean) такой раздел отсутствует - """ - # фильтруем список по имени раздела, помещаем в список тип раздела - filtered = [typeChapter for name, na, na, na, typeChapter \ - in self.chapter if name == nameChapter] - # если среди фильтрованных есть хоть один элемент - if len(filtered) > 0: - # возвращаем - он запрашиваемый - return filtered[0] - else: - # такой раздел отсутствует - return False - - def clearAllOpt(self): - """Очистить все опции, полученные посредством getAllOpt""" - if len(self.shortOpt) > 0: - self.shortOpt = [] - if len(self.longOpt) > 0: - self.longOpt = [] - return True - - def getAllOpt(self,typeOpt="all", optionsChapters=False): - """Получить все доступные опции - - Параметры: - typeOpt 'short'/'long'/'all', вернуть короткие или длинные - опции или все (возвращаются кортежем) - optionsChapters фильтр для опций по типам разделов (список,кортеж) - - Возвращаемые параметры: - строка коротки или список строк длинных опций ('hb:c:wg:G:k:ms:u:') - """ - # Выдать все действующие опции - if typeOpt=="short" or typeOpt=="all": - if len(self.shortOpt) == 0: - for par in self.data: - if optionsChapters and\ - self.getTypeChapter(par['helpChapter'])=="options": - if not (par['helpChapter'] in optionsChapters): - continue - if par.has_key("shortOption") and self.access(par): - if par.has_key("optVal"): - self.shortOpt.append(par["shortOption"]+':') - else: - self.shortOpt.append(par["shortOption"]) - if typeOpt=="long" or typeOpt=="all": - if len(self.longOpt) == 0: - for par in self.data: - if optionsChapters and\ - self.getTypeChapter(par['helpChapter'])=="options": - #print par["longOption"] - if not (par['helpChapter'] in optionsChapters): - continue - if par.has_key("longOption") and self.access(par): - if par.has_key("optVal"): - self.longOpt.append(par["longOption"]+'=') - else: - self.longOpt.append(par["longOption"]) - if typeOpt=="short": - return "".join(self.shortOpt) - elif typeOpt=="long": - return self.longOpt - elif typeOpt=="all": - return ("".join(self.shortOpt),self.longOpt) - - def getShortOpt(self,option): - """Из любой опции получить короткую опцию. - - Фильтрация также происходит и по названию команды. - - Параметры: - option запрашиваемая опция - - Возвращаемые параметры: - короткая опция, если же для длинной опции нет короткой, возвращается - пустая строка. - """ - # Из любой опции получаем короткую опцию - for par in self.data: - if par.has_key("shortOption") and self.access(par): - if (par.has_key("longOption") and\ - par["longOption"] == option) or \ - par["shortOption"] == option: - return par["shortOption"] - break - return "" - -class cl_smartcon(object): - - def getconsolewidth(self): - """Получить ширину текущей консоли""" - s = struct.pack("HHHH", 0, 0, 0, 0) - fd_stdout = sys.stdout.fileno() - try: - x = fcntl.ioctl(fd_stdout, termios.TIOCGWINSZ, s) - except IOError: - # если ошибка то ширина 80 символов - return 80 - #(rows, cols, x pixels, y pixels) - return struct.unpack("HHHH", x)[1] - - def printRight(self, offsetLeft, offsetRight): - """Добавляет необходимое количество пробелов: - - количество пробелов = (ширина консоли - offsetLeft - offsetRight) - """ - cols = self.getconsolewidth() - for i in range(cols - offsetLeft - offsetRight): - sys.stdout.write(" ") - - def colorPrint(self,attr,fg,bg,string): - """Раскрашивает выводимое сообщение - - Параметры: - attr - это атрибут - fg - цвет символа - bg - цвет фона - - в случае если параметр равен "" то он не изменяется - - attr может принимать следующие значения: - 0 сбросить все атрибуты (вернуться в нормальный режим) - 1 яркий (обычно включает толстый шрифт) - 2 тусклый - 3 подчёркнутый - 5 мигающий - 7 реверсный - 8 невидимый - - fg может принимать следующие значения: - 30 чёрный - 31 красный - 32 зелёный - 33 жёлтый - 34 синий - 35 фиолетовый - 36 голубой - 37 белый - - bg может принимать следующие значения: - 40 чёрный - 41 красный - 42 зелёный - 43 жёлтый - 44 синий - 45 фиолетовый - 46 голубой - 47 белый - """ - lst = [] - if attr: - lst.append(attr) - if fg: - lst.append(fg) - if bg: - lst.append(bg) - sys.stdout.write("\033[%sm%s\033[0m" %(";".join(lst),string)) - - def redBrightPrint(self, string): - """Печатает яркое красное сообщение""" - self.colorPrint("1","31","",string) - - def greenBrightPrint(self, string): - """Печатает яркое зеленое сообщение""" - self.colorPrint("1","32","",string) - - def yellowBrightPrint(self, string): - """Печатает яркое желтое сообщение""" - self.colorPrint("1","33","",string) - - def blueBrightPrint(self, string): - """Печатает яркое cинее сообщение""" - self.colorPrint("1","34","",string) - - def lenString(self, string): - """Получаем длинну строки""" - stringUnicode = cl_utils._toUNICODE(string) - lenString = len(stringUnicode) - return lenString - - - def defaultPrint(self, string): - sys.stdout.write(string) - sys.stdout.flush() - - def printLine(self, argL, argR, offsetL=0, printBR=True): - """Печатает справа и слева консоли цветные сообщения""" - #Допустимые цвета - colorDict = {\ - # цвет по умолчанию - '':self.defaultPrint, - # ярко зеленый - 'greenBr':self.greenBrightPrint, - # ярко голубой - 'blueBr':self.blueBrightPrint, - # ярко красный - 'redBr':self.redBrightPrint, - # ярко желтый - 'yellowBr':self.yellowBrightPrint, - } - # cмещение от левого края консоли - #offsetL = 0 - for color,leftString in argL: - offsetL += self.lenString(leftString) - if colorDict.has_key(color): - # печатаем и считаем смещение - colorDict[color](leftString) - else: - colorDict[''](leftString) - # cмещение от правого края консоли - offsetR = 0 - for color,rightString in argR: - offsetR += self.lenString(rightString) - # Добавляем пробелы - if offsetR: - self.printRight(offsetL, offsetR) - for color,rightString in argR: - if colorDict.has_key(color): - # печатаем и считаем смещение - colorDict[color](rightString) - else: - colorDict[''](rightString) - if printBR: - print "" - - def printNotOK(self, string, offsetL=0, printBR=True): - """Вывод на печать в случае сбоя""" - self.printLine((('greenBr',' * '), - ('',string), - ), - (('blueBr','['), - ('redBr',' !! '), - ('blueBr',']'), - ), offsetL, printBR) - - def printOnlyNotOK(self, string, offsetL=0, printBR=True): - """Вывод на печать в случае сбоя""" - self.printLine((('', string),), - (('blueBr','['), - ('redBr',' !! '), - ('blueBr',']'), - ), offsetL, printBR) - - def printOK(self, string, offsetL=0, printBR=True): - """Вывод на печать в случае успеха""" - self.printLine((('greenBr',' * '), - ('',string), - ), - (('blueBr','['), - ('greenBr',' ok '), - ('blueBr',']'), - ), offsetL, printBR) - - def printOnlyOK(self, string, offsetL=0, printBR=True): - """Вывод на печать в случае успеха""" - self.printLine((('',string),), - (('blueBr','['), - ('greenBr',' ok '), - ('blueBr',']'), - ), offsetL, printBR) - - def printWARNING(self, string, offsetL=0, printBR=True): - """Вывод на печать предупреждения""" - self.printLine((('yellowBr',' * '), - ('',string), - ), - (('',''), - ), offsetL, printBR) - - def printERROR(self, string, offsetL=0, printBR=True): - """Вывод на печать предупреждения""" - self.printLine((('redBr',' * '), - ('',string), - ), - (('',''), - ), offsetL, printBR) - - def printSUCCESS(self, string, offsetL=0, printBR=True): - """Вывод на печать в случае успеха без [ok] справа""" - self.printLine((('greenBr',' * '), - ('',string), - ), - (('',''), - ), offsetL, printBR) diff --git a/build/lib/calculate-lib/pym/cl_vars.py b/build/lib/calculate-lib/pym/cl_vars.py deleted file mode 100644 index be174fd..0000000 --- a/build/lib/calculate-lib/pym/cl_vars.py +++ /dev/null @@ -1,91 +0,0 @@ -#-*- coding: utf-8 -*- - -# Copyright 2008-2010 Mir Calculate Ltd. http://www.calculate-linux.org -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -#Допустимые ключи значений -# mode - режим переменной r-не переназначается из командной строки, -# w-переназначается из командной строки -# type - тип переменной состоит из двух элементов(что это и для чего -# это) -# value - значение переменной - -class Data: - - # имя компьютера - os_net_hostname = {'mode':"w"} - # разрешенные сети - os_net_allow ={} - # ip на всех интерфейсах - os_net_ip ={} - - #короткое название системы (CLD) - os_linux_shortname={} - - #домен - os_net_domain = {'mode':"w"} - - # Пути к ini файлам - cl_env_path = {'value':['/var/calculate/remote/calculate.env', - '/var/calculate/calculate.env', - '/etc/calculate/calculate.env']} - - # локаль (прим: ru_RU.UTF-8) - os_locale_locale = {} - # язык (прим: ru_RU) - os_locale_lang = {} - # язык (прим: ru) - os_locale_language = {} - - # раскладка клавиатуры для X - os_locale_xkb = {} - - # названия используемых раскладок клавиатуры для X - os_locale_xkbname = {} - - # архитектура компьютера (i686,x86_64) - os_arch_machine = {} - - #проход при наложении профилей 1,2,3,4,5 и.т д - cl_pass_step = {'mode':"w"} - - # обрабатываемый файл профиля - cl_pass_file = {'mode':"w"} - - # корневой раздел файловой системы - os_root_dev = {} - - # тип носителя (ram, hdd, usb-hdd, livecd) - os_root_type = {} - - # полное название системы - os_linux_name = {} - - # постфикс к названию системы - os_linux_subname = {} - - # название виртуальной машины (virtualbox, vmware, qemu) - hr_virtual = {} - - # версия системы - os_linux_ver = {} - - # Тип профиля - cl_pass_type = {'mode':"w"} - - # Действие программы - cl_pass_run = {'mode':"w"} - - #Логин пользователя - ur_login = {'mode':"w"}