4984 lines
217 KiB
Python
4984 lines
217 KiB
Python
#-*- coding: utf-8 -*-
|
||
|
||
# Copyright 2008-2010 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 stat
|
||
import re
|
||
import xml.dom.minidom
|
||
from xml import xpath
|
||
import subprocess
|
||
import types
|
||
import random
|
||
import string
|
||
import time
|
||
|
||
|
||
# Переопределение exit
|
||
import cl_overriding
|
||
|
||
from cl_utils import _error, _toUNICODE, getModeFile, removeDir, typeFile,\
|
||
scanDirectory, convertStrListDict, pathJoin
|
||
|
||
import cl_lang
|
||
tr = cl_lang.lang()
|
||
tr.setLocalDomain('cl_lib')
|
||
tr.setLanguage(sys.modules[__name__])
|
||
|
||
|
||
class _shareTermsFunction:
|
||
"""Общие аттрибуты для классов _terms и templateFunctions"""
|
||
# Символы допустимые в скобках функции шаблона
|
||
_reFunctionArgvInSquareBrackets = "a-zA-Z0-9_\-\+\,\*\/\.\'\"~\\\\ "
|
||
_reFunctionArgvText = "[%s]"%_reFunctionArgvInSquareBrackets
|
||
# регулярное выражение для поиска функции в шаблоне
|
||
_reFunctionText = "([a-zA-Z0-9\_\-]+)\((%s+|)\)" %_reFunctionArgvText
|
||
|
||
|
||
class _terms(_error, _shareTermsFunction):
|
||
"""Вычисление условий применяемых в шаблонах
|
||
|
||
"""
|
||
# регулярное выражение для поиска функции в шаблоне
|
||
_reFunction = re.compile(_shareTermsFunction._reFunctionText)
|
||
# регулярное выражение для не версии
|
||
_re_not_Version = re.compile("[^0-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(" ")
|
||
listSplitOr = []
|
||
if "or" in trs:
|
||
lst = []
|
||
for t in trs:
|
||
if t != "or":
|
||
lst.append(t)
|
||
else:
|
||
listSplitOr.append(lst)
|
||
lst = []
|
||
if lst:
|
||
listSplitOr.append(lst)
|
||
else:
|
||
listSplitOr = [trs]
|
||
for trsAnd in listSplitOr:
|
||
listEqual = []
|
||
for t in trsAnd:
|
||
flagRule = False
|
||
for sepF in rule:
|
||
if sepF in t:
|
||
flagRule = True
|
||
vals = t.split(sepF)
|
||
break
|
||
if flagRule:
|
||
#проверка на допустимость названия переменной
|
||
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) and\
|
||
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:
|
||
cl_overriding.printERROR(textError)
|
||
cl_overriding.printERROR(e)
|
||
cl_overriding.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(True)
|
||
else:
|
||
listEqual.append(False)
|
||
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(True)
|
||
else:
|
||
listEqual.append(False)
|
||
flagNotIniFunct = False
|
||
else:
|
||
if flagIntTypeVar is 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(True)
|
||
else:
|
||
listEqual.append(False)
|
||
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(True)
|
||
else:
|
||
listEqual.append(False)
|
||
else:
|
||
if not flagNotEmptyVals:
|
||
listEqual.append(False)
|
||
else:
|
||
self.setError("'%s'"%term + " "\
|
||
+ _("incorrect"))
|
||
self.setError(textError)
|
||
return False
|
||
else:
|
||
if t == "and":
|
||
if listEqual == [] or False in listEqual:
|
||
listEqual = [False]
|
||
else:
|
||
listEqual = [True]
|
||
else:
|
||
self.setError("'%s'"%term + " " + _("incorrect"))
|
||
self.setError(textError)
|
||
return False
|
||
if not (listEqual == [] or False in listEqual):
|
||
break
|
||
if listEqual == [] or False in listEqual:
|
||
return False
|
||
return True
|
||
#exec("res=(%s)"%("".join(listEqual)))
|
||
#return res
|
||
|
||
class fileHeader(_terms):
|
||
"""Обработка заголовков шаблонов и конфигурационных файлов
|
||
|
||
"""
|
||
# Допустимые параметры заголовка
|
||
allowParam = ["format", "format_conf", "comment", "append", "force",
|
||
"link", "mirror", "symbolic", "chmod", "chown", "name",
|
||
"path"]
|
||
|
||
# Тип шаблона
|
||
fileType = ""
|
||
# Тип вставки шаблона
|
||
typeAppend = ""
|
||
# Возможные типы вставки шаблонов
|
||
_fileAppend = "join", "before", "after", "replace", "remove", "skip"
|
||
# Интерпретатор (#!/bin/bash) (#!/usr/bin/python)
|
||
execStr = ""
|
||
# Символ комментария
|
||
comment = False
|
||
# Выражение для поиска строки интерпретатора
|
||
reExecStr = re.compile("^#!.+\s*",re.I)
|
||
# условные операторы
|
||
terms = ('>', '<', '==', '!=', '>=', '<=')
|
||
# параметры без значения
|
||
listParNotVal = ("symbolic", "force", "mirror")
|
||
# Результат вычисления условия в заголовке
|
||
headerTerm = True
|
||
|
||
def __init__(self, templateName, text, comment=False, fileType=False,
|
||
objVar=False, function=False):
|
||
self.body = text
|
||
# Объект с переменными
|
||
self.objVar=objVar
|
||
# Параметры описанные в заголовке файла шаблона
|
||
self.params = {}
|
||
# некорректные параметры
|
||
incorrectParams = set([])
|
||
# Удаление Заголовка Calculate
|
||
if comment:
|
||
titleFirst = _("Modified")
|
||
# В случае текста XML
|
||
if type(comment) == types.TupleType and len(comment) == 2:
|
||
reCalcHeader =\
|
||
re.compile("\s*%s\s+%s.+\s+(.+\n)+%s\s?"\
|
||
%(comment[0], titleFirst, comment[1]),re.M|re.I)
|
||
reS = reCalcHeader.search(text)
|
||
if reS:
|
||
self.body = text[:reS.start()]+text[reS.end():]
|
||
else:
|
||
reCalcHeader = re.compile(\
|
||
"\s*%s\-+\s+%s\s+%s.+\s+(%s.+\s+)+%s\-+\s?"\
|
||
%(comment, comment, titleFirst ,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
|
||
errorMsg = _("Incorrect template") +\
|
||
": "+ templateName +"\n"+\
|
||
_("header template not valid")+\
|
||
": "+ i
|
||
if function:
|
||
rezTerm = self._equalTerm(i,
|
||
errorMsg,
|
||
function)
|
||
else:
|
||
rezTerm = self._equalTerm(i,
|
||
errorMsg)
|
||
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.setError(_("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", "path"]
|
||
|
||
# Тип вставки шаблона
|
||
typeAppend = ""
|
||
|
||
# Возможные типы вставки шаблонов
|
||
_fileAppend = "join", "remove", "skip"
|
||
|
||
# условные операторы
|
||
terms = ('>', '<', '==', '!=', '>=', '<=')
|
||
|
||
# параметры без значения
|
||
listParNotVal = ("symbolic", "force")
|
||
|
||
# Результат вычисления условия в заголовке
|
||
headerTerm = True
|
||
|
||
def __init__(self, templateName, 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.setError(_("incorrect text in template: '%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
|
||
errorMsg = _("Incorrect template") +\
|
||
": "+ templateName +"\n"+\
|
||
_("header template not valid")+ ": "+ i
|
||
if function:
|
||
rezTerm = self._equalTerm(i, errorMsg,
|
||
function)
|
||
else:
|
||
rezTerm = self._equalTerm(i, errorMsg)
|
||
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.setError(_("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
|
||
"!" - <action>drop</action> удаляет
|
||
"+" - <action>join</action> добавляет
|
||
"-" - <action>replace</action> заменяет
|
||
"""
|
||
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(_toUNICODE(text))
|
||
element.appendChild(txtNode)
|
||
for attr in attributes.keys():
|
||
attribute = doc.createAttribute(attr)
|
||
attribute.nodeValue = attributes[attr]
|
||
element.setAttributeNode(attribute)
|
||
return element
|
||
|
||
|
||
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 = '<?xml version="1.0" encoding="UTF-8"?><cxmlconf><head>'
|
||
docTxt += '<ver>%s</ver>'% version
|
||
docTxt += '<format>%s</format>' % typeDoc
|
||
docTxt += '</head><body></body></cxmlconf>'
|
||
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
|
||
if parentNode:
|
||
fieldsVal = xpath.Evaluate(\
|
||
"child::field[attribute::type='seplist'][child::name='%s'] "\
|
||
%(nameField), parentNode)
|
||
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<lenOldFields:
|
||
nextNode = oldFields[i+1]
|
||
if self.getTypeField(nextNode) == "br":
|
||
removeNodes.append(nextNode)
|
||
removeNodesDict[nameNewField] = removeNodes
|
||
return removeNodes
|
||
|
||
|
||
def addNewFielsOldArea(self, newFields, joinNewFields, xmlOldArea):
|
||
"""Добавляет новые XML поля в область шаблона"""
|
||
removeNodesDict = {}
|
||
notRemoveNodesDict = {}
|
||
for notRemNode in joinNewFields:
|
||
nameField = self.getNameField(notRemNode)
|
||
if not notRemoveNodesDict.has_key(nameField):
|
||
notRemoveNodesDict[nameField] = []
|
||
notRemoveNodesDict[nameField].append(notRemNode)
|
||
else:
|
||
notRemoveNodesDict[nameField].append(notRemNode)
|
||
notSepListField = []
|
||
sepListField = []
|
||
for nField in newFields:
|
||
if self.getRemoveNodeSepList(removeNodesDict, xmlOldArea,
|
||
nField):
|
||
sepListField.append(nField)
|
||
else:
|
||
if self.getNameField(nField):
|
||
notSepListField.append(nField)
|
||
for name in notRemoveNodesDict.keys():
|
||
if removeNodesDict.has_key(name):
|
||
removeNodesDict[name] = []
|
||
for removeNodes in removeNodesDict.values():
|
||
if removeNodes:
|
||
if self.getTypeField(removeNodes[-1]) == "seplist":
|
||
removeNodes = removeNodes[:-1]
|
||
else:
|
||
removeNodes = removeNodes[:-2]
|
||
|
||
for removeNode in removeNodes:
|
||
xmlOldArea.removeChild(removeNode)
|
||
for node in sepListField:
|
||
node.setAttribute("type", "seplist")
|
||
if not (self.getActionField(node) == "join" or\
|
||
self.getActionField(node) == "drop"):
|
||
self.setActionField(node,"insert")
|
||
self.joinField(xmlOldArea, node)
|
||
for node in notSepListField:
|
||
if self.getTypeField(node) == "seplist":
|
||
self.setActionField(node, "append")
|
||
xmlOldArea.appendChild(node)
|
||
else:
|
||
self.joinField(xmlOldArea, node)
|
||
|
||
def insertBeforeSepAreas(self, xmlArea):
|
||
"""Добавляет разделитель областей перед каждой областью"""
|
||
if not self.sepAreas:
|
||
return False
|
||
areaNodes = xpath.Evaluate('descendant::area',xmlArea)
|
||
for areaNode in areaNodes:
|
||
prevNode = areaNode.previousSibling
|
||
if prevNode:
|
||
parentNode = areaNode.parentNode
|
||
parentNode.insertBefore(self.sepAreas.cloneNode(True),
|
||
areaNode)
|
||
return True
|
||
|
||
def getAreaFields(self, nameArea, xmlArea):
|
||
"""По имени области выводит названия и значения всех переменных
|
||
|
||
поиск ведется только в 1-х потомках области xmlArea
|
||
на выход словарь переменных {имя:значение}
|
||
"""
|
||
namesAreaComare = xpath.Evaluate(\
|
||
"child::area/child::caption[child::name='%s']" %(nameArea),
|
||
xmlArea)
|
||
if not namesAreaComare:
|
||
return False
|
||
fields = xpath.Evaluate("child::field/child::name",
|
||
namesAreaComare[0].parentNode)
|
||
dictVar = {}
|
||
for fieldName in fields:
|
||
nodeField = fieldName.parentNode
|
||
fieldValue = xpath.Evaluate("child::value",nodeField)
|
||
name = fieldName.firstChild.nodeValue
|
||
value = ""
|
||
if fieldValue and fieldValue[0].firstChild:
|
||
value = fieldValue[0].firstChild.nodeValue
|
||
dictVar[name] = value
|
||
return dictVar
|
||
|
||
def getAreaFieldValues(self, nameArea, nameField, xmlArea):
|
||
"""По имени области и имени переменной выводит значениe переменной
|
||
|
||
поиск ведется только в 1-х потомках области xmlArea
|
||
"""
|
||
namesAreaComare = xpath.Evaluate(\
|
||
"child::area/child::caption[child::name='%s']" %(nameArea),
|
||
xmlArea)
|
||
fieldsVal = False
|
||
for areaComp in namesAreaComare:
|
||
fieldsVal = xpath.Evaluate(\
|
||
"child::field[child::name='%s'] "\
|
||
%(nameField), areaComp.parentNode)
|
||
if fieldsVal:
|
||
break
|
||
if not fieldsVal:
|
||
return False
|
||
fieldValue = xpath.Evaluate("child::value",
|
||
fieldsVal[0])
|
||
if not fieldValue:
|
||
return False
|
||
if fieldValue[0].firstChild:
|
||
return fieldValue[0].firstChild.nodeValue
|
||
else:
|
||
return ""
|
||
|
||
def getAllAreas(self):
|
||
"""Выдает все области"""
|
||
return xpath.Evaluate('descendant::area', self.body)
|
||
|
||
def getArea(self, nameArea, xmlArea):
|
||
"""По имени области находит области (первый потомок xmlArea)"""
|
||
namesAreaComare = xpath.Evaluate(\
|
||
"child::area/child::caption[child::name='%s']" %(nameArea),
|
||
xmlArea)
|
||
return map(lambda x: x.parentNode, namesAreaComare)
|
||
|
||
|
||
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" or newAreaAction == "replace"):
|
||
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)
|
||
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" or\
|
||
newAreaAction == "replace"):
|
||
appendArea(baseNode, xmlNewArea)
|
||
else:
|
||
tmpXmlNewAreas = xpath.Evaluate('child::area',xmlNewArea)
|
||
for na in tmpXmlNewAreas:
|
||
for bn in baseNodes:
|
||
self.joinArea(bn, na)
|
||
return True
|
||
|
||
|
||
def joinDoc(self, xmlNewDoc):
|
||
"""Объединяет два документа"""
|
||
newRootNode = xmlNewDoc.documentElement
|
||
newBodyNode = xpath.Evaluate('child::body',newRootNode)[0]
|
||
newImportBodyNode = self.doc.importNode(newBodyNode, True)
|
||
# Перед объединение области с документом
|
||
# удаляем комментарии
|
||
self.removeComment(newImportBodyNode)
|
||
self.joinBody(self.body, newImportBodyNode)
|
||
# расставляем BR
|
||
self.insertBRtoBody(self.body)
|
||
|
||
def getQuoteField(self, xmlField):
|
||
"""Выдает текст из поля"""
|
||
xmlQuotes = xpath.Evaluate('child::quote',xmlField)
|
||
br = ""
|
||
if xmlField.hasAttribute("type") and\
|
||
xmlField.getAttribute("type") == "br":
|
||
br = "\n"
|
||
if xmlQuotes:
|
||
field = xmlQuotes[0]
|
||
if field.firstChild:
|
||
return field.firstChild.nodeValue + br
|
||
return "" + br
|
||
|
||
def getFieldsArea(self, xmlArea):
|
||
"""Выдает потомков XML области"""
|
||
xmlFields = []
|
||
childNodes = xmlArea.childNodes
|
||
for node in childNodes:
|
||
if node.nodeType == node.ELEMENT_NODE:
|
||
if node.tagName == "area" or node.tagName == "field":
|
||
xmlFields.append(node)
|
||
return xmlFields
|
||
|
||
def getTypeField(self, xmlField):
|
||
"""Выдает тип поля"""
|
||
if xmlField.hasAttribute("type"):
|
||
return xmlField.getAttribute("type")
|
||
else:
|
||
return False
|
||
|
||
def getNameField(self, xmlField):
|
||
"""Выдает имя поля"""
|
||
xmlNameFields = xpath.Evaluate('child::name', xmlField)
|
||
if xmlNameFields and xmlNameFields[0].firstChild:
|
||
return xmlNameFields[0].firstChild.nodeValue
|
||
else:
|
||
return False
|
||
|
||
def getNameArea(self, xmlArea):
|
||
"""Выдает имя области"""
|
||
xmlNameAreas = xpath.Evaluate('child::caption/name', xmlArea)
|
||
if xmlNameAreas and xmlNameAreas[0].firstChild:
|
||
return xmlNameAreas[0].firstChild.nodeValue
|
||
else:
|
||
return False
|
||
|
||
def xmlToText(self, xmlAreas, text):
|
||
"""Преобразует список XML областей в текст"""
|
||
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
|
||
|
||
for i in xmlAreas:
|
||
if i.tagName == "area":
|
||
quotesI = getQuotesArea(i)
|
||
startAreaI = quotesI[0]
|
||
endAreaI = quotesI[1]
|
||
text.append(startAreaI)
|
||
xmlFieldsI = self.getFieldsArea(i)
|
||
for f in xmlFieldsI:
|
||
if f.tagName == "area":
|
||
quotesF = getQuotesArea(f)
|
||
startAreaF = quotesF[0]
|
||
endAreaF = quotesF[1]
|
||
text.append(startAreaF)
|
||
xmlFieldsF = self.getFieldsArea(f)
|
||
self.xmlToText(xmlFieldsF, text)
|
||
text.append(endAreaF)
|
||
else:
|
||
fieldF = self.getQuoteField(f)
|
||
text.append(fieldF)
|
||
text.append(endAreaI)
|
||
else:
|
||
fieldI = self.getQuoteField(i)
|
||
text.append(fieldI)
|
||
|
||
def getActionField(self, xmlField):
|
||
"""Выдает свойство action XML поля"""
|
||
xmlActions = xpath.Evaluate('child::action',xmlField)
|
||
if xmlActions and xmlActions[0].firstChild:
|
||
return xmlActions[0].firstChild.nodeValue
|
||
else:
|
||
return False
|
||
|
||
def getFieldValues(self, xmlField):
|
||
"""Выдает значения XML поля в виде массива"""
|
||
vals = []
|
||
xmlValues = xpath.Evaluate('child::value',xmlField)
|
||
if xmlValues:
|
||
for node in xmlValues:
|
||
if node.firstChild:
|
||
vals.append(node.firstChild.nodeValue)
|
||
return vals
|
||
|
||
def getActionArea(self, xmlArea):
|
||
"""Выдает свойство action XML области"""
|
||
xmlActions = xpath.Evaluate('child::caption/action',xmlArea)
|
||
if xmlActions and xmlActions[0].firstChild:
|
||
return xmlActions[0].firstChild.nodeValue
|
||
else:
|
||
return False
|
||
|
||
def delActionNodeArea(self, xmlArea):
|
||
"""Удаляет свойство action XML области"""
|
||
xmlActions = xpath.Evaluate('child::caption/action',xmlArea)
|
||
if xmlActions and xmlActions[0].firstChild:
|
||
parentNode = xmlActions[0].parentNode
|
||
parentNode.removeChild(xmlActions[0])
|
||
return True
|
||
else:
|
||
return False
|
||
|
||
def delActionNodeField(self, xmlField):
|
||
"""Удаляет свойство action XML поля"""
|
||
xmlActions = xpath.Evaluate('child::action',xmlField)
|
||
if xmlActions and xmlActions[0].firstChild:
|
||
parentNode = xmlActions[0].parentNode
|
||
parentNode.removeChild(xmlActions[0])
|
||
return True
|
||
else:
|
||
return False
|
||
|
||
# Создает распределенные списки
|
||
def postParserListSeplist(self, xmlArea):
|
||
"""Создает распределенные списки из элементов области"""
|
||
# Потомки
|
||
childNodes = self.getFieldsArea(xmlArea)
|
||
# содержит списки нод полей с одинаковыми именами в одной области
|
||
fieldsSeplist = {}
|
||
for node in childNodes:
|
||
if node.tagName == "area":
|
||
self.postParserListSeplist(node)
|
||
else:
|
||
fieldName = False
|
||
xmlFieldNameNodes = xpath.Evaluate('child::name',node)
|
||
if xmlFieldNameNodes and xmlFieldNameNodes[0].firstChild:
|
||
fieldName = xmlFieldNameNodes[0].firstChild.nodeValue
|
||
if fieldName:
|
||
if fieldsSeplist.has_key(fieldName):
|
||
fieldsSeplist[fieldName].append(node)
|
||
else:
|
||
fieldsSeplist[fieldName] = []
|
||
fieldsSeplist[fieldName].append(node)
|
||
for listNodes in fieldsSeplist.values():
|
||
if len(listNodes) > 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)<len(blocsTxt):
|
||
headersTxt.insert(0,"")
|
||
if len(headersTxt)!=len(blocsTxt):
|
||
return False
|
||
return (headersTxt, blocsTxt)
|
||
else:
|
||
return False
|
||
|
||
|
||
class _file(_error):
|
||
"""Класс для работы с файлами
|
||
|
||
"""
|
||
def __init__(self):
|
||
# Имя файла конфигурационного файла
|
||
self.nameFileConfig = ""
|
||
# Содержимое конфигурационного файла
|
||
self.textConfig = ""
|
||
# Имя файла шаблона
|
||
self.nameFileTemplate = ""
|
||
# Содержимое шаблона
|
||
self.textTemplate = ""
|
||
# Дескриптор файла шаблона
|
||
self.F_TEMPL = False
|
||
# Дескриптор файла конфигурационного файла
|
||
self.F_CONF = False
|
||
|
||
def saveConfFile(self):
|
||
"""Записать конфигурацию"""
|
||
if self.F_CONF:
|
||
self.F_CONF.truncate(0)
|
||
self.F_CONF.seek(0)
|
||
if not self.textConfig:
|
||
self.textConfig = self.textTemplate
|
||
try:
|
||
self.F_CONF.write(self.textConfig)
|
||
except:
|
||
self.setError(_("not open file:" ) + self.nameFileConfig)
|
||
return False
|
||
self.F_CONF.flush()
|
||
return True
|
||
|
||
def openTemplFile(self, nameFileTemplate):
|
||
"""Открыть файл шаблона"""
|
||
F_TEMPL = False
|
||
try:
|
||
F_TEMPL = open(nameFileTemplate, "r")
|
||
except:
|
||
self.setError(_("not open file:" ) + nameFileTemplate)
|
||
return False
|
||
return F_TEMPL
|
||
|
||
def closeTemplFile(self):
|
||
if self.F_TEMPL:
|
||
self.F_TEMPL.close()
|
||
self.F_TEMPL = False
|
||
|
||
def __closeOldFile(self):
|
||
if self.F_CONF:
|
||
self.F_CONF.close()
|
||
self.F_CONF = False
|
||
|
||
def __openConfFile(self, nameFileConfig):
|
||
"""Отктрыть конфигурационный файл"""
|
||
F_CONF = False
|
||
try:
|
||
if os.path.islink(nameFileConfig):
|
||
# если ссылка то удаляем её
|
||
os.unlink(nameFileConfig)
|
||
F_CONF = open (nameFileConfig, "r+")
|
||
except:
|
||
try:
|
||
F_CONF = open(nameFileConfig, "w+")
|
||
except:
|
||
self.setError(_("not open file:" ) + nameFileConfig)
|
||
return False
|
||
return F_CONF
|
||
|
||
|
||
def openFiles(self, nameFileTemplate, nameFileConfig):
|
||
"""Открывает шаблон и конфигурационный файл"""
|
||
self.textConfig = ""
|
||
self.textTemplate = ""
|
||
self.closeFiles()
|
||
self.F_TEMPL = False
|
||
self.F_CONF = False
|
||
self.nameFileConfig = os.path.abspath(nameFileConfig)
|
||
self.nameFileTemplate = os.path.abspath(nameFileTemplate)
|
||
self.F_TEMPL = self.openTemplFile(self.nameFileTemplate)
|
||
self.F_CONF = self.__openConfFile(self.nameFileConfig)
|
||
if self.F_TEMPL and self.F_CONF:
|
||
self.textTemplate = self.F_TEMPL.read()
|
||
self.textConfig = self.F_CONF.read()
|
||
|
||
def __del__(self):
|
||
self.closeFiles()
|
||
|
||
def closeFiles(self):
|
||
"""Закрытие файлов"""
|
||
self.closeTemplFile()
|
||
self.__closeOldFile()
|
||
|
||
|
||
class utfBin:
|
||
"""Класс для преобразования в utf-8
|
||
|
||
преобразование бинарного или смеси бинарного и utf-8 кода в utf-8 и
|
||
обратное преобразование
|
||
методы класса encode и decode
|
||
"""
|
||
def _retUTF(self, char):
|
||
byte = ord(char)
|
||
if byte<=127:
|
||
return ('_ch_',1)
|
||
elif byte<=191:
|
||
return ('_nb_',1)
|
||
elif byte<=223:
|
||
return ('_fb_',2)
|
||
elif byte<=239:
|
||
return ('_fb_',3)
|
||
elif byte<=247:
|
||
return ('_fb_',4)
|
||
else:
|
||
return ('_er_',1)
|
||
|
||
def _sumbUtf(self, symbols, lenTail):
|
||
if not symbols:
|
||
return (False,0)
|
||
lenSymb = len(symbols)
|
||
if lenSymb >= 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)
|
||
textTemplateTmp = text
|
||
while resS:
|
||
mark = textTemplateTmp[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
|
||
textTemplateTmp = textTemplateTmp.replace(mark, stringInsert)
|
||
resS = reVar.search(textTemplateTmp)
|
||
return textTemplateTmp
|
||
|
||
class templateFormat:
|
||
"""Методы получения классов и объектов форматов шаблонов"""
|
||
# Импортированные классы поддерживаемых форматов шаблонов
|
||
importFormats = {}
|
||
|
||
def getClassObj(self, nameClassTemplate):
|
||
"""Создает класс шаблона по имени"""
|
||
if nameClassTemplate in self.importFormats:
|
||
classFormat = self.importFormats[nameClassTemplate]
|
||
else:
|
||
try:
|
||
classFormat = getattr(__import__("format.%s"%nameClassTemplate,
|
||
globals(), locals(),
|
||
[nameClassTemplate]),
|
||
nameClassTemplate)
|
||
except (ImportError, AttributeError):
|
||
#Создаем объект из self.newObjProt с помощью
|
||
# метаклассов
|
||
if nameClassTemplate in self.newObjProt:
|
||
# Прототип класса
|
||
nameProt = self.newObjProt[nameClassTemplate]
|
||
if nameProt in self.importFormats:
|
||
classProt = self.importFormats[nameProt]
|
||
else:
|
||
try:
|
||
classProt = getattr(__import__("format.%s"%nameProt,
|
||
globals(), locals(),
|
||
[nameProt]),
|
||
nameProt)
|
||
except (ImportError, AttributeError):
|
||
return False
|
||
self.importFormats[nameProt] = classProt
|
||
classFormat = self.createNewClass(nameClassTemplate,
|
||
(classProt,))
|
||
else:
|
||
return False
|
||
self.importFormats[nameClassTemplate] = classFormat
|
||
return classFormat
|
||
|
||
def getFormatObj(self, formatTemplate, textTemplate):
|
||
"""Создание объекта формата шаблона.
|
||
|
||
Объект создается на основании формата шаблона и текста шаблона"""
|
||
classFormat = self.getClassObj(formatTemplate)
|
||
if classFormat:
|
||
return classFormat(textTemplate)
|
||
else:
|
||
return False
|
||
|
||
class _shareTemplate:
|
||
"""Общие аттрибуты для классов шаблонов"""
|
||
# Метка начала переменной
|
||
varStart = "#-"
|
||
# Метка конца переменной
|
||
varEnd = "-#"
|
||
_deltVarStart = len(varStart)
|
||
_deltVarEnd = len(varEnd)
|
||
|
||
def getDataUser(self, groupsInfo=False):
|
||
"""Получить информацию о пользователе"""
|
||
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:
|
||
cl_overriding.printERROR(_("Can not found user %s")%str(userName))
|
||
cl_overriding.exit(1)
|
||
if groupsInfo:
|
||
import grp
|
||
try:
|
||
groupName = grp.getgrgid(gid).gr_name
|
||
except:
|
||
cl_overriding.printERROR(\
|
||
_("Can not found group id %s")%str(gid))
|
||
cl_overriding.exit(1)
|
||
groupsNames = map(lambda x: x.gr_name,\
|
||
filter(lambda x: userName in x.gr_mem, grp.getgrall()))
|
||
groupsNames = [groupName] + groupsNames
|
||
return uid, gid, homeDir, groupsNames
|
||
return uid, gid, homeDir
|
||
|
||
class templateFunction(_error, _shareTemplate, _shareTermsFunction):
|
||
"""Класс для функций шаблонов"""
|
||
# Словарь установленных программ {"имя программы":[версии]}
|
||
installProg = {}
|
||
|
||
# Cписок просканированных категорий установленных программ
|
||
installCategory = []
|
||
|
||
# Флаг сканирования всех установленных программ
|
||
flagAllPkgScan = False
|
||
|
||
# Список названий функций шаблона
|
||
namesTemplateFunction = []
|
||
|
||
# Словарь {название функции шаблона: функция шаблона, ...}
|
||
templateFunction = {}
|
||
|
||
# Регулярное выражение для сложения
|
||
sNum = re.compile("\-[^\-\+]+|[^\-\+]+")
|
||
|
||
# Регулярное выражение для умножениея и деления
|
||
sMD = re.compile("[^\-\+\*\/]+")
|
||
|
||
# директория установленных программ
|
||
basePkgDir = "/var/db/pkg"
|
||
|
||
# стек глобальных переменных
|
||
stackGlobalVars = []
|
||
|
||
# регулярное выражение для поиска версии
|
||
reFindVer = re.compile("(?<=\-)\d+\.?\d*\.?\d*")
|
||
|
||
# Имя обрабатываемого шаблона
|
||
nameTemplate = ""
|
||
|
||
# Текст функции шаблона
|
||
functText = ""
|
||
|
||
|
||
def __init__(self, objVar):
|
||
# Если не определен словарь функций шаблона
|
||
if not self.templateFunction:
|
||
# префикс функций шаблона
|
||
pref = "func"
|
||
# cписок [(название функции, функция), ...]
|
||
dictFunc = filter(lambda x: x[0].startswith(pref) and\
|
||
hasattr(x[1],"__call__"),
|
||
self.__class__.__dict__.items())
|
||
# удаляем у названия функции префикс и переводим остаток названия
|
||
# в нижний регистр
|
||
dictFunc = map(lambda x: (x[0][len(pref):].lower(), x[1]), dictFunc)
|
||
# Формируем словарь функций шаблона
|
||
self.templateFunction.update(dictFunc)
|
||
# Формируем список функций шаблона
|
||
for nameFunction in self.templateFunction.keys():
|
||
self.namesTemplateFunction.append(nameFunction)
|
||
# Объект хранения переменных
|
||
self.objVar = objVar
|
||
# Директория другой системы
|
||
self._chrootDir = self.objVar.Get("cl_chroot_path")
|
||
if self._chrootDir != '/':
|
||
# Изменение директории к базе пакетов
|
||
self.basePkgDir = pathJoin(self._chrootDir, self.basePkgDir)
|
||
# Базовая директория переноса шаблонов "/mnt/calculate" или "/" и.т.д
|
||
self._baseDir=pathJoin(self._chrootDir,self.objVar.Get("cl_root_path"))
|
||
self._reFunc = re.compile(("%s%s%s")\
|
||
%(self.varStart,self._reFunctionText,self.varEnd),re.M)
|
||
# Аттрибуты для функции шаблона ini()
|
||
# Первоначальный словарь переменных для ini()
|
||
self.prevDictIni = {}
|
||
# Текущий словарь переменных для ini()
|
||
self.currDictIni = {}
|
||
# Время модификации конфигурационного файла для ini()
|
||
self.timeIni = -1
|
||
self.uid, self.gid, self.homeDir, self.groups =\
|
||
self.getDataUser(groupsInfo=True)
|
||
# Домашняя директория, плюс базовая директория
|
||
self.homeDir = pathJoin(self._baseDir, self.homeDir)
|
||
# Путь к конфигурационному файлу для ini()
|
||
self.pathConfigIni = os.path.join(self.homeDir, ".calculate")
|
||
self.fileConfigIni = os.path.join(self.pathConfigIni,"ini.env")
|
||
# Словарь времен модификации env файлов
|
||
self.timeConfigsIni = {}
|
||
# Словарь хранения переменых полученных функцией env() из env файлов
|
||
self.valuesVarEnv = {}
|
||
# Словарь хранения опций для функции info()
|
||
self.optionsInfo = {}
|
||
# файл параметров сервисов
|
||
envFile = self.objVar.Get("cl_env_server_path")
|
||
# объект конвертирования из старого remote env файла
|
||
self.convObj = False
|
||
if os.access(envFile, os.R_OK):
|
||
self.convObj = False
|
||
elif os.access("/var/calculate/remote/calculate.env", os.R_OK):
|
||
from convertenv import convertEnv
|
||
self.convObj = convertEnv()
|
||
|
||
def equalTerm(self, term, localVars):
|
||
"""Метод для вычисления выражения"""
|
||
terms = self.sNum.findall(term)
|
||
if terms:
|
||
strNumers = []
|
||
for n in terms:
|
||
strNum = n.strip()
|
||
if "*" in strNum or "/" in strNum:
|
||
strNum = self.multAndDiv(strNum,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:
|
||
self.printErrTemplate()
|
||
cl_overriding.printERROR(\
|
||
_("error var %s not int")%str(strNum))
|
||
cl_overriding.exit(1)
|
||
elif self.objVar.exists(strNum):
|
||
try:
|
||
num = int(self.objVar.Get(strNum))
|
||
except:
|
||
self.printErrTemplate()
|
||
cl_overriding.printERROR(\
|
||
_("error var %s not int")%str(strNum))
|
||
cl_overriding.exit(1)
|
||
else:
|
||
self.printErrTemplate()
|
||
cl_overriding.printERROR(\
|
||
_("error local var %s not defined")%str(strNum))
|
||
cl_overriding.exit(1)
|
||
if minus:
|
||
num = -num
|
||
strNumers.append(num)
|
||
return sum(strNumers)
|
||
self.printErrTemplate()
|
||
cl_overriding.printERROR(_("error template term %s, incorrect data")\
|
||
%str(term))
|
||
cl_overriding.exit(1)
|
||
|
||
def multAndDiv(self, term, localVars):
|
||
"""Метод для умножения и деления"""
|
||
termTmp = term
|
||
varsLocal = self.sMD.findall(term)
|
||
for var in varsLocal:
|
||
flagVarTxt = True
|
||
try:
|
||
int(var)
|
||
except:
|
||
flagVarTxt = False
|
||
if flagVarTxt:
|
||
continue
|
||
varReplace = str(self.equalTerm(var, localVars))
|
||
termTmp = termTmp.replace(var,varReplace)
|
||
ret = eval(termTmp)
|
||
return ret
|
||
|
||
def funcSum(self, funArgv, resS, localVars, textTemplateTmp):
|
||
"""Функция шаблона, вычисляет функцию sum()"""
|
||
terms = funArgv.replace(" ","").split(",")
|
||
# Название локальной переменной
|
||
nameLocVar = terms[0]
|
||
if not localVars.has_key(nameLocVar):
|
||
localVars[nameLocVar] = 0
|
||
if len(terms) == 2:
|
||
if terms[1].strip():
|
||
localVars[nameLocVar] = self.equalTerm(terms[1], localVars)
|
||
replace = str(localVars[nameLocVar])
|
||
else:
|
||
replace = ""
|
||
textTemplateTmp = textTemplateTmp[:resS.start()] + replace +\
|
||
textTemplateTmp[resS.end():]
|
||
elif len(terms) == 3:
|
||
if terms[1].strip():
|
||
replaceInt = self.equalTerm(terms[1], localVars)
|
||
replace = str(replaceInt)
|
||
else:
|
||
replace = ""
|
||
localVars[nameLocVar] = self.equalTerm(terms[2], localVars)
|
||
textTemplateTmp = textTemplateTmp[:resS.start()] + replace +\
|
||
textTemplateTmp[resS.end():]
|
||
else:
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
return textTemplateTmp
|
||
|
||
def funcExists(self, funArgv, resS, localVars, textTemplateTmp):
|
||
"""Функция шаблона exists(),
|
||
проверяет существование файла, если существует выдает '1'
|
||
"""
|
||
terms = map(lambda x: x.strip(), funArgv.split(","))
|
||
if len(terms) !=1:
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
fileName = terms[0]
|
||
if fileName[0] == "~":
|
||
# Получаем директорию пользователя
|
||
fileName = os.path.join(self.homeDir,
|
||
fileName.partition("/")[2],"")[:-1]
|
||
elif fileName[0] != "/":
|
||
self.printErrTemplate()
|
||
cl_overriding.printERROR(_("wrong path '%s'")%fileName)
|
||
cl_overriding.exit(1)
|
||
else:
|
||
fileName = pathJoin(self._baseDir, fileName)
|
||
replace = ""
|
||
if os.path.exists(fileName):
|
||
replace = "1"
|
||
textTemplateTmp = textTemplateTmp[:resS.start()] + replace +\
|
||
textTemplateTmp[resS.end():]
|
||
return textTemplateTmp
|
||
|
||
def funcLoad(self, funArgv, resS, localVars, textTemplateTmp):
|
||
"""Функция шаблона load(),
|
||
|
||
если файл существует читает из файла локальную переменную
|
||
если один параметр - выводит значение локальной переменной
|
||
"""
|
||
terms = funArgv.split(",")
|
||
if not terms or not terms[0].strip() or\
|
||
(len(terms)==2 and not terms[1].strip()) or\
|
||
len(terms)>2:
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
if len(terms) == 2:
|
||
if not terms[0] in ["ver","num","char","key"]:
|
||
self.printErrTemplate()
|
||
cl_overriding.printERROR(\
|
||
_("first argument function is not 'ver' or 'num' or 'char'"))
|
||
cl_overriding.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] != "/":
|
||
self.printErrTemplate()
|
||
cl_overriding.printERROR(_("wrong path '%s'")%fileName)
|
||
cl_overriding.exit(1)
|
||
else:
|
||
fileName = pathJoin(self._baseDir, fileName)
|
||
else:
|
||
fileName = terms[1].strip()
|
||
# Если домашняя директория
|
||
if fileName[0] == "~":
|
||
# Получаем директорию пользователя
|
||
fileName = os.path.join(self.homeDir,
|
||
fileName.partition("/")[2],"")[:-1]
|
||
elif fileName[0] != "/":
|
||
self.printErrTemplate()
|
||
cl_overriding.printERROR(_("wrong path '%s'")%fileName)
|
||
cl_overriding.exit(1)
|
||
else:
|
||
fileName = pathJoin(self._baseDir,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"
|
||
textTemplateTmp = textTemplateTmp[:resS.start()] + replace +\
|
||
textTemplateTmp[resS.end():]
|
||
return textTemplateTmp
|
||
|
||
def sharePkg(self, 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 getInstallPkgGentoo(self):
|
||
"""Выдает словарь инсталлированных программ и номеров версий"""
|
||
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 self.sharePkg(pkgs)
|
||
|
||
def pkg(self, nameProg, installProg):
|
||
"""Выдает установленные версии по имени программы"""
|
||
if nameProg in installProg:
|
||
return installProg[nameProg][-1]
|
||
else:
|
||
return ""
|
||
|
||
def funcPkg(self, funArgv, resS, localVars, textTemplateTmp):
|
||
"""Функция шаблона pkg(), выдает номер версии программы"""
|
||
# Название программы
|
||
nameProg = funArgv.replace(" ","")
|
||
# Замена функции в тексте шаблона
|
||
replace = ""
|
||
if "/" in nameProg:
|
||
if nameProg in self.installProg:
|
||
replace = self.pkg(nameProg, self.installProg)
|
||
else:
|
||
category, spl, nProg = nameProg.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 = self.sharePkg(pkgs)
|
||
replace = self.pkg(nameProg, installProg)
|
||
self.installProg.update(installProg)
|
||
else:
|
||
if not self.flagAllPkgScan:
|
||
installProg = self.getInstallPkgGentoo()
|
||
self.installProg.update(installProg)
|
||
templateFunction.flagAllPkgScan = True
|
||
replace = self.pkg(nameProg, self.installProg)
|
||
textTemplateTmp = textTemplateTmp[:resS.start()] + replace +\
|
||
textTemplateTmp[resS.end():]
|
||
return textTemplateTmp
|
||
|
||
def funcRnd(self, funArgv, resS, localVars, textTemplateTmp):
|
||
"""Функция шаблона rnd(), выдает строку случайных символов
|
||
|
||
первый аргумент:
|
||
'num' - числа,
|
||
'pas' - цифры и буквы
|
||
второй аргумент:
|
||
количество символов
|
||
"""
|
||
terms = funArgv.replace(" ","").split(",")
|
||
if not terms[0].strip() or\
|
||
(len(terms)==2 and not terms[1].strip()) or\
|
||
len(terms)!=2:
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
fArgvNames = ['num','pas']
|
||
if not terms[0] in fArgvNames:
|
||
self.printErrTemplate()
|
||
cl_overriding.printERROR(\
|
||
_("first argument function is not 'num' or 'pas'"))
|
||
cl_overriding.exit(1)
|
||
try:
|
||
lenStr = int(terms[1])
|
||
except:
|
||
self.printErrTemplate()
|
||
cl_overriding.printERROR(\
|
||
_("two argument function is not number"))
|
||
cl_overriding.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:
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
textTemplateTmp = textTemplateTmp[:resS.start()] + replace +\
|
||
textTemplateTmp[resS.end():]
|
||
return textTemplateTmp
|
||
|
||
def funcCase(self, funArgv, resS, localVars, textTemplateTmp):
|
||
"""Функция шаблона case(), выдает переменную в определенном регистре
|
||
|
||
первый аргумент:
|
||
'upper' - верхний регистр,
|
||
'lower' - нижний регистр,
|
||
'capitalize' - первая буква в верхнем регистре
|
||
второй аргумент:
|
||
название переменной
|
||
"""
|
||
terms = funArgv.replace(" ","").split(",")
|
||
if not terms[0].strip() or\
|
||
(len(terms)==2 and not terms[1].strip()) or len(terms)!=2:
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
fArgvNames = ['upper','lower','capitalize']
|
||
if not terms[0] in fArgvNames:
|
||
self.printErrTemplate()
|
||
cl_overriding.printERROR(_("first argument function is not 'upper' \
|
||
or 'lower' or 'capitalize'"))
|
||
cl_overriding.exit(1)
|
||
try:
|
||
strValue = str(self.objVar.Get(terms[1]))
|
||
except:
|
||
cl_overriding.printERROR(_("error in template %s")\
|
||
%self.nameTemplate)
|
||
cl_overriding.printERROR(_("error var %s not found")%str(terms[1]))
|
||
cl_overriding.exit(1)
|
||
replace = ""
|
||
strValue = _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")
|
||
textTemplateTmp = textTemplateTmp[:resS.start()] + replace +\
|
||
textTemplateTmp[resS.end():]
|
||
return textTemplateTmp
|
||
|
||
def funcPush(self, funArgv, resS, localVars, textTemplateTmp):
|
||
"""локальная функция записывает значение переменной
|
||
|
||
в стек глобальных переменных
|
||
"""
|
||
terms = funArgv.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:
|
||
self.printErrTemplate()
|
||
cl_overriding.printERROR(_("error var %s exists")\
|
||
%str(nameLocVar))
|
||
cl_overriding.exit(1)
|
||
else:
|
||
# Если переменная не существует
|
||
if len(terms) == 1:
|
||
self.printErrTemplate()
|
||
cl_overriding.printERROR(_("error var %s not exists")\
|
||
%str(nameLocVar))
|
||
cl_overriding.exit(1)
|
||
elif len(terms) == 2:
|
||
value = terms[1].strip()
|
||
self.stackGlobalVars.append(str(value))
|
||
localVars[nameLocVar] = value
|
||
else:
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
replace = ""
|
||
textTemplateTmp = textTemplateTmp[:resS.start()] + replace +\
|
||
textTemplateTmp[resS.end():]
|
||
return textTemplateTmp
|
||
|
||
def funcPop(self, funArgv, resS, localVars, textTemplateTmp):
|
||
"""локальная функция получает значение
|
||
|
||
из стека глобальных переменных и присваивает локальной переменной
|
||
|
||
"""
|
||
terms = funArgv.replace(" ","").split(",")
|
||
# Название локальной переменной
|
||
nameLocVar = terms[0]
|
||
if len(terms) == 1:
|
||
if self.stackGlobalVars:
|
||
localVars[nameLocVar] = self.stackGlobalVars.pop()
|
||
else:
|
||
self.printErrTemplate()
|
||
cl_overriding.printERROR(\
|
||
_("error, gloval variables stack is empty"))
|
||
cl_overriding.exit(1)
|
||
else:
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
replace = ""
|
||
textTemplateTmp = textTemplateTmp[:resS.start()] + replace +\
|
||
textTemplateTmp[resS.end():]
|
||
return textTemplateTmp
|
||
|
||
def loadVarsIni(self, iniFileName):
|
||
""" Читает файл fileName
|
||
создает и заполняет переменные на основе этого файла
|
||
Используеться совместно c funcIni
|
||
"""
|
||
localVarsIni = {}
|
||
# получить объект ini файла
|
||
config = 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(self, fileName):
|
||
# Получаем время модификации файла
|
||
nameEnvFile = os.path.split(fileName)[1]
|
||
if nameEnvFile in self.timeConfigsIni:
|
||
return self.timeConfigsIni[nameEnvFile]
|
||
return 0
|
||
|
||
def funcIni(self, funArgv, resS, localVars, textTemplateTmp):
|
||
"""локальная функция записывает и считывает значение переменной
|
||
|
||
из ini файла ~./calculate/ini.env
|
||
"""
|
||
# Создаем директорию
|
||
if not os.path.exists(self.pathConfigIni):
|
||
os.makedirs(self.pathConfigIni)
|
||
os.chown(self.pathConfigIni, self.uid, self.gid)
|
||
termsRaw = funArgv.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:
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
replace = ""
|
||
# Получаем время модификации конфигурационного файла
|
||
curTime = self.getTimeFile(self.fileConfigIni)
|
||
if len(terms) == 1:
|
||
if self.timeIni != curTime:
|
||
# читаем переменные из файла
|
||
self.prevDictIni = self.loadVarsIni(self.fileConfigIni)
|
||
self.currDictIni.update(self.prevDictIni)
|
||
self.timeIni = self.getTimeFile(self.fileConfigIni)
|
||
if nameLocVar in self.currDictIni.keys():
|
||
replace = self.currDictIni[nameLocVar]
|
||
elif len(terms) == 2:
|
||
if self.timeIni != curTime:
|
||
# читаем переменные из файла
|
||
self.prevDictIni = self.loadVarsIni(self.fileConfigIni)
|
||
self.currDictIni.update(self.prevDictIni)
|
||
self.timeIni = self.getTimeFile(self.fileConfigIni)
|
||
# Значение локальной переменной
|
||
valueLocVar = terms[1]
|
||
self.currDictIni[nameLocVar] = valueLocVar
|
||
else:
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
textTemplateTmp = textTemplateTmp[:resS.start()] + replace +\
|
||
textTemplateTmp[resS.end():]
|
||
return (textTemplateTmp)
|
||
|
||
def funcReplace(self, funArgv, resS, localVars, textTemplateTmp):
|
||
"""локальная функция заменяет в значении переменной old на new
|
||
|
||
replace(old, new, name_var_template)
|
||
|
||
одинарные и двойные кавычки должны быть обязательно использованы
|
||
в первых двух аргументах old и new
|
||
"test\ntest" - преобразование строки (строка с переводом)
|
||
'test\ntest' - без преобразования (одна строка)
|
||
"""
|
||
def getStrArgv(terms):
|
||
"""Определяет в двойных или одинарных кавычках параметры
|
||
|
||
Результат [(тип, аргумент),...] [("double", arg1).]
|
||
"""
|
||
listArgv = []
|
||
for term in terms:
|
||
if term.startswith('"') and term.endswith('"'):
|
||
replTerms = [(r"\'", "'"), (r'\"', '"'), (r'\n', '\n'),
|
||
(r'\r', '\r'), (r'\t', '\t'), (r"\\", "\\")]
|
||
textArgv = term[1:-1]
|
||
for replTerm in replTerms:
|
||
textArgv = textArgv.replace(*replTerm)
|
||
listArgv.append(textArgv)
|
||
elif term.startswith("'") and term.endswith("'"):
|
||
listArgv.append(term[1:-1])
|
||
else:
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
return listArgv
|
||
|
||
terms = map(lambda x: x.strip(), funArgv.split(","))
|
||
if len(terms) != 3:
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
listArgv = getStrArgv(terms[:2])
|
||
old = listArgv[0]
|
||
new = listArgv[1]
|
||
nameVar = terms[2]
|
||
# Получаем значение переменной
|
||
if nameVar in localVars:
|
||
value = str(localVars[nameVar])
|
||
else:
|
||
try:
|
||
value = str(self.objVar.Get(nameVar))
|
||
except:
|
||
self.printErrTemplate()
|
||
cl_overriding.printERROR(_("not found template variable '%s'")\
|
||
%str(nameVar))
|
||
cl_overriding.exit(1)
|
||
replace = value.replace(old,new)
|
||
textTemplateTmp = textTemplateTmp[:resS.start()] + replace +\
|
||
textTemplateTmp[resS.end():]
|
||
return textTemplateTmp
|
||
|
||
def funcEnv(self, funArgv, resS, localVars, textTemplateTmp):
|
||
"""Функция шаблона env(), выдает значение переменной из env файлов
|
||
"""
|
||
terms = funArgv.replace(" ","").split(",")
|
||
if len(terms) != 1:
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
nameVar = terms[0]
|
||
replace = ''
|
||
if nameVar in self.valuesVarEnv:
|
||
replace = self.valuesVarEnv[nameVar]
|
||
else:
|
||
# Получаем значение из env файлов
|
||
value = self.objVar.GetIniVar(nameVar)
|
||
if value is False:
|
||
self.printErrTemplate()
|
||
errMsg = self.getError()
|
||
if errMsg:
|
||
cl_overriding.printERROR(errMsg)
|
||
cl_overriding.exit(1)
|
||
self.valuesVarEnv[nameVar] = value
|
||
replace = value
|
||
textTemplateTmp = textTemplateTmp[:resS.start()] + replace +\
|
||
textTemplateTmp[resS.end():]
|
||
return textTemplateTmp
|
||
|
||
def funcServer(self, funArgv, resS, localVars, textTemplateTmp):
|
||
"""Функция шаблона info(), выдает значение опций сервиса
|
||
|
||
из /var/calculate/remote/calculate.env
|
||
"""
|
||
terms = funArgv.replace(" ","").split(",")
|
||
if len(terms)==0 or len(terms)>2:
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
nameLocalVar = ""
|
||
if len(terms)==2:
|
||
if not terms[1]:
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
nameLocalVar = terms[1]
|
||
textLine = terms[0]
|
||
vals = textLine.split(".")
|
||
if len(vals)!= 2:
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
if filter(lambda x: not x.strip(), vals):
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
service, option = vals
|
||
if not service or not option:
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
if not self.optionsInfo:
|
||
# файл /var/calculate/remote/server.env
|
||
envFile = self.objVar.Get("cl_env_server_path")
|
||
# получаем словарь всех информационных переменных
|
||
if self.convObj:
|
||
optInfo = self.convObj.convert()
|
||
else:
|
||
optInfo = self.objVar.GetRemoteInfo(envFile)
|
||
if optInfo is False:
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
if optInfo:
|
||
self.optionsInfo = optInfo
|
||
replace = ''
|
||
if service in self.optionsInfo and option in self.optionsInfo[service]:
|
||
value = self.optionsInfo[service][option]
|
||
if nameLocalVar:
|
||
localVars[nameLocalVar] = value
|
||
else:
|
||
replace = value
|
||
elif nameLocalVar:
|
||
localVars[nameLocalVar] = ""
|
||
textTemplateTmp = textTemplateTmp[:resS.start()] + replace +\
|
||
textTemplateTmp[resS.end():]
|
||
return textTemplateTmp
|
||
|
||
def funcGroups(self, funArgv, resS, localVars, textTemplateTmp):
|
||
"""Функция шаблона groups(),
|
||
проверяет нахождение пользователя в группах, если находится выдает '1'
|
||
"""
|
||
terms = map(lambda x: x.strip(), funArgv.split(","))
|
||
groupNames = set(terms)
|
||
userGroups = set(self.groups)
|
||
replace = ""
|
||
if groupNames & userGroups:
|
||
replace = "1"
|
||
textTemplateTmp = textTemplateTmp[:resS.start()] + replace +\
|
||
textTemplateTmp[resS.end():]
|
||
return textTemplateTmp
|
||
|
||
def funcBelong(self, funArgv, resS, localVars, textTemplateTmp):
|
||
"""Функция шаблона belong().
|
||
В случае установки переменной os_belongs_pkg=имя пакета, и совпадения
|
||
имени пакета в переменной и имени пакета в функции выдает "1" иначе ""
|
||
Если переменная os_belongs_pkg пуста выдает "1"
|
||
"""
|
||
terms = funArgv.replace(" ","").split(",")
|
||
if len(terms) != 1:
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
funcPkg = terms[0]
|
||
if not funcPkg:
|
||
funcPkg = os.path.split(os.path.dirname(self.nameTemplate))[1]
|
||
if not funcPkg:
|
||
cl_overriding.printERROR(_("incorrect template path"))
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
pkg = self.objVar.Get("cl_belong_pkg")
|
||
replace = ""
|
||
if pkg:
|
||
if pkg == funcPkg:
|
||
replace = "1"
|
||
else:
|
||
replace = "1"
|
||
textTemplateTmp = textTemplateTmp[:resS.start()] + replace +\
|
||
textTemplateTmp[resS.end():]
|
||
return textTemplateTmp
|
||
|
||
def funcList(self, funArgv, resS, localVars, textTemplateTmp):
|
||
"""Функция шаблона list().
|
||
Если первый аргумент является именем локальной или глобальной
|
||
переменной и значение переменной является списком, выдает
|
||
элемент списка по второму аргументу индексу.
|
||
Первый элемент имеет индекс 0
|
||
"""
|
||
terms = funArgv.replace(" ","").split(",")
|
||
# У функции должно быть два аргумента
|
||
if len(terms) != 2:
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
# Название локальной или глобальной переменной
|
||
nameLocVar = terms[0]
|
||
strIndex = terms[1]
|
||
try:
|
||
intIndex = int(strIndex)
|
||
except:
|
||
cl_overriding.printERROR(_("'%s' is not a number")%strIndex)
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
flagFoundVar = False
|
||
if nameLocVar in localVars.keys():
|
||
flagFoundVar = True
|
||
value = localVars[nameLocVar]
|
||
else:
|
||
try:
|
||
value = self.objVar.Get(nameLocVar)
|
||
flagFoundVar = True
|
||
except:
|
||
pass
|
||
if not flagFoundVar:
|
||
# Если переменная не существует
|
||
cl_overriding.printERROR(_("error var %s not exists")\
|
||
%str(nameLocVar))
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
if not type(value) in (list,tuple):
|
||
# Значение переменной не список или кортеж
|
||
cl_overriding.printERROR(_("value of %s is not a list or tuple")\
|
||
%str(nameLocVar))
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
try:
|
||
replace = str(value[intIndex])
|
||
except:
|
||
cl_overriding.printERROR(_("%s wrong")%strIndex)
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
textTemplateTmp = textTemplateTmp[:resS.start()] + replace +\
|
||
textTemplateTmp[resS.end():]
|
||
return textTemplateTmp
|
||
|
||
def funcDisk(self, funArgv, resS, localVars, textTemplateTmp):
|
||
"""Функция шаблона disk().
|
||
Первый аргумент ищется в значении переменной os_disk_install
|
||
(значение os_install_disk_mount - список точек монтирования при установке)
|
||
второй аргумент используется для поиска в переменной
|
||
os_disk_второй_аргумент (значение os_disk_второй_аргумент - список)
|
||
В os_install_disk_mount ищется первый аргумент, находим его индекс
|
||
результат - элемент cписка из os_disk_второй_аргумент с этим индексом
|
||
"""
|
||
terms = funArgv.replace(" ","").split(",")
|
||
# У функции должно быть два аргумента
|
||
if len(terms) != 2:
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
# Название глобальной переменной
|
||
mountPoint = terms[0]
|
||
lastElementVar = terms[1]
|
||
if not mountPoint or mountPoint[:1] !="/":
|
||
cl_overriding.printERROR(_("%s wrong")%lastElementVar)
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
nameVar = "os_install_disk_mount"
|
||
try:
|
||
valueVar = self.objVar.Get(nameVar)
|
||
except:
|
||
# Если переменная не существует
|
||
cl_overriding.printERROR(_("error var %s not exists")%nameVar)
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
nameElementVar = "os_disk_%s"%lastElementVar
|
||
try:
|
||
valueElementVar = self.objVar.Get(nameElementVar)
|
||
except:
|
||
# Если переменная не существует
|
||
cl_overriding.printERROR(_("%s wrong")%lastElementVar)
|
||
cl_overriding.printERROR(_("error var %s not exists")\
|
||
%nameElementVar)
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
if not type(valueVar) in (list,tuple):
|
||
# Значение переменной не список или кортеж
|
||
cl_overriding.printERROR(_("value of %s is not a list or tuple")\
|
||
%nameVar)
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
if not type(valueElementVar) in (list,tuple):
|
||
# Значение переменной не список или кортеж
|
||
cl_overriding.printERROR(_("value of %s is not a list or tuple")\
|
||
%nameElementVar)
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
if len(valueVar) != len(valueElementVar):
|
||
cl_overriding.printERROR(\
|
||
_("size %s is not equal to the size of %s")\
|
||
%(nameVar, nameElementVar))
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
index = None
|
||
for num, mPoint in enumerate(valueVar):
|
||
if mountPoint == mPoint:
|
||
index = num
|
||
break
|
||
if index is None:
|
||
for num, mPoint in enumerate(valueVar):
|
||
if "/" == mPoint:
|
||
index = num
|
||
break
|
||
if index is None:
|
||
cl_overriding.printERROR(_("in the value of the variable \
|
||
os_disk_install not found mount point '\' and '\%s'")%mountPoint)
|
||
self.printErrTemplate()
|
||
cl_overriding.exit(1)
|
||
replace = valueElementVar[index]
|
||
textTemplateTmp = textTemplateTmp[:resS.start()] + replace +\
|
||
textTemplateTmp[resS.end():]
|
||
return textTemplateTmp
|
||
|
||
def printErrTemplate(self):
|
||
"""Печать ошибки при обработке функций шаблона"""
|
||
cl_overriding.printERROR(_("error in template %s")%self.nameTemplate)
|
||
cl_overriding.printERROR(_("error template term '%s'")\
|
||
%str(self.functText))
|
||
|
||
def applyFuncTemplate(self, textTemplate, nameTemplate):
|
||
"""Применяет функции к тексту шаблона"""
|
||
# Локальные переменные
|
||
localVars = {}
|
||
# Имя обрабатываемого шаблона
|
||
self.nameTemplate = nameTemplate
|
||
# Регулярное выражение для поиска функции в шаблоне
|
||
reFunc = self._reFunc
|
||
resS = reFunc.search(textTemplate)
|
||
textTemplateTmp = textTemplate
|
||
flagIniFunc = False
|
||
while resS:
|
||
mark = textTemplateTmp[resS.start():resS.end()]
|
||
self.functText = mark[self._deltVarStart:-self._deltVarEnd]
|
||
funcName, spl, funcEnd = self.functText.partition("(")
|
||
if funcName in self.namesTemplateFunction:
|
||
# аргументы функции - '(' аргументы ')'
|
||
funArgv = funcEnd.rpartition(")")[0]
|
||
# вызов функции шаблона
|
||
textTemplateTmp = self.templateFunction[funcName](self, funArgv,
|
||
resS, localVars,
|
||
textTemplateTmp)
|
||
resS = reFunc.search(textTemplateTmp)
|
||
if funcName == "ini":
|
||
flagIniFunc = True
|
||
else:
|
||
self.printErrTemplate()
|
||
cl_overriding.printERROR(\
|
||
_("can not found template function '%s'")\
|
||
%str(self.functText))
|
||
cl_overriding.exit(1)
|
||
|
||
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 = self.getTimeFile(self.fileConfigIni)
|
||
if curTime != self.timeIni:
|
||
# Считаем переменные из конф. файла
|
||
self.prevDictIni = self.loadVarsIni(self.fileConfigIni)
|
||
self.currDictIni.update(self.prevDictIni)
|
||
self.timeIni = curTime
|
||
# Если словари переменных не совпадают
|
||
if self.prevDictIni != self.currDictIni:
|
||
# Запишем переменные в конфигурационный файл
|
||
# Создание объекта парсера
|
||
config = 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 = self.loadVarsIni(self.fileConfigIni)
|
||
self.currDictIni.update(self.prevDictIni)
|
||
self.timeConfigsIni[self.fileConfigIni] = float(time.time())
|
||
self.timeIni = self.getTimeFile(self.fileConfigIni)
|
||
# Меняем владельца в случае необходимости
|
||
if os.path.exists(self.fileConfigIni):
|
||
uid, gid = getModeFile(self.fileConfigIni, "owner")
|
||
if self.uid!=uid or self.gid!=gid:
|
||
os.chown(self.fileConfigIni, self.uid, self.gid)
|
||
return textTemplateTmp
|
||
|
||
class template(_file, _terms, xmlShare, templateFormat, _shareTemplate):
|
||
"""Класс для работы с шаблонами
|
||
|
||
На вход 2 параметра: объект хранения переменных, имя сервиса - не
|
||
обязательный параметр
|
||
|
||
"""
|
||
# Название файла шаблона директории
|
||
templDirNameFile = ".calculate_directory"
|
||
|
||
def __init__(self, objVar, servDir=False, dirsFilter=[], filesFilter=[],
|
||
cltObj=True, cltFilter=True):
|
||
# Необрабатываемые директории
|
||
self.dirsFilter = dirsFilter
|
||
# Необрабатываемые файлы
|
||
self.filesFilter = filesFilter
|
||
_file.__init__(self)
|
||
# Словарь для создания объектов новых классов по образцу
|
||
self.newObjProt = {'proftpd':'apache'}
|
||
# Заголовок title
|
||
self.__titleHead = "--------------------------------------\
|
||
----------------------------------------"
|
||
self._titleBody = ""
|
||
self._titleList = (_("Modified"), _("Processed template files") + ":")
|
||
self._reVar = re.compile(("%s[a-zA-Z0-9_-]+%s")%(self.varStart,
|
||
self.varEnd),re.M)
|
||
# Условия
|
||
self._reTermBloc = re.compile("#\?(?P<rTerm>[a-zA-Z0-9\-_]+)\
|
||
(?P<func>\((%s+|)\))?\
|
||
(?P<lTerm>[\>\<\=\!\&\|]+\
|
||
[\>\<\=\!\|\&\(\)%s]*)#\
|
||
\n*(?P<body>.+?)\n*#(?P=rTerm)#(?P<end>[ ,\t]*\n?)"\
|
||
%(self._reFunctionArgvText, self._reFunctionArgvInSquareBrackets),
|
||
re.M|re.S)
|
||
# Объект с переменными
|
||
self.objVar = objVar
|
||
# Базовая директория переноса шаблонов "/mnt/calculate" или "/" и.т.д
|
||
self._baseDir = pathJoin(self.objVar.Get("cl_chroot_path"),
|
||
self.objVar.Get("cl_root_path"))
|
||
# Последняя часть директории шаблона (имя сервиса: 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.numberProcessTempl = 0
|
||
# имя текущей программы
|
||
_nameProgram = self.objVar.Get("cl_name").capitalize()
|
||
# версия текущей программы
|
||
_versionProgram = self.objVar.Get("cl_ver")
|
||
# имя и версия текущей программы
|
||
self.programVersion = "%s %s"%(_nameProgram, _versionProgram)
|
||
# Словарь директорий с количеством файлов шаблонов
|
||
self.dictTemplates = {}
|
||
# Общее количество шаблонов
|
||
self.allTemplates = 0
|
||
# Объект функций шаблона
|
||
self.functObj = templateFunction(self.objVar)
|
||
# Метод применения функций к шаблонам
|
||
self.applyFuncTemplate = self.functObj.applyFuncTemplate
|
||
# Объект для определения типа файла шаблона
|
||
self.typeFileObj = typeFile()
|
||
self.uid, self.gid, self.homeDir = self.getDataUser()
|
||
# Домашняя директория, плюс базовая директория
|
||
self.homeDir = pathJoin(self._baseDir, self.homeDir)
|
||
# Глобальный словарь обработанных шаблонов файлов
|
||
# {путь к конф. файлу:[имена шаблонов] ...}
|
||
self.dictProcessedTemplates = {}
|
||
if cltObj is True:
|
||
# Объект templateClt
|
||
self.cltObj = templateClt(self.objVar)
|
||
elif cltObj:
|
||
# Объект templateClt
|
||
self.cltObj = cltObj
|
||
else:
|
||
# Объект templateClt
|
||
self.cltObj = False
|
||
# Фильтровать ли шаблоны clt по конфигурационным файлам обычных шаблонов
|
||
self.cltFilter = cltFilter
|
||
|
||
|
||
# Преобразование восьмеричного в целое (ввод строка, вывод число)
|
||
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 getTemplateType(self):
|
||
"""выдать тип шаблона (text, bin)"""
|
||
isBin = self.typeFileObj.isBinary(self.nameFileTemplate)
|
||
typeTemplate = "bin"
|
||
if isBin is True:
|
||
typeTemplate = "bin"
|
||
elif isBin is False:
|
||
typeTemplate = "text"
|
||
else:
|
||
self.setError(_("ERROR") + ": getTemplateType()")
|
||
self.setError(isBin)
|
||
return False
|
||
return typeTemplate
|
||
|
||
def createDir(self, dirName, mode=False, uid=False, gid=False):
|
||
"""Создает директорию"""
|
||
if os.access(dirName, os.F_OK):
|
||
return True
|
||
else:
|
||
dMode = False
|
||
prevDir, tmpSubdir = os.path.split(dirName)
|
||
createDirs = []
|
||
while not os.access(prevDir, os.F_OK) and prevDir:
|
||
createDirs.append(prevDir)
|
||
prevDir = os.path.split(prevDir)[0]
|
||
try:
|
||
dUid,dGid = getModeFile(prevDir,"owner")
|
||
except OSError:
|
||
self.setError(_("Not access dir: " ) + prevDir)
|
||
return False
|
||
if not mode is False:
|
||
dMode = mode
|
||
if not uid is False:
|
||
dUid = uid
|
||
if not gid is False:
|
||
dGid = gid
|
||
createDirs.reverse()
|
||
for nameDir in createDirs:
|
||
try:
|
||
if dMode:
|
||
os.mkdir(nameDir, dMode)
|
||
else:
|
||
os.mkdir(nameDir)
|
||
os.chown(nameDir, dUid, dGid)
|
||
except:
|
||
self.setError(_("Can not create dir: " ) + nameDir)
|
||
return False
|
||
try:
|
||
if dMode:
|
||
os.mkdir(dirName, dMode)
|
||
else:
|
||
os.mkdir(dirName)
|
||
os.chown(dirName, dUid, dGid)
|
||
createDirs.append(dirName)
|
||
except:
|
||
self.setError(_("Can not create dir: " ) + dirName)
|
||
return False
|
||
return createDirs
|
||
|
||
def applyVarsTemplate(self, textTemplate, nameTemplate):
|
||
""" Заменяет переменные на их значения
|
||
"""
|
||
resS = self._reVar.search(textTemplate)
|
||
textTemplateTmp = textTemplate
|
||
while resS:
|
||
mark = textTemplateTmp[resS.start():resS.end()]
|
||
varName = mark[self._deltVarStart:-self._deltVarEnd]
|
||
varValue = ""
|
||
try:
|
||
varValue = str(self.objVar.Get(varName))
|
||
except self.objVar.DataVarsError, e:
|
||
cl_overriding.printERROR(_("error in template %s")%nameTemplate)
|
||
cl_overriding.printERROR(e)
|
||
cl_overriding.exit(1)
|
||
textTemplateTmp = textTemplateTmp.replace(mark, varValue)
|
||
resS = self._reVar.search(textTemplateTmp)
|
||
return textTemplateTmp
|
||
|
||
def applyTermsTemplate(self,textTemplate,nameTemplate):
|
||
""" Применяет условия, к условным блокам текста
|
||
"""
|
||
def function(text):
|
||
"""Функция обработки функций в заголовке"""
|
||
return self.applyFuncTemplate(text, nameTemplate)
|
||
|
||
textTerm = ""
|
||
resS = self._reTermBloc.search(textTemplate)
|
||
textTemplateTmp = textTemplate
|
||
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 template not valid: ")+\
|
||
nameTemplate, function):
|
||
textTemplateTmp = textTemplateTmp.replace(mark, body+end)
|
||
else:
|
||
textTemplateTmp = textTemplateTmp.replace(mark, "")
|
||
resS = self._reTermBloc.search(textTemplateTmp)
|
||
return textTemplateTmp
|
||
|
||
def getNeedTemplate(self, fileTemplate):
|
||
"""Применяем правила к названию файла"""
|
||
dirP,fileP = os.path.split(fileTemplate)
|
||
if fileP:
|
||
spFile = fileP.split("?")
|
||
realFileName = spFile[0]
|
||
if len(spFile)>1:
|
||
flagTrue = False
|
||
for term in spFile[1:]:
|
||
if self._equalTerm(term, _("name template not valid: ")+\
|
||
fileTemplate):
|
||
flagTrue = True
|
||
break
|
||
if flagTrue:
|
||
return True
|
||
else:
|
||
return False
|
||
else:
|
||
return True
|
||
else:
|
||
self.setError(_("name template not valid: ")+ str(fileTemplate))
|
||
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
|
||
flagFirst = True
|
||
for com in list(self._titleList) + [""]*(len(commentList)):
|
||
if com:
|
||
if flagFirst:
|
||
self._titleBody += commentInsert + " " + com + " "+\
|
||
self.programVersion + "\n"
|
||
flagFirst = False
|
||
else:
|
||
self._titleBody += commentInsert + " " + com + "\n"
|
||
else:
|
||
self._titleBody += commentInsert + " " +\
|
||
commentList[z] + "\n"
|
||
z += 1
|
||
if flagList:
|
||
self._titleBody += commentLast +"\n"
|
||
else:
|
||
self._titleBody += commentLast + self.__titleHead + "\n"
|
||
return self._titleBody
|
||
else:
|
||
return ""
|
||
|
||
def numberAllTemplates(self, number):
|
||
"""Количество шаблонов
|
||
|
||
Вызов происходит перед наложением шаблонов
|
||
в момент вызова в number находится количество обрабатываемых файлов
|
||
Наследуемая функция
|
||
Используется для отображения прогресса при наложениии шаблонов
|
||
"""
|
||
return True
|
||
|
||
def numberProcessTemplates(self, number):
|
||
"""Номер текущего обрабатываемого шаблона
|
||
|
||
Вызов происходит при наложении шаблона
|
||
в момент вызова в number находится номер обрабатываемого шаблона
|
||
Наследуемая функция
|
||
Используется для отображения прогресса при наложениии шаблонов
|
||
"""
|
||
return True
|
||
|
||
def applyTemplates(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_template_path"):
|
||
self.setError(_("not defined Var: ") + "cl_template_path")
|
||
return False
|
||
dirsTemplates = self.objVar.Get("cl_template_path")
|
||
dirsTemplates.sort()
|
||
# Созданные директории
|
||
self.createdDirs = []
|
||
# Примененные файлы
|
||
self.filesApply = []
|
||
# Номер применяемого шаблона
|
||
self.numberProcessTempl = 0
|
||
# Словарь директорий с количеством файлов шаблонов
|
||
self.dictTemplates = {}
|
||
# Количество шаблонов
|
||
self.allTemplates = 0
|
||
# Установка по умолчанию аттрибутов для функциии шаблонов ini()
|
||
# Время доступа к конфигурационному файлу функции шаблона ini()
|
||
self.functObj.timeIni = -1
|
||
# Первоначальный словарь переменных для ini()
|
||
self.functObj.prevDictIni = {}
|
||
# Текущий словарь переменных для ini()
|
||
self.functObj.currDictIni = {}
|
||
# Словарь времен модификации env файлов для ini()
|
||
self.functObj.timeConfigsIni = {}
|
||
|
||
if self._servDir:
|
||
tmpDirsTemplates = []
|
||
for dirP in dirsTemplates:
|
||
dirTempl = dirP + self._servDir
|
||
if os.access(dirTempl, os.F_OK):
|
||
# Если директория существует
|
||
tmpDirsTemplates.append(dirTempl)
|
||
dirsTemplates = tmpDirsTemplates
|
||
scanObj = scanDirectory()
|
||
scanObj.processingFile = lambda x,y: createDictTemplates(x, y,\
|
||
self.dictTemplates)
|
||
# Считаем количество шаблонов
|
||
dirsTemplatesExists = filter(lambda x: os.path.exists(x), dirsTemplates)
|
||
if not dirsTemplatesExists:
|
||
self.setError(_("No such template directories") +\
|
||
": %s"%", ".join(map(lambda x: "'%s'"%x ,dirsTemplates)))
|
||
return (self.createdDirs, self.filesApply)
|
||
for dirTemplate in dirsTemplatesExists:
|
||
scanObj.scanningDirectory(dirTemplate)
|
||
# Считаем количество шаблонов clt
|
||
if self.cltObj:
|
||
# Считаем количество шаблонов clt
|
||
self.cltObj.countsNumberTemplates()
|
||
# не считать количество файлов в объекте self.cltObj
|
||
self.cltObj.checkNumberTemplate = False
|
||
# начальны номер clt шаблона
|
||
self.cltObj.numberProcessTempl = self.allTemplates
|
||
# метод показывающий номер clt шаблона
|
||
self.cltObj.numberProcessTemplates = self.numberProcessTemplates
|
||
# общее количество шаблонов
|
||
self.allTemplates += self.cltObj.allTemplates
|
||
self.cltObj.allTemplates = self.allTemplates
|
||
self.numberAllTemplates(self.allTemplates)
|
||
# Обрабатываем шаблоны
|
||
for dirTemplate in dirsTemplatesExists:
|
||
if self.scanningTemplates(dirTemplate) is False:
|
||
return False
|
||
if self.cltObj:
|
||
# Созданные директории
|
||
self.cltObj.createdDirs = self.createdDirs
|
||
# Примененные файлы
|
||
self.cltObj.filesApply = self.filesApply
|
||
# Словарь директорий с количеством файлов шаблонов
|
||
self.cltObj.dictTemplates = self.dictTemplates
|
||
# Количество шаблонов
|
||
self.cltObj.allTemplates = self.allTemplates
|
||
# Установка по умолчанию аттрибутов для функциии шаблонов ini()
|
||
# Время доступа к конфигурационному файлу функции шаблона ini()
|
||
self.cltObj.functObj = self.functObj
|
||
# Словарь примененных файлов шаблонов
|
||
self.cltObj.dictProcessedTemplates = self.dictProcessedTemplates
|
||
if self.cltFilter:
|
||
# Шаблоны + .clt которые будут применены
|
||
self.cltObj.filterApplyTemplates=\
|
||
map(lambda x: pathJoin('/', x.partition(self._baseDir)[2]),
|
||
self.dictProcessedTemplates.keys())
|
||
# Обрабатываем шаблоны clt
|
||
if not self.cltObj.applyTemplates():
|
||
return False
|
||
return (self.createdDirs, self.filesApply)
|
||
|
||
|
||
def scanningTemplates(self, scanDir, prefix=None, flagDir=False, optDir={}):
|
||
"""Сканирование и обработка шаблонов в директории scanDir"""
|
||
ret = True
|
||
if not prefix:
|
||
prefix = os.path.realpath(scanDir)
|
||
if not flagDir:
|
||
# проверка корневой директории
|
||
retDir = self.processingDirectory(scanDir, scanDir, optDir)
|
||
if retDir is None:
|
||
return None
|
||
elif retDir is False:
|
||
return False
|
||
pathDir, objHead = retDir
|
||
optDir["path"] = pathDir
|
||
if not objHead is True and objHead.typeAppend == "skip":
|
||
# Установка опции пропуска директории
|
||
optDir["skip"] = True
|
||
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)
|
||
stInfo = os.lstat(absPath)
|
||
statInfo = stInfo[stat.ST_MODE]
|
||
if stat.S_ISREG(statInfo):
|
||
if not self.processingFile(absPath, prefix, optDir):
|
||
ret = False
|
||
break
|
||
elif stat.S_ISDIR(statInfo):
|
||
# Обработка директории
|
||
retDir = self.processingDirectory(absPath, prefix,
|
||
optDir)
|
||
if retDir is None:
|
||
continue
|
||
elif retDir is False:
|
||
ret = False
|
||
break
|
||
# Опции следующей директории
|
||
optNextDir = {}
|
||
pathDir, objHead = retDir
|
||
optNextDir["path"] = pathDir
|
||
if not objHead is True and objHead.typeAppend == "skip":
|
||
# Установка опции пропуска директории
|
||
optNextDir["skip"] = True
|
||
ret = self.scanningTemplates(absPath, prefix, True,
|
||
optNextDir)
|
||
if ret is False:
|
||
break
|
||
return ret
|
||
|
||
|
||
def processingFile(self, path, prefix, optFile):
|
||
"""Обработка в случае шаблона файла"""
|
||
self.numberProcessTempl += 1
|
||
self.numberProcessTemplates(self.numberProcessTempl)
|
||
# Пропуск шаблонов директорий
|
||
if self.templDirNameFile == os.path.split(path)[1]:
|
||
return True
|
||
# Проверка на переменные в названии файла
|
||
if not self.getNeedTemplate(path):
|
||
if self.getError():
|
||
return False
|
||
return True
|
||
if self.getError():
|
||
return False
|
||
nameFileConfig = path.partition(prefix)[2]
|
||
# файл в системе без условий
|
||
nameFileConfig = "/".join(map(lambda x:x.split("?")[0],\
|
||
nameFileConfig.split("/")))
|
||
# Записываем в переменную обрабатываемый файл
|
||
self.objVar.Set("cl_pass_file",nameFileConfig)
|
||
# Пишем время модификации *.env файлов
|
||
if nameFileConfig.endswith(".env"):
|
||
nameEnvFile = os.path.split(nameFileConfig)[1]
|
||
self.functObj.timeConfigsIni[nameEnvFile] = float(time.time())
|
||
filesApl = self.joinTemplate(path, nameFileConfig, optFile)
|
||
if self.getError():
|
||
return False
|
||
if filesApl:
|
||
self.filesApply += filesApl
|
||
return True
|
||
|
||
def processingDirectory(self, path, prefix, opt):
|
||
"""Обработка в случае директории если возвращаем None то пропуск дир."""
|
||
# Файл шаблона директории
|
||
dirInfoFile = os.path.join(path, self.templDirNameFile)
|
||
newDir = pathJoin(self._baseDir, path.partition(prefix)[2])
|
||
newDir = "/".join(map(lambda x:x.split("?")[0], newDir.split("/")))
|
||
# Применяем шаблон
|
||
pathDir, objHeadDir, createdDirs =\
|
||
self.__getApplyHeadDir(newDir, dirInfoFile, opt)
|
||
if createdDirs:
|
||
self.createdDirs += createdDirs
|
||
if objHeadDir:
|
||
return pathDir, objHeadDir
|
||
else:
|
||
if self.getError():
|
||
return False
|
||
# Добавление количества файлов в пропущенной директории
|
||
if path in self.dictTemplates.keys():
|
||
self.numberProcessTempl += self.dictTemplates[path]
|
||
return None
|
||
|
||
def __getApplyHeadDir(self, newDir, templateDirFile, optDir):
|
||
"""Применяет шаблон к директории (права, владелец, и.т. д)"""
|
||
|
||
def function(text):
|
||
"""Функция обработки функций в заголовке"""
|
||
return self.applyFuncTemplate(text, templateDirFile)
|
||
|
||
def chownConfDir(nameDirConfig, uid, gid, nameFileTemplate):
|
||
"""Изменение владельца конфигурационной директории"""
|
||
try:
|
||
os.chown(nameDirConfig, uid, gid)
|
||
except:
|
||
import pwd, grp
|
||
try:
|
||
userName = pwd.getpwuid(uid).pw_name
|
||
except:
|
||
userName = str(uid)
|
||
try:
|
||
groupName = grp.getgrgid(gid).gr_name
|
||
except:
|
||
groupName = str(gid)
|
||
owner = userName + ":" + groupName
|
||
self.setError(_("Failed to apply template file %s")\
|
||
%nameFileTemplate)
|
||
self.setError(_("error") + " " +\
|
||
"'chown %s %s'"%(owner, nameDirConfig))
|
||
return False
|
||
return True
|
||
|
||
applyDir = newDir
|
||
# Родительская директория
|
||
if optDir.get("path"):
|
||
path = optDir["path"]
|
||
else:
|
||
path = os.path.split(applyDir)[1]
|
||
path = pathJoin(self._baseDir, path)
|
||
if not os.path.exists(templateDirFile):
|
||
applyDir = os.path.join(path, os.path.split(applyDir)[1])
|
||
# Фильтрация шаблонов по названию директории
|
||
realPath = os.path.join("/",applyDir.partition(self._baseDir)[2])
|
||
if realPath in self.dirsFilter:
|
||
return ("", False, [])
|
||
# Создаем директорию если необходимо
|
||
crDirs = self.createDir(applyDir, False, self.uid, self.gid)
|
||
if not crDirs:
|
||
return ("", False, [])
|
||
if crDirs is True:
|
||
return (applyDir, True, [])
|
||
else:
|
||
return (applyDir, True, crDirs)
|
||
try:
|
||
FD = open(templateDirFile)
|
||
textTemplate = FD.read()
|
||
FD.close()
|
||
except:
|
||
self.setError(_("Error open template") + ": " +\
|
||
templateDirFile)
|
||
return ("", False, [])
|
||
|
||
# Заменяем переменные на их значения
|
||
textTemplate = self.applyVarsTemplate(textTemplate, templateDirFile)
|
||
|
||
# Заменяем функции на их значения
|
||
textTemplate = self.applyFuncTemplate(textTemplate, templateDirFile)
|
||
# Обработка заголовка
|
||
objHead = dirHeader(templateDirFile,textTemplate,self.objVar,function)
|
||
# Директория с профилями не будет применена
|
||
if not objHead.headerTerm:
|
||
if objHead.getError():
|
||
self.setError(_("Incorrect template") + ": " +\
|
||
templateDirFile)
|
||
return ("", False, [])
|
||
|
||
# Пропускаем директорию
|
||
if objHead.typeAppend == "skip":
|
||
applyDir = path
|
||
return (applyDir, objHead, [])
|
||
|
||
# Изменяем название родительской директории
|
||
if "path" in objHead.params:
|
||
path = objHead.params['path']
|
||
if path and path[0] == "~":
|
||
# Получаем путь с заменой ~ на директорию пользователя
|
||
path = os.path.join(self.homeDir,
|
||
path.partition("/")[2],"")[:-1]
|
||
elif not path or path and path[0] != "/":
|
||
self.setError(_("False value 'path' in template") + ": " +\
|
||
templateDirFile)
|
||
return ("", False, [])
|
||
else:
|
||
path = pathJoin(self._baseDir, path)
|
||
|
||
# Изменяем название директории
|
||
if "name" in objHead.params:
|
||
nameDir = objHead.params['name']
|
||
if "/" in nameDir or nameDir == ".." or nameDir == ".":
|
||
self.setError(_("False value 'name' in template") + ": " +\
|
||
templateDirFile)
|
||
return ("", False, [])
|
||
# Новый путь к директории
|
||
applyDir = os.path.join(path, nameDir)
|
||
else:
|
||
applyDir = os.path.join(path, os.path.split(applyDir)[1])
|
||
|
||
# Фильтрация шаблонов по названию директории
|
||
realPath = os.path.join("/",applyDir.partition(self._baseDir)[2])
|
||
if realPath in self.dirsFilter:
|
||
return ("", False, [])
|
||
# Удаляем директорию
|
||
if objHead.typeAppend == "remove":
|
||
if os.path.isdir(applyDir):
|
||
# удаляем директорию
|
||
try:
|
||
removeDir(applyDir)
|
||
except:
|
||
self.setError(_("Can not delete dir: " ) +\
|
||
applyDir)
|
||
return ("", False, [])
|
||
|
||
# Созданные директории
|
||
createdDirs = []
|
||
# chmod - изменяем права
|
||
if "chmod" in objHead.params:
|
||
mode = self.__octToInt(objHead.params['chmod'])
|
||
if mode:
|
||
if not os.path.exists(applyDir):
|
||
crDirs = self.createDir(applyDir, mode, self.uid, self.gid)
|
||
if not crDirs:
|
||
return ("", False, [])
|
||
if not crDirs is True:
|
||
createdDirs += crDirs
|
||
else:
|
||
os.chmod(applyDir, mode)
|
||
else:
|
||
self.setError(_("False value 'chmod' in template") + ": " +\
|
||
templateDirFile)
|
||
return ("", False, [])
|
||
# chown - изменяем владельца и группу
|
||
if "chown" in objHead.params:
|
||
owner = objHead.params['chown']
|
||
if owner:
|
||
if ":" in owner:
|
||
strUid, strGid = owner.split(":")
|
||
import pwd
|
||
try:
|
||
uid = pwd.getpwnam(strUid).pw_uid
|
||
except:
|
||
self.setError(_("Not user in this system: ") + strUid)
|
||
self.setError(_("False value 'chown' in template")+\
|
||
": " + templateDirFile)
|
||
return ("", False, [])
|
||
try:
|
||
import grp
|
||
gid = grp.getgrnam(strGid).gr_gid
|
||
except:
|
||
self.setError(_("Not group in this system: ")+strGid)
|
||
self.setError(_("False value 'chown' in template") +\
|
||
": "+ templateDirFile)
|
||
return ("", False, [])
|
||
|
||
if not os.path.exists(applyDir):
|
||
crDirs = self.createDir(applyDir, False, uid, gid)
|
||
if not crDirs:
|
||
return ("", False, [])
|
||
if not crDirs is True:
|
||
createdDirs += crDirs
|
||
else:
|
||
if not chownConfDir(applyDir, uid, gid,
|
||
templateDirFile):
|
||
return ("", False, [])
|
||
else:
|
||
self.setError(_("False value 'chown' in template") + ": " +\
|
||
templateDirFile)
|
||
return ("", False, [])
|
||
else:
|
||
self.setError(_("False value 'chown' in template") + ": " +\
|
||
templateDirFile)
|
||
return ("", False, [])
|
||
else:
|
||
# Устанавливаем владельцем директории, пользователя по умолчанию
|
||
# (переменная шаблона ur_login)
|
||
if os.path.exists(applyDir):
|
||
tUid, tGid = getModeFile(applyDir, mode="owner")
|
||
if (self.uid, self.gid) != (tUid, tGid):
|
||
if not chownConfDir(applyDir, self.uid, self.gid,
|
||
templateDirFile):
|
||
return ("", False, [])
|
||
else:
|
||
crDirs = self.createDir(applyDir, False, self.uid, self.gid)
|
||
if not crDirs:
|
||
return ("", False, [])
|
||
if not crDirs is True:
|
||
createdDirs += crDirs
|
||
if not objHead:
|
||
applyDir = ""
|
||
return (applyDir, objHead, createdDirs)
|
||
|
||
def __getApplyHeadTemplate(self, nameFileTemplate, nameFileConfig,
|
||
templateFileType, optFile):
|
||
"""Применяет заголовок к шаблону (права, владелец, и.т. д)"""
|
||
def function(text):
|
||
"""Функция обработки функций в заголовке"""
|
||
return self.applyFuncTemplate(text,nameFileTemplate)
|
||
|
||
def preReturn(pathProg):
|
||
"""Действия перед выходом из метода"""
|
||
if pathProg:
|
||
os.chdir(pathProg)
|
||
|
||
def chownConfFile(nameFileConfig, uid, gid, nameFileTemplate,
|
||
checkExists=True):
|
||
"""Изменение владельца конфигурационного файла"""
|
||
try:
|
||
if checkExists and not os.path.exists(nameFileConfig):
|
||
# Создание файла
|
||
FD = open(nameFileConfig, "w")
|
||
FD.close()
|
||
os.chown(nameFileConfig, uid, gid)
|
||
except:
|
||
import pwd, grp
|
||
try:
|
||
userName = pwd.getpwuid(uid).pw_name
|
||
except:
|
||
userName = str(uid)
|
||
try:
|
||
groupName = grp.getgrgid(gid).gr_name
|
||
except:
|
||
groupName = str(gid)
|
||
owner = userName + ":" + groupName
|
||
self.setError(_("Failed to apply template file %s")\
|
||
%nameFileTemplate)
|
||
self.setError(_("error") + " " +\
|
||
"'chown %s %s'"%(owner, nameFileConfig))
|
||
return False
|
||
return True
|
||
|
||
def chmodConfFile(nameFileConfig, mode, nameFileTemplate,
|
||
checkExists=True):
|
||
"""Изменения режима доступа конфигурационного файла"""
|
||
try:
|
||
if checkExists and not os.path.exists(pathOldFile):
|
||
# Создание файла
|
||
FD = open(nameFileConfig, "w")
|
||
FD.close()
|
||
os.chmod(nameFileConfig, mode)
|
||
except:
|
||
self.setError(_("Failed to apply template file %s")\
|
||
%nameFileTemplate)
|
||
self.setError(\
|
||
_("error") + " " +\
|
||
"'chmod %s %s'"%(str(oct(mode)), nameFileConfig))
|
||
return False
|
||
return True
|
||
|
||
self.closeFiles()
|
||
pathProg = ""
|
||
# Файлы в системе к которым были применены шаблоны
|
||
applyFiles = [nameFileConfig]
|
||
# В случае бинарного типа файла читаем шаблон
|
||
if templateFileType == "bin":
|
||
self.nameFileTemplate = os.path.abspath(nameFileTemplate)
|
||
self.F_TEMPL = self.openTemplFile(self.nameFileTemplate)
|
||
self.textTemplate = self.F_TEMPL.read()
|
||
self.closeTemplFile()
|
||
objHeadNew = fileHeader(nameFileTemplate, self.textTemplate, False,
|
||
templateFileType ,objVar=self.objVar,
|
||
function=function)
|
||
# файл шаблона не будет применен
|
||
if not objHeadNew.headerTerm:
|
||
if objHeadNew.getError():
|
||
self.setError(_("Incorrect template") + ": " +\
|
||
nameFileTemplate)
|
||
return ([], False)
|
||
|
||
# Родительская директория
|
||
path = optFile["path"]
|
||
|
||
# Изменяем название родительской директории
|
||
if "path" in objHeadNew.params:
|
||
path = objHeadNew.params['path']
|
||
if path and path[0] == "~":
|
||
# Получаем путь с заменой ~ на директорию пользователя
|
||
path = os.path.join(self.homeDir,path.partition("/")[2],"")[:-1]
|
||
elif not path or path and path[0] != "/":
|
||
self.setError(_("False value 'path' in template") + ": " +\
|
||
nameFileTemplate)
|
||
return ([], False)
|
||
else:
|
||
path = pathJoin(self._baseDir, path)
|
||
|
||
# Путь к оригинальному файлу - pathOldFile
|
||
# Изменяем путь к оригинальному файлу
|
||
if objHeadNew.params.has_key("name"):
|
||
nameFile = objHeadNew.params['name']
|
||
if "/" in nameFile or nameFile == ".." or nameFile == ".":
|
||
self.setError(_("False value 'name' in template") + ": " +\
|
||
nameFileTemplate)
|
||
return ([], False)
|
||
# Новый путь к оригинальному файлу
|
||
pathOldFile = os.path.join(path,nameFile)
|
||
else:
|
||
pathOldFile = os.path.join(path,os.path.split(nameFileConfig)[1])
|
||
applyFiles = [pathOldFile]
|
||
# Фильтрация шаблонов по названию файла
|
||
realPath = os.path.join("/",pathOldFile.partition(self._baseDir)[2])
|
||
if realPath in self.filesFilter:
|
||
return ([], False)
|
||
typeAppendTemplate = objHeadNew.typeAppend
|
||
# Удаляем оригинальный файл
|
||
if typeAppendTemplate == "remove":
|
||
if os.path.islink(pathOldFile):
|
||
# удаляем ссылку
|
||
try:
|
||
os.unlink(pathOldFile)
|
||
except:
|
||
self.setError(_("Error in template") + ": " +\
|
||
nameFileTemplate)
|
||
self.setError(_("Can not delete link") + ": " +\
|
||
pathOldFile)
|
||
return ([], False)
|
||
if os.path.isfile(pathOldFile):
|
||
# удаляем файл
|
||
try:
|
||
os.remove(pathOldFile)
|
||
except:
|
||
self.setError(_("Error in template") + ": " +\
|
||
nameFileTemplate)
|
||
self.setError(_("Can not delete file") + ": " +\
|
||
pathOldFile)
|
||
return ([], False)
|
||
return (applyFiles, False)
|
||
# Пропускаем обработку шаблона
|
||
elif typeAppendTemplate == "skip":
|
||
return ([], False)
|
||
|
||
# Создаем директорию для файла если ее нет
|
||
if not os.path.exists(path):
|
||
if not self.createDir(path):
|
||
return ([], False)
|
||
# В случае force
|
||
if objHeadNew.params.has_key("force"):
|
||
if os.path.islink(pathOldFile):
|
||
# удаляем ссылку
|
||
try:
|
||
os.unlink(pathOldFile)
|
||
except:
|
||
self.setError(_("Error in template") + ": " +\
|
||
nameFileTemplate)
|
||
self.setError(_("Can not delete link") + ": " +\
|
||
pathOldFile)
|
||
return ([], False)
|
||
if os.path.isfile(pathOldFile):
|
||
# удаляем файл
|
||
try:
|
||
os.remove(pathOldFile)
|
||
except:
|
||
self.setError(_("Error in template") + ": " +\
|
||
nameFileTemplate)
|
||
self.setError(_("Can not delete file") + ": " +\
|
||
pathOldFile)
|
||
return ([], False)
|
||
|
||
flagSymlink = False
|
||
flagForce = False
|
||
# Если есть параметр mirror
|
||
if objHeadNew.params.has_key("mirror"):
|
||
if objHeadNew.params.has_key("link"):
|
||
templateFile = objHeadNew.params['link']
|
||
templateFile = pathJoin(self._baseDir, templateFile)
|
||
if not os.path.exists(templateFile):
|
||
if os.path.exists(pathOldFile):
|
||
try:
|
||
os.remove(pathOldFile)
|
||
except:
|
||
self.setError(_("Error in template") + ": " +\
|
||
nameFileTemplate)
|
||
self.setError(_("Can not delete file") + ": " +\
|
||
pathOldFile)
|
||
return ([], False)
|
||
elif not os.path.exists(pathOldFile):
|
||
return ([], False)
|
||
# Если есть указатель на файл шаблона (link)
|
||
if objHeadNew.params.has_key("link") and\
|
||
not objHeadNew.params.has_key("symbolic"):
|
||
templateFile = objHeadNew.params['link']
|
||
templateFile = pathJoin(self._baseDir, templateFile)
|
||
foundTemplateFile = os.path.exists(templateFile)
|
||
if foundTemplateFile:
|
||
try:
|
||
F_CONF = self.openTemplFile(templateFile)
|
||
buff = F_CONF.read()
|
||
F_CONF.close()
|
||
fMode, fUid, fGid = getModeFile(templateFile)
|
||
except:
|
||
self.setError(_("Error in template") + ": " +\
|
||
nameFileTemplate)
|
||
self.setError(_("Can not open file") + ": " +\
|
||
templateFile)
|
||
return ([], False)
|
||
if os.path.exists(pathOldFile):
|
||
try:
|
||
os.remove(pathOldFile)
|
||
except:
|
||
self.setError(_("Error in template") + ": " +\
|
||
nameFileTemplate)
|
||
self.setError(_("Can not delete file") + ": " +\
|
||
pathOldFile)
|
||
return ([], False)
|
||
if foundTemplateFile:
|
||
try:
|
||
FD = open(pathOldFile, "w+")
|
||
FD.write(buff)
|
||
FD.close()
|
||
except:
|
||
self.setError(_("Error in template") + ": " +\
|
||
nameFileTemplate)
|
||
self.setError(_("Can not create file") + " '%s'"\
|
||
%pathOldFile)
|
||
return ([], False)
|
||
oMode = getModeFile(pathOldFile, mode="mode")
|
||
# Если права не совпадают, меняем права
|
||
if fMode != oMode:
|
||
if not chmodConfFile(pathOldFile, fMode, nameFileTemplate,
|
||
checkExists=False):
|
||
return ([], False)
|
||
|
||
# Если символическая ссылка
|
||
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()
|
||
try:
|
||
os.chdir(pathLink)
|
||
except:
|
||
self.setError(_("Error in template") + ": " +\
|
||
nameFileTemplate)
|
||
self.setError(_("Can not change the current directory to")+\
|
||
" " + pathLink)
|
||
return ([], False)
|
||
|
||
# chmod - изменяем права
|
||
if objHeadNew.params.has_key("chmod"):
|
||
mode = self.__octToInt(objHeadNew.params['chmod'])
|
||
if mode:
|
||
if not chmodConfFile(pathOldFile, mode, nameFileTemplate):
|
||
preReturn(pathProg)
|
||
return ([], False)
|
||
else:
|
||
self.setError(_("False value 'chmod' in template") + ": " +\
|
||
nameFileTemplate)
|
||
preReturn(pathProg)
|
||
return ([], 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).pw_uid
|
||
except:
|
||
self.setError(_("Not user in this system: ") + strUid)
|
||
self.setError(_("False value 'chown' in template") +\
|
||
": "+ nameFileTemplate)
|
||
preReturn(pathProg)
|
||
return ([], False)
|
||
try:
|
||
import grp
|
||
gid = grp.getgrnam(strGid).gr_gid
|
||
except:
|
||
self.setError(_("Not group in this system: ")+strGid)
|
||
self.setError(_("False value 'chown' in template") +\
|
||
": "+ nameFileTemplate)
|
||
preReturn(pathProg)
|
||
return ([], False)
|
||
# Изменяем владельца файла
|
||
if not chownConfFile(pathOldFile,uid,gid,nameFileTemplate):
|
||
preReturn(pathProg)
|
||
return ([], False)
|
||
else:
|
||
self.setError(_("False value 'chown' in template") + ": " +\
|
||
nameFileTemplate)
|
||
preReturn(pathProg)
|
||
return ([], False)
|
||
else:
|
||
self.setError(_("False value 'chown' in template") + ": " +\
|
||
nameFileTemplate)
|
||
preReturn(pathProg)
|
||
return ([], False)
|
||
|
||
self.openFiles(nameFileTemplate, pathOldFile)
|
||
if not objHeadNew.params.has_key("chown"):
|
||
# Устанавливаем владельцем конфигурационного файла,
|
||
# пользователя по умолчанию (переменная шаблона ur_login)
|
||
tUid, tGid = getModeFile(pathOldFile, mode="owner")
|
||
if (self.uid, self.gid) != (tUid, tGid):
|
||
# Изменяем владельца файла
|
||
if not chownConfFile(pathOldFile, self.uid, self.gid,
|
||
nameFileTemplate, checkExists=False):
|
||
preReturn(pathProg)
|
||
return ([], False)
|
||
if flagSymlink:
|
||
if os.path.exists(prevOldFile) or os.path.islink(prevOldFile):
|
||
try:
|
||
if os.path.islink(prevOldFile):
|
||
# если ссылка то удаляем её
|
||
os.unlink(prevOldFile)
|
||
else:
|
||
# иначе удаляем файл
|
||
os.remove(prevOldFile)
|
||
except:
|
||
self.setError(_("Error in template") + ": " +\
|
||
nameFileTemplate)
|
||
self.setError(_("Can not delete file") + ": " +\
|
||
prevOldFile)
|
||
preReturn(pathProg)
|
||
return ([], False)
|
||
if not "/" == pathOldFile[0]:
|
||
applyFiles = [prevOldFile,os.path.join(pathLink,pathOldFile)]
|
||
else:
|
||
applyFiles = [prevOldFile,pathOldFile]
|
||
try:
|
||
os.symlink(pathOldFile, prevOldFile)
|
||
except:
|
||
self.setError(_("Error in template") + ": " +\
|
||
nameFileTemplate)
|
||
self.setError(_("Can not create symbolic link") + " :" +\
|
||
"%s -> %s"%(prevOldFile, pathOldFile))
|
||
preReturn(pathProg)
|
||
return ([], False)
|
||
if not objHeadNew.body.strip():
|
||
preReturn(pathProg)
|
||
return ([], False)
|
||
else:
|
||
applyFiles = [pathOldFile]
|
||
if pathProg:
|
||
os.chdir(pathProg)
|
||
# Если файлы заменяются не нужно их обрабатывать дальше
|
||
if typeAppendTemplate == "replace" and\
|
||
not objHeadNew.params.has_key("symbolic") and\
|
||
objHeadNew.params.has_key("link"):
|
||
preReturn(pathProg)
|
||
return ([], False)
|
||
if not pathOldFile in self.dictProcessedTemplates:
|
||
self.dictProcessedTemplates[pathOldFile] = []
|
||
self.dictProcessedTemplates[pathOldFile].append(nameFileTemplate)
|
||
preReturn(pathProg)
|
||
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(os.path.abspath(fileName))
|
||
newTemplate = FD.read()
|
||
FD.close()
|
||
try:
|
||
newTemplate.decode("UTF-8")
|
||
except:
|
||
return False
|
||
return True
|
||
|
||
def joinTemplate(self, nameFileTemplate, nameFileConfig, optFile={}):
|
||
"""Объединения шаблона и конф. файла
|
||
|
||
join(nameFileTemplate, nameFileConfig, ListOptTitle)
|
||
Объединение шаблона nameFileTemplate и конф. файла nameFileConfig,
|
||
ListOptTitle - список строк которые добавятся в заголовок
|
||
optFile = опции для шаблона
|
||
"""
|
||
# Выполняем условия для блока текста а так-же заменяем переменные
|
||
self.nameFileTemplate = os.path.abspath(nameFileTemplate)
|
||
self.F_TEMPL = self.openTemplFile(self.nameFileTemplate)
|
||
self.textTemplate = self.F_TEMPL.read()
|
||
self.closeTemplFile()
|
||
# Флаг копирования шаблона в конфигурационный файл
|
||
flagCopyTemplate = True
|
||
# Тип шаблона бинарный или текстовый
|
||
templateFileType = self.getTemplateType()
|
||
if templateFileType != "bin":
|
||
# Вычисляем условные блоки
|
||
self.textTemplate = self.applyTermsTemplate(self.textTemplate,
|
||
nameFileTemplate)
|
||
# Заменяем переменные на их значения
|
||
self.textTemplate = self.applyVarsTemplate(self.textTemplate,
|
||
nameFileTemplate)
|
||
# Вычисляем функции
|
||
self.textTemplate = self.applyFuncTemplate(self.textTemplate,
|
||
nameFileTemplate)
|
||
flagCopyTemplate = False
|
||
if not optFile:
|
||
optFile = {"path":os.path.split(nameFileConfig)[0]}
|
||
filesApply, objHeadNew = self.__getApplyHeadTemplate(nameFileTemplate,
|
||
nameFileConfig,
|
||
templateFileType,
|
||
optFile)
|
||
if not objHeadNew:
|
||
return filesApply
|
||
# Настоящее имя конфигурационного файла
|
||
nameFileConfig = filesApply[0]
|
||
# Флаг - кодировка с бинарными примесями у файла шаблона включаем при
|
||
# условии текстового файла и кодировки отличной от UTF-8
|
||
flagNotUtf8New = False
|
||
# Флаг - кодировка с бинарными примесями у оригинального файла
|
||
flagNotUtf8Old = False
|
||
if not flagCopyTemplate:
|
||
# проверяем кодировку шаблона
|
||
if not self.fileIsUtf(nameFileTemplate):
|
||
flagNotUtf8New = True
|
||
if not (objHeadNew.params.has_key("link") and\
|
||
objHeadNew.params.has_key("symbolic")):
|
||
# проверяем кодировку оригинального файла
|
||
if not self.fileIsUtf(nameFileConfig):
|
||
flagNotUtf8Old = True
|
||
self.textTemplate = objHeadNew.body
|
||
# Список примененных шаблонов
|
||
ListOptTitle = []
|
||
if nameFileConfig in self.dictProcessedTemplates:
|
||
ListOptTitle = self.dictProcessedTemplates[nameFileConfig]
|
||
# Титл конфигурационного файла
|
||
title = ""
|
||
if ListOptTitle:
|
||
title = self.getTitle(objHeadNew.comment, ListOptTitle)
|
||
title = title.encode("UTF-8")
|
||
|
||
objHeadOld = False
|
||
if objHeadNew.comment:
|
||
objHeadOld = fileHeader(nameFileConfig, self.textConfig,
|
||
objHeadNew.comment)
|
||
if objHeadNew.fileType:
|
||
formatTemplate = objHeadNew.fileType
|
||
typeAppendTemplate = objHeadNew.typeAppend
|
||
# Создаем объект в случае параметра format в заголовке
|
||
if (typeAppendTemplate == "replace" or\
|
||
typeAppendTemplate == "before" or\
|
||
typeAppendTemplate == "after") and\
|
||
not (formatTemplate == "bin" or\
|
||
formatTemplate == "raw"):
|
||
# Преобразовываем бинарные файлы
|
||
if flagNotUtf8New:
|
||
objTxtCoder = utfBin()
|
||
self.textTemplate = objTxtCoder.encode(self.textTemplate)
|
||
# создаем объект формата шаблона
|
||
objTemplNew = self.getFormatObj(formatTemplate,
|
||
self.textTemplate)
|
||
if not objTemplNew:
|
||
self.setError(\
|
||
_("Incorrect header parmeter format=%s in template")\
|
||
%formatTemplate + " " + nameFileTemplate)
|
||
return False
|
||
if "xml_" in formatTemplate:
|
||
if objTemplNew.getError():
|
||
self.setError(_("False template") + ": " +\
|
||
nameFileTemplate)
|
||
return False
|
||
# Имя файла внутри xml xfce конфигурационных файлов
|
||
nameRootNode=nameFileConfig.rpartition("/")[2].split(".")[0]
|
||
objTemplNew.setNameBodyNode(nameRootNode)
|
||
# Объект Документ
|
||
docObj = objTemplNew.docObj
|
||
# Удаление комментариев из документа
|
||
docObj.removeComment(docObj.getNodeBody())
|
||
# Добавление необходимых переводов строк
|
||
docObj.insertBRtoBody(docObj.getNodeBody())
|
||
# Добавление необходимых разделителей между областями
|
||
docObj.insertBeforeSepAreas(docObj.getNodeBody())
|
||
# Пост обработка
|
||
if 'postXML' in dir(objTemplNew):
|
||
objTemplNew.postXML()
|
||
# Получение текстового файла из XML документа
|
||
self.textTemplate = objTemplNew.getConfig().encode("UTF-8")
|
||
# Если не UTF-8 производим преобразование
|
||
if flagNotUtf8New:
|
||
self.textTemplate = objTxtCoder.decode(self.textTemplate)
|
||
# Титл для объединения
|
||
if ListOptTitle:
|
||
title = self.getTitle(objTemplNew._comment,
|
||
ListOptTitle)
|
||
title = title.encode("UTF-8")
|
||
# Замена
|
||
if typeAppendTemplate == "replace":
|
||
if "xml_" in formatTemplate:
|
||
data = self.textTemplate.split("\n")
|
||
data.insert(1,title)
|
||
self.textConfig = "\n".join(data)
|
||
else:
|
||
if objHeadNew.execStr:
|
||
self.textConfig = objHeadNew.execStr+title+\
|
||
self.textTemplate
|
||
else:
|
||
self.textConfig = title + self.textTemplate
|
||
self.saveConfFile()
|
||
return filesApply
|
||
# Впереди
|
||
elif typeAppendTemplate == "before":
|
||
if "xml_" in formatTemplate:
|
||
self.setError(\
|
||
_("False option append=before in template %s")\
|
||
%nameFileTemplate)
|
||
return False
|
||
if objHeadOld and objHeadOld.body:
|
||
self.textConfig = objHeadOld.body
|
||
if self.textTemplate[-1] == "\n":
|
||
tmpTemplate = self.textTemplate + self.textConfig
|
||
else:
|
||
tmpTemplate = self.textTemplate + "\n" + self.textConfig
|
||
if objHeadNew.execStr:
|
||
self.textConfig = objHeadNew.execStr + title + tmpTemplate
|
||
elif objHeadOld and objHeadOld.execStr:
|
||
self.textConfig = objHeadOld.execStr + title + tmpTemplate
|
||
else:
|
||
self.textConfig = title + tmpTemplate
|
||
|
||
self.saveConfFile()
|
||
return filesApply
|
||
# Cзади
|
||
elif typeAppendTemplate == "after":
|
||
if "xml_" in formatTemplate:
|
||
self.setError(\
|
||
_("False option append=after in template %s")\
|
||
%nameFileTemplate)
|
||
return False
|
||
if objHeadOld and objHeadOld.body:
|
||
self.textConfig = objHeadOld.body
|
||
if self.textTemplate[-1] == "\n":
|
||
tmpTemplate = self.textConfig + self.textTemplate
|
||
else:
|
||
tmpTemplate = self.textConfig + "\n" + self.textTemplate
|
||
if objHeadNew.execStr:
|
||
self.textConfig = objHeadNew.execStr + title + tmpTemplate
|
||
elif objHeadOld and objHeadOld.execStr:
|
||
self.textConfig = objHeadOld.execStr + title + tmpTemplate
|
||
else:
|
||
self.textConfig = title + tmpTemplate
|
||
self.saveConfFile()
|
||
return filesApply
|
||
# Объединение
|
||
elif typeAppendTemplate == "join":
|
||
if flagNotUtf8New:
|
||
objTxtCoder = utfBin()
|
||
self.textTemplate = objTxtCoder.encode(self.textTemplate)
|
||
# создаем объект формата шаблона
|
||
objTemplNew = self.getFormatObj(formatTemplate,
|
||
self.textTemplate)
|
||
if not objTemplNew:
|
||
self.setError(\
|
||
_("Incorrect header parmeter format=%s in template")\
|
||
%formatTemplate + " " + nameFileTemplate)
|
||
return False
|
||
if "xml_" in formatTemplate:
|
||
if objTemplNew.getError():
|
||
self.setError(_("False template") + ": " +\
|
||
nameFileTemplate)
|
||
return False
|
||
nameRootNode=nameFileConfig.rpartition("/")[2].split(".")[0]
|
||
objTemplNew.setNameBodyNode(nameRootNode)
|
||
# Титл для объединения
|
||
if ListOptTitle:
|
||
title = self.getTitle(objTemplNew._comment,
|
||
ListOptTitle)
|
||
title = title.encode("UTF-8")
|
||
|
||
# В случае пустого конфигурационного файла
|
||
reNoClean = re.compile("[^\s]",re.M)
|
||
if not self.textConfig or\
|
||
not reNoClean.search(self.textConfig):
|
||
self.textConfig = ""
|
||
#if objHeadNew.execStr:
|
||
#self.textConfig = objHeadNew.execStr + \
|
||
#title + objTemplNew.getConfig().encode("UTF-8")
|
||
#else:
|
||
#self.textConfig = title +\
|
||
#objTemplNew.getConfig().encode("UTF-8")
|
||
#self.saveConfFile()
|
||
#return True
|
||
|
||
objHeadOld = fileHeader(nameFileConfig, self.textConfig,
|
||
objTemplNew._comment)
|
||
if objHeadOld.body:
|
||
self.textConfig = objHeadOld.body
|
||
else:
|
||
self.textConfig = ""
|
||
if flagNotUtf8Old:
|
||
objTxtCoder = utfBin()
|
||
self.textConfig = objTxtCoder.encode(self.textConfig)
|
||
# создаем объект формата шаблона для конфигурационного файла
|
||
objTemplOld = self.getFormatObj(formatTemplate,
|
||
self.textConfig)
|
||
if not objTemplOld:
|
||
self.setError(_("Error in template %s") %nameFileConfig)
|
||
return False
|
||
if "xml_" in formatTemplate:
|
||
if objTemplOld.getError():
|
||
self.setError(_("False template") + ": " +\
|
||
nameFileConfig)
|
||
return False
|
||
nameRootNode=nameFileConfig.rpartition("/")[2].split(".")[0]
|
||
objTemplOld.setNameBodyNode(nameRootNode)
|
||
|
||
objTemplOld.join(objTemplNew)
|
||
if "xml_" in formatTemplate:
|
||
if objTemplOld.getError():
|
||
self.setError(_("False template") + ": " +\
|
||
nameFileTemplate)
|
||
return False
|
||
data = objTemplOld.getConfig().encode("UTF-8").split("\n")
|
||
data.insert(1,title)
|
||
self.textConfig = "\n".join(data)
|
||
else:
|
||
if objHeadNew.execStr:
|
||
self.textConfig = objHeadNew.execStr + title +\
|
||
objTemplOld.getConfig().encode("UTF-8")
|
||
elif objHeadOld.execStr:
|
||
self.textConfig = objHeadOld.execStr + title +\
|
||
objTemplOld.getConfig().encode("UTF-8")
|
||
else:
|
||
self.textConfig = title +\
|
||
objTemplOld.getConfig().encode("UTF-8")
|
||
# Декодируем если кодировка не UTF-8
|
||
if flagNotUtf8New or flagNotUtf8Old:
|
||
self.textTemplate = objTxtCoder.decode(self.textTemplate)
|
||
self.textConfig = objTxtCoder.decode(self.textConfig)
|
||
self.saveConfFile()
|
||
return filesApply
|
||
else:
|
||
self.setError(_("False (type append) template") + ": " +\
|
||
typeAppendTemplate)
|
||
return False
|
||
else:
|
||
self.setError(_("Type template not found: ") + nameFileTemplate)
|
||
return False
|
||
return filesApply
|
||
|
||
class scanDirectoryClt:
|
||
"""Класс для cканирования директорий с файлами .clt"""
|
||
|
||
# Расширение файла шаблона
|
||
extFileTemplate = ".clt"
|
||
lenExtFileTemplate = len(extFileTemplate)
|
||
filterApplyTemplates = []
|
||
|
||
def processingFile(self, path, prefix):
|
||
"""Обработка в случае файла"""
|
||
return True
|
||
|
||
def scanningTemplates(self, scanDir, prefix=None, flagDir=False):
|
||
"""Сканирование и обработка шаблонов в директории scanDir"""
|
||
ret = True
|
||
if not prefix:
|
||
prefix = os.path.realpath(scanDir)
|
||
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)
|
||
stInfo = os.lstat(absPath)
|
||
statInfo = stInfo[stat.ST_MODE]
|
||
if fileOrDir.endswith(self.extFileTemplate) and\
|
||
stat.S_ISREG(statInfo):
|
||
if not self.filterApplyTemplates or\
|
||
absPath[:-self.lenExtFileTemplate] in\
|
||
self.filterApplyTemplates:
|
||
if not self.processingFile(absPath, prefix):
|
||
ret = False
|
||
break
|
||
elif stat.S_ISDIR(statInfo):
|
||
ret = self.scanningTemplates(absPath, prefix, True)
|
||
if ret is False:
|
||
break
|
||
return ret
|
||
|
||
class templateClt(scanDirectoryClt, template):
|
||
"""Класс для обработки шаблонов c расширением .clt"""
|
||
|
||
def __init__(self, objVar):
|
||
self.checkNumberTemplate = True
|
||
template.__init__(self, objVar, cltObj=False)
|
||
applyPackages = ["calculate-install"]
|
||
self.flagApplyTemplates = False
|
||
if self.objVar.Get("cl_name") in applyPackages:
|
||
self.flagApplyTemplates = True
|
||
|
||
def applyTemplate(self, path):
|
||
"""Применение отдельного .clt шаблона"""
|
||
if not self.flagApplyTemplates:
|
||
return True
|
||
return self.processingFile(path, "")
|
||
|
||
def processingFile(self, path, prefix):
|
||
"""Обработка в случае шаблона файла"""
|
||
self.numberProcessTempl += 1
|
||
self.numberProcessTemplates(self.numberProcessTempl)
|
||
# Пропуск шаблонов директорий
|
||
if self.templDirNameFile == os.path.split(path)[1]:
|
||
return True
|
||
# Проверка на переменные в названии файла
|
||
if not self.getNeedTemplate(path):
|
||
if self.getError():
|
||
return False
|
||
return True
|
||
if self.getError():
|
||
return False
|
||
if prefix and prefix[-1] == "/":
|
||
prefix = prefix[:-1]
|
||
if prefix:
|
||
nameFileConfig = path.partition(prefix)[2]
|
||
else:
|
||
nameFileConfig = path
|
||
nameFileConfig = nameFileConfig[:-self.lenExtFileTemplate]
|
||
# файл в системе без условий
|
||
nameFileConfig = "/".join(map(lambda x:x.split("?")[0],\
|
||
nameFileConfig.split("/")))
|
||
# Записываем в переменную обрабатываемый файл
|
||
self.objVar.Set("cl_pass_file",nameFileConfig)
|
||
# Пишем время модификации *.env файлов
|
||
if nameFileConfig.endswith(".env"):
|
||
nameEnvFile = os.path.split(nameFileConfig)[1]
|
||
self.functObj.timeConfigsIni[nameEnvFile] = float(time.time())
|
||
filesApl = self.joinTemplate(path, nameFileConfig)
|
||
if self.getError():
|
||
return False
|
||
if filesApl:
|
||
self.filesApply += filesApl
|
||
# Настоящее имя конфигурационного файла
|
||
nameFileConfig = filesApl[0]
|
||
return nameFileConfig
|
||
|
||
def countsNumberTemplates(self, dirsTemplates=[]):
|
||
"""Считаем количество шаблонов"""
|
||
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 dirsTemplates:
|
||
dirsTemplates = self.objVar.Get("cl_template_clt_path")
|
||
dirsTemplates.sort()
|
||
scanObj = scanDirectoryClt()
|
||
scanObj.processingFile = lambda x,y: createDictTemplates(x, y,\
|
||
self.dictTemplates)
|
||
# Считаем количество шаблонов
|
||
for dirTemplate in dirsTemplates:
|
||
scanObj.scanningTemplates(dirTemplate, "/")
|
||
|
||
def applyTemplates(self):
|
||
"""Применяет шаблоны к конфигурационным файлам"""
|
||
if not self.flagApplyTemplates:
|
||
return ([],[])
|
||
if not self.objVar.defined("cl_template_clt_path"):
|
||
self.setError(_("not defined Var: ") + "cl_template_clt_path")
|
||
return False
|
||
dirsTemplates = self.objVar.Get("cl_template_clt_path")
|
||
dirsTemplates.sort()
|
||
if self.checkNumberTemplate:
|
||
# Созданные директории
|
||
self.createdDirs = []
|
||
# Примененные файлы
|
||
self.filesApply = []
|
||
# Номер применяемого шаблона
|
||
self.numberProcessTempl = 0
|
||
# Словарь директорий с количеством файлов шаблонов
|
||
self.dictTemplates = {}
|
||
# Количество шаблонов
|
||
self.allTemplates = 0
|
||
# Установка по умолчанию аттрибутов для функциии шаблонов ini()
|
||
# Время доступа к конфигурационному файлу функции шаблона ini()
|
||
self.functObj.timeIni = -1
|
||
# Первоначальный словарь переменных для ini()
|
||
self.functObj.prevDictIni = {}
|
||
# Текущий словарь переменных для ini()
|
||
self.functObj.currDictIni = {}
|
||
# Словарь времен модификации env файлов для ini()
|
||
self.functObj.timeConfigsIni = {}
|
||
# Считаем количество шаблонов
|
||
self.countsNumberTemplates(dirsTemplates=dirsTemplates)
|
||
self.numberAllTemplates(self.allTemplates)
|
||
# Обрабатываем шаблоны
|
||
for dirTemplate in dirsTemplates:
|
||
if self.scanningTemplates(dirTemplate, "/") is False:
|
||
return False
|
||
return (self.createdDirs, self.filesApply)
|
||
|
||
class iniParser(_error, templateFormat):
|
||
"""Класс для работы с 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):
|
||
try:
|
||
# Создание файла
|
||
FD = open(self.iniFile, "w+")
|
||
os.chmod(self.iniFile, self.mode)
|
||
except:
|
||
self.setError(_("Unable to create file") + ": " + self.iniFile)
|
||
return False
|
||
else:
|
||
try:
|
||
FD = open(self.iniFile, "r+")
|
||
except:
|
||
self.setError(_("Unable to open file") + ": " + self.iniFile)
|
||
return False
|
||
FD.truncate(0)
|
||
FD.seek(0)
|
||
FD.write(txtConfig)
|
||
FD.close()
|
||
return True
|
||
|
||
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 = self.getClassObj("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 = self.getClassObj("samba")
|
||
# создаем объект
|
||
# и записываем в него содержимое ini-файла
|
||
objIni = classObj(textIni)
|
||
# создаем текст из строки заголовка и
|
||
# словаря переменных области
|
||
txtConfig = objIni.createTxtConfig(strHeader, dictVar)
|
||
# создаем объект и записываем в него текст
|
||
objIniAdd = classObj(txtConfig)
|
||
# объединяем объекты для получения результирующего текста
|
||
objIni.join(objIniAdd)
|
||
# получаем текст
|
||
txtConfig = objIni.getConfig().encode("UTF-8")
|
||
# записываем его в ini файл
|
||
if not self.writeIniFile(txtConfig):
|
||
return False
|
||
return True
|
||
|
||
def isEmptyFile(self, textIni):
|
||
"""Является ли файл пустым"""
|
||
if not textIni.strip():
|
||
return True
|
||
else:
|
||
return False
|
||
|
||
def checkIniFile(self, textIni):
|
||
"""Проверка на правильность формата файла"""
|
||
if self.checkIni is None:
|
||
# Ошибка
|
||
if textIni == False:
|
||
self.checkIni = False
|
||
return False
|
||
self.checkIni = "samba"
|
||
# В файле есть данные
|
||
if not self.isEmptyFile(textIni):
|
||
try:
|
||
objIni = self.getClassObj("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 = self.getClassObj("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, checkExistVar=False):
|
||
"""Получаем значение переменной из ini-файла"""
|
||
textIni = self.openIniFile()
|
||
nameFomat = self.checkIniFile(textIni)
|
||
if not nameFomat:
|
||
return False
|
||
formatPlasma = False
|
||
if type(strHeader) in (tuple, list):
|
||
# формат plasma
|
||
classObj = self.getClassObj("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 = self.getClassObj("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 checkExistVar:
|
||
if res is False:
|
||
return False, ""
|
||
else:
|
||
return True, res
|
||
else:
|
||
if res is False:
|
||
return ""
|
||
else:
|
||
return res
|
||
|
||
|
||
def getLastNode(self, objIni, xmlBody, strHeader, formatPlasma):
|
||
"""Ищет область в XML в которой область с переменными"""
|
||
flagFound = True
|
||
if not strHeader:
|
||
flagFound = False
|
||
return flagFound,xmlBody
|
||
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 = self.getClassObj("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 = self.getClassObj("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 = self.getClassObj("samba")(textIni)
|
||
elif nameFomat == "plasma":
|
||
# создаем объект типа plasma и записываем в него содержимое
|
||
# ini-файла
|
||
objIni = self.getClassObj("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
|