Skip to content

Commit

Permalink
Fix end offset
Browse files Browse the repository at this point in the history
  • Loading branch information
nineteendo committed Jul 19, 2024
1 parent 1092b88 commit 84c9135
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 25 deletions.
8 changes: 4 additions & 4 deletions src/jsonyx/_decoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,14 @@
).match


# TODO(Nice Zombies): refactor
def _get_err_context(doc: str, start: int, end: int) -> (
tuple[int, str, int]
):
line_start: int = doc.rfind("\n", 0, start) + 1
if (line_end := doc.find("\n", start)) == -1:
line_end = len(doc)

end = min(end, line_end + 1)
end = min(max(start + 1, line_end), end)
max_chars: int = get_terminal_size().columns - 4 # leading spaces
text_start: int = max(min(
line_end - max_chars, end - max_chars // 2 - 1, start - max_chars // 3,
Expand Down Expand Up @@ -175,9 +174,10 @@ def __init__( # pylint: disable=R0913

lineno: int = doc.count("\n", 0, start) + 1
self.colno: int = start - doc.rfind("\n", 0, start)
start_offset, text, end_offset = _get_err_context(doc, start, end)
self.end_colno: int = self.colno + end - start
offset, text, end_offset = _get_err_context(doc, start, end)
super().__init__(
msg, (filename, lineno, start_offset, text, lineno, end_offset),
msg, (filename, lineno, offset, text, lineno, end_offset),
)

def __str__(self) -> str:
Expand Down
3 changes: 3 additions & 0 deletions src/jsonyx/test_jsonyx/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# Copyright (C) 2024 Nice Zombies
# TODO(Nice Zombies): test jsonyx.dumps
# TODO(Nice Zombies): test jsonyx.format_syntax_error
# TODO(Nice Zombies): test jsonyx.DuplicateKey
"""JSON tests."""
from __future__ import annotations

Expand Down
36 changes: 15 additions & 21 deletions src/jsonyx/test_jsonyx/test_loads.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,26 @@
from types import ModuleType


# pylint: disable-next=R0913
def _check_syntax_err( # noqa: PLR0913, PLR0917
def _check_syntax_err(
exc_info: pytest.ExceptionInfo[Any], msg: str, lineno: int, colno: int,
offset: int, end_offset: int = -1,
end_colno: int = -1,
) -> None:
exc: Any = exc_info.value
assert exc.msg == msg
assert exc.lineno == lineno
assert exc.colno == colno
assert exc.offset == offset
if end_offset == -1:
assert exc.end_offset == colno + 1
if end_colno == -1:
assert exc.end_colno == colno + 1
else:
assert exc.end_offset == end_offset
assert exc.end_colno == end_colno


def test_empty(json: ModuleType) -> None:
"""Test empty JSON."""
with pytest.raises(json.JSONSyntaxError) as exc_info:
json.loads("")

_check_syntax_err(exc_info, "Expecting value", 1, 1, 1)
_check_syntax_err(exc_info, "Expecting value", 1, 1)


@pytest.mark.parametrize(("string", "expected"), [
Expand Down Expand Up @@ -74,7 +72,7 @@ def test_nan_and_infinity_not_allowed(json: ModuleType, string: str) -> None:
json.loads(string)

_check_syntax_err(
exc_info, f"{string} is not allowed", 1, 1, 1, len(string) + 1,
exc_info, f"{string} is not allowed", 1, 1, len(string) + 1,
)


Expand Down Expand Up @@ -154,9 +152,7 @@ def test_big_number(json: ModuleType, string: str) -> None:
with pytest.raises(json.JSONSyntaxError) as exc_info:
json.loads(string)

_check_syntax_err(
exc_info, "Number is too large", 1, 1, 1, len(string) + 1,
)
_check_syntax_err(exc_info, "Number is too large", 1, 1, len(string) + 1)


@pytest.mark.parametrize(("string", "expected"), [
Expand Down Expand Up @@ -204,26 +200,26 @@ def test_string(json: ModuleType, string: str, expected: Any) -> None:
assert json.loads(string) == expected


@pytest.mark.parametrize(("string", "msg", "colno", "end_offset"), [
@pytest.mark.parametrize(("string", "msg", "colno", "end_colno"), [
('"foo', "Unterminated string", 1, 5),
('"foo\n', "Unterminated string", 1, 5),
('"\b"', "Unescaped control character", 2, -1),
('"\\', "Expecting escaped character", 3, -1),
('"\\\n', "Expecting escaped character", 3, -1),
(r'"\a"', "Invalid backslash escape", 2, 4),
(r'"\u', "Expecting 4 hex digits", 4, -1),
(r'"\u', "Expecting 4 hex digits", 4, 8),
(r'"\uXXXX"', "Expecting 4 hex digits", 4, 8),
(r'"\ud800\u', "Expecting 4 hex digits", 10, -1),
(r'"\ud800\u', "Expecting 4 hex digits", 10, 14),
(r'"\ud800\uXXXX"', "Expecting 4 hex digits", 10, 14),
])
def test_invalid_string(
json: ModuleType, string: str, msg: str, colno: int, end_offset: int,
json: ModuleType, string: str, msg: str, colno: int, end_colno: int,
) -> None:
"""Test invalid JSON string."""
with pytest.raises(json.JSONSyntaxError) as exc_info:
json.loads(string)

_check_syntax_err(exc_info, msg, 1, colno, colno, end_offset)
_check_syntax_err(exc_info, msg, 1, colno, end_colno)


@pytest.mark.parametrize(("string", "expected"), [
Expand Down Expand Up @@ -280,9 +276,7 @@ def test_trailing_comma_not_allowed(
with pytest.raises(json.JSONSyntaxError) as exc_info:
json.loads(string)

_check_syntax_err(
exc_info, "Trailing comma is not allowed", 1, colno, colno,
)
_check_syntax_err(exc_info, "Trailing comma is not allowed", 1, colno)


@pytest.mark.parametrize("string", ["-", "foo"])
Expand All @@ -291,4 +285,4 @@ def test_invalid_value(json: ModuleType, string: str) -> None:
with pytest.raises(json.JSONSyntaxError) as exc_info:
json.loads(string)

_check_syntax_err(exc_info, "Expecting value", 1, 1, 1)
_check_syntax_err(exc_info, "Expecting value", 1, 1)

0 comments on commit 84c9135

Please sign in to comment.