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.

178 lines
7.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 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):
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