Skip to content

Commit 3c8222f

Browse files
suzakunicoddemus
authored andcommitted
Highlight the path of file location in error report
So that it's more obvious when we need to copy the file path.
1 parent aa145fa commit 3c8222f

File tree

4 files changed

+76
-40
lines changed

4 files changed

+76
-40
lines changed

AUTHORS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,4 @@ Tom Viner
122122
Trevor Bekolay
123123
Vasily Kuznetsov
124124
Wouter van Ackooy
125-
125+
Xuecong Liao

CHANGELOG.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ time or change existing behaviors in order to make them less surprising/more use
166166
* Plugins now benefit from assertion rewriting. Thanks
167167
`@sober7`_, `@nicoddemus`_ and `@flub`_ for the PR.
168168

169+
* Highlight path of the file location in the error report to make it easier to copy/paste.
170+
Thanks `@suzaku`_ for the PR (`#1778`_).
171+
169172
* Fixtures marked with ``@pytest.fixture`` can now use ``yield`` statements exactly like
170173
those marked with the ``@pytest.yield_fixture`` decorator. This change renders
171174
``@pytest.yield_fixture`` deprecated and makes ``@pytest.fixture`` with ``yield`` statements
@@ -347,6 +350,7 @@ time or change existing behaviors in order to make them less surprising/more use
347350
.. _#1723: https://github.com/pytest-dev/pytest/pull/1723
348351
.. _#1740: https://github.com/pytest-dev/pytest/issues/1740
349352
.. _#1749: https://github.com/pytest-dev/pytest/issues/1749
353+
.. _#1778: https://github.com/pytest-dev/pytest/pull/1778
350354
.. _#372: https://github.com/pytest-dev/pytest/issues/372
351355
.. _#457: https://github.com/pytest-dev/pytest/issues/457
352356
.. _#460: https://github.com/pytest-dev/pytest/pull/460
@@ -385,6 +389,7 @@ time or change existing behaviors in order to make them less surprising/more use
385389
.. _@RedBeardCode: https://github.com/RedBeardCode
386390
.. _@sallner: https://github.com/sallner
387391
.. _@sober7: https://github.com/sober7
392+
.. _@suzaku: https://github.com/suzaku
388393
.. _@Stranger6667: https://github.com/Stranger6667
389394
.. _@tareqalayan: https://github.com/tareqalayan
390395
.. _@taschini: https://github.com/taschini

_pytest/_code/code.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,8 @@ def toterminal(self, tw):
785785
i = msg.find("\n")
786786
if i != -1:
787787
msg = msg[:i]
788-
tw.line("%s:%s: %s" %(self.path, self.lineno, msg))
788+
tw.write(self.path, bold=True, red=True)
789+
tw.line(":%s: %s" % (self.lineno, msg))
789790

790791
class ReprLocals(TerminalRepr):
791792
def __init__(self, lines):

testing/code/test_excinfo.py

Lines changed: 68 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,23 @@
2626
pytest_version_info = tuple(map(int, pytest.__version__.split(".")[:3]))
2727

2828
class TWMock:
29+
WRITE = object()
30+
2931
def __init__(self):
3032
self.lines = []
33+
self.is_writing = False
3134
def sep(self, sep, line=None):
3235
self.lines.append((sep, line))
36+
def write(self, msg, **kw):
37+
self.lines.append((TWMock.WRITE, msg))
3338
def line(self, line, **kw):
3439
self.lines.append(line)
3540
def markup(self, text, **kw):
3641
return text
42+
def get_write_msg(self, idx):
43+
flag, msg = self.lines[idx]
44+
assert flag == TWMock.WRITE
45+
return msg
3746

3847
fullwidth = 80
3948

@@ -803,14 +812,18 @@ def f():
803812
assert tw.lines[0] == " def f():"
804813
assert tw.lines[1] == "> g(3)"
805814
assert tw.lines[2] == ""
806-
assert tw.lines[3].endswith("mod.py:5: ")
807-
assert tw.lines[4] == ("_ ", None)
808-
assert tw.lines[5] == ""
809-
assert tw.lines[6] == " def g(x):"
810-
assert tw.lines[7] == "> raise ValueError(x)"
811-
assert tw.lines[8] == "E ValueError: 3"
812-
assert tw.lines[9] == ""
813-
assert tw.lines[10].endswith("mod.py:3: ValueError")
815+
line = tw.get_write_msg(3)
816+
assert line.endswith("mod.py")
817+
assert tw.lines[4] == (":5: ")
818+
assert tw.lines[5] == ("_ ", None)
819+
assert tw.lines[6] == ""
820+
assert tw.lines[7] == " def g(x):"
821+
assert tw.lines[8] == "> raise ValueError(x)"
822+
assert tw.lines[9] == "E ValueError: 3"
823+
assert tw.lines[10] == ""
824+
line = tw.get_write_msg(11)
825+
assert line.endswith("mod.py")
826+
assert tw.lines[12] == ":3: ValueError"
814827

815828
def test_toterminal_long_missing_source(self, importasmod, tmpdir):
816829
mod = importasmod("""
@@ -829,13 +842,17 @@ def f():
829842
tw.lines.pop(0)
830843
assert tw.lines[0] == "> ???"
831844
assert tw.lines[1] == ""
832-
assert tw.lines[2].endswith("mod.py:5: ")
833-
assert tw.lines[3] == ("_ ", None)
834-
assert tw.lines[4] == ""
835-
assert tw.lines[5] == "> ???"
836-
assert tw.lines[6] == "E ValueError: 3"
837-
assert tw.lines[7] == ""
838-
assert tw.lines[8].endswith("mod.py:3: ValueError")
845+
line = tw.get_write_msg(2)
846+
assert line.endswith("mod.py")
847+
assert tw.lines[3] == ":5: "
848+
assert tw.lines[4] == ("_ ", None)
849+
assert tw.lines[5] == ""
850+
assert tw.lines[6] == "> ???"
851+
assert tw.lines[7] == "E ValueError: 3"
852+
assert tw.lines[8] == ""
853+
line = tw.get_write_msg(9)
854+
assert line.endswith("mod.py")
855+
assert tw.lines[10] == ":3: ValueError"
839856

840857
def test_toterminal_long_incomplete_source(self, importasmod, tmpdir):
841858
mod = importasmod("""
@@ -854,13 +871,17 @@ def f():
854871
tw.lines.pop(0)
855872
assert tw.lines[0] == "> ???"
856873
assert tw.lines[1] == ""
857-
assert tw.lines[2].endswith("mod.py:5: ")
858-
assert tw.lines[3] == ("_ ", None)
859-
assert tw.lines[4] == ""
860-
assert tw.lines[5] == "> ???"
861-
assert tw.lines[6] == "E ValueError: 3"
862-
assert tw.lines[7] == ""
863-
assert tw.lines[8].endswith("mod.py:3: ValueError")
874+
line = tw.get_write_msg(2)
875+
assert line.endswith("mod.py")
876+
assert tw.lines[3] == ":5: "
877+
assert tw.lines[4] == ("_ ", None)
878+
assert tw.lines[5] == ""
879+
assert tw.lines[6] == "> ???"
880+
assert tw.lines[7] == "E ValueError: 3"
881+
assert tw.lines[8] == ""
882+
line = tw.get_write_msg(9)
883+
assert line.endswith("mod.py")
884+
assert tw.lines[10] == ":3: ValueError"
864885

865886
def test_toterminal_long_filenames(self, importasmod):
866887
mod = importasmod("""
@@ -874,15 +895,18 @@ def f():
874895
try:
875896
repr = excinfo.getrepr(abspath=False)
876897
repr.toterminal(tw)
877-
line = tw.lines[-1]
878898
x = py.path.local().bestrelpath(path)
879899
if len(x) < len(str(path)):
880-
assert line == "mod.py:3: ValueError"
900+
msg = tw.get_write_msg(-2)
901+
assert msg == "mod.py"
902+
assert tw.lines[-1] == ":3: ValueError"
881903

882904
repr = excinfo.getrepr(abspath=True)
883905
repr.toterminal(tw)
906+
msg = tw.get_write_msg(-2)
907+
assert msg == path
884908
line = tw.lines[-1]
885-
assert line == "%s:3: ValueError" %(path,)
909+
assert line == ":3: ValueError"
886910
finally:
887911
old.chdir()
888912

@@ -929,19 +953,25 @@ def i():
929953
assert tw.lines[1] == " def f():"
930954
assert tw.lines[2] == "> g()"
931955
assert tw.lines[3] == ""
932-
assert tw.lines[4].endswith("mod.py:3: ")
933-
assert tw.lines[5] == ("_ ", None)
934-
assert tw.lines[6].endswith("in g")
935-
assert tw.lines[7] == " h()"
936-
assert tw.lines[8].endswith("in h")
937-
assert tw.lines[9] == " i()"
938-
assert tw.lines[10] == ("_ ", None)
939-
assert tw.lines[11] == ""
940-
assert tw.lines[12] == " def i():"
941-
assert tw.lines[13] == "> raise ValueError()"
942-
assert tw.lines[14] == "E ValueError"
943-
assert tw.lines[15] == ""
944-
assert tw.lines[16].endswith("mod.py:9: ValueError")
956+
msg = tw.get_write_msg(4)
957+
assert msg.endswith("mod.py")
958+
assert tw.lines[5] == ":3: "
959+
assert tw.lines[6] == ("_ ", None)
960+
tw.get_write_msg(7)
961+
assert tw.lines[8].endswith("in g")
962+
assert tw.lines[9] == " h()"
963+
tw.get_write_msg(10)
964+
assert tw.lines[11].endswith("in h")
965+
assert tw.lines[12] == " i()"
966+
assert tw.lines[13] == ("_ ", None)
967+
assert tw.lines[14] == ""
968+
assert tw.lines[15] == " def i():"
969+
assert tw.lines[16] == "> raise ValueError()"
970+
assert tw.lines[17] == "E ValueError"
971+
assert tw.lines[18] == ""
972+
msg = tw.get_write_msg(19)
973+
msg.endswith("mod.py")
974+
assert tw.lines[20] == ":9: ValueError"
945975

946976
@pytest.mark.skipif("sys.version_info[0] < 3")
947977
def test_exc_chain_repr(self, importasmod):

0 commit comments

Comments
 (0)