You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
calculate-utils-2.2-lib/pym/format/bind.py

318 lines
14 KiB

#-*- 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 re
from cl_template import objShare, blocText, xmlDoc
class bind(objShare):
"""Класс для обработки конфигурационного файла типа bind
"""
_comment = "//"
configName = "bind"
configVersion = "0.1"
__openArea = "{"
__closeArea = "[ \t]*\}[ \t]*;[ \t]*"
sepFields = ";"
reOpen = re.compile(__openArea)
reClose = re.compile(__closeArea)
reCloseArea = re.compile(__closeArea + "\s*\Z")
reComment = re.compile("[ \t]+%s|^%s|(?<=;)%s"%(_comment,_comment,_comment))
reSepFields = re.compile(sepFields)
reSeparator = re.compile("[ \t]+")
def __init__(self,text):
self.text = text
self.blocTextObj = blocText()
# Объект документ
self.docObj = self.textToXML()
# Создаем поля-массивы
self.docObj.postParserList()
# XML документ
self.doc = self.docObj.doc
# Делим область на составные части
def findOpenClose(self, text, reOpen, reClose, reComment):
"""Делит область на составные части
начальный текстовый блок,
открывающий блок,
блок-тело,
закрывающий блок
"""
firstBloc = ""
startBloc = ""
bodyBloc = ""
endBloc = ""
textLines = text.splitlines()
findOpen = False
if textLines:
findOpen = reOpen.search(textLines[0])
openBl = reOpen.search(text)
if findOpen and reComment.split(text)[0].strip():
blocA = text[openBl.end():]
firstBloc = text[:openBl.start()]
startBloc = text[openBl.start():openBl.end()]
closeBl = reClose.search(blocA)
endBloc = blocA[closeBl.start():closeBl.end()]
bodyBloc = blocA[:closeBl.start()]
return (firstBloc, startBloc, bodyBloc, endBloc)
else:
return (firstBloc, startBloc, text, endBloc)
# Делим текст на области включая вложенные (areas массив областей)
def splitToAllArea(self, text, areas, reOpen, reClose, reCloseArea,
reComment, reSepFields):
"""Делит текст на области включая вложенные
возвращает список объектов областей (переменная areas)
"""
class area:
def __init__(self):
self.header = False
self.start = False
self.fields = []
self.end = False
blocs = self.blocTextObj.splitTxtToBloc(text,reOpen,reClose,
reComment,reSepFields)
for i in blocs:
areaA = area()
first,start,body,end = self.findOpenClose(i, reOpen, reCloseArea,
reComment)
areaA.header = first.replace(" ","").replace("\t","")
areaA.start = first + start
areaA.end = end
if areaA.end:
blocsA = self.blocTextObj.splitTxtToBloc(body,reOpen,reClose,
reComment,reSepFields)
if blocsA and blocsA[0] == body:
areaA.fields.append(body)
areas.append(areaA)
else:
for ar in blocsA:
self.splitToAllArea(ar, areaA.fields, reOpen,
reClose,
reCloseArea, reComment,
reSepFields)
areas.append(areaA)
else:
areaA.fields.append(body)
areas.append(areaA)
return areas
def setDataField(self, txtLines, endtxtLines):
"""Создаем список объектов с переменными"""
class fieldData:
def __init__(self):
self.name = False
self.value = False
self.comment = False
self.br = False
fields = []
field = fieldData()
z = 0
for k in txtLines:
textLine = k + endtxtLines[z]
z += 1
findComment = self.reComment.search(textLine)
if not textLine.strip():
field.br = textLine
fields.append(field)
field = fieldData()
elif findComment:
field.comment = textLine
fields.append(field)
field = fieldData()
else:
pars = textLine.strip()
nameValue = self.reSeparator.split(pars)
if len (nameValue) == 1:
field.name = ""
field.value = textLine.replace(self.sepFields,"")
field.br = textLine
fields.append(field)
field = fieldData()
if len(nameValue) > 2:
valueList = nameValue[1:]
nameValue =[nameValue[0]," ".join(valueList).replace(\
self.sepFields,"")]
if len(nameValue) == 2:
name = nameValue[0]
value = nameValue[1].replace(self.sepFields,"")
field.name = name.replace(" ","").replace("\t","")
field.value = value
field.br = textLine
fields.append(field)
field = fieldData()
return fields
def createCaptionTerm(self, header, start, end, docObj):
"""Создание пустой области с заголовком
при создании области проверяется первый символ заголовка
и добавляется тег action
"!" - <action>drop</action>
"-" - <action>replace</action>
"""
areaAction = False
if header:
if header[0] == "!":
docObj.createCaption(header[1:], [start,
end.replace("\n","")])
areaAction = "drop"
elif header[0] == "-":
docObj.createCaption(header[1:], [start,
end.replace("\n","")])
areaAction = "replace"
else:
docObj.createCaption(header, [start,
end.replace("\n","")])
else:
docObj.createCaption(header, [start,
end.replace("\n","")])
areaXML = docObj.createArea()
if areaAction:
docObj.setActionArea(areaXML, areaAction)
return areaXML
def createXML(self, areas, rootNode, docObj):
"""Создаем из массивов областей XML"""
for i in areas:
if str(i.__class__.__name__) == "area":
if i.header and i.start:
areaXML = self.createCaptionTerm(i.header, i.start,
i.end.replace("\n",""),
docObj)
else:
areaXML = rootNode
for f in i.fields:
if str(f.__class__.__name__) == "area":
if f.header and f.start:
areaXMLChild = self.createCaptionTerm(f.header,
f.start,
f.end.replace("\n",""),
docObj)
self.createXML(f.fields, areaXMLChild, docObj)
areaXML.appendChild(areaXMLChild)
else:
self.createXML(f.fields, areaXML, docObj)
if "\n" in f.end:
fieldXMLBr = docObj.createField("br",[],
"",[],
False, False)
areaXML.appendChild(fieldXMLBr)
else:
if not f:
continue
fields = self.splitToFields(f)
for field in fields:
if field.name != False:
fieldXML = self.createFieldTerm(field.name,
field.value,
field.br, docObj)
areaXML.appendChild(fieldXML)
if field.br[-1] == "\n":
fieldXMLBr = docObj.createField("br",[],
"",[],
False, False)
areaXML.appendChild(fieldXMLBr)
elif field.comment != False:
fieldXML = docObj.createField("comment",
[field.comment],
"", [],
False, False)
areaXML.appendChild(fieldXML)
elif field.br != False:
brText = field.br.replace("\n","")
if brText:
fieldXML = docObj.createField('br',
[brText],
"", [],
False, False)
else:
fieldXML = docObj.createField('br',
[],
"", [],
False, False)
areaXML.appendChild(fieldXML)
if i.header and i.start:
rootNode.appendChild(areaXML)
if "\n" in i.end:
fieldXMLBr = docObj.createField("br",[],
"",[],
False, False)
rootNode.appendChild(fieldXMLBr)
else:
fields = self.splitToFields(i)
for field in fields:
if field.name != False:
fieldXML = self.createFieldTerm(field.name,
field.value,
field.br, docObj)
rootNode.appendChild(fieldXML)
if field.br[-1] == "\n":
fieldXMLBr = docObj.createField("br",[],"", [],
False, False)
rootNode.appendChild(fieldXMLBr)
elif field.comment != False:
fieldXML = docObj.createField("comment",
[field.comment],
"", [],
False, False)
rootNode.appendChild(fieldXML)
elif field.br != False:
brText = field.br.replace("\n","")
if brText:
fieldXML = docObj.createField('br', [brText],"",[],
False, False)
else:
fieldXML = docObj.createField('br', [], "", [],
False, False)
rootNode.appendChild(fieldXML)
#rootNode.appendChild(areaXML)
def textToXML(self):
"""Преобразуем текст в XML"""
areas = []
if self.text.strip():
self.splitToAllArea(self.text, areas, self.reOpen, self.reClose,
self.reCloseArea,self.reComment,self.reSepFields)
docObj = xmlDoc()
# Создание объекта документ c пустым разделителем между полями
docObj.createDoc(self.configName, self.configVersion)
if not areas:
return docObj
self.createXML(areas, docObj.getNodeBody(), docObj)
return docObj
def join(self, bindObj):
"""Объединяем конфигурации"""
if isinstance(bindObj, bind):
self.docObj.joinDoc(bindObj.doc)