• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SlowAPI / fast-json-pointer / 3798344209

pending completion
3798344209

push

github

Tristan Sweeney
Clean up a bit

6 of 6 new or added lines in 2 files covered. (100.0%)

285 of 294 relevant lines covered (96.94%)

0.97 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

100.0
/src/fast_json_pointer/rel_parser.py
1
"""Implements releative json pointer parsing. See `2020-12 relative json
1✔
2
pointer draft <https://json-schema.org/draft/2020-12/relative-json-pointer.html>`_ for
3
the (draft) specification.
4
"""
5

6
import re
1✔
7
from typing import Iterable
1✔
8

9
from . import rfc6901_parser
1✔
10
from .exceptions import ParseException
1✔
11

12
RE_NONNEG_INT = re.compile("0|[1-9][0-9]*")
1✔
13

14

15
def parse(s: str) -> tuple[int, list[str] | None]:
1✔
16
    """Parse a relative json pointer into :code:`tuple[offset, parts | None]`.
17

18
    If parts aren't returned it's due to the pointer containing a ``#`` operator at
19
    it's tail, and thus being an "index / name of" reference.
20

21
    :raises: :exc:`.ParseException`: If relative json pointer is invalid.
22

23
    An offset by itself is valid.
24

25
    >>> parse("0") # Points at self
26
    (0, [])
27
    >>> parse("1") # Points at parent
28
    (1, [])
29
    >>> parse("2") # Points at grandparent
30
    (2, [])
31

32

33
    Only non-negative integers are valid offsets.
34

35
    >>> parse("-1")
36
    Traceback (most recent call last):
37
    fast_json_pointer.exceptions.ParseException: ...
38
    >>> parse("-0") # Even negative zero
39
    Traceback (most recent call last):
40
    fast_json_pointer.exceptions.ParseException: ...
41

42

43
    An offset must always be provided, an empty string **isn't** valid.
44

45
    >>> parse("")
46
    Traceback (most recent call last):
47
    fast_json_pointer.exceptions.ParseException: ...
48

49

50
    An offset can be followed by ``#`` to imply the index or name of the referenced
51
    object should be returned, rather than it's value.
52

53
    >>> parse("0#")
54
    (0, None)
55
    >>> parse("2#")
56
    (2, None)
57

58

59
    ``#`` is *also* a valid character in a json pointer, there are a few ways to
60
    write relative pointers that break first-glance intuition.
61

62
    >>> parse("0/#")
63
    (0, ['#'])
64
    >>> parse("0/#/foo")
65
    (0, ['#', 'foo'])
66
    >>> parse("0/foo#")
67
    (0, ['foo#'])
68
    >>> parse("0/foo/#")
69
    (0, ['foo', '#'])
70

71

72
    ``#`` without an offset is invalid.
73

74
    >>> parse('#')
75
    Traceback (most recent call last):
76
    fast_json_pointer.exceptions.ParseException: ...
77

78

79
    ``#`` **must not** be followed with a json pointer, or any other text.
80

81
    >>> parse("0#/foo")
82
    Traceback (most recent call last):
83
    fast_json_pointer.exceptions.ParseException: ...
84
    >>> parse("#im_not_a_pointer")
85
    Traceback (most recent call last):
86
    fast_json_pointer.exceptions.ParseException: ...
87
    """
88
    match = RE_NONNEG_INT.match(s)
1✔
89

90
    if not match:
1✔
91
        raise ParseException("Relative json-pointer must begin with non-neg int")
1✔
92

93
    offset = int(match.group())
1✔
94
    rest = s[match.end() :]
1✔
95

96
    if rest.startswith("#"):
1✔
97
        if len(rest) > 1:
1✔
98
            raise ParseException("Relative json-pointer has symbols after #")
1✔
99
        return offset, None
1✔
100
    else:
101
        return offset, rfc6901_parser.parse(rest)
1✔
102

103

104
def unparse(offset: int, parts: Iterable[str] | None) -> str:
1✔
105
    """Serialize a relative json pointer.
106

107
    >>> unparse(0, ["foo"])
108
    '0/foo'
109
    >>> unparse(0, None)
110
    '0#'
111
    >>> unparse(0, [])
112
    '0'
113
    >>> unparse(0, ['#'])
114
    '0/#'
115
    >>> unparse(0, ["foo#"])
116
    '0/foo#'
117
    """
118
    return f"{offset}{'#' if parts is None else rfc6901_parser.unparse(parts)}"
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc