Lib.robot.utils.escaping.py Maven / Gradle / Ivy
# Copyright 2008-2015 Nokia Solutions and Networks
#
# 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 .platform import PY3
from .robottypes import is_string
if PY3:
unichr = chr
_CONTROL_WORDS = frozenset(('ELSE', 'ELSE IF', 'AND', 'WITH NAME'))
_SEQUENCES_TO_BE_ESCAPED = ('\\', '${', '@{', '%{', '&{', '*{', '=')
def escape(item):
if not is_string(item):
return item
if item in _CONTROL_WORDS:
return '\\' + item
for seq in _SEQUENCES_TO_BE_ESCAPED:
if seq in item:
item = item.replace(seq, '\\' + seq)
return item
def unescape(item):
if not (is_string(item) and '\\' in item):
return item
return Unescaper().unescape(item)
class Unescaper(object):
def unescape(self, string):
return ''.join(self._yield_unescaped(string))
def _yield_unescaped(self, string):
while '\\' in string:
finder = EscapeFinder(string)
yield finder.before + finder.backslashes
if finder.escaped and finder.text:
yield self._unescape(finder.text)
else:
yield finder.text
string = finder.after
yield string
def _unescape(self, text):
try:
escape = str(text[0])
except UnicodeError:
return text
try:
unescaper = getattr(self, '_unescaper_for_' + escape)
except AttributeError:
return text
else:
return unescaper(text[1:])
def _unescaper_for_n(self, text):
if text.startswith(' '):
text = text[1:]
return '\n' + text
def _unescaper_for_r(self, text):
return '\r' + text
def _unescaper_for_t(self, text):
return '\t' + text
def _unescaper_for_x(self, text):
return self._unescape_character(text, 2, 'x')
def _unescaper_for_u(self, text):
return self._unescape_character(text, 4, 'u')
def _unescaper_for_U(self, text):
return self._unescape_character(text, 8, 'U')
def _unescape_character(self, text, length, escape):
try:
char = self._get_character(text[:length], length)
except ValueError:
return escape + text
else:
return char + text[length:]
def _get_character(self, text, length):
if len(text) < length or not text.isalnum():
raise ValueError
ordinal = int(text, 16)
# No Unicode code points above 0x10FFFF
if ordinal > 0x10FFFF:
raise ValueError
# unichr only supports ordinals up to 0xFFFF with narrow Python builds
if ordinal > 0xFFFF:
return eval("u'\\U%08x'" % ordinal)
return unichr(ordinal)
class EscapeFinder(object):
_escaped = re.compile(r'(\\+)([^\\]*)')
def __init__(self, string):
res = self._escaped.search(string)
self.before = string[:res.start()]
escape_chars = len(res.group(1))
self.backslashes = '\\' * (escape_chars // 2)
self.escaped = bool(escape_chars % 2)
self.text = res.group(2)
self.after = string[res.end():]
def split_from_equals(string):
index = _get_split_index(string)
if index == -1:
return string, None
return string[:index], string[index+1:]
def _get_split_index(string):
index = 0
while '=' in string[index:]:
index += string[index:].index('=')
if _not_escaping(string[:index]):
return index
index += 1
return -1
def _not_escaping(name):
backslashes = len(name) - len(name.rstrip('\\'))
return backslashes % 2 == 0
© 2015 - 2025 Weber Informatics LLC | Privacy Policy