Skip to content

Commit

Permalink
Add unit tests to validate exception formatting of new Python syntax
Browse files Browse the repository at this point in the history
These tests ensure that there are no unexpected errors during syntax
highlighting and local variable collection. However, this also shows
that the implementation can be improved. Some new keywords (such as
"match") are not recognized.

The addition of "--force-exclude" is necessary to prevent "black"
formatter from failing (despite "fmt: off") due to a parsing error
(caused by "--target-version py35" when the file contains a new
syntax).
  • Loading branch information
Delgan committed Sep 8, 2023
1 parent c5f2ac1 commit c9cfa9c
Show file tree
Hide file tree
Showing 14 changed files with 261 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ repos:
rev: 23.7.0
hooks:
- id: black
args: [-l, '100', --target-version, py35]
args: [-l, '100', --target-version, py35, --force-exclude, tests/exceptions/source/modern/*]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.0.286
hooks:
Expand Down
30 changes: 30 additions & 0 deletions tests/exceptions/output/modern/exception_group_catch.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

+ Exception Group Traceback (most recent call last):
|
| File "tests/exceptions/source/modern/exception_group_catch.py", line 14, in a
| raise ExceptionGroup("group", [ValueError(1)])
|
| ExceptionGroup: group (1 sub-exception)
+-+---------------- 1 ----------------
| ValueError: 1
+------------------------------------


During handling of the above exception, another exception occurred:


Traceback (most recent call last):

File "tests/exceptions/source/modern/exception_group_catch.py", line 25, in <module>
b()
└ <function b at 0xDEADBEEF>

File "tests/exceptions/source/modern/exception_group_catch.py", line 21, in b
except* TypeError: a()
 └ <function a at 0xDEADBEEF>

File "tests/exceptions/source/modern/exception_group_catch.py", line 15, in a
except* x as e: raise ValueError(2)
 └ <class 'ValueError'>

ValueError: 2
11 changes: 11 additions & 0 deletions tests/exceptions/output/modern/f_string.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

Traceback (most recent call last):

File "tests/exceptions/source/modern/f_string.py", line 17, in <module>
hello()
└ <function hello at 0xDEADBEEF>

File "tests/exceptions/source/modern/f_string.py", line 13, in hello
f"{name + f}" or f'{{ {10*10} }}'

TypeError: can only concatenate str (not "int") to str
20 changes: 20 additions & 0 deletions tests/exceptions/output/modern/match_statement.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

Traceback (most recent call last):

File "tests/exceptions/source/modern/match_statement.py", line 21, in <module>
match(1)
└ <function match at 0xDEADBEEF>

File "tests/exceptions/source/modern/match_statement.py", line 18, in match
case y: case(x)
│ │ │ └ 1
│ │ └ <function case at 0xDEADBEEF>
│ └ 1
└ <function case at 0xDEADBEEF>

File "tests/exceptions/source/modern/match_statement.py", line 11, in case
match y / 0:
│ └ 1
└ <function match at 0xDEADBEEF>

ZeroDivisionError: division by zero
20 changes: 20 additions & 0 deletions tests/exceptions/output/modern/positional_only_argument.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

Traceback (most recent call last):

File "tests/exceptions/source/modern/positional_only_argument.py", line 23, in <module>
main()
└ <function main at 0xDEADBEEF>

File "tests/exceptions/source/modern/positional_only_argument.py", line 19, in main
foo(1, 2, c=3)
└ <function foo at 0xDEADBEEF>

File "tests/exceptions/source/modern/positional_only_argument.py", line 15, in foo
def foo(a, /, b, *, c, **d): 1 / 0
 │ │ │ │ └ {}
 │ │ │ └ 3
 │ │ └ 2
 │ └ 1
 └ <function foo at 0xDEADBEEF>

ZeroDivisionError: division by zero
22 changes: 22 additions & 0 deletions tests/exceptions/output/modern/type_hints.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

Traceback (most recent call last):

File "tests/exceptions/source/modern/type_hints.py", line 23, in <module>
main()
└ <function main at 0xDEADBEEF>

File "tests/exceptions/source/modern/type_hints.py", line 19, in main
bar: Name = foo(1, 2, 3)
 └ <function foo at 0xDEADBEEF>

File "tests/exceptions/source/modern/type_hints.py", line 15, in foo
def foo(a: int, b: Union[Name, float], c: "Name") -> T: 1 / 0
 │ │ │ │ │ │ └ ~T
 │ │ │ │ │ └ 3
 │ │ │ │ └ <class 'str'>
 │ │ │ └ typing.Union
 │ │ └ 2
 │ └ 1
 └ <function foo at 0xDEADBEEF>

ZeroDivisionError: division by zero
17 changes: 17 additions & 0 deletions tests/exceptions/output/modern/walrus_operator.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

Traceback (most recent call last):

> File "tests/exceptions/source/modern/walrus_operator.py", line 25, in <module>
main()
└ <function main at 0xDEADBEEF>

File "tests/exceptions/source/modern/walrus_operator.py", line 19, in main
(walrus := foo())
 │ └ <function foo at 0xDEADBEEF>
 └ False

File "tests/exceptions/source/modern/walrus_operator.py", line 8, in foo
if a := "a" + (x:=1):
 └ 1

TypeError: can only concatenate str (not "int") to str
25 changes: 25 additions & 0 deletions tests/exceptions/source/modern/exception_group_catch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# fmt: off
import sys

from loguru import logger

logger.remove()
logger.add(sys.stderr, format="", colorize=True, backtrace=False, diagnose=True)

x = ValueError


def a():
try:
raise ExceptionGroup("group", [ValueError(1)])
except* x as e: raise ValueError(2)


def b():
try:
raise ExceptionGroup("group", [TypeError(1)])
except* TypeError: a()


with logger.catch():
b()
17 changes: 17 additions & 0 deletions tests/exceptions/source/modern/f_string.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# fmt: off
import sys

from loguru import logger

logger.remove()
logger.add(sys.stderr, format="", colorize=True, backtrace=False, diagnose=True)


def hello():
name = "world"
f = 1
f"{name + f}" or f'{{ {10*10} }}'


with logger.catch():
hello()
21 changes: 21 additions & 0 deletions tests/exceptions/source/modern/match_statement.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# fmt: off
import sys

from loguru import logger

logger.remove()
logger.add(sys.stderr, format="", colorize=True, backtrace=False, diagnose=True)

def case(x):
y = 1
match y / 0:
case 1:
pass

def match(x):
y = 1
match x:
case y: case(x)

with logger.catch():
match(1)
23 changes: 23 additions & 0 deletions tests/exceptions/source/modern/positional_only_argument.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# fmt: off
import sys
from typing import TypeVar, Union

from loguru import logger

logger.remove()
logger.add(sys.stderr, format="", colorize=True, backtrace=False, diagnose=True)


T = TypeVar("T")
Name = str


def foo(a, /, b, *, c, **d): 1 / 0


def main():
foo(1, 2, c=3)


with logger.catch():
main()
23 changes: 23 additions & 0 deletions tests/exceptions/source/modern/type_hints.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# fmt: off
import sys
from typing import TypeVar, Union

from loguru import logger

logger.remove()
logger.add(sys.stderr, format="", colorize=True, backtrace=False, diagnose=True)


T = TypeVar("T")
Name = str


def foo(a: int, b: Union[Name, float], c: "Name") -> T: 1 / 0


def main():
bar: Name = foo(1, 2, 3)


with logger.catch():
main()
25 changes: 25 additions & 0 deletions tests/exceptions/source/modern/walrus_operator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# fmt: off
import sys

from loguru import logger


def foo():
if a := "a" + (x:=1):
pass


def bar():
return [y for x in [1, 2] if (y := foo()) != 0]


@logger.catch
def main():
walrus = False
(walrus := foo())


logger.remove()
logger.add(sys.stderr, format="", diagnose=True, backtrace=True, colorize=True)

main()
6 changes: 6 additions & 0 deletions tests/test_exceptions_formatting.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,12 @@ def test_exception_others(filename):
@pytest.mark.parametrize(
"filename, minimum_python_version",
[
("type_hints", (3, 6)),
("f_string", (3, 6)),
("positional_only_argument", (3, 8)),
("walrus_operator", (3, 8)),
("match_statement", (3, 10)),
("exception_group_catch", (3, 11)),
("grouped_simple", (3, 11)),
("grouped_nested", (3, 11)),
("grouped_with_cause_and_context", (3, 11)),
Expand Down

0 comments on commit c9cfa9c

Please sign in to comment.