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.

179 lines
7.9 KiB

4 years ago
# vim: fileencoding=utf-8
#
from .base_format import BaseFormat
from collections import OrderedDict
import re
try:
from lxml.etree.ElementTree import fromstring
except ImportError:
from xml.etree.ElementTree import fromstring
class PatchFormat(BaseFormat):
def __init__(self, document_text: str, multiline=False, dotall=False,
comment_symbol=''):
4 years ago
processing_methods = OrderedDict()
super().__init__(processing_methods)
self._format = 'patch'
self._multiline_flag = multiline
self._dotall_flag = dotall
self._parsed_patch = None
self._document_to_patch = ''
self._FLAG_VALUES = {'True': True,
'False': False,
'true': True,
'false': False,
'1': True,
'0': False}
self._XML_ROOT_LINE = '<?xml version="1.0" encoding="utf-8"?>\
<patch>{0}</patch>'
if not self._parse_patch(document_text):
# Какая-то обработка ошибки.
print('Error: Can not parse patch document.')
def _parse_patch(self, patch_text):
xml_patch = self._XML_ROOT_LINE.format(patch_text.strip())
try:
self._parsed_patch = fromstring(xml_patch)
return True
except Exception:
# Какая-то обработка ошибки.
print('Error: Incorrect text of the template.')
return False
def execute_format(self, document_to_patch):
if not document_to_patch.strip() == '':
self._document_to_patch = document_to_patch
if self._parse_patch is None:
return False
else:
if not self._patch_document(document_to_patch):
error_message = 'Error: Can not run patch.'
print(error_message)
return False
else:
after_patch = self._document_to_patch
self._document_to_patch = ''
return after_patch
def _patch_document(self, document_to_patch):
patch_iterator = self._parsed_patch.getiterator()
PATCH_DOCUMENT_TAGS = ('reg', 'text')
patch_element = next(patch_iterator, False)
if not patch_element or not patch_element.tag == 'patch':
print('Error: Incorrect text of the template.')
return False
while True:
for patch_tag in PATCH_DOCUMENT_TAGS:
patch_element = next(patch_iterator, None)
if patch_element is None:
if patch_tag == 'text':
print('Error: Last <text>Text</text> '
'object is missed.')
return False
else:
break
if patch_element.tag == patch_tag:
if patch_element.text is not None:
element_text = patch_element.text.strip()
if element_text == '':
error_message = 'Error: Incorrect text of the \
template: <{0}>%s</{0}>'.format(
patch_tag
)
print(error_message)
return False
else:
error_message = 'Error: Incorrect text of the \
template: <{0}></{0}>'.format(
patch_tag
)
print(error_message)
return False
if patch_tag == 'reg':
dotall = patch_element.attrib.get('dotall', False)
regex_flags = 0
if 'multiline' in patch_element.attrib:
multiline = patch_element.attrib['multiline']
if multiline not in self._FLAG_VALUES:
error_message = ('Error: Invalid multiline '
'value.')
print(error_message)
return False
else:
multiline = self._FLAG_VALUES[multiline]
# Если глобально флаг MULTILINE включен, но в
# атрибутах тэга <reg> этот флаг присутствует со
# значением False -- для этого регулярного
# выражения этот флаг также будет False.
multiline_global = self._multiline_flag & multiline
else:
multiline = False
multiline_global = self._multiline_flag
if multiline_global or multiline:
regex_flags |= re.MULTILINE
if 'dotall' in patch_element.attrib:
dotall = patch_element.attrib['dotall']
if dotall not in self._FLAG_VALUES:
error_message = 'Error: Invalid dotall value.'
print(error_message)
return False
else:
dotall = self._FLAG_VALUES[dotall]
# Если глобально флаг DOTALL включен, но в
# атрибутах тэга <reg> этот флаг присутствует со
# значением False -- для этого регулярного
# выражения этот флаг также будет False.
dotall_global = self._dotall_flag & dotall
else:
dotall = False
dotall_global = self._dotall_flag
if dotall_global or dotall:
regex_flags |= re.DOTALL
regex_expression = re.compile(element_text,
regex_flags)
else:
text_for_replace = element_text
else:
if patch_element.tag in PATCH_DOCUMENT_TAGS:
error_message = 'Error: <{0}> is expected, \
<{1}> instead.'.format(
patch_tag,
patch_element.tag
)
print(error_message)
else:
error_message = 'Error: Unknown tag: {0}'.format(
patch_element.tag
)
print(error_message)
# Какая-то обработка ошибки.
error_message = 'Error: Incorrect text of the template.'
print(error_message)
return False
else:
self._document_to_patch = re.sub(regex_expression,
text_for_replace,
self._document_to_patch)
continue
return True