Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
rev: v6.0.0
hooks:
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace
exclude: ^(tests/.*)
- repo: https://github.com/asottile/reorder-python-imports
rev: v3.12.0
rev: v3.16.0
hooks:
- id: reorder-python-imports

- repo: https://github.com/psf/black
rev: '23.10.1'
- repo: https://github.com/psf/black-pre-commit-mirror
rev: '25.9.0'
hooks:
- id: black
args:
Expand All @@ -21,13 +21,13 @@ repos:
- "120"

- repo: https://github.com/asottile/pyupgrade
rev: v3.15.0
rev: v3.21.0
hooks:
- id: pyupgrade
args: ["--py38-plus"]

- repo: https://github.com/pre-commit/mirrors-mypy
rev: 'v1.6.1'
rev: 'v1.18.2'
hooks:
- id: mypy
args:
Expand All @@ -39,7 +39,7 @@ repos:
- types-regex

- repo: https://github.com/pycqa/flake8
rev: '6.1.0' # pick a git hash / tag to point to
rev: '7.3.0' # pick a git hash / tag to point to
hooks:
- id: flake8
args:
Expand Down
9 changes: 4 additions & 5 deletions json5/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,13 @@ def __init__(
self.parse_int: Callable[[str], typing.Any] | None = parse_int
self.parse_constant: Callable[[Literal['-Infinity', 'Infinity', 'NaN']], typing.Any] | None = parse_constant
self.strict: bool = strict
self.object_pairs_hook: None | (
Callable[[list[tuple[str | JsonIdentifier, typing.Any]]], typing.Any]
) = object_pairs_hook
self.object_pairs_hook: None | (Callable[[list[tuple[str | JsonIdentifier, typing.Any]]], typing.Any]) = (
object_pairs_hook
)
self.parse_json5_identifiers: Callable[[JsonIdentifier], typing.Any] | None = parse_json5_identifiers


class JsonIdentifier(str):
...
class JsonIdentifier(str): ...


def load(
Expand Down
24 changes: 9 additions & 15 deletions json5/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ class KeyValuePair(NamedTuple):
value: Value


def walk(root: Node) -> typing.Generator[Node, None, None]:
def walk(root: Node) -> typing.Generator[Node]:
todo = deque([root])
while todo:
node: Node = todo.popleft()
todo.extend(iter_child_nodes(node))
yield node


def iter_child_nodes(node: Node) -> typing.Generator[Node, None, None]:
def iter_child_nodes(node: Node) -> typing.Generator[Node]:
for attr, value in iter_fields(node):
if isinstance(value, Node):
yield value
Expand All @@ -59,7 +59,7 @@ def iter_child_nodes(node: Node) -> typing.Generator[Node, None, None]:
yield item


def iter_fields(node: Node) -> typing.Generator[tuple[str, Any], None, None]:
def iter_fields(node: Node) -> typing.Generator[tuple[str, Any]]:
for field_name in node._fields:
try:
value = getattr(node, field_name)
Expand Down Expand Up @@ -133,8 +133,7 @@ class Value(Node):
pass


class Key(Node):
...
class Key(Node): ...


class JSONObject(Value):
Expand Down Expand Up @@ -208,8 +207,7 @@ def __eq__(self, other: Any) -> bool:
return hash(self) == hash(other)


class Number(Value):
...
class Number(Value): ...


class Integer(Number):
Expand Down Expand Up @@ -301,12 +299,10 @@ def __init__(
super().__init__(tok=tok, end_tok=tok)


class DoubleQuotedString(String):
...
class DoubleQuotedString(String): ...


class SingleQuotedString(String):
...
class SingleQuotedString(String): ...


class BooleanLiteral(Value):
Expand Down Expand Up @@ -348,9 +344,7 @@ def __init__(self, value: str, tok: JSON5Token | None = None, end_tok: JSON5Toke
super().__init__(tok=tok, end_tok=tok) # Comments are always a single token


class LineComment(Comment):
...
class LineComment(Comment): ...


class BlockComment(Comment):
...
class BlockComment(Comment): ...
49 changes: 18 additions & 31 deletions json5/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ def warning(self, *args: Any, **kwargs: Any) -> None:

ESCAPE_SEQUENCES = {
'b': '\u0008',
'f': '\u000C',
'n': '\u000A',
'r': '\u000D',
'f': '\u000c',
'n': '\u000a',
'r': '\u000d',
't': '\u0009',
'v': '\u000B',
'v': '\u000b',
'0': '\u0000',
'\\': '\u005c',
'"': '\u0022',
Expand Down Expand Up @@ -97,8 +97,7 @@ def unicode_escape_replace(matchobj: re.Match[str]) -> str:


class T_TokenSlice(Protocol):
def __getitem__(self, item: int) -> JSON5Token:
...
def __getitem__(self, item: int) -> JSON5Token: ...


class T_AnyProduction(Protocol):
Expand All @@ -110,8 +109,7 @@ class T_TextProduction(Protocol):
wsc1: list[Comment | str]
value: Value

def __getitem__(self, i: Literal[1]) -> Value:
...
def __getitem__(self, i: Literal[1]) -> Value: ...


class T_FirstKeyValuePairProduction(Protocol):
Expand All @@ -122,22 +120,19 @@ class T_FirstKeyValuePairProduction(Protocol):
value: Value
_slice: T_TokenSlice

def __getitem__(self, item: int) -> Key | Value:
...
def __getitem__(self, item: int) -> Key | Value: ...


class T_WSCProduction(Protocol):
_slice: T_TokenSlice

def __getitem__(self, item: Literal[0]) -> str | Comment:
...
def __getitem__(self, item: Literal[0]) -> str | Comment: ...


class T_CommentProduction(Protocol):
_slice: T_TokenSlice

def __getitem__(self, item: Literal[0]) -> str:
...
def __getitem__(self, item: Literal[0]) -> str: ...


class T_KeyValuePairsProduction(Protocol):
Expand All @@ -161,8 +156,7 @@ class SubsequentKeyValuePairProduction(Protocol):
class T_FirstArrayValueProduction(Protocol):
_slice: T_TokenSlice

def __getitem__(self, item: Literal[1]) -> Value:
...
def __getitem__(self, item: Literal[1]) -> Value: ...

wsc: list[Comment | str]

Expand All @@ -188,20 +182,17 @@ class T_JsonArrayProduction(Protocol):
class T_IdentifierProduction(Protocol):
_slice: T_TokenSlice

def __getitem__(self, item: Literal[0]) -> str:
...
def __getitem__(self, item: Literal[0]) -> str: ...


class T_KeyProduction(Protocol):
def __getitem__(self, item: Literal[1]) -> Identifier | DoubleQuotedString | SingleQuotedString:
...
def __getitem__(self, item: Literal[1]) -> Identifier | DoubleQuotedString | SingleQuotedString: ...


class T_NumberProduction(Protocol):
_slice: T_TokenSlice

def __getitem__(self, item: Literal[0]) -> str:
...
def __getitem__(self, item: Literal[0]) -> str: ...


class T_ValueNumberProduction(Protocol):
Expand All @@ -212,22 +203,19 @@ class T_ValueNumberProduction(Protocol):
class T_ExponentNotationProduction(Protocol):
_slice: T_TokenSlice

def __getitem__(self, item: int) -> str:
...
def __getitem__(self, item: int) -> str: ...


class T_StringTokenProduction(Protocol):
_slice: T_TokenSlice

def __getitem__(self, item: Literal[0]) -> str:
...
def __getitem__(self, item: Literal[0]) -> str: ...


class T_StringProduction(Protocol):
_slice: T_TokenSlice

def __getitem__(self, item: Literal[0]) -> DoubleQuotedString | SingleQuotedString:
...
def __getitem__(self, item: Literal[0]) -> DoubleQuotedString | SingleQuotedString: ...


class T_ValueProduction(Protocol):
Expand All @@ -246,8 +234,7 @@ def __getitem__(
| Integer
| Float
| NaN
):
...
): ...


T_CallArg = typing.TypeVar('T_CallArg')
Expand Down Expand Up @@ -642,7 +629,7 @@ class tok:
self.errors.append(JSON5DecodeError('Expecting value. Received unexpected EOF', None))
return None

def _token_gen(self, tokens: typing.Iterable[JSON5Token]) -> typing.Generator[JSON5Token, None, None]:
def _token_gen(self, tokens: typing.Iterable[JSON5Token]) -> typing.Generator[JSON5Token]:
for tok in tokens:
self.last_token = tok
self.seen_tokens.append(tok)
Expand Down
8 changes: 4 additions & 4 deletions json5/tokenizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class JSONLexer(Lexer): # type: ignore[misc]
OCTAL, # Not allowed, but we capture as a token to raise error later
}

def tokenize(self, text: str, lineno: int = 1, index: int = 0) -> Generator[JSON5Token, None, None]:
def tokenize(self, text: str, lineno: int = 1, index: int = 0) -> Generator[JSON5Token]:
for tok in super().tokenize(text, lineno, index):
tok = JSON5Token(tok, text)
yield tok
Expand Down Expand Up @@ -120,7 +120,7 @@ def BLOCK_COMMENT(self, tok: JSON5Token) -> JSON5Token:
self.lineno += tok.value.count('\n')
return tok

@_("[\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u2028\u2029\ufeff]+")
@_("[\u0009\u000a\u000b\u000c\u000d\u0020\u00a0\u2028\u2029\ufeff]+")
def WHITESPACE(self, tok: JSON5Token) -> JSON5Token:
self.lineno += tok.value.count('\n')
return tok
Expand All @@ -147,13 +147,13 @@ def error(self, t: JSON5Token) -> NoReturn:
raise JSON5DecodeError(f'Illegal character {t.value[0]!r} at index {self.index}', None)


def tokenize(text: str) -> Generator[JSON5Token, None, None]:
def tokenize(text: str) -> Generator[JSON5Token]:
lexer = JSONLexer()
tokens = lexer.tokenize(text)
return tokens


def reversed_enumerate(tokens: typing.Sequence[JSON5Token]) -> typing.Generator[tuple[int, JSON5Token], None, None]:
def reversed_enumerate(tokens: typing.Sequence[JSON5Token]) -> typing.Generator[tuple[int, JSON5Token]]:
for i in reversed(range(len(tokens))):
tok = tokens[i]
yield i, tok
15 changes: 5 additions & 10 deletions tests/test_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,23 @@ def test_loading_comment_raises_runtime_error_default_loader():


def test_loading_unknown_node_raises_error():
class Foo:
...
class Foo: ...

f = Foo()
with pytest.raises(NotImplementedError):
DefaultLoader().load(f)


def test_dumping_unknown_node_raises_error():
class Foo:
...
class Foo: ...

f = Foo()
with pytest.raises(NotImplementedError):
DefaultDumper().dump(f)


def test_known_type_in_wsc_raises_error():
class Foo:
...
class Foo: ...

f = Foo()
model = loads('{foo: "bar"}', loader=ModelLoader())
Expand All @@ -53,17 +50,15 @@ class Foo:


def test_modelizing_unknown_object_raises_error():
class Foo:
...
class Foo: ...

f = Foo()
with pytest.raises(NotImplementedError):
modelize(f)


def test_model_dumper_raises_error_for_unknown_node():
class Foo:
...
class Foo: ...

f = Foo()
with pytest.raises(NotImplementedError):
Expand Down
2 changes: 1 addition & 1 deletion tests/test_json5_load.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ def test_escape_unicode():
sig\\u03A3ma: "\\u03A3 is the sum of all things"
}
"""
assert loads(json_string) == {"sig\u03A3ma": "\u03A3 is the sum of all things"}
assert loads(json_string) == {"sig\u03a3ma": "\u03a3 is the sum of all things"}


def test_load_identifier_with_connector_punctuation():
Expand Down
Loading