Skip to content
Merged
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
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ ignore-variadic-names = true
"S101", # assert statements in tests
"PLR2004", # magic values in assertions in tests
]
"src/jsonlt/_exceptions.py" = [
"TC001", # direct imports from _types.py to break circular import cycle
]

[tool.uv.build-backend]
module-name = "jsonlt"
7 changes: 1 addition & 6 deletions src/jsonlt/_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,9 @@
following the specification's error categories.
"""

# pyright: reportImportCycles=false

from typing import TYPE_CHECKING
from typing_extensions import override

if TYPE_CHECKING:
from ._json import JSONObject
from ._keys import Key
from ._types import JSONObject, Key


class JSONLTError(Exception):
Expand Down
11 changes: 4 additions & 7 deletions src/jsonlt/_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,17 @@

import json
from json import JSONDecodeError
from typing import TYPE_CHECKING, TypeAlias, cast
from typing import TYPE_CHECKING, cast

from ._constants import MIN_NESTING_DEPTH
from ._exceptions import LimitError, ParseError
from ._types import JSONArray, JSONObject, JSONPrimitive, JSONValue

if TYPE_CHECKING:
from collections.abc import Mapping, Sequence

# JSON type definitions per RFC 8259
# Using string annotations for forward references to avoid runtime | issues
JSONPrimitive: TypeAlias = "str | int | float | bool | None"
JSONArray: TypeAlias = "list[JSONValue]"
JSONObject: TypeAlias = "dict[str, JSONValue]"
JSONValue: TypeAlias = "JSONPrimitive | JSONArray | JSONObject"
# Re-export type aliases for backwards compatibility
__all__ = ["JSONArray", "JSONObject", "JSONPrimitive", "JSONValue"]


def json_nesting_depth(value: object) -> int:
Expand Down
24 changes: 4 additions & 20 deletions src/jsonlt/_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import json
from collections.abc import Sequence
from typing import TYPE_CHECKING, TypeAlias
from typing import TYPE_CHECKING

from ._constants import (
MAX_INTEGER_KEY,
Expand All @@ -16,30 +16,14 @@
)
from ._exceptions import InvalidKeyError, LimitError
from ._json import utf8_byte_length
from ._types import Key, KeyElement, KeySpecifier

if TYPE_CHECKING:
from typing import TypeGuard
from typing_extensions import TypeIs

KeyElement: TypeAlias = "str | int"
"""A key element is a string or integer that may appear in a tuple key."""

Key: TypeAlias = "str | int | tuple[str | int, ...]"
"""A key identifies a record within a table.

A key is one of:
- A string
- An integer in the range [-(2^53)+1, (2^53)-1]
- A tuple of key elements (non-empty, max 16 elements)
"""

KeySpecifier: TypeAlias = "str | tuple[str, ...]"
"""A key specifier defines how to extract a key from a record.

A key specifier is one of:
- A string naming a single field
- A tuple of strings naming multiple fields (for compound keys)
"""
# Re-export type aliases for backwards compatibility
__all__ = ["Key", "KeyElement", "KeySpecifier"]


def is_valid_key_element(value: object) -> "TypeIs[str | int]":
Expand Down
48 changes: 48 additions & 0 deletions src/jsonlt/_types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"""Type aliases for JSONLT.

This module contains ONLY TypeAlias definitions for JSON and key types.
It exists to break circular imports between _exceptions.py, _json.py, and _keys.py:
- _exceptions.py needs JSONObject and Key for ConflictError
- _json.py needs ParseError, LimitError from _exceptions.py
- _keys.py needs InvalidKeyError, LimitError from _exceptions.py

By placing the type aliases here with no dependencies on other JSONLT modules,
all modules can safely import from _types.py.
"""

from typing import TypeAlias

# JSON type definitions per RFC 8259
# Using string annotations for forward references to avoid runtime | issues
JSONPrimitive: TypeAlias = "str | int | float | bool | None"
"""A JSON primitive value: string, number, boolean, or null."""

JSONArray: TypeAlias = "list[JSONValue]"
"""A JSON array containing any JSON values."""

JSONObject: TypeAlias = "dict[str, JSONValue]"
"""A JSON object mapping string keys to JSON values."""

JSONValue: TypeAlias = "JSONPrimitive | JSONArray | JSONObject"
"""Any JSON value: primitive, array, or object."""

# Key type definitions per JSONLT specification
KeyElement: TypeAlias = "str | int"
"""A key element is a string or integer that may appear in a tuple key."""

Key: TypeAlias = "str | int | tuple[str | int, ...]"
"""A key identifies a record within a table.

A key is one of:
- A string
- An integer in the range [-(2^53)+1, (2^53)-1]
- A tuple of key elements (non-empty, max 16 elements)
"""

KeySpecifier: TypeAlias = "str | tuple[str, ...]"
"""A key specifier defines how to extract a key from a record.

A key specifier is one of:
- A string naming a single field
- A tuple of strings naming multiple fields (for compound keys)
"""