#-*- coding: utf-8 -*-

#Copyright 2008 Calculate Pack, http://www.calculate-linux.ru
#
#  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()
        if not self.checkIniFile(textIni):
            return False
        # создаем объект типа samba и записываем в него содержимое ini-файла
        objIni = cl_profile.samba(textIni)
        # создаем текст в формате samba из строки заголовка и
        # словаря переменных области
        txtConfig = objIni.createTxtConfig(strHeader, dictVar)
        # создаем объект типа samba и записываем в него текст
        objIniAdd = cl_profile.samba(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 = True
            # В файле есть данные
            if not self.isEmptyFile(textIni):
                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 файла"""
        delStrHeader = "!%s" %(strHeader)
        dictVar = {"del":"del"}
        res = self.setVar(delStrHeader, dictVar)
        return res

    def getVar(self, strHeader, nameVar):
        """Получаем значение переменной из ini-файла"""
        textIni = self.openIniFile()
        if not self.checkIniFile(textIni):
            return False
        # создаем объект типа samba и записываем в него содержимое ini-файла
        objIni = cl_profile.samba(textIni)
        # получаем ноду body
        xmlBody = objIni.docObj.getNodeBody()
        # находим в области переменную
        res = objIni.docObj.getAreaFieldValues(strHeader, nameVar, xmlBody)
        if res == False:
            return ""
        else:
            return res

    def getAreaVars(self,strHeader):
        """Получаем все переменнные области из ini-файла"""
        textIni = self.openIniFile()
        if not self.checkIniFile(textIni):
            return False
        # создаем объект типа samba и записываем в него содержимое ini-файла
        objIni = cl_profile.samba(textIni)
        # получаем ноду body
        xmlBody = objIni.docObj.getNodeBody()
        # если находим область то выдаем словарем все переменные иначе False
        res = objIni.docObj.getAreaFields(strHeader, xmlBody)
        if res == False:
            return {}
        else:
            return res

    def getAllSectionNames(self):
        """Получаем все имена секций определенных в ini файле"""
        textIni = self.openIniFile()
        if not self.checkIniFile(textIni):
            return False
        # создаем объект типа samba и записываем в него содержимое ini-файла
        objIni = cl_profile.samba(textIni)
        # получаем ноду body
        xmlBody = objIni.docObj.getNodeBody()
        xmlNodes = objIni.docObj.getFieldsArea(xmlBody)
        # Имена секций ini файла
        namesSection = []
        for xmlNode in xmlNodes:
            if xmlNode.tagName == "area":
                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 self.__dict__.has_key(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 self.__dict__.has_key(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 self.__dict__.has_key(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 self.__dict__.has_key(vname):
            if self.__dict__[vname].service == 'Global':
                return 'calculate'
            else:
                return self.__dict__[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')

        Возвращаемые значение:
        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)
        # Удаляем переменную
        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):
        #if vname:
            #if self.__dict__.has_key(vname):
                #return True
        #return False
    def defined(self, vname):
        return True



    def exists(self, nameVar):
        """ Определяет существует ли переменная с таким имененм
        """
        if self.__dict__.has_key(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:
    """Глобальные аттрибуты для методов заполнения переменных"""
    path_env = cl_utils.getpathenv()

    def _runos(self,cmd,ret_first=None):
        """Вернуть результат выполнения команды ОС"""
        return cl_utils.runOsCommand(cmd, None, ret_first)
