#-*- 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 import types import copy from xml import xpath from cl_template import xmlDoc,blocText from format.samba import samba class plasmaBlocText(blocText): def findBloc(self, text, captionTxtBloc, bodyTxtBloc): """ Делит текст на блоки (с заголовками) captionTxtBloc - регулярное выражение для заголовка блока bodyTxtBloc - регулярное выражение для тела блока возвращает два списка: первый - заголовки, второй - тела блоков """ # Заголовки блоков headersTxt = [] # Тексты блоков blocsTxt = [] r = captionTxtBloc.search(text) if r: headersTxt.append(r.group(0)) txtSpl = text.partition(r.group(0)) blocTxt = txtSpl[0] txtWr = txtSpl[2] 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.partition(r.group(0)) blocTxt = txtSpl[0] txtWr = txtSpl[2] 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)1: ret = False return ret blTmp = self.blocTextObj.findBloc(self.text,self.reHeader,self.reBody) blocs = self.getFullAreas(blTmp) if blocs == []: return [] reH = re.compile("\[([^\[\]]+)\]") # Список имен блоков namesBlockList = [] # Временные поля fieldsTmp = [] # Добавляем заголовки z = 0 for h in blocs[0]: if not h: if blocs[1][z] == "": fieldsTmp.append("") #fieldsTmp.append("\n") else: fieldsTmp.append(blocs[1][z]) z += 1 continue z += 1 slpNamesBlock = reH.split(h) # Отступ слева для заголовка indentionLeft = slpNamesBlock[0] namesBlock = filter(lambda x: x.strip(), slpNamesBlock) #namesBlock = map(lambda x: self.removeSymbolTerm(x), namesBlock) findArea = findPathArea(copy.copy(namesBlock), areas) namesBlockList.append(namesBlock) if findArea: if len(namesBlock) > 1: namesBlockView = map(lambda x: self.removeSymbolTerm(x), namesBlock) else: namesBlockView = namesBlock findArea.start = indentionLeft + "[" + \ "][".join(namesBlockView) + "]" else: i = 0 lenNamesBlock = len(namesBlock) namesBlockTmp = [] for nameB in namesBlock: namesBlockTmp.append(nameB) findArea = findPathArea(copy.copy(namesBlockTmp), areas) i += 1 if not findArea: areaNew = area() areaNew.header = nameB if lenNamesBlock == i: if len(namesBlock) > 1: namesBlockView = map(\ lambda x: self.removeSymbolTerm(x), namesBlock) else: namesBlockView = namesBlock areaNew.start = indentionLeft + "[" + \ "][".join(namesBlockView) + "]" else: areaNew.start = "" areaNew.end = "" if i == 1: if lenNamesBlock == i: areas += fieldsTmp areas.append(areaNew) findAreaPrev = areas[-1] else: if lenNamesBlock == i: findAreaPrev.fields += fieldsTmp findAreaPrev.fields.append(areaNew) findAreaPrev = findAreaPrev.fields[-1] else: findAreaPrev = findArea fieldsTmp = [] i = 0 delt = 0 # Добавляем тела for body in blocs[1]: if not blocs[0][i]: i += 1 delt +=1 continue ## В случае последнего комментария не добавляем перевод строки #if self.reComment.search(body.splitlines()[-1]): body = "\n" + body namesBlock = namesBlockList[i-delt] findArea = findPathArea(copy.copy(namesBlock), areas) if findArea: #if findArea.fields: #if type(findArea.fields[0]) == types.StringType: #findArea.fields.pop(0) findArea.fields.insert(0, body) i += 1 return areas def createCaptionTerm(self, header, start, end, docObj): """Создание пустой области с заголовком при создании области проверяется первый символ заголовка и добавляется тег action "!" - drop "-" - replace """ 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: areaXML = self.createCaptionTerm(i.header, i.start, i.end.replace("\n",""), docObj) for f in i.fields: if str(f.__class__.__name__) == "area": if f.header: 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) if areaXML: areaXML.appendChild(fieldXML) if i.header: rootNode.appendChild(areaXML) if "\n" in i.end: fieldXMLBr = docObj.createField("br",[], "",[], False, False) rootNode.appendChild(fieldXMLBr) else: if not i: continue 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 createTxtConfig(self, strHeader, dictVar): """Cоздает область с заголовком создает текст конфигурационного файла в формате samba из заголовка (строка) и словаря переменных """ if not strHeader: return "" if type(strHeader) in (tuple, list): outTxt = "".join(map(lambda x: "["+x+"]",strHeader)) if not outTxt: return "" outTxt += "\n" else: outTxt = "[" + strHeader + "]\n" for key in dictVar.keys(): outTxt += "%s=%s\n" %(key,dictVar[key]) return outTxt def _textToXML(self): """Преобразуем текст в XML""" areas = [] if self.text.strip(): self.splitToAllArea(self.text, areas) #docObj = xmlDoc() # Создаем новый класс xmlDoc с измененным методом joinArea newClass = type("newXmlDocPlalma",(xmlDocPlasma,xmlDoc,object),{}) # Создаем экземпляр нового класса docObj = newClass() # Создание объекта документ c пустым разделителем между полями docObj.createDoc(self.configName, self.configVersion) if not areas: return docObj self.createXML(areas, docObj.getNodeBody(), docObj) return docObj def postXML(self): """Последующая постобработка 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 xmlAreas = xpath.Evaluate("descendant::area", self.docObj.body) for xmlArea in xmlAreas: # Перед пустой областью и после нее удаляем переводы строк if getQuotesArea(xmlArea) == ["",""]: if xmlArea.previousSibling and\ self.docObj.getTypeField(xmlArea.previousSibling) == "br": parentNode = xmlArea.previousSibling.parentNode if xmlArea.previousSibling.previousSibling and\ self.docObj.getTypeField(xmlArea.previousSibling.previousSibling) == "br": parentNode.removeChild(\ xmlArea.previousSibling.previousSibling) parentNode.removeChild(xmlArea.previousSibling) if xmlArea.nextSibling and\ self.docObj.getTypeField(xmlArea.nextSibling) == "br": parentNode = xmlArea.nextSibling.parentNode if xmlArea.nextSibling.nextSibling and\ self.docObj.getTypeField(xmlArea.nextSibling.nextSibling) == "br": parentNode.removeChild(xmlArea.nextSibling.nextSibling) parentNode.removeChild(xmlArea.nextSibling) continue # Собираем поля в кучку xmlChildAreas = xpath.Evaluate("child::area", xmlArea) if xmlChildAreas: childNodes = self.docObj.getFieldsArea(xmlArea) firstChildArea = xmlChildAreas[0] if firstChildArea.previousSibling and\ self.docObj.getTypeField(firstChildArea.previousSibling)=="br": if firstChildArea.previousSibling.previousSibling: if self.docObj.getTypeField(\ firstChildArea.previousSibling.previousSibling)=="br": firstChildArea = firstChildArea.previousSibling flagFoundArea = False it = 0 lenChild = len(childNodes) for node in childNodes: it += 1 if node.tagName == "area": flagFoundArea = True continue if flagFoundArea and node.tagName == "field": if self.docObj.getTypeField(node) == "var": xmlArea.insertBefore(node, firstChildArea) if it < lenChild: if self.docObj.getTypeField(childNodes[it])==\ "br": xmlArea.insertBefore(childNodes[it], firstChildArea) # Добавление перевода строк в если его нет между полями if self.docObj.getTypeField(node) == "var" and\ node.previousSibling and\ not (self.docObj.getTypeField(node.previousSibling) in\ ("br","comment")): xmlArea.insertBefore(self.docObj.createField("br", [],"",[], False,False), node) # Добавляем BR если его нет первым полем xmlFields = xpath.Evaluate("child::field", xmlArea) if not (xmlFields and\ (self.docObj.getTypeField(xmlFields[0]) == "br" or\ self.docObj.getTypeField(xmlFields[0]) == "comment")): if xmlFields: xmlArea.insertBefore(self.docObj.createField("br", [],"",[], False,False), xmlFields[0]) # Добавление переводов строк между полями if xmlFields: for node in xmlFields: # Добавление перевода строк в если его нет между полями if self.docObj.getTypeField(node) == "var" and\ node.previousSibling and\ not (self.docObj.getTypeField(node.previousSibling) in\ ("br","comment")): xmlArea.insertBefore(self.docObj.createField("br", [],"",[], False, False), node) # Если последним полем BR, удаляем его if xmlFields and self.docObj.getTypeField(xmlFields[-1]) == "br": if not xmlFields[-1].nextSibling: xmlArea.removeChild(xmlFields[-1]) # Если предыдущим полем не (BR или комментарий) - добавляем BR if xmlArea.previousSibling and\ not (self.docObj.getTypeField(xmlArea.previousSibling) == "br" or\ self.docObj.getTypeField(xmlArea.previousSibling) == "comment"): parentNode = xmlArea.parentNode parentNode.insertBefore(self.docObj.createField("br", [],"",[], False,False), xmlArea) # Если есть предыдущее поле, и поле предыдущеее предыдущему # не равно BR или комментарий то добавляем BR if xmlArea.previousSibling: prPrSibling = xmlArea.previousSibling.previousSibling if prPrSibling and\ not (self.docObj.getTypeField(prPrSibling) == "br" or\ self.docObj.getTypeField(prPrSibling) == "comment"): parentNode = xmlArea.parentNode parentNode.insertBefore(self.docObj.createField("br", [],"",[], False,False), xmlArea) # Если после есть BR а за ним ничего нет, удаляем BR if xmlArea.nextSibling and\ self.docObj.getTypeField(xmlArea.nextSibling) == "br": if not xmlArea.nextSibling.nextSibling: parentNode = xmlArea.nextSibling.parentNode parentNode.removeChild(xmlArea.nextSibling) def join(self, kdeObj): """Объединяем конфигурации""" if isinstance(kdeObj, plasma): self.docObj.joinDoc(kdeObj.doc) self.postXML()