pytest:使用 re.escape() 断言转义字符失败
pytest: assert escaped characters with re.escape() fails
我有一个函数可以使用 re.escape()
方法 returns 个字符。
在实证测试中它似乎有效,我想用 pytest 测试它。
但是我无法让测试正常工作,所以在尝试了几次之后,我尝试了类似的方法:
def test_escape():
> assert re.escape('!') == "\!"
E AssertionError: assert '!' == '\!'
E - !
E + \!
test/test_e.py:6: AssertionError
我也用解释器测试过,没有任何问题:
>>> re.escape('!') == '\!'
True
禁用使用“-s”捕获pytest的输出并尝试打印re.escape('!')
的输出我得到"!"
而不是"\!"
,这不会发生口译员。
我试图通过强制 "\!"
作为输出来对 re.escape 进行 monkeypatch,它神奇地起作用了。这显然不能解决我的问题,但突出显示了我不知道的某种问题 re.escape
@pytest.fixture
def mock_escape(monkeypatch):
monkeypatch.setattr(re, "escape", lambda x: "\!")
def test_escape(mock_escape):
assert re.escape('!') == "\!"
...
test/test_e.py .
======================================== 1 passed in 0.07s =========================================
all test passed
出于好奇,我对我的原始函数做了同样的事情(没有 monkeypatching 但编辑它的 return),即使在这种情况下它也能工作。
所以这不是因为导入而发生的问题。
# 编辑:#
tmt发现是python或者pytest版本的问题。
python 3.7.2 和 pytest 5.2.1 会出现问题。
python 3.6.3 和 pytest 4.5.0 不会出现此问题
所以这几乎可以肯定是一个错误(在我看来更容易出现 pytest)
正如家伙的回复,这只是 re.escape()
的行为改变
如果您查看 re.py,您会看到 escape()
正在使用定义的特殊字符列表
_special_chars_map = {i: '\' + chr(i) for i in b'()[]{}?*+-|^$\.&~# \t\n\r\v\f'}
def escape(pattern):
"""
Escape special characters in a string.
"""
if isinstance(pattern, str):
return pattern.translate(_special_chars_map)
else:
pattern = str(pattern, 'latin1')
return pattern.translate(_special_chars_map).encode('latin1')
和!
不包括在那里,所以re.escape('!')
return!
,而不是\!
。
assert re.escape('[') == '\['
例如会起作用。
更新:
此答案适用于 Python 3.7,适用于 Python 3.6。 Pull request #1007 changed escape()
pull source code
re.escape() now escapes only special characters.
以前的版本:
_alphanum_str = frozenset("_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890")
_alphanum_bytes = frozenset(b"_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890")
def escape(pattern):
if isinstance(pattern, str):
alphanum = _alphanum_str
s = list(pattern)
for i, c in enumerate(pattern):
if c not in alphanum:
if c == "[=12=]0":
s[i] = "\000"
else:
s[i] = "\" + c
return "".join(s)
else:
alphanum = _alphanum_bytes
s = []
esc = ord(b"\")
for c in pattern:
if c in alphanum:
s.append(c)
else:
if c == 0:
s.extend(b"\000")
else:
s.append(esc)
s.append(c)
return bytes(s)
它于 2017 年 4 月 13 日修改,所以查看 versions history re.escape('!') == '\!'
应该适用于 Python 3.6 和更早的版本。
我有一个函数可以使用 re.escape()
方法 returns 个字符。
在实证测试中它似乎有效,我想用 pytest 测试它。
但是我无法让测试正常工作,所以在尝试了几次之后,我尝试了类似的方法:
def test_escape():
> assert re.escape('!') == "\!"
E AssertionError: assert '!' == '\!'
E - !
E + \!
test/test_e.py:6: AssertionError
我也用解释器测试过,没有任何问题:
>>> re.escape('!') == '\!'
True
禁用使用“-s”捕获pytest的输出并尝试打印re.escape('!')
的输出我得到"!"
而不是"\!"
,这不会发生口译员。
我试图通过强制 "\!"
作为输出来对 re.escape 进行 monkeypatch,它神奇地起作用了。这显然不能解决我的问题,但突出显示了我不知道的某种问题 re.escape
@pytest.fixture
def mock_escape(monkeypatch):
monkeypatch.setattr(re, "escape", lambda x: "\!")
def test_escape(mock_escape):
assert re.escape('!') == "\!"
...
test/test_e.py .
======================================== 1 passed in 0.07s =========================================
all test passed
出于好奇,我对我的原始函数做了同样的事情(没有 monkeypatching 但编辑它的 return),即使在这种情况下它也能工作。 所以这不是因为导入而发生的问题。
# 编辑:#
tmt发现是python或者pytest版本的问题。
python 3.7.2 和 pytest 5.2.1 会出现问题。
python 3.6.3 和 pytest 4.5.0 不会出现此问题
所以这几乎可以肯定是一个错误(在我看来更容易出现 pytest)
正如家伙的回复,这只是 re.escape()
如果您查看 re.py,您会看到 escape()
正在使用定义的特殊字符列表
_special_chars_map = {i: '\' + chr(i) for i in b'()[]{}?*+-|^$\.&~# \t\n\r\v\f'}
def escape(pattern):
"""
Escape special characters in a string.
"""
if isinstance(pattern, str):
return pattern.translate(_special_chars_map)
else:
pattern = str(pattern, 'latin1')
return pattern.translate(_special_chars_map).encode('latin1')
和!
不包括在那里,所以re.escape('!')
return!
,而不是\!
。
assert re.escape('[') == '\['
例如会起作用。
更新:
此答案适用于 Python 3.7,适用于 Python 3.6。 Pull request #1007 changed escape()
pull source code
re.escape() now escapes only special characters.
以前的版本:
_alphanum_str = frozenset("_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890")
_alphanum_bytes = frozenset(b"_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890")
def escape(pattern):
if isinstance(pattern, str):
alphanum = _alphanum_str
s = list(pattern)
for i, c in enumerate(pattern):
if c not in alphanum:
if c == "[=12=]0":
s[i] = "\000"
else:
s[i] = "\" + c
return "".join(s)
else:
alphanum = _alphanum_bytes
s = []
esc = ord(b"\")
for c in pattern:
if c in alphanum:
s.append(c)
else:
if c == 0:
s.extend(b"\000")
else:
s.append(esc)
s.append(c)
return bytes(s)
它于 2017 年 4 月 13 日修改,所以查看 versions history re.escape('!') == '\!'
应该适用于 Python 3.6 和更早的版本。