#-*- 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 sys import cl_utils from cl_lang import lang from cl_template import iniParser from cl_string import columnWrite import cl_overriding # Перевод модуля на другой язык tr = lang() tr.setLocalDomain('cl_lib') tr.setLanguage(sys.modules[__name__]) class var: '''Объект "Переменная окружения"''' # название сервиса которому принадлежит переменная #(Main, Builder, Client итд) 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') # объект который создал этот объект self.parentObj = parentObj def is_update(self): #Нужно ли перезапускать метод заполнения (если зависимые переменные #обновились то нужно) upd = False for depVarName in self.dependValues.keys(): value = getattr(self.parentObj, depVarName).Get() if self.dependValues[depVarName] != value: self.dependValues[depVarName] =\ getattr(self.parentObj, 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 # Импортируемые модули - (раздел: модуль переменных, модуль заполнения #переменных) __modlist={'Main':('cl_vars','cl_fill')} def __init__(self): # Для нахождения зависимостей переменных self.__levelNumber = 0 self.__LevelsVar = [] # Для хранения импортированных модулей и объектов #[(cекция,импортированный модуль переменных, объект заполнения),] self._importList = [] self.importData("Main") # Переменные которые нужно записать self.varsNeedWritten = [] def importData(self, section, modlist=[]): """Импортирует модули с переменными и модули с функциями заполнения section секция раздела (Main, Client итд) создает необходимые структуры данных """ if modlist: self.__modlist.update({section:modlist}) 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: globals()[modVar] = __import__(modVar) except (ImportError, AttributeError), e: err1 = _("Error in import module %s")%modVar err2 = _("error") + ": " +str(e) raise self.DataVarsError("%s\n%s"%(err1,err2)) flagFindFillModule = True try: globals()[modFill] = __import__(modFill) except (ImportError, AttributeError), 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: # Создаем объект с методами заполнения переменных fillObj = globals()[modFill].fillVars() # Подключаем методы получения и записи переменных fillObj.Get = self.Get fillObj.Set = self.Set else: fillObj = False # Заполняем self._importList self._importList.insert(0,(section,globals()[modVar],fillObj)) def __findVarData(self, nameVar): """Находит данные для создания объекта переменная в модулях и объектах """ # Ищем переменную в модуле dataVar = False e = False for section, moduleVar, fillobj in self._importList: try: dataVar = getattr(moduleVar.Data, nameVar) except AttributeError, e: pass if not dataVar is False: 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 and hasattr(fillobj, nameMethod): flagFindMetod = True method = getattr(fillobj, 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 = getattr(self, nameVar).Get() elif self.__findVarData(nameVar): dictVar, methodFill =self.__findVarData(nameVar) varobj = var(self) # Устанавливаем аттрибуты self.__setAttributesVar(varobj, nameVar, dictVar) if methodFill: varobj.Fill = methodFill setattr(self, nameVar, varobj) ret = getattr(self, nameVar).Get() self.__levelNumber -= 1 if self.__levelNumber == 0 and\ getattr(self, nameVar).fillStart and\ len(self.__LevelsVar)>1: links = self.__getLinks(self.__LevelsVar) for name in links.keys(): for nameLink in links[name].keys(): val = getattr(self, nameLink).Get() getattr(self, 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 setattr(self, nameVar, varobj) if hasattr(self, nameVar): if not force and "r" in getattr(self, nameVar).mode: cl_overriding.printERROR(\ _("Attempt to rewrite a variable for reading") +\ ": %s"%nameVar) return False getattr(self, nameVar).fillStart = False return getattr(self, nameVar).Set(value) def Set(self, nameVar, value, force=False): return self.__Set(nameVar, value, force) def SetWriteVar(self, nameVar, value, force=False): """Установка значения переменной, и запись в список сохраняемых переменных""" ret = self.__Set(nameVar, value, force) if ret and not nameVar in self.varsNeedWritten: self.varsNeedWritten.append(nameVar) return ret def WriteVars(self, location='default', header=False): """Запись переменных установленных командой SetWriteVar""" flagSuccess = True for nameVar in self.varsNeedWritten: if not self.Write(nameVar, self.Get(nameVar), force=False, location=location, header=header): flagSuccess = False break return flagSuccess 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, location): """Получить путь к ini файлу по алиасу пути""" retData = self.Get('cl_env_data') ini_dict = {} ini_dict.update(retData) if location in ini_dict.keys(): name_calculate_ini = ini_dict[location] else: cl_overriding.printERROR(\ _("Unable to find the alias '%s' of the file path for \ storage of variables templates")%location) cl_overriding.exit(1) return name_calculate_ini def __getSection(self, vname): """секция для записи в ini файл переменной vname - имя переменной """ if not hasattr(self, vname): try: self.Get(vname) except self.DataVarsError, e: cl_overriding.printERROR(_("Not found template variable %s")\ %vname) cl_overriding.printERROR(e) cl_overriding.exit(1) 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', 'main') Возвращаемые значение: True запись успешна False запись не удалсь ''' # получаем путь до ini файла name_calculate_ini = self.__getPathCalculateIni(location) # извлекаем из полного имени файла путь onlydir = os.path.split(name_calculate_ini)[0] try: # проверяем чтобы путь до ини файла существовал if not os.path.exists(onlydir): # создаем его если отсутствует os.makedirs(onlydir) except OSError (nerr,msg): cl_overriding.printERROR(str(nerr) + " " + str(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') Возвращаемые значение: True удалено успешна False удаление не удалсь ''' # получаем путь до ini файла name_calculate_ini = self.__getPathCalculateIni(location) # извлекаем из полного имени файла путь 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) # Удаляем переменную 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', '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 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: act_section.append(service.lower()) return act_section def GetIniVar(self, section_dot_nameVar): """Получить значение переменной из конфигурационного файла section_dot_nameVar - "имя_секции.имя_переменной_профиля" """ calculate_ini_files = self.Get('cl_env_path') section, spl, name_var = section_dot_nameVar.rpartition(".") if section and name_var: pass elif name_var: section = "main" else: cl_overriding.printERROR(\ _("error Datavars.GetIniVar: empty section")) return False # Значение переменной в env файлах valueVar = "" for name_calculate_ini in calculate_ini_files: # проверить сущестование ini файла if os.path.exists(name_calculate_ini): # получить объект настроенный на ini config = iniParser(name_calculate_ini) # получаем значение переменной из секции data = config.getVar(section, name_var, checkExistVar=True) if data is False: return False existsVar, value = data if existsVar: valueVar = value return valueVar.encode("UTF-8") def GetRemoteInfo(self, envFile): """Получение информационных переменных из файла envFile""" optionsInfo = {} # получить объект настроенный на ini config = iniParser(envFile) # получаем все секции из конфигурационного файла allsect = config.getAllSectionNames() if allsect: # Секция (название сервиса) for section in allsect: allvars = config.getAreaVars(section) if allvars == False: return False # Опции сервиса options = {} for varName, value in allvars.items(): varName = varName.encode("UTF-8") value=cl_utils.convertStrListDict(value.encode("UTF-8")) options[varName] = value if options: optionsInfo[section] = options return optionsInfo def flIniFile(self): '''Заместить значение переменных значениями из ини файлов Возвращаемые значения: cловарь импортированных переменных - переменные считаны False - файл не был обнаружен ''' #Cловарь переменных из ini файлов importVars = {} calculate_ini_files = self.Get('cl_env_path') # активные секции (секции из которых будут использованы переменные) act_section = self.__getActiveSections() set_act_section = set(act_section) i = 0 # Алиасы к путям env locations = self.Get('cl_env_location') for name_calculate_ini in calculate_ini_files: # проверить сущестование 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 defined(self, vname): """Имеет ли значение переменная""" try: value = self.Get(vname) except: cl_overriding.printERROR(_("error var %s not found")%str(vname)) cl_overriding.exit(1) if value: return True else: return False #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 hasattr(moduleVar.Data, 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: varType =list(getattr(self, nameVar).type) 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 not '[' in var[i].mode: 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_overriding.printSUCCESS(_("The list of variables:")) cl_overriding.printSUCCESS(_("var name").center(mlen_name)+ " " +\ _("Mode") + " " +_("Value")) cl_overriding.printSUCCESS(br) for i in plist: p_val=var[i].value if var[i].official: continue columnWrite( i, mlen_name, var[i].mode.lower(), mlen_mode, p_val) cl_overriding.printSUCCESS(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