diff --git a/pym/cl_datavars.py b/pym/cl_datavars.py index 7bf34ab..3e112de 100644 --- a/pym/cl_datavars.py +++ b/pym/cl_datavars.py @@ -370,7 +370,7 @@ storage of variables templates")%location) Возвращаемые значение: True запись успешна - False запись не удалсь + False запись не удалaсь ''' # получаем путь до ini файла name_calculate_ini = self.__getPathCalculateIni(location) @@ -399,7 +399,7 @@ storage of variables templates")%location) Возвращаемые значение: True удалено успешна - False удаление не удалсь + False удаление не удалось ''' # получаем путь до ini файла name_calculate_ini = self.__getPathCalculateIni(location) @@ -422,7 +422,7 @@ storage of variables templates")%location) else: return False - def Write(self, vname, val, force=False, location='default',header=False): + def Write(self,vname,val=None,force=False,location='default',header=False): '''Установить и записать значение переменной в ini файл Параметры: @@ -432,11 +432,13 @@ storage of variables templates")%location) location расположение ini файла ('default', 'local', 'remote') header раздел ini файла ('client', 'server', 'main') ''' - if self.__Set(vname, val, force)!= False: - if not val.strip(): - self.__deleteVarValue(vname, location, header) - if self.__writeVarValue(vname, val, location, header): - return True + if val is None: + val = self.Get(vname) + else: + if self.__Set(vname, val, force) is False: + return False + if self.__writeVarValue(vname, val, location, header): + return True return False def Delete(self, vname, location='default', header=False): @@ -637,10 +639,89 @@ storage of variables templates")%location) p_val=var[i].value if var[i].official: continue - #print ( i, mlen_name, var[i].mode.lower(), mlen_mode, p_val) columnWrite( i, mlen_name, var[i].mode.lower(), mlen_mode, p_val) cl_overriding.printSUCCESS(br) + def GetList(self, nameVar, spl=","): + """Получить значение переменной в виде списка + + если значение переменной: + строка - разделяем spl (по умолчанию ',') и выводим список, + кроме строки - выводим как есть + """ + value = self.Get(nameVar) + if type(value) in (str, unicode): + return map(lambda x: x.strip(), value.split(spl)) + return value + + def SetList(self, nameVar, value, force=False, spl=","): + """Записать список в переменную в виде строки, элементы разделены spl + + если значение переменной: + список - объединяем через spl (по умолчанию ',') + список в строку, записываем + кроме списка - записываем + """ + if type(value) == list: + strValue = ",".join(value) + else: + strValue = value + return self.Set(nameVar, strValue, force) + + def WriteList(self, vname, val=None, force=False, + location='default', header=False, spl=","): + """Записать список в переменную в виде строки и записать в ini файл + (элементы разделены spl) + + если значение переменной: + список - объединяем через spl (по умолчанию ',') + список в строку, записываем + кроме списка - записываем + """ + if val is None: + val = self.Get(vname) + if type(val) == list: + strValue = ",".join(val) + else: + strValue = val + if not strValue and type(strValue) in (str, unicode): + if self.__Set(vname, strValue, force) is False: + return False + if not self.__deleteVarValue(vname, location, header): + return False + return True + return self.Write(vname, strValue, force, location, header) + + def AppendToList(self, nameVar, value, force=False, spl=",", + unique=True): + """Добавление в переменную со строковым значением элемента + + Разделитель элементов spl (по умолчанию ',') + """ + listValues = self.GetList(nameVar, spl) + if type(listValues) == list: + listValues = filter(lambda x: x, listValues) + if unique: + if not value in listValues: + listValues.append(value) + else: + listValues.append(value) + return self.SetList(nameVar, listValues, force, spl) + + def RemoveToList(self, nameVar, value, force=False, spl=","): + """Удаление из переменной со строковым значением элементов + + со значением value + + Разделитель элементов spl (по умолчанию ',') + """ + listValues = self.GetList(nameVar, spl) + if type(listValues) == list: + listValues = filter(lambda x: x, listValues) + listValues = filter(lambda x: x!=value, listValues) + self.SetList(nameVar, listValues, force, spl) + return True + class glob_attr: """Глобальные аттрибуты для методов заполнения переменных""" diff --git a/pym/cl_template.py b/pym/cl_template.py index 285286f..cda2aac 100644 --- a/pym/cl_template.py +++ b/pym/cl_template.py @@ -4446,7 +4446,7 @@ re.M|re.S) tmpTemplate = self.textTemplate + "\n" + self.textConfig if objHeadNew.execStr: self.textConfig = objHeadNew.execStr + title + tmpTemplate - elif objHeadOld.execStr: + elif objHeadOld and objHeadOld.execStr: self.textConfig = objHeadOld.execStr + title + tmpTemplate else: self.textConfig = title + tmpTemplate @@ -4468,7 +4468,7 @@ re.M|re.S) tmpTemplate = self.textConfig + "\n" + self.textTemplate if objHeadNew.execStr: self.textConfig = objHeadNew.execStr + title + tmpTemplate - elif objHeadOld.execStr: + elif objHeadOld and objHeadOld.execStr: self.textConfig = objHeadOld.execStr + title + tmpTemplate else: self.textConfig = title + tmpTemplate diff --git a/pym/cl_utils.py b/pym/cl_utils.py index 1ddeac0..ceceb8c 100644 --- a/pym/cl_utils.py +++ b/pym/cl_utils.py @@ -475,3 +475,23 @@ def getTupleVersion(ver): vers = toTuple(vers) revision = toTuple(revision or "r0") return [vers,revision] + +def appendProgramToEnvFile(nameProg, objVar): + """Append name program to variable cl-merges and + + save /etc/calculate/calculate.env """ + if not objVar.AppendToList("cl_merges", nameProg, force=True): + return False + if not objVar.WriteList("cl_merges", force=True): + return False + return True + +def removeProgramToEnvFile(nameProg, objVar): + """Remove name program from variable cl-merges and save + + /etc/calculate/calculate.env""" + if not objVar.RemoveToList("cl_merges", nameProg, force=True): + return False + if not objVar.WriteList("cl_merges", force=True): + return False + return True diff --git a/pym/cl_vars.py b/pym/cl_vars.py index 8e7cbd4..194f664 100644 --- a/pym/cl_vars.py +++ b/pym/cl_vars.py @@ -134,9 +134,8 @@ class Data: cl_chroot_path = {'mode':"r", 'value':"/"} # program action - # user - user profile generation - # install / uninstall - install or uninstall program - cl_pass_action = {} + # install, uninstall, merge, domain, undomain, system, desktop + cl_action = {} # program state # specifies addition to cl_pass_action for needing @@ -158,13 +157,13 @@ class Data: # hasn't belong function # (package_name == value of cl_belong_pkg) cl_belong_pkg = {'mode':'r', 'official':True} - + # vertical resolution for X server os_x11_height = {'mode':"w"} # horizontal resolution for X server os_x11_width = {'mode':"w"} - + # the nearest standard size of image to current screen resolution os_x11_standart = {} @@ -180,5 +179,5 @@ class Data: # on/off composite mode os_x11_composite = {} - # on/off apply templates - cl_templates_set = {'mode':"w", 'value':"off"} + # programs have templates setup + cl_merges = {} diff --git a/pym/update_config/cl_update_config.py b/pym/update_config/cl_update_config.py index b584a80..63b0717 100644 --- a/pym/update_config/cl_update_config.py +++ b/pym/update_config/cl_update_config.py @@ -14,7 +14,6 @@ # See the License for the specific language governing permissions and # limitations under the License. - __version__ = "2.2.0.0" __app__ = "calculate-lib" @@ -35,16 +34,6 @@ tr.setLanguage(sys.modules[__name__]) cl_overriding.printERROR = lambda x:filter(lambda y:color_print().printERROR(y), str(x).splitlines()) -packagePath = "/usr/lib/calculate-2.2" -for path in os.listdir(packagePath): - realPath = os.path.join(packagePath,path) - if os.path.isdir(realPath): - pymPath = os.path.join(realPath,"pym") - if len(filter(lambda x:x.startswith("cl_vars_") and\ - x.endswith(".py") or x.startswith("cl_fill_") and\ - x.endswith(".py"), os.listdir(pymPath)))==2: - sys.path.insert(0, os.path.abspath(pymPath)) - class writeLog: """Класс логгирования""" logger = log("apply-templates", @@ -88,69 +77,41 @@ class color_print(old_color_print, writeLog): class DataVarsObject(cl_datavars.DataVars): """Класс переменных для десктопа""" - def __init__(self, section): + packagePath = "/usr/lib/calculate-2.2" + + def __init__(self, nameProgram): cl_datavars.DataVars.__init__(self) - self.section=section + self.nameProgram = nameProgram + + def findPathVars(self): + pymPath = os.path.join(self.packagePath, self.nameProgram, "pym") + if os.path.isdir(pymPath) and\ + len(filter(lambda x:x.startswith("cl_vars_") and\ + x.endswith(".py") or x.startswith("cl_fill_") and\ + x.endswith(".py"), os.listdir(pymPath)))==2: + importPath = os.path.abspath(pymPath) + if not importPath in sys.path: + sys.path.insert(0, importPath) + return True + return False def importDataObject(self, **args): '''Заполнить конфигурацию переменных, для десктопа''' - # Имя секции в calculate.env - #envSection = "calculate-desktop" # заполнить переменные окружения алгоритмом по умолнанию - self.importData(self.section, ('cl_vars_%s' %self.section, - 'cl_fill_%s' %self.section)) + sectName = self.nameProgram.rpartition("-")[2] + self.importData(sectName, ('cl_vars_%s' %sectName, + 'cl_fill_%s' %sectName)) self.flIniFile() class shareUpdateConfigs(color_print, writeLog): """Общие методы для обновления конфигурационных файлов""" - patternBelongDir = re.compile("belong\(\)") - patternBelongName = re.compile("belong\(([^\(\)]+)\)") - patternSect = re.compile("^\s*\[([^\[\]]+)\]\s*") - templatePaths = ['/usr/share/calculate/templates', - '/var/calculate/templates', - '/var/calculate/remote/templates'] - firstEnvFile = "/etc/calculate/calculate2.env" - reCleanVer = re.compile("\d+\.?\d*\.?\d*") - def _isApplyTemplateDir(self, scanDir, nameProgram, flagSkipDesktop=True, - flagDir=False): - """Есть ли шаблоны в директории scanDir для пакета nameProgram - - выдает True, False - """ - ret = False - if flagDir or stat.S_ISDIR(os.stat(scanDir)[stat.ST_MODE]): - for fileOrDir in sorted(os.listdir(scanDir)): - absPath = os.path.join(scanDir,fileOrDir) - statInfo = os.stat(absPath)[stat.ST_MODE] - if stat.S_ISREG(statInfo): - textFile = open(absPath).read() - if flagSkipDesktop and\ - "cl_pass_action==desktop" in textFile: - break - if self.patternBelongDir.search(textFile): - ret = os.path.basename(os.path.dirname(absPath)) - if ret == nameProgram: - ret = True - break - else: - ret = False - else: - searchObj = self.patternBelongName.search(textFile) - if searchObj: - ret = searchObj.group(1) - if ret == nameProgram: - ret = True - break - else: - ret = False - elif stat.S_ISDIR(statInfo): - ret = self._isApplyTemplateDir(absPath, nameProgram, True, - flagSkipDesktop) - if ret: - break - return ret + def getPrograms(self): + """Получаем установленные программы работающие с шаблонами""" + clVars = cl_datavars.DataVars() + clVars.flIniFile() + return clVars.GetList("cl_merges") class updateUserConfigs(shareUpdateConfigs): """Обновление пользовательских конфигурационных файлов""" @@ -172,25 +133,6 @@ class updateUserConfigs(shareUpdateConfigs): return False return xUsers - def _getUserTemplateDirs(self, scanDir, userTemplDirs=[], flagDir=False): - """Находит в директории scanDir директории шаблонов для пользователя - - выдает найденные директории. - """ - if flagDir or stat.S_ISDIR(os.stat(scanDir)[stat.ST_MODE]): - for fileOrDir in sorted(os.listdir(scanDir)): - absPath = os.path.join(scanDir,fileOrDir) - statInfo = os.stat(absPath)[stat.ST_MODE] - if stat.S_ISREG(statInfo): - textFile = open(absPath).read() - if "cl_pass_action==desktop" in textFile: - userTemplDirs.append(scanDir) - break - elif stat.S_ISDIR(statInfo): - self._getUserTemplateDirs(absPath, userTemplDirs, True) - return userTemplDirs - - def updateConfig(self, nameProgram, category, version, xUsers): """Обновление конфигурационных файлов у пользователей""" cleanVer = self.reCleanVer.search(version) @@ -198,57 +140,43 @@ class updateUserConfigs(shareUpdateConfigs): version = cleanVer.group() self.logger.info(_("Package %s") %nameProgram) self.logger.info(_("Update desktop configuration files")) - if not os.path.exists(self.firstEnvFile): - self.printWARNING(_("File '%s' does not exist")%self.firstEnvFile) - return True - if not os.access(self.firstEnvFile, os.R_OK): - self.printWARNING(_("Permission denied: '%s'")%self.firstEnvFile) - return True - sectionsWork = [] - for line in open(self.firstEnvFile).readlines(): - sRet = self.patternSect.search(line) - if sRet: - sectionsWork.append(sRet.group(1)) - sectName = "desktop" + # Программы используемые для наложения шаблонов + mergePrograms = self.getPrograms() + if "calculate-desktop" in mergePrograms: + mergePrograms = ["calculate-desktop"] + else: + mergePrograms = [] dictPakkages = {} - # Если установлен calculate-desktop - if sectName in sectionsWork: - section = "" - for templatePath in self.templatePaths: - fullPath = os.path.join(templatePath,sectName) - if os.path.isdir(fullPath): - for foundUserPath in self._getUserTemplateDirs(fullPath): - if self._isApplyTemplateDir(foundUserPath, nameProgram, - flagSkipDesktop=False): - section = sectName - break - if section: - # Добавление условия, что программа category/nameProgram - # установлена - cl_template.templateFunction.installProg.update(\ + # Добавление условия, что программа category/nameProgram + # установлена + cl_template.templateFunction.installProg.update(\ {"%s/%s"%(category,nameProgram):[version], "%s"%(nameProgram):[version]}) - for userName in xUsers: - clVars = DataVarsObject(section) - clVars.importDataObject() - clVars.Set("ur_login", userName, True) - clVars.Set("cl_pass_action", section, True) - clVars.Set("cl_belong_pkg", nameProgram, True) - clTempl = cl_template.template(clVars) - dirsFiles = clTempl.applyTemplates() - if dirsFiles is False: - self.printERROR(\ - _("Error using templates for the user %s")%userName) - for errMess in clTempl.getError().splitlines(): - self.printERROR(errMess) - return False - if dirsFiles and dirsFiles[1]: - nameAndVerPkg = clVars.Get("cl_name")+"-"+\ - clVars.Get("cl_ver") - if not nameAndVerPkg in dictPakkages: - dictPakkages[nameAndVerPkg] = [] - dictPakkages[nameAndVerPkg].append((userName, - sorted(list(set(dirsFiles[1]))))) + for mergeProgram in mergePrograms: + for userName in xUsers: + clVars = DataVarsObject(mergeProgram) + if not clVars.findPathVars(): + continue + clVars.importDataObject() + clVars.Set("ur_login", userName, True) + clVars.Set("cl_action", "desktop", True) + clVars.Set("cl_belong_pkg", nameProgram, True) + clTempl = cl_template.template(clVars) + dirsFiles = clTempl.applyTemplates() + if dirsFiles is False: + self.printERROR(\ + _("Error using templates for the user %s")\ + %userName) + for errMess in clTempl.getError().splitlines(): + self.printERROR(errMess) + return False + if dirsFiles and dirsFiles[1]: + nameAndVerPkg = clVars.Get("cl_name")+"-"+\ + clVars.Get("cl_ver") + if not nameAndVerPkg in dictPakkages: + dictPakkages[nameAndVerPkg] = [] + dictPakkages[nameAndVerPkg].append((userName, + sorted(list(set(dirsFiles[1]))))) if dictPakkages: for calcPkg in dictPakkages: self.printWARNING(_("Package %s has changed files")\ @@ -292,37 +220,21 @@ class updateSystemConfigs(shareUpdateConfigs): if not os.path.exists(configPath): self.printERROR(_("Path '%s' does not exist")%configPath) return False - if not os.path.exists(self.firstEnvFile): - self.printWARNING(_("File '%s' does not exist")%self.firstEnvFile) - return True - if not os.access(self.firstEnvFile, os.R_OK): - self.printWARNING(_("Permission denied: '%s'")%self.firstEnvFile) - return True - sections = [] - sectionsWork = [] - for line in open(self.firstEnvFile).readlines(): - sRet = self.patternSect.search(line) - if sRet: - sectionsWork.append(sRet.group(1)) - #sectionsWork = os.listdir(self.templatePaths[0]) - for sectName in sectionsWork: - for templatePath in self.templatePaths: - fullPath = os.path.join(templatePath,sectName) - if not sectName in sections and os.path.isdir(fullPath): - if self._isApplyTemplateDir(fullPath, nameProgram): - sections.append(sectName) - + # Программы используемые для наложения шаблонов + mergePrograms = self.getPrograms() dictPakkages = {} - if sections: - # Добавление условия, что программа category/nameProgram установлена - cl_template.templateFunction.installProg.update(\ - {"%s/%s"%(category,nameProgram):[version], - "%s"%(nameProgram):[version]}) - for sectName in sections: - clVars = DataVarsObject(sectName) + # Добавление условия, что программа category/nameProgram установлена + cl_template.templateFunction.installProg.update(\ + {"%s/%s"%(category,nameProgram):[version], + "%s"%(nameProgram):[version]}) + for mergeProgram in mergePrograms: + clVars = DataVarsObject(mergeProgram) + if not clVars.findPathVars(): + continue clVars.importDataObject() - clVars.Set("cl_root_path",configPath, True) - clVars.Set("cl_belong_pkg",nameProgram, True) + clVars.Set("cl_root_path", configPath, True) + clVars.Set("cl_belong_pkg", nameProgram, True) + clVars.Set("cl_action", 'merge', True) clTempl = cl_template.template(clVars) dirsFiles = clTempl.applyTemplates() nameAndVerPkg = clVars.Get("cl_name")+"-"+clVars.Get("cl_ver")