def __init__(self): # This is a bit of a hack. We're just using the error class for its # formatting features. # # If I ever get around to refactoring this, note that the unit tests # rely on being able to access list of all log messages with parameters # substituted but without bullet points applied. self._err = Error()
def test_push_pop_info(s): class A(Error): pass class B(A): pass A.push_info(s['template'], **s['data']) B.push_info("x: {x}", x=1) B.push_info("y: {y}", y=2) a, b = A("Brief"), B("Brief") assert a.info_strs == [ s['expected'], ] assert b.info_strs == [ s['expected'], "x: 1", "y: 2", ] with pytest.raises(IndexError): Error.pop_info() a, b = A("Brief"), B("Brief") assert a.info_strs == [ s['expected'], ] assert b.info_strs == [ s['expected'], "x: 1", "y: 2", ] B.pop_info() a, b = A("Brief"), B("Brief") assert a.info_strs == [ s['expected'], ] assert b.info_strs == [ s['expected'], "x: 1", ] A.pop_info() a, b = A("Brief"), B("Brief") assert a.info_strs == [] assert b.info_strs == [ "x: 1", ]
def test_hints(s): e = Error("Brief", **s['data']) e.hints += s['template'] e.hints += "Second line" with pytest.raises(AttributeError, match=r"did you mean to use `\+\=`"): e.hints = "Direct assignment" assert e.brief_str == "Brief" assert e.info_strs == [] assert e.hint_strs == [s['expected'], "Second line"] assert e.blame_strs == [] assert str(e) == f"""\
def test_push_clear_info(s): class A(Error): pass class B(A): pass A.push_info(s['template'], **s['data']) B.push_info("x: {x}", x=1) B.push_info("y: {y}", y=2) a, b = A("Brief"), B("Brief") assert a.info_strs == [ s['expected'], ] assert b.info_strs == [ s['expected'], "x: 1", "y: 2", ] Error.clear_info() a, b = A("Brief"), B("Brief") assert a.info_strs == [ s['expected'], ] assert b.info_strs == [ s['expected'], "x: 1", "y: 2", ] B.clear_info() a, b = A("Brief"), B("Brief") assert a.info_strs == [ s['expected'], ] assert b.info_strs == [ s['expected'], ] A.clear_info() a, b = A("Brief"), B("Brief") assert a.info_strs == [] assert b.info_strs == []
def test_str(): e = Error("Brief") e.info += "Info" e.blame += "Blame" e.hints += "Hint" assert str(e) == """\
class Log: def __init__(self): # This is a bit of a hack. We're just using the error class for its # formatting features. # # If I ever get around to refactoring this, note that the unit tests # rely on being able to access list of all log messages with parameters # substituted but without bullet points applied. self._err = Error() def __str__(self): return str(self._err) def info(self, message, **kwargs): self._err.put_info(message, **kwargs) def hint(self, message): self._err.info += message
def test_brief(s): e = Error(s['template'], **s['data']) assert e.brief_str == s['expected'] assert e.info_strs == [] assert e.blame_strs == [] assert e.hint_strs == [] assert str(e) == f"""\
def test_iadd(): e = Error() e.info += "a" e.info += lambda e: "b" e.info += ["c", "d"] e.info += ("e", "f") assert e.info_strs == ["a", "b", "c", "d", "e", "f"]
def test_put_info(): e = Error(a=1, z=-1) e.info += "a={a}" e.put_info("a={a}") e.put_info("b={b}", b=2) e.put_info("b={b}", "c={c}", c=3) e.info += "z={z}" assert e.info_strs == [ "a=1", "a=1", "b=2", "b=2", "c=3", "z=-1", ]
def test_put_info_nested(): e = Error(a=1, b=1, c=1) e.put_info("a={a} b={b} c={c}", a=2, b=2) e.put_info("a={a} b={b} c={c}", a=3) assert e.info_strs == [ "a=2 b=2 c=1", "a=3 b=2 c=1", ]
def test_data(): e = Error(a=1) assert 'a' in e.data assert 'b' not in e.data assert len(e.data) == 1 assert e.data == {'a': 1} # getattr assert e.data.a == 1 assert e.data['a'] == 1 with pytest.raises(AttributeError): e.data.b with pytest.raises(KeyError): e.data['b'] # setattr e.data.b = 2 assert e.data == {'a': 1, 'b': 2} e.data['c'] = 3 assert e.data == {'a': 1, 'b': 2, 'c': 3} # delattr del e.data.b assert e.data == {'a': 1, 'c': 3} del e.data['c'] assert e.data == {'a': 1} with pytest.raises(AttributeError): del e.data.b with pytest.raises(KeyError): del e.data['b']
def test_str_dict(): # When I was using dotmap, I ran into a problem where dictionary data would # be converted into a dotmap and rendered confusingly. This test just # makes sure that that behavior is eliminated. e = Error("{d}", d={'a': 1}) assert str(e) == "{'a': 1}\n"
def test_str_err(): e = Error("{x}") e_str = str(e) assert "Error occurred while formatting Error:" in e_str assert "KeyError: 'x'" in e_str
def test_raise(): with pytest.raises(Error, match="Brief"): raise Error("Brief")